@supabase/pg-delta 1.0.0-alpha.16 → 1.0.0-alpha.18
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/expand-replace-dependencies.js +27 -0
- package/dist/core/objects/procedure/procedure.diff.js +33 -20
- package/dist/core/objects/table/table.diff.js +1 -0
- package/dist/core/objects/table/table.model.d.ts +4 -0
- package/dist/core/objects/table/table.model.js +2 -0
- package/dist/core/objects/trigger/trigger.diff.js +7 -2
- package/dist/core/objects/trigger/trigger.model.d.ts +1 -1
- package/dist/core/objects/trigger/trigger.model.js +5 -1
- package/dist/core/plan/sql-format/fixtures.js +4 -0
- package/dist/core/post-diff-cycle-breaking.d.ts +7 -0
- package/dist/core/post-diff-cycle-breaking.js +69 -3
- package/package.json +1 -1
- package/src/core/expand-replace-dependencies.test.ts +118 -0
- package/src/core/expand-replace-dependencies.ts +26 -0
- package/src/core/objects/procedure/procedure.diff.test.ts +100 -2
- package/src/core/objects/procedure/procedure.diff.ts +39 -21
- package/src/core/objects/table/changes/table.alter.test.ts +1 -0
- package/src/core/objects/table/table.diff.test.ts +102 -0
- package/src/core/objects/table/table.diff.ts +1 -0
- package/src/core/objects/table/table.model.ts +2 -0
- package/src/core/objects/trigger/trigger.diff.ts +7 -2
- package/src/core/objects/trigger/trigger.model.ts +5 -1
- package/src/core/plan/sql-format/fixtures.ts +4 -0
- package/src/core/post-diff-cycle-breaking.test.ts +142 -0
- package/src/core/post-diff-cycle-breaking.ts +83 -2
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { Catalog } from "./catalog.model.ts";
|
|
2
2
|
import type { Change } from "./change.types.ts";
|
|
3
3
|
import {
|
|
4
|
+
AlterTableAddConstraint,
|
|
4
5
|
AlterTableDropColumn,
|
|
5
6
|
AlterTableDropConstraint,
|
|
7
|
+
AlterTableValidateConstraint,
|
|
6
8
|
} from "./objects/table/changes/table.alter.ts";
|
|
9
|
+
import { CreateCommentOnConstraint } from "./objects/table/changes/table.comment.ts";
|
|
7
10
|
import { DropTable } from "./objects/table/changes/table.drop.ts";
|
|
8
11
|
import { stableId } from "./objects/utils.ts";
|
|
9
12
|
|
|
@@ -52,6 +55,72 @@ function isSupersededByTableReplacement(
|
|
|
52
55
|
return replacedTableIds.has(change.table.stableId);
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Drop earlier duplicates of `AlterTableAddConstraint` /
|
|
60
|
+
* `AlterTableValidateConstraint` / `CreateCommentOnConstraint` targeting
|
|
61
|
+
* replaced tables, keeping only the last occurrence of each
|
|
62
|
+
* `(changeType, table.stableId, constraint.name)`.
|
|
63
|
+
*
|
|
64
|
+
* When `expandReplaceDependencies()` promotes a table to a full
|
|
65
|
+
* `DropTable + CreateTable` pair, it also emits one
|
|
66
|
+
* `AlterTableAddConstraint` (plus optional `VALIDATE CONSTRAINT` /
|
|
67
|
+
* `COMMENT ON CONSTRAINT`) per branch constraint. If `diffTables()` already
|
|
68
|
+
* emitted the same change for a shape flip or a new constraint on that
|
|
69
|
+
* table, the plan ends up with two identical `ALTER TABLE ... ADD
|
|
70
|
+
* CONSTRAINT ...` statements and PostgreSQL fails at apply time with
|
|
71
|
+
* `constraint "..." for relation "..." already exists`. Because
|
|
72
|
+
* `expandReplaceDependencies()` appends its additions after the original
|
|
73
|
+
* `diffTables()` output, the last occurrence is the expansion's emission —
|
|
74
|
+
* keeping it preserves correctness while removing the duplicate.
|
|
75
|
+
*/
|
|
76
|
+
function dropReplacedTableDuplicateConstraintChanges(
|
|
77
|
+
changes: Change[],
|
|
78
|
+
replacedTableIds: ReadonlySet<string>,
|
|
79
|
+
): Change[] {
|
|
80
|
+
if (replacedTableIds.size === 0) return changes;
|
|
81
|
+
|
|
82
|
+
const keyFor = (change: Change): string | null => {
|
|
83
|
+
if (
|
|
84
|
+
!(change instanceof AlterTableAddConstraint) &&
|
|
85
|
+
!(change instanceof AlterTableValidateConstraint) &&
|
|
86
|
+
!(change instanceof CreateCommentOnConstraint)
|
|
87
|
+
) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (!replacedTableIds.has(change.table.stableId)) return null;
|
|
91
|
+
const tag =
|
|
92
|
+
change instanceof AlterTableAddConstraint
|
|
93
|
+
? "add"
|
|
94
|
+
: change instanceof AlterTableValidateConstraint
|
|
95
|
+
? "validate"
|
|
96
|
+
: "comment";
|
|
97
|
+
return `${tag}:${constraintStableId(change.table, change.constraint.name)}`;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const seen = new Set<string>();
|
|
101
|
+
const reversedKept: Change[] = [];
|
|
102
|
+
let mutated = false;
|
|
103
|
+
|
|
104
|
+
// Walk backwards: the first encounter of each key corresponds to its LAST
|
|
105
|
+
// occurrence in the original order. `expandReplaceDependencies()` appends
|
|
106
|
+
// additions after the original changes, so "last wins" keeps the
|
|
107
|
+
// expansion's emission and drops the earlier diffTables duplicate.
|
|
108
|
+
for (let i = changes.length - 1; i >= 0; i--) {
|
|
109
|
+
const change = changes[i] as Change;
|
|
110
|
+
const key = keyFor(change);
|
|
111
|
+
if (key !== null) {
|
|
112
|
+
if (seen.has(key)) {
|
|
113
|
+
mutated = true;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
seen.add(key);
|
|
117
|
+
}
|
|
118
|
+
reversedKept.push(change);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return mutated ? reversedKept.reverse() : changes;
|
|
122
|
+
}
|
|
123
|
+
|
|
55
124
|
function collectExplicitConstraintDropIds(changes: Change[]) {
|
|
56
125
|
const explicitConstraintDropIds = new Set<string>();
|
|
57
126
|
|
|
@@ -84,6 +153,13 @@ function hasSameEntries(
|
|
|
84
153
|
* - If replace expansion added `DropTable(T)+CreateTable(T)`, targeted
|
|
85
154
|
* `AlterTableDropColumn(T.*)` / `AlterTableDropConstraint(T.*)` changes are
|
|
86
155
|
* redundant and create an unbreakable drop-phase cycle, so we elide them.
|
|
156
|
+
* - When the same `DropTable+CreateTable` pair is present, the expansion
|
|
157
|
+
* also emits one `AlterTableAddConstraint` / `AlterTableValidateConstraint`
|
|
158
|
+
* / `CreateCommentOnConstraint` per branch constraint, which may collide
|
|
159
|
+
* with the same change already emitted by `diffTables()` (for example on a
|
|
160
|
+
* shape flip or a new constraint). We dedupe these keeping only the last
|
|
161
|
+
* occurrence so the expansion's emission survives and the diffTables
|
|
162
|
+
* duplicate is removed.
|
|
87
163
|
* - If two dropped tables reference each other via FK, we insert dedicated
|
|
88
164
|
* `AlterTableDropConstraint` changes and teach the paired `DropTable`
|
|
89
165
|
* changes not to claim those FK stable IDs.
|
|
@@ -100,10 +176,15 @@ export function normalizePostDiffCycles({
|
|
|
100
176
|
mainCatalog: Catalog;
|
|
101
177
|
replacedTableIds?: ReadonlySet<string>;
|
|
102
178
|
}): Change[] {
|
|
179
|
+
const dedupedChanges = dropReplacedTableDuplicateConstraintChanges(
|
|
180
|
+
changes,
|
|
181
|
+
replacedTableIds,
|
|
182
|
+
);
|
|
183
|
+
|
|
103
184
|
const structurallyNormalizedChanges =
|
|
104
185
|
replacedTableIds.size === 0
|
|
105
|
-
?
|
|
106
|
-
:
|
|
186
|
+
? dedupedChanges
|
|
187
|
+
: dedupedChanges.filter(
|
|
107
188
|
(change) => !isSupersededByTableReplacement(change, replacedTableIds),
|
|
108
189
|
);
|
|
109
190
|
|