@supabase/pg-delta 1.0.0-alpha.22 → 1.0.0-alpha.24
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.js +1 -0
- package/dist/core/integrations/filter/flatten.js +13 -0
- package/dist/core/objects/aggregate/aggregate.diff.js +16 -0
- package/dist/core/objects/aggregate/aggregate.model.d.ts +10 -0
- package/dist/core/objects/aggregate/aggregate.model.js +19 -1
- package/dist/core/objects/aggregate/changes/aggregate.base.d.ts +1 -1
- package/dist/core/objects/aggregate/changes/aggregate.security-label.d.ts +28 -0
- package/dist/core/objects/aggregate/changes/aggregate.security-label.js +64 -0
- package/dist/core/objects/aggregate/changes/aggregate.types.d.ts +2 -1
- package/dist/core/objects/base.model.d.ts +8 -0
- package/dist/core/objects/base.model.js +2 -0
- package/dist/core/objects/domain/changes/domain.base.d.ts +1 -1
- package/dist/core/objects/domain/changes/domain.security-label.d.ts +28 -0
- package/dist/core/objects/domain/changes/domain.security-label.js +61 -0
- package/dist/core/objects/domain/changes/domain.types.d.ts +2 -1
- package/dist/core/objects/domain/domain.diff.js +16 -0
- package/dist/core/objects/domain/domain.model.d.ts +10 -0
- package/dist/core/objects/domain/domain.model.js +19 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.base.d.ts +1 -1
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.d.ts +28 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.security-label.js +61 -0
- package/dist/core/objects/event-trigger/changes/event-trigger.types.d.ts +2 -1
- package/dist/core/objects/event-trigger/event-trigger.diff.js +16 -0
- package/dist/core/objects/event-trigger/event-trigger.model.d.ts +10 -0
- package/dist/core/objects/event-trigger/event-trigger.model.js +19 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.d.ts +1 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.d.ts +28 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.js +61 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.d.ts +2 -1
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.js +16 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.d.ts +22 -0
- package/dist/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.js +20 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.base.d.ts +1 -1
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.d.ts +28 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.security-label.js +61 -0
- package/dist/core/objects/materialized-view/changes/materialized-view.types.d.ts +2 -1
- package/dist/core/objects/materialized-view/materialized-view.diff.js +18 -0
- package/dist/core/objects/materialized-view/materialized-view.model.d.ts +22 -0
- package/dist/core/objects/materialized-view/materialized-view.model.js +20 -1
- package/dist/core/objects/procedure/changes/procedure.base.d.ts +1 -1
- package/dist/core/objects/procedure/changes/procedure.security-label.d.ts +28 -0
- package/dist/core/objects/procedure/changes/procedure.security-label.js +69 -0
- package/dist/core/objects/procedure/changes/procedure.types.d.ts +2 -1
- package/dist/core/objects/procedure/procedure.diff.js +16 -0
- package/dist/core/objects/procedure/procedure.model.d.ts +10 -0
- package/dist/core/objects/procedure/procedure.model.js +19 -1
- package/dist/core/objects/publication/changes/publication.base.d.ts +1 -1
- package/dist/core/objects/publication/changes/publication.security-label.d.ts +28 -0
- package/dist/core/objects/publication/changes/publication.security-label.js +61 -0
- package/dist/core/objects/publication/changes/publication.types.d.ts +2 -1
- package/dist/core/objects/publication/publication.diff.js +16 -0
- package/dist/core/objects/publication/publication.model.d.ts +14 -0
- package/dist/core/objects/publication/publication.model.js +20 -1
- package/dist/core/objects/role/changes/role.base.d.ts +1 -1
- package/dist/core/objects/role/changes/role.security-label.d.ts +28 -0
- package/dist/core/objects/role/changes/role.security-label.js +61 -0
- package/dist/core/objects/role/changes/role.types.d.ts +2 -1
- package/dist/core/objects/role/role.diff.js +16 -0
- package/dist/core/objects/role/role.model.d.ts +10 -0
- package/dist/core/objects/role/role.model.js +29 -0
- package/dist/core/objects/schema/changes/schema.base.d.ts +1 -1
- package/dist/core/objects/schema/changes/schema.security-label.d.ts +28 -0
- package/dist/core/objects/schema/changes/schema.security-label.js +61 -0
- package/dist/core/objects/schema/changes/schema.types.d.ts +2 -1
- package/dist/core/objects/schema/schema.diff.js +24 -1
- package/dist/core/objects/schema/schema.model.d.ts +10 -0
- package/dist/core/objects/schema/schema.model.js +18 -1
- package/dist/core/objects/security-label.types.d.ts +20 -0
- package/dist/core/objects/security-label.types.js +46 -0
- package/dist/core/objects/sequence/changes/sequence.base.d.ts +1 -1
- package/dist/core/objects/sequence/changes/sequence.security-label.d.ts +28 -0
- package/dist/core/objects/sequence/changes/sequence.security-label.js +61 -0
- package/dist/core/objects/sequence/changes/sequence.types.d.ts +2 -1
- package/dist/core/objects/sequence/sequence.diff.js +16 -0
- package/dist/core/objects/sequence/sequence.model.d.ts +10 -0
- package/dist/core/objects/sequence/sequence.model.js +19 -1
- package/dist/core/objects/subscription/changes/subscription.base.d.ts +1 -1
- package/dist/core/objects/subscription/changes/subscription.security-label.d.ts +28 -0
- package/dist/core/objects/subscription/changes/subscription.security-label.js +61 -0
- package/dist/core/objects/subscription/changes/subscription.types.d.ts +2 -1
- package/dist/core/objects/subscription/subscription.diff.js +16 -0
- package/dist/core/objects/subscription/subscription.model.d.ts +10 -0
- package/dist/core/objects/subscription/subscription.model.js +19 -1
- package/dist/core/objects/table/changes/table.base.d.ts +1 -1
- package/dist/core/objects/table/changes/table.security-label.d.ts +63 -0
- package/dist/core/objects/table/changes/table.security-label.js +134 -0
- package/dist/core/objects/table/changes/table.types.d.ts +2 -1
- package/dist/core/objects/table/table.diff.js +49 -0
- package/dist/core/objects/table/table.model.d.ts +30 -0
- package/dist/core/objects/table/table.model.js +34 -2
- package/dist/core/objects/type/composite-type/changes/composite-type.base.d.ts +1 -1
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.d.ts +28 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.security-label.js +61 -0
- package/dist/core/objects/type/composite-type/changes/composite-type.types.d.ts +2 -1
- package/dist/core/objects/type/composite-type/composite-type.diff.js +16 -0
- package/dist/core/objects/type/composite-type/composite-type.model.d.ts +22 -0
- package/dist/core/objects/type/composite-type/composite-type.model.js +22 -2
- package/dist/core/objects/type/enum/changes/enum.base.d.ts +1 -1
- package/dist/core/objects/type/enum/changes/enum.security-label.d.ts +28 -0
- package/dist/core/objects/type/enum/changes/enum.security-label.js +61 -0
- package/dist/core/objects/type/enum/changes/enum.types.d.ts +2 -1
- package/dist/core/objects/type/enum/enum.diff.js +16 -0
- package/dist/core/objects/type/enum/enum.model.d.ts +10 -0
- package/dist/core/objects/type/enum/enum.model.js +20 -1
- package/dist/core/objects/type/range/changes/range.base.d.ts +1 -1
- package/dist/core/objects/type/range/changes/range.security-label.d.ts +28 -0
- package/dist/core/objects/type/range/changes/range.security-label.js +61 -0
- package/dist/core/objects/type/range/changes/range.types.d.ts +2 -1
- package/dist/core/objects/type/range/range.diff.js +16 -0
- package/dist/core/objects/type/range/range.model.d.ts +10 -0
- package/dist/core/objects/type/range/range.model.js +19 -1
- package/dist/core/objects/utils.d.ts +1 -0
- package/dist/core/objects/utils.js +3 -0
- package/dist/core/objects/view/changes/view.base.d.ts +1 -1
- package/dist/core/objects/view/changes/view.security-label.d.ts +28 -0
- package/dist/core/objects/view/changes/view.security-label.js +61 -0
- package/dist/core/objects/view/changes/view.types.d.ts +2 -1
- package/dist/core/objects/view/view.diff.js +13 -0
- package/dist/core/objects/view/view.model.d.ts +26 -0
- package/dist/core/objects/view/view.model.js +20 -1
- package/dist/core/plan/sql-format/fixtures.js +1 -0
- 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 +1 -0
- package/src/core/integrations/filter/dsl.test.ts +27 -0
- package/src/core/integrations/filter/flatten.ts +16 -0
- package/src/core/objects/aggregate/aggregate.diff.ts +33 -0
- package/src/core/objects/aggregate/aggregate.model.ts +22 -1
- package/src/core/objects/aggregate/changes/aggregate.base.ts +5 -1
- package/src/core/objects/aggregate/changes/aggregate.security-label.ts +99 -0
- package/src/core/objects/aggregate/changes/aggregate.types.ts +3 -1
- package/src/core/objects/base.model.ts +2 -0
- package/src/core/objects/domain/changes/domain.base.ts +5 -1
- package/src/core/objects/domain/changes/domain.security-label.test.ts +56 -0
- package/src/core/objects/domain/changes/domain.security-label.ts +77 -0
- package/src/core/objects/domain/changes/domain.types.ts +3 -1
- package/src/core/objects/domain/domain.diff.ts +33 -0
- package/src/core/objects/domain/domain.model.ts +22 -1
- package/src/core/objects/event-trigger/changes/event-trigger.base.ts +1 -1
- package/src/core/objects/event-trigger/changes/event-trigger.security-label.ts +95 -0
- package/src/core/objects/event-trigger/changes/event-trigger.types.ts +3 -1
- package/src/core/objects/event-trigger/event-trigger.diff.ts +33 -0
- package/src/core/objects/event-trigger/event-trigger.model.ts +22 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.base.ts +5 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.security-label.ts +95 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/changes/foreign-table.types.ts +3 -1
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.diff.ts +33 -0
- package/src/core/objects/foreign-data-wrapper/foreign-table/foreign-table.model.ts +24 -1
- package/src/core/objects/materialized-view/changes/materialized-view.base.ts +5 -1
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.test.ts +63 -0
- package/src/core/objects/materialized-view/changes/materialized-view.security-label.ts +95 -0
- package/src/core/objects/materialized-view/changes/materialized-view.types.ts +3 -1
- package/src/core/objects/materialized-view/materialized-view.diff.ts +37 -0
- package/src/core/objects/materialized-view/materialized-view.model.ts +25 -4
- package/src/core/objects/procedure/changes/procedure.base.ts +5 -1
- package/src/core/objects/procedure/changes/procedure.security-label.ts +105 -0
- package/src/core/objects/procedure/changes/procedure.types.ts +3 -1
- package/src/core/objects/procedure/procedure.diff.ts +33 -0
- package/src/core/objects/procedure/procedure.model.ts +23 -2
- package/src/core/objects/publication/changes/publication.base.ts +1 -1
- package/src/core/objects/publication/changes/publication.security-label.ts +95 -0
- package/src/core/objects/publication/changes/publication.types.ts +3 -1
- package/src/core/objects/publication/publication.diff.ts +33 -0
- package/src/core/objects/publication/publication.model.ts +24 -1
- package/src/core/objects/role/changes/role.base.ts +2 -1
- package/src/core/objects/role/changes/role.security-label.ts +77 -0
- package/src/core/objects/role/changes/role.types.ts +3 -1
- package/src/core/objects/role/role.diff.ts +33 -0
- package/src/core/objects/role/role.model.ts +32 -0
- package/src/core/objects/schema/changes/schema.alter.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.base.ts +5 -1
- package/src/core/objects/schema/changes/schema.create.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.drop.test.ts +1 -0
- package/src/core/objects/schema/changes/schema.security-label.test.ts +76 -0
- package/src/core/objects/schema/changes/schema.security-label.ts +77 -0
- package/src/core/objects/schema/changes/schema.types.ts +3 -1
- package/src/core/objects/schema/schema.diff.test.ts +1 -0
- package/src/core/objects/schema/schema.diff.ts +43 -1
- package/src/core/objects/schema/schema.model.ts +21 -1
- package/src/core/objects/security-label.types.test.ts +106 -0
- package/src/core/objects/security-label.types.ts +61 -0
- package/src/core/objects/sequence/changes/sequence.base.ts +5 -1
- package/src/core/objects/sequence/changes/sequence.security-label.test.ts +58 -0
- package/src/core/objects/sequence/changes/sequence.security-label.ts +92 -0
- package/src/core/objects/sequence/changes/sequence.types.ts +3 -1
- package/src/core/objects/sequence/sequence.diff.ts +33 -0
- package/src/core/objects/sequence/sequence.model.ts +22 -1
- package/src/core/objects/subscription/changes/subscription.base.ts +1 -1
- package/src/core/objects/subscription/changes/subscription.security-label.ts +95 -0
- package/src/core/objects/subscription/changes/subscription.types.ts +3 -1
- package/src/core/objects/subscription/subscription.diff.ts +33 -0
- package/src/core/objects/subscription/subscription.model.ts +22 -1
- package/src/core/objects/table/changes/table.base.ts +5 -1
- package/src/core/objects/table/changes/table.security-label.test.ts +140 -0
- package/src/core/objects/table/changes/table.security-label.ts +183 -0
- package/src/core/objects/table/changes/table.types.ts +3 -1
- package/src/core/objects/table/table.diff.ts +87 -0
- package/src/core/objects/table/table.model.ts +42 -2
- package/src/core/objects/type/composite-type/changes/composite-type.base.ts +5 -1
- package/src/core/objects/type/composite-type/changes/composite-type.security-label.ts +95 -0
- package/src/core/objects/type/composite-type/changes/composite-type.types.ts +3 -1
- package/src/core/objects/type/composite-type/composite-type.diff.ts +33 -0
- package/src/core/objects/type/composite-type/composite-type.model.ts +26 -2
- package/src/core/objects/type/enum/changes/enum.base.ts +5 -1
- package/src/core/objects/type/enum/changes/enum.security-label.ts +77 -0
- package/src/core/objects/type/enum/changes/enum.types.ts +3 -1
- package/src/core/objects/type/enum/enum.diff.ts +33 -0
- package/src/core/objects/type/enum/enum.model.ts +25 -1
- package/src/core/objects/type/range/changes/range.base.ts +5 -1
- package/src/core/objects/type/range/changes/range.security-label.ts +77 -0
- package/src/core/objects/type/range/changes/range.types.ts +3 -1
- package/src/core/objects/type/range/range.diff.ts +33 -0
- package/src/core/objects/type/range/range.model.ts +22 -1
- package/src/core/objects/utils.ts +3 -0
- package/src/core/objects/view/changes/view.base.ts +5 -1
- package/src/core/objects/view/changes/view.security-label.test.ts +64 -0
- package/src/core/objects/view/changes/view.security-label.ts +77 -0
- package/src/core/objects/view/changes/view.types.ts +3 -1
- package/src/core/objects/view/view.diff.ts +31 -0
- package/src/core/objects/view/view.model.ts +25 -2
- package/src/core/plan/sql-format/fixtures.ts +1 -0
- 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
|
@@ -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
|
|
@@ -62,7 +62,9 @@ function fkConstraint(props: {
|
|
|
62
62
|
fkColumn: string;
|
|
63
63
|
targetSchema: string;
|
|
64
64
|
targetTable: string;
|
|
65
|
+
targetColumn?: string;
|
|
65
66
|
}) {
|
|
67
|
+
const targetColumn = props.targetColumn ?? "id";
|
|
66
68
|
return {
|
|
67
69
|
name: props.name,
|
|
68
70
|
constraint_type: "f" as const,
|
|
@@ -78,7 +80,7 @@ function fkConstraint(props: {
|
|
|
78
80
|
parent_table_schema: null,
|
|
79
81
|
parent_table_name: null,
|
|
80
82
|
key_columns: [props.fkColumn],
|
|
81
|
-
foreign_key_columns: [
|
|
83
|
+
foreign_key_columns: [targetColumn],
|
|
82
84
|
foreign_key_table: props.targetTable,
|
|
83
85
|
foreign_key_schema: props.targetSchema,
|
|
84
86
|
foreign_key_table_is_partition: false,
|
|
@@ -91,7 +93,41 @@ function fkConstraint(props: {
|
|
|
91
93
|
match_type: "s" as const,
|
|
92
94
|
check_expression: null,
|
|
93
95
|
owner: "postgres",
|
|
94
|
-
definition: `FOREIGN KEY (${props.fkColumn}) REFERENCES ${props.targetSchema}.${props.targetTable}(
|
|
96
|
+
definition: `FOREIGN KEY (${props.fkColumn}) REFERENCES ${props.targetSchema}.${props.targetTable}(${targetColumn})`,
|
|
97
|
+
comment: null,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function uniqueConstraint(name: string, column: string) {
|
|
102
|
+
return {
|
|
103
|
+
name,
|
|
104
|
+
constraint_type: "u" as const,
|
|
105
|
+
deferrable: false,
|
|
106
|
+
initially_deferred: false,
|
|
107
|
+
validated: true,
|
|
108
|
+
is_local: true,
|
|
109
|
+
no_inherit: false,
|
|
110
|
+
is_temporal: false,
|
|
111
|
+
is_partition_clone: false,
|
|
112
|
+
parent_constraint_schema: null,
|
|
113
|
+
parent_constraint_name: null,
|
|
114
|
+
parent_table_schema: null,
|
|
115
|
+
parent_table_name: null,
|
|
116
|
+
key_columns: [column],
|
|
117
|
+
foreign_key_columns: null,
|
|
118
|
+
foreign_key_table: null,
|
|
119
|
+
foreign_key_schema: null,
|
|
120
|
+
foreign_key_table_is_partition: null,
|
|
121
|
+
foreign_key_parent_schema: null,
|
|
122
|
+
foreign_key_parent_table: null,
|
|
123
|
+
foreign_key_effective_schema: null,
|
|
124
|
+
foreign_key_effective_table: null,
|
|
125
|
+
on_update: null,
|
|
126
|
+
on_delete: null,
|
|
127
|
+
match_type: null,
|
|
128
|
+
check_expression: null,
|
|
129
|
+
owner: "postgres",
|
|
130
|
+
definition: `UNIQUE (${column})`,
|
|
95
131
|
comment: null,
|
|
96
132
|
};
|
|
97
133
|
}
|
|
@@ -448,6 +484,204 @@ describe("tryBreakCycleByChangeInjection", () => {
|
|
|
448
484
|
expect(broken).toBeNull();
|
|
449
485
|
});
|
|
450
486
|
|
|
487
|
+
test("publication FK-chain constraint-drop 3-cycle: injects terminal FK drop", () => {
|
|
488
|
+
// Schema:
|
|
489
|
+
// publication p includes labs and posts
|
|
490
|
+
// posts.lab_id REFERENCES labs(id)
|
|
491
|
+
// Diff drops posts and drops labs.unique_lab_id while also removing both
|
|
492
|
+
// tables from the publication. The FK edge from posts to the terminal
|
|
493
|
+
// constraint drop forms:
|
|
494
|
+
// AlterPublicationDropTables → DropTable(posts)
|
|
495
|
+
// DropTable(posts) → AlterTableDropConstraint(labs.unique_lab_id)
|
|
496
|
+
// AlterTableDropConstraint(labs.unique_lab_id) → AlterPublicationDropTables
|
|
497
|
+
const tableLabs = new Table({
|
|
498
|
+
...baseTableProps,
|
|
499
|
+
name: "labs",
|
|
500
|
+
columns: [{ ...integerColumn("id", 1), not_null: true }],
|
|
501
|
+
constraints: [uniqueConstraint("unique_lab_id", "id")],
|
|
502
|
+
});
|
|
503
|
+
const tablePosts = new Table({
|
|
504
|
+
...baseTableProps,
|
|
505
|
+
name: "posts",
|
|
506
|
+
columns: [
|
|
507
|
+
{ ...integerColumn("id", 1), not_null: true },
|
|
508
|
+
integerColumn("lab_id", 2),
|
|
509
|
+
],
|
|
510
|
+
constraints: [
|
|
511
|
+
fkConstraint({
|
|
512
|
+
name: "posts_lab_id_fkey",
|
|
513
|
+
fkColumn: "lab_id",
|
|
514
|
+
targetSchema: "public",
|
|
515
|
+
targetTable: "labs",
|
|
516
|
+
}),
|
|
517
|
+
],
|
|
518
|
+
});
|
|
519
|
+
const publication = new Publication({
|
|
520
|
+
name: "p",
|
|
521
|
+
owner: "postgres",
|
|
522
|
+
comment: null,
|
|
523
|
+
all_tables: false,
|
|
524
|
+
publish_insert: true,
|
|
525
|
+
publish_update: true,
|
|
526
|
+
publish_delete: true,
|
|
527
|
+
publish_truncate: true,
|
|
528
|
+
publish_via_partition_root: false,
|
|
529
|
+
tables: [
|
|
530
|
+
{ schema: "public", name: "labs", columns: null, row_filter: null },
|
|
531
|
+
{ schema: "public", name: "posts", columns: null, row_filter: null },
|
|
532
|
+
],
|
|
533
|
+
schemas: [],
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
const terminalDrop = new AlterTableDropConstraint({
|
|
537
|
+
table: tableLabs,
|
|
538
|
+
constraint: tableLabs.constraints[0],
|
|
539
|
+
});
|
|
540
|
+
const changes: Change[] = [
|
|
541
|
+
new AlterPublicationDropTables({
|
|
542
|
+
publication,
|
|
543
|
+
tables: publication.tables,
|
|
544
|
+
}),
|
|
545
|
+
new DropTable({ table: tablePosts }),
|
|
546
|
+
terminalDrop,
|
|
547
|
+
];
|
|
548
|
+
|
|
549
|
+
const broken = tryBreakCycleByChangeInjection([0, 1, 2], changes);
|
|
550
|
+
if (broken === null) throw new Error("expected breaker to fire");
|
|
551
|
+
|
|
552
|
+
const injectedDrops = broken.filter(
|
|
553
|
+
(change): change is AlterTableDropConstraint =>
|
|
554
|
+
change instanceof AlterTableDropConstraint &&
|
|
555
|
+
change.table.stableId === tablePosts.stableId,
|
|
556
|
+
);
|
|
557
|
+
expect(injectedDrops).toHaveLength(1);
|
|
558
|
+
expect(injectedDrops[0].constraint.name).toBe("posts_lab_id_fkey");
|
|
559
|
+
|
|
560
|
+
const rewrittenPostsDrop = broken.find(
|
|
561
|
+
(change): change is DropTable =>
|
|
562
|
+
change instanceof DropTable &&
|
|
563
|
+
change.table.stableId === tablePosts.stableId,
|
|
564
|
+
);
|
|
565
|
+
if (!rewrittenPostsDrop) throw new Error("missing rewritten DropTable");
|
|
566
|
+
expect(
|
|
567
|
+
rewrittenPostsDrop.externallyDroppedConstraints.has("posts_lab_id_fkey"),
|
|
568
|
+
).toBe(true);
|
|
569
|
+
expect(broken).toContain(terminalDrop);
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
test("publication FK-chain constraint-drop 4-cycle: injects FK drops along the dropped-table chain", () => {
|
|
573
|
+
// Schema:
|
|
574
|
+
// publication p includes labs, posts, and post_attachments
|
|
575
|
+
// post_attachments.post_id REFERENCES posts(id)
|
|
576
|
+
// posts.lab_id REFERENCES labs(id)
|
|
577
|
+
// Diff drops post_attachments and posts, drops labs.unique_lab_id,
|
|
578
|
+
// and removes all three tables from the publication.
|
|
579
|
+
const tableLabs = new Table({
|
|
580
|
+
...baseTableProps,
|
|
581
|
+
name: "labs",
|
|
582
|
+
columns: [{ ...integerColumn("id", 1), not_null: true }],
|
|
583
|
+
constraints: [uniqueConstraint("unique_lab_id", "id")],
|
|
584
|
+
});
|
|
585
|
+
const tablePosts = new Table({
|
|
586
|
+
...baseTableProps,
|
|
587
|
+
name: "posts",
|
|
588
|
+
columns: [
|
|
589
|
+
{ ...integerColumn("id", 1), not_null: true },
|
|
590
|
+
integerColumn("lab_id", 2),
|
|
591
|
+
],
|
|
592
|
+
constraints: [
|
|
593
|
+
fkConstraint({
|
|
594
|
+
name: "posts_lab_id_fkey",
|
|
595
|
+
fkColumn: "lab_id",
|
|
596
|
+
targetSchema: "public",
|
|
597
|
+
targetTable: "labs",
|
|
598
|
+
}),
|
|
599
|
+
],
|
|
600
|
+
});
|
|
601
|
+
const tablePostAttachments = new Table({
|
|
602
|
+
...baseTableProps,
|
|
603
|
+
name: "post_attachments",
|
|
604
|
+
columns: [
|
|
605
|
+
{ ...integerColumn("id", 1), not_null: true },
|
|
606
|
+
integerColumn("post_id", 2),
|
|
607
|
+
],
|
|
608
|
+
constraints: [
|
|
609
|
+
fkConstraint({
|
|
610
|
+
name: "post_attachments_post_id_fkey",
|
|
611
|
+
fkColumn: "post_id",
|
|
612
|
+
targetSchema: "public",
|
|
613
|
+
targetTable: "posts",
|
|
614
|
+
}),
|
|
615
|
+
],
|
|
616
|
+
});
|
|
617
|
+
const publication = new Publication({
|
|
618
|
+
name: "p",
|
|
619
|
+
owner: "postgres",
|
|
620
|
+
comment: null,
|
|
621
|
+
all_tables: false,
|
|
622
|
+
publish_insert: true,
|
|
623
|
+
publish_update: true,
|
|
624
|
+
publish_delete: true,
|
|
625
|
+
publish_truncate: true,
|
|
626
|
+
publish_via_partition_root: false,
|
|
627
|
+
tables: [
|
|
628
|
+
{ schema: "public", name: "labs", columns: null, row_filter: null },
|
|
629
|
+
{
|
|
630
|
+
schema: "public",
|
|
631
|
+
name: "post_attachments",
|
|
632
|
+
columns: null,
|
|
633
|
+
row_filter: null,
|
|
634
|
+
},
|
|
635
|
+
{ schema: "public", name: "posts", columns: null, row_filter: null },
|
|
636
|
+
],
|
|
637
|
+
schemas: [],
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
const terminalDrop = new AlterTableDropConstraint({
|
|
641
|
+
table: tableLabs,
|
|
642
|
+
constraint: tableLabs.constraints[0],
|
|
643
|
+
});
|
|
644
|
+
const changes: Change[] = [
|
|
645
|
+
new AlterPublicationDropTables({
|
|
646
|
+
publication,
|
|
647
|
+
tables: publication.tables,
|
|
648
|
+
}),
|
|
649
|
+
new DropTable({ table: tablePostAttachments }),
|
|
650
|
+
new DropTable({ table: tablePosts }),
|
|
651
|
+
terminalDrop,
|
|
652
|
+
];
|
|
653
|
+
|
|
654
|
+
const broken = tryBreakCycleByChangeInjection([0, 1, 2, 3], changes);
|
|
655
|
+
if (broken === null) throw new Error("expected breaker to fire");
|
|
656
|
+
|
|
657
|
+
const injectedDropNames = broken
|
|
658
|
+
.filter(
|
|
659
|
+
(change): change is AlterTableDropConstraint =>
|
|
660
|
+
change instanceof AlterTableDropConstraint && change !== terminalDrop,
|
|
661
|
+
)
|
|
662
|
+
.map((change) => change.constraint.name)
|
|
663
|
+
.sort();
|
|
664
|
+
expect(injectedDropNames).toEqual([
|
|
665
|
+
"post_attachments_post_id_fkey",
|
|
666
|
+
"posts_lab_id_fkey",
|
|
667
|
+
]);
|
|
668
|
+
|
|
669
|
+
for (const [tableId, constraintName] of [
|
|
670
|
+
[tablePostAttachments.stableId, "post_attachments_post_id_fkey"],
|
|
671
|
+
[tablePosts.stableId, "posts_lab_id_fkey"],
|
|
672
|
+
] as const) {
|
|
673
|
+
const rewrittenDrop = broken.find(
|
|
674
|
+
(change): change is DropTable =>
|
|
675
|
+
change instanceof DropTable && change.table.stableId === tableId,
|
|
676
|
+
);
|
|
677
|
+
if (!rewrittenDrop) throw new Error(`missing DropTable for ${tableId}`);
|
|
678
|
+
expect(
|
|
679
|
+
rewrittenDrop.externallyDroppedConstraints.has(constraintName),
|
|
680
|
+
).toBe(true);
|
|
681
|
+
}
|
|
682
|
+
expect(broken).toContain(terminalDrop);
|
|
683
|
+
});
|
|
684
|
+
|
|
451
685
|
test("returns null for a cycle with no recognised pattern (e.g. publication-only)", () => {
|
|
452
686
|
// Cycle of `AlterPublicationSetOwner` changes — neither FK nor
|
|
453
687
|
// publication-column shape. Breaker must bail so the formatted
|