@jantokic/chtype 0.2.0 → 0.4.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.
Files changed (55) hide show
  1. package/dist/client/client.d.ts +4 -2
  2. package/dist/client/client.d.ts.map +1 -1
  3. package/dist/client/client.js +11 -0
  4. package/dist/client/client.js.map +1 -1
  5. package/dist/migrate/differ.d.ts +43 -0
  6. package/dist/migrate/differ.d.ts.map +1 -0
  7. package/dist/migrate/differ.js +77 -0
  8. package/dist/migrate/differ.js.map +1 -0
  9. package/dist/migrate/generator.d.ts +33 -0
  10. package/dist/migrate/generator.d.ts.map +1 -0
  11. package/dist/migrate/generator.js +125 -0
  12. package/dist/migrate/generator.js.map +1 -0
  13. package/dist/migrate/index.d.ts +4 -0
  14. package/dist/migrate/index.d.ts.map +1 -0
  15. package/dist/migrate/index.js +4 -0
  16. package/dist/migrate/index.js.map +1 -0
  17. package/dist/migrate/snapshot.d.ts +31 -0
  18. package/dist/migrate/snapshot.d.ts.map +1 -0
  19. package/dist/migrate/snapshot.js +68 -0
  20. package/dist/migrate/snapshot.js.map +1 -0
  21. package/dist/query/compile-utils.d.ts +37 -0
  22. package/dist/query/compile-utils.d.ts.map +1 -0
  23. package/dist/query/compile-utils.js +59 -0
  24. package/dist/query/compile-utils.js.map +1 -0
  25. package/dist/query/delete-builder.d.ts +24 -0
  26. package/dist/query/delete-builder.d.ts.map +1 -0
  27. package/dist/query/delete-builder.js +56 -0
  28. package/dist/query/delete-builder.js.map +1 -0
  29. package/dist/query/expressions.d.ts +70 -3
  30. package/dist/query/expressions.d.ts.map +1 -1
  31. package/dist/query/expressions.js +194 -1
  32. package/dist/query/expressions.js.map +1 -1
  33. package/dist/query/index.d.ts +6 -3
  34. package/dist/query/index.d.ts.map +1 -1
  35. package/dist/query/index.js +5 -2
  36. package/dist/query/index.js.map +1 -1
  37. package/dist/query/query-builder.d.ts +10 -2
  38. package/dist/query/query-builder.d.ts.map +1 -1
  39. package/dist/query/query-builder.js +12 -1
  40. package/dist/query/query-builder.js.map +1 -1
  41. package/dist/query/select-builder.d.ts +61 -5
  42. package/dist/query/select-builder.d.ts.map +1 -1
  43. package/dist/query/select-builder.js +129 -35
  44. package/dist/query/select-builder.js.map +1 -1
  45. package/dist/query/sql-template.d.ts +37 -0
  46. package/dist/query/sql-template.d.ts.map +1 -0
  47. package/dist/query/sql-template.js +80 -0
  48. package/dist/query/sql-template.js.map +1 -0
  49. package/dist/query/types.d.ts +12 -4
  50. package/dist/query/types.d.ts.map +1 -1
  51. package/dist/query/update-builder.d.ts +27 -0
  52. package/dist/query/update-builder.d.ts.map +1 -0
  53. package/dist/query/update-builder.js +72 -0
  54. package/dist/query/update-builder.js.map +1 -0
  55. package/package.json +8 -4
@@ -6,8 +6,10 @@
6
6
  import { type ClickHouseClient as BaseClient, type ClickHouseClientConfigOptions } from '@clickhouse/client';
7
7
  import type { CompiledQuery, DatabaseSchema, InsertType, TableName } from '../query/types.js';
8
8
  export interface ChtypeClient<DB extends DatabaseSchema> {
9
- /** Execute a compiled query and return typed rows. */
10
- execute<T = Record<string, unknown>>(query: CompiledQuery): Promise<T[]>;
9
+ /** Execute a compiled query and return typed rows. Result type is inferred from the compiled query. */
10
+ execute<T = Record<string, unknown>>(query: CompiledQuery<T>): Promise<T[]>;
11
+ /** Execute a compiled query and return a typed async iterable for streaming large result sets. */
12
+ stream<T = Record<string, unknown>>(query: CompiledQuery<T>): AsyncIterable<T[]>;
11
13
  /** Execute a raw SQL query with optional parameters. */
12
14
  query<T = Record<string, unknown>>(sql: string, params?: Record<string, unknown>): Promise<T[]>;
13
15
  /** Insert rows into a table. Type-checked against the table's Insert type. */
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,gBAAgB,IAAI,UAAU,EACnC,KAAK,6BAA6B,EAEnC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9F,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,cAAc;IACrD,sDAAsD;IACtD,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEzE,wDAAwD;IACxD,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhG,8EAA8E;IAC9E,MAAM,CAAC,CAAC,SAAS,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpF;;;;;;OAMG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,cAAc,EACpD,OAAO,EAAE,6BAA6B,GACrC,YAAY,CAAC,EAAE,CAAC,CA8ClB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,KAAK,gBAAgB,IAAI,UAAU,EACnC,KAAK,6BAA6B,EAEnC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9F,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,cAAc;IACrD,uGAAuG;IACvG,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAE5E,kGAAkG;IAClG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;IAEjF,wDAAwD;IACxD,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhG,8EAA8E;IAC9E,MAAM,CAAC,CAAC,SAAS,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpF;;;;;;OAMG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;CAC1B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,cAAc,EACpD,OAAO,EAAE,6BAA6B,GACrC,YAAY,CAAC,EAAE,CAAC,CA0DlB"}
@@ -29,6 +29,17 @@ export function createClient(options) {
29
29
  });
30
30
  return result.json();
31
31
  },
32
+ async *stream(query) {
33
+ const result = await client.query({
34
+ query: query.sql,
35
+ query_params: query.params,
36
+ format: 'JSONEachRow',
37
+ });
38
+ const stream = result.stream();
39
+ for await (const rows of stream) {
40
+ yield rows.map((row) => row.json());
41
+ }
42
+ },
32
43
  async query(sql, params) {
33
44
  const result = await client.query({
34
45
  query: sql,
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,YAAY,IAAI,gBAAgB,GACjC,MAAM,oBAAoB,CAAC;AA0B5B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAsC;IAEtC,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAEzC,OAAO;QACL,KAAK,CAAC,OAAO,CAA8B,KAAoB;YAC7D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAChC,KAAK,EAAE,KAAK,CAAC,GAAG;gBAChB,YAAY,EAAE,KAAK,CAAC,MAAM;gBAC1B,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAK,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,KAAK,CACT,GAAW,EACX,MAAgC;YAEhC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAChC,KAAK,EAAE,GAAG;gBACV,YAAY,EAAE,MAAM;gBACpB,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAK,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,MAAM,CAA0B,KAAQ,EAAE,IAAyB;YACvE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC9B,MAAM,MAAM,CAAC,MAAM,CAAC;gBAClB,KAAK,EAAE,KAAe;gBACtB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,GAAW;YACvB,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,GAAG;YACL,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGL,YAAY,IAAI,gBAAgB,GACjC,MAAM,oBAAoB,CAAC;AA6B5B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAsC;IAEtC,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAEzC,OAAO;QACL,KAAK,CAAC,OAAO,CAA8B,KAAuB;YAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAChC,KAAK,EAAE,KAAK,CAAC,GAAG;gBAChB,YAAY,EAAE,KAAK,CAAC,MAAM;gBAC1B,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAK,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,CAAC,MAAM,CAA8B,KAAuB;YAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAChC,KAAK,EAAE,KAAK,CAAC,GAAG;gBAChB,YAAY,EAAE,KAAK,CAAC,MAAM;gBAC1B,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAK,CAAC;YAClC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,KAAK,CAAC,KAAK,CACT,GAAW,EACX,MAAgC;YAEhC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAChC,KAAK,EAAE,GAAG;gBACV,YAAY,EAAE,MAAM;gBACpB,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC,IAAI,EAAK,CAAC;QAC1B,CAAC;QAED,KAAK,CAAC,MAAM,CAA0B,KAAQ,EAAE,IAAyB;YACvE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC9B,MAAM,MAAM,CAAC,MAAM,CAAC;gBAClB,KAAK,EAAE,KAAe;gBACtB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,aAAa;aACtB,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,GAAW;YACvB,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,GAAG;YACL,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Schema differ — compares two schemas (arrays of IntrospectedTable)
3
+ * and produces a structured diff describing all changes.
4
+ */
5
+ import type { IntrospectedColumn, IntrospectedTable } from '../codegen/introspect.js';
6
+ export type DiffAction = 'add' | 'drop' | 'modify';
7
+ export interface ColumnDiff {
8
+ action: DiffAction;
9
+ column: IntrospectedColumn;
10
+ /** Present only when action is 'modify' — the column definition before the change. */
11
+ previous?: IntrospectedColumn;
12
+ }
13
+ export interface TableDiff {
14
+ action: DiffAction;
15
+ table: string;
16
+ /** Full table definition — present for 'add' (the new table) and 'drop' (the dropped table). */
17
+ definition?: IntrospectedTable;
18
+ /** Column-level changes — present only when action is 'modify'. */
19
+ columns?: ColumnDiff[];
20
+ }
21
+ export interface SchemaDiff {
22
+ tables: TableDiff[];
23
+ /** True when the two schemas are identical. */
24
+ isEmpty: boolean;
25
+ }
26
+ /**
27
+ * Compare two IntrospectedColumn values and return true if they differ
28
+ * in type, default kind, default expression, or comment.
29
+ *
30
+ * Key membership flags (isInSortingKey, isInPrimaryKey, isInPartitionKey) are
31
+ * intentionally excluded — changing ORDER BY / PARTITION BY requires table
32
+ * recreation in ClickHouse, which is out of scope for column-level diffing.
33
+ */
34
+ export declare function columnsEqual(a: IntrospectedColumn, b: IntrospectedColumn): boolean;
35
+ /**
36
+ * Diff two schemas and produce a list of table-level and column-level changes.
37
+ *
38
+ * @param from - The current / source schema (e.g. production snapshot).
39
+ * @param to - The desired / target schema (e.g. dev database).
40
+ * @returns A SchemaDiff describing every change needed to go from `from` to `to`.
41
+ */
42
+ export declare function diffSchemas(from: IntrospectedTable[], to: IntrospectedTable[]): SchemaDiff;
43
+ //# sourceMappingURL=differ.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../../src/migrate/differ.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAEtF,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,mEAAmE;IACnE,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAOlF;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,GAAG,UAAU,CA8B1F"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Schema differ — compares two schemas (arrays of IntrospectedTable)
3
+ * and produces a structured diff describing all changes.
4
+ */
5
+ /**
6
+ * Compare two IntrospectedColumn values and return true if they differ
7
+ * in type, default kind, default expression, or comment.
8
+ *
9
+ * Key membership flags (isInSortingKey, isInPrimaryKey, isInPartitionKey) are
10
+ * intentionally excluded — changing ORDER BY / PARTITION BY requires table
11
+ * recreation in ClickHouse, which is out of scope for column-level diffing.
12
+ */
13
+ export function columnsEqual(a, b) {
14
+ return (a.type === b.type &&
15
+ a.defaultKind === b.defaultKind &&
16
+ a.defaultExpression === b.defaultExpression &&
17
+ a.comment === b.comment);
18
+ }
19
+ /**
20
+ * Diff two schemas and produce a list of table-level and column-level changes.
21
+ *
22
+ * @param from - The current / source schema (e.g. production snapshot).
23
+ * @param to - The desired / target schema (e.g. dev database).
24
+ * @returns A SchemaDiff describing every change needed to go from `from` to `to`.
25
+ */
26
+ export function diffSchemas(from, to) {
27
+ const fromMap = new Map(from.map((t) => [t.name, t]));
28
+ const toMap = new Map(to.map((t) => [t.name, t]));
29
+ const tables = [];
30
+ // Detect dropped tables (in `from` but not in `to`)
31
+ for (const [name, table] of fromMap) {
32
+ if (!toMap.has(name)) {
33
+ tables.push({ action: 'drop', table: name, definition: table });
34
+ }
35
+ }
36
+ // Detect new tables and modified tables
37
+ for (const [name, toTable] of toMap) {
38
+ const fromTable = fromMap.get(name);
39
+ if (!fromTable) {
40
+ tables.push({ action: 'add', table: name, definition: toTable });
41
+ continue;
42
+ }
43
+ // Table exists in both — diff columns
44
+ const columnDiffs = diffColumns(fromTable.columns, toTable.columns);
45
+ if (columnDiffs.length > 0) {
46
+ tables.push({ action: 'modify', table: name, columns: columnDiffs });
47
+ }
48
+ }
49
+ return { tables, isEmpty: tables.length === 0 };
50
+ }
51
+ /**
52
+ * Diff two column lists and return the set of column-level changes.
53
+ */
54
+ function diffColumns(from, to) {
55
+ const fromMap = new Map(from.map((c) => [c.name, c]));
56
+ const toMap = new Map(to.map((c) => [c.name, c]));
57
+ const diffs = [];
58
+ // Dropped columns
59
+ for (const [name, col] of fromMap) {
60
+ if (!toMap.has(name)) {
61
+ diffs.push({ action: 'drop', column: col });
62
+ }
63
+ }
64
+ // New and modified columns
65
+ for (const [name, toCol] of toMap) {
66
+ const fromCol = fromMap.get(name);
67
+ if (!fromCol) {
68
+ diffs.push({ action: 'add', column: toCol });
69
+ continue;
70
+ }
71
+ if (!columnsEqual(fromCol, toCol)) {
72
+ diffs.push({ action: 'modify', column: toCol, previous: fromCol });
73
+ }
74
+ }
75
+ return diffs;
76
+ }
77
+ //# sourceMappingURL=differ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differ.js","sourceRoot":"","sources":["../../src/migrate/differ.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * SQL generator — converts schema diffs into valid ClickHouse SQL statements.
3
+ *
4
+ * Produces CREATE TABLE, DROP TABLE, and ALTER TABLE ADD/DROP/MODIFY COLUMN statements.
5
+ */
6
+ import type { IntrospectedTable } from '../codegen/introspect.js';
7
+ import type { ColumnDiff, SchemaDiff } from './differ.js';
8
+ /**
9
+ * Generate ClickHouse SQL statements from a SchemaDiff.
10
+ *
11
+ * Returns an array of SQL strings, one per statement.
12
+ */
13
+ export declare function generateSQL(diff: SchemaDiff): string[];
14
+ /**
15
+ * Generate a CREATE TABLE statement from a full table definition.
16
+ *
17
+ * Note: sortingKey, partitionKey, defaultExpression, and other values are
18
+ * trusted inputs from introspect.ts (sourced from system tables), not
19
+ * user-supplied strings, so they are emitted as-is without sanitization.
20
+ */
21
+ export declare function generateCreateTable(table: IntrospectedTable): string;
22
+ /**
23
+ * Generate a DROP TABLE statement.
24
+ */
25
+ export declare function generateDropTable(tableName: string): string;
26
+ /**
27
+ * Generate ALTER TABLE statements for column-level changes.
28
+ *
29
+ * Each column change produces a separate ALTER TABLE statement for clarity
30
+ * and to allow partial application.
31
+ */
32
+ export declare function generateAlterTable(tableName: string, columns: ColumnDiff[]): string[];
33
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/migrate/generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAa,MAAM,aAAa,CAAC;AAErE;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAsBtD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAgCpE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAmCrF"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * SQL generator — converts schema diffs into valid ClickHouse SQL statements.
3
+ *
4
+ * Produces CREATE TABLE, DROP TABLE, and ALTER TABLE ADD/DROP/MODIFY COLUMN statements.
5
+ */
6
+ /**
7
+ * Generate ClickHouse SQL statements from a SchemaDiff.
8
+ *
9
+ * Returns an array of SQL strings, one per statement.
10
+ */
11
+ export function generateSQL(diff) {
12
+ const statements = [];
13
+ for (const tableDiff of diff.tables) {
14
+ switch (tableDiff.action) {
15
+ case 'add':
16
+ if (tableDiff.definition) {
17
+ statements.push(generateCreateTable(tableDiff.definition));
18
+ }
19
+ break;
20
+ case 'drop':
21
+ statements.push(generateDropTable(tableDiff.table));
22
+ break;
23
+ case 'modify':
24
+ if (tableDiff.columns) {
25
+ statements.push(...generateAlterTable(tableDiff.table, tableDiff.columns));
26
+ }
27
+ break;
28
+ }
29
+ }
30
+ return statements;
31
+ }
32
+ /**
33
+ * Generate a CREATE TABLE statement from a full table definition.
34
+ *
35
+ * Note: sortingKey, partitionKey, defaultExpression, and other values are
36
+ * trusted inputs from introspect.ts (sourced from system tables), not
37
+ * user-supplied strings, so they are emitted as-is without sanitization.
38
+ */
39
+ export function generateCreateTable(table) {
40
+ const columns = table.columns.map((col) => {
41
+ let def = ` ${quoteIdentifier(col.name)} ${col.type}`;
42
+ if (col.defaultKind && col.defaultExpression) {
43
+ def += ` ${col.defaultKind} ${col.defaultExpression}`;
44
+ }
45
+ if (col.comment) {
46
+ def += ` COMMENT ${quoteSingleString(col.comment)}`;
47
+ }
48
+ return def;
49
+ });
50
+ let sql = `CREATE TABLE ${quoteIdentifier(table.name)}\n(\n${columns.join(',\n')}\n)`;
51
+ sql += `\nENGINE = ${table.engineFull || table.engine}`;
52
+ // ORDER BY, PARTITION BY, and PRIMARY KEY are only valid for MergeTree-family engines.
53
+ // Emitting them for Log, Memory, Kafka, etc. produces invalid DDL.
54
+ const isMergeTree = table.engine.includes('MergeTree');
55
+ if (isMergeTree && table.partitionKey) {
56
+ sql += `\nPARTITION BY ${table.partitionKey}`;
57
+ }
58
+ if (isMergeTree && table.sortingKey) {
59
+ sql += `\nORDER BY (${table.sortingKey})`;
60
+ }
61
+ if (isMergeTree && table.primaryKey && table.primaryKey !== table.sortingKey) {
62
+ sql += `\nPRIMARY KEY (${table.primaryKey})`;
63
+ }
64
+ if (table.comment) {
65
+ sql += `\nCOMMENT ${quoteSingleString(table.comment)}`;
66
+ }
67
+ return sql;
68
+ }
69
+ /**
70
+ * Generate a DROP TABLE statement.
71
+ */
72
+ export function generateDropTable(tableName) {
73
+ return `DROP TABLE ${quoteIdentifier(tableName)}`;
74
+ }
75
+ /**
76
+ * Generate ALTER TABLE statements for column-level changes.
77
+ *
78
+ * Each column change produces a separate ALTER TABLE statement for clarity
79
+ * and to allow partial application.
80
+ */
81
+ export function generateAlterTable(tableName, columns) {
82
+ const statements = [];
83
+ const quoted = quoteIdentifier(tableName);
84
+ for (const diff of columns) {
85
+ switch (diff.action) {
86
+ case 'add': {
87
+ let clause = `ALTER TABLE ${quoted} ADD COLUMN ${quoteIdentifier(diff.column.name)} ${diff.column.type}`;
88
+ if (diff.column.defaultKind && diff.column.defaultExpression) {
89
+ clause += ` ${diff.column.defaultKind} ${diff.column.defaultExpression}`;
90
+ }
91
+ if (diff.column.comment) {
92
+ clause += ` COMMENT ${quoteSingleString(diff.column.comment)}`;
93
+ }
94
+ statements.push(clause);
95
+ break;
96
+ }
97
+ case 'drop':
98
+ statements.push(`ALTER TABLE ${quoted} DROP COLUMN ${quoteIdentifier(diff.column.name)}`);
99
+ break;
100
+ case 'modify': {
101
+ let clause = `ALTER TABLE ${quoted} MODIFY COLUMN ${quoteIdentifier(diff.column.name)} ${diff.column.type}`;
102
+ if (diff.column.defaultKind && diff.column.defaultExpression) {
103
+ clause += ` ${diff.column.defaultKind} ${diff.column.defaultExpression}`;
104
+ }
105
+ if (diff.column.comment) {
106
+ clause += ` COMMENT ${quoteSingleString(diff.column.comment)}`;
107
+ }
108
+ statements.push(clause);
109
+ break;
110
+ }
111
+ }
112
+ }
113
+ return statements;
114
+ }
115
+ /** Quote a ClickHouse identifier with backticks if it contains special characters. */
116
+ function quoteIdentifier(name) {
117
+ if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name))
118
+ return name;
119
+ return `\`${name.replace(/`/g, '\\`')}\``;
120
+ }
121
+ /** Escape and quote a string for use in SQL (single quotes). */
122
+ function quoteSingleString(value) {
123
+ return `'${value.replace(/'/g, "\\'")}'`;
124
+ }
125
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../src/migrate/generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { diffSchemas, columnsEqual, type ColumnDiff, type TableDiff, type SchemaDiff, type DiffAction, } from './differ.js';
2
+ export { generateSQL, generateCreateTable, generateDropTable, generateAlterTable, } from './generator.js';
3
+ export { createSnapshot, saveSnapshot, loadSnapshot, type Snapshot, type SnapshotMeta, } from './snapshot.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,eAAe,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { diffSchemas, columnsEqual, } from './differ.js';
2
+ export { generateSQL, generateCreateTable, generateDropTable, generateAlterTable, } from './generator.js';
3
+ export { createSnapshot, saveSnapshot, loadSnapshot, } from './snapshot.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,YAAY,GAKb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,GAGb,MAAM,eAAe,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Schema snapshot — save and load IntrospectedTable arrays as JSON files.
3
+ *
4
+ * Snapshots are the mechanism for comparing a live database against a
5
+ * previously captured schema state.
6
+ */
7
+ import type { IntrospectedTable } from '../codegen/introspect.js';
8
+ export interface SnapshotMeta {
9
+ version: 1;
10
+ createdAt: string;
11
+ database: string;
12
+ }
13
+ export interface Snapshot {
14
+ meta: SnapshotMeta;
15
+ tables: IntrospectedTable[];
16
+ }
17
+ /**
18
+ * Create a Snapshot object from introspected tables.
19
+ */
20
+ export declare function createSnapshot(tables: IntrospectedTable[], database: string): Snapshot;
21
+ /**
22
+ * Save a snapshot to a JSON file.
23
+ */
24
+ export declare function saveSnapshot(snapshot: Snapshot, filePath: string): Promise<void>;
25
+ /**
26
+ * Load a snapshot from a JSON file.
27
+ *
28
+ * Throws if the file does not exist or contains invalid JSON.
29
+ */
30
+ export declare function loadSnapshot(filePath: string): Promise<Snapshot>;
31
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/migrate/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAStF;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGtF;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAStE"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Schema snapshot — save and load IntrospectedTable arrays as JSON files.
3
+ *
4
+ * Snapshots are the mechanism for comparing a live database against a
5
+ * previously captured schema state.
6
+ */
7
+ import { readFile, writeFile } from 'node:fs/promises';
8
+ /**
9
+ * Create a Snapshot object from introspected tables.
10
+ */
11
+ export function createSnapshot(tables, database) {
12
+ return {
13
+ meta: {
14
+ version: 1,
15
+ createdAt: new Date().toISOString(),
16
+ database,
17
+ },
18
+ tables,
19
+ };
20
+ }
21
+ /**
22
+ * Save a snapshot to a JSON file.
23
+ */
24
+ export async function saveSnapshot(snapshot, filePath) {
25
+ const json = JSON.stringify(snapshot, null, 2);
26
+ await writeFile(filePath, json + '\n', 'utf-8');
27
+ }
28
+ /**
29
+ * Load a snapshot from a JSON file.
30
+ *
31
+ * Throws if the file does not exist or contains invalid JSON.
32
+ */
33
+ export async function loadSnapshot(filePath) {
34
+ const raw = await readFile(filePath, 'utf-8');
35
+ const parsed = JSON.parse(raw);
36
+ if (!isSnapshot(parsed)) {
37
+ throw new Error(`Invalid snapshot file: ${filePath}`);
38
+ }
39
+ return parsed;
40
+ }
41
+ function isSnapshot(value) {
42
+ if (typeof value !== 'object' || value === null)
43
+ return false;
44
+ const obj = value;
45
+ if (typeof obj['meta'] !== 'object' || obj['meta'] === null)
46
+ return false;
47
+ const meta = obj['meta'];
48
+ if (meta['version'] !== 1)
49
+ return false;
50
+ if (typeof meta['createdAt'] !== 'string')
51
+ return false;
52
+ if (typeof meta['database'] !== 'string')
53
+ return false;
54
+ if (!Array.isArray(obj['tables']))
55
+ return false;
56
+ // Validate each table entry has the minimum required shape
57
+ for (const entry of obj['tables']) {
58
+ if (typeof entry !== 'object' || entry === null)
59
+ return false;
60
+ const table = entry;
61
+ if (typeof table['name'] !== 'string')
62
+ return false;
63
+ if (!Array.isArray(table['columns']))
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/migrate/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAcvD;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,MAA2B,EAAE,QAAgB;IAC1E,OAAO;QACL,IAAI,EAAE;YACJ,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,QAAQ;SACT;QACD,MAAM;KACP,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAkB,EAAE,QAAgB;IACrE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAExC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC1E,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAA4B,CAAC;IACpD,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAEhD,2DAA2D;IAC3D,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAc,EAAE,CAAC;QAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAC9D,MAAM,KAAK,GAAG,KAAgC,CAAC;QAC/C,IAAI,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACrD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared compilation utilities for SELECT, DELETE, and UPDATE builders.
3
+ */
4
+ import type { BetweenOp, ComparisonOp, SetOp, UnaryOp } from './types.js';
5
+ import { Expression } from './expressions.js';
6
+ import { Param } from './param.js';
7
+ export type WhereClause = {
8
+ kind: 'comparison';
9
+ column: string;
10
+ op: ComparisonOp | SetOp;
11
+ value: Param | Expression;
12
+ } | {
13
+ kind: 'unary';
14
+ column: string;
15
+ op: UnaryOp;
16
+ } | {
17
+ kind: 'between';
18
+ column: string;
19
+ op: BetweenOp;
20
+ low: Param | Expression;
21
+ high: Param | Expression;
22
+ } | {
23
+ kind: 'expression';
24
+ expr: Expression;
25
+ };
26
+ export interface CompileContext {
27
+ params: Record<string, unknown>;
28
+ /** Param names that came from subqueries/CTEs (external sources). */
29
+ externalParams: Set<string>;
30
+ }
31
+ export declare function createCompileContext(): CompileContext;
32
+ export declare function mergeParams(ctx: CompileContext, source: Record<string, unknown>): void;
33
+ export declare function renderValue(value: number | Param | Expression, ctx: CompileContext): string;
34
+ export declare function renderWhereClause(w: WhereClause, ctx: CompileContext): string;
35
+ /** Valid SQL identifier pattern (settings keys, CTE names, cluster names, column names). */
36
+ export declare const VALID_IDENTIFIER: RegExp;
37
+ //# sourceMappingURL=compile-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-utils.d.ts","sourceRoot":"","sources":["../../src/query/compile-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,EAAkB,UAAU,EAAY,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,YAAY,GAAG,KAAK,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CAAA;CAAE,GAC3F;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,KAAK,GAAG,UAAU,CAAC;IAAC,IAAI,EAAE,KAAK,GAAG,UAAU,CAAA;CAAE,GACrG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,qEAAqE;IACrE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC7B;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAQtF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,UAAU,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,CAiB3F;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,CAoB7E;AAED,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB,QAA6B,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Shared compilation utilities for SELECT, DELETE, and UPDATE builders.
3
+ */
4
+ import { ConditionGroup, Expression, Subquery } from './expressions.js';
5
+ import { Param } from './param.js';
6
+ export function createCompileContext() {
7
+ return { params: {}, externalParams: new Set() };
8
+ }
9
+ export function mergeParams(ctx, source) {
10
+ for (const key of Object.keys(source)) {
11
+ if (key in ctx.params) {
12
+ throw new Error(`Param name collision: "${key}" is used in both the subquery/CTE and outer query`);
13
+ }
14
+ ctx.params[key] = source[key];
15
+ ctx.externalParams.add(key);
16
+ }
17
+ }
18
+ export function renderValue(value, ctx) {
19
+ if (value instanceof Subquery) {
20
+ mergeParams(ctx, value.subqueryParams);
21
+ return value.sql;
22
+ }
23
+ if (value instanceof Param) {
24
+ if (ctx.externalParams.has(value.name)) {
25
+ throw new Error(`Param name collision: "${value.name}" is used in both the subquery/CTE and outer query`);
26
+ }
27
+ ctx.params[value.name] = undefined;
28
+ return value.toString();
29
+ }
30
+ if (value instanceof Expression) {
31
+ return value.sql;
32
+ }
33
+ // Only numbers reach here (from limit/offset)
34
+ return String(value);
35
+ }
36
+ export function renderWhereClause(w, ctx) {
37
+ switch (w.kind) {
38
+ case 'comparison':
39
+ return `${w.column} ${w.op} ${renderValue(w.value, ctx)}`;
40
+ case 'unary':
41
+ return `${w.column} ${w.op}`;
42
+ case 'between':
43
+ return `${w.column} ${w.op} ${renderValue(w.low, ctx)} AND ${renderValue(w.high, ctx)}`;
44
+ case 'expression': {
45
+ if (w.expr instanceof ConditionGroup) {
46
+ for (const p of w.expr.params) {
47
+ if (ctx.externalParams.has(p.name)) {
48
+ throw new Error(`Param name collision: "${p.name}" is used in both the subquery/CTE and outer query`);
49
+ }
50
+ ctx.params[p.name] = undefined;
51
+ }
52
+ }
53
+ return w.expr.sql;
54
+ }
55
+ }
56
+ }
57
+ /** Valid SQL identifier pattern (settings keys, CTE names, cluster names, column names). */
58
+ export const VALID_IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
59
+ //# sourceMappingURL=compile-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-utils.js","sourceRoot":"","sources":["../../src/query/compile-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Type-safe DELETE builder for ClickHouse.
3
+ *
4
+ * ClickHouse uses ALTER TABLE ... DELETE WHERE syntax.
5
+ * All values in WHERE must be Param or Expression — no raw strings.
6
+ */
7
+ import type { BetweenOp, ColumnName, CompiledQuery, ComparisonOp, DatabaseSchema, SetOp, TableName, UnaryOp } from './types.js';
8
+ import { Expression } from './expressions.js';
9
+ import { Param } from './param.js';
10
+ export declare class DeleteBuilder<DB extends DatabaseSchema, T extends TableName<DB> = TableName<DB>> {
11
+ private _table;
12
+ private _cluster?;
13
+ private _wheres;
14
+ constructor(table: T);
15
+ /** Specify the cluster for distributed deletes: ALTER TABLE ... ON CLUSTER ... */
16
+ onCluster(cluster: string): this;
17
+ where(column: ColumnName<DB, T> | Expression | string, op: ComparisonOp, value: Param | Expression): this;
18
+ where(column: ColumnName<DB, T> | Expression | string, op: SetOp, value: Param | Expression): this;
19
+ where(column: ColumnName<DB, T> | Expression | string, op: UnaryOp): this;
20
+ where(column: ColumnName<DB, T> | Expression | string, op: BetweenOp, value: [Param | Expression, Param | Expression]): this;
21
+ where(condition: Expression): this;
22
+ compile(): CompiledQuery;
23
+ }
24
+ //# sourceMappingURL=delete-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-builder.d.ts","sourceRoot":"","sources":["../../src/query/delete-builder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,KAAK,EACL,SAAS,EACT,OAAO,EAER,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAQnC,qBAAa,aAAa,CACxB,EAAE,SAAS,cAAc,EACzB,CAAC,SAAS,SAAS,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;IAEvC,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAqB;gBAExB,KAAK,EAAE,CAAC;IAIpB,kFAAkF;IAClF,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQhC,KAAK,CACH,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,UAAU,GAAG,MAAM,EAC/C,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,KAAK,GAAG,UAAU,GACxB,IAAI;IACP,KAAK,CACH,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,UAAU,GAAG,MAAM,EAC/C,EAAE,EAAE,KAAK,EACT,KAAK,EAAE,KAAK,GAAG,UAAU,GACxB,IAAI;IACP,KAAK,CACH,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,UAAU,GAAG,MAAM,EAC/C,EAAE,EAAE,OAAO,GACV,IAAI;IACP,KAAK,CACH,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,UAAU,GAAG,MAAM,EAC/C,EAAE,EAAE,SAAS,EACb,KAAK,EAAE,CAAC,KAAK,GAAG,UAAU,EAAE,KAAK,GAAG,UAAU,CAAC,GAC9C,IAAI;IACP,KAAK,CAAC,SAAS,EAAE,UAAU,GAAG,IAAI;IAUlC,OAAO,IAAI,aAAa;CAazB"}