@intentius/sql-yodeler 0.0.0-stage → 0.1.0
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/LICENSE +202 -0
- package/README.md +110 -2
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +14 -0
- package/dist/bin.js.map +1 -0
- package/dist/chant/apply.d.ts +51 -0
- package/dist/chant/apply.js +104 -0
- package/dist/chant/apply.js.map +1 -0
- package/dist/chant/build.d.ts +34 -0
- package/dist/chant/build.js +48 -0
- package/dist/chant/build.js.map +1 -0
- package/dist/chant/drift.d.ts +44 -0
- package/dist/chant/drift.js +91 -0
- package/dist/chant/drift.js.map +1 -0
- package/dist/chant/plan.d.ts +45 -0
- package/dist/chant/plan.js +61 -0
- package/dist/chant/plan.js.map +1 -0
- package/dist/chant/process.d.ts +41 -0
- package/dist/chant/process.js +87 -0
- package/dist/chant/process.js.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/command.d.ts +17 -0
- package/dist/command.js +13 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/apply.d.ts +3 -0
- package/dist/commands/apply.js +306 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/drift.d.ts +3 -0
- package/dist/commands/drift.js +38 -0
- package/dist/commands/drift.js.map +1 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.js +22 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.js +135 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/lint.d.ts +3 -0
- package/dist/commands/lint.js +193 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/new.d.ts +3 -0
- package/dist/commands/new.js +168 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/plan.d.ts +3 -0
- package/dist/commands/plan.js +171 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/rebase.d.ts +3 -0
- package/dist/commands/rebase.js +167 -0
- package/dist/commands/rebase.js.map +1 -0
- package/dist/commands/repair.d.ts +3 -0
- package/dist/commands/repair.js +117 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +54 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/define.d.ts +50 -0
- package/dist/config/define.js +20 -0
- package/dist/config/define.js.map +1 -0
- package/dist/config/index.d.ts +11 -0
- package/dist/config/index.js +12 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/load.d.ts +17 -0
- package/dist/config/load.js +102 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/settings.d.ts +40 -0
- package/dist/config/settings.js +88 -0
- package/dist/config/settings.js.map +1 -0
- package/dist/env-args.d.ts +18 -0
- package/dist/env-args.js +62 -0
- package/dist/env-args.js.map +1 -0
- package/dist/history/client.d.ts +17 -0
- package/dist/history/client.js +19 -0
- package/dist/history/client.js.map +1 -0
- package/dist/history/ddl.d.ts +58 -0
- package/dist/history/ddl.js +100 -0
- package/dist/history/ddl.js.map +1 -0
- package/dist/history/index.d.ts +25 -0
- package/dist/history/index.js +26 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/lock.d.ts +100 -0
- package/dist/history/lock.js +224 -0
- package/dist/history/lock.js.map +1 -0
- package/dist/history/postgres/ddl.d.ts +22 -0
- package/dist/history/postgres/ddl.js +47 -0
- package/dist/history/postgres/ddl.js.map +1 -0
- package/dist/history/postgres/index.d.ts +12 -0
- package/dist/history/postgres/index.js +13 -0
- package/dist/history/postgres/index.js.map +1 -0
- package/dist/history/postgres/lock.d.ts +48 -0
- package/dist/history/postgres/lock.js +95 -0
- package/dist/history/postgres/lock.js.map +1 -0
- package/dist/history/postgres/store.d.ts +39 -0
- package/dist/history/postgres/store.js +68 -0
- package/dist/history/postgres/store.js.map +1 -0
- package/dist/history/rows.d.ts +96 -0
- package/dist/history/rows.js +73 -0
- package/dist/history/rows.js.map +1 -0
- package/dist/history/store.d.ts +72 -0
- package/dist/history/store.js +134 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/topology.d.ts +41 -0
- package/dist/history/topology.js +54 -0
- package/dist/history/topology.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/init/adopt.d.ts +70 -0
- package/dist/init/adopt.js +138 -0
- package/dist/init/adopt.js.map +1 -0
- package/dist/init/baseline.d.ts +61 -0
- package/dist/init/baseline.js +88 -0
- package/dist/init/baseline.js.map +1 -0
- package/dist/init/files.d.ts +23 -0
- package/dist/init/files.js +77 -0
- package/dist/init/files.js.map +1 -0
- package/dist/init/index.d.ts +16 -0
- package/dist/init/index.js +17 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/live.d.ts +28 -0
- package/dist/init/live.js +45 -0
- package/dist/init/live.js.map +1 -0
- package/dist/lint/check.d.ts +81 -0
- package/dist/lint/check.js +208 -0
- package/dist/lint/check.js.map +1 -0
- package/dist/lint/config.d.ts +21 -0
- package/dist/lint/config.js +43 -0
- package/dist/lint/config.js.map +1 -0
- package/dist/lint/index.d.ts +31 -0
- package/dist/lint/index.js +43 -0
- package/dist/lint/index.js.map +1 -0
- package/dist/lint/project-rules.d.ts +19 -0
- package/dist/lint/project-rules.js +32 -0
- package/dist/lint/project-rules.js.map +1 -0
- package/dist/lint/report.d.ts +7 -0
- package/dist/lint/report.js +48 -0
- package/dist/lint/report.js.map +1 -0
- package/dist/lint/rules.d.ts +53 -0
- package/dist/lint/rules.js +42 -0
- package/dist/lint/rules.js.map +1 -0
- package/dist/lint/silences.d.ts +49 -0
- package/dist/lint/silences.js +91 -0
- package/dist/lint/silences.js.map +1 -0
- package/dist/lint/statements.d.ts +38 -0
- package/dist/lint/statements.js +120 -0
- package/dist/lint/statements.js.map +1 -0
- package/dist/migrations/checksum.d.ts +56 -0
- package/dist/migrations/checksum.js +72 -0
- package/dist/migrations/checksum.js.map +1 -0
- package/dist/migrations/create.d.ts +73 -0
- package/dist/migrations/create.js +119 -0
- package/dist/migrations/create.js.map +1 -0
- package/dist/migrations/directory.d.ts +119 -0
- package/dist/migrations/directory.js +225 -0
- package/dist/migrations/directory.js.map +1 -0
- package/dist/migrations/document.d.ts +83 -0
- package/dist/migrations/document.js +82 -0
- package/dist/migrations/document.js.map +1 -0
- package/dist/migrations/index.d.ts +20 -0
- package/dist/migrations/index.js +21 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/pr/comment.d.ts +32 -0
- package/dist/pr/comment.js +99 -0
- package/dist/pr/comment.js.map +1 -0
- package/dist/pr/forge.d.ts +50 -0
- package/dist/pr/forge.js +105 -0
- package/dist/pr/forge.js.map +1 -0
- package/dist/pr/model.d.ts +91 -0
- package/dist/pr/model.js +113 -0
- package/dist/pr/model.js.map +1 -0
- package/dist/pr/render.d.ts +27 -0
- package/dist/pr/render.js +246 -0
- package/dist/pr/render.js.map +1 -0
- package/dist/project.d.ts +62 -0
- package/dist/project.js +92 -0
- package/dist/project.js.map +1 -0
- package/dist/rebase/index.d.ts +121 -0
- package/dist/rebase/index.js +390 -0
- package/dist/rebase/index.js.map +1 -0
- package/dist/rebase/repair.d.ts +41 -0
- package/dist/rebase/repair.js +68 -0
- package/dist/rebase/repair.js.map +1 -0
- package/dist/replay/clickhouse.d.ts +33 -0
- package/dist/replay/clickhouse.js +106 -0
- package/dist/replay/clickhouse.js.map +1 -0
- package/dist/replay/index.d.ts +36 -0
- package/dist/replay/index.js +54 -0
- package/dist/replay/index.js.map +1 -0
- package/dist/replay/postgres.d.ts +31 -0
- package/dist/replay/postgres.js +140 -0
- package/dist/replay/postgres.js.map +1 -0
- package/dist/replay/replay.d.ts +114 -0
- package/dist/replay/replay.js +98 -0
- package/dist/replay/replay.js.map +1 -0
- package/dist/replay/report.d.ts +18 -0
- package/dist/replay/report.js +72 -0
- package/dist/replay/report.js.map +1 -0
- package/dist/steps/backfill.d.ts +128 -0
- package/dist/steps/backfill.js +307 -0
- package/dist/steps/backfill.js.map +1 -0
- package/dist/steps/index.d.ts +52 -0
- package/dist/steps/index.js +52 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/steps/kinds.d.ts +101 -0
- package/dist/steps/kinds.js +143 -0
- package/dist/steps/kinds.js.map +1 -0
- package/dist/steps/postgres-migration.d.ts +95 -0
- package/dist/steps/postgres-migration.js +149 -0
- package/dist/steps/postgres-migration.js.map +1 -0
- package/dist/steps/rebuild.d.ts +97 -0
- package/dist/steps/rebuild.js +162 -0
- package/dist/steps/rebuild.js.map +1 -0
- package/dist/steps/run.d.ts +45 -0
- package/dist/steps/run.js +72 -0
- package/dist/steps/run.js.map +1 -0
- package/dist/topology/render.d.ts +17 -0
- package/dist/topology/render.js +17 -0
- package/dist/topology/render.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/dist/versioned/approval.d.ts +35 -0
- package/dist/versioned/approval.js +53 -0
- package/dist/versioned/approval.js.map +1 -0
- package/dist/versioned/clickhouse.d.ts +24 -0
- package/dist/versioned/clickhouse.js +34 -0
- package/dist/versioned/clickhouse.js.map +1 -0
- package/dist/versioned/digest.d.ts +77 -0
- package/dist/versioned/digest.js +69 -0
- package/dist/versioned/digest.js.map +1 -0
- package/dist/versioned/driver.d.ts +41 -0
- package/dist/versioned/driver.js +13 -0
- package/dist/versioned/driver.js.map +1 -0
- package/dist/versioned/engine.d.ts +152 -0
- package/dist/versioned/engine.js +277 -0
- package/dist/versioned/engine.js.map +1 -0
- package/dist/versioned/explain.d.ts +123 -0
- package/dist/versioned/explain.js +289 -0
- package/dist/versioned/explain.js.map +1 -0
- package/dist/versioned/index.d.ts +37 -0
- package/dist/versioned/index.js +54 -0
- package/dist/versioned/index.js.map +1 -0
- package/dist/versioned/op.d.ts +62 -0
- package/dist/versioned/op.js +153 -0
- package/dist/versioned/op.js.map +1 -0
- package/dist/versioned/postgres/catalog.d.ts +33 -0
- package/dist/versioned/postgres/catalog.js +34 -0
- package/dist/versioned/postgres/catalog.js.map +1 -0
- package/dist/versioned/postgres/driver.d.ts +69 -0
- package/dist/versioned/postgres/driver.js +113 -0
- package/dist/versioned/postgres/driver.js.map +1 -0
- package/dist/versioned/postgres/executor.d.ts +104 -0
- package/dist/versioned/postgres/executor.js +172 -0
- package/dist/versioned/postgres/executor.js.map +1 -0
- package/dist/versioned/postgres/index.d.ts +11 -0
- package/dist/versioned/postgres/index.js +12 -0
- package/dist/versioned/postgres/index.js.map +1 -0
- package/dist/versioned/report.d.ts +22 -0
- package/dist/versioned/report.js +81 -0
- package/dist/versioned/report.js.map +1 -0
- package/dist/versioned/state.d.ts +108 -0
- package/dist/versioned/state.js +153 -0
- package/dist/versioned/state.js.map +1 -0
- package/package.json +51 -4
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yodel rebase` (#15): move a migration onto another parent, so two
|
|
3
|
+
* branches that each added one can both merge.
|
|
4
|
+
*
|
|
5
|
+
* Two pull requests that each ran `yodel new` from the same newest
|
|
6
|
+
* migration give it two children: a fork, which `readMigrations` refuses.
|
|
7
|
+
* Rebasing moves one of them (the newer, unless named) and every migration
|
|
8
|
+
* that follows it onto the end of the other branch, and rewrites each one's
|
|
9
|
+
* `migration.json` and `migration.sql`:
|
|
10
|
+
*
|
|
11
|
+
* - its change is its recorded schema minus its old parent's recorded
|
|
12
|
+
* schema, object by object (keyed by export name, as chant's diff keys
|
|
13
|
+
* them);
|
|
14
|
+
* - its new recorded schema is the new parent's recorded schema with that
|
|
15
|
+
* change applied: a three-way merge, base the old parent, ours the
|
|
16
|
+
* migration, theirs the new parent. For the usual case, two branches that
|
|
17
|
+
* change different objects, that is the schema the declared build has
|
|
18
|
+
* once both are merged;
|
|
19
|
+
* - its statements are diffed again, from the new parent's recorded schema
|
|
20
|
+
* to the new recorded schema, and its checksum recomputed; a backfill
|
|
21
|
+
* step (#12) is kept at the end, and its module (one of the migration's
|
|
22
|
+
* own files, unchanged) counts in the new checksum;
|
|
23
|
+
* - each `-- yodel:allow <rule> <reason>` line (#14) is carried over to the
|
|
24
|
+
* same step in the new file: the step `migration.json` records exactly as
|
|
25
|
+
* before, found in order. When the step a line silenced is gone from the
|
|
26
|
+
* rebased migration, or is not the same step any more, the rebase refuses
|
|
27
|
+
* and names the line: a reason given for one statement is not moved onto
|
|
28
|
+
* another.
|
|
29
|
+
*
|
|
30
|
+
* When both sides change the same object (by export name, or by the name it
|
|
31
|
+
* has on the server) and do not make the same change, the rebase refuses
|
|
32
|
+
* and names the object: no merge of two changes to one table is safe to
|
|
33
|
+
* guess. The author resolves it by hand: delete the migration and run
|
|
34
|
+
* `yodel new` again on top of the other branch.
|
|
35
|
+
*
|
|
36
|
+
* Ids are kept. The order is the chain of parent ids, never the ids'
|
|
37
|
+
* timestamps, so a rebased migration whose timestamp is older than its new
|
|
38
|
+
* parent's is in order; renaming it would change nothing about when it
|
|
39
|
+
* runs and would break whatever already names it (a review, a branch,
|
|
40
|
+
* another migration's parent).
|
|
41
|
+
*
|
|
42
|
+
* Pure apart from {@link writeRebase}: migrations in, the rewritten ones
|
|
43
|
+
* out.
|
|
44
|
+
*/
|
|
45
|
+
import { renameSync, writeFileSync } from "node:fs";
|
|
46
|
+
import { join } from "node:path";
|
|
47
|
+
import { diffStatements } from "@intentius/chant-lexicon-sql/migration-statements";
|
|
48
|
+
import { YodelError } from "../project.js";
|
|
49
|
+
import { computeChecksum, emptyBuild, MIGRATION_ID, MIGRATION_JSON, MIGRATION_SQL, normalizeLineEndings, renderMigrationSql, serializeDocument, sortKeys, verifyChecksum, } from "../migrations/index.js";
|
|
50
|
+
import { asBackfill } from "../steps/kinds.js";
|
|
51
|
+
import { silencesOf } from "../lint/index.js";
|
|
52
|
+
/** Exit code: the rebase is refused (a conflict, hand edits, a silence it cannot carry over, or a migration a history records). Nothing was written. */
|
|
53
|
+
export const REBASE_REFUSED = 4;
|
|
54
|
+
/** Two sides change one object differently. */
|
|
55
|
+
export class RebaseConflict extends YodelError {
|
|
56
|
+
migration;
|
|
57
|
+
objects;
|
|
58
|
+
constructor(migration, objects, message) {
|
|
59
|
+
super(message, REBASE_REFUSED);
|
|
60
|
+
this.migration = migration;
|
|
61
|
+
this.objects = objects;
|
|
62
|
+
this.name = "RebaseConflict";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const same = (a, b) => JSON.stringify(sortKeys(a) ?? null) === JSON.stringify(sortKeys(b) ?? null);
|
|
66
|
+
/** Sorts migrations oldest first: by the id's timestamp, then `createdAt`, then id. */
|
|
67
|
+
function byAge(a, b) {
|
|
68
|
+
const stamp = (m) => MIGRATION_ID.exec(m.id)?.[1] ?? "";
|
|
69
|
+
return stamp(a).localeCompare(stamp(b)) || (a.document.createdAt ?? "").localeCompare(b.document.createdAt ?? "") || a.id.localeCompare(b.id);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The three-way merge of one migration's change onto a new base: `base1`
|
|
73
|
+
* with every object `ours` changed from `base0` changed the same way.
|
|
74
|
+
* Throws a {@link RebaseConflict} when `base1` (theirs) changed one of
|
|
75
|
+
* those objects too, differently.
|
|
76
|
+
*/
|
|
77
|
+
export function mergeChange(base0, ours, base1, label) {
|
|
78
|
+
if (ours.dialect !== base1.dialect) {
|
|
79
|
+
throw new YodelError(`${label.migration} is ${ours.dialect}, but ${label.theirs} is ${base1.dialect}; a rebase stays in one dialect`);
|
|
80
|
+
}
|
|
81
|
+
const index = (b) => new Map(b.objects.map((o) => [o.export, o]));
|
|
82
|
+
const m0 = index(base0);
|
|
83
|
+
const mo = index(ours);
|
|
84
|
+
const m1 = index(base1);
|
|
85
|
+
const changedFrom = (m) => [...new Set([...m0.keys(), ...m.keys()])].filter((k) => !same(m0.get(k), m.get(k)));
|
|
86
|
+
const ourChanged = changedFrom(mo);
|
|
87
|
+
const theirChanged = new Set(changedFrom(m1));
|
|
88
|
+
const conflicts = new Set(ourChanged.filter((k) => theirChanged.has(k) && !same(mo.get(k), m1.get(k))));
|
|
89
|
+
// The same object under two export names: compare the names the diff gives each side's steps on the server.
|
|
90
|
+
const touched = (to) => {
|
|
91
|
+
try {
|
|
92
|
+
return diffStatements(base0, to).steps;
|
|
93
|
+
}
|
|
94
|
+
catch (e) {
|
|
95
|
+
throw new YodelError(`${label.migration}: ${e instanceof Error ? e.message : String(e)}`);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const theirNames = new Map(touched(base1).map((s) => [s.name, s.object]));
|
|
99
|
+
for (const s of touched(ours)) {
|
|
100
|
+
const theirs = theirNames.get(s.name);
|
|
101
|
+
if (theirs !== undefined && theirs !== s.object)
|
|
102
|
+
conflicts.add(`${s.object} / ${theirs}`);
|
|
103
|
+
}
|
|
104
|
+
const keys = [...new Set([...Object.keys(base0), ...Object.keys(ours)])].filter((k) => k !== "objects");
|
|
105
|
+
for (const k of keys) {
|
|
106
|
+
if (!same(base0[k], ours[k]) && !same(base0[k], base1[k]) && !same(ours[k], base1[k]))
|
|
107
|
+
conflicts.add(`the build's ${k}`);
|
|
108
|
+
}
|
|
109
|
+
if (conflicts.size > 0) {
|
|
110
|
+
const names = [...conflicts];
|
|
111
|
+
throw new RebaseConflict(label.migration, names, `refused: ${label.migration} and ${label.theirs} both change ${names.join(", ")}, differently; rebase does not merge two changes to one object. ` +
|
|
112
|
+
`Nothing was written. Resolve it by hand: delete ${label.migration}'s directory, then run yodel new from a declared schema that makes both changes.`);
|
|
113
|
+
}
|
|
114
|
+
const objects = [...base1.objects];
|
|
115
|
+
for (const k of ourChanged) {
|
|
116
|
+
const o = mo.get(k);
|
|
117
|
+
const at = objects.findIndex((x) => x.export === k);
|
|
118
|
+
if (o === undefined) {
|
|
119
|
+
if (at >= 0)
|
|
120
|
+
objects.splice(at, 1);
|
|
121
|
+
}
|
|
122
|
+
else if (at >= 0)
|
|
123
|
+
objects[at] = o;
|
|
124
|
+
else
|
|
125
|
+
objects.push(o);
|
|
126
|
+
}
|
|
127
|
+
const top = Object.fromEntries([...new Set([...Object.keys(base1), ...keys])]
|
|
128
|
+
.filter((k) => k !== "objects")
|
|
129
|
+
.map((k) => [k, same(base0[k], ours[k]) ? base1[k] : ours[k]])
|
|
130
|
+
.filter(([, v]) => v !== undefined));
|
|
131
|
+
return { ...top, dialect: base1.dialect, objects };
|
|
132
|
+
}
|
|
133
|
+
/** A migration document's steps as chant's `SchemaStatements`, to render them again. */
|
|
134
|
+
export function statementsOf(doc) {
|
|
135
|
+
return {
|
|
136
|
+
dialect: doc.dialect,
|
|
137
|
+
...(doc.defaultDatabase !== undefined ? { defaultDatabase: doc.defaultDatabase } : {}),
|
|
138
|
+
...(doc.defaultSchema !== undefined ? { defaultSchema: doc.defaultSchema } : {}),
|
|
139
|
+
...(doc.major !== undefined ? { major: doc.major } : {}),
|
|
140
|
+
steps: doc.steps,
|
|
141
|
+
refused: doc.refused,
|
|
142
|
+
hints: doc.hints,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Whether a migration's files are what yodel writes for its document: its
|
|
147
|
+
* SQL rendered from its steps, and its checksum matching. Its well-formed
|
|
148
|
+
* `-- yodel:allow` lines do not count as an edit: a rebase carries them
|
|
149
|
+
* over.
|
|
150
|
+
*/
|
|
151
|
+
export function asWritten(m) {
|
|
152
|
+
if (!verifyChecksum(m).ok)
|
|
153
|
+
return false;
|
|
154
|
+
const silenced = new Set(silencesOf(m).map((s) => s.line));
|
|
155
|
+
const sql = normalizeLineEndings(m.files.sql)
|
|
156
|
+
.split("\n")
|
|
157
|
+
.filter((_, i) => !silenced.has(i + 1))
|
|
158
|
+
.join("\n");
|
|
159
|
+
return sql === renderMigrationSql(m.document, statementsOf(m.document));
|
|
160
|
+
}
|
|
161
|
+
/** The text that marks a step in migration.sql, as lint finds it (`src/lint/silences.ts`). */
|
|
162
|
+
function anchorOf(step) {
|
|
163
|
+
return step.kind === "statement" ? `${step.sql};` : `-- ${step.object} (${step.name}):`;
|
|
164
|
+
}
|
|
165
|
+
const stepLabel = (step) => step.kind === "statement" ? `${step.name}: ${step.sql.split("\n")[0] ?? ""}` : `${step.kind === "op" ? step.op : step.kind} for ${step.name}`;
|
|
166
|
+
/**
|
|
167
|
+
* Carries `m`'s `-- yodel:allow` lines over to `sql`, rendered from
|
|
168
|
+
* `steps`: each goes above the step that is the same as the one it was
|
|
169
|
+
* above (the first such step not already matched, in order). Throws a
|
|
170
|
+
* YodelError naming every line whose step is gone or changed.
|
|
171
|
+
*/
|
|
172
|
+
function carrySilences(m, steps, sql) {
|
|
173
|
+
const old = silencesOf(m);
|
|
174
|
+
if (old.length === 0)
|
|
175
|
+
return { sql, silences: [] };
|
|
176
|
+
const oldLines = normalizeLineEndings(m.files.sql).split("\n");
|
|
177
|
+
// Each old step to the same step in the new list, in order.
|
|
178
|
+
const used = new Set();
|
|
179
|
+
const to = new Map();
|
|
180
|
+
m.document.steps.forEach((s, i) => {
|
|
181
|
+
const j = steps.findIndex((n, k) => !used.has(k) && same(n, s));
|
|
182
|
+
if (j >= 0) {
|
|
183
|
+
used.add(j);
|
|
184
|
+
to.set(i, j);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
const lost = old.filter((s) => !to.has(s.step));
|
|
188
|
+
if (lost.length > 0) {
|
|
189
|
+
const why = lost.map((s) => {
|
|
190
|
+
const was = m.document.steps[s.step];
|
|
191
|
+
const now = steps.find((n, k) => !used.has(k) && n.kind === was.kind && n.name === was.name);
|
|
192
|
+
return (` migration.sql line ${String(s.line)}: ${(oldLines[s.line - 1] ?? "").trim()}\n` +
|
|
193
|
+
` it silences step ${String(s.step)} (${stepLabel(was)}), which ${now ? `the rebase changes to ${stepLabel(now)}` : "the rebased migration no longer has"}`);
|
|
194
|
+
});
|
|
195
|
+
throw new YodelError(`refused: ${m.id} has ${lost.length === 1 ? "a yodel:allow line" : "yodel:allow lines"} for a statement the rebase does not keep as it was, so ${lost.length === 1 ? "its reason" : "their reasons"} would no longer be about the statement that runs:\n${why.join("\n")}\n` +
|
|
196
|
+
`Nothing was written. Remove ${lost.length === 1 ? "the line" : "the lines"} from ${m.id}'s migration.sql, record its checksum (yodel lint --update-checksum ${m.id}), rebase, then silence what the rebased statements need again.`, REBASE_REFUSED);
|
|
197
|
+
}
|
|
198
|
+
// Insert each line at the start of the line holding its new step's anchor, finding the anchors the way lint does.
|
|
199
|
+
const wanted = new Map();
|
|
200
|
+
for (const s of old) {
|
|
201
|
+
const j = to.get(s.step);
|
|
202
|
+
wanted.set(j, [...(wanted.get(j) ?? []), (oldLines[s.line - 1] ?? "").replace(/\s+$/, "")]);
|
|
203
|
+
}
|
|
204
|
+
let out = "";
|
|
205
|
+
let cursor = 0;
|
|
206
|
+
steps.forEach((step, j) => {
|
|
207
|
+
const anchor = anchorOf(step);
|
|
208
|
+
const at = sql.indexOf(anchor, cursor);
|
|
209
|
+
const lines = wanted.get(j);
|
|
210
|
+
if (at === -1) {
|
|
211
|
+
if (lines)
|
|
212
|
+
throw new YodelError(`${m.id}: the rebased migration.sql has no place for step ${String(j)} (${stepLabel(step)}), so ${lines.join(", ")} cannot be carried over; nothing was written`, REBASE_REFUSED);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (lines) {
|
|
216
|
+
const lineStart = sql.lastIndexOf("\n", at - 1) + 1;
|
|
217
|
+
const pos = Math.max(lineStart, cursor);
|
|
218
|
+
out += sql.slice(cursor, pos) + (pos === lineStart ? "" : "\n") + lines.map((l) => `${l}\n`).join("") + sql.slice(pos, at);
|
|
219
|
+
}
|
|
220
|
+
else
|
|
221
|
+
out += sql.slice(cursor, at);
|
|
222
|
+
out += anchor;
|
|
223
|
+
cursor = at + anchor.length;
|
|
224
|
+
});
|
|
225
|
+
out += sql.slice(cursor);
|
|
226
|
+
// Read back the way lint and apply read it: the same {rule, reason}s, each on its new step.
|
|
227
|
+
const carried = silencesOf({ files: { sql: out, json: "" }, document: { steps } });
|
|
228
|
+
const key = (s) => `${String(s.step)} ${s.rule} ${s.reason}`;
|
|
229
|
+
const expected = old.map((s) => key({ ...s, step: to.get(s.step) }));
|
|
230
|
+
if (JSON.stringify(carried.map(key)) !== JSON.stringify(expected)) {
|
|
231
|
+
throw new YodelError(`${m.id}: its yodel:allow lines did not read back on the same steps after the rebase; nothing was written. Rebase it by hand.`, REBASE_REFUSED);
|
|
232
|
+
}
|
|
233
|
+
return { sql: out, silences: carried };
|
|
234
|
+
}
|
|
235
|
+
/** Rewrites one migration onto a new parent whose recorded schema is `base1`. */
|
|
236
|
+
function rebaseOne(m, base0, newParent, base1, theirs) {
|
|
237
|
+
if (m.document.topology !== undefined && m.document.topology !== "single") {
|
|
238
|
+
throw new YodelError(`${m.id} was rendered for ClickHouse topology ${m.document.topology}; yodel writes migrations for a single node and renders them per environment when applied, so it cannot rebase one written for a topology`);
|
|
239
|
+
}
|
|
240
|
+
const schema = mergeChange(base0, m.document.schema, base1, { migration: m.id, theirs });
|
|
241
|
+
let statements;
|
|
242
|
+
try {
|
|
243
|
+
statements = diffStatements(base1, schema, {
|
|
244
|
+
...(m.document.defaultDatabase !== undefined ? { defaultDatabase: m.document.defaultDatabase } : {}),
|
|
245
|
+
...(m.document.defaultSchema !== undefined ? { defaultSchema: m.document.defaultSchema } : {}),
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
throw new YodelError(`${m.id}: ${e instanceof Error ? e.message : String(e)}`);
|
|
250
|
+
}
|
|
251
|
+
// A backfill step (#12) is the author's, not the diff's: it keeps its place at the end, with its module.
|
|
252
|
+
const kept = m.document.steps.filter((s) => asBackfill(s) !== undefined);
|
|
253
|
+
if (kept.length > 0)
|
|
254
|
+
statements = { ...statements, refused: true, steps: [...statements.steps, ...kept] };
|
|
255
|
+
if (statements.steps.length === 0) {
|
|
256
|
+
throw new YodelError(`${m.id} makes no change on top of ${newParent}: ${theirs} already makes it. Nothing was written; delete ${m.id}'s directory instead.`, REBASE_REFUSED);
|
|
257
|
+
}
|
|
258
|
+
const dropped = new Set(["defaultDatabase", "defaultSchema", "major", "topology"]);
|
|
259
|
+
const rest = Object.fromEntries(Object.entries(m.document).filter(([k]) => !dropped.has(k)));
|
|
260
|
+
const unsigned = {
|
|
261
|
+
...rest,
|
|
262
|
+
parent: newParent,
|
|
263
|
+
checksum: "",
|
|
264
|
+
dialect: statements.dialect,
|
|
265
|
+
...(statements.defaultDatabase !== undefined ? { defaultDatabase: statements.defaultDatabase } : {}),
|
|
266
|
+
...(statements.defaultSchema !== undefined ? { defaultSchema: statements.defaultSchema } : {}),
|
|
267
|
+
...(statements.major !== undefined ? { major: statements.major } : {}),
|
|
268
|
+
refused: statements.refused,
|
|
269
|
+
hints: statements.hints,
|
|
270
|
+
steps: statements.steps,
|
|
271
|
+
schema,
|
|
272
|
+
};
|
|
273
|
+
const { sql, silences } = carrySilences(m, statements.steps, renderMigrationSql(unsigned, statements));
|
|
274
|
+
const document = { ...unsigned, checksum: computeChecksum({ sql, json: unsigned, extra: m.files.extra }) };
|
|
275
|
+
return {
|
|
276
|
+
id: m.id,
|
|
277
|
+
dir: m.dir,
|
|
278
|
+
oldParent: m.parent,
|
|
279
|
+
parent: newParent,
|
|
280
|
+
oldChecksum: m.checksum,
|
|
281
|
+
checksum: document.checksum,
|
|
282
|
+
document,
|
|
283
|
+
files: { sql, json: serializeDocument(document), ...(m.files.extra ? { extra: m.files.extra } : {}) },
|
|
284
|
+
statements,
|
|
285
|
+
silences,
|
|
286
|
+
handEdited: !asWritten(m),
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* What a rebase would write. `migrations` is every migration in the
|
|
291
|
+
* directory (`scanMigrations(dir).migrations`: a fork is what this is for,
|
|
292
|
+
* so `readMigrations` would refuse it). Throws a YodelError when the
|
|
293
|
+
* migration or its new parent cannot be chosen, and a
|
|
294
|
+
* {@link RebaseConflict} when one rewritten migration's change meets a
|
|
295
|
+
* different change to the same object.
|
|
296
|
+
*/
|
|
297
|
+
export function planRebase(migrations, options = {}) {
|
|
298
|
+
const byId = new Map(migrations.map((m) => [m.id, m]));
|
|
299
|
+
const children = new Map();
|
|
300
|
+
for (const m of migrations)
|
|
301
|
+
children.set(m.parent, [...(children.get(m.parent) ?? []), m]);
|
|
302
|
+
const kids = (id) => [...(children.get(id) ?? [])].sort(byAge);
|
|
303
|
+
const cycle = (id) => new YodelError(`${id} follows itself through its parents (a cycle); fix the parent ids by hand`);
|
|
304
|
+
const get = (id, what) => {
|
|
305
|
+
const m = byId.get(id);
|
|
306
|
+
if (!m)
|
|
307
|
+
throw new YodelError(`${what} ${id} is not in the migrations directory`);
|
|
308
|
+
return m;
|
|
309
|
+
};
|
|
310
|
+
/** The end of the branch that starts at `m`. */
|
|
311
|
+
const tip = (m) => {
|
|
312
|
+
let at = m;
|
|
313
|
+
const seen = new Set();
|
|
314
|
+
for (;;) {
|
|
315
|
+
if (seen.has(at.id))
|
|
316
|
+
throw cycle(at.id);
|
|
317
|
+
seen.add(at.id);
|
|
318
|
+
const next = kids(at.id);
|
|
319
|
+
if (next.length === 0)
|
|
320
|
+
return at;
|
|
321
|
+
if (next.length > 1)
|
|
322
|
+
throw new YodelError(`the branch from ${m.id} forks again at ${at.id} (${next.map((n) => n.id).join(" and ")}); rebase that fork first, or name the new parent with --onto`);
|
|
323
|
+
at = next[0];
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
let moved;
|
|
327
|
+
if (options.id !== undefined)
|
|
328
|
+
moved = get(options.id, "migration");
|
|
329
|
+
else {
|
|
330
|
+
const forks = [...children.entries()].filter(([, list]) => list.length > 1);
|
|
331
|
+
if (forks.length === 0)
|
|
332
|
+
return { moved: undefined };
|
|
333
|
+
if (forks.length > 1) {
|
|
334
|
+
throw new YodelError(`the migrations directory forks in more than one place; name the migration to move:\n${forks.map(([p, list]) => ` ${list.map((l) => l.id).join(" and ")} follow ${p ?? "nothing (each is a first migration)"}`).join("\n")}`);
|
|
335
|
+
}
|
|
336
|
+
moved = (kids(forks[0]?.[0] ?? null).at(-1));
|
|
337
|
+
}
|
|
338
|
+
// The moved migration and every one after it: they move together.
|
|
339
|
+
const chain = [moved];
|
|
340
|
+
for (let next = kids(moved.id); next.length > 0; next = kids(chain.at(-1).id)) {
|
|
341
|
+
if (chain.some((c) => c.id === next[0]?.id))
|
|
342
|
+
throw cycle(moved.id);
|
|
343
|
+
if (next.length > 1)
|
|
344
|
+
throw new YodelError(`${chain.at(-1).id} has two children (${next.map((n) => n.id).join(" and ")}); rebase that fork first`);
|
|
345
|
+
chain.push(next[0]);
|
|
346
|
+
}
|
|
347
|
+
const inChain = new Set(chain.map((m) => m.id));
|
|
348
|
+
let onto;
|
|
349
|
+
if (options.onto !== undefined)
|
|
350
|
+
onto = get(options.onto, "--onto");
|
|
351
|
+
else {
|
|
352
|
+
const siblings = kids(moved.parent).filter((s) => s.id !== moved.id);
|
|
353
|
+
if (siblings.length === 0) {
|
|
354
|
+
throw new YodelError(`${moved.id} is not in a fork (nothing else follows ${moved.parent ?? "nothing"}); name its new parent with --onto <id>`);
|
|
355
|
+
}
|
|
356
|
+
onto = tip(siblings[0]);
|
|
357
|
+
}
|
|
358
|
+
if (inChain.has(onto.id))
|
|
359
|
+
throw new YodelError(`${moved.id} cannot be rebased onto ${onto.id}: ${onto.id === moved.id ? "itself" : "it follows " + moved.id}`);
|
|
360
|
+
if (onto.id === moved.parent)
|
|
361
|
+
throw new YodelError(`${moved.id} already follows ${onto.id}; nothing to rebase`);
|
|
362
|
+
const ontoKids = kids(onto.id);
|
|
363
|
+
if (ontoKids.length > 0) {
|
|
364
|
+
throw new YodelError(`${ontoKids.map((k) => k.id).join(" and ")} already follow${ontoKids.length === 1 ? "s" : ""} ${onto.id}, so rebasing onto it would fork again; rebase onto the end of that branch, ${tip(onto).id}`);
|
|
365
|
+
}
|
|
366
|
+
const schemaOf = (id) => (id === null ? emptyBuild(moved.document.schema) : get(id, "parent").document.schema);
|
|
367
|
+
const rewritten = [];
|
|
368
|
+
const theirs = moved.parent === null ? `the chain ending at ${onto.id}` : `the migrations after ${moved.parent} up to ${onto.id}`;
|
|
369
|
+
for (const m of chain) {
|
|
370
|
+
const prev = rewritten.at(-1);
|
|
371
|
+
const base1 = prev ? prev.document.schema : onto.document.schema;
|
|
372
|
+
rewritten.push(rebaseOne(m, schemaOf(m.parent), prev ? prev.id : onto.id, base1, theirs));
|
|
373
|
+
}
|
|
374
|
+
return { moved: moved.id, from: moved.parent, onto: onto.id, rewritten };
|
|
375
|
+
}
|
|
376
|
+
/** Writes each rewritten migration over its files, each file through a temporary one renamed into place. */
|
|
377
|
+
export function writeRebase(plan) {
|
|
378
|
+
for (const m of plan.rewritten) {
|
|
379
|
+
for (const [name, text] of [
|
|
380
|
+
[MIGRATION_SQL, m.files.sql],
|
|
381
|
+
[MIGRATION_JSON, m.files.json],
|
|
382
|
+
]) {
|
|
383
|
+
const path = join(m.dir, name);
|
|
384
|
+
const tmp = join(m.dir, `.${name}.rebasing`);
|
|
385
|
+
writeFileSync(tmp, text);
|
|
386
|
+
renameSync(tmp, path);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rebase/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yodel repair` (#15): record an intended edit to an applied migration.
|
|
3
|
+
*
|
|
4
|
+
* Apply and status compare every applied migration's checksum in the
|
|
5
|
+
* history with its files' checksum, recomputed, and refuse on a mismatch
|
|
6
|
+
* (`../versioned/state.ts`). The history's state of a migration is its
|
|
7
|
+
* migration row with the highest `seq` (`../history/rows.ts`), so a repair
|
|
8
|
+
* is one more migration row, appended under the apply lock:
|
|
9
|
+
*
|
|
10
|
+
* kind = 'migration', statement_index = -1, statement_sha = ''
|
|
11
|
+
* status = 'succeeded' it stays applied
|
|
12
|
+
* checksum = the files' checksum now
|
|
13
|
+
* parent = the parent its migration.json names now
|
|
14
|
+
* plan_digest = the digest it was applied under, carried over
|
|
15
|
+
* note = the reason, as given
|
|
16
|
+
*
|
|
17
|
+
* Nothing is sent to the server but that row; the edit is not run. The
|
|
18
|
+
* first `succeeded` row still says when the migration was applied, so the
|
|
19
|
+
* order of applied migrations is unchanged.
|
|
20
|
+
*/
|
|
21
|
+
import { type HistoryRow, type HistoryState, type MigrationRecord, type RunContext } from "../history/index.js";
|
|
22
|
+
import { type Migration } from "../migrations/index.js";
|
|
23
|
+
/** Exit code: refused, nothing written (not applied, already matching, or gone from the directory). */
|
|
24
|
+
export declare const REPAIR_REFUSED = 4;
|
|
25
|
+
export interface RepairCheck {
|
|
26
|
+
record: MigrationRecord;
|
|
27
|
+
/** The checksum the history records now. */
|
|
28
|
+
oldChecksum: string;
|
|
29
|
+
/** The checksum of the files now, which the repair records. */
|
|
30
|
+
newChecksum: string;
|
|
31
|
+
}
|
|
32
|
+
/** Whether `m` can be repaired against `state`: applied, and its files hash to something else than the history records. Throws a YodelError naming why not. */
|
|
33
|
+
export declare function checkRepair(m: Migration | undefined, id: string, state: HistoryState, environment: string): RepairCheck;
|
|
34
|
+
/** The history row a repair appends. `seq` is one more than the history's highest, taken under the lock. */
|
|
35
|
+
export declare function repairRow(input: {
|
|
36
|
+
migration: Migration;
|
|
37
|
+
check: RepairCheck;
|
|
38
|
+
reason: string;
|
|
39
|
+
run: RunContext;
|
|
40
|
+
seq: number;
|
|
41
|
+
}): HistoryRow;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `yodel repair` (#15): record an intended edit to an applied migration.
|
|
3
|
+
*
|
|
4
|
+
* Apply and status compare every applied migration's checksum in the
|
|
5
|
+
* history with its files' checksum, recomputed, and refuse on a mismatch
|
|
6
|
+
* (`../versioned/state.ts`). The history's state of a migration is its
|
|
7
|
+
* migration row with the highest `seq` (`../history/rows.ts`), so a repair
|
|
8
|
+
* is one more migration row, appended under the apply lock:
|
|
9
|
+
*
|
|
10
|
+
* kind = 'migration', statement_index = -1, statement_sha = ''
|
|
11
|
+
* status = 'succeeded' it stays applied
|
|
12
|
+
* checksum = the files' checksum now
|
|
13
|
+
* parent = the parent its migration.json names now
|
|
14
|
+
* plan_digest = the digest it was applied under, carried over
|
|
15
|
+
* note = the reason, as given
|
|
16
|
+
*
|
|
17
|
+
* Nothing is sent to the server but that row; the edit is not run. The
|
|
18
|
+
* first `succeeded` row still says when the migration was applied, so the
|
|
19
|
+
* order of applied migrations is unchanged.
|
|
20
|
+
*/
|
|
21
|
+
import { YodelError } from "../project.js";
|
|
22
|
+
import { isApplied, MIGRATION_ROW } from "../history/index.js";
|
|
23
|
+
import { computeChecksum } from "../migrations/index.js";
|
|
24
|
+
/** Exit code: refused, nothing written (not applied, already matching, or gone from the directory). */
|
|
25
|
+
export const REPAIR_REFUSED = 4;
|
|
26
|
+
/** Whether `m` can be repaired against `state`: applied, and its files hash to something else than the history records. Throws a YodelError naming why not. */
|
|
27
|
+
export function checkRepair(m, id, state, environment) {
|
|
28
|
+
const record = state.byId.get(id);
|
|
29
|
+
if (!m) {
|
|
30
|
+
throw new YodelError(record
|
|
31
|
+
? `refused: ${id} is in ${environment}'s history, but the migrations directory no longer has it; restore its directory (repair records an edit to a migration's files, not its removal)`
|
|
32
|
+
: `refused: ${id} is not in the migrations directory`, REPAIR_REFUSED);
|
|
33
|
+
}
|
|
34
|
+
if (!record)
|
|
35
|
+
throw new YodelError(`refused: ${id} has not run in ${environment}: its history has no row for it. Nothing to repair; an edit to a pending migration needs none.`, REPAIR_REFUSED);
|
|
36
|
+
if (!isApplied(record)) {
|
|
37
|
+
throw new YodelError(`refused: ${id} is not applied in ${environment}: it ran part way (its latest row is ${record.status}). ` +
|
|
38
|
+
`A migration that failed part way may be edited before it resumes, as long as the statements that succeeded are unchanged; yodel apply resumes it. Repair is for an applied migration.`, REPAIR_REFUSED);
|
|
39
|
+
}
|
|
40
|
+
const newChecksum = computeChecksum(m.files);
|
|
41
|
+
if (record.checksum === newChecksum) {
|
|
42
|
+
throw new YodelError(`refused: ${id}'s files already hash to the checksum ${environment}'s history records (${newChecksum}); nothing to repair`, REPAIR_REFUSED);
|
|
43
|
+
}
|
|
44
|
+
return { record, oldChecksum: record.checksum, newChecksum };
|
|
45
|
+
}
|
|
46
|
+
/** The history row a repair appends. `seq` is one more than the history's highest, taken under the lock. */
|
|
47
|
+
export function repairRow(input) {
|
|
48
|
+
const reason = input.reason.trim();
|
|
49
|
+
if (reason === "")
|
|
50
|
+
throw new YodelError("a repair needs a reason: --reason \"<why the files changed>\"");
|
|
51
|
+
return {
|
|
52
|
+
seq: input.seq,
|
|
53
|
+
run_id: input.run.runId,
|
|
54
|
+
kind: "migration",
|
|
55
|
+
migration_id: input.migration.id,
|
|
56
|
+
parent: input.migration.parent ?? "",
|
|
57
|
+
checksum: input.check.newChecksum,
|
|
58
|
+
statement_index: MIGRATION_ROW,
|
|
59
|
+
statement_sha: "",
|
|
60
|
+
status: "succeeded",
|
|
61
|
+
error: "",
|
|
62
|
+
applied_by: input.run.appliedBy,
|
|
63
|
+
plan_digest: input.run.planDigest,
|
|
64
|
+
silences: "[]",
|
|
65
|
+
note: reason,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.js","sourceRoot":"","sources":["../../src/rebase/repair.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,aAAa,EAA6E,MAAM,qBAAqB,CAAC;AAC1I,OAAO,EAAE,eAAe,EAAkB,MAAM,wBAAwB,CAAC;AAEzE,uGAAuG;AACvG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAUhC,+JAA+J;AAC/J,MAAM,UAAU,WAAW,CAAC,CAAwB,EAAE,EAAU,EAAE,KAAmB,EAAE,WAAmB;IACxG,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,UAAU,CAClB,MAAM;YACJ,CAAC,CAAC,YAAY,EAAE,UAAU,WAAW,mJAAmJ;YACxL,CAAC,CAAC,YAAY,EAAE,qCAAqC,EACvD,cAAc,CACf,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,YAAY,EAAE,mBAAmB,WAAW,gGAAgG,EAAE,cAAc,CAAC,CAAC;IAChM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,UAAU,CAClB,YAAY,EAAE,sBAAsB,WAAW,wCAAwC,MAAM,CAAC,MAAM,KAAK;YACvG,uLAAuL,EACzL,cAAc,CACf,CAAC;IACJ,CAAC;IACD,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,IAAI,UAAU,CAAC,YAAY,EAAE,yCAAyC,WAAW,uBAAuB,WAAW,sBAAsB,EAAE,cAAc,CAAC,CAAC;IACnK,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;AAC/D,CAAC;AAED,4GAA4G;AAC5G,MAAM,UAAU,SAAS,CAAC,KAAiG;IACzH,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,MAAM,KAAK,EAAE;QAAE,MAAM,IAAI,UAAU,CAAC,+DAA+D,CAAC,CAAC;IACzG,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK;QACvB,IAAI,EAAE,WAAW;QACjB,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE;QAChC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE;QACpC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW;QACjC,eAAe,EAAE,aAAa;QAC9B,aAAa,EAAE,EAAE;QACjB,MAAM,EAAE,WAAW;QACnB,KAAK,EAAE,EAAE;QACT,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS;QAC/B,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,UAAU;QACjC,QAAQ,EAAE,IAAI;QACd,IAAI,EAAE,MAAM;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replaying a ClickHouse history: the server `sql.profiles.<env>` binds (the
|
|
3
|
+
* emulator, `chant emulator up --lexicon sql`), statements sent as
|
|
4
|
+
* `yodel apply` sends them (rendered for the environment's topology, a
|
|
5
|
+
* mutation waited for), rebuild steps run as apply runs them, and each
|
|
6
|
+
* migration's recorded schema compared with what the server then holds, the
|
|
7
|
+
* way `chant sql plan` compares a build with a server (chant's normalizer,
|
|
8
|
+
* then the server's own formatter for expressions the rules leave
|
|
9
|
+
* different).
|
|
10
|
+
*
|
|
11
|
+
* The comparison reads every database the history names, so an object the
|
|
12
|
+
* replay made that the recorded schema leaves out is a difference too, and
|
|
13
|
+
* so is a database a migration should have dropped. chant's working objects
|
|
14
|
+
* (a rebuild's retained `__chant_old` table) are not read, as a plan does
|
|
15
|
+
* not read them.
|
|
16
|
+
*/
|
|
17
|
+
import { type Environment, type Project } from "../project.js";
|
|
18
|
+
import { type ClickHousePort } from "../history/index.js";
|
|
19
|
+
import type { Migration } from "../migrations/index.js";
|
|
20
|
+
import { type StepRunner } from "../steps/index.js";
|
|
21
|
+
import type { ReplayDriver } from "./replay.js";
|
|
22
|
+
export interface ClickHouseReplayOptions {
|
|
23
|
+
processEnv?: NodeJS.ProcessEnv;
|
|
24
|
+
/** The server, in place of an HTTP port to the bound endpoint. */
|
|
25
|
+
port?: ClickHousePort;
|
|
26
|
+
/** Runs a rebuild step. Default: chant's local executor, as apply runs it. */
|
|
27
|
+
runStep?: StepRunner;
|
|
28
|
+
log?: (line: string) => void;
|
|
29
|
+
}
|
|
30
|
+
/** The databases a ClickHouse build output names, with bare names in `defaultDatabase`. */
|
|
31
|
+
export declare function clickhouseDatabases(schema: unknown, defaultDatabase: string): Promise<string[]>;
|
|
32
|
+
/** The replay driver for `env`, a ClickHouse environment, over the history `ordered`. */
|
|
33
|
+
export declare function clickhouseReplay(project: Project, env: Environment, ordered: readonly Migration[], options?: ClickHouseReplayOptions): Promise<ReplayDriver>;
|