Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/cli-go/pkg/migration/queries/drop.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ begin
-- schemas
for rec in
select pn.*
from pg_namespace pn
left join pg_depend pd on pd.objid = pn.oid
from pg_catalog.pg_namespace pn
left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass
where pd.deptype is null
and not pn.nspname like any(array['information\_schema', 'pg\_%', '\_analytics', '\_realtime', '\_supavisor', 'pgbouncer', 'pgmq', 'pgsodium', 'pgtle', 'supabase\_migrations', 'vault', 'extensions', 'public'])
and pn.nspowner::regrole::text != 'supabase_admin'
Expand Down
4 changes: 2 additions & 2 deletions apps/cli-go/pkg/migration/queries/list.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
-- Extension created schemas
-- Supabase managed schemas
select pn.nspname
from pg_namespace pn
left join pg_depend pd on pd.objid = pn.oid
from pg_catalog.pg_namespace pn
left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass
Comment thread
7ttp marked this conversation as resolved.
where pd.deptype is null
and not pn.nspname like any($1)
and pn.nspowner::regrole::text != 'supabase_admin'
Expand Down
4 changes: 2 additions & 2 deletions apps/cli/src/legacy/commands/db/lint/lint.lint-sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export const LEGACY_LIST_SCHEMAS_SQL = `-- List user defined schemas, excluding
-- Extension created schemas
-- Supabase managed schemas
select pn.nspname
from pg_namespace pn
left join pg_depend pd on pd.objid = pn.oid
from pg_catalog.pg_namespace pn
left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass
where pd.deptype is null
and not pn.nspname like any($1)
and pn.nspowner::regrole::text != 'supabase_admin'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ begin
-- schemas
for rec in
select pn.*
from pg_namespace pn
left join pg_depend pd on pd.objid = pn.oid
from pg_catalog.pg_namespace pn
left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass
where pd.deptype is null
and not pn.nspname like any(array['information\\_schema', 'pg\\_%', '\\_analytics', '\\_realtime', '\\_supavisor', 'pgbouncer', 'pgmq', 'pgsodium', 'pgtle', 'supabase\\_migrations', 'vault', 'extensions', 'public'])
and pn.nspowner::regrole::text != 'supabase_admin'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,70 @@ describe("embedded migra templates", () => {
expect(legacyMigraDiffScript).toContain(LEGACY_EDGE_RUNTIME_SCRIPT_ERROR_SENTINEL);
});
});

// The user-schema listing predicate is hand-copied across four modules —
// drift between the copies caused supabase/cli#6375.
const CLASSID_CONSTRAINT =
"left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass";

const SCHEMA_LISTING_SOURCES: ReadonlyArray<[label: string, relPath: string]> = [
["legacy-drop-schemas.ts", "./legacy-drop-schemas.ts"],
["legacy-drop-objects.ts", "../../../shared/legacy-drop-objects.ts"],
["lint.lint-sql.ts", "../lint/lint.lint-sql.ts"],
["legacy-migra.ts", "./legacy-migra.ts"],
];

const readSchemaListingSource = (relPath: string) =>
readFileSync(fileURLToPath(new URL(relPath, import.meta.url)), "utf8");

// Both copies in each compared pair use identical template-literal escaping,
// so the raw captured source is compared without decoding.
function extractSqlLiteral(source: string, name: string): string {
const match = new RegExp(`${name} = \`([\\s\\S]*?)\`;`).exec(source);
if (match?.[1] === undefined) {
throw new Error(`missing template literal '${name}'`);
}
return match[1].trimEnd();
}

describe("embedded user-schema listing queries", () => {
it.each(SCHEMA_LISTING_SOURCES)(
"%s constrains the pg_depend anti-join to pg_namespace rows (supabase/cli#6375)",
(_label, relPath) => {
const source = readSchemaListingSource(relPath);
expect(source).toContain(CLASSID_CONSTRAINT);
// every join occurrence must carry the classid constraint, regardless of
// line wrapping or trailing same-line text
const normalized = source.replaceAll(/\s+/gu, " ");
const joins = normalized.match(/pd\.objid = pn\.oid/gu) ?? [];
const constrained =
normalized.match(
/pd\.objid = pn\.oid and pd\.classid = 'pg_catalog\.pg_namespace'::regclass/gu,
) ?? [];
expect(joins.length).toBeGreaterThan(0);
expect(constrained.length).toBe(joins.length);
},
);

it("keeps the two drop DO blocks identical to each other", () => {
expect(
extractSqlLiteral(readSchemaListingSource("./legacy-drop-schemas.ts"), "DROP_OBJECTS"),
).toBe(
extractSqlLiteral(
readSchemaListingSource("../../../shared/legacy-drop-objects.ts"),
"LEGACY_DROP_OBJECTS_SQL",
),
);
});

it("keeps the two list queries identical to each other", () => {
expect(
extractSqlLiteral(
readSchemaListingSource("../lint/lint.lint-sql.ts"),
"LEGACY_LIST_SCHEMAS_SQL",
),
).toBe(
extractSqlLiteral(readSchemaListingSource("./legacy-migra.ts"), "LEGACY_LIST_SCHEMAS_SQL"),
);
});
Comment thread
7ttp marked this conversation as resolved.
});
4 changes: 2 additions & 2 deletions apps/cli/src/legacy/commands/db/shared/legacy-migra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ const LEGACY_LIST_SCHEMAS_SQL = `-- List user defined schemas, excluding
-- Extension created schemas
-- Supabase managed schemas
select pn.nspname
from pg_namespace pn
left join pg_depend pd on pd.objid = pn.oid
from pg_catalog.pg_namespace pn
left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass
where pd.deptype is null
and not pn.nspname like any($1)
and pn.nspowner::regrole::text != 'supabase_admin'
Expand Down
4 changes: 2 additions & 2 deletions apps/cli/src/legacy/shared/legacy-drop-objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ begin
-- schemas
for rec in
select pn.*
from pg_namespace pn
left join pg_depend pd on pd.objid = pn.oid
from pg_catalog.pg_namespace pn
left join pg_catalog.pg_depend pd on pd.objid = pn.oid and pd.classid = 'pg_catalog.pg_namespace'::regclass
where pd.deptype is null
and not pn.nspname like any(array['information\\_schema', 'pg\\_%', '\\_analytics', '\\_realtime', '\\_supavisor', 'pgbouncer', 'pgmq', 'pgsodium', 'pgtle', 'supabase\\_migrations', 'vault', 'extensions', 'public'])
and pn.nspowner::regrole::text != 'supabase_admin'
Expand Down
Loading