@supabase/pg-delta 1.0.0-alpha.23 → 1.0.0-alpha.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/catalog.model.d.ts +2 -2
- package/dist/core/catalog.model.js +26 -21
- package/dist/core/integrations/supabase.js +84 -0
- package/dist/core/objects/aggregate/changes/aggregate.privilege.js +21 -9
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.js +4 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.js +6 -3
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.d.ts +11 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.js +11 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.js +4 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.js +6 -3
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +11 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +11 -0
- package/dist/core/objects/foreign-data-wrapper/sensitive-options.d.ts +32 -0
- package/dist/core/objects/foreign-data-wrapper/sensitive-options.js +129 -0
- package/dist/core/objects/foreign-data-wrapper/server/changes/server.alter.js +4 -1
- package/dist/core/objects/foreign-data-wrapper/server/changes/server.create.js +6 -3
- package/dist/core/objects/foreign-data-wrapper/server/server.model.d.ts +10 -0
- package/dist/core/objects/foreign-data-wrapper/server/server.model.js +10 -0
- package/dist/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.js +4 -1
- package/dist/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.js +6 -3
- package/dist/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.d.ts +10 -0
- package/dist/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.js +10 -0
- package/dist/core/objects/rls-policy/rls-policy.model.d.ts +2 -2
- package/dist/core/objects/table/table.model.js +7 -2
- package/dist/core/post-diff-normalization.d.ts +7 -0
- package/dist/core/post-diff-normalization.js +33 -4
- package/dist/core/sort/cycle-breakers.js +139 -17
- package/package.json +1 -1
- package/src/core/catalog.model.ts +36 -20
- package/src/core/integrations/supabase.test.ts +198 -0
- package/src/core/integrations/supabase.ts +84 -0
- package/src/core/objects/aggregate/changes/aggregate.privilege.test.ts +79 -0
- package/src/core/objects/aggregate/changes/aggregate.privilege.ts +22 -9
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.test.ts +34 -4
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.alter.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.test.ts +34 -0
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/changes/foreign-data-wrapper.create.ts +7 -5
- package/src/core/objects/foreign-data-wrapper/foreign-data-wrapper/foreign-data-wrapper.model.ts +11 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.test.ts +25 -4
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.alter.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.test.ts +54 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.create.ts +7 -5
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +11 -0
- package/src/core/objects/foreign-data-wrapper/sensitive-options.test.ts +98 -0
- package/src/core/objects/foreign-data-wrapper/sensitive-options.ts +133 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.test.ts +39 -4
- package/src/core/objects/foreign-data-wrapper/server/changes/server.alter.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/server/changes/server.create.test.ts +36 -0
- package/src/core/objects/foreign-data-wrapper/server/changes/server.create.ts +7 -5
- package/src/core/objects/foreign-data-wrapper/server/server.model.ts +10 -0
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.test.ts +39 -6
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.alter.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.test.ts +38 -2
- package/src/core/objects/foreign-data-wrapper/user-mapping/changes/user-mapping.create.ts +7 -5
- package/src/core/objects/foreign-data-wrapper/user-mapping/user-mapping.model.ts +10 -0
- package/src/core/objects/table/table.model.ts +7 -2
- package/src/core/plan/sql-format/format-off.test.ts +4 -4
- package/src/core/plan/sql-format/format-pretty-lower-leading.test.ts +4 -4
- package/src/core/plan/sql-format/format-pretty-narrow.test.ts +5 -4
- package/src/core/plan/sql-format/format-pretty-preserve.test.ts +4 -4
- package/src/core/plan/sql-format/format-pretty-upper.test.ts +4 -4
- package/src/core/post-diff-normalization.test.ts +123 -0
- package/src/core/post-diff-normalization.ts +40 -4
- package/src/core/sort/cycle-breakers.test.ts +236 -2
- package/src/core/sort/cycle-breakers.ts +184 -24
- package/src/core/sort/sort-changes.test.ts +317 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SerializeOptions } from "../../../../integrations/serialize/serialize.types.ts";
|
|
2
2
|
import { quoteLiteral } from "../../../base.change.ts";
|
|
3
3
|
import { stableId } from "../../../utils.ts";
|
|
4
|
+
import { redactOptionValue } from "../../sensitive-options.ts";
|
|
4
5
|
import type { UserMapping } from "../user-mapping.model.ts";
|
|
5
6
|
import { CreateUserMappingChange } from "./user-mapping.base.ts";
|
|
6
7
|
|
|
@@ -51,11 +52,12 @@ export class CreateUserMapping extends CreateUserMappingChange {
|
|
|
51
52
|
if (this.userMapping.options && this.userMapping.options.length > 0) {
|
|
52
53
|
const optionPairs: string[] = [];
|
|
53
54
|
for (let i = 0; i < this.userMapping.options.length; i += 2) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
const key = this.userMapping.options[i];
|
|
56
|
+
const value = this.userMapping.options[i + 1];
|
|
57
|
+
if (key === undefined || value === undefined) continue;
|
|
58
|
+
optionPairs.push(
|
|
59
|
+
`${key} ${quoteLiteral(redactOptionValue(key, value))}`,
|
|
60
|
+
);
|
|
59
61
|
}
|
|
60
62
|
if (optionPairs.length > 0) {
|
|
61
63
|
parts.push(`OPTIONS (${optionPairs.join(", ")})`);
|
|
@@ -56,6 +56,16 @@ export class UserMapping extends BasePgModel {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Extract `pg_user_mapping` rows into `UserMapping` models.
|
|
61
|
+
*
|
|
62
|
+
* The returned models carry option values **verbatim** from
|
|
63
|
+
* `pg_user_mapping.umoptions`, which means cleartext secrets like
|
|
64
|
+
* `password` are present in memory. Always route through
|
|
65
|
+
* `extractCatalog` (which calls `normalizeCatalog`) before emitting
|
|
66
|
+
* options to any output channel — see CLI-1467 and
|
|
67
|
+
* `packages/pg-delta/src/core/objects/foreign-data-wrapper/sensitive-options.ts`.
|
|
68
|
+
*/
|
|
59
69
|
export async function extractUserMappings(pool: Pool): Promise<UserMapping[]> {
|
|
60
70
|
const { rows: mappingRows } = await pool.query<UserMappingProps>(sql`
|
|
61
71
|
select
|
|
@@ -341,8 +341,13 @@ select
|
|
|
341
341
|
'no_inherit', c.connoinherit,
|
|
342
342
|
'is_temporal', coalesce((to_jsonb(c)->>'conperiod')::boolean, false),
|
|
343
343
|
|
|
344
|
-
--
|
|
345
|
-
|
|
344
|
+
-- Inherited from a parent (partition or classical inheritance).
|
|
345
|
+
-- coninhcount > 0 is the canonical signal across every constraint
|
|
346
|
+
-- kind. We previously used conparentid <> 0, but PostgreSQL only
|
|
347
|
+
-- populates conparentid for PK / UNIQUE / FK on partitions; CHECK
|
|
348
|
+
-- constraints on partitions always have conparentid = 0 and were
|
|
349
|
+
-- being re-emitted on every child, failing apply with 42710.
|
|
350
|
+
'is_partition_clone', (c.coninhcount > 0),
|
|
346
351
|
'parent_constraint_schema', case when c.conparentid <> 0::oid then pc.connamespace::regnamespace::text end,
|
|
347
352
|
'parent_constraint_name', case when c.conparentid <> 0::oid then quote_ident(pc.conname) end,
|
|
348
353
|
'parent_table_schema', case when c.conparentid <> 0::oid then pc_rel.relnamespace::regnamespace::text end,
|
|
@@ -689,7 +689,7 @@ describe("sql formatting snapshots", () => {
|
|
|
689
689
|
COMMENT ON SUBSCRIPTION sub_replica IS NULL;
|
|
690
690
|
|
|
691
691
|
-- fdw.create
|
|
692
|
-
CREATE FOREIGN DATA WRAPPER postgres_fdw HANDLER postgres_fdw_handler VALIDATOR postgres_fdw_validator OPTIONS (debug '
|
|
692
|
+
CREATE FOREIGN DATA WRAPPER postgres_fdw HANDLER postgres_fdw_handler VALIDATOR postgres_fdw_validator OPTIONS (debug '__OPTION_DEBUG__');
|
|
693
693
|
|
|
694
694
|
-- fdw.drop
|
|
695
695
|
DROP FOREIGN DATA WRAPPER postgres_fdw;
|
|
@@ -698,7 +698,7 @@ describe("sql formatting snapshots", () => {
|
|
|
698
698
|
ALTER FOREIGN DATA WRAPPER postgres_fdw OWNER TO new_owner;
|
|
699
699
|
|
|
700
700
|
-- fdw.alter.set_options
|
|
701
|
-
ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (SET debug '
|
|
701
|
+
ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (SET debug '__OPTION_DEBUG__', ADD use_remote_estimate '');
|
|
702
702
|
|
|
703
703
|
-- fdw.comment
|
|
704
704
|
COMMENT ON FOREIGN DATA WRAPPER postgres_fdw IS 'PostgreSQL foreign data wrapper';
|
|
@@ -794,13 +794,13 @@ describe("sql formatting snapshots", () => {
|
|
|
794
794
|
REVOKE GRANT OPTION FOR ALL ON SERVER remote_server FROM app_user;
|
|
795
795
|
|
|
796
796
|
-- user_mapping.create
|
|
797
|
-
CREATE USER MAPPING FOR app_user SERVER remote_server OPTIONS (user 'remote_app', password '
|
|
797
|
+
CREATE USER MAPPING FOR app_user SERVER remote_server OPTIONS (user 'remote_app', password '__OPTION_PASSWORD__');
|
|
798
798
|
|
|
799
799
|
-- user_mapping.drop
|
|
800
800
|
DROP USER MAPPING FOR app_user SERVER remote_server;
|
|
801
801
|
|
|
802
802
|
-- user_mapping.alter.set_options
|
|
803
|
-
ALTER USER MAPPING FOR app_user SERVER remote_server OPTIONS (SET password '
|
|
803
|
+
ALTER USER MAPPING FOR app_user SERVER remote_server OPTIONS (SET password '__OPTION_PASSWORD__');"
|
|
804
804
|
`);
|
|
805
805
|
});
|
|
806
806
|
});
|
|
@@ -912,7 +912,7 @@ describe("sql formatting snapshots", () => {
|
|
|
912
912
|
create foreign data wrapper postgres_fdw
|
|
913
913
|
handler postgres_fdw_handler
|
|
914
914
|
validator postgres_fdw_validator
|
|
915
|
-
options (debug '
|
|
915
|
+
options (debug '__OPTION_DEBUG__');
|
|
916
916
|
|
|
917
917
|
-- fdw.drop
|
|
918
918
|
drop foreign data wrapper postgres_fdw;
|
|
@@ -924,7 +924,7 @@ describe("sql formatting snapshots", () => {
|
|
|
924
924
|
-- fdw.alter.set_options
|
|
925
925
|
alter foreign data wrapper postgres_fdw
|
|
926
926
|
options (
|
|
927
|
-
SET debug '
|
|
927
|
+
SET debug '__OPTION_DEBUG__'
|
|
928
928
|
, ADD use_remote_estimate ''
|
|
929
929
|
);
|
|
930
930
|
|
|
@@ -1049,13 +1049,13 @@ describe("sql formatting snapshots", () => {
|
|
|
1049
1049
|
|
|
1050
1050
|
-- user_mapping.create
|
|
1051
1051
|
create user mapping for app_user server remote_server
|
|
1052
|
-
options (user 'remote_app', password '
|
|
1052
|
+
options (user 'remote_app', password '__OPTION_PASSWORD__');
|
|
1053
1053
|
|
|
1054
1054
|
-- user_mapping.drop
|
|
1055
1055
|
drop user mapping for app_user server remote_server;
|
|
1056
1056
|
|
|
1057
1057
|
-- user_mapping.alter.set_options
|
|
1058
|
-
alter user mapping for app_user server remote_server options (SET password '
|
|
1058
|
+
alter user mapping for app_user server remote_server options (SET password '__OPTION_PASSWORD__');"
|
|
1059
1059
|
`);
|
|
1060
1060
|
});
|
|
1061
1061
|
});
|
|
@@ -1094,7 +1094,7 @@ describe("sql formatting snapshots", () => {
|
|
|
1094
1094
|
CREATE FOREIGN DATA WRAPPER postgres_fdw
|
|
1095
1095
|
HANDLER postgres_fdw_handler
|
|
1096
1096
|
VALIDATOR postgres_fdw_validator
|
|
1097
|
-
OPTIONS (debug '
|
|
1097
|
+
OPTIONS (debug '__OPTION_DEBUG__');
|
|
1098
1098
|
|
|
1099
1099
|
-- fdw.drop
|
|
1100
1100
|
DROP FOREIGN DATA WRAPPER postgres_fdw;
|
|
@@ -1106,7 +1106,7 @@ describe("sql formatting snapshots", () => {
|
|
|
1106
1106
|
-- fdw.alter.set_options
|
|
1107
1107
|
ALTER FOREIGN DATA WRAPPER postgres_fdw
|
|
1108
1108
|
OPTIONS (
|
|
1109
|
-
SET debug '
|
|
1109
|
+
SET debug '__OPTION_DEBUG__',
|
|
1110
1110
|
ADD use_remote_estimate ''
|
|
1111
1111
|
);
|
|
1112
1112
|
|
|
@@ -1264,7 +1264,7 @@ describe("sql formatting snapshots", () => {
|
|
|
1264
1264
|
remote_server
|
|
1265
1265
|
OPTIONS
|
|
1266
1266
|
(user 'remote_app', password
|
|
1267
|
-
'
|
|
1267
|
+
'__OPTION_PASSWORD__');
|
|
1268
1268
|
|
|
1269
1269
|
-- user_mapping.drop
|
|
1270
1270
|
DROP USER MAPPING FOR app_user SERVER
|
|
@@ -1273,7 +1273,8 @@ describe("sql formatting snapshots", () => {
|
|
|
1273
1273
|
-- user_mapping.alter.set_options
|
|
1274
1274
|
ALTER USER MAPPING FOR app_user SERVER
|
|
1275
1275
|
remote_server
|
|
1276
|
-
OPTIONS
|
|
1276
|
+
OPTIONS
|
|
1277
|
+
(SET password '__OPTION_PASSWORD__');"
|
|
1277
1278
|
`);
|
|
1278
1279
|
});
|
|
1279
1280
|
});
|
|
@@ -908,7 +908,7 @@ describe("sql formatting snapshots", () => {
|
|
|
908
908
|
CREATE FOREIGN DATA WRAPPER postgres_fdw
|
|
909
909
|
HANDLER postgres_fdw_handler
|
|
910
910
|
VALIDATOR postgres_fdw_validator
|
|
911
|
-
OPTIONS (debug '
|
|
911
|
+
OPTIONS (debug '__OPTION_DEBUG__');
|
|
912
912
|
|
|
913
913
|
-- fdw.drop
|
|
914
914
|
DROP FOREIGN DATA WRAPPER postgres_fdw;
|
|
@@ -920,7 +920,7 @@ describe("sql formatting snapshots", () => {
|
|
|
920
920
|
-- fdw.alter.set_options
|
|
921
921
|
ALTER FOREIGN DATA WRAPPER postgres_fdw
|
|
922
922
|
OPTIONS (
|
|
923
|
-
SET debug '
|
|
923
|
+
SET debug '__OPTION_DEBUG__',
|
|
924
924
|
ADD use_remote_estimate ''
|
|
925
925
|
);
|
|
926
926
|
|
|
@@ -1045,13 +1045,13 @@ describe("sql formatting snapshots", () => {
|
|
|
1045
1045
|
|
|
1046
1046
|
-- user_mapping.create
|
|
1047
1047
|
CREATE USER MAPPING FOR app_user SERVER remote_server
|
|
1048
|
-
OPTIONS (user 'remote_app', password '
|
|
1048
|
+
OPTIONS (user 'remote_app', password '__OPTION_PASSWORD__');
|
|
1049
1049
|
|
|
1050
1050
|
-- user_mapping.drop
|
|
1051
1051
|
DROP USER MAPPING FOR app_user SERVER remote_server;
|
|
1052
1052
|
|
|
1053
1053
|
-- user_mapping.alter.set_options
|
|
1054
|
-
ALTER USER MAPPING FOR app_user SERVER remote_server OPTIONS (SET password '
|
|
1054
|
+
ALTER USER MAPPING FOR app_user SERVER remote_server OPTIONS (SET password '__OPTION_PASSWORD__');"
|
|
1055
1055
|
`);
|
|
1056
1056
|
});
|
|
1057
1057
|
});
|
|
@@ -899,7 +899,7 @@ describe("sql formatting snapshots", () => {
|
|
|
899
899
|
CREATE FOREIGN DATA WRAPPER postgres_fdw
|
|
900
900
|
HANDLER postgres_fdw_handler
|
|
901
901
|
VALIDATOR postgres_fdw_validator
|
|
902
|
-
OPTIONS (debug '
|
|
902
|
+
OPTIONS (debug '__OPTION_DEBUG__');
|
|
903
903
|
|
|
904
904
|
-- fdw.drop
|
|
905
905
|
DROP FOREIGN DATA WRAPPER postgres_fdw;
|
|
@@ -911,7 +911,7 @@ describe("sql formatting snapshots", () => {
|
|
|
911
911
|
-- fdw.alter.set_options
|
|
912
912
|
ALTER FOREIGN DATA WRAPPER postgres_fdw
|
|
913
913
|
OPTIONS (
|
|
914
|
-
SET debug '
|
|
914
|
+
SET debug '__OPTION_DEBUG__',
|
|
915
915
|
ADD use_remote_estimate ''
|
|
916
916
|
);
|
|
917
917
|
|
|
@@ -1036,13 +1036,13 @@ describe("sql formatting snapshots", () => {
|
|
|
1036
1036
|
|
|
1037
1037
|
-- user_mapping.create
|
|
1038
1038
|
CREATE USER MAPPING FOR app_user SERVER remote_server
|
|
1039
|
-
OPTIONS (user 'remote_app', password '
|
|
1039
|
+
OPTIONS (user 'remote_app', password '__OPTION_PASSWORD__');
|
|
1040
1040
|
|
|
1041
1041
|
-- user_mapping.drop
|
|
1042
1042
|
DROP USER MAPPING FOR app_user SERVER remote_server;
|
|
1043
1043
|
|
|
1044
1044
|
-- user_mapping.alter.set_options
|
|
1045
|
-
ALTER USER MAPPING FOR app_user SERVER remote_server OPTIONS (SET password '
|
|
1045
|
+
ALTER USER MAPPING FOR app_user SERVER remote_server OPTIONS (SET password '__OPTION_PASSWORD__');"
|
|
1046
1046
|
`);
|
|
1047
1047
|
});
|
|
1048
1048
|
});
|
|
@@ -3,6 +3,12 @@ import type { Change } from "./change.types.ts";
|
|
|
3
3
|
import { CreateIndex } from "./objects/index/changes/index.create.ts";
|
|
4
4
|
import { DropIndex } from "./objects/index/changes/index.drop.ts";
|
|
5
5
|
import { Index, type IndexProps } from "./objects/index/index.model.ts";
|
|
6
|
+
import { CreateSequence } from "./objects/sequence/changes/sequence.create.ts";
|
|
7
|
+
import { DropSequence } from "./objects/sequence/changes/sequence.drop.ts";
|
|
8
|
+
import {
|
|
9
|
+
Sequence,
|
|
10
|
+
type SequenceProps,
|
|
11
|
+
} from "./objects/sequence/sequence.model.ts";
|
|
6
12
|
import {
|
|
7
13
|
AlterTableAddConstraint,
|
|
8
14
|
AlterTableChangeOwner,
|
|
@@ -304,6 +310,123 @@ describe("normalizePostDiffChanges", () => {
|
|
|
304
310
|
).toHaveLength(1);
|
|
305
311
|
});
|
|
306
312
|
|
|
313
|
+
describe("DropSequence pruning on replaced tables", () => {
|
|
314
|
+
const baseSequenceProps: SequenceProps = {
|
|
315
|
+
schema: "public",
|
|
316
|
+
name: "project_link_type_id_seq",
|
|
317
|
+
data_type: "integer",
|
|
318
|
+
start_value: 1,
|
|
319
|
+
minimum_value: 1n,
|
|
320
|
+
maximum_value: 2147483647n,
|
|
321
|
+
increment: 1,
|
|
322
|
+
cycle_option: false,
|
|
323
|
+
cache_size: 1,
|
|
324
|
+
persistence: "p",
|
|
325
|
+
owned_by_schema: "public",
|
|
326
|
+
owned_by_table: "project_link_type",
|
|
327
|
+
owned_by_column: "id",
|
|
328
|
+
comment: null,
|
|
329
|
+
privileges: [],
|
|
330
|
+
owner: "postgres",
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
test("prunes DropSequence when its OWNED BY table is in replacedTableIds", () => {
|
|
334
|
+
const replacedTable = new Table({
|
|
335
|
+
...baseTableProps,
|
|
336
|
+
name: "project_link_type",
|
|
337
|
+
columns: [{ ...integerColumn("id", 1), not_null: true }],
|
|
338
|
+
});
|
|
339
|
+
const ownedSequence = new Sequence(baseSequenceProps);
|
|
340
|
+
|
|
341
|
+
const dropSequence = new DropSequence({ sequence: ownedSequence });
|
|
342
|
+
const dropTable = new DropTable({ table: replacedTable });
|
|
343
|
+
const createTable = new CreateTable({ table: replacedTable });
|
|
344
|
+
|
|
345
|
+
const changes: Change[] = [dropSequence, dropTable, createTable];
|
|
346
|
+
|
|
347
|
+
const normalized = normalizePostDiffChanges({
|
|
348
|
+
changes,
|
|
349
|
+
replacedTableIds: new Set([replacedTable.stableId]),
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
expect(normalized.some((change) => change instanceof DropSequence)).toBe(
|
|
353
|
+
false,
|
|
354
|
+
);
|
|
355
|
+
expect(normalized).toContain(dropTable);
|
|
356
|
+
expect(normalized).toContain(createTable);
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
test("keeps DropSequence whose OWNED BY table is not in replacedTableIds", () => {
|
|
360
|
+
const survivingTable = new Table({
|
|
361
|
+
...baseTableProps,
|
|
362
|
+
name: "project_link_type",
|
|
363
|
+
columns: [{ ...integerColumn("id", 1), not_null: true }],
|
|
364
|
+
});
|
|
365
|
+
const ownedSequence = new Sequence(baseSequenceProps);
|
|
366
|
+
|
|
367
|
+
const dropSequence = new DropSequence({ sequence: ownedSequence });
|
|
368
|
+
|
|
369
|
+
const normalized = normalizePostDiffChanges({
|
|
370
|
+
changes: [dropSequence],
|
|
371
|
+
// Different table is being replaced; the sequence's OWNED BY does
|
|
372
|
+
// not match, so DropSequence must survive.
|
|
373
|
+
replacedTableIds: new Set([
|
|
374
|
+
`table:${survivingTable.schema}.unrelated_table` as const,
|
|
375
|
+
]),
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
expect(normalized).toContain(dropSequence);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
test("keeps DropSequence with no OWNED BY when replacedTableIds is non-empty", () => {
|
|
382
|
+
const orphanSequence = new Sequence({
|
|
383
|
+
...baseSequenceProps,
|
|
384
|
+
owned_by_schema: null,
|
|
385
|
+
owned_by_table: null,
|
|
386
|
+
owned_by_column: null,
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
const dropSequence = new DropSequence({ sequence: orphanSequence });
|
|
390
|
+
|
|
391
|
+
const normalized = normalizePostDiffChanges({
|
|
392
|
+
changes: [dropSequence],
|
|
393
|
+
replacedTableIds: new Set(["table:public.project_link_type" as const]),
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
expect(normalized).toContain(dropSequence);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
test("keeps unrelated CreateSequence and DropSequence even when its non-owning table is replaced", () => {
|
|
400
|
+
const sequenceA = new Sequence(baseSequenceProps);
|
|
401
|
+
const sequenceB = new Sequence({
|
|
402
|
+
...baseSequenceProps,
|
|
403
|
+
name: "unrelated_seq",
|
|
404
|
+
owned_by_schema: null,
|
|
405
|
+
owned_by_table: null,
|
|
406
|
+
owned_by_column: null,
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
const dropOwned = new DropSequence({ sequence: sequenceA });
|
|
410
|
+
const createUnrelated = new CreateSequence({ sequence: sequenceB });
|
|
411
|
+
|
|
412
|
+
const replacedTable = new Table({
|
|
413
|
+
...baseTableProps,
|
|
414
|
+
name: "project_link_type",
|
|
415
|
+
columns: [{ ...integerColumn("id", 1), not_null: true }],
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const normalized = normalizePostDiffChanges({
|
|
419
|
+
changes: [dropOwned, createUnrelated],
|
|
420
|
+
replacedTableIds: new Set([replacedTable.stableId]),
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
expect(normalized.some((change) => change instanceof DropSequence)).toBe(
|
|
424
|
+
false,
|
|
425
|
+
);
|
|
426
|
+
expect(normalized).toContain(createUnrelated);
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
307
430
|
describe("restoreReplicaIdentityAfterIndexReplace", () => {
|
|
308
431
|
const baseIndexProps: IndexProps = {
|
|
309
432
|
schema: "public",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Change } from "./change.types.ts";
|
|
2
2
|
import { CreateIndex } from "./objects/index/changes/index.create.ts";
|
|
3
3
|
import { DropIndex } from "./objects/index/changes/index.drop.ts";
|
|
4
|
+
import { DropSequence } from "./objects/sequence/changes/sequence.drop.ts";
|
|
4
5
|
import {
|
|
5
6
|
AlterTableAddConstraint,
|
|
6
7
|
AlterTableDropColumn,
|
|
@@ -24,12 +25,40 @@ function isSupersededByTableReplacement(
|
|
|
24
25
|
replacedTableIds: ReadonlySet<string>,
|
|
25
26
|
): boolean {
|
|
26
27
|
if (
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
change instanceof AlterTableDropColumn ||
|
|
29
|
+
change instanceof AlterTableDropConstraint
|
|
29
30
|
) {
|
|
30
|
-
return
|
|
31
|
+
return replacedTableIds.has(change.table.stableId);
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
|
|
34
|
+
// `DropSequence(S)` is superseded when S is OWNED BY a column on a table
|
|
35
|
+
// that `expandReplaceDependencies` has promoted to `DropTable + CreateTable`
|
|
36
|
+
// in the same plan. PostgreSQL cascade-drops the OWNED BY sequence as part
|
|
37
|
+
// of the DROP TABLE, so the explicit DROP SEQUENCE is redundant and — more
|
|
38
|
+
// importantly — closes an unbreakable `DropSequence ↔ DropTable` cycle in
|
|
39
|
+
// the drop phase via the bidirectional pg_depend edges between the
|
|
40
|
+
// sequence and its owning column (`column → sequence` for the DEFAULT
|
|
41
|
+
// nextval reference, `sequence → column` for the OWNED BY auto-dependency).
|
|
42
|
+
// The alpha.15 short-circuit in `diffSequences.dropped` only suppresses
|
|
43
|
+
// `DropSequence` when the owning table itself is gone from `branchTables`;
|
|
44
|
+
// here the table survives in branch and the replacement is added later by
|
|
45
|
+
// the expander, so this whole-plan rewrite has to happen post-diff.
|
|
46
|
+
if (change instanceof DropSequence) {
|
|
47
|
+
if (
|
|
48
|
+
!change.sequence.owned_by_schema ||
|
|
49
|
+
!change.sequence.owned_by_table ||
|
|
50
|
+
!change.sequence.owned_by_column
|
|
51
|
+
) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const ownedByTableId = stableId.table(
|
|
55
|
+
change.sequence.owned_by_schema,
|
|
56
|
+
change.sequence.owned_by_table,
|
|
57
|
+
);
|
|
58
|
+
return replacedTableIds.has(ownedByTableId);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return false;
|
|
33
62
|
}
|
|
34
63
|
|
|
35
64
|
/**
|
|
@@ -219,6 +248,13 @@ function restoreReplicaIdentityAfterIndexReplace(
|
|
|
219
248
|
* `DropTable(T) + CreateTable(T)` pair. Without this, the apply phase
|
|
220
249
|
* would try to drop a column that no longer exists in the freshly
|
|
221
250
|
* recreated table.
|
|
251
|
+
* - Prunes `DropSequence(S)` changes when `S` is `OWNED BY` a column on a
|
|
252
|
+
* table promoted to `DropTable + CreateTable` by the expander. The
|
|
253
|
+
* `DROP TABLE` cascade drops the sequence at apply time; emitting an
|
|
254
|
+
* explicit `DROP SEQUENCE` in the same drop phase both duplicates the
|
|
255
|
+
* cascade and forms an unbreakable `DropSequence ↔ DropTable` cycle on
|
|
256
|
+
* the bidirectional pg_depend edges between the sequence and the
|
|
257
|
+
* owning column.
|
|
222
258
|
* - Dedupes duplicate `AlterTableAddConstraint` /
|
|
223
259
|
* `AlterTableValidateConstraint` / `CreateCommentOnConstraint` changes
|
|
224
260
|
* produced when `diffTables()` and `expandReplaceDependencies()` both
|