@hypequery/clickhouse 2.0.1 → 2.0.2
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/core/tests/integration/test-data.json +190 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +2 -1
- package/dist/datasets.d.ts +41 -0
- package/dist/datasets.d.ts.map +1 -0
- package/dist/datasets.js +387 -0
- package/dist/migrations/config/index.d.ts +3 -0
- package/dist/migrations/config/index.d.ts.map +1 -0
- package/dist/migrations/config/index.js +1 -0
- package/dist/migrations/config/types.d.ts +45 -0
- package/dist/migrations/config/types.d.ts.map +1 -0
- package/dist/migrations/config/types.js +28 -0
- package/dist/migrations/diff/diff.d.ts +11 -0
- package/dist/migrations/diff/diff.d.ts.map +1 -0
- package/dist/migrations/diff/diff.js +240 -0
- package/dist/migrations/diff/index.d.ts +3 -0
- package/dist/migrations/diff/index.d.ts.map +1 -0
- package/dist/migrations/diff/index.js +1 -0
- package/dist/migrations/diff/types.d.ts +74 -0
- package/dist/migrations/diff/types.d.ts.map +1 -0
- package/dist/migrations/diff/types.js +1 -0
- package/dist/migrations/introspect/index.d.ts +3 -0
- package/dist/migrations/introspect/index.d.ts.map +1 -0
- package/dist/migrations/introspect/index.js +1 -0
- package/dist/migrations/introspect/pull-schema.d.ts +23 -0
- package/dist/migrations/introspect/pull-schema.d.ts.map +1 -0
- package/dist/migrations/introspect/pull-schema.js +135 -0
- package/dist/migrations/plan/index.d.ts +3 -0
- package/dist/migrations/plan/index.d.ts.map +1 -0
- package/dist/migrations/plan/index.js +1 -0
- package/dist/migrations/plan/plan.d.ts +12 -0
- package/dist/migrations/plan/plan.d.ts.map +1 -0
- package/dist/migrations/plan/plan.js +416 -0
- package/dist/migrations/plan/types.d.ts +93 -0
- package/dist/migrations/plan/types.d.ts.map +1 -0
- package/dist/migrations/plan/types.js +1 -0
- package/dist/migrations/schema/column.d.ts +71 -0
- package/dist/migrations/schema/column.d.ts.map +1 -0
- package/dist/migrations/schema/column.js +123 -0
- package/dist/migrations/schema/define.d.ts +24 -0
- package/dist/migrations/schema/define.d.ts.map +1 -0
- package/dist/migrations/schema/define.js +47 -0
- package/dist/migrations/schema/index.d.ts +4 -0
- package/dist/migrations/schema/index.d.ts.map +1 -0
- package/dist/migrations/schema/index.js +2 -0
- package/dist/migrations/schema/types.d.ts +74 -0
- package/dist/migrations/schema/types.d.ts.map +1 -0
- package/dist/migrations/schema/types.js +1 -0
- package/dist/migrations/snapshot/index.d.ts +3 -0
- package/dist/migrations/snapshot/index.d.ts.map +1 -0
- package/dist/migrations/snapshot/index.js +1 -0
- package/dist/migrations/snapshot/serialize.d.ts +21 -0
- package/dist/migrations/snapshot/serialize.d.ts.map +1 -0
- package/dist/migrations/snapshot/serialize.js +127 -0
- package/dist/migrations/snapshot/types.d.ts +47 -0
- package/dist/migrations/snapshot/types.d.ts.map +1 -0
- package/dist/migrations/snapshot/types.js +1 -0
- package/dist/migrations/sql/index.d.ts +4 -0
- package/dist/migrations/sql/index.d.ts.map +1 -0
- package/dist/migrations/sql/index.js +2 -0
- package/dist/migrations/sql/render.d.ts +10 -0
- package/dist/migrations/sql/render.d.ts.map +1 -0
- package/dist/migrations/sql/render.js +347 -0
- package/dist/migrations/sql/types.d.ts +53 -0
- package/dist/migrations/sql/types.d.ts.map +1 -0
- package/dist/migrations/sql/types.js +1 -0
- package/dist/migrations/sql/write.d.ts +10 -0
- package/dist/migrations/sql/write.d.ts.map +1 -0
- package/dist/migrations/sql/write.js +35 -0
- package/dist/semantic-backend.d.ts +7 -0
- package/dist/semantic-backend.d.ts.map +1 -0
- package/dist/semantic-backend.js +208 -0
- package/package.json +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { isSQLExpression } from '../../dataset/sql-tag.js';
|
|
2
|
+
/**
|
|
3
|
+
* Immutable builder for ClickHouse column definitions.
|
|
4
|
+
*
|
|
5
|
+
* Each modifier returns a new builder so reusable column fragments can be shared
|
|
6
|
+
* safely without later calls mutating earlier definitions.
|
|
7
|
+
*/
|
|
8
|
+
export class ClickHouseColumnBuilder {
|
|
9
|
+
columnType;
|
|
10
|
+
defaultExpression;
|
|
11
|
+
constructor(columnType, defaultExpression) {
|
|
12
|
+
this.columnType = columnType;
|
|
13
|
+
this.defaultExpression = defaultExpression;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Adds a column default.
|
|
17
|
+
*
|
|
18
|
+
* Primitive values are rendered as SQL literals. Use the `sql` template tag for
|
|
19
|
+
* database expressions such as `sql\`now()\``.
|
|
20
|
+
*/
|
|
21
|
+
default(expression) {
|
|
22
|
+
return new ClickHouseColumnBuilder(this.columnType, toDefaultValue(expression));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Wraps this column type in `Nullable(...)`.
|
|
26
|
+
*/
|
|
27
|
+
nullable() {
|
|
28
|
+
return new ClickHouseColumnBuilder({ kind: 'nullable', inner: this.columnType }, this.defaultExpression);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Wraps this column type in `LowCardinality(...)`.
|
|
32
|
+
*/
|
|
33
|
+
lowCardinality() {
|
|
34
|
+
return new ClickHouseColumnBuilder({ kind: 'low_cardinality', inner: this.columnType }, this.defaultExpression);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Materializes the builder into a named column definition for a table AST.
|
|
38
|
+
*/
|
|
39
|
+
build(name) {
|
|
40
|
+
return {
|
|
41
|
+
name,
|
|
42
|
+
type: this.columnType,
|
|
43
|
+
...(this.defaultExpression !== undefined ? { default: this.defaultExpression } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Returns the underlying type AST for nested type builders.
|
|
48
|
+
*/
|
|
49
|
+
toColumnType() {
|
|
50
|
+
return this.columnType;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Factory helpers for common ClickHouse column types.
|
|
55
|
+
*
|
|
56
|
+
* Examples:
|
|
57
|
+
* `column.String().default('pending')`, `column.Nullable('String')`,
|
|
58
|
+
* `column.DateTime('UTC')`.
|
|
59
|
+
*/
|
|
60
|
+
export const column = {
|
|
61
|
+
Int8: () => named('Int8'),
|
|
62
|
+
Int16: () => named('Int16'),
|
|
63
|
+
Int32: () => named('Int32'),
|
|
64
|
+
Int64: () => named('Int64'),
|
|
65
|
+
Int128: () => named('Int128'),
|
|
66
|
+
Int256: () => named('Int256'),
|
|
67
|
+
UInt8: () => named('UInt8'),
|
|
68
|
+
UInt16: () => named('UInt16'),
|
|
69
|
+
UInt32: () => named('UInt32'),
|
|
70
|
+
UInt64: () => named('UInt64'),
|
|
71
|
+
UInt128: () => named('UInt128'),
|
|
72
|
+
UInt256: () => named('UInt256'),
|
|
73
|
+
Float32: () => named('Float32'),
|
|
74
|
+
Float64: () => named('Float64'),
|
|
75
|
+
Decimal: (precision, scale) => named('Decimal', precision, scale),
|
|
76
|
+
String: () => named('String'),
|
|
77
|
+
FixedString: (length) => named('FixedString', length),
|
|
78
|
+
Date: () => named('Date'),
|
|
79
|
+
DateTime: (timezone) => timezone ? named('DateTime', timezone) : named('DateTime'),
|
|
80
|
+
DateTime64: (precision, timezone) => timezone ? named('DateTime64', precision, timezone) : named('DateTime64', precision),
|
|
81
|
+
UUID: () => named('UUID'),
|
|
82
|
+
JSON: () => named('JSON'),
|
|
83
|
+
LowCardinality: (inner) => new ClickHouseColumnBuilder({
|
|
84
|
+
kind: 'low_cardinality',
|
|
85
|
+
inner: normalizeNestedColumnType(inner),
|
|
86
|
+
}),
|
|
87
|
+
Nullable: (inner) => new ClickHouseColumnBuilder({
|
|
88
|
+
kind: 'nullable',
|
|
89
|
+
inner: normalizeNestedColumnType(inner),
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
function named(name, ...argumentsList) {
|
|
93
|
+
const type = {
|
|
94
|
+
kind: 'named',
|
|
95
|
+
name,
|
|
96
|
+
...(argumentsList.length > 0 ? { arguments: argumentsList } : {}),
|
|
97
|
+
};
|
|
98
|
+
return new ClickHouseColumnBuilder(type);
|
|
99
|
+
}
|
|
100
|
+
function normalizeNestedColumnType(input) {
|
|
101
|
+
if (typeof input === 'string') {
|
|
102
|
+
return {
|
|
103
|
+
kind: 'named',
|
|
104
|
+
name: input,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (input instanceof ClickHouseColumnBuilder) {
|
|
108
|
+
return input.toColumnType();
|
|
109
|
+
}
|
|
110
|
+
return input;
|
|
111
|
+
}
|
|
112
|
+
function toDefaultValue(input) {
|
|
113
|
+
if (isSQLExpression(input)) {
|
|
114
|
+
return {
|
|
115
|
+
kind: 'sql',
|
|
116
|
+
value: input,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
kind: 'literal',
|
|
121
|
+
value: input,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ClickHouseMaterializedViewDefinition, ClickHouseMaterializedViewInputDefinition, ClickHouseSchemaAst, ClickHouseSchemaDefinition, ClickHouseTableDefinition, ClickHouseTableInputDefinition } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a schema AST from the tables and materialized views declared in code.
|
|
4
|
+
*
|
|
5
|
+
* The returned AST is intentionally not SQL yet. It is serialized into a stable
|
|
6
|
+
* snapshot first, then diffed against a previous snapshot to generate migrations.
|
|
7
|
+
*/
|
|
8
|
+
export declare function defineSchema(definition: ClickHouseSchemaDefinition): ClickHouseSchemaAst;
|
|
9
|
+
/**
|
|
10
|
+
* Defines a ClickHouse table for the migration DSL.
|
|
11
|
+
*
|
|
12
|
+
* Column builders are keyed by their final column names, which keeps the schema
|
|
13
|
+
* definition compact while preserving enough structure for snapshot diffing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function defineTable(name: string, definition: ClickHouseTableInputDefinition): ClickHouseTableDefinition;
|
|
16
|
+
/**
|
|
17
|
+
* Defines a ClickHouse materialized view and records its source-table dependency.
|
|
18
|
+
*
|
|
19
|
+
* The `from` and `to` fields may reference table definitions directly or use table
|
|
20
|
+
* names. Dependencies are used by the renderer to drop and recreate views around
|
|
21
|
+
* table mutations that could otherwise break stored SELECT definitions.
|
|
22
|
+
*/
|
|
23
|
+
export declare function defineMaterializedView(name: string, definition: ClickHouseMaterializedViewInputDefinition): ClickHouseMaterializedViewDefinition;
|
|
24
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../../src/migrations/schema/define.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oCAAoC,EACpC,yCAAyC,EACzC,mBAAmB,EACnB,0BAA0B,EAC1B,yBAAyB,EACzB,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAEpB;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,0BAA0B,GAAG,mBAAmB,CAOxF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,8BAA8B,GACzC,yBAAyB,CAQ3B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,yCAAyC,GACpD,oCAAoC,CAUtC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a schema AST from the tables and materialized views declared in code.
|
|
3
|
+
*
|
|
4
|
+
* The returned AST is intentionally not SQL yet. It is serialized into a stable
|
|
5
|
+
* snapshot first, then diffed against a previous snapshot to generate migrations.
|
|
6
|
+
*/
|
|
7
|
+
export function defineSchema(definition) {
|
|
8
|
+
return {
|
|
9
|
+
tables: [...definition.tables],
|
|
10
|
+
...(definition.materializedViews !== undefined
|
|
11
|
+
? { materializedViews: [...definition.materializedViews] }
|
|
12
|
+
: {}),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Defines a ClickHouse table for the migration DSL.
|
|
17
|
+
*
|
|
18
|
+
* Column builders are keyed by their final column names, which keeps the schema
|
|
19
|
+
* definition compact while preserving enough structure for snapshot diffing.
|
|
20
|
+
*/
|
|
21
|
+
export function defineTable(name, definition) {
|
|
22
|
+
return {
|
|
23
|
+
kind: 'table',
|
|
24
|
+
name,
|
|
25
|
+
columns: Object.entries(definition.columns).map(([columnName, builder]) => builder.build(columnName)),
|
|
26
|
+
engine: definition.engine,
|
|
27
|
+
...(definition.settings !== undefined ? { settings: definition.settings } : {}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Defines a ClickHouse materialized view and records its source-table dependency.
|
|
32
|
+
*
|
|
33
|
+
* The `from` and `to` fields may reference table definitions directly or use table
|
|
34
|
+
* names. Dependencies are used by the renderer to drop and recreate views around
|
|
35
|
+
* table mutations that could otherwise break stored SELECT definitions.
|
|
36
|
+
*/
|
|
37
|
+
export function defineMaterializedView(name, definition) {
|
|
38
|
+
return {
|
|
39
|
+
kind: 'materialized_view',
|
|
40
|
+
name,
|
|
41
|
+
from: typeof definition.from === 'string' ? definition.from : definition.from.name,
|
|
42
|
+
...(definition.to !== undefined
|
|
43
|
+
? { to: typeof definition.to === 'string' ? definition.to : definition.to.name }
|
|
44
|
+
: {}),
|
|
45
|
+
select: definition.select,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { column, ClickHouseColumnBuilder } from './column.js';
|
|
2
|
+
export { defineMaterializedView, defineSchema, defineTable } from './define.js';
|
|
3
|
+
export type { ClickHouseColumnBuilderLike, ClickHouseColumnDefaultValue, ClickHouseColumnDefinition, ClickHouseColumnType, ClickHouseDefaultInput, ClickHouseLowCardinalityColumnType, ClickHouseLiteralDefaultValue, ClickHouseMaterializedViewDefinition, ClickHouseMaterializedViewInputDefinition, ClickHouseNamedColumnType, ClickHouseNullableColumnType, ClickHouseSqlDefaultValue, ClickHouseSchemaAst, ClickHouseSchemaDefinition, ClickHouseSqlExpression, ClickHouseTableDefinition, ClickHouseTableInputDefinition, ClickHouseTableEngine, } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/migrations/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEhF,YAAY,EACV,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACtB,kCAAkC,EAClC,6BAA6B,EAC7B,oCAAoC,EACpC,yCAAyC,EACzC,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,yBAAyB,EACzB,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { SQLExpression } from '../../dataset/sql-tag.js';
|
|
2
|
+
export type ClickHouseSqlExpression = string | SQLExpression;
|
|
3
|
+
export type ClickHouseDefaultInput = string | number | boolean | null | SQLExpression;
|
|
4
|
+
export interface ClickHouseSchemaAst {
|
|
5
|
+
tables: ClickHouseTableDefinition[];
|
|
6
|
+
materializedViews?: ClickHouseMaterializedViewDefinition[];
|
|
7
|
+
}
|
|
8
|
+
export interface ClickHouseSchemaDefinition {
|
|
9
|
+
tables: ClickHouseTableDefinition[];
|
|
10
|
+
materializedViews?: ClickHouseMaterializedViewDefinition[];
|
|
11
|
+
}
|
|
12
|
+
export interface ClickHouseTableDefinition {
|
|
13
|
+
kind: 'table';
|
|
14
|
+
name: string;
|
|
15
|
+
columns: ClickHouseColumnDefinition[];
|
|
16
|
+
engine: ClickHouseTableEngine;
|
|
17
|
+
settings?: Record<string, string | number | boolean>;
|
|
18
|
+
}
|
|
19
|
+
export interface ClickHouseTableInputDefinition {
|
|
20
|
+
columns: Record<string, ClickHouseColumnBuilderLike>;
|
|
21
|
+
engine: ClickHouseTableEngine;
|
|
22
|
+
settings?: Record<string, string | number | boolean>;
|
|
23
|
+
}
|
|
24
|
+
export interface ClickHouseColumnDefinition {
|
|
25
|
+
name: string;
|
|
26
|
+
type: ClickHouseColumnType;
|
|
27
|
+
default?: ClickHouseColumnDefaultValue;
|
|
28
|
+
}
|
|
29
|
+
export interface ClickHouseColumnBuilderLike {
|
|
30
|
+
build(name: string): ClickHouseColumnDefinition;
|
|
31
|
+
}
|
|
32
|
+
export type ClickHouseColumnDefaultValue = ClickHouseLiteralDefaultValue | ClickHouseSqlDefaultValue;
|
|
33
|
+
export interface ClickHouseLiteralDefaultValue {
|
|
34
|
+
kind: 'literal';
|
|
35
|
+
value: string | number | boolean | null;
|
|
36
|
+
}
|
|
37
|
+
export interface ClickHouseSqlDefaultValue {
|
|
38
|
+
kind: 'sql';
|
|
39
|
+
value: ClickHouseSqlExpression;
|
|
40
|
+
}
|
|
41
|
+
export type ClickHouseColumnType = ClickHouseNamedColumnType | ClickHouseNullableColumnType | ClickHouseLowCardinalityColumnType;
|
|
42
|
+
export interface ClickHouseNamedColumnType {
|
|
43
|
+
kind: 'named';
|
|
44
|
+
name: string;
|
|
45
|
+
arguments?: Array<string | number>;
|
|
46
|
+
}
|
|
47
|
+
export interface ClickHouseNullableColumnType {
|
|
48
|
+
kind: 'nullable';
|
|
49
|
+
inner: ClickHouseColumnType;
|
|
50
|
+
}
|
|
51
|
+
export interface ClickHouseLowCardinalityColumnType {
|
|
52
|
+
kind: 'low_cardinality';
|
|
53
|
+
inner: ClickHouseColumnType;
|
|
54
|
+
}
|
|
55
|
+
export interface ClickHouseTableEngine {
|
|
56
|
+
type: string;
|
|
57
|
+
orderBy?: ClickHouseSqlExpression[];
|
|
58
|
+
partitionBy?: ClickHouseSqlExpression;
|
|
59
|
+
primaryKey?: ClickHouseSqlExpression[];
|
|
60
|
+
sampleBy?: ClickHouseSqlExpression;
|
|
61
|
+
}
|
|
62
|
+
export interface ClickHouseMaterializedViewDefinition {
|
|
63
|
+
kind: 'materialized_view';
|
|
64
|
+
name: string;
|
|
65
|
+
from: string;
|
|
66
|
+
to?: string;
|
|
67
|
+
select: ClickHouseSqlExpression;
|
|
68
|
+
}
|
|
69
|
+
export interface ClickHouseMaterializedViewInputDefinition {
|
|
70
|
+
from: string | ClickHouseTableDefinition;
|
|
71
|
+
to?: string | ClickHouseTableDefinition;
|
|
72
|
+
select: ClickHouseSqlExpression;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/migrations/schema/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,aAAa,CAAC;AAC7D,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,aAAa,CAAC;AAEtF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,yBAAyB,EAAE,CAAC;IACpC,iBAAiB,CAAC,EAAE,oCAAoC,EAAE,CAAC;CAC5D;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,yBAAyB,EAAE,CAAC;IACpC,iBAAiB,CAAC,EAAE,oCAAoC,EAAE,CAAC;CAC5D;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACrD,MAAM,EAAE,qBAAqB,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,CAAC,EAAE,4BAA4B,CAAC;CACxC;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,0BAA0B,CAAC;CACjD;AAED,MAAM,MAAM,4BAA4B,GACpC,6BAA6B,GAC7B,yBAAyB,CAAC;AAE9B,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,uBAAuB,CAAC;CAChC;AAED,MAAM,MAAM,oBAAoB,GAC5B,yBAAyB,GACzB,4BAA4B,GAC5B,kCAAkC,CAAC;AAEvC,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAED,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,iBAAiB,CAAC;IACxB,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,uBAAuB,CAAC;CACpC;AAED,MAAM,WAAW,oCAAoC;IACnD,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,uBAAuB,CAAC;CACjC;AAED,MAAM,WAAW,yCAAyC;IACxD,IAAI,EAAE,MAAM,GAAG,yBAAyB,CAAC;IACzC,EAAE,CAAC,EAAE,MAAM,GAAG,yBAAyB,CAAC;IACxC,MAAM,EAAE,uBAAuB,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { hashSnapshot, serializeSchemaToSnapshot, snapshotToStableJson, } from './serialize.js';
|
|
2
|
+
export type { Snapshot, SnapshotColumn, SnapshotColumnDefault, SnapshotDependencyEdge, SnapshotMaterializedView, SnapshotTable, SnapshotTableEngine, } from './types.js';
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/migrations/snapshot/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,aAAa,EACb,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { hashSnapshot, serializeSchemaToSnapshot, snapshotToStableJson, } from './serialize.js';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ClickHouseSchemaAst } from '../schema/types.js';
|
|
2
|
+
import type { Snapshot } from './types.js';
|
|
3
|
+
type SnapshotWithoutHash = Omit<Snapshot, 'contentHash'>;
|
|
4
|
+
/**
|
|
5
|
+
* Converts a schema AST into a deterministic ClickHouse snapshot.
|
|
6
|
+
*
|
|
7
|
+
* Snapshot serialization normalizes ordering, SQL-expression whitespace, type
|
|
8
|
+
* wrappers, settings, and materialized-view dependencies before computing the
|
|
9
|
+
* content hash used by migration metadata.
|
|
10
|
+
*/
|
|
11
|
+
export declare function serializeSchemaToSnapshot(schema: ClickHouseSchemaAst): Snapshot;
|
|
12
|
+
/**
|
|
13
|
+
* Serializes a snapshot with stable formatting for writing to disk and hashing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function snapshotToStableJson(snapshot: Snapshot | SnapshotWithoutHash): string;
|
|
16
|
+
/**
|
|
17
|
+
* Computes the SHA-256 content hash for a normalized snapshot.
|
|
18
|
+
*/
|
|
19
|
+
export declare function hashSnapshot(snapshot: Snapshot | SnapshotWithoutHash): string;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../../src/migrations/snapshot/serialize.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAGV,mBAAmB,EAEpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,QAAQ,EAMT,MAAM,YAAY,CAAC;AAEpB,KAAK,mBAAmB,GAAG,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,GAAG,QAAQ,CA6D/E;AAgBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,mBAAmB,GAAG,MAAM,CAErF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,mBAAmB,GAAG,MAAM,CAE7E"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { isSQLExpression } from '../../dataset/sql-tag.js';
|
|
3
|
+
/**
|
|
4
|
+
* Converts a schema AST into a deterministic ClickHouse snapshot.
|
|
5
|
+
*
|
|
6
|
+
* Snapshot serialization normalizes ordering, SQL-expression whitespace, type
|
|
7
|
+
* wrappers, settings, and materialized-view dependencies before computing the
|
|
8
|
+
* content hash used by migration metadata.
|
|
9
|
+
*/
|
|
10
|
+
export function serializeSchemaToSnapshot(schema) {
|
|
11
|
+
const snapshot = {
|
|
12
|
+
version: 1,
|
|
13
|
+
dialect: 'clickhouse',
|
|
14
|
+
tables: [...schema.tables]
|
|
15
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
16
|
+
.map((table) => ({
|
|
17
|
+
name: table.name,
|
|
18
|
+
columns: [...table.columns]
|
|
19
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
20
|
+
.map((column) => ({
|
|
21
|
+
name: column.name,
|
|
22
|
+
type: normalizeColumnType(column.type),
|
|
23
|
+
...(column.default !== undefined
|
|
24
|
+
? { default: normalizeColumnDefault(column.default) }
|
|
25
|
+
: {}),
|
|
26
|
+
})),
|
|
27
|
+
engine: {
|
|
28
|
+
type: table.engine.type,
|
|
29
|
+
orderBy: (table.engine.orderBy ?? []).map(normalizeSqlExpression),
|
|
30
|
+
...(table.engine.partitionBy !== undefined
|
|
31
|
+
? { partitionBy: normalizeSqlExpression(table.engine.partitionBy) }
|
|
32
|
+
: {}),
|
|
33
|
+
primaryKey: (table.engine.primaryKey ?? []).map(normalizeSqlExpression),
|
|
34
|
+
...(table.engine.sampleBy !== undefined
|
|
35
|
+
? { sampleBy: normalizeSqlExpression(table.engine.sampleBy) }
|
|
36
|
+
: {}),
|
|
37
|
+
},
|
|
38
|
+
settings: Object.fromEntries(Object.entries(table.settings ?? {})
|
|
39
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
40
|
+
.map(([key, value]) => [key, String(value)])),
|
|
41
|
+
})),
|
|
42
|
+
materializedViews: [...(schema.materializedViews ?? [])]
|
|
43
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
44
|
+
.map((view) => ({
|
|
45
|
+
name: view.name,
|
|
46
|
+
from: view.from,
|
|
47
|
+
...(view.to !== undefined ? { to: view.to } : {}),
|
|
48
|
+
select: normalizeSqlExpression(view.select),
|
|
49
|
+
})),
|
|
50
|
+
dependencies: [...(schema.materializedViews ?? [])]
|
|
51
|
+
.sort((left, right) => left.name.localeCompare(right.name))
|
|
52
|
+
.map((view) => ({
|
|
53
|
+
from: view.from,
|
|
54
|
+
to: view.name,
|
|
55
|
+
kind: 'table_to_materialized_view',
|
|
56
|
+
})),
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
...snapshot,
|
|
60
|
+
contentHash: hashSnapshot(snapshot),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function normalizeColumnDefault(defaultValue) {
|
|
64
|
+
if (defaultValue.kind === 'literal') {
|
|
65
|
+
return {
|
|
66
|
+
kind: 'literal',
|
|
67
|
+
value: defaultValue.value,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
kind: 'sql',
|
|
72
|
+
value: normalizeSqlExpression(defaultValue.value),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Serializes a snapshot with stable formatting for writing to disk and hashing.
|
|
77
|
+
*/
|
|
78
|
+
export function snapshotToStableJson(snapshot) {
|
|
79
|
+
return JSON.stringify(snapshot, null, 2);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Computes the SHA-256 content hash for a normalized snapshot.
|
|
83
|
+
*/
|
|
84
|
+
export function hashSnapshot(snapshot) {
|
|
85
|
+
return createHash('sha256').update(snapshotToStableJson(snapshot)).digest('hex');
|
|
86
|
+
}
|
|
87
|
+
function normalizeColumnType(type) {
|
|
88
|
+
switch (type.kind) {
|
|
89
|
+
case 'named': {
|
|
90
|
+
const args = type.arguments?.length ? `(${type.arguments.join(', ')})` : '';
|
|
91
|
+
return `${type.name}${args}`;
|
|
92
|
+
}
|
|
93
|
+
case 'nullable':
|
|
94
|
+
return `Nullable(${normalizeColumnType(type.inner)})`;
|
|
95
|
+
case 'low_cardinality':
|
|
96
|
+
return `LowCardinality(${normalizeColumnType(type.inner)})`;
|
|
97
|
+
default: {
|
|
98
|
+
const exhaustiveCheck = type;
|
|
99
|
+
return exhaustiveCheck;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function normalizeSqlExpression(expression) {
|
|
104
|
+
const sql = typeof expression === 'string'
|
|
105
|
+
? expression
|
|
106
|
+
: isSQLExpression(expression)
|
|
107
|
+
? expression.sql
|
|
108
|
+
: String(expression);
|
|
109
|
+
const lines = sql
|
|
110
|
+
.replace(/\r\n/g, '\n')
|
|
111
|
+
.split('\n')
|
|
112
|
+
.map(line => line.replace(/\s+$/g, ''));
|
|
113
|
+
while (lines.length > 0 && lines[0].trim() === '') {
|
|
114
|
+
lines.shift();
|
|
115
|
+
}
|
|
116
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === '') {
|
|
117
|
+
lines.pop();
|
|
118
|
+
}
|
|
119
|
+
const indents = lines
|
|
120
|
+
.filter(line => line.trim().length > 0)
|
|
121
|
+
.map(line => line.match(/^\s*/)?.[0].length ?? 0);
|
|
122
|
+
const minIndent = indents.length > 0 ? Math.min(...indents) : 0;
|
|
123
|
+
return lines
|
|
124
|
+
.map(line => line.slice(minIndent))
|
|
125
|
+
.join('\n')
|
|
126
|
+
.trim();
|
|
127
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface Snapshot {
|
|
2
|
+
version: 1;
|
|
3
|
+
dialect: 'clickhouse';
|
|
4
|
+
tables: SnapshotTable[];
|
|
5
|
+
materializedViews: SnapshotMaterializedView[];
|
|
6
|
+
dependencies: SnapshotDependencyEdge[];
|
|
7
|
+
contentHash: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SnapshotTable {
|
|
10
|
+
name: string;
|
|
11
|
+
columns: SnapshotColumn[];
|
|
12
|
+
engine: SnapshotTableEngine;
|
|
13
|
+
settings: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export interface SnapshotColumn {
|
|
16
|
+
name: string;
|
|
17
|
+
type: string;
|
|
18
|
+
default?: SnapshotColumnDefault;
|
|
19
|
+
}
|
|
20
|
+
export type SnapshotColumnDefault = SnapshotLiteralColumnDefault | SnapshotSqlColumnDefault;
|
|
21
|
+
export interface SnapshotLiteralColumnDefault {
|
|
22
|
+
kind: 'literal';
|
|
23
|
+
value: string | number | boolean | null;
|
|
24
|
+
}
|
|
25
|
+
export interface SnapshotSqlColumnDefault {
|
|
26
|
+
kind: 'sql';
|
|
27
|
+
value: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SnapshotTableEngine {
|
|
30
|
+
type: string;
|
|
31
|
+
orderBy: string[];
|
|
32
|
+
partitionBy?: string;
|
|
33
|
+
primaryKey: string[];
|
|
34
|
+
sampleBy?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface SnapshotMaterializedView {
|
|
37
|
+
name: string;
|
|
38
|
+
from: string;
|
|
39
|
+
to?: string;
|
|
40
|
+
select: string;
|
|
41
|
+
}
|
|
42
|
+
export interface SnapshotDependencyEdge {
|
|
43
|
+
from: string;
|
|
44
|
+
to: string;
|
|
45
|
+
kind: 'table_to_materialized_view';
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/migrations/snapshot/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,iBAAiB,EAAE,wBAAwB,EAAE,CAAC;IAC9C,YAAY,EAAE,sBAAsB,EAAE,CAAC;IACvC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED,MAAM,MAAM,qBAAqB,GAAG,4BAA4B,GAAG,wBAAwB,CAAC;AAE5F,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,4BAA4B,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { renderMigrationArtifacts } from './render.js';
|
|
2
|
+
export { writeMigrationArtifacts } from './write.js';
|
|
3
|
+
export type { MigrationMeta, RenderMigrationArtifactsInput, RenderMigrationArtifactsOptions, RenderMigrationArtifactsResult, WriteMigrationArtifactsOptions, WriteMigrationArtifactsResult, } from './types.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAErD,YAAY,EACV,aAAa,EACb,6BAA6B,EAC7B,+BAA+B,EAC/B,8BAA8B,EAC9B,8BAA8B,EAC9B,6BAA6B,GAC9B,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RenderMigrationArtifactsInput, RenderMigrationArtifactsOptions, RenderMigrationArtifactsResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Renders a snapshot diff into reviewable migration artifacts.
|
|
4
|
+
*
|
|
5
|
+
* The renderer produces forward SQL, best-effort reverse SQL, and metadata. It
|
|
6
|
+
* also sequences dependent materialized views around table mutations so stored
|
|
7
|
+
* view SELECT definitions are dropped and recreated with the target snapshot.
|
|
8
|
+
*/
|
|
9
|
+
export declare function renderMigrationArtifacts(input: RenderMigrationArtifactsInput, options: RenderMigrationArtifactsOptions): RenderMigrationArtifactsResult;
|
|
10
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/render.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAEV,6BAA6B,EAC7B,+BAA+B,EAC/B,8BAA8B,EAG/B,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,6BAA6B,EACpC,OAAO,EAAE,+BAA+B,GACvC,8BAA8B,CAkDhC"}
|