@intentius/sql-yodeler 0.2.0 → 0.3.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/README.md +3 -3
- package/dist/chant/build.js +7 -0
- package/dist/chant/build.js.map +1 -1
- package/dist/ci/render.d.ts +289 -0
- package/dist/ci/render.js +688 -0
- package/dist/ci/render.js.map +1 -0
- package/dist/ci/replay.d.ts +17 -0
- package/dist/ci/replay.js +69 -0
- package/dist/ci/replay.js.map +1 -0
- package/dist/commands/apply.d.ts +113 -0
- package/dist/commands/apply.js +228 -21
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/approve.js +44 -0
- package/dist/commands/approve.js.map +1 -1
- package/dist/commands/checkpoint.d.ts +3 -0
- package/dist/commands/checkpoint.js +78 -0
- package/dist/commands/checkpoint.js.map +1 -0
- package/dist/commands/ci.d.ts +3 -0
- package/dist/commands/ci.js +118 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/docs.d.ts +11 -0
- package/dist/commands/docs.js +108 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/drift.d.ts +13 -1
- package/dist/commands/drift.js +18 -2
- package/dist/commands/drift.js.map +1 -1
- package/dist/commands/index.js +10 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.js +11 -3
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/override.js +48 -16
- package/dist/commands/override.js.map +1 -1
- package/dist/commands/plan.js +5 -1
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/report.d.ts +13 -0
- package/dist/commands/report.js +121 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/revert.d.ts +20 -0
- package/dist/commands/revert.js +246 -0
- package/dist/commands/revert.js.map +1 -0
- package/dist/commands/status.js +32 -5
- package/dist/commands/status.js.map +1 -1
- package/dist/config/base.d.ts +69 -0
- package/dist/config/base.js +121 -0
- package/dist/config/base.js.map +1 -0
- package/dist/config/define.d.ts +123 -1
- package/dist/config/define.js +2 -0
- package/dist/config/define.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/load.d.ts +1 -1
- package/dist/config/load.js +90 -5
- package/dist/config/load.js.map +1 -1
- package/dist/config/settings.d.ts +4 -1
- package/dist/config/settings.js +8 -2
- package/dist/config/settings.js.map +1 -1
- package/dist/exit.js +1 -1
- package/dist/exit.js.map +1 -1
- package/dist/history/postgres/ddl.d.ts +18 -0
- package/dist/history/postgres/ddl.js +27 -2
- package/dist/history/postgres/ddl.js.map +1 -1
- package/dist/history/postgres/store.d.ts +2 -0
- package/dist/history/postgres/store.js +7 -1
- package/dist/history/postgres/store.js.map +1 -1
- package/dist/history/rows.d.ts +16 -3
- package/dist/history/rows.js +30 -1
- package/dist/history/rows.js.map +1 -1
- package/dist/history/store.d.ts +2 -0
- package/dist/history/store.js +2 -2
- package/dist/history/store.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lint/check.js +17 -2
- package/dist/lint/check.js.map +1 -1
- package/dist/lint/report.js +1 -1
- package/dist/lint/report.js.map +1 -1
- package/dist/lint/routines.d.ts +26 -0
- package/dist/lint/routines.js +65 -0
- package/dist/lint/routines.js.map +1 -0
- package/dist/lint/rules.d.ts +16 -4
- package/dist/lint/rules.js +9 -4
- package/dist/lint/rules.js.map +1 -1
- package/dist/mcp/tools.d.ts +1 -1
- package/dist/mcp/tools.js +1 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/migrations/checkpoint.d.ts +45 -0
- package/dist/migrations/checkpoint.js +110 -0
- package/dist/migrations/checkpoint.js.map +1 -0
- package/dist/migrations/create.js +2 -0
- package/dist/migrations/create.js.map +1 -1
- package/dist/migrations/document.d.ts +10 -0
- package/dist/migrations/document.js +1 -0
- package/dist/migrations/document.js.map +1 -1
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.js +2 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/routines.d.ts +31 -0
- package/dist/migrations/routines.js +55 -0
- package/dist/migrations/routines.js.map +1 -0
- package/dist/notify/index.d.ts +124 -0
- package/dist/notify/index.js +210 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/verify.d.ts +53 -0
- package/dist/notify/verify.js +71 -0
- package/dist/notify/verify.js.map +1 -0
- package/dist/pr/model.d.ts +3 -0
- package/dist/pr/model.js +16 -2
- package/dist/pr/model.js.map +1 -1
- package/dist/pr/render.js +27 -1
- package/dist/pr/render.js.map +1 -1
- package/dist/project.d.ts +19 -2
- package/dist/project.js +33 -1
- package/dist/project.js.map +1 -1
- package/dist/replay/replay.d.ts +9 -1
- package/dist/replay/replay.js +62 -31
- package/dist/replay/replay.js.map +1 -1
- package/dist/replay/report.js +1 -1
- package/dist/replay/report.js.map +1 -1
- package/dist/report/audit.d.ts +138 -0
- package/dist/report/audit.js +202 -0
- package/dist/report/audit.js.map +1 -0
- package/dist/report/jsonl.d.ts +21 -0
- package/dist/report/jsonl.js +52 -0
- package/dist/report/jsonl.js.map +1 -0
- package/dist/report/model.d.ts +68 -0
- package/dist/report/model.js +127 -0
- package/dist/report/model.js.map +1 -0
- package/dist/report/render.d.ts +18 -0
- package/dist/report/render.js +127 -0
- package/dist/report/render.js.map +1 -0
- package/dist/schema-docs/render.d.ts +49 -0
- package/dist/schema-docs/render.js +359 -0
- package/dist/schema-docs/render.js.map +1 -0
- package/dist/schemas.d.ts +5 -2
- package/dist/schemas.js +5 -2
- package/dist/schemas.js.map +1 -1
- package/dist/sources/ddl.d.ts +53 -0
- package/dist/sources/ddl.js +347 -0
- package/dist/sources/ddl.js.map +1 -0
- package/dist/sources/index.d.ts +69 -0
- package/dist/sources/index.js +170 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/steps/postgres-migration.d.ts +35 -25
- package/dist/steps/postgres-migration.js +42 -29
- package/dist/steps/postgres-migration.js.map +1 -1
- package/dist/tenants/index.d.ts +40 -0
- package/dist/tenants/index.js +122 -0
- package/dist/tenants/index.js.map +1 -0
- package/dist/tenants/target.d.ts +23 -0
- package/dist/tenants/target.js +29 -0
- package/dist/tenants/target.js.map +1 -0
- package/dist/versioned/engine.d.ts +6 -0
- package/dist/versioned/engine.js +12 -2
- package/dist/versioned/engine.js.map +1 -1
- package/dist/versioned/index.d.ts +1 -0
- package/dist/versioned/index.js +1 -0
- package/dist/versioned/index.js.map +1 -1
- package/dist/versioned/op.d.ts +6 -1
- package/dist/versioned/op.js +7 -2
- package/dist/versioned/op.js.map +1 -1
- package/dist/versioned/policy.d.ts +33 -2
- package/dist/versioned/policy.js +59 -8
- package/dist/versioned/policy.js.map +1 -1
- package/dist/versioned/report.js +9 -0
- package/dist/versioned/report.js.map +1 -1
- package/dist/versioned/revert.d.ts +128 -0
- package/dist/versioned/revert.js +251 -0
- package/dist/versioned/revert.js.map +1 -0
- package/dist/versioned/state.d.ts +25 -0
- package/dist/versioned/state.js +36 -3
- package/dist/versioned/state.js.map +1 -1
- package/dist/waves/index.d.ts +179 -0
- package/dist/waves/index.js +268 -0
- package/dist/waves/index.js.map +1 -0
- package/dist/waves/promotion.d.ts +56 -0
- package/dist/waves/promotion.js +108 -0
- package/dist/waves/promotion.js.map +1 -0
- package/dist/waves/record.d.ts +24 -0
- package/dist/waves/record.js +20 -0
- package/dist/waves/record.js.map +1 -0
- package/package.json +11 -7
- package/schemas/apply.schema.json +162 -3
- package/schemas/checkpoint.schema.json +19 -0
- package/schemas/drift.schema.json +26 -1
- package/schemas/event.schema.json +36 -0
- package/schemas/lint.schema.json +4 -0
- package/schemas/plan.schema.json +118 -0
- package/schemas/report.schema.json +114 -0
- package/schemas/revert.schema.json +69 -0
- package/schemas/status.schema.json +64 -3
package/dist/schemas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,qFAAqF;AACrF,MAAM,CAAC,MAAM,WAAW,GAAG,6CAA6C,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC;AAElG,6EAA6E;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEjF,wFAAwF;AACxF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,cAAc,EAAE,YAAY;IAC5B,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,qFAAqF;AACrF,MAAM,CAAC,MAAM,WAAW,GAAG,6CAA6C,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC;AAElG,6EAA6E;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEjF,wFAAwF;AACxF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,KAAK;IACV,UAAU,EAAE,YAAY;IACxB,IAAI,EAAE,MAAM;IACZ,cAAc,EAAE,YAAY;IAC5B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,uHAAuH;AACvH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAU,CAAC;AAInG,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAgB,EAAU,EAAE,CAAC,GAAG,WAAW,GAAG,IAAI,cAAc,CAAC;AAE1F,wCAAwC;AACxC,MAAM,UAAU,UAAU,CAAC,IAAgB;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,UAAU,GAAG,IAAI,cAAc,EAAE,MAAM,CAAC,CAA4B,CAAC;AACzG,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A file of DDL, as an ORM prints it (Prisma's `migrate diff --script`,
|
|
3
|
+
* Drizzle's `generate`, Django's `sqlmigrate`, SQLAlchemy's `CreateTable`),
|
|
4
|
+
* read with the sql lexicon's own parsers and written out as declarations:
|
|
5
|
+
* one TypeScript file of `table`, `index`, `view`, ... templates, the same
|
|
6
|
+
* file `chant import` writes. The build then treats them like any other
|
|
7
|
+
* declaration in `src/`.
|
|
8
|
+
*
|
|
9
|
+
* What is read:
|
|
10
|
+
*
|
|
11
|
+
* - Postgres: `CREATE SCHEMA`, `TABLE`, `INDEX`, `VIEW`, `MATERIALIZED VIEW`,
|
|
12
|
+
* `SEQUENCE`, `TYPE ... AS ENUM`, `DOMAIN`, `EXTENSION` and `COMMENT ON`,
|
|
13
|
+
* each parsed by the lexicon's Postgres parser. `ALTER TABLE <t> ADD
|
|
14
|
+
* [CONSTRAINT <c>] FOREIGN KEY | UNIQUE | PRIMARY KEY | CHECK ...`, the
|
|
15
|
+
* form ORMs print foreign keys in, is folded into `<t>`'s CREATE TABLE as
|
|
16
|
+
* a table constraint. `BEGIN` and `COMMIT` are skipped.
|
|
17
|
+
* - ClickHouse: `CREATE DATABASE`, `TABLE`, `VIEW` and `MATERIALIZED VIEW`,
|
|
18
|
+
* as `chant import <file>.sql` reads them.
|
|
19
|
+
*
|
|
20
|
+
* Any other statement is an error naming it: a statement left out would be
|
|
21
|
+
* a schema yodel does not manage, silently.
|
|
22
|
+
*
|
|
23
|
+
* `schema` (a Postgres schema, a ClickHouse database) qualifies the names
|
|
24
|
+
* the DDL leaves unqualified, as an ORM does when the schema comes from its
|
|
25
|
+
* connection: on Postgres an object's own name, an index's table, a foreign
|
|
26
|
+
* key's table and a column type naming an enum or domain the file creates;
|
|
27
|
+
* on ClickHouse an object's own name.
|
|
28
|
+
*/
|
|
29
|
+
import { type SqlDialect } from "../project.js";
|
|
30
|
+
export interface DdlOptions {
|
|
31
|
+
/** Qualifies unqualified names (a Postgres schema, a ClickHouse database). */
|
|
32
|
+
schema?: string | undefined;
|
|
33
|
+
/** Comment lines at the top of the generated file. */
|
|
34
|
+
header?: string | undefined;
|
|
35
|
+
/** Names the DDL in errors. */
|
|
36
|
+
origin: string;
|
|
37
|
+
}
|
|
38
|
+
/** One object the DDL creates. */
|
|
39
|
+
export interface DdlObject {
|
|
40
|
+
/** The export it is declared as. */
|
|
41
|
+
export: string;
|
|
42
|
+
/** Its entity type, `Postgres::Table`. */
|
|
43
|
+
type: string;
|
|
44
|
+
/** `schema.name` (Postgres), `database.name` (ClickHouse). */
|
|
45
|
+
name: string;
|
|
46
|
+
}
|
|
47
|
+
export interface Declarations {
|
|
48
|
+
/** The TypeScript file's content. */
|
|
49
|
+
content: string;
|
|
50
|
+
objects: DdlObject[];
|
|
51
|
+
}
|
|
52
|
+
/** Turns a file of DDL into declarations. */
|
|
53
|
+
export declare function ddlToDeclarations(dialect: SqlDialect, ddl: string, options: DdlOptions): Promise<Declarations>;
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A file of DDL, as an ORM prints it (Prisma's `migrate diff --script`,
|
|
3
|
+
* Drizzle's `generate`, Django's `sqlmigrate`, SQLAlchemy's `CreateTable`),
|
|
4
|
+
* read with the sql lexicon's own parsers and written out as declarations:
|
|
5
|
+
* one TypeScript file of `table`, `index`, `view`, ... templates, the same
|
|
6
|
+
* file `chant import` writes. The build then treats them like any other
|
|
7
|
+
* declaration in `src/`.
|
|
8
|
+
*
|
|
9
|
+
* What is read:
|
|
10
|
+
*
|
|
11
|
+
* - Postgres: `CREATE SCHEMA`, `TABLE`, `INDEX`, `VIEW`, `MATERIALIZED VIEW`,
|
|
12
|
+
* `SEQUENCE`, `TYPE ... AS ENUM`, `DOMAIN`, `EXTENSION` and `COMMENT ON`,
|
|
13
|
+
* each parsed by the lexicon's Postgres parser. `ALTER TABLE <t> ADD
|
|
14
|
+
* [CONSTRAINT <c>] FOREIGN KEY | UNIQUE | PRIMARY KEY | CHECK ...`, the
|
|
15
|
+
* form ORMs print foreign keys in, is folded into `<t>`'s CREATE TABLE as
|
|
16
|
+
* a table constraint. `BEGIN` and `COMMIT` are skipped.
|
|
17
|
+
* - ClickHouse: `CREATE DATABASE`, `TABLE`, `VIEW` and `MATERIALIZED VIEW`,
|
|
18
|
+
* as `chant import <file>.sql` reads them.
|
|
19
|
+
*
|
|
20
|
+
* Any other statement is an error naming it: a statement left out would be
|
|
21
|
+
* a schema yodel does not manage, silently.
|
|
22
|
+
*
|
|
23
|
+
* `schema` (a Postgres schema, a ClickHouse database) qualifies the names
|
|
24
|
+
* the DDL leaves unqualified, as an ORM does when the schema comes from its
|
|
25
|
+
* connection: on Postgres an object's own name, an index's table, a foreign
|
|
26
|
+
* key's table and a column type naming an enum or domain the file creates;
|
|
27
|
+
* on ClickHouse an object's own name.
|
|
28
|
+
*/
|
|
29
|
+
import { YodelError } from "../project.js";
|
|
30
|
+
const isTrivia = (t) => t.kind === "ws" || t.kind === "comment";
|
|
31
|
+
const isName = (t) => t !== undefined && (t.kind === "ident" || t.kind === "qident");
|
|
32
|
+
const word = (t, ...words) => t !== undefined && t.kind === "ident" && words.includes(t.text.toUpperCase());
|
|
33
|
+
/** A name as SQL text: bare when it is a plain lower-case identifier, else double-quoted. */
|
|
34
|
+
const quoteIdent = (name) => (/^[a-z_][a-z0-9_]*$/.test(name) ? name : `"${name.replace(/"/g, '""')}"`);
|
|
35
|
+
/** The statements of a file, each as its tokens (trivia kept inside, trimmed at the ends), split on top-level `;`. */
|
|
36
|
+
function splitTokens(tokens) {
|
|
37
|
+
const out = [];
|
|
38
|
+
let current = [];
|
|
39
|
+
const flush = () => {
|
|
40
|
+
let from = 0;
|
|
41
|
+
let to = current.length;
|
|
42
|
+
const trivia = (i) => {
|
|
43
|
+
const t = current[i];
|
|
44
|
+
return t !== undefined && isTrivia(t);
|
|
45
|
+
};
|
|
46
|
+
while (from < to && trivia(from))
|
|
47
|
+
from++;
|
|
48
|
+
while (to > from && trivia(to - 1))
|
|
49
|
+
to--;
|
|
50
|
+
if (to > from)
|
|
51
|
+
out.push(current.slice(from, to));
|
|
52
|
+
current = [];
|
|
53
|
+
};
|
|
54
|
+
for (const t of tokens) {
|
|
55
|
+
if (t.kind === "punct" && t.text === ";")
|
|
56
|
+
flush();
|
|
57
|
+
else
|
|
58
|
+
current.push(t);
|
|
59
|
+
}
|
|
60
|
+
flush();
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
const text = (tokens) => tokens.map((t) => t.text).join("");
|
|
64
|
+
const firstLine = (s) => (s.split("\n")[0] ?? "").slice(0, 100);
|
|
65
|
+
/** Turns a file of DDL into declarations. */
|
|
66
|
+
export async function ddlToDeclarations(dialect, ddl, options) {
|
|
67
|
+
const ir = dialect === "postgres" ? await postgresIR(ddl, options) : await clickhouseIR(ddl, options);
|
|
68
|
+
if (ir.resources.length === 0)
|
|
69
|
+
throw new YodelError(`${options.origin}: the DDL creates no objects`);
|
|
70
|
+
const files = dialect === "postgres"
|
|
71
|
+
? new (await import("@intentius/chant-lexicon-sql/postgres/import/generator")).PostgresGenerator(options.header).generate(ir)
|
|
72
|
+
: new (await import("@intentius/chant-lexicon-sql/clickhouse/import/generator")).ClickHouseGenerator(options.header).generate(ir);
|
|
73
|
+
const [file] = files;
|
|
74
|
+
if (!file || files.length !== 1)
|
|
75
|
+
throw new YodelError(`${options.origin}: the lexicon's generator wrote ${String(files.length)} files, expected one`);
|
|
76
|
+
return {
|
|
77
|
+
content: file.content,
|
|
78
|
+
objects: ir.resources.map((r) => {
|
|
79
|
+
const p = r.properties;
|
|
80
|
+
const qualifier = p.schema ?? p.database;
|
|
81
|
+
return { export: r.logicalId, type: r.type, name: qualifier ? `${qualifier}.${p.name}` : p.name };
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// ---------- ClickHouse ----------
|
|
86
|
+
async function clickhouseIR(ddl, options) {
|
|
87
|
+
const { tokenizeText } = await import("@intentius/chant-lexicon-sql/clickhouse/tokens");
|
|
88
|
+
const { parseCreate } = await import("@intentius/chant-lexicon-sql/clickhouse/parser");
|
|
89
|
+
const { describeStatement, objectsToIR } = await import("@intentius/chant-lexicon-sql/clickhouse/import/ir");
|
|
90
|
+
const objects = [];
|
|
91
|
+
const problems = [];
|
|
92
|
+
for (const stmt of splitTokens(tokenizeText(ddl, 0))) {
|
|
93
|
+
let sql = text(stmt);
|
|
94
|
+
if (!/^CREATE\b/i.test(sql)) {
|
|
95
|
+
problems.push(`not a CREATE statement: ${firstLine(sql)}`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const tokens = tokenizeText(sql, 0);
|
|
100
|
+
const node = parseCreate(tokens);
|
|
101
|
+
const name = tokens.slice(node.name.from, node.name.to).filter((t) => !isTrivia(t));
|
|
102
|
+
const [only] = name;
|
|
103
|
+
if (options.schema && node.statement !== "database" && only && name.length === 1) {
|
|
104
|
+
const at = tokens.indexOf(only);
|
|
105
|
+
sql = text(tokens.slice(0, at)) + `${quoteIdent(options.schema)}.` + text(tokens.slice(at));
|
|
106
|
+
}
|
|
107
|
+
objects.push(describeStatement(sql));
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
problems.push(`does not parse (${e instanceof Error ? e.message : String(e)}): ${firstLine(sql)}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (problems.length > 0)
|
|
114
|
+
throw ddlError(options.origin, problems);
|
|
115
|
+
return objectsToIR(objects);
|
|
116
|
+
}
|
|
117
|
+
// ---------- Postgres ----------
|
|
118
|
+
const PG_TYPE = {
|
|
119
|
+
schema: "Postgres::Schema",
|
|
120
|
+
table: "Postgres::Table",
|
|
121
|
+
index: "Postgres::Index",
|
|
122
|
+
view: "Postgres::View",
|
|
123
|
+
sequence: "Postgres::Sequence",
|
|
124
|
+
enum: "Postgres::Enum",
|
|
125
|
+
domain: "Postgres::Domain",
|
|
126
|
+
extension: "Postgres::Extension",
|
|
127
|
+
};
|
|
128
|
+
function ddlError(origin, problems) {
|
|
129
|
+
return new YodelError(`${origin}: ${String(problems.length)} statement(s) yodel cannot read as declarations:\n${problems.map((p) => ` - ${p}`).join("\n")}\n` +
|
|
130
|
+
`A DDL source holds CREATE statements (and, on Postgres, COMMENT ON and ALTER TABLE ... ADD of a table constraint).`);
|
|
131
|
+
}
|
|
132
|
+
async function postgresIR(ddl, options) {
|
|
133
|
+
const { tokenizeText } = await import("@intentius/chant-lexicon-sql/postgres/tokens");
|
|
134
|
+
const { parseStatements, identValue } = await import("@intentius/chant-lexicon-sql/postgres/parser");
|
|
135
|
+
const { objectsToIR } = await import("@intentius/chant-lexicon-sql/postgres/import/ir");
|
|
136
|
+
const problems = [];
|
|
137
|
+
const parsed = [];
|
|
138
|
+
const alters = [];
|
|
139
|
+
for (const stmt of splitTokens(tokenizeText(ddl, 0))) {
|
|
140
|
+
const sig = stmt.filter((t) => !isTrivia(t));
|
|
141
|
+
const sql = text(stmt);
|
|
142
|
+
if (sig.length === 1 && word(sig[0], "BEGIN", "COMMIT"))
|
|
143
|
+
continue;
|
|
144
|
+
if (word(sig[0], "ALTER") && word(sig[1], "TABLE")) {
|
|
145
|
+
const alter = readAlterAdd(stmt, sig, identValue);
|
|
146
|
+
if (alter)
|
|
147
|
+
alters.push({ ...alter, sql });
|
|
148
|
+
else
|
|
149
|
+
problems.push(`an ALTER TABLE other than ADD of a table constraint: ${firstLine(sql)}`);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (!word(sig[0], "CREATE", "COMMENT")) {
|
|
153
|
+
problems.push(`not a CREATE statement: ${firstLine(sql)}`);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const tokens = tokenizeText(sql, 0);
|
|
158
|
+
const nodes = parseStatements(tokens);
|
|
159
|
+
for (const node of nodes)
|
|
160
|
+
parsed.push({ tokens, node });
|
|
161
|
+
}
|
|
162
|
+
catch (e) {
|
|
163
|
+
problems.push(`does not parse (${e instanceof Error ? e.message : String(e)}): ${firstLine(sql)}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (problems.length > 0)
|
|
167
|
+
throw ddlError(options.origin, problems);
|
|
168
|
+
const nameOf = (tokens, n) => n.pieces.length > 0 ? n.pieces : tokens.slice(n.span.from, n.span.to).filter((t) => isName(t)).map((t) => identValue(t));
|
|
169
|
+
const qualify = (pieces) => {
|
|
170
|
+
const name = pieces[pieces.length - 1] ?? "";
|
|
171
|
+
const schema = pieces.length >= 2 ? pieces[pieces.length - 2] : options.schema;
|
|
172
|
+
return schema ? { schema, name } : { name };
|
|
173
|
+
};
|
|
174
|
+
const key = (q) => `${q.schema ?? ""}.${q.name}`;
|
|
175
|
+
// The types the file creates, so a column of one is qualified with the rest.
|
|
176
|
+
const fileTypes = new Set();
|
|
177
|
+
for (const { tokens, node } of parsed) {
|
|
178
|
+
if (node.statement === "enum" || node.statement === "domain") {
|
|
179
|
+
const pieces = nameOf(tokens, node.name);
|
|
180
|
+
const [only] = pieces;
|
|
181
|
+
if (only !== undefined && pieces.length === 1)
|
|
182
|
+
fileTypes.add(only);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const objects = [];
|
|
186
|
+
const byName = new Map();
|
|
187
|
+
for (const { tokens, node } of parsed) {
|
|
188
|
+
const inserts = new Set();
|
|
189
|
+
/** Qualifies an unqualified name in the statement, when `schema` is set. */
|
|
190
|
+
const mark = (n) => {
|
|
191
|
+
if (!n || !options.schema)
|
|
192
|
+
return;
|
|
193
|
+
const names = tokens.slice(n.span.from, n.span.to).filter((t) => !isTrivia(t));
|
|
194
|
+
const [only] = names;
|
|
195
|
+
if (only && names.length === 1 && isName(only))
|
|
196
|
+
inserts.add(tokens.indexOf(only));
|
|
197
|
+
};
|
|
198
|
+
if (node.statement === "comment") {
|
|
199
|
+
const target = qualify(nameOf(tokens, node.objectType === "COLUMN" ? { ...node.target, pieces: nameOf(tokens, node.target).slice(0, -1) } : node.target));
|
|
200
|
+
const owner = byName.get(key(target));
|
|
201
|
+
if (!owner) {
|
|
202
|
+
problems.push(`COMMENT ON ${node.objectType} for an object the file does not create: ${firstLine(text(tokens))}`);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (node.objectType !== "COLUMN" || nameOf(tokens, node.target).length < 3)
|
|
206
|
+
mark(node.target);
|
|
207
|
+
owner.statements.push(rewrite(tokens, inserts, options.schema));
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (node.statement === "policy" || node.statement === "role" || node.statement === "grant" || node.statement === "rowSecurity") {
|
|
211
|
+
problems.push(`access control (a policy, role, grant or row security) is not read from a DDL source: ${firstLine(text(tokens))}`);
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (node.statement === "index") {
|
|
215
|
+
if (!node.name) {
|
|
216
|
+
problems.push(`an index with no name (the declaration needs one): ${firstLine(text(tokens))}`);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
mark(node.table);
|
|
220
|
+
}
|
|
221
|
+
else if (node.statement === "table") {
|
|
222
|
+
for (const c of [...node.columns.flatMap((col) => col.constraints), ...node.constraints])
|
|
223
|
+
mark(c.references?.table);
|
|
224
|
+
if (options.schema) {
|
|
225
|
+
for (const col of node.columns) {
|
|
226
|
+
if (!col.type)
|
|
227
|
+
continue;
|
|
228
|
+
const type = tokens.slice(col.type.from, col.type.to).filter((t) => !isTrivia(t));
|
|
229
|
+
const first = type[0];
|
|
230
|
+
if (first && isName(first) && fileTypes.has(identValue(first)) && !(type[1]?.kind === "punct" && type[1].text === "."))
|
|
231
|
+
inserts.add(tokens.indexOf(first));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
else if (node.statement === "schema" && !node.name) {
|
|
236
|
+
problems.push(`a CREATE SCHEMA with no name: ${firstLine(text(tokens))}`);
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
// An index takes its table's schema: its own name is never qualified.
|
|
240
|
+
if (node.statement !== "schema" && node.statement !== "extension" && node.statement !== "index")
|
|
241
|
+
mark(node.name);
|
|
242
|
+
const pieces = node.name ? nameOf(tokens, node.name) : [];
|
|
243
|
+
const q = node.statement === "schema" || node.statement === "extension" ? { name: pieces[pieces.length - 1] ?? "" } : node.statement === "index" ? qualify([...nameOf(tokens, node.table).slice(0, -1), pieces[pieces.length - 1] ?? ""]) : qualify(pieces);
|
|
244
|
+
const type = node.statement === "view" && node.materialized ? "Postgres::MaterializedView" : (PG_TYPE[node.statement] ?? node.statement);
|
|
245
|
+
const object = { type, ...q, statements: [rewrite(tokens, inserts, options.schema)], constraints: [] };
|
|
246
|
+
objects.push(object);
|
|
247
|
+
if (node.statement !== "index")
|
|
248
|
+
byName.set(key(q), object);
|
|
249
|
+
}
|
|
250
|
+
for (const alter of alters) {
|
|
251
|
+
const table = byName.get(key(qualify(alter.table)));
|
|
252
|
+
if (!table || table.type !== "Postgres::Table") {
|
|
253
|
+
problems.push(`ALTER TABLE of a table the file does not create: ${firstLine(alter.sql)}`);
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
table.constraints.push(await qualifyConstraint(alter.constraint, options.schema));
|
|
257
|
+
}
|
|
258
|
+
if (problems.length > 0)
|
|
259
|
+
throw ddlError(options.origin, problems);
|
|
260
|
+
return objectsToIR(objects.map((o) => {
|
|
261
|
+
const [create = [], ...comments] = o.statements;
|
|
262
|
+
const ddl = [o.constraints.length > 0 ? addConstraints(create, o.constraints) : text(create), ...comments.map((c) => text(c))].join(";\n");
|
|
263
|
+
return { type: o.type, ...(o.schema ? { schema: o.schema } : {}), name: o.name, ddl };
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
/** The statement's tokens with `schema.` inserted before each marked one. */
|
|
267
|
+
function rewrite(tokens, inserts, schema) {
|
|
268
|
+
if (!schema || inserts.size === 0)
|
|
269
|
+
return [...tokens];
|
|
270
|
+
const out = [];
|
|
271
|
+
tokens.forEach((t, i) => {
|
|
272
|
+
if (inserts.has(i))
|
|
273
|
+
out.push({ kind: "ident", text: `${quoteIdent(schema)}.`, part: 0, start: 0, end: 0 });
|
|
274
|
+
out.push(t);
|
|
275
|
+
});
|
|
276
|
+
return out;
|
|
277
|
+
}
|
|
278
|
+
/** `ALTER TABLE [ONLY] [IF EXISTS] <name> ADD <table constraint>`: the table's name pieces and the constraint's text. */
|
|
279
|
+
function readAlterAdd(stmt, sig, identValue) {
|
|
280
|
+
let i = 2;
|
|
281
|
+
if (word(sig[i], "IF") && word(sig[i + 1], "EXISTS"))
|
|
282
|
+
i += 2;
|
|
283
|
+
if (word(sig[i], "ONLY"))
|
|
284
|
+
i++;
|
|
285
|
+
const table = [];
|
|
286
|
+
for (let t = sig[i]; t && isName(t); t = sig[i]) {
|
|
287
|
+
table.push(identValue(t));
|
|
288
|
+
i++;
|
|
289
|
+
const dot = sig[i];
|
|
290
|
+
if (dot?.kind === "punct" && dot.text === ".")
|
|
291
|
+
i++;
|
|
292
|
+
else
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
if (table.length === 0 || !word(sig[i], "ADD"))
|
|
296
|
+
return undefined;
|
|
297
|
+
i++;
|
|
298
|
+
if (!word(sig[i], "CONSTRAINT", "FOREIGN", "UNIQUE", "PRIMARY", "CHECK", "EXCLUDE"))
|
|
299
|
+
return undefined;
|
|
300
|
+
// One constraint: a comma at depth 0 starts another ALTER action, which is not read.
|
|
301
|
+
let depth = 0;
|
|
302
|
+
for (const t of sig.slice(i)) {
|
|
303
|
+
if (t.kind === "punct" && t.text === "(")
|
|
304
|
+
depth++;
|
|
305
|
+
else if (t.kind === "punct" && t.text === ")")
|
|
306
|
+
depth--;
|
|
307
|
+
else if (t.kind === "punct" && t.text === "," && depth === 0)
|
|
308
|
+
return undefined;
|
|
309
|
+
}
|
|
310
|
+
const start = sig[i];
|
|
311
|
+
return start ? { table, constraint: text(stmt.slice(stmt.indexOf(start))) } : undefined;
|
|
312
|
+
}
|
|
313
|
+
/** Qualifies the table a folded FOREIGN KEY references, when it is unqualified. */
|
|
314
|
+
async function qualifyConstraint(constraint, schema) {
|
|
315
|
+
if (!schema)
|
|
316
|
+
return constraint;
|
|
317
|
+
const { tokenizeText } = await import("@intentius/chant-lexicon-sql/postgres/tokens");
|
|
318
|
+
const tokens = tokenizeText(constraint, 0);
|
|
319
|
+
const sig = tokens.map((t, i) => ({ t, i })).filter((x) => !isTrivia(x.t));
|
|
320
|
+
const inserts = new Set();
|
|
321
|
+
sig.forEach((x, k) => {
|
|
322
|
+
const target = sig[k + 1];
|
|
323
|
+
const dot = sig[k + 2]?.t;
|
|
324
|
+
if (word(x.t, "REFERENCES") && target && isName(target.t) && !(dot?.kind === "punct" && dot.text === "."))
|
|
325
|
+
inserts.add(target.i);
|
|
326
|
+
});
|
|
327
|
+
return text(rewrite(tokens, inserts, schema));
|
|
328
|
+
}
|
|
329
|
+
/** A CREATE TABLE with table constraints added at the end of its column list (the `)` matching the first `(`). */
|
|
330
|
+
function addConstraints(create, constraints) {
|
|
331
|
+
let depth = 0;
|
|
332
|
+
const close = create.findIndex((t) => {
|
|
333
|
+
if (t.kind !== "punct")
|
|
334
|
+
return false;
|
|
335
|
+
if (t.text === "(")
|
|
336
|
+
depth++;
|
|
337
|
+
else if (t.text === ")")
|
|
338
|
+
return --depth === 0;
|
|
339
|
+
return false;
|
|
340
|
+
});
|
|
341
|
+
if (close < 0)
|
|
342
|
+
return text(create);
|
|
343
|
+
const before = text(create.slice(0, close)).replace(/\s+$/, "");
|
|
344
|
+
const indent = /\n([ \t]+)\S[^\n]*$/.exec(before)?.[1] ?? " ";
|
|
345
|
+
return `${before}${constraints.map((c) => `,\n${indent}${c}`).join("")}\n${text(create.slice(close))}`;
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=ddl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ddl.js","sourceRoot":"","sources":["../../src/sources/ddl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DDL sources (#67): schema that an ORM defines, read from the DDL it
|
|
3
|
+
* prints, beside the declarations in `src/`.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* // yodel.config.ts
|
|
7
|
+
* export default defineConfig({
|
|
8
|
+
* sources: {
|
|
9
|
+
* prisma: { command: "npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script", schema: "app" },
|
|
10
|
+
* legacy: { file: "db/legacy.sql" },
|
|
11
|
+
* },
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Before each build, yodel runs each source's command (or reads its file)
|
|
16
|
+
* in the project directory and writes the DDL out as declarations in
|
|
17
|
+
* `<sourceDir>/<name>.generated.ts`, the file `chant import` would write.
|
|
18
|
+
* The build, and so plan, new, apply and drift, read it like any other
|
|
19
|
+
* declaration; the ApplyOp's own build finds it there too. Commit it: a
|
|
20
|
+
* build that does not run yodel (chant build, an Op run elsewhere) reads
|
|
21
|
+
* the committed file.
|
|
22
|
+
*
|
|
23
|
+
* Each object has one owner: an object a source creates that `src/` (or
|
|
24
|
+
* another source) also declares is an error, naming both.
|
|
25
|
+
*/
|
|
26
|
+
import type { BuildOutput } from "../chant/build.js";
|
|
27
|
+
import { YodelError, type Project } from "../project.js";
|
|
28
|
+
import { type DdlObject } from "./ddl.js";
|
|
29
|
+
/** One source, in yodel.config.ts `sources.<name>`. */
|
|
30
|
+
export interface DdlSource {
|
|
31
|
+
/** A shell command, run in the project directory, that prints the DDL on stdout. */
|
|
32
|
+
command?: string;
|
|
33
|
+
/** A file of DDL, relative to the project directory. */
|
|
34
|
+
file?: string;
|
|
35
|
+
/**
|
|
36
|
+
* The Postgres schema (ClickHouse database) for the names the DDL leaves
|
|
37
|
+
* unqualified, as an ORM does when the schema comes from its connection.
|
|
38
|
+
*/
|
|
39
|
+
schema?: string;
|
|
40
|
+
}
|
|
41
|
+
/** What one source wrote. */
|
|
42
|
+
export interface SyncedSource {
|
|
43
|
+
name: string;
|
|
44
|
+
/** The generated file, relative to the project directory. */
|
|
45
|
+
path: string;
|
|
46
|
+
objects: DdlObject[];
|
|
47
|
+
}
|
|
48
|
+
/** The generated file a source writes, relative to the project directory. */
|
|
49
|
+
export declare const generatedPath: (project: Project, name: string) => string;
|
|
50
|
+
/** Checks `sources` in yodel.config.ts. */
|
|
51
|
+
export declare function checkSources(value: unknown, where: string): Record<string, DdlSource>;
|
|
52
|
+
/**
|
|
53
|
+
* Writes each source's declarations to its generated file, and returns what
|
|
54
|
+
* each declared. A file whose content is unchanged is not rewritten.
|
|
55
|
+
*/
|
|
56
|
+
export declare function syncSources(project: Project, options?: {
|
|
57
|
+
env?: NodeJS.ProcessEnv;
|
|
58
|
+
}): Promise<SyncedSource[]>;
|
|
59
|
+
/**
|
|
60
|
+
* chant's build refuses two declarations exported under one name. When one
|
|
61
|
+
* of them is a source's, that is an object declared twice: say so, naming
|
|
62
|
+
* the source.
|
|
63
|
+
*/
|
|
64
|
+
export declare function duplicateExport(buildOutput: string, synced: readonly SyncedSource[]): YodelError | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Each object declared once: an object a source creates that another export
|
|
67
|
+
* in the build (in `src/`, or another source) also creates is an error.
|
|
68
|
+
*/
|
|
69
|
+
export declare function checkOwnership(output: BuildOutput, synced: readonly SyncedSource[]): Promise<void>;
|