diff --git a/drizzle/20261024013208_books/migration.sql b/drizzle/20261024013208_books/migration.sql index fdd4071..41ef432 100644 --- a/drizzle/20261024013208_books/migration.sql +++ b/drizzle/20261024013208_books/migration.sql @@ -170,7 +170,11 @@ BEGIN ('books','shelves','books-shelves','Book shelves','core',true,false,1000), ('books','files','books-files','Book files','core',false,false,1000) ON CONFLICT DO NOTHING; - PERFORM meta.sync(); + -- meta.sync() is executable by personal_app/personal_ddl, not by the migration role + -- (personal) in prod; deploy-remote.sh runs it as the app role after migrating. + IF has_function_privilege('meta.sync(integer)', 'EXECUTE') THEN + PERFORM meta.sync(); + END IF; END IF; END $$; diff --git a/scripts/db-meta-sync.ts b/scripts/db-meta-sync.ts new file mode 100644 index 0000000..e4ced6f --- /dev/null +++ b/scripts/db-meta-sync.ts @@ -0,0 +1,19 @@ +// Refreshes meta.columns from the live catalog for every table in meta.tables +// (meta.sync() is SECURITY DEFINER and granted to the app role). Idempotent. +// bun scripts/db-meta-sync.ts uses DB_URL (personal_app) +import postgres from 'postgres'; + +const url = process.env.DB_URL; +if (!url) throw new Error('Set DB_URL (app role)'); +const client = postgres(url, { max: 1, connect_timeout: 10, onnotice: () => {} }); +try { + const [registry] = await client`select to_regprocedure('meta.sync(integer)') is not null as ok`; + if (!registry.ok) { + console.log('meta.sync() not present; skipping'); + } else { + const [row] = await client`select meta.sync() as added`; + console.log(`meta.sync(): ${row.added} column(s) added`); + } +} finally { + await client.end(); +} diff --git a/scripts/deploy-remote.sh b/scripts/deploy-remote.sh index 7094878..ebd165b 100644 --- a/scripts/deploy-remote.sh +++ b/scripts/deploy-remote.sh @@ -103,6 +103,12 @@ run_database_script() { if [ "$mode" = deploy ]; then # Schema changes: Drizzle migrations from ./drizzle, as the schema owner. run_database_script scripts/db-migrate.ts + # Refresh the generic table GUI's column registry (meta.columns) for tables that migrations + # registered in meta.tables. meta.sync() is SECURITY DEFINER and granted to the app role, not + # to the schema owner, so run it as DB_URL (personal_app). + echo "Running meta.sync()" + sudo docker run --rm --network backend --env-file "$environment" "$image" \ + bun scripts/db-meta-sync.ts run_database_script scripts/seed-catalog.ts run_database_script scripts/seed-cod-catalog.ts run_database_script scripts/seed-pokemon-research.ts