chkit 0.2.0-beta.11 → 0.2.0-beta.12
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/README.md +5 -5
- package/dist/bin/chkit.js +26 -6
- package/dist/bin/chkit.js.map +1 -1
- package/dist/commands/check/output.js +1 -1
- package/dist/commands/check/output.js.map +1 -1
- package/dist/commands/drift/command.d.ts.map +1 -1
- package/dist/commands/drift/command.js +9 -0
- package/dist/commands/drift/command.js.map +1 -1
- package/dist/commands/drift/compare.d.ts +27 -3
- package/dist/commands/drift/compare.d.ts.map +1 -1
- package/dist/commands/drift/compare.js +112 -5
- package/dist/commands/drift/compare.js.map +1 -1
- package/dist/commands/drift/payload.d.ts +1 -0
- package/dist/commands/drift/payload.d.ts.map +1 -1
- package/dist/commands/drift/payload.js +31 -13
- package/dist/commands/drift/payload.js.map +1 -1
- package/dist/commands/generate/command.d.ts.map +1 -1
- package/dist/commands/generate/command.js +69 -17
- package/dist/commands/generate/command.js.map +1 -1
- package/dist/commands/generate/cutover.d.ts +56 -0
- package/dist/commands/generate/cutover.d.ts.map +1 -0
- package/dist/commands/generate/cutover.js +138 -0
- package/dist/commands/generate/cutover.js.map +1 -0
- package/dist/commands/generate/output.d.ts +3 -2
- package/dist/commands/generate/output.d.ts.map +1 -1
- package/dist/commands/generate/output.js +17 -2
- package/dist/commands/generate/output.js.map +1 -1
- package/dist/commands/migrate/abandon.d.ts +4 -3
- package/dist/commands/migrate/abandon.d.ts.map +1 -1
- package/dist/commands/migrate/abandon.js +4 -3
- package/dist/commands/migrate/abandon.js.map +1 -1
- package/dist/commands/migrate/apply.d.ts +3 -1
- package/dist/commands/migrate/apply.d.ts.map +1 -1
- package/dist/commands/migrate/apply.js +64 -5
- package/dist/commands/migrate/apply.js.map +1 -1
- package/dist/commands/migrate/async-apply.d.ts +11 -3
- package/dist/commands/migrate/async-apply.d.ts.map +1 -1
- package/dist/commands/migrate/async-apply.js +43 -19
- package/dist/commands/migrate/async-apply.js.map +1 -1
- package/dist/commands/migrate/command.d.ts +3 -1
- package/dist/commands/migrate/command.d.ts.map +1 -1
- package/dist/commands/migrate/command.js +11 -1
- package/dist/commands/migrate/command.js.map +1 -1
- package/dist/commands/migrate/output.js +3 -3
- package/dist/commands/migrate/output.js.map +1 -1
- package/dist/commands/migrate/settings.d.ts +8 -0
- package/dist/commands/migrate/settings.d.ts.map +1 -0
- package/dist/commands/migrate/settings.js +40 -0
- package/dist/commands/migrate/settings.js.map +1 -0
- package/dist/commands/plugin.d.ts.map +1 -1
- package/dist/commands/plugin.js +25 -3
- package/dist/commands/plugin.js.map +1 -1
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +11 -15
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/registry.js +1 -1
- package/dist/commands/registry.js.map +1 -1
- package/dist/commands/snapshot/rebuild.d.ts.map +1 -1
- package/dist/commands/snapshot/rebuild.js +18 -1
- package/dist/commands/snapshot/rebuild.js.map +1 -1
- package/dist/registry/resolve.d.ts.map +1 -1
- package/dist/registry/resolve.js +7 -0
- package/dist/registry/resolve.js.map +1 -1
- package/dist/runtime/command-dispatch.d.ts +2 -1
- package/dist/runtime/command-dispatch.d.ts.map +1 -1
- package/dist/runtime/command-dispatch.js +10 -7
- package/dist/runtime/command-dispatch.js.map +1 -1
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +2 -1
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/help.d.ts +1 -1
- package/dist/runtime/help.d.ts.map +1 -1
- package/dist/runtime/help.js +10 -4
- package/dist/runtime/help.js.map +1 -1
- package/dist/runtime/journal-store.d.ts.map +1 -1
- package/dist/runtime/journal-store.js +123 -16
- package/dist/runtime/journal-store.js.map +1 -1
- package/dist/runtime/json-output.d.ts +14 -0
- package/dist/runtime/json-output.d.ts.map +1 -1
- package/dist/runtime/json-output.js +43 -2
- package/dist/runtime/json-output.js.map +1 -1
- package/dist/runtime/plugin-runtime/executor-debug.d.ts.map +1 -1
- package/dist/runtime/plugin-runtime/executor-debug.js +8 -8
- package/dist/runtime/plugin-runtime/executor-debug.js.map +1 -1
- package/dist/runtime/safety-markers.d.ts +4 -2
- package/dist/runtime/safety-markers.d.ts.map +1 -1
- package/dist/runtime/safety-markers.js +1 -1
- package/dist/runtime/safety-markers.js.map +1 -1
- package/package.json +8 -5
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
-
import { canonicalizeSqlFragments, isUnknownDatabaseError, } from '@chkit/clickhouse';
|
|
2
|
+
import { canonicalizeSqlFragments, isUnknownDatabaseError, listViewDetails, } from '@chkit/clickhouse';
|
|
3
3
|
import { debug } from '../../runtime/debug.js';
|
|
4
|
-
import { collectTableSqlFragments, compareSchemaObjects, compareTableShape, } from './compare.js';
|
|
4
|
+
import { collectTableSqlFragments, collectViewSqlQueries, compareSchemaObjects, compareTableShape, compareViewShape, } from './compare.js';
|
|
5
5
|
/**
|
|
6
|
-
* Build a canonicalizer for every SQL fragment across the compared tables
|
|
7
|
-
*
|
|
6
|
+
* Build a canonicalizer for every SQL fragment across the compared tables and
|
|
7
|
+
* views, one batched ClickHouse query per kind. Returns undefined when there is nothing to
|
|
8
8
|
* canonicalize or ClickHouse can't format (old server, offline) — the comparer
|
|
9
9
|
* then falls back to plain string normalization.
|
|
10
10
|
*/
|
|
11
|
-
async function buildSqlCanonicalizer(db, pairs) {
|
|
11
|
+
async function buildSqlCanonicalizer(db, pairs, viewQueries) {
|
|
12
12
|
const expressions = [];
|
|
13
|
-
const queries = [];
|
|
13
|
+
const queries = [...viewQueries];
|
|
14
14
|
for (const { expected, actual } of pairs) {
|
|
15
15
|
const fragments = collectTableSqlFragments(expected, actual);
|
|
16
16
|
expressions.push(...fragments.expressions);
|
|
@@ -19,10 +19,10 @@ async function buildSqlCanonicalizer(db, pairs) {
|
|
|
19
19
|
if (expressions.length === 0 && queries.length === 0)
|
|
20
20
|
return undefined;
|
|
21
21
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
// One after the other: the CLI's executor is bound to one HTTP session, and
|
|
23
|
+
// ClickHouse rejects a second query while the session is busy.
|
|
24
|
+
const expressionMap = await canonicalizeSqlFragments(db, expressions, { wrap: true });
|
|
25
|
+
const queryMap = await canonicalizeSqlFragments(db, queries, { wrap: false });
|
|
26
26
|
return {
|
|
27
27
|
expression: (fragment) => expressionMap.get(fragment) ?? null,
|
|
28
28
|
query: (fragment) => queryMap.get(fragment) ?? null,
|
|
@@ -44,6 +44,7 @@ export function computeDrifted(input) {
|
|
|
44
44
|
return (input.missingCount > 0 ||
|
|
45
45
|
input.kindMismatchCount > 0 ||
|
|
46
46
|
input.tableDriftCount > 0 ||
|
|
47
|
+
input.viewDriftCount > 0 ||
|
|
47
48
|
(input.failOnExtraObjects && input.extraCount > 0));
|
|
48
49
|
}
|
|
49
50
|
export async function buildDriftPayload(config, metaDir, snapshot, scope, executor) {
|
|
@@ -113,16 +114,33 @@ export async function buildDriftPayload(config, metaDir, snapshot, scope, execut
|
|
|
113
114
|
const expected = expectedTableMap.get(`${actual.database}.${actual.name}`);
|
|
114
115
|
return expected ? [{ expected, actual }] : [];
|
|
115
116
|
});
|
|
116
|
-
const
|
|
117
|
+
const expectedViewMap = new Map(snapshot.definitions
|
|
118
|
+
.filter((def) => def.kind === 'view' || def.kind === 'materialized_view')
|
|
119
|
+
.map((def) => [`${def.kind}:${def.database}.${def.name}`, def]));
|
|
120
|
+
const actualViews = expectedViewMap.size > 0 ? await listViewDetails(db, [...expectedDatabases]) : [];
|
|
121
|
+
const viewPairs = actualViews.flatMap((actual) => {
|
|
122
|
+
const expected = expectedViewMap.get(`${actual.kind}:${actual.database}.${actual.name}`);
|
|
123
|
+
return expected ? [{ expected, actual }] : [];
|
|
124
|
+
});
|
|
125
|
+
// Unqualified names in a view's query resolve to the session database.
|
|
126
|
+
const currentDatabase = viewPairs.length > 0
|
|
127
|
+
? (await db.query('SELECT currentDatabase() AS database'))[0]?.database
|
|
128
|
+
: undefined;
|
|
129
|
+
const canonicalizer = await buildSqlCanonicalizer(db, pairs, viewPairs.flatMap(({ expected, actual }) => collectViewSqlQueries(expected, actual)));
|
|
117
130
|
const tableDrift = pairs
|
|
118
131
|
.map(({ expected, actual }) => compareTableShape(expected, actual, canonicalizer))
|
|
119
132
|
.filter((item) => item !== null)
|
|
120
133
|
.sort((a, b) => a.table.localeCompare(b.table));
|
|
121
|
-
|
|
134
|
+
const viewDrift = viewPairs
|
|
135
|
+
.flatMap(({ expected, actual }) => compareViewShape(expected, actual, currentDatabase ?? '', canonicalizer))
|
|
136
|
+
.sort((a, b) => a.object.localeCompare(b.object));
|
|
137
|
+
const objectDriftWithViews = [...objectDrift, ...viewDrift];
|
|
138
|
+
debug('drift', `comparison: missing=${missing.length}, extra=${extra.length}, kindMismatches=${kindMismatches.length}, objectDrift=${objectDrift.length}, tableDrift=${tableDrift.length}, viewDrift=${viewDrift.length}`);
|
|
122
139
|
const drifted = computeDrifted({
|
|
123
140
|
missingCount: missing.length,
|
|
124
141
|
kindMismatchCount: kindMismatches.length,
|
|
125
142
|
tableDriftCount: tableDrift.length,
|
|
143
|
+
viewDriftCount: viewDrift.length,
|
|
126
144
|
extraCount: extra.length,
|
|
127
145
|
failOnExtraObjects: config.check?.failOnExtraObjects === true,
|
|
128
146
|
});
|
|
@@ -135,7 +153,7 @@ export async function buildDriftPayload(config, metaDir, snapshot, scope, execut
|
|
|
135
153
|
missing,
|
|
136
154
|
extra,
|
|
137
155
|
kindMismatches,
|
|
138
|
-
objectDrift,
|
|
156
|
+
objectDrift: objectDriftWithViews,
|
|
139
157
|
tableDrift,
|
|
140
158
|
};
|
|
141
159
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/commands/drift/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/commands/drift/payload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EACL,wBAAwB,EACxB,sBAAsB,EACtB,eAAe,GAIhB,MAAM,mBAAmB,CAAA;AAS1B,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAE9C,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GAIjB,MAAM,cAAc,CAAA;AAErB;;;;;GAKG;AACH,KAAK,UAAU,qBAAqB,CAClC,EAAsB,EACtB,KAAsE,EACtE,WAAqB;IAErB,MAAM,WAAW,GAAa,EAAE,CAAA;IAChC,MAAM,OAAO,GAAa,CAAC,GAAG,WAAW,CAAC,CAAA;IAC1C,KAAK,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,wBAAwB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC5D,WAAW,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,CAAA;QAC1C,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IAEtE,IAAI,CAAC;QACH,4EAA4E;QAC5E,+DAA+D;QAC/D,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACrF,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QAC7E,OAAO;YACL,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI;YAC7D,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI;SACpD,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,CAAC,OAAO,EAAE,8DAA8D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC7F,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAiBD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAO9B;IACC,OAAO,CACL,KAAK,CAAC,YAAY,GAAG,CAAC;QACtB,KAAK,CAAC,iBAAiB,GAAG,CAAC;QAC3B,KAAK,CAAC,eAAe,GAAG,CAAC;QACzB,KAAK,CAAC,cAAc,GAAG,CAAC;QACxB,CAAC,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CACnD,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAiB,EACjB,OAAe,EACf,QAAkB,EAClB,KAAkB,EAClB,QAA6B;IAE7B,MAAM,cAAc,GAClB,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACnF,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IAChF,MAAM,EAAE,GAAG,QAAQ,CAAA;IAEnB,KAAK,CAAC,OAAO,EAAE,sCAAsC,QAAQ,CAAC,WAAW,CAAC,MAAM,cAAc,CAAC,CAAA;IAC/F,IAAI,aAAgC,CAAA;IACpC,IAAI,CAAC;QACH,aAAa,GAAG,MAAM,EAAE,CAAC,iBAAiB,EAAE,CAAA;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW;iBACrC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;gBACd,IAAI,CAAC,cAAc;oBAAE,OAAO,IAAI,CAAA;gBAChC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;oBAAE,OAAO,IAAI,CAAA;gBACrC,OAAO,cAAc,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;YAC1D,CAAC,CAAC;iBACD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;YAC9C,OAAO;gBACL,KAAK;gBACL,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;gBAC5C,aAAa,EAAE,WAAW,CAAC,MAAM;gBACjC,WAAW,EAAE,CAAC;gBACd,OAAO,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC;gBAC/B,eAAe,EAAE,IAAI;gBACrB,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ;gBACrC,OAAO,EAAE,WAAW;gBACpB,KAAK,EAAE,EAAE;gBACT,cAAc,EAAE,EAAE;gBAClB,WAAW,EAAE,EAAE;gBACf,UAAU,EAAE,EAAE;aACf,CAAA;QACH,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;IACD,MAAM,eAAe,GAAG,QAAQ,CAAC,WAAW;SACzC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACd,IAAI,CAAC,cAAc;YAAE,OAAO,IAAI,CAAA;QAChC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,IAAI,CAAA;QACrC,OAAO,cAAc,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;IAC1D,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACb,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,GAAG,CAAC,IAAI;KACf,CAAC,CAAC,CAAA;IACL,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC7E,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IAE1F,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,GAAG,oBAAoB,CAC1E,eAAe,EACf,aAAa,CACd,CAAA;IAED,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAA0B,EAAE;QACjF,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,KAAK,CAAA;QACtC,IAAI,CAAC,cAAc;YAAE,OAAO,IAAI,CAAA;QAChC,OAAO,cAAc,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;IAC1D,CAAC,CAAC,CAAA;IACF,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAC9B,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,CAC1E,CAAA;IACD,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,gBAAgB,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAA;IACtE,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC5C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QAC1E,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;IACF,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,QAAQ,CAAC,WAAW;SACjB,MAAM,CACL,CAAC,GAAG,EAAsD,EAAE,CAC1D,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,CAC1D;SACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,CAClE,CAAA;IACD,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,EAAE,EAAE,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACrG,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAC/C,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACxF,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;IACF,uEAAuE;IACvE,MAAM,eAAe,GACnB,SAAS,CAAC,MAAM,GAAG,CAAC;QAClB,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAuB,sCAAsC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ;QAC7F,CAAC,CAAC,SAAS,CAAA;IACf,MAAM,aAAa,GAAG,MAAM,qBAAqB,CAC/C,EAAE,EACF,KAAK,EACL,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CACrF,CAAA;IACD,MAAM,UAAU,GAAG,KAAK;SACrB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;SACjF,MAAM,CAAC,CAAC,IAAI,EAAoC,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC;SACjE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,MAAM,SAAS,GAAG,SAAS;SACxB,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAChC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,IAAI,EAAE,EAAE,aAAa,CAAC,CACzE;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IACnD,MAAM,oBAAoB,GAAG,CAAC,GAAG,WAAW,EAAE,GAAG,SAAS,CAAC,CAAA;IAE3D,KAAK,CAAC,OAAO,EAAE,uBAAuB,OAAO,CAAC,MAAM,WAAW,KAAK,CAAC,MAAM,oBAAoB,cAAc,CAAC,MAAM,iBAAiB,WAAW,CAAC,MAAM,gBAAgB,UAAU,CAAC,MAAM,eAAe,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;IAE1N,MAAM,OAAO,GAAG,cAAc,CAAC;QAC7B,YAAY,EAAE,OAAO,CAAC,MAAM;QAC5B,iBAAiB,EAAE,cAAc,CAAC,MAAM;QACxC,eAAe,EAAE,UAAU,CAAC,MAAM;QAClC,cAAc,EAAE,SAAS,CAAC,MAAM;QAChC,UAAU,EAAE,KAAK,CAAC,MAAM;QACxB,kBAAkB,EAAE,MAAM,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI;KAC9D,CAAC,CAAA;IACF,OAAO;QACL,KAAK;QACL,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC;QAC5C,aAAa,EAAE,eAAe,CAAC,MAAM;QACrC,WAAW,EAAE,aAAa,CAAC,MAAM;QACjC,OAAO;QACP,OAAO;QACP,KAAK;QACL,cAAc;QACd,WAAW,EAAE,oBAAoB;QACjC,UAAU;KACX,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/command.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/command.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAyDjF,eAAO,MAAM,eAAe,EAAE,gBAK7B,CAAA"}
|
|
@@ -12,6 +12,7 @@ import { detectDictionaryPasswordWarnings } from './dictionary-password-warnings
|
|
|
12
12
|
import { applyExplicitDictionaryRenames, applyExplicitTableRenames, applySelectedRenameSuggestions, assertCliColumnMappingsResolvable, buildExplicitColumnRenameSuggestions, } from './plan-pipeline.js';
|
|
13
13
|
import { assertCliDictionaryMappingsResolvable, assertCliTableMappingsResolvable, assertNoConflictingColumnMappings, assertNoConflictingDictionaryMappings, assertNoConflictingTableMappings, collectSchemaRenameMappings, mergeColumnMappings, mergeDictionaryMappings, mergeTableMappings, parseRenameColumnMappings, parseRenameDictionaryMappings, parseRenameTableMappings, remapOldDefinitionsForDictionaryRenames, remapOldDefinitionsForTableRenames, resolveActiveDictionaryMappings, resolveActiveTableMappings, } from './rename-mappings.js';
|
|
14
14
|
import { emitGenerateApplyOutput, emitGenerateEmptyOutput, emitGeneratePlanOutput } from './output.js';
|
|
15
|
+
import { applyCutovers, carryRetainedDefinitions, resolveCutoverFlags, summarizeCutover } from './cutover.js';
|
|
15
16
|
import { debug } from '../../runtime/debug.js';
|
|
16
17
|
const GENERATE_FLAGS = defineFlags([
|
|
17
18
|
{ name: '--name', type: 'string', description: 'Migration name', placeholder: '<name>' },
|
|
@@ -21,6 +22,10 @@ const GENERATE_FLAGS = defineFlags([
|
|
|
21
22
|
{ name: '--rename-dictionary', type: 'string[]', description: 'Explicit dictionary rename mapping', placeholder: '<mapping>' },
|
|
22
23
|
{ name: '--dryrun', type: 'boolean', description: 'Print plan without writing artifacts' },
|
|
23
24
|
{ name: '--empty', type: 'boolean', description: 'Scaffold a blank manual migration (no schema diff, snapshot untouched)' },
|
|
25
|
+
{ name: '--cutover', type: 'string[]', description: 'Cut a structural table change over without downtime, keyed by a unique key', placeholder: '<database.table=key>' },
|
|
26
|
+
{ name: '--cutover-copy', type: 'string', description: 'Where the cutover copies existing rows: migration (default) or backfill', placeholder: '<mode>' },
|
|
27
|
+
{ name: '--cutover-old', type: 'string', description: 'What happens to the pre-cutover table: keep (default, as <table>_previous) or drop', placeholder: '<mode>' },
|
|
28
|
+
{ name: '--drop-retained', type: 'string[]', description: 'Drop a table a cutover retained', placeholder: '<database.table>' },
|
|
24
29
|
]);
|
|
25
30
|
export const generateCommand = {
|
|
26
31
|
name: 'generate',
|
|
@@ -53,19 +58,31 @@ async function cmdGenerate(ctx) {
|
|
|
53
58
|
emitGenerateEmptyOutput(result, jsonMode);
|
|
54
59
|
return 0;
|
|
55
60
|
}
|
|
56
|
-
const
|
|
61
|
+
const cutoverFlags = resolveCutoverFlags({
|
|
62
|
+
cutover: f['--cutover'] ?? [],
|
|
63
|
+
copy: f['--cutover-copy'],
|
|
64
|
+
oldTable: f['--cutover-old'],
|
|
65
|
+
dropRetained: f['--drop-retained'] ?? [],
|
|
66
|
+
});
|
|
67
|
+
const now = new Date();
|
|
68
|
+
const schemaDefinitions = await loadSchemaDefinitionsWithHooks({ command: 'generate', config, configPath, flags, jsonMode, tableSelector }, { pluginRuntime });
|
|
57
69
|
const renameTableValues = f['--rename-table'] ?? [];
|
|
58
70
|
const renameColumnValues = f['--rename-column'] ?? [];
|
|
59
71
|
const renameDictionaryValues = f['--rename-dictionary'] ?? [];
|
|
60
72
|
const cliTableMappings = parseRenameTableMappings(renameTableValues);
|
|
61
73
|
const cliColumnMappings = parseRenameColumnMappings(renameColumnValues);
|
|
62
74
|
const cliDictionaryMappings = parseRenameDictionaryMappings(renameDictionaryValues);
|
|
63
|
-
const schemaMappings = collectSchemaRenameMappings(
|
|
75
|
+
const schemaMappings = collectSchemaRenameMappings(schemaDefinitions);
|
|
64
76
|
const tableMappings = mergeTableMappings(schemaMappings.tableMappings, cliTableMappings);
|
|
65
77
|
const columnMappings = mergeColumnMappings(schemaMappings.columnMappings, cliColumnMappings);
|
|
66
78
|
const dictionaryMappings = mergeDictionaryMappings(schemaMappings.dictionaryMappings, cliDictionaryMappings);
|
|
67
79
|
const { migrationsDir, metaDir } = dirs;
|
|
68
80
|
const previousDefinitions = (await readSnapshot(metaDir))?.definitions ?? [];
|
|
81
|
+
const definitions = carryRetainedDefinitions({
|
|
82
|
+
previousDefinitions,
|
|
83
|
+
definitions: schemaDefinitions,
|
|
84
|
+
dropRetained: f['--drop-retained'] ?? [],
|
|
85
|
+
});
|
|
69
86
|
const resolvedScope = resolveTableScope(tableSelector, [
|
|
70
87
|
...tableKeysFromDefinitions(previousDefinitions),
|
|
71
88
|
...tableKeysFromDefinitions(definitions),
|
|
@@ -101,18 +118,7 @@ async function cmdGenerate(ctx) {
|
|
|
101
118
|
plan = planDiff(remappedPreviousDefinitions, definitions);
|
|
102
119
|
}
|
|
103
120
|
catch (error) {
|
|
104
|
-
|
|
105
|
-
if (jsonMode) {
|
|
106
|
-
emitJson('generate', {
|
|
107
|
-
error: 'validation_failed',
|
|
108
|
-
issues: error.issues,
|
|
109
|
-
});
|
|
110
|
-
return 1;
|
|
111
|
-
}
|
|
112
|
-
const details = error.issues.map((issue) => `- [${issue.code}] ${issue.message}`).join('\n');
|
|
113
|
-
throw new Error(`${error.message}\n${details}`);
|
|
114
|
-
}
|
|
115
|
-
throw error;
|
|
121
|
+
return reportValidationError(error, jsonMode);
|
|
116
122
|
}
|
|
117
123
|
plan = applyExplicitTableRenames(plan, activeTableMappings);
|
|
118
124
|
plan = applyExplicitDictionaryRenames(plan, activeDictionaryMappings);
|
|
@@ -129,6 +135,27 @@ async function cmdGenerate(ctx) {
|
|
|
129
135
|
renameMappings: activeTableMappings,
|
|
130
136
|
}).plan;
|
|
131
137
|
}
|
|
138
|
+
// A cutover replaces the DROP + CREATE of a structural change with a
|
|
139
|
+
// zero-downtime copy and swap. It runs after scope filtering, so a table
|
|
140
|
+
// outside --table has no DROP + CREATE to replace.
|
|
141
|
+
let cutovers = [];
|
|
142
|
+
if (cutoverFlags.requests.length > 0) {
|
|
143
|
+
try {
|
|
144
|
+
;
|
|
145
|
+
({ plan, cutovers } = applyCutovers({
|
|
146
|
+
plan,
|
|
147
|
+
previousDefinitions: remappedPreviousDefinitions,
|
|
148
|
+
definitions,
|
|
149
|
+
cutovers: cutoverFlags,
|
|
150
|
+
cluster: config.clickhouse?.cluster,
|
|
151
|
+
stamp: migrationStamp(now),
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
return reportValidationError(error, jsonMode);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const cutoverSummaries = cutovers.map(summarizeCutover);
|
|
132
159
|
// Cluster mode: stamp `ON CLUSTER <name>` onto every DDL statement as a final
|
|
133
160
|
// post-pass, after all plan transforms (renames, plugins, scope filtering).
|
|
134
161
|
plan = applyOnClusterToPlan(plan, config.clickhouse?.cluster);
|
|
@@ -137,10 +164,10 @@ async function cmdGenerate(ctx) {
|
|
|
137
164
|
...plan.operations.flatMap((operation) => operation.warning ? [operation.warning] : []),
|
|
138
165
|
];
|
|
139
166
|
if (planMode) {
|
|
140
|
-
emitGeneratePlanOutput(plan, jsonMode, resolvedScope, dictionaryPasswordWarnings);
|
|
167
|
+
emitGeneratePlanOutput(plan, jsonMode, resolvedScope, dictionaryPasswordWarnings, cutoverSummaries);
|
|
141
168
|
return 0;
|
|
142
169
|
}
|
|
143
|
-
const
|
|
170
|
+
const scopedDefinitions = resolvedScope.enabled
|
|
144
171
|
? buildScopedSnapshotDefinitions({
|
|
145
172
|
previousDefinitions,
|
|
146
173
|
nextDefinitions: definitions,
|
|
@@ -148,6 +175,12 @@ async function cmdGenerate(ctx) {
|
|
|
148
175
|
renameMappings: activeTableMappings,
|
|
149
176
|
})
|
|
150
177
|
: definitions;
|
|
178
|
+
// A keep-mode cutover leaves the old table as <table>_previous: record it so
|
|
179
|
+
// drift, check and the next generate treat it as managed.
|
|
180
|
+
const artifactDefinitions = [
|
|
181
|
+
...scopedDefinitions,
|
|
182
|
+
...cutovers.flatMap((cutover) => (cutover.retained ? [cutover.retained] : [])),
|
|
183
|
+
];
|
|
151
184
|
debug('generate', `plan: ${plan.operations.length} operations — writing artifacts`);
|
|
152
185
|
const result = await generateArtifacts({
|
|
153
186
|
definitions: artifactDefinitions,
|
|
@@ -157,6 +190,7 @@ async function cmdGenerate(ctx) {
|
|
|
157
190
|
migrationId,
|
|
158
191
|
plan,
|
|
159
192
|
cliVersion: CLI_VERSION,
|
|
193
|
+
now,
|
|
160
194
|
});
|
|
161
195
|
const codegenPlugin = pluginRuntime.plugins.find((entry) => entry.plugin.manifest.name === 'codegen');
|
|
162
196
|
const codegenRunOnGenerate = codegenPlugin ? codegenPlugin.options.runOnGenerate !== false : false;
|
|
@@ -174,7 +208,25 @@ async function cmdGenerate(ctx) {
|
|
|
174
208
|
throw new Error(`Plugin "codegen" failed in generate integration with exit code ${codegenExitCode}.`);
|
|
175
209
|
}
|
|
176
210
|
}
|
|
177
|
-
emitGenerateApplyOutput(result, artifactDefinitions, plan, jsonMode, resolvedScope, dictionaryPasswordWarnings);
|
|
211
|
+
emitGenerateApplyOutput(result, artifactDefinitions, plan, jsonMode, resolvedScope, dictionaryPasswordWarnings, cutoverSummaries);
|
|
178
212
|
return 0;
|
|
179
213
|
}
|
|
214
|
+
/** Prints a schema or cutover validation failure; rethrows anything else. */
|
|
215
|
+
function reportValidationError(error, jsonMode) {
|
|
216
|
+
if (!(error instanceof ChxValidationError))
|
|
217
|
+
throw error;
|
|
218
|
+
if (jsonMode) {
|
|
219
|
+
emitJson('generate', {
|
|
220
|
+
error: 'validation_failed',
|
|
221
|
+
issues: error.issues,
|
|
222
|
+
});
|
|
223
|
+
return 1;
|
|
224
|
+
}
|
|
225
|
+
const details = error.issues.map((issue) => `- [${issue.code}] ${issue.message}`).join('\n');
|
|
226
|
+
throw new Error(`${error.message}\n${details}`);
|
|
227
|
+
}
|
|
228
|
+
/** The migration file's timestamp prefix, `YYYYMMDDHHMMSS`; names a cutover's temporary objects. */
|
|
229
|
+
function migrationStamp(now) {
|
|
230
|
+
return now.toISOString().replace(/[-:TZ.]/g, '').slice(0, 14);
|
|
231
|
+
}
|
|
180
232
|
//# sourceMappingURL=command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/commands/generate/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC1E,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/commands/generate/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { type CutoverCopyMode, type CutoverOldTableMode, type CutoverRequest, type MigrationPlan, type PlannedCutover, type SchemaDefinition } from '@chkit/core';
|
|
2
|
+
export interface CutoverFlags {
|
|
3
|
+
cutover: string[];
|
|
4
|
+
copy: string | undefined;
|
|
5
|
+
oldTable: string | undefined;
|
|
6
|
+
dropRetained: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface ResolvedCutovers {
|
|
9
|
+
requests: CutoverRequest[];
|
|
10
|
+
copy: CutoverCopyMode;
|
|
11
|
+
oldTable: CutoverOldTableMode;
|
|
12
|
+
}
|
|
13
|
+
/** What `generate` reports for each cutover, in JSON and text. */
|
|
14
|
+
export interface CutoverSummary {
|
|
15
|
+
table: string;
|
|
16
|
+
key: string[];
|
|
17
|
+
copy: CutoverCopyMode;
|
|
18
|
+
oldTable: CutoverOldTableMode;
|
|
19
|
+
shadow: string;
|
|
20
|
+
mirror: string;
|
|
21
|
+
snapshot: string;
|
|
22
|
+
columns: string[];
|
|
23
|
+
retainedAs?: string;
|
|
24
|
+
nextSteps: string[];
|
|
25
|
+
}
|
|
26
|
+
/** Reads `--cutover`, `--cutover-copy` and `--cutover-old`; usage errors throw. */
|
|
27
|
+
export declare function resolveCutoverFlags(flags: CutoverFlags): ResolvedCutovers;
|
|
28
|
+
/**
|
|
29
|
+
* Tables a keep-mode cutover retained (`retainedBy` in the snapshot) stay
|
|
30
|
+
* planned as they are, so they never read as a pending drop. `--drop-retained`
|
|
31
|
+
* leaves one out, which plans its DROP like any removed table. A table the
|
|
32
|
+
* schema declares again is planned from the schema.
|
|
33
|
+
*/
|
|
34
|
+
export declare function carryRetainedDefinitions(input: {
|
|
35
|
+
previousDefinitions: SchemaDefinition[];
|
|
36
|
+
definitions: SchemaDefinition[];
|
|
37
|
+
dropRetained: string[];
|
|
38
|
+
}): SchemaDefinition[];
|
|
39
|
+
/**
|
|
40
|
+
* Replaces the DROP + CREATE that `planDiff` emits for each cutover table with
|
|
41
|
+
* the cutover's operations, at the CREATE's position (after the drops, before
|
|
42
|
+
* objects created on top of the table).
|
|
43
|
+
*/
|
|
44
|
+
export declare function applyCutovers(input: {
|
|
45
|
+
plan: MigrationPlan;
|
|
46
|
+
previousDefinitions: SchemaDefinition[];
|
|
47
|
+
definitions: SchemaDefinition[];
|
|
48
|
+
cutovers: ResolvedCutovers;
|
|
49
|
+
cluster: string | undefined;
|
|
50
|
+
stamp: string;
|
|
51
|
+
}): {
|
|
52
|
+
plan: MigrationPlan;
|
|
53
|
+
cutovers: PlannedCutover[];
|
|
54
|
+
};
|
|
55
|
+
export declare function summarizeCutover(cutover: PlannedCutover): CutoverSummary;
|
|
56
|
+
//# sourceMappingURL=cutover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cutover.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/cutover.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAClB,KAAK,cAAc,EAEnB,KAAK,gBAAgB,EAEtB,MAAM,aAAa,CAAA;AAEpB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;IACxB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,IAAI,EAAE,eAAe,CAAA;IACrB,QAAQ,EAAE,mBAAmB,CAAA;CAC9B;AAED,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,IAAI,EAAE,eAAe,CAAA;IACrB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,gBAAgB,CAoBzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC9C,mBAAmB,EAAE,gBAAgB,EAAE,CAAA;IACvC,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB,GAAG,gBAAgB,EAAE,CAmBrB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,IAAI,EAAE,aAAa,CAAA;IACnB,mBAAmB,EAAE,gBAAgB,EAAE,CAAA;IACvC,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;CACd,GAAG;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAkCtD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAuBxE"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { CUTOVER_COPY_MODES, CUTOVER_OLD_TABLE_MODES, parseCutoverRequest, planCutover, readsTable, } from '@chkit/core';
|
|
2
|
+
/** Reads `--cutover`, `--cutover-copy` and `--cutover-old`; usage errors throw. */
|
|
3
|
+
export function resolveCutoverFlags(flags) {
|
|
4
|
+
const requests = flags.cutover.map(parseCutoverRequest);
|
|
5
|
+
if (requests.length === 0 && (flags.copy !== undefined || flags.oldTable !== undefined)) {
|
|
6
|
+
throw new Error('--cutover-copy and --cutover-old apply to a cutover: add --cutover <database>.<table>=<key columns>.');
|
|
7
|
+
}
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
for (const request of requests) {
|
|
10
|
+
const target = `${request.database}.${request.table}`;
|
|
11
|
+
if (seen.has(target))
|
|
12
|
+
throw new Error(`--cutover ${target} is given more than once.`);
|
|
13
|
+
seen.add(target);
|
|
14
|
+
}
|
|
15
|
+
const copy = flags.copy ?? 'migration';
|
|
16
|
+
if (!CUTOVER_COPY_MODES.includes(copy)) {
|
|
17
|
+
throw new Error(`Invalid --cutover-copy "${copy}". Expected ${CUTOVER_COPY_MODES.join(' or ')}.`);
|
|
18
|
+
}
|
|
19
|
+
const oldTable = flags.oldTable ?? 'keep';
|
|
20
|
+
if (!CUTOVER_OLD_TABLE_MODES.includes(oldTable)) {
|
|
21
|
+
throw new Error(`Invalid --cutover-old "${oldTable}". Expected ${CUTOVER_OLD_TABLE_MODES.join(' or ')}.`);
|
|
22
|
+
}
|
|
23
|
+
return { requests, copy: copy, oldTable: oldTable };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Tables a keep-mode cutover retained (`retainedBy` in the snapshot) stay
|
|
27
|
+
* planned as they are, so they never read as a pending drop. `--drop-retained`
|
|
28
|
+
* leaves one out, which plans its DROP like any removed table. A table the
|
|
29
|
+
* schema declares again is planned from the schema.
|
|
30
|
+
*/
|
|
31
|
+
export function carryRetainedDefinitions(input) {
|
|
32
|
+
const retained = input.previousDefinitions.filter((def) => def.kind === 'table' && def.retainedBy !== undefined);
|
|
33
|
+
const retainedNames = new Set(retained.map((def) => `${def.database}.${def.name}`));
|
|
34
|
+
for (const name of input.dropRetained) {
|
|
35
|
+
if (!retainedNames.has(name)) {
|
|
36
|
+
const known = [...retainedNames];
|
|
37
|
+
throw new Error(`--drop-retained ${name}: no table retained by a cutover has that name${known.length > 0 ? ` (retained: ${known.join(', ')})` : ''}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const drop = new Set(input.dropRetained);
|
|
41
|
+
const declared = new Set(input.definitions.map((def) => `${def.kind}:${def.database}.${def.name}`));
|
|
42
|
+
const carried = retained.filter((def) => !drop.has(`${def.database}.${def.name}`) && !declared.has(`table:${def.database}.${def.name}`));
|
|
43
|
+
return [...input.definitions, ...carried];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Replaces the DROP + CREATE that `planDiff` emits for each cutover table with
|
|
47
|
+
* the cutover's operations, at the CREATE's position (after the drops, before
|
|
48
|
+
* objects created on top of the table).
|
|
49
|
+
*/
|
|
50
|
+
export function applyCutovers(input) {
|
|
51
|
+
const { cutovers } = input;
|
|
52
|
+
let operations = input.plan.operations;
|
|
53
|
+
const planned = [];
|
|
54
|
+
for (const request of cutovers.requests) {
|
|
55
|
+
const target = `${request.database}.${request.table}`;
|
|
56
|
+
const key = `table:${target}`;
|
|
57
|
+
const dropIndex = operations.findIndex((op) => op.type === 'drop_table' && op.key === key);
|
|
58
|
+
const createIndex = operations.findIndex((op) => op.type === 'create_table' && op.key === key);
|
|
59
|
+
if (dropIndex === -1 || createIndex === -1) {
|
|
60
|
+
throw new Error(`--cutover ${target}: the plan does not recreate ${target}. A cutover replaces the DROP TABLE and CREATE TABLE of a change to the engine, ORDER BY, PRIMARY KEY or PARTITION BY of an existing table${input.plan.operations.length === 0 ? '; the plan is empty' : ''}. Check the table name and the --table scope.`);
|
|
61
|
+
}
|
|
62
|
+
assertNoDependentRecreated(operations, [...input.previousDefinitions, ...input.definitions], request);
|
|
63
|
+
const oldDef = findTable(input.previousDefinitions, request);
|
|
64
|
+
const newDef = findTable(input.definitions, request);
|
|
65
|
+
if (!oldDef || !newDef)
|
|
66
|
+
throw new Error(`--cutover ${target}: the table is missing from the snapshot or the schema.`);
|
|
67
|
+
const cutover = planCutover({
|
|
68
|
+
oldDef,
|
|
69
|
+
newDef,
|
|
70
|
+
request,
|
|
71
|
+
options: { copy: cutovers.copy, oldTable: cutovers.oldTable, cluster: input.cluster, stamp: input.stamp },
|
|
72
|
+
definitions: input.definitions,
|
|
73
|
+
});
|
|
74
|
+
planned.push(cutover);
|
|
75
|
+
const drop = operations[dropIndex];
|
|
76
|
+
const create = operations[createIndex];
|
|
77
|
+
operations = operations.flatMap((op) => (op === create ? cutover.operations : op === drop ? [] : [op]));
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
plan: { ...input.plan, operations, riskSummary: summarizeRisk(operations) },
|
|
81
|
+
cutovers: planned,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function summarizeCutover(cutover) {
|
|
85
|
+
const { request, options, names } = cutover;
|
|
86
|
+
const target = `${request.database}.${request.table}`;
|
|
87
|
+
const nextSteps = options.copy === 'backfill'
|
|
88
|
+
? [
|
|
89
|
+
'chkit migrate --apply (creates the shadow table and the mirror, then stops at the copy check)',
|
|
90
|
+
`chkit plugin backfill plan --cutover ${target} (then run or submit the plan)`,
|
|
91
|
+
'chkit migrate --apply (verifies the copy and swaps the tables)',
|
|
92
|
+
]
|
|
93
|
+
: ['chkit migrate --apply'];
|
|
94
|
+
return {
|
|
95
|
+
table: target,
|
|
96
|
+
key: request.key,
|
|
97
|
+
copy: options.copy,
|
|
98
|
+
oldTable: options.oldTable,
|
|
99
|
+
shadow: `${request.database}.${names.shadow}`,
|
|
100
|
+
mirror: `${request.database}.${names.mirror}`,
|
|
101
|
+
snapshot: `${request.database}.${names.snapshot}`,
|
|
102
|
+
columns: cutover.columns,
|
|
103
|
+
...(cutover.retained ? { retainedAs: `${request.database}.${names.previous}` } : {}),
|
|
104
|
+
nextSteps,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* A view that reads from or writes into the cutover table and is dropped and
|
|
109
|
+
* recreated by the same migration would miss every INSERT of the cutover: the
|
|
110
|
+
* drop runs before the cutover's first step and the CREATE after its last.
|
|
111
|
+
*/
|
|
112
|
+
function assertNoDependentRecreated(operations, definitions, request) {
|
|
113
|
+
const target = `${request.database}.${request.table}`;
|
|
114
|
+
const table = { database: request.database, name: request.table };
|
|
115
|
+
const dependents = new Set(definitions.flatMap((def) => {
|
|
116
|
+
if (def.kind === 'materialized_view') {
|
|
117
|
+
const writes = def.to.database === request.database && def.to.name === request.table;
|
|
118
|
+
return writes || readsTable(def.as, table, def.database) ? [`materialized_view:${def.database}.${def.name}`] : [];
|
|
119
|
+
}
|
|
120
|
+
if (def.kind === 'view')
|
|
121
|
+
return readsTable(def.as, table, def.database) ? [`view:${def.database}.${def.name}`] : [];
|
|
122
|
+
return [];
|
|
123
|
+
}));
|
|
124
|
+
const recreated = operations.find((op) => (op.type === 'drop_materialized_view' || op.type === 'drop_view') && dependents.has(op.key));
|
|
125
|
+
if (recreated) {
|
|
126
|
+
throw new Error(`--cutover ${target}: ${recreated.key.replace(/^\w+:/, '')} reads from or writes into ${target} and is recreated in the same migration, so it would miss every INSERT during the cutover. Change it in a separate migration, before or after the cutover.`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function findTable(definitions, request) {
|
|
130
|
+
return definitions.find((def) => def.kind === 'table' && def.database === request.database && def.name === request.table);
|
|
131
|
+
}
|
|
132
|
+
function summarizeRisk(operations) {
|
|
133
|
+
const riskSummary = { safe: 0, caution: 0, danger: 0 };
|
|
134
|
+
for (const operation of operations)
|
|
135
|
+
riskSummary[operation.risk] += 1;
|
|
136
|
+
return riskSummary;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=cutover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cutover.js","sourceRoot":"","sources":["../../../src/commands/generate/cutover.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { MigrationPlan, SchemaDefinition } from '@chkit/core';
|
|
2
2
|
import type { TableScope } from '../../runtime/table-scope.js';
|
|
3
|
+
import type { CutoverSummary } from './cutover.js';
|
|
3
4
|
export declare function emitGenerateEmptyOutput(result: {
|
|
4
5
|
migrationFile: string;
|
|
5
6
|
}, jsonMode: boolean): void;
|
|
6
|
-
export declare function emitGeneratePlanOutput(plan: MigrationPlan, jsonMode: boolean, scope: TableScope, warnings?: string[]): void;
|
|
7
|
+
export declare function emitGeneratePlanOutput(plan: MigrationPlan, jsonMode: boolean, scope: TableScope, warnings?: string[], cutovers?: CutoverSummary[]): void;
|
|
7
8
|
export declare function emitGenerateApplyOutput(result: {
|
|
8
9
|
migrationFile: string | null;
|
|
9
10
|
snapshotFile: string;
|
|
10
|
-
}, definitions: SchemaDefinition[], plan: MigrationPlan, jsonMode: boolean, scope: TableScope, warnings?: string[]): void;
|
|
11
|
+
}, definitions: SchemaDefinition[], plan: MigrationPlan, jsonMode: boolean, scope: TableScope, warnings?: string[], cutovers?: CutoverSummary[]): void;
|
|
11
12
|
//# sourceMappingURL=output.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAIlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../../src/commands/generate/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAIlE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AA6BlD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI,CAalG;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,GAAE,MAAM,EAAO,EACvB,QAAQ,GAAE,cAAc,EAAO,GAC9B,IAAI,CAkCN;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE;IAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC9D,WAAW,EAAE,gBAAgB,EAAE,EAC/B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,UAAU,EACjB,QAAQ,GAAE,MAAM,EAAO,EACvB,QAAQ,GAAE,cAAc,EAAO,GAC9B,IAAI,CAoCN"}
|
|
@@ -12,7 +12,7 @@ export function emitGenerateEmptyOutput(result, jsonMode) {
|
|
|
12
12
|
console.log(`Generated empty migration: ${result.migrationFile}`);
|
|
13
13
|
console.log('Snapshot unchanged. Add your SQL to the file, then run "chkit migrate".');
|
|
14
14
|
}
|
|
15
|
-
export function emitGeneratePlanOutput(plan, jsonMode, scope, warnings = []) {
|
|
15
|
+
export function emitGeneratePlanOutput(plan, jsonMode, scope, warnings = [], cutovers = []) {
|
|
16
16
|
const payload = {
|
|
17
17
|
scope,
|
|
18
18
|
mode: 'plan',
|
|
@@ -21,6 +21,7 @@ export function emitGeneratePlanOutput(plan, jsonMode, scope, warnings = []) {
|
|
|
21
21
|
operations: plan.operations,
|
|
22
22
|
renameSuggestions: plan.renameSuggestions,
|
|
23
23
|
warnings,
|
|
24
|
+
...(cutovers.length > 0 ? { cutovers } : {}),
|
|
24
25
|
};
|
|
25
26
|
if (jsonMode) {
|
|
26
27
|
emitJson('generate', payload);
|
|
@@ -32,6 +33,7 @@ export function emitGeneratePlanOutput(plan, jsonMode, scope, warnings = []) {
|
|
|
32
33
|
console.log(`- ${line}`);
|
|
33
34
|
for (const warning of payload.warnings)
|
|
34
35
|
console.warn(`Warning: ${warning}`);
|
|
36
|
+
printCutovers(cutovers);
|
|
35
37
|
if (payload.renameSuggestions.length > 0) {
|
|
36
38
|
console.log('\nRename suggestions (review and confirm manually):');
|
|
37
39
|
for (const suggestion of payload.renameSuggestions) {
|
|
@@ -41,7 +43,7 @@ export function emitGeneratePlanOutput(plan, jsonMode, scope, warnings = []) {
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
export function emitGenerateApplyOutput(result, definitions, plan, jsonMode, scope, warnings = []) {
|
|
46
|
+
export function emitGenerateApplyOutput(result, definitions, plan, jsonMode, scope, warnings = [], cutovers = []) {
|
|
45
47
|
const payload = {
|
|
46
48
|
scope,
|
|
47
49
|
migrationFile: result.migrationFile,
|
|
@@ -50,6 +52,7 @@ export function emitGenerateApplyOutput(result, definitions, plan, jsonMode, sco
|
|
|
50
52
|
operationCount: plan.operations.length,
|
|
51
53
|
riskSummary: plan.riskSummary,
|
|
52
54
|
warnings,
|
|
55
|
+
...(cutovers.length > 0 ? { cutovers } : {}),
|
|
53
56
|
};
|
|
54
57
|
if (jsonMode) {
|
|
55
58
|
emitJson('generate', payload);
|
|
@@ -73,5 +76,17 @@ export function emitGenerateApplyOutput(result, definitions, plan, jsonMode, sco
|
|
|
73
76
|
console.log(`Risk summary: safe=${plan.riskSummary.safe}, caution=${plan.riskSummary.caution}, danger=${plan.riskSummary.danger}`);
|
|
74
77
|
for (const warning of payload.warnings)
|
|
75
78
|
console.warn(`Warning: ${warning}`);
|
|
79
|
+
printCutovers(cutovers);
|
|
80
|
+
}
|
|
81
|
+
function printCutovers(cutovers) {
|
|
82
|
+
for (const cutover of cutovers) {
|
|
83
|
+
console.log(`\nCutover ${cutover.table} (key ${cutover.key.join(', ')}, copy: ${cutover.copy}, old table: ${cutover.oldTable})`);
|
|
84
|
+
console.log(` shadow ${cutover.shadow}, mirror ${cutover.mirror}, snapshot ${cutover.snapshot}`);
|
|
85
|
+
if (cutover.retainedAs)
|
|
86
|
+
console.log(` the old table is kept as ${cutover.retainedAs}`);
|
|
87
|
+
console.log(' Next:');
|
|
88
|
+
for (const step of cutover.nextSteps)
|
|
89
|
+
console.log(` - ${step}`);
|
|
90
|
+
}
|
|
76
91
|
}
|
|
77
92
|
//# sourceMappingURL=output.js.map
|