@intentius/chant-lexicon-sql 0.124.31 → 0.124.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/change-set.js +250 -0
- package/dist/clickhouse/access.js +722 -0
- package/dist/clickhouse/apply/apply.js +243 -0
- package/dist/clickhouse/apply/mutations.js +66 -0
- package/dist/clickhouse/apply/statements.js +545 -0
- package/dist/clickhouse/catalog-types.js +7 -0
- package/dist/clickhouse/container.js +152 -0
- package/dist/clickhouse/engine-syntax.js +159 -0
- package/dist/clickhouse/entities.js +593 -0
- package/dist/clickhouse/expressions.js +107 -0
- package/dist/clickhouse/http.js +55 -0
- package/dist/clickhouse/import/generator.js +192 -0
- package/dist/clickhouse/import/inlined.js +207 -0
- package/dist/clickhouse/import/ir.js +160 -0
- package/dist/clickhouse/import/live-export.js +131 -0
- package/dist/clickhouse/import/parser.js +17 -0
- package/dist/clickhouse/live/bind.js +116 -0
- package/dist/clickhouse/live/catalog.js +223 -0
- package/dist/clickhouse/live/describe-resources.js +91 -0
- package/dist/clickhouse/live/undeclarable.js +59 -0
- package/dist/clickhouse/overlays/codecs.js +57 -0
- package/dist/clickhouse/overlays/engines.js +101 -0
- package/dist/clickhouse/overlays/kinds.js +1 -0
- package/dist/clickhouse/overlays/projections.js +26 -0
- package/dist/clickhouse/overlays/skip-indexes.js +40 -0
- package/dist/clickhouse/overlays/ttl.js +34 -0
- package/dist/clickhouse/overlays/types.js +59 -0
- package/dist/clickhouse/ownership.js +83 -0
- package/dist/clickhouse/parser.js +674 -0
- package/dist/clickhouse/plan/commands.js +159 -0
- package/dist/clickhouse/plan/deep.js +345 -0
- package/dist/clickhouse/plan/diff.js +312 -0
- package/dist/clickhouse/plan/disruption.js +73 -0
- package/dist/clickhouse/plan/normalize.js +545 -0
- package/dist/clickhouse/plan/rebuild-handoff.js +57 -0
- package/dist/clickhouse/plan/report.js +26 -0
- package/dist/clickhouse/plan/rules.js +72 -0
- package/dist/clickhouse/plan/schema.js +67 -0
- package/dist/clickhouse/plan/server-format.js +35 -0
- package/dist/clickhouse/rebuild/backfill.js +265 -0
- package/dist/clickhouse/rebuild/engines.js +146 -0
- package/dist/clickhouse/rebuild/observe.js +260 -0
- package/dist/clickhouse/rebuild/op.js +152 -0
- package/dist/clickhouse/rebuild/partitions.js +65 -0
- package/dist/clickhouse/rebuild/receipts.js +120 -0
- package/dist/clickhouse/rebuild/replicas.js +121 -0
- package/dist/clickhouse/rebuild/shards.js +76 -0
- package/dist/clickhouse/rebuild/steps.js +383 -0
- package/dist/clickhouse/rebuild/verify.js +279 -0
- package/dist/clickhouse/row-types.js +151 -0
- package/dist/clickhouse/testing/fake-server.js +47 -0
- package/dist/clickhouse/testing/roundtrip-schema.js +25 -0
- package/dist/clickhouse/testing/writable-server.js +123 -0
- package/dist/clickhouse/tokens.js +23 -0
- package/dist/clickhouse/topology.js +463 -0
- package/dist/clickhouse/type-syntax.js +73 -0
- package/dist/clickhouse.js +25 -0
- package/dist/codegen/classifier-page.js +93 -0
- package/dist/codegen/clickhouse-module.js +249 -0
- package/dist/codegen/coverage-page.js +70 -0
- package/dist/codegen/docs-cli.js +3 -0
- package/dist/codegen/docs.js +222 -0
- package/dist/codegen/generate-cli.js +13 -0
- package/dist/codegen/generate.js +97 -0
- package/dist/codegen/package.js +28 -0
- package/dist/codegen/postgres-classifier-page.js +95 -0
- package/dist/codegen/postgres-module.js +418 -0
- package/dist/codegen/registry.js +52 -0
- package/dist/composites/audit-log-table.js +35 -0
- package/dist/composites/catalog.js +524 -0
- package/dist/composites/cdc-mirror.js +32 -0
- package/dist/composites/clickhouse.js +6 -0
- package/dist/composites/events-table.js +26 -0
- package/dist/composites/index.js +8 -0
- package/dist/composites/join-table.js +25 -0
- package/dist/composites/postgres.js +6 -0
- package/dist/composites/refreshed-view.js +24 -0
- package/dist/composites/replacing-table.js +28 -0
- package/dist/composites/rollup-view.js +29 -0
- package/dist/composites/sharded-table.js +27 -0
- package/dist/composites/soft-delete-table.js +34 -0
- package/dist/composites/tenant-table.js +26 -0
- package/dist/composites/typed.js +8 -0
- package/dist/config.js +206 -0
- package/dist/core/apply.js +93 -0
- package/dist/core/classifier.js +115 -0
- package/dist/core/container.js +69 -0
- package/dist/core/cursor.js +261 -0
- package/dist/core/diff.js +48 -0
- package/dist/core/entity.js +58 -0
- package/dist/core/find-templates.js +118 -0
- package/dist/core/foreign-tables.js +27 -0
- package/dist/core/handoff.js +32 -0
- package/dist/core/index.js +64 -0
- package/dist/core/interpolation.js +191 -0
- package/dist/core/normalize.js +43 -0
- package/dist/core/ownership.js +119 -0
- package/dist/core/receipts.js +22 -0
- package/dist/core/references.js +61 -0
- package/dist/core/statements.js +42 -0
- package/dist/core/template.js +79 -0
- package/dist/core/testing/http-stub.js +21 -0
- package/dist/core/tokens.js +202 -0
- package/dist/core/typed.js +40 -0
- package/dist/core/undeclarable.js +46 -0
- package/dist/coverage.js +161 -0
- package/dist/detect.js +32 -0
- package/dist/dialects.js +18 -0
- package/dist/files/build-root.js +72 -0
- package/dist/files/clickhouse.js +138 -0
- package/dist/files/common.js +58 -0
- package/dist/files/postgres.js +389 -0
- package/dist/generated/clickhouse-types.js +5 -0
- package/dist/generated/clickhouse.js +4361 -0
- package/dist/generated/postgres-types.js +227 -0
- package/dist/generated/postgres.js +3667 -0
- package/dist/import-generator.js +14 -0
- package/dist/import-parser.js +71 -0
- package/dist/index.js +24 -0
- package/dist/init-templates.js +290 -0
- package/dist/integrity.json +2 -2
- package/dist/lint/audit-catalog.js +31 -0
- package/dist/lint/audit-lineage.js +22 -0
- package/dist/lint/post-synth/audit-entries.js +34 -0
- package/dist/lint/post-synth/clickhouse-helpers.js +79 -0
- package/dist/lint/post-synth/clickhouse-type-check.js +162 -0
- package/dist/lint/post-synth/index.js +112 -0
- package/dist/lint/post-synth/postgres-audit-entries.js +35 -0
- package/dist/lint/post-synth/postgres-helpers.js +65 -0
- package/dist/lint/post-synth/postgres-names.js +507 -0
- package/dist/lint/post-synth/sql-helpers.js +23 -0
- package/dist/lint/post-synth/sql101.js +59 -0
- package/dist/lint/post-synth/sql102.js +34 -0
- package/dist/lint/post-synth/sqlch101.js +34 -0
- package/dist/lint/post-synth/sqlch102.js +23 -0
- package/dist/lint/post-synth/sqlch103.js +45 -0
- package/dist/lint/post-synth/sqlch104.js +41 -0
- package/dist/lint/post-synth/sqlch105.js +36 -0
- package/dist/lint/post-synth/sqlch106.js +27 -0
- package/dist/lint/post-synth/sqlch107.js +39 -0
- package/dist/lint/post-synth/sqlch108.js +28 -0
- package/dist/lint/post-synth/sqlch109.js +21 -0
- package/dist/lint/post-synth/sqlch110.js +31 -0
- package/dist/lint/post-synth/sqlch111.js +41 -0
- package/dist/lint/post-synth/sqlch112.js +28 -0
- package/dist/lint/post-synth/sqlch113.js +19 -0
- package/dist/lint/post-synth/sqlch114.js +26 -0
- package/dist/lint/post-synth/sqlch115.js +30 -0
- package/dist/lint/post-synth/sqlch116.js +22 -0
- package/dist/lint/post-synth/sqlch117.js +26 -0
- package/dist/lint/post-synth/sqlch118.js +27 -0
- package/dist/lint/post-synth/sqlch119.js +32 -0
- package/dist/lint/post-synth/sqlch120.js +20 -0
- package/dist/lint/post-synth/sqlch121.js +11 -0
- package/dist/lint/post-synth/sqlch122.js +11 -0
- package/dist/lint/post-synth/sqlch123.js +10 -0
- package/dist/lint/post-synth/sqlch124.js +21 -0
- package/dist/lint/post-synth/sqlch125.js +55 -0
- package/dist/lint/post-synth/sqlch126.js +62 -0
- package/dist/lint/post-synth/sqlch127.js +132 -0
- package/dist/lint/post-synth/sqlpg101.js +25 -0
- package/dist/lint/post-synth/sqlpg102.js +35 -0
- package/dist/lint/post-synth/sqlpg103.js +23 -0
- package/dist/lint/post-synth/sqlpg104.js +23 -0
- package/dist/lint/post-synth/sqlpg105.js +22 -0
- package/dist/lint/post-synth/sqlpg106.js +22 -0
- package/dist/lint/post-synth/sqlpg107.js +22 -0
- package/dist/lint/post-synth/sqlpg108.js +28 -0
- package/dist/lint/post-synth/sqlpg109.js +39 -0
- package/dist/lint/post-synth/sqlpg110.js +38 -0
- package/dist/lint/post-synth/sqlpg111.js +23 -0
- package/dist/lint/post-synth/sqlpg112.js +25 -0
- package/dist/lint/post-synth/sqlpg113.js +29 -0
- package/dist/lint/post-synth/sqlpg114.js +39 -0
- package/dist/lint/post-synth/sqlpg115.js +48 -0
- package/dist/lint/post-synth/sqlpg116.js +26 -0
- package/dist/lint/post-synth/sqlpg117.js +24 -0
- package/dist/lint/post-synth/sqlpg118.js +22 -0
- package/dist/lint/post-synth/sqlpg119.js +41 -0
- package/dist/lint/post-synth/sqlpg120.js +83 -0
- package/dist/lint/post-synth/sqlpg121.js +33 -0
- package/dist/lint/post-synth/sqlpg122.js +27 -0
- package/dist/lint/post-synth/sqlpg123.js +69 -0
- package/dist/lint/post-synth/sqlpg124.js +50 -0
- package/dist/lint/post-synth/sqlpg125.js +41 -0
- package/dist/lint/post-synth/sqlpg126.js +38 -0
- package/dist/lint/rules/index.js +12 -0
- package/dist/lint/rules/postgres-templates.js +27 -0
- package/dist/lint/rules/sqlch001.js +79 -0
- package/dist/lint/rules/sqlch002.js +124 -0
- package/dist/lint/rules/sqlch003.js +69 -0
- package/dist/lint/rules/sqlch004.js +83 -0
- package/dist/lint/rules/sqlpg001.js +68 -0
- package/dist/lint/rules/sqlpg002.js +69 -0
- package/dist/lint/rules/sqlpg003.js +58 -0
- package/dist/lint/rules/sqlpg004.js +77 -0
- package/dist/lint/rules/sqlpg005.js +86 -0
- package/dist/lint/rules/templates.js +25 -0
- package/dist/lint/rules/typed-names.js +132 -0
- package/dist/live-dialect.js +32 -0
- package/dist/lsp/catalog.js +44 -0
- package/dist/lsp/completions.js +136 -0
- package/dist/lsp/hover.js +115 -0
- package/dist/lsp/postgres-catalog.js +176 -0
- package/dist/lsp/postgres-template.js +171 -0
- package/dist/lsp/postgres.js +266 -0
- package/dist/lsp/refs.js +60 -0
- package/dist/lsp/registry.d.ts.map +1 -1
- package/dist/lsp/registry.js +19 -0
- package/dist/lsp/template.js +143 -0
- package/dist/manifest.json +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +293 -0
- package/dist/mcp/postgres.js +117 -0
- package/dist/migration-statements.js +243 -0
- package/dist/op/activities/clickhouse-apply.js +83 -0
- package/dist/op/activities/clickhouse-emulator.js +53 -0
- package/dist/op/activities/clickhouse-rebuild.js +119 -0
- package/dist/op/activities/index.js +26 -0
- package/dist/op/activities/postgres-apply.js +126 -0
- package/dist/op/activities/postgres-emulator.js +70 -0
- package/dist/op/activities/postgres-migration.js +156 -0
- package/dist/op/activities/sql-exec.js +57 -0
- package/dist/op/activity-contracts.js +103 -0
- package/dist/package-cli.js +14 -0
- package/dist/plugin.js +259 -0
- package/dist/postgres/access/acl.js +344 -0
- package/dist/postgres/access/changes.js +30 -0
- package/dist/postgres/access/import.js +61 -0
- package/dist/postgres/access/live.js +96 -0
- package/dist/postgres/apply/apply.js +557 -0
- package/dist/postgres/apply/statements.js +882 -0
- package/dist/postgres/catalog-types.js +18 -0
- package/dist/postgres/container.js +58 -0
- package/dist/postgres/entities.js +1390 -0
- package/dist/postgres/entity-types.js +28 -0
- package/dist/postgres/import/generator.js +283 -0
- package/dist/postgres/import/ir.js +53 -0
- package/dist/postgres/import/live-export.js +83 -0
- package/dist/postgres/keywords.js +32 -0
- package/dist/postgres/live/bind.js +130 -0
- package/dist/postgres/live/catalog-kinds.js +301 -0
- package/dist/postgres/live/catalog.js +644 -0
- package/dist/postgres/live/client.js +151 -0
- package/dist/postgres/live/describe-resources.js +135 -0
- package/dist/postgres/live/undeclarable.js +111 -0
- package/dist/postgres/migrate/backfill.js +170 -0
- package/dist/postgres/migrate/batches.js +122 -0
- package/dist/postgres/migrate/carry.js +518 -0
- package/dist/postgres/migrate/handoff.js +59 -0
- package/dist/postgres/migrate/names.js +61 -0
- package/dist/postgres/migrate/observe.js +360 -0
- package/dist/postgres/migrate/op.js +178 -0
- package/dist/postgres/migrate/receipts.js +117 -0
- package/dist/postgres/migrate/replication.js +106 -0
- package/dist/postgres/migrate/steps.js +514 -0
- package/dist/postgres/overlays/columns.js +31 -0
- package/dist/postgres/overlays/constraints.js +52 -0
- package/dist/postgres/overlays/extension-objects.js +88 -0
- package/dist/postgres/overlays/indexes.js +25 -0
- package/dist/postgres/overlays/kinds.js +2 -0
- package/dist/postgres/overlays/partitioning.js +23 -0
- package/dist/postgres/overlays/relations.js +25 -0
- package/dist/postgres/overlays/storage.js +65 -0
- package/dist/postgres/overlays/type-ddl.js +36 -0
- package/dist/postgres/overlays/types.js +74 -0
- package/dist/postgres/parser.js +1824 -0
- package/dist/postgres/plan/commands.js +137 -0
- package/dist/postgres/plan/deep.js +324 -0
- package/dist/postgres/plan/diff.js +499 -0
- package/dist/postgres/plan/disruption.js +64 -0
- package/dist/postgres/plan/normalize.js +889 -0
- package/dist/postgres/plan/report.js +21 -0
- package/dist/postgres/plan/rules.js +115 -0
- package/dist/postgres/plan/schema.js +105 -0
- package/dist/postgres/plan/server-normalize.js +166 -0
- package/dist/postgres/providers/aurora.js +44 -0
- package/dist/postgres/providers/azure.js +53 -0
- package/dist/postgres/providers/cloud-sql.js +41 -0
- package/dist/postgres/providers/index.js +73 -0
- package/dist/postgres/providers/neon.js +44 -0
- package/dist/postgres/providers/rds.js +47 -0
- package/dist/postgres/providers/supabase.js +45 -0
- package/dist/postgres/providers/types.js +21 -0
- package/dist/postgres/row-types.js +107 -0
- package/dist/postgres/testing/fake-client.js +34 -0
- package/dist/postgres/testing/migration.js +48 -0
- package/dist/postgres/testing/roundtrip-schema.js +64 -0
- package/dist/postgres/testing/server.js +47 -0
- package/dist/postgres/testing/writable-server.js +160 -0
- package/dist/postgres/tokens.js +41 -0
- package/dist/postgres.js +15 -0
- package/dist/read/clickhouse.js +82 -0
- package/dist/read/objects.js +44 -0
- package/dist/read/postgres.js +104 -0
- package/dist/read.js +52 -0
- package/dist/receipts.js +207 -0
- package/dist/serializer.js +172 -0
- package/dist/skill-defs.js +93 -0
- package/dist/spec/catalog.js +191 -0
- package/dist/spec/fetch.d.ts.map +1 -1
- package/dist/spec/fetch.js +90 -0
- package/dist/spec/pin.js +42 -0
- package/dist/spec/postgres-catalog.js +171 -0
- package/dist/spec/postgres-fetch.js +91 -0
- package/dist/spec/postgres-pin.js +82 -0
- package/dist/sql-files.js +206 -0
- package/dist/sql-types-command.js +97 -0
- package/dist/sql-types.js +323 -0
- package/dist/token-source.js +156 -0
- package/dist/validate-cli.js +5 -0
- package/dist/validate.js +151 -0
- package/dist/workspace-outputs.js +191 -0
- package/package.json +7 -7
- package/src/codegen/package.ts +2 -2
- package/src/lint/rules/typescript-7.test.ts +2 -1
- package/src/lsp/catalog.ts +2 -2
- package/src/lsp/postgres-catalog.ts +2 -2
- package/src/lsp/registry.ts +2 -1
- package/src/mcp/index.ts +4 -2
- package/src/spec/fetch.ts +2 -2
- package/src/spec/postgres-fetch.ts +2 -2
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fake Postgres server for the applier's unit tests (#3280): a client that
|
|
3
|
+
* keeps the objects it was sent `CREATE` for, their comments set by
|
|
4
|
+
* `COMMENT ON`, and drops them on `DROP`, with transactions that roll back;
|
|
5
|
+
* and a catalog reader over what it keeps, standing in for
|
|
6
|
+
* `../live/catalog.ts`. What it was sent is recorded, so a test asserts on
|
|
7
|
+
* the transport.
|
|
8
|
+
*
|
|
9
|
+
* It parses statements with the dialect's own parser, so what it stores reads
|
|
10
|
+
* back as the declaration it came from. It does not model locks, column
|
|
11
|
+
* changes or dependencies: a test that needs those runs against the pinned
|
|
12
|
+
* server (`../../op/activities/postgres-apply.e2e.test.ts`).
|
|
13
|
+
*/
|
|
14
|
+
import { PostgresQueryError } from "../live/client.js";
|
|
15
|
+
import { stripMarker } from "../../core/ownership.js";
|
|
16
|
+
import { tokenizeText } from "../tokens.js";
|
|
17
|
+
import { parseStatements } from "../parser.js";
|
|
18
|
+
import { POSTGRES_ENTITY_TYPES } from "../entity-types.js";
|
|
19
|
+
import { quoteIdent } from "../keywords.js";
|
|
20
|
+
const KIND_WORD = {
|
|
21
|
+
[POSTGRES_ENTITY_TYPES.schema]: "SCHEMA",
|
|
22
|
+
[POSTGRES_ENTITY_TYPES.table]: "TABLE",
|
|
23
|
+
[POSTGRES_ENTITY_TYPES.index]: "INDEX",
|
|
24
|
+
[POSTGRES_ENTITY_TYPES.view]: "VIEW",
|
|
25
|
+
[POSTGRES_ENTITY_TYPES.materializedView]: "MATERIALIZED VIEW",
|
|
26
|
+
[POSTGRES_ENTITY_TYPES.sequence]: "SEQUENCE",
|
|
27
|
+
[POSTGRES_ENTITY_TYPES.enum]: "TYPE",
|
|
28
|
+
[POSTGRES_ENTITY_TYPES.domain]: "DOMAIN",
|
|
29
|
+
[POSTGRES_ENTITY_TYPES.extension]: "EXTENSION",
|
|
30
|
+
};
|
|
31
|
+
const flat = (type) => type === POSTGRES_ENTITY_TYPES.schema || type === POSTGRES_ENTITY_TYPES.extension;
|
|
32
|
+
const qname = (o) => (flat(o.type) || !o.schema ? quoteIdent(o.name) : `${quoteIdent(o.schema)}.${quoteIdent(o.name)}`);
|
|
33
|
+
const split = (n, defaultSchema = "public") => n.pieces.length > 1 ? { schema: n.pieces[0], name: n.pieces[1] } : { schema: defaultSchema, name: n.pieces[0] };
|
|
34
|
+
const unquote = (s) => s.replace(/^'/, "").replace(/'$/, "").replace(/''/g, "'");
|
|
35
|
+
export function writablePostgres(seed = []) {
|
|
36
|
+
let objects = seed.map((o) => ({ ...o }));
|
|
37
|
+
let snapshot;
|
|
38
|
+
const server = {
|
|
39
|
+
objects,
|
|
40
|
+
writes: [],
|
|
41
|
+
deletes: [],
|
|
42
|
+
control: [],
|
|
43
|
+
readLive: async () => server.objects.map((o, i) => {
|
|
44
|
+
const own = o.comment !== undefined ? stripMarker(o.comment) : "";
|
|
45
|
+
return {
|
|
46
|
+
type: o.type,
|
|
47
|
+
...(flat(o.type) ? {} : { schema: o.schema }),
|
|
48
|
+
name: o.name,
|
|
49
|
+
oid: String(16384 + i),
|
|
50
|
+
...(o.comment !== undefined ? { comment: o.comment } : {}),
|
|
51
|
+
...(o.foreign ? { foreign: o.foreign } : {}),
|
|
52
|
+
statement: [o.create, ...(own ? [`COMMENT ON ${KIND_WORD[o.type]} ${qname(o)} IS '${own.replace(/'/g, "''")}'`] : [])].join(";\n"),
|
|
53
|
+
};
|
|
54
|
+
}),
|
|
55
|
+
client: {
|
|
56
|
+
async query(sql) {
|
|
57
|
+
const s = sql.trim();
|
|
58
|
+
if (/^BEGIN$/i.test(s)) {
|
|
59
|
+
server.control.push("BEGIN");
|
|
60
|
+
snapshot = server.objects.map((o) => ({ ...o }));
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
if (/^COMMIT$/i.test(s)) {
|
|
64
|
+
server.control.push("COMMIT");
|
|
65
|
+
snapshot = undefined;
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
if (/^ROLLBACK$/i.test(s)) {
|
|
69
|
+
server.control.push("ROLLBACK");
|
|
70
|
+
if (snapshot)
|
|
71
|
+
server.objects = objects = snapshot;
|
|
72
|
+
snapshot = undefined;
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
if (/^(SET|SELECT|RESET)\b/i.test(s))
|
|
76
|
+
return [];
|
|
77
|
+
if (server.refuse?.test(s))
|
|
78
|
+
throw new PostgresQueryError(`refused: ${s.split("\n")[0]}`, server.refuseCode ?? "XX000");
|
|
79
|
+
server.writes.push(s);
|
|
80
|
+
const drop = /^DROP\s+(MATERIALIZED VIEW|INDEX(?:\s+CONCURRENTLY)?|TABLE|VIEW|SEQUENCE|TYPE|DOMAIN|EXTENSION|SCHEMA)\s+(.+)$/i.exec(s);
|
|
81
|
+
if (drop) {
|
|
82
|
+
server.deletes.push(s);
|
|
83
|
+
const word = drop[1].toUpperCase().replace(/\s+CONCURRENTLY$/, "");
|
|
84
|
+
const at = server.objects.findIndex((o) => KIND_WORD[o.type] === word && qname(o) === drop[2].trim());
|
|
85
|
+
if (at >= 0)
|
|
86
|
+
server.objects.splice(at, 1);
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
let node;
|
|
90
|
+
try {
|
|
91
|
+
node = parseStatements(tokenizeText(s, 0))[0];
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return []; // ALTER and the rest: recorded, not modelled
|
|
95
|
+
}
|
|
96
|
+
if (!node)
|
|
97
|
+
return [];
|
|
98
|
+
if (node.statement === "comment") {
|
|
99
|
+
const c = node;
|
|
100
|
+
const entry = Object.entries(KIND_WORD).find(([, w]) => w === c.objectType.toUpperCase());
|
|
101
|
+
if (!entry)
|
|
102
|
+
return [];
|
|
103
|
+
const type = entry[0];
|
|
104
|
+
const n = flat(type) ? { name: c.target.pieces[0] } : split(c.target);
|
|
105
|
+
const o = server.objects.find((x) => x.type === type && x.name === n.name && (flat(type) || x.schema === n.schema));
|
|
106
|
+
const text = c.text ? unquote(/IS\s+('(?:[^']|'')*')\s*$/i.exec(s)?.[1] ?? "") : undefined;
|
|
107
|
+
if (o) {
|
|
108
|
+
if (text === undefined)
|
|
109
|
+
delete o.comment;
|
|
110
|
+
else
|
|
111
|
+
o.comment = text;
|
|
112
|
+
}
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const add = (type, schema, name) => {
|
|
116
|
+
if (server.objects.some((x) => x.type === type && x.name === name && x.schema === schema)) {
|
|
117
|
+
throw new PostgresQueryError(`relation "${name}" already exists`, "42P07");
|
|
118
|
+
}
|
|
119
|
+
server.objects.push({ type, ...(schema !== undefined ? { schema } : {}), name, create: s.replace(/\bCREATE\s+OR\s+REPLACE\s+/i, "CREATE ") });
|
|
120
|
+
};
|
|
121
|
+
switch (node.statement) {
|
|
122
|
+
case "schema":
|
|
123
|
+
add(POSTGRES_ENTITY_TYPES.schema, undefined, node.name.pieces[0]);
|
|
124
|
+
break;
|
|
125
|
+
case "extension":
|
|
126
|
+
add(POSTGRES_ENTITY_TYPES.extension, undefined, node.name.pieces[0]);
|
|
127
|
+
break;
|
|
128
|
+
case "table":
|
|
129
|
+
case "sequence":
|
|
130
|
+
case "enum":
|
|
131
|
+
case "domain": {
|
|
132
|
+
const n = split(node.name);
|
|
133
|
+
const type = { table: POSTGRES_ENTITY_TYPES.table, sequence: POSTGRES_ENTITY_TYPES.sequence, enum: POSTGRES_ENTITY_TYPES.enum, domain: POSTGRES_ENTITY_TYPES.domain }[node.statement];
|
|
134
|
+
add(type, n.schema, n.name);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case "view": {
|
|
138
|
+
const n = split(node.name);
|
|
139
|
+
const type = node.materialized ? POSTGRES_ENTITY_TYPES.materializedView : POSTGRES_ENTITY_TYPES.view;
|
|
140
|
+
if (node.orReplace) {
|
|
141
|
+
const o = server.objects.find((x) => x.type === type && x.name === n.name && x.schema === n.schema);
|
|
142
|
+
if (o) {
|
|
143
|
+
o.create = s.replace(/\bCREATE\s+OR\s+REPLACE\s+/i, "CREATE ");
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
add(type, n.schema, n.name);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "index":
|
|
151
|
+
add(POSTGRES_ENTITY_TYPES.index, split(node.table).schema, node.name.pieces[0]);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
return [];
|
|
155
|
+
},
|
|
156
|
+
async end() { },
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
return server;
|
|
160
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres's lexical rules over the shared lossless tokenizer
|
|
3
|
+
* (`../core/tokens.ts`, chant #3278), from the Postgres 18 reference,
|
|
4
|
+
* "Lexical Structure":
|
|
5
|
+
*
|
|
6
|
+
* - `"` quotes an identifier; a backtick is an operator character.
|
|
7
|
+
* - A backslash is an ordinary character in `'...'` (standard_conforming_strings
|
|
8
|
+
* is on by default since 9.1) and escapes only in an `E'...'` string. `B'...'`,
|
|
9
|
+
* `X'...'`, `N'...'` and `U&'...'` are strings too, each one token.
|
|
10
|
+
* - `$$...$$` and `$tag$...$tag$` are strings; `$1` is a parameter.
|
|
11
|
+
* - Block comments nest.
|
|
12
|
+
* - `( ) , ; . [ ]` are punctuation; `=` is an operator, so `WITH (a = 1)`
|
|
13
|
+
* reads `=` as an `op` token.
|
|
14
|
+
* - A number never runs into a name: `42`, `3.5`, `.5`, `1e-3`, `0x1F`,
|
|
15
|
+
* `0o17`, `0b101`, `1_000`.
|
|
16
|
+
* - A multi-character operator does not end in `+` or `-` unless it holds
|
|
17
|
+
* one of `~ ! @ # % ^ & | \` ?`, so `fillfactor=-30` reads `=` then `-`.
|
|
18
|
+
*/
|
|
19
|
+
import { tokenize as tokenizeWith, tokenizeText as tokenizeTextWith } from "../core/tokens.js";
|
|
20
|
+
export { isTrivia, SqlSyntaxError, untokenize } from "../core/tokens.js";
|
|
21
|
+
export const POSTGRES_LEXICAL = {
|
|
22
|
+
identQuotes: '"',
|
|
23
|
+
backslashEscapes: false,
|
|
24
|
+
punct: "(),;.[]",
|
|
25
|
+
// The operator characters (sql-syntax-lexical, "Operators"), and `:` for the `::` cast.
|
|
26
|
+
opChars: /[+\-*/<>=~!@#%^&|`?:]/,
|
|
27
|
+
prefixedStrings: true,
|
|
28
|
+
dollarQuotes: true,
|
|
29
|
+
nestedComments: true,
|
|
30
|
+
numbers: "sql",
|
|
31
|
+
unicodeIdentifiers: true,
|
|
32
|
+
operatorsEndWithoutSign: true,
|
|
33
|
+
};
|
|
34
|
+
/** Tokenize one string with Postgres's rules. `part` is the part index recorded on each token and on an error. */
|
|
35
|
+
export function tokenizeText(src, part) {
|
|
36
|
+
return tokenizeTextWith(src, part, POSTGRES_LEXICAL);
|
|
37
|
+
}
|
|
38
|
+
/** Tokenize a template's parts with Postgres's rules, with a `ref` token for each interpolation between them. */
|
|
39
|
+
export function tokenize(parts) {
|
|
40
|
+
return tokenizeWith(parts, POSTGRES_LEXICAL);
|
|
41
|
+
}
|
package/dist/postgres.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@intentius/chant-lexicon-sql/postgres`: the Postgres dialect (#3289).
|
|
3
|
+
*
|
|
4
|
+
* Everything here is spec-true to Postgres, not a database-agnostic model:
|
|
5
|
+
* the statements are Postgres's own DDL, parsed at build time into entities,
|
|
6
|
+
* and the names fold and quote as Postgres folds and quotes them.
|
|
7
|
+
*/
|
|
8
|
+
export { schema, table, index, view, sequence, type, domain, extension, func, procedure, aggregate, trigger, eventTrigger, collation, cast, policy, role, grant, literal, SqlLiteral, SqlTemplateError, PostgresObject, POSTGRES_ENTITY_TYPES, isPostgresObject, isColumnRef, quoteIdent, } from "./postgres/entities.js";
|
|
9
|
+
export { POSTGRES_PROVIDERS, COMMON_REFUSED, providerData, isPostgresProvider, providerAllowsExtension, isProviderOwned, refusedStatement, normalizeStatement, } from "./postgres/providers/index.js";
|
|
10
|
+
export { PostgresMigrationOp, } from "./postgres/migrate/op.js";
|
|
11
|
+
export { POSTGRES_RECEIPTS_TABLE } from "./postgres/migrate/receipts.js";
|
|
12
|
+
export * from "./composites/postgres.js";
|
|
13
|
+
// The build's Postgres objects as typed values, for a project's own
|
|
14
|
+
// `lint.policies` (#3870); also at `@intentius/chant-lexicon-sql/read`.
|
|
15
|
+
export { readPostgres, canonicalPostgresType, } from "./read/postgres.js";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ClickHouse half of the public read API (`../read.ts`): the build's
|
|
3
|
+
* tables, columns, sort keys, skip indexes, engines and views as typed values,
|
|
4
|
+
* built from the serialized output. The lexicon's post-synth checks read the
|
|
5
|
+
* same values (`../lint/post-synth/clickhouse-helpers.ts`).
|
|
6
|
+
*/
|
|
7
|
+
import { relationKey } from "../core/typed.js";
|
|
8
|
+
import { bareName, baseEngineName, isMergeTree, isNullableType, keyElements, typeFamily, unwrapType } from "../clickhouse/expressions.js";
|
|
9
|
+
import { dialectObjects } from "./objects.js";
|
|
10
|
+
function columnInfo(c, sortKey) {
|
|
11
|
+
const inner = /^LowCardinality\s*\(/i.test((c.type ?? "").trim());
|
|
12
|
+
const nullable = c.nullable === true || isNullableType(c.type) || (inner && isNullableType(unwrapLowCardinality(c.type)));
|
|
13
|
+
return {
|
|
14
|
+
...c,
|
|
15
|
+
nullable,
|
|
16
|
+
lowCardinality: inner,
|
|
17
|
+
...(c.type !== undefined ? { baseType: unwrapType(c.type), family: typeFamily(c.type) } : {}),
|
|
18
|
+
inSortKey: sortKey.has(c.name),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function unwrapLowCardinality(type) {
|
|
22
|
+
return type.trim().replace(/^LowCardinality\s*\(([\s\S]*)\)$/i, "$1").trim();
|
|
23
|
+
}
|
|
24
|
+
function build(objects) {
|
|
25
|
+
const tables = objects
|
|
26
|
+
.filter((o) => o.type === "ClickHouse::Table")
|
|
27
|
+
.map((o) => {
|
|
28
|
+
const t = o;
|
|
29
|
+
const sortKey = t.orderBy ? keyElements(t.orderBy) : [];
|
|
30
|
+
const bare = new Set(sortKey.map(bareName).filter((n) => n !== undefined));
|
|
31
|
+
const columns = (t.columns ?? []).map((c) => columnInfo(c, bare));
|
|
32
|
+
return {
|
|
33
|
+
...t,
|
|
34
|
+
qualifiedName: relationKey(t),
|
|
35
|
+
columns,
|
|
36
|
+
...(t.engine ? { engineFamily: baseEngineName(t.engine) } : {}),
|
|
37
|
+
mergeTree: isMergeTree(t.engine),
|
|
38
|
+
sortKey,
|
|
39
|
+
primaryKeyElements: t.primaryKey ? keyElements(t.primaryKey) : sortKey,
|
|
40
|
+
column: (name) => columns.find((c) => c.name === name),
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
const views = objects
|
|
44
|
+
.filter((o) => o.type === "ClickHouse::View" || o.type === "ClickHouse::MaterializedView")
|
|
45
|
+
.map((o) => {
|
|
46
|
+
const v = o;
|
|
47
|
+
const columns = (v.columns ?? []).map((c) => columnInfo(c, new Set()));
|
|
48
|
+
return {
|
|
49
|
+
...v,
|
|
50
|
+
qualifiedName: relationKey(v),
|
|
51
|
+
materialized: v.type === "ClickHouse::MaterializedView",
|
|
52
|
+
columns,
|
|
53
|
+
outputs: columns.length > 0 ? columns.map((c) => c.name) : (v.lineage ?? []).map((e) => e.output),
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
return {
|
|
57
|
+
dialect: "clickhouse",
|
|
58
|
+
tables,
|
|
59
|
+
views,
|
|
60
|
+
objects,
|
|
61
|
+
table: (ref) => tables.find((t) => t.export === ref) ?? tables.find((t) => t.qualifiedName === ref) ?? tables.find((t) => t.name === ref),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const cache = new WeakMap();
|
|
65
|
+
/**
|
|
66
|
+
* What a ClickHouse build declares, read from a post-synth context's `docs`
|
|
67
|
+
* (a `lint.policies` check's `ctx`), or from the serialized output document
|
|
68
|
+
* itself. Empty when the build has no ClickHouse output. The result is cached
|
|
69
|
+
* per context; treat it as read-only.
|
|
70
|
+
*/
|
|
71
|
+
export function readClickHouse(source) {
|
|
72
|
+
if ("objects" in source)
|
|
73
|
+
return build(source.dialect === "clickhouse" ? source.objects : []);
|
|
74
|
+
const key = source.docs;
|
|
75
|
+
const hit = key ? cache.get(key) : undefined;
|
|
76
|
+
if (hit)
|
|
77
|
+
return hit;
|
|
78
|
+
const read = build(dialectObjects(source, "clickhouse"));
|
|
79
|
+
if (key)
|
|
80
|
+
cache.set(key, read);
|
|
81
|
+
return read;
|
|
82
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sql build output as the serializer writes it (`../serializer.ts`): one
|
|
3
|
+
* JSON document per build with `dialect`, `applyOrder` and `objects`, each
|
|
4
|
+
* object its entity's props with the template source dropped, the DDL moved
|
|
5
|
+
* to the end, and every reference to another declared object written as that
|
|
6
|
+
* object's export name.
|
|
7
|
+
*
|
|
8
|
+
* This is the one place that finds those documents in a post-synth context.
|
|
9
|
+
* The public read API (`../read.ts`) and the lexicon's own post-synth checks
|
|
10
|
+
* (`../lint/post-synth/sql-helpers.ts`) both start here.
|
|
11
|
+
*/
|
|
12
|
+
// ── Finding the documents ─────────────────────────────────────────────
|
|
13
|
+
/** True for a value shaped like the serializer's document. */
|
|
14
|
+
export function isSqlOutputDocument(value) {
|
|
15
|
+
const v = value;
|
|
16
|
+
return v !== null && typeof v === "object" && (v.dialect === "clickhouse" || v.dialect === "postgres") && Array.isArray(v.objects);
|
|
17
|
+
}
|
|
18
|
+
/** Every sql output document in the context, in output order. */
|
|
19
|
+
export function sqlDocuments(source) {
|
|
20
|
+
const out = [];
|
|
21
|
+
for (const doc of source.docs ?? []) {
|
|
22
|
+
if (doc.error || doc.lexicon !== "sql" || doc.format !== "json")
|
|
23
|
+
continue;
|
|
24
|
+
if (isSqlOutputDocument(doc.value))
|
|
25
|
+
out.push(doc.value);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/** Every serialized object of one dialect, across the context's sql documents. */
|
|
30
|
+
export function dialectObjects(source, dialect) {
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const doc of sqlDocuments(source))
|
|
33
|
+
if (doc.dialect === dialect)
|
|
34
|
+
out.push(...doc.objects);
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
/** The Postgres major the build output records, else `fallback`. */
|
|
38
|
+
export function recordedPostgresMajor(source, fallback) {
|
|
39
|
+
for (const doc of sqlDocuments(source)) {
|
|
40
|
+
if (doc.dialect === "postgres" && typeof doc.postgresMajor === "number")
|
|
41
|
+
return doc.postgresMajor;
|
|
42
|
+
}
|
|
43
|
+
return fallback;
|
|
44
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Postgres half of the public read API (`../read.ts`): the build's
|
|
3
|
+
* tables, columns, keys, indexes and views as typed values, built from the
|
|
4
|
+
* serialized output. The lexicon's post-synth checks read the same values
|
|
5
|
+
* (`../lint/post-synth/postgres-helpers.ts`).
|
|
6
|
+
*/
|
|
7
|
+
import { POSTGRES_MAJORS } from "../generated/postgres.js";
|
|
8
|
+
import { relationKey } from "../core/typed.js";
|
|
9
|
+
import { parseType, projectFromObjects, resolveType, typeLabel } from "../lint/post-synth/postgres-names.js";
|
|
10
|
+
import { dialectObjects, recordedPostgresMajor, } from "./objects.js";
|
|
11
|
+
const PINNED_MAJOR = POSTGRES_MAJORS[POSTGRES_MAJORS.length - 1];
|
|
12
|
+
/** A column type's canonical name, array-ness and serial-ness against a project. */
|
|
13
|
+
function typeOf(p, text) {
|
|
14
|
+
const t = parseType(text);
|
|
15
|
+
if (!t)
|
|
16
|
+
return { ...(text ? { typeName: text.trim().toLowerCase() } : {}), array: false, serial: false };
|
|
17
|
+
const r = resolveType(p, t, { serial: true });
|
|
18
|
+
const typeName = r.kind === "builtin" || r.kind === "absent" ? r.canonical : r.kind === "declared" ? String(r.object.sqlName ?? r.object.name) : typeLabel(t);
|
|
19
|
+
return { typeName, array: t.array, serial: r.kind === "builtin" && r.serial === true };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The canonical name of a Postgres type as written: `timestamptz` and
|
|
23
|
+
* `TIMESTAMP WITH TIME ZONE` are both `timestamp with time zone`, `int4` is
|
|
24
|
+
* `integer`. Compare a column's {@link PostgresColumnInfo.typeName} with it,
|
|
25
|
+
* so a rule does not depend on how the DDL spelled the type.
|
|
26
|
+
*/
|
|
27
|
+
export function canonicalPostgresType(text) {
|
|
28
|
+
return typeOf(projectFromObjects([], PINNED_MAJOR), text).typeName;
|
|
29
|
+
}
|
|
30
|
+
function columnInfo(p, c, pk) {
|
|
31
|
+
const { typeName, array, serial } = typeOf(p, c.type);
|
|
32
|
+
const inPrimaryKey = pk.has(c.name);
|
|
33
|
+
const nullable = !(c.notNull === true || inPrimaryKey || c.generated?.kind === "identity" || serial);
|
|
34
|
+
return { ...c, nullable, ...(typeName !== undefined ? { typeName } : {}), array, inPrimaryKey };
|
|
35
|
+
}
|
|
36
|
+
function indexInfo(i) {
|
|
37
|
+
const columns = [];
|
|
38
|
+
for (const e of i.elements ?? []) {
|
|
39
|
+
if (!e.column)
|
|
40
|
+
break;
|
|
41
|
+
columns.push(e.column);
|
|
42
|
+
}
|
|
43
|
+
return { ...i, columns };
|
|
44
|
+
}
|
|
45
|
+
function build(objects, major) {
|
|
46
|
+
const p = projectFromObjects(objects, major);
|
|
47
|
+
const indexes = objects.filter((o) => o.type === "Postgres::Index").map((o) => indexInfo(o));
|
|
48
|
+
const tables = objects
|
|
49
|
+
.filter((o) => o.type === "Postgres::Table")
|
|
50
|
+
.map((o) => {
|
|
51
|
+
const t = o;
|
|
52
|
+
const pk = new Set(t.primaryKey?.columns ?? []);
|
|
53
|
+
const columns = (t.columns ?? []).map((c) => columnInfo(p, c, pk));
|
|
54
|
+
return {
|
|
55
|
+
...t,
|
|
56
|
+
qualifiedName: relationKey(t),
|
|
57
|
+
columns,
|
|
58
|
+
indexes: indexes.filter((i) => i.table === t.export || i.tableName === t.sqlName),
|
|
59
|
+
column: (name) => columns.find((c) => c.name === name),
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
const views = objects
|
|
63
|
+
.filter((o) => o.type === "Postgres::View" || o.type === "Postgres::MaterializedView")
|
|
64
|
+
.map((o) => {
|
|
65
|
+
const v = o;
|
|
66
|
+
const declared = v.columns ?? [];
|
|
67
|
+
return {
|
|
68
|
+
...v,
|
|
69
|
+
qualifiedName: relationKey(v),
|
|
70
|
+
materialized: v.type === "Postgres::MaterializedView",
|
|
71
|
+
outputs: declared.length > 0 ? [...declared] : (v.lineage ?? []).map((e) => e.output),
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
dialect: "postgres",
|
|
76
|
+
major,
|
|
77
|
+
tables,
|
|
78
|
+
views,
|
|
79
|
+
indexes,
|
|
80
|
+
objects,
|
|
81
|
+
table: (ref) => tables.find((t) => t.export === ref) ?? tables.find((t) => t.qualifiedName === ref) ?? tables.find((t) => t.name === ref),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const cache = new WeakMap();
|
|
85
|
+
/**
|
|
86
|
+
* What a Postgres build declares, read from a post-synth context's `docs`
|
|
87
|
+
* (a `lint.policies` check's `ctx`), or from the serialized output document
|
|
88
|
+
* itself. Empty when the build has no Postgres output. The result is cached
|
|
89
|
+
* per context; treat it as read-only.
|
|
90
|
+
*/
|
|
91
|
+
export function readPostgres(source) {
|
|
92
|
+
if ("objects" in source) {
|
|
93
|
+
const objects = source.dialect === "postgres" ? source.objects : [];
|
|
94
|
+
return build(objects, typeof source.postgresMajor === "number" ? source.postgresMajor : PINNED_MAJOR);
|
|
95
|
+
}
|
|
96
|
+
const key = source.docs;
|
|
97
|
+
const hit = key ? cache.get(key) : undefined;
|
|
98
|
+
if (hit)
|
|
99
|
+
return hit;
|
|
100
|
+
const read = build(dialectObjects(source, "postgres"), recordedPostgresMajor(source, PINNED_MAJOR));
|
|
101
|
+
if (key)
|
|
102
|
+
cache.set(key, read);
|
|
103
|
+
return read;
|
|
104
|
+
}
|
package/dist/read.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@intentius/chant-lexicon-sql/read`: a typed, read-only view of the SQL
|
|
3
|
+
* objects a build declares (#3870), for a project's own `lint.policies`.
|
|
4
|
+
*
|
|
5
|
+
* A policy's `check(ctx)` gets the build's parsed output in `ctx.docs`.
|
|
6
|
+
* {@link readPostgres} and {@link readClickHouse} turn the sql lexicon's part
|
|
7
|
+
* of it into tables with typed columns (SQL type, nullability, default,
|
|
8
|
+
* comment), keys, indexes and engines, and views with their outputs and
|
|
9
|
+
* column lineage. The lexicon's own post-synth checks read the same values,
|
|
10
|
+
* so a project rule sees exactly what `SQLPG101` or `SQLCH113` sees.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import type { PostSynthCheck } from "@intentius/chant/lint/post-synth";
|
|
14
|
+
* import { canonicalPostgresType, readPostgres } from "@intentius/chant-lexicon-sql/read";
|
|
15
|
+
*
|
|
16
|
+
* const TIMESTAMPTZ = canonicalPostgresType("timestamptz");
|
|
17
|
+
*
|
|
18
|
+
* export const createdAt: PostSynthCheck = {
|
|
19
|
+
* id: "ORG-CREATED-AT",
|
|
20
|
+
* description: "every table has created_at timestamptz NOT NULL",
|
|
21
|
+
* check(ctx) {
|
|
22
|
+
* return readPostgres(ctx).tables
|
|
23
|
+
* .filter((t) => { const c = t.column("created_at"); return !c || c.typeName !== TIMESTAMPTZ || c.nullable; })
|
|
24
|
+
* .map((t) => ({ checkId: "ORG-CREATED-AT", severity: "error", entity: t.export,
|
|
25
|
+
* message: `${t.qualifiedName} needs created_at timestamptz NOT NULL` }));
|
|
26
|
+
* },
|
|
27
|
+
* };
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Every value keeps the fields the serializer writes (see the Serialization
|
|
31
|
+
* page) and adds the derived ones documented on each type. The reads also take
|
|
32
|
+
* the serialized document itself (`{ dialect, objects }`), for a tool that
|
|
33
|
+
* holds a recorded build rather than a post-synth context.
|
|
34
|
+
*/
|
|
35
|
+
export { readPostgres, canonicalPostgresType } from "./read/postgres.js";
|
|
36
|
+
export { readClickHouse } from "./read/clickhouse.js";
|
|
37
|
+
export { sqlDocuments, isSqlOutputDocument } from "./read/objects.js";
|
|
38
|
+
import { readClickHouse } from "./read/clickhouse.js";
|
|
39
|
+
import { readPostgres } from "./read/postgres.js";
|
|
40
|
+
import { sqlDocuments } from "./read/objects.js";
|
|
41
|
+
/**
|
|
42
|
+
* The build's SQL objects in whichever dialect it declares: one build holds
|
|
43
|
+
* one dialect. Undefined when the build has no sql output.
|
|
44
|
+
*/
|
|
45
|
+
export function readSql(source) {
|
|
46
|
+
const dialect = "objects" in source ? source.dialect : sqlDocuments(source)[0]?.dialect;
|
|
47
|
+
if (dialect === "postgres")
|
|
48
|
+
return readPostgres(source);
|
|
49
|
+
if (dialect === "clickhouse")
|
|
50
|
+
return readClickHouse(source);
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|