From 0c7abf41a3c047719c16dbd5e16f167a699e21be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20M=C3=BCllner?= Date: Fri, 6 Mar 2026 08:18:23 +0100 Subject: [PATCH] docs(db): add reproducible public schema export query pack --- DB_README.md | 11 +++++ db/export_schema.sql | 115 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 db/export_schema.sql diff --git a/DB_README.md b/DB_README.md index 4a97541..853a364 100644 --- a/DB_README.md +++ b/DB_README.md @@ -82,6 +82,17 @@ Status: TBD 5. Promote to production. 6. Record change summary in this document. +## Reproducible Schema Snapshot + +- Query pack: `db/export_schema.sql` +- Goal: produce repeatable app-focused schema snapshots without bloating docs + +Suggested usage: + +1. Run `db/export_schema.sql` in Supabase SQL Editor. +2. Export result sets (CSV/JSON) and store externally (for example `db_exports/` in local/private ops repo). +3. Summarize only key changes in this `DB_README.md`. + ## Operational Checklist Before deploy: diff --git a/db/export_schema.sql b/db/export_schema.sql new file mode 100644 index 0000000..0498a34 --- /dev/null +++ b/db/export_schema.sql @@ -0,0 +1,115 @@ +-- Reproducible schema export query pack (app-focused) +-- Run in Supabase SQL Editor or psql and export results as CSV/JSON. + +-- 1) App tables and columns (public only) +select + c.table_name, + c.ordinal_position, + c.column_name, + c.data_type, + c.udt_name, + c.is_nullable, + c.column_default +from information_schema.columns c +join information_schema.tables t + on t.table_schema = c.table_schema + and t.table_name = c.table_name +where c.table_schema = 'public' + and t.table_type = 'BASE TABLE' +order by c.table_name, c.ordinal_position; + +-- 2) Constraints +select + rel.relname as table_name, + con.conname as constraint_name, + case con.contype + when 'p' then 'PRIMARY KEY' + when 'u' then 'UNIQUE' + when 'f' then 'FOREIGN KEY' + when 'c' then 'CHECK' + else con.contype::text + end as constraint_type, + pg_get_constraintdef(con.oid, true) as definition +from pg_constraint con +join pg_class rel on rel.oid = con.conrelid +join pg_namespace n on n.oid = rel.relnamespace +where n.nspname = 'public' +order by rel.relname, con.conname; + +-- 3) Indexes +select + tablename, + indexname, + indexdef +from pg_indexes +where schemaname = 'public' +order by tablename, indexname; + +-- 4) Views +select + c.relname as view_name, + case c.relkind when 'v' then 'VIEW' when 'm' then 'MATERIALIZED VIEW' end as view_type, + pg_get_viewdef(c.oid, true) as definition +from pg_class c +join pg_namespace n on n.oid = c.relnamespace +where n.nspname = 'public' + and c.relkind in ('v', 'm') +order by c.relname; + +-- 5) Functions / Procedures +select + p.proname as routine_name, + case p.prokind when 'p' then 'PROCEDURE' else 'FUNCTION' end as routine_type, + l.lanname as language, + pg_get_function_identity_arguments(p.oid) as args, + pg_get_functiondef(p.oid) as definition +from pg_proc p +join pg_namespace n on n.oid = p.pronamespace +join pg_language l on l.oid = p.prolang +where n.nspname = 'public' +order by p.proname; + +-- 6) Triggers +select + c.relname as table_name, + t.tgname as trigger_name, + pg_get_triggerdef(t.oid, true) as definition +from pg_trigger t +join pg_class c on c.oid = t.tgrelid +join pg_namespace n on n.oid = c.relnamespace +where n.nspname = 'public' + and not t.tgisinternal +order by c.relname, t.tgname; + +-- 7) RLS status +select + c.relname as table_name, + c.relrowsecurity as rls_enabled, + c.relforcerowsecurity as rls_forced +from pg_class c +join pg_namespace n on n.oid = c.relnamespace +where n.nspname = 'public' + and c.relkind = 'r' +order by c.relname; + +-- 8) RLS policies +select + tablename, + policyname, + permissive, + roles, + cmd, + qual, + with_check +from pg_policies +where schemaname = 'public' +order by tablename, policyname; + +-- 9) Grants (tables) +select + table_name, + privilege_type, + grantee +from information_schema.role_table_grants +where table_schema = 'public' +order by table_name, grantee, privilege_type;