@intentius/chant-lexicon-sql 0.124.12 → 0.124.13
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/clickhouse/apply/statements.d.ts.map +1 -1
- package/dist/clickhouse/entities.d.ts +7 -1
- package/dist/clickhouse/entities.d.ts.map +1 -1
- package/dist/clickhouse/expressions.d.ts +27 -0
- package/dist/clickhouse/expressions.d.ts.map +1 -0
- package/dist/clickhouse/parser.d.ts +12 -2
- package/dist/clickhouse/parser.d.ts.map +1 -1
- package/dist/clickhouse/plan/diff.d.ts.map +1 -1
- package/dist/clickhouse/plan/normalize.d.ts +11 -1
- package/dist/clickhouse/plan/normalize.d.ts.map +1 -1
- package/dist/clickhouse/plan/rebuild-handoff.d.ts.map +1 -1
- package/dist/clickhouse/plan/rules.d.ts +1 -0
- package/dist/clickhouse/plan/rules.d.ts.map +1 -1
- package/dist/clickhouse.d.ts +1 -0
- package/dist/clickhouse.d.ts.map +1 -1
- package/dist/codegen/classifier-page.d.ts.map +1 -1
- package/dist/codegen/postgres-classifier-page.d.ts.map +1 -1
- package/dist/core/cursor.d.ts +41 -0
- package/dist/core/cursor.d.ts.map +1 -1
- package/dist/core/interpolation.d.ts +18 -1
- package/dist/core/interpolation.d.ts.map +1 -1
- package/dist/files/clickhouse.d.ts +2 -2
- package/dist/files/clickhouse.d.ts.map +1 -1
- package/dist/files/common.d.ts +16 -0
- package/dist/files/common.d.ts.map +1 -1
- package/dist/files/postgres.d.ts +2 -2
- package/dist/files/postgres.d.ts.map +1 -1
- package/dist/import-parser.d.ts +2 -1
- package/dist/import-parser.d.ts.map +1 -1
- package/dist/integrity.json +19 -19
- package/dist/lint/post-synth/clickhouse-helpers.d.ts +6 -19
- package/dist/lint/post-synth/clickhouse-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/postgres-helpers.d.ts +15 -55
- package/dist/lint/post-synth/postgres-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/postgres-names.d.ts +2 -2
- package/dist/lint/post-synth/postgres-names.d.ts.map +1 -1
- package/dist/lint/post-synth/sql-helpers.d.ts +5 -6
- package/dist/lint/post-synth/sql-helpers.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch102.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch103.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch104.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch105.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch106.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch107.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch111.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch112.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch113.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch114.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch115.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch120.d.ts.map +1 -1
- package/dist/lint/post-synth/sqlch125.d.ts.map +1 -1
- package/dist/manifest.json +1 -1
- package/dist/postgres/apply/statements.d.ts.map +1 -1
- package/dist/postgres/entities.d.ts +7 -1
- package/dist/postgres/entities.d.ts.map +1 -1
- package/dist/postgres/parser.d.ts +10 -2
- package/dist/postgres/parser.d.ts.map +1 -1
- package/dist/postgres/plan/diff.d.ts.map +1 -1
- package/dist/postgres/plan/normalize.d.ts.map +1 -1
- package/dist/postgres/plan/rules.d.ts +1 -0
- package/dist/postgres/plan/rules.d.ts.map +1 -1
- package/dist/postgres.d.ts +1 -0
- package/dist/postgres.d.ts.map +1 -1
- package/dist/read/clickhouse.d.ts +66 -0
- package/dist/read/clickhouse.d.ts.map +1 -0
- package/dist/read/objects.d.ts +99 -0
- package/dist/read/objects.d.ts.map +1 -0
- package/dist/read/postgres.d.ts +83 -0
- package/dist/read/postgres.d.ts.map +1 -0
- package/dist/read.d.ts +49 -0
- package/dist/read.d.ts.map +1 -0
- package/dist/rules/clickhouse-helpers.ts +20 -97
- package/dist/rules/postgres-helpers.ts +18 -53
- package/dist/rules/postgres-names.ts +6 -6
- package/dist/rules/sql-helpers.ts +8 -28
- package/dist/rules/sqlch102.ts +2 -3
- package/dist/rules/sqlch103.ts +2 -3
- package/dist/rules/sqlch104.ts +2 -3
- package/dist/rules/sqlch105.ts +2 -3
- package/dist/rules/sqlch106.ts +2 -3
- package/dist/rules/sqlch107.ts +2 -3
- package/dist/rules/sqlch111.ts +2 -3
- package/dist/rules/sqlch112.ts +2 -3
- package/dist/rules/sqlch113.ts +2 -3
- package/dist/rules/sqlch114.ts +2 -3
- package/dist/rules/sqlch115.ts +2 -3
- package/dist/rules/sqlch120.ts +2 -3
- package/dist/rules/sqlch125.ts +2 -3
- package/dist/serializer.d.ts +11 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/sql-files.d.ts +17 -1
- package/dist/sql-files.d.ts.map +1 -1
- package/dist/sql-types.d.ts +3 -0
- package/dist/sql-types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/clickhouse/apply/statements.ts +2 -0
- package/src/clickhouse/entities.ts +8 -1
- package/src/clickhouse/expressions.ts +108 -0
- package/src/clickhouse/parser.ts +113 -31
- package/src/clickhouse/plan/diff.ts +19 -0
- package/src/clickhouse/plan/normalize.ts +27 -2
- package/src/clickhouse/plan/rebuild-handoff.ts +2 -1
- package/src/clickhouse/plan/rules.ts +7 -0
- package/src/clickhouse/testdata/server-ddl-baseline.json +67 -0
- package/src/clickhouse.ts +10 -0
- package/src/codegen/classifier-page.ts +2 -0
- package/src/codegen/postgres-classifier-page.ts +2 -0
- package/src/core/cursor.ts +96 -0
- package/src/core/interpolation.ts +32 -1
- package/src/files/clickhouse.ts +7 -5
- package/src/files/common.ts +23 -0
- package/src/files/postgres.ts +12 -8
- package/src/import-parser.ts +2 -1
- package/src/lint/post-synth/clickhouse-helpers.ts +20 -97
- package/src/lint/post-synth/postgres-helpers.ts +18 -53
- package/src/lint/post-synth/postgres-names.ts +6 -6
- package/src/lint/post-synth/sql-helpers.ts +8 -28
- package/src/lint/post-synth/sqlch102.ts +2 -3
- package/src/lint/post-synth/sqlch103.ts +2 -3
- package/src/lint/post-synth/sqlch104.ts +2 -3
- package/src/lint/post-synth/sqlch105.ts +2 -3
- package/src/lint/post-synth/sqlch106.ts +2 -3
- package/src/lint/post-synth/sqlch107.ts +2 -3
- package/src/lint/post-synth/sqlch111.ts +2 -3
- package/src/lint/post-synth/sqlch112.ts +2 -3
- package/src/lint/post-synth/sqlch113.ts +2 -3
- package/src/lint/post-synth/sqlch114.ts +2 -3
- package/src/lint/post-synth/sqlch115.ts +2 -3
- package/src/lint/post-synth/sqlch120.ts +2 -3
- package/src/lint/post-synth/sqlch125.ts +2 -3
- package/src/postgres/apply/statements.ts +2 -0
- package/src/postgres/entities.ts +9 -1
- package/src/postgres/parser.ts +31 -8
- package/src/postgres/plan/diff.ts +18 -0
- package/src/postgres/plan/normalize.ts +12 -0
- package/src/postgres/plan/rules.ts +7 -0
- package/src/postgres/testdata/server-ddl-baseline.json +38 -0
- package/src/postgres.ts +12 -0
- package/src/read/clickhouse.ts +137 -0
- package/src/read/objects.ts +137 -0
- package/src/read/postgres.ts +180 -0
- package/src/read-policies.e2e.test.ts +144 -0
- package/src/read.test.ts +143 -0
- package/src/read.ts +69 -0
- package/src/serializer.ts +37 -1
- package/src/sql-files.ts +27 -6
- package/src/sql-types.ts +19 -2
- package/src/unknown-clauses.test.ts +227 -0
|
@@ -8,54 +8,26 @@
|
|
|
8
8
|
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
9
9
|
import { POSTGRES_MAJORS, VERSION_RANGES } from "../../generated/postgres";
|
|
10
10
|
import type { VersionRange } from "../../postgres/catalog-types";
|
|
11
|
-
import type
|
|
12
|
-
import {
|
|
11
|
+
import { readPostgres, type PostgresIndexInfo, type PostgresTableInfo, type PostgresViewInfo } from "../../read/postgres";
|
|
12
|
+
import type { PostgresIndexJson, PostgresTableJson, PostgresViewJson } from "../../read/objects";
|
|
13
|
+
import { postgresMajorOf, type OutputObject } from "./sql-helpers";
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
checks: Array<{ name?: string; expr: string; notEnforced?: boolean }>;
|
|
23
|
-
foreignKeys: Array<{ name?: string; columns: string[]; refTable: string; refColumns: string[] }>;
|
|
24
|
-
exclusions: unknown[];
|
|
25
|
-
inherits: unknown[];
|
|
26
|
-
partitionOf?: unknown;
|
|
27
|
-
ofType?: unknown;
|
|
28
|
-
persistence?: string;
|
|
29
|
-
with?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface PgIndex extends OutputObject {
|
|
33
|
-
sqlName: string;
|
|
34
|
-
schema?: string;
|
|
35
|
-
table: string;
|
|
36
|
-
tableName: string;
|
|
37
|
-
unique?: boolean;
|
|
38
|
-
method?: string;
|
|
39
|
-
elements: Array<{ expr: string; column?: string }>;
|
|
40
|
-
include?: string;
|
|
41
|
-
where?: string;
|
|
42
|
-
with?: string;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface PgView extends OutputObject {
|
|
46
|
-
sqlName: string;
|
|
47
|
-
schema?: string;
|
|
48
|
-
query: string;
|
|
49
|
-
with?: string;
|
|
50
|
-
}
|
|
15
|
+
/**
|
|
16
|
+
* The objects as the public read API types them (`../../read/postgres.ts`,
|
|
17
|
+
* `@intentius/chant-lexicon-sql/read`): the checks and a project's own
|
|
18
|
+
* `lint.policies` read the same values.
|
|
19
|
+
*/
|
|
20
|
+
export type PgTable = PostgresTableInfo;
|
|
21
|
+
export type PgIndex = PostgresIndexInfo;
|
|
22
|
+
export type PgView = PostgresViewInfo;
|
|
51
23
|
|
|
52
|
-
export const isTable = (o: OutputObject): o is
|
|
53
|
-
export const isIndex = (o: OutputObject): o is
|
|
54
|
-
export const isView = (o: OutputObject): o is
|
|
55
|
-
export const isMaterializedView = (o: OutputObject): o is
|
|
24
|
+
export const isTable = (o: OutputObject): o is OutputObject & PostgresTableJson => o.type === "Postgres::Table";
|
|
25
|
+
export const isIndex = (o: OutputObject): o is OutputObject & PostgresIndexJson => o.type === "Postgres::Index";
|
|
26
|
+
export const isView = (o: OutputObject): o is OutputObject & PostgresViewJson => o.type === "Postgres::View";
|
|
27
|
+
export const isMaterializedView = (o: OutputObject): o is OutputObject & PostgresViewJson => o.type === "Postgres::MaterializedView";
|
|
56
28
|
|
|
57
|
-
export const tablesOf = (ctx: PostSynthContext): PgTable[] =>
|
|
58
|
-
export const indexesOf = (ctx: PostSynthContext): PgIndex[] =>
|
|
29
|
+
export const tablesOf = (ctx: PostSynthContext): PgTable[] => readPostgres(ctx).tables;
|
|
30
|
+
export const indexesOf = (ctx: PostSynthContext): PgIndex[] => readPostgres(ctx).indexes;
|
|
59
31
|
|
|
60
32
|
/** The major the build targets (`postgresMajor` in the output), else the newest pinned. */
|
|
61
33
|
export const targetMajor = (ctx: PostSynthContext): number => postgresMajorOf(ctx, PINNED_MAJOR);
|
|
@@ -87,14 +59,7 @@ export function storageParams(text: string | undefined): Map<string, string> {
|
|
|
87
59
|
}
|
|
88
60
|
|
|
89
61
|
/** The leading bare-column elements of an index, in order; stops at the first expression. */
|
|
90
|
-
export
|
|
91
|
-
const out: string[] = [];
|
|
92
|
-
for (const e of index.elements) {
|
|
93
|
-
if (!e.column) break;
|
|
94
|
-
out.push(e.column);
|
|
95
|
-
}
|
|
96
|
-
return out;
|
|
97
|
-
}
|
|
62
|
+
export const leadingColumns = (index: PgIndex): string[] => index.columns;
|
|
98
63
|
|
|
99
64
|
/** A check over the build's Postgres objects, so each check file holds its rule. */
|
|
100
65
|
export function checkOf(
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
|
|
15
|
-
import { COLUMN_TYPES, FUNCTIONS, INDEX_ACCESS_METHODS, KEYWORDS, OPERATOR_CLASSES } from "../../generated/postgres";
|
|
15
|
+
import { COLUMN_TYPES, FUNCTIONS, INDEX_ACCESS_METHODS, KEYWORDS, OPERATOR_CLASSES, POSTGRES_MAJORS } from "../../generated/postgres";
|
|
16
16
|
import { EXTENSION_OBJECTS } from "../../postgres/overlays/extension-objects";
|
|
17
17
|
import { GRAMMAR_TYPE_SPELLINGS, SERIAL_TYPES, SERIAL_WIDTH_SPELLINGS, TYPE_SPELLINGS } from "../../postgres/overlays/types";
|
|
18
18
|
import { isTrivia, tokenizeText, type Token } from "../../postgres/tokens";
|
|
19
19
|
import type { ColumnTypeSpec } from "../../postgres/catalog-types";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
20
|
+
import { dialectObjects, recordedPostgresMajor, type PostgresTableJson as PgTable } from "../../read/objects";
|
|
21
|
+
import type { OutputObject } from "./sql-helpers";
|
|
22
22
|
|
|
23
23
|
// ── Catalog lookups ────────────────────────────────────────────────────
|
|
24
24
|
|
|
@@ -120,7 +120,7 @@ export interface PgProject {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
export function projectOf(ctx: PostSynthContext): PgProject {
|
|
123
|
-
return projectFromObjects(
|
|
123
|
+
return projectFromObjects(dialectObjects(ctx, "postgres"), recordedPostgresMajor(ctx, POSTGRES_MAJORS[POSTGRES_MAJORS.length - 1]!));
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/** The project a set of output objects declares, at `major`: for a reader that holds the build output itself (`chant sql types`). */
|
|
@@ -386,7 +386,7 @@ function providesFunction(e: (typeof EXTENSION_OBJECTS)[string], name: string):
|
|
|
386
386
|
export function expressionsOf(o: OutputObject): Array<{ where: string; expr: string }> {
|
|
387
387
|
const out: Array<{ where: string; expr: string }> = [];
|
|
388
388
|
if (o.type === "Postgres::Table") {
|
|
389
|
-
const t = o as PgTable;
|
|
389
|
+
const t = o as unknown as PgTable;
|
|
390
390
|
for (const c of t.columns) {
|
|
391
391
|
if (c.default) out.push({ where: `column ${c.name}'s DEFAULT`, expr: c.default });
|
|
392
392
|
if (c.generated?.expr) out.push({ where: `generated column ${c.name}`, expr: c.generated.expr });
|
|
@@ -483,7 +483,7 @@ export function interpolatedTable(p: PgProject, ref: unknown, sqlName: string |
|
|
|
483
483
|
const o = p.byExport.get(ref);
|
|
484
484
|
if (!o || o.type !== "Postgres::Table") return undefined;
|
|
485
485
|
if (sqlName !== undefined && o.sqlName !== sqlName) return undefined;
|
|
486
|
-
return o as PgTable;
|
|
486
|
+
return o as unknown as PgTable;
|
|
487
487
|
}
|
|
488
488
|
|
|
489
489
|
/**
|
|
@@ -1,41 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Reading the sql lexicon's build output in a post-synth check: the JSON
|
|
3
|
-
* document the serializer writes (`dialect`, `applyOrder`, `objects`).
|
|
3
|
+
* document the serializer writes (`dialect`, `applyOrder`, `objects`). The
|
|
4
|
+
* documents are found by `../../read/objects.ts`, the same path the public
|
|
5
|
+
* read API (`@intentius/chant-lexicon-sql/read`) takes.
|
|
4
6
|
*/
|
|
5
7
|
|
|
6
8
|
import type { PostSynthContext } from "@intentius/chant/lint/post-synth";
|
|
9
|
+
import { dialectObjects, recordedPostgresMajor, type SqlObjectJson } from "../../read/objects";
|
|
7
10
|
|
|
8
|
-
export interface OutputObject {
|
|
9
|
-
export: string;
|
|
10
|
-
type: string;
|
|
11
|
-
name: string;
|
|
11
|
+
export interface OutputObject extends SqlObjectJson {
|
|
12
12
|
database?: string;
|
|
13
13
|
engine?: { name: string; args?: string[] };
|
|
14
|
-
[key: string]: unknown;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
/** Every schema object in the build's sql output, ClickHouse dialect. */
|
|
18
17
|
export function clickhouseObjects(ctx: PostSynthContext): OutputObject[] {
|
|
19
|
-
|
|
20
|
-
for (const doc of ctx.docs ?? []) {
|
|
21
|
-
if (doc.error || doc.lexicon !== "sql" || doc.format !== "json") continue;
|
|
22
|
-
const value = doc.value as { dialect?: unknown; objects?: unknown };
|
|
23
|
-
if (value?.dialect !== "clickhouse" || !Array.isArray(value.objects)) continue;
|
|
24
|
-
out.push(...(value.objects as OutputObject[]));
|
|
25
|
-
}
|
|
26
|
-
return out;
|
|
18
|
+
return dialectObjects(ctx, "clickhouse") as OutputObject[];
|
|
27
19
|
}
|
|
28
20
|
|
|
29
21
|
/** Every schema object in the build's sql output, Postgres dialect. */
|
|
30
22
|
export function postgresObjects(ctx: PostSynthContext): OutputObject[] {
|
|
31
|
-
|
|
32
|
-
for (const doc of ctx.docs ?? []) {
|
|
33
|
-
if (doc.error || doc.lexicon !== "sql" || doc.format !== "json") continue;
|
|
34
|
-
const value = doc.value as { dialect?: unknown; objects?: unknown };
|
|
35
|
-
if (value?.dialect !== "postgres" || !Array.isArray(value.objects)) continue;
|
|
36
|
-
out.push(...(value.objects as OutputObject[]));
|
|
37
|
-
}
|
|
38
|
-
return out;
|
|
23
|
+
return dialectObjects(ctx, "postgres") as OutputObject[];
|
|
39
24
|
}
|
|
40
25
|
|
|
41
26
|
/**
|
|
@@ -44,10 +29,5 @@ export function postgresObjects(ctx: PostSynthContext): OutputObject[] {
|
|
|
44
29
|
* output that carries none.
|
|
45
30
|
*/
|
|
46
31
|
export function postgresMajorOf(ctx: PostSynthContext, fallback: number): number {
|
|
47
|
-
|
|
48
|
-
if (doc.error || doc.lexicon !== "sql" || doc.format !== "json") continue;
|
|
49
|
-
const value = doc.value as { dialect?: unknown; postgresMajor?: unknown };
|
|
50
|
-
if (value?.dialect === "postgres" && typeof value.postgresMajor === "number") return value.postgresMajor;
|
|
51
|
-
}
|
|
52
|
-
return fallback;
|
|
32
|
+
return recordedPostgresMajor(ctx, fallback);
|
|
53
33
|
}
|
package/dist/rules/sqlch102.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { checkOf, keyElements, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* SQLCH102: a PRIMARY KEY that is not a prefix of ORDER BY.
|
|
@@ -9,7 +8,7 @@ import { clickhouseObjects } from "./sql-helpers";
|
|
|
9
8
|
* the table at CREATE.
|
|
10
9
|
*/
|
|
11
10
|
export const sqlch102 = checkOf({ id: "SQLCH102", description: "A PRIMARY KEY is not a prefix of ORDER BY" }, (ctx, report) => {
|
|
12
|
-
for (const t of
|
|
11
|
+
for (const t of tablesOf(ctx)) {
|
|
13
12
|
if (!t.primaryKey || !t.orderBy) continue;
|
|
14
13
|
const pk = keyElements(t.primaryKey).map((e) => e.replace(/\s+/g, ""));
|
|
15
14
|
const ob = keyElements(t.orderBy).map((e) => e.replace(/\s+/g, ""));
|
package/dist/rules/sqlch103.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { baseEngineName, checkOf, columnByName, engineArguments, isNullableType,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { baseEngineName, checkOf, columnByName, engineArguments, isNullableType, tablesOf, typeFamily } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
const VERSION_TYPES = new Set(["UInt8", "UInt16", "UInt32", "UInt64", "UInt128", "UInt256", "Date", "DateTime", "DateTime64"]);
|
|
5
4
|
|
|
@@ -25,7 +24,7 @@ const SPECIAL: Record<string, Array<{ role: string; index: number; accepts: (fam
|
|
|
25
24
|
* .../collapsingmergetree, .../versionedcollapsingmergetree (sign: Int8).
|
|
26
25
|
*/
|
|
27
26
|
export const sqlch103 = checkOf({ id: "SQLCH103", description: "An engine's version, sign or is_deleted column has an unsupported type" }, (ctx, report) => {
|
|
28
|
-
for (const t of
|
|
27
|
+
for (const t of tablesOf(ctx)) {
|
|
29
28
|
if (!t.engine) continue;
|
|
30
29
|
const roles = SPECIAL[baseEngineName(t.engine)];
|
|
31
30
|
if (!roles) continue;
|
package/dist/rules/sqlch104.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { baseEngineName, checkOf, engineArguments,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { baseEngineName, checkOf, engineArguments, splitTop, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
/** The engine arguments that name columns, by base engine. */
|
|
5
4
|
function columnArguments(engine: string, args: string[]): string[] {
|
|
@@ -26,7 +25,7 @@ function columnArguments(engine: string, args: string[]): string[] {
|
|
|
26
25
|
* sign, version, is_deleted and summed columns are columns of the table).
|
|
27
26
|
*/
|
|
28
27
|
export const sqlch104 = checkOf({ id: "SQLCH104", description: "A MergeTree engine argument names a column the table does not declare" }, (ctx, report) => {
|
|
29
|
-
for (const t of
|
|
28
|
+
for (const t of tablesOf(ctx)) {
|
|
30
29
|
if (!t.engine || t.columns.length === 0) continue;
|
|
31
30
|
const declared = new Set(t.columns.map((c) => c.name));
|
|
32
31
|
for (const arg of columnArguments(baseEngineName(t.engine), engineArguments(t.engine))) {
|
package/dist/rules/sqlch105.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { bareName, checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { bareName, checkOf, keyElements, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* SQLCH105: ORDER BY, PRIMARY KEY, PARTITION BY or SAMPLE BY lists a bare
|
|
@@ -10,7 +9,7 @@ import { clickhouseObjects } from "./sql-helpers";
|
|
|
10
9
|
* judged; an expression is left to the server.
|
|
11
10
|
*/
|
|
12
11
|
export const sqlch105 = checkOf({ id: "SQLCH105", description: "A table key clause names a column the table does not declare" }, (ctx, report) => {
|
|
13
|
-
for (const t of
|
|
12
|
+
for (const t of tablesOf(ctx)) {
|
|
14
13
|
if (t.columns.length === 0) continue;
|
|
15
14
|
const declared = new Set(t.columns.map((c) => c.name));
|
|
16
15
|
const clauses: Array<[string, string | undefined]> = [
|
package/dist/rules/sqlch106.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { checkOf, mentionedNames, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* SQLCH106: a data skipping index expression mentions a column the table does
|
|
@@ -11,7 +10,7 @@ import { clickhouseObjects } from "./sql-helpers";
|
|
|
11
10
|
* SQL parser would guess.
|
|
12
11
|
*/
|
|
13
12
|
export const sqlch106 = checkOf({ id: "SQLCH106", description: "A skip index expression names a column the table does not declare" }, (ctx, report) => {
|
|
14
|
-
for (const t of
|
|
13
|
+
for (const t of tablesOf(ctx)) {
|
|
15
14
|
if (t.columns.length === 0) continue;
|
|
16
15
|
const declared = new Set(t.columns.map((c) => c.name));
|
|
17
16
|
for (const index of t.indexes ?? []) {
|
package/dist/rules/sqlch107.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { bareName, checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { bareName, checkOf, splitTop, tablesOf, typeFamily } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
const DATE_TYPES = new Set(["Date", "Date32", "DateTime", "DateTime64"]);
|
|
5
4
|
const TTL_ACTION = /\s+(DELETE|TO\s+DISK|TO\s+VOLUME|RECOMPRESS|GROUP\s+BY|WHERE)\b[\s\S]*$/i;
|
|
@@ -13,7 +12,7 @@ const TTL_ACTION = /\s+(DELETE|TO\s+DISK|TO\s+VOLUME|RECOMPRESS|GROUP\s+BY|WHERE
|
|
|
13
12
|
* a function call is left to the server.
|
|
14
13
|
*/
|
|
15
14
|
export const sqlch107 = checkOf({ id: "SQLCH107", description: "A TTL expression is built on a column that is not a Date or DateTime" }, (ctx, report) => {
|
|
16
|
-
for (const t of
|
|
15
|
+
for (const t of tablesOf(ctx)) {
|
|
17
16
|
const ttls: Array<{ where: string; expr: string }> = [];
|
|
18
17
|
if (t.ttl) for (const clause of splitTop(t.ttl)) ttls.push({ where: "table TTL", expr: clause.replace(TTL_ACTION, "") });
|
|
19
18
|
for (const c of t.columns) if (c.ttl) ttls.push({ where: `column ${c.name} TTL`, expr: c.ttl.replace(TTL_ACTION, "") });
|
package/dist/rules/sqlch111.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { checkOf, splitTop, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
const MAX_VALUES = 100;
|
|
5
4
|
|
|
@@ -23,7 +22,7 @@ function allowedValues(expr: string): { column: string; count: number } | undefi
|
|
|
23
22
|
* https://clickhouse.com/docs/best-practices/select-data-types.
|
|
24
23
|
*/
|
|
25
24
|
export const sqlch111 = checkOf({ id: "SQLCH111", description: "A String column limited to a few values is not LowCardinality" }, (ctx, report) => {
|
|
26
|
-
for (const t of
|
|
25
|
+
for (const t of tablesOf(ctx)) {
|
|
27
26
|
for (const c of t.constraints ?? []) {
|
|
28
27
|
if (c.kind !== "CHECK") continue;
|
|
29
28
|
const found = allowedValues(c.expr);
|
package/dist/rules/sqlch112.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { checkOf, tablesOf, typeFamily } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
const FINE_FUNCTIONS =
|
|
5
4
|
/\b(toStartOfSecond|toStartOfMinute|toStartOfFiveMinutes?|toStartOfTenMinutes|toStartOfFifteenMinutes|toStartOfHour|toRelativeSecondNum|toRelativeMinuteNum|toRelativeHourNum|toUnixTimestamp|toYYYYMMDDhhmmss|toStartOfInterval)\s*\(/;
|
|
@@ -15,7 +14,7 @@ const FINE_FUNCTIONS =
|
|
|
15
14
|
* the sub-day truncation functions.
|
|
16
15
|
*/
|
|
17
16
|
export const sqlch112 = checkOf({ id: "SQLCH112", description: "A PARTITION BY expression is finer than a day" }, (ctx, report) => {
|
|
18
|
-
for (const t of
|
|
17
|
+
for (const t of tablesOf(ctx)) {
|
|
19
18
|
const expr = t.partitionBy?.trim();
|
|
20
19
|
if (!expr) continue;
|
|
21
20
|
const col = t.columns.find((c) => c.name === expr.replace(/^\(|\)$/g, "").trim());
|
package/dist/rules/sqlch113.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { checkOf, isMergeTree,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { checkOf, isMergeTree, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* SQLCH113: a MergeTree table with neither ORDER BY nor PRIMARY KEY.
|
|
@@ -9,7 +8,7 @@ import { clickhouseObjects } from "./sql-helpers";
|
|
|
9
8
|
* `ORDER BY tuple()` to have none). The server refuses the CREATE.
|
|
10
9
|
*/
|
|
11
10
|
export const sqlch113 = checkOf({ id: "SQLCH113", description: "A MergeTree table declares no sort key" }, (ctx, report) => {
|
|
12
|
-
for (const t of
|
|
11
|
+
for (const t of tablesOf(ctx)) {
|
|
13
12
|
if (!isMergeTree(t.engine) || t.orderBy || t.primaryKey) continue;
|
|
14
13
|
report({
|
|
15
14
|
severity: "error",
|
package/dist/rules/sqlch114.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CODECS } from "../../generated/clickhouse";
|
|
2
|
-
import { checkOf, codecNames,
|
|
3
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
2
|
+
import { checkOf, codecNames, tablesOf } from "./clickhouse-helpers";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* SQLCH114: a column CODEC names a codec the pinned server does not have.
|
|
@@ -10,7 +9,7 @@ import { clickhouseObjects } from "./sql-helpers";
|
|
|
10
9
|
*/
|
|
11
10
|
export const sqlch114 = checkOf({ id: "SQLCH114", description: "A column codec is not one the pinned server has" }, (ctx, report) => {
|
|
12
11
|
const known = new Set(Object.keys(CODECS).map((n) => n.toLowerCase()));
|
|
13
|
-
for (const t of
|
|
12
|
+
for (const t of tablesOf(ctx)) {
|
|
14
13
|
for (const c of t.columns) {
|
|
15
14
|
if (!c.codec) continue;
|
|
16
15
|
for (const name of codecNames(c.codec)) {
|
package/dist/rules/sqlch115.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CODECS } from "../../generated/clickhouse";
|
|
2
|
-
import { checkOf, codecNames,
|
|
3
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
2
|
+
import { checkOf, codecNames, tablesOf } from "./clickhouse-helpers";
|
|
4
3
|
|
|
5
4
|
const SENSITIVE = /(^|_)(password|passwd|pwd|secret|api_?key|access_?key|private_?key|token|ssn|social_?security|credit_?card|card_?number|iban)(_|$)/i;
|
|
6
5
|
|
|
@@ -17,7 +16,7 @@ const SENSITIVE = /(^|_)(password|passwd|pwd|secret|api_?key|access_?key|private
|
|
|
17
16
|
*/
|
|
18
17
|
export const sqlch115 = checkOf({ id: "SQLCH115", description: "A secret- or PII-named column carries no comment, TTL or encryption" }, (ctx, report) => {
|
|
19
18
|
const encryption = new Set(Object.entries(CODECS).filter(([, s]) => s.encryption).map(([n]) => n.toLowerCase()));
|
|
20
|
-
for (const t of
|
|
19
|
+
for (const t of tablesOf(ctx)) {
|
|
21
20
|
for (const c of t.columns) {
|
|
22
21
|
if (!SENSITIVE.test(c.name) || c.comment || c.ttl || t.ttl) continue;
|
|
23
22
|
if (c.codec && codecNames(c.codec).some((n) => encryption.has(n.toLowerCase()))) continue;
|
package/dist/rules/sqlch120.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { checkOf,
|
|
2
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
1
|
+
import { checkOf, tablesOf } from "./clickhouse-helpers";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* SQLCH120: a MergeTree engine written with the legacy positional arguments.
|
|
@@ -10,7 +9,7 @@ import { clickhouseObjects } from "./sql-helpers";
|
|
|
10
9
|
* syntax is a bare `MergeTree` with ORDER BY, PARTITION BY and SETTINGS.
|
|
11
10
|
*/
|
|
12
11
|
export const sqlch120 = checkOf({ id: "SQLCH120", description: "A MergeTree engine uses the deprecated positional arguments" }, (ctx, report) => {
|
|
13
|
-
for (const t of
|
|
12
|
+
for (const t of tablesOf(ctx)) {
|
|
14
13
|
if (t.engine?.name !== "MergeTree" || (t.engine.args ?? []).length === 0) continue;
|
|
15
14
|
report({
|
|
16
15
|
severity: "warning",
|
package/dist/rules/sqlch125.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CODECS, CLICKHOUSE_VERSION } from "../../generated/clickhouse";
|
|
2
|
-
import { checkOf,
|
|
3
|
-
import { clickhouseObjects } from "./sql-helpers";
|
|
2
|
+
import { checkOf, splitTop, tablesOf } from "./clickhouse-helpers";
|
|
4
3
|
|
|
5
4
|
type Param = { name: string; kind: string; optional?: boolean; range?: readonly [number, number]; values?: readonly string[] };
|
|
6
5
|
|
|
@@ -17,7 +16,7 @@ const NUMBER = /^-?\d+(\.\d+)?$/;
|
|
|
17
16
|
*/
|
|
18
17
|
export const sqlch125 = checkOf({ id: "SQLCH125", description: "A codec parameter is outside what the codec takes" }, (ctx, report) => {
|
|
19
18
|
const codecs = CODECS as Record<string, { parameters: readonly Param[] | "unknown" } | undefined>;
|
|
20
|
-
for (const t of
|
|
19
|
+
for (const t of tablesOf(ctx)) {
|
|
21
20
|
for (const c of t.columns) {
|
|
22
21
|
if (!c.codec) continue;
|
|
23
22
|
for (const part of splitTop(c.codec)) {
|
package/dist/serializer.d.ts
CHANGED
|
@@ -25,11 +25,21 @@
|
|
|
25
25
|
* targets (`sql.postgresMajor`, else the newest pinned major). Post-synth
|
|
26
26
|
* checks and the lock classifier read it; ClickHouse output has no such field.
|
|
27
27
|
*
|
|
28
|
+
* A clause chant's parser does not know (#3872) is kept in the statement as
|
|
29
|
+
* written and named in a build warning ({@link unparsedWarnings}).
|
|
30
|
+
*
|
|
28
31
|
* Rule ids: `SQL` for rules that hold in every dialect, `SQLCH` for the
|
|
29
32
|
* ClickHouse dialect's (#3199), `SQLPG` for Postgres's (#3289).
|
|
30
33
|
*/
|
|
31
|
-
import type { Serializer } from "@intentius/chant";
|
|
34
|
+
import type { Declarable, Serializer } from "@intentius/chant";
|
|
32
35
|
export { applyOrder } from "./core/references.js";
|
|
36
|
+
/**
|
|
37
|
+
* A warning for each clause chant's parser does not know (#3872): where it
|
|
38
|
+
* is (the `.sql` file and line, or the template's file and the line in its
|
|
39
|
+
* statement), which object, and what follows from it. The statement is sent
|
|
40
|
+
* as written; the server decides.
|
|
41
|
+
*/
|
|
42
|
+
export declare function unparsedWarnings(objects: ReadonlyMap<string, Declarable>): string[];
|
|
33
43
|
/** The file the statements are written to, beside the primary output. */
|
|
34
44
|
export declare const CLICKHOUSE_DDL_FILE = "clickhouse.sql";
|
|
35
45
|
/** The Postgres statements' file, beside the primary output. */
|
package/dist/serializer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"serializer.d.ts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAoB,MAAM,kBAAkB,CAAC;AAYjF,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,MAAM,EAAE,CAkBnF;AAED,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAqEhD,eAAO,MAAM,aAAa,EAAE,UAyC3B,CAAC"}
|
package/dist/sql-files.d.ts
CHANGED
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
* `MATERIALIZED VIEW`, `DICTIONARY`, `FUNCTION`, `USER`, `ROLE` and `ROW
|
|
19
19
|
* POLICY`, and `GRANT` (#3711). Any other statement, and any
|
|
20
20
|
* statement that does not parse, throws a {@link SqlFileError} naming every
|
|
21
|
-
* such statement: none is left out.
|
|
21
|
+
* such statement: none is left out. A statement that parses except for a
|
|
22
|
+
* clause the parser does not know (#3872) is read, kept as written, and the
|
|
23
|
+
* clause listed in its object's `unparsed` with the line it is on.
|
|
22
24
|
*
|
|
23
25
|
* A name is a reference where it is qualified (`app.users`), or bare where an
|
|
24
26
|
* object is named (`REFERENCES users`, `FROM users`, an index's table, a
|
|
@@ -41,6 +43,18 @@ export interface SqlFileObject {
|
|
|
41
43
|
ddl: string;
|
|
42
44
|
/** The file it came from, the `origin` it was read under. */
|
|
43
45
|
origin: string;
|
|
46
|
+
/** The line its statement starts on in the file, from 1. */
|
|
47
|
+
line?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Clauses in it chant's parser does not know (#3872), each with the line
|
|
50
|
+
* it starts on: kept in `ddl` as written, for the server to check. Absent
|
|
51
|
+
* when there are none.
|
|
52
|
+
*/
|
|
53
|
+
unparsed?: Array<{
|
|
54
|
+
clause: string;
|
|
55
|
+
line: number;
|
|
56
|
+
column?: string;
|
|
57
|
+
}>;
|
|
44
58
|
}
|
|
45
59
|
/** A file to read: its DDL and the name errors give it. */
|
|
46
60
|
export interface SqlFileSource extends ReadOptions {
|
|
@@ -60,6 +74,8 @@ export declare function sqlFileDeclarations(dialect: SqlDialect, ddl: string, op
|
|
|
60
74
|
};
|
|
61
75
|
/** Where an entity read from a `.sql` file came from: its `origin`. Undefined for any other entity. */
|
|
62
76
|
export declare function sqlFileOf(entity: unknown): string | undefined;
|
|
77
|
+
/** The line an entity read from a `.sql` file starts on in it. Undefined for any other entity. */
|
|
78
|
+
export declare function sqlFileLineOf(entity: unknown): number | undefined;
|
|
63
79
|
/**
|
|
64
80
|
* The declarations the files make, by export name. `known` holds the
|
|
65
81
|
* entities declared elsewhere (the project's tagged templates): a file's
|
package/dist/sql-files.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-files.d.ts","sourceRoot":"","sources":["../src/sql-files.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sql-files.d.ts","sourceRoot":"","sources":["../src/sql-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAiB,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAU/E,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,WAAW,IAAI,cAAc,EAAE,CAAC;AAE9C,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,+GAA+G;IAC/G,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrE;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,GAAG,EAAE,MAAM,CAAC;CACb;AA0BD,8GAA8G;AAC9G,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAInG;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,aAAa,EAAE,CAAA;CAAE,CAW/J;AAED,uGAAuG;AACvG,wBAAgB,SAAS,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE7D;AAED,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAEjE;AA6BD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;CAAO,GAAG,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAuD1K;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAatH"}
|
package/dist/sql-types.d.ts
CHANGED
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
* (`./lint/post-synth/postgres-names.ts`'s `typeIdentity`), the type
|
|
23
23
|
* family in ClickHouse; `never` when it cannot be told.
|
|
24
24
|
*
|
|
25
|
+
* A column that carries a clause chant does not read (#3872) keeps the type
|
|
26
|
+
* that was read, with `nullable` and `cmp` `never`.
|
|
27
|
+
*
|
|
25
28
|
* A view's column that is one column reference (`${t.columns.c}`, `o.${t.columns.c}`)
|
|
26
29
|
* is that column's type; any other expression is `unknown`.
|
|
27
30
|
*/
|
package/dist/sql-types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-types.d.ts","sourceRoot":"","sources":["../src/sql-types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"sql-types.d.ts","sourceRoot":"","sources":["../src/sql-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAW9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ7C,4EAA4E;AAC5E,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,MAAM,CAGpG;AAED,kGAAkG;AAClG,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EACzC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,qBAA0B,GAC/B,SAAS,GAAG,OAAO,GAAG,SAAS,CASjC;AAED,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAGjE,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,yGAAyG;IACzG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yGAAyG;IACzG,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AA+OD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,IAAI,GAAE,qBAA0B,GAAG,MAAM,CAiClH"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-sql",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.13",
|
|
4
4
|
"description": "SQL lexicon for chant — database schema as typed declarations, one dialect at a time; ClickHouse first, with types read from a pinned server's catalog",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -70,6 +70,6 @@
|
|
|
70
70
|
"typescript": "^5.9.3"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"@intentius/chant": "^0.124.
|
|
73
|
+
"@intentius/chant": "^0.124.13"
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -187,6 +187,8 @@ export function refusalDetail(changes: readonly Change[], key?: string, type?: s
|
|
|
187
187
|
type === undefined || type === CLICKHOUSE_ENTITY_TYPES.table
|
|
188
188
|
? `Run it as the rebuild migration Op: ClickHouseRebuildOp({ table: ${JSON.stringify(key ?? "<database.table>")}, ... }) from @intentius/chant-lexicon-sql/clickhouse`
|
|
189
189
|
: "The rebuild migration Op rebuilds tables only; drop and create this object instead";
|
|
190
|
+
// A clause chant does not read (#3872) is refused for review: whether ALTER can make it is not known.
|
|
191
|
+
if (changes.every((c) => c.rule === "SQLCH290")) return `needs review, since chant does not read the clause: ${parts.join("; ")}`;
|
|
190
192
|
return `needs a rebuild, which ALTER cannot make: ${parts.join("; ")}. ${instead}`;
|
|
191
193
|
}
|
|
192
194
|
|
|
@@ -42,7 +42,7 @@ import { setInterpolationFields } from "@intentius/chant/provenance";
|
|
|
42
42
|
import { CLICKHOUSE_LEXICAL, isTrivia, SqlSyntaxError, untokenize } from "./tokens";
|
|
43
43
|
import { parseCreate, unquote, type ColumnNode, type CreateNode, type Span, type StorageNode } from "./parser";
|
|
44
44
|
import { parseAccess, type AccessNode } from "./access";
|
|
45
|
-
import { feed, lineage, spanText as text, splice as spliceWith, templateSyntaxError, type TemplateCtx, type TemplateDialect } from "../core/interpolation";
|
|
45
|
+
import { feed, lineage, spanText as text, splice as spliceWith, templateSyntaxError, unparsedClauses, type TemplateCtx, type TemplateDialect, type UnparsedClause } from "../core/interpolation";
|
|
46
46
|
import { SQL_LEXICON, SqlObject, isColumnRefOf, isSqlObjectOf, makeSqlEntity } from "../core/entity";
|
|
47
47
|
import type { LineageEdge } from "../core/references";
|
|
48
48
|
import { SqlLiteral, SqlTemplateError, describeValue as describe, stripUnset as strip, templateParts } from "../core/template";
|
|
@@ -50,6 +50,7 @@ import { setTypedSlots, type ColumnsIn, type Named, type RowIn, type SlotsIn, ty
|
|
|
50
50
|
|
|
51
51
|
export { SQL_LEXICON } from "../core/entity";
|
|
52
52
|
export type { LineageEdge } from "../core/references";
|
|
53
|
+
export type { UnparsedClause } from "../core/interpolation";
|
|
53
54
|
export { SqlLiteral, SqlTemplateError, templateParts, unescapeTemplateDelimiters } from "../core/template";
|
|
54
55
|
export type { AnyColumn, Column, ColumnTraits, KeyColumn, Named, NotNullColumn, UncheckedColumn, Unnamed } from "../core/typed";
|
|
55
56
|
|
|
@@ -110,6 +111,11 @@ interface CommonProps {
|
|
|
110
111
|
ddl: string;
|
|
111
112
|
/** The template's raw parts, as written, for a source round trip. */
|
|
112
113
|
source: { strings: string[] };
|
|
114
|
+
/**
|
|
115
|
+
* Clauses chant's parser does not know (#3872), kept in `ddl` as written
|
|
116
|
+
* and left to the catalog checks and the server. Absent when there are none.
|
|
117
|
+
*/
|
|
118
|
+
unparsed?: UnparsedClause[];
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
export interface DatabaseProps extends CommonProps {
|
|
@@ -540,6 +546,7 @@ function build(tag: Expect, strings: TemplateStringsArray | readonly string[], v
|
|
|
540
546
|
database,
|
|
541
547
|
onCluster: text(ctx, node.onCluster, "onCluster"),
|
|
542
548
|
comment: stringValue(text(ctx, node.comment, "comment")),
|
|
549
|
+
unparsed: unparsedClauses(ctx, node.unknown),
|
|
543
550
|
};
|
|
544
551
|
const done = <T extends ClickHouseObject>(entity: T): T => {
|
|
545
552
|
setInterpolationFields(entity, ctx.fed.map((paths) => [...paths].sort()));
|