@hypequery/clickhouse 1.3.1-beta.0 → 1.3.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/README.md +18 -1
- package/dist/cli/generate-types.js +41 -3
- package/dist/core/connection.d.ts.map +1 -1
- package/dist/core/connection.js +4 -3
- package/dist/core/cross-filter.d.ts +3 -7
- package/dist/core/cross-filter.d.ts.map +1 -1
- package/dist/core/cross-filter.js +3 -2
- package/dist/core/env/auto-client.browser.d.ts +3 -0
- package/dist/core/env/auto-client.browser.d.ts.map +1 -0
- package/dist/core/env/auto-client.browser.js +3 -0
- package/dist/core/env/auto-client.d.ts +9 -0
- package/dist/core/env/auto-client.d.ts.map +1 -0
- package/dist/core/env/auto-client.js +21 -0
- package/dist/core/features/aggregations.d.ts +18 -22
- package/dist/core/features/aggregations.d.ts.map +1 -1
- package/dist/core/features/aggregations.js +6 -6
- package/dist/core/features/analytics.d.ts +15 -19
- package/dist/core/features/analytics.d.ts.map +1 -1
- package/dist/core/features/analytics.js +2 -2
- package/dist/core/features/cross-filtering.d.ts +5 -24
- package/dist/core/features/cross-filtering.d.ts.map +1 -1
- package/dist/core/features/cross-filtering.js +0 -33
- package/dist/core/features/executor.d.ts +5 -9
- package/dist/core/features/executor.d.ts.map +1 -1
- package/dist/core/features/filtering.d.ts +32 -28
- package/dist/core/features/filtering.d.ts.map +1 -1
- package/dist/core/features/filtering.js +27 -26
- package/dist/core/features/joins.d.ts +7 -10
- package/dist/core/features/joins.d.ts.map +1 -1
- package/dist/core/features/pagination.d.ts +8 -10
- package/dist/core/features/pagination.d.ts.map +1 -1
- package/dist/core/features/pagination.js +13 -41
- package/dist/core/features/query-modifiers.d.ts +18 -21
- package/dist/core/features/query-modifiers.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.js +6 -0
- package/dist/core/join-relationships.d.ts +2 -1
- package/dist/core/join-relationships.d.ts.map +1 -1
- package/dist/core/query-builder.d.ts +50 -73
- package/dist/core/query-builder.d.ts.map +1 -1
- package/dist/core/query-builder.js +113 -92
- package/dist/core/tests/integration/setup.d.ts +1 -1
- package/dist/core/tests/test-utils.d.ts +4 -3
- package/dist/core/tests/test-utils.d.ts.map +1 -1
- package/dist/core/tests/test-utils.js +18 -8
- package/dist/core/types/builder-state.d.ts +25 -0
- package/dist/core/types/builder-state.d.ts.map +1 -0
- package/dist/core/types/builder-state.js +1 -0
- package/dist/core/types/select-types.d.ts +25 -0
- package/dist/core/types/select-types.d.ts.map +1 -0
- package/dist/core/types/select-types.js +1 -0
- package/dist/core/types/type-helpers.d.ts +5 -0
- package/dist/core/types/type-helpers.d.ts.map +1 -0
- package/dist/core/types/type-helpers.js +1 -0
- package/dist/core/utils/predicate-builder.d.ts +29 -0
- package/dist/core/utils/predicate-builder.d.ts.map +1 -0
- package/dist/core/utils/predicate-builder.js +92 -0
- package/dist/core/utils/sql-expressions.d.ts +11 -10
- package/dist/core/utils/sql-expressions.d.ts.map +1 -1
- package/dist/core/utils/sql-expressions.js +4 -2
- package/dist/core/validators/filter-validator.d.ts +2 -1
- package/dist/core/validators/filter-validator.d.ts.map +1 -1
- package/dist/core/validators/value-validator.d.ts +2 -1
- package/dist/core/validators/value-validator.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/types/base.d.ts +10 -15
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/clickhouse-types.d.ts +2 -2
- package/dist/types/clickhouse-types.d.ts.map +1 -1
- package/dist/types/filters.d.ts +1 -1
- package/dist/types/filters.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/schema.d.ts +19 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +1 -0
- package/package.json +7 -3
- package/dist/core/tests/integration/test-initializer.d.ts +0 -7
- package/dist/core/tests/integration/test-initializer.d.ts.map +0 -1
- package/dist/core/tests/integration/test-initializer.js +0 -32
|
@@ -8,26 +8,23 @@ import { ExecutorFeature } from './features/executor.js';
|
|
|
8
8
|
import { QueryModifiersFeature } from './features/query-modifiers.js';
|
|
9
9
|
import { FilterValidator } from './validators/filter-validator.js';
|
|
10
10
|
import { PaginationFeature } from './features/pagination.js';
|
|
11
|
+
import { createPredicateBuilder, } from './utils/predicate-builder.js';
|
|
11
12
|
import { CrossFilteringFeature } from './features/cross-filtering.js';
|
|
12
13
|
/**
|
|
13
14
|
* Type guard to check if a config is a client-based configuration.
|
|
14
15
|
*/
|
|
15
16
|
export function isClientConfig(config) {
|
|
16
|
-
return 'client' in config &&
|
|
17
|
+
return 'client' in config && config.client !== undefined;
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
19
20
|
* A type-safe query builder for ClickHouse databases.
|
|
20
|
-
*
|
|
21
|
-
* @template T - The schema type of the current table
|
|
22
|
-
* @template HasSelect - Whether a SELECT clause has been applied
|
|
23
|
-
* @template Aggregations - The type of any aggregation functions applied
|
|
21
|
+
* The builder carries a single state object that encodes scope, output, and schema metadata.
|
|
24
22
|
*/
|
|
25
23
|
export class QueryBuilder {
|
|
26
24
|
static relationships;
|
|
27
25
|
config = {};
|
|
28
26
|
tableName;
|
|
29
|
-
|
|
30
|
-
originalSchema;
|
|
27
|
+
state;
|
|
31
28
|
formatter = new SQLFormatter();
|
|
32
29
|
aggregations;
|
|
33
30
|
joins;
|
|
@@ -37,10 +34,9 @@ export class QueryBuilder {
|
|
|
37
34
|
modifiers;
|
|
38
35
|
pagination;
|
|
39
36
|
crossFiltering;
|
|
40
|
-
constructor(tableName,
|
|
37
|
+
constructor(tableName, state) {
|
|
41
38
|
this.tableName = tableName;
|
|
42
|
-
this.
|
|
43
|
-
this.originalSchema = originalSchema;
|
|
39
|
+
this.state = state;
|
|
44
40
|
this.aggregations = new AggregationFeature(this);
|
|
45
41
|
this.joins = new JoinFeature(this);
|
|
46
42
|
this.filtering = new FilteringFeature(this);
|
|
@@ -50,28 +46,18 @@ export class QueryBuilder {
|
|
|
50
46
|
this.pagination = new PaginationFeature(this);
|
|
51
47
|
this.crossFiltering = new CrossFilteringFeature(this);
|
|
52
48
|
}
|
|
49
|
+
fork(state, config) {
|
|
50
|
+
const builder = new QueryBuilder(this.tableName, state);
|
|
51
|
+
builder.config = { ...config };
|
|
52
|
+
return builder;
|
|
53
|
+
}
|
|
53
54
|
debug() {
|
|
54
55
|
console.log('Current Type:', {
|
|
55
|
-
|
|
56
|
-
originalSchema: this.originalSchema,
|
|
56
|
+
state: this.state,
|
|
57
57
|
config: this.config
|
|
58
58
|
});
|
|
59
59
|
return this;
|
|
60
60
|
}
|
|
61
|
-
clone() {
|
|
62
|
-
const newBuilder = new QueryBuilder(this.tableName, this.schema, this.originalSchema);
|
|
63
|
-
newBuilder.config = { ...this.config };
|
|
64
|
-
// Initialize features with the new builder
|
|
65
|
-
newBuilder.aggregations = new AggregationFeature(newBuilder);
|
|
66
|
-
newBuilder.joins = new JoinFeature(newBuilder);
|
|
67
|
-
newBuilder.filtering = new FilteringFeature(newBuilder);
|
|
68
|
-
newBuilder.analytics = new AnalyticsFeature(newBuilder);
|
|
69
|
-
newBuilder.executor = new ExecutorFeature(newBuilder);
|
|
70
|
-
newBuilder.modifiers = new QueryModifiersFeature(newBuilder);
|
|
71
|
-
newBuilder.pagination = new PaginationFeature(newBuilder);
|
|
72
|
-
newBuilder.crossFiltering = new CrossFilteringFeature(newBuilder);
|
|
73
|
-
return newBuilder;
|
|
74
|
-
}
|
|
75
61
|
// --- Analytics Helper: Add a CTE.
|
|
76
62
|
withCTE(alias, subquery) {
|
|
77
63
|
this.config = this.analytics.addCTE(alias, subquery);
|
|
@@ -90,7 +76,7 @@ export class QueryBuilder {
|
|
|
90
76
|
* @returns The current QueryBuilder instance.
|
|
91
77
|
*/
|
|
92
78
|
groupByTimeInterval(column, interval, method = 'toStartOfInterval') {
|
|
93
|
-
this.config = this.analytics.addTimeInterval(column, interval, method);
|
|
79
|
+
this.config = this.analytics.addTimeInterval(String(column), interval, method);
|
|
94
80
|
return this;
|
|
95
81
|
}
|
|
96
82
|
// --- Analytics Helper: Add a raw SQL fragment.
|
|
@@ -116,23 +102,34 @@ export class QueryBuilder {
|
|
|
116
102
|
this.config = this.crossFiltering.applyCrossFilters(crossFilter);
|
|
117
103
|
return this;
|
|
118
104
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
105
|
+
select(columnsOrAsterisk) {
|
|
106
|
+
if (columnsOrAsterisk === '*') {
|
|
107
|
+
const nextState = {
|
|
108
|
+
...this.state,
|
|
109
|
+
output: {}
|
|
110
|
+
};
|
|
111
|
+
const nextConfig = {
|
|
112
|
+
...this.config,
|
|
113
|
+
select: ['*'],
|
|
114
|
+
orderBy: this.config.orderBy?.map(({ column, direction }) => ({
|
|
115
|
+
column: String(column),
|
|
116
|
+
direction
|
|
117
|
+
}))
|
|
118
|
+
};
|
|
119
|
+
return this.fork(nextState, nextConfig);
|
|
120
|
+
}
|
|
121
|
+
const columns = columnsOrAsterisk;
|
|
122
|
+
const processedColumns = columns.map(col => {
|
|
123
|
+
if (typeof col === 'object' && col !== null && '__type' in col) {
|
|
124
|
+
return col.toSql();
|
|
125
|
+
}
|
|
126
|
+
return String(col);
|
|
127
|
+
});
|
|
128
|
+
const nextState = {
|
|
129
|
+
...this.state,
|
|
130
|
+
output: {}
|
|
131
|
+
};
|
|
132
|
+
const nextConfig = {
|
|
136
133
|
...this.config,
|
|
137
134
|
select: processedColumns,
|
|
138
135
|
orderBy: this.config.orderBy?.map(({ column, direction }) => ({
|
|
@@ -140,32 +137,35 @@ export class QueryBuilder {
|
|
|
140
137
|
direction
|
|
141
138
|
}))
|
|
142
139
|
};
|
|
143
|
-
return
|
|
140
|
+
return this.fork(nextState, nextConfig);
|
|
141
|
+
}
|
|
142
|
+
selectConst(...columns) {
|
|
143
|
+
return this.select(columns);
|
|
144
144
|
}
|
|
145
145
|
sum(column, alias) {
|
|
146
|
-
|
|
147
|
-
newBuilder.config = this.aggregations.sum(column, alias);
|
|
148
|
-
return newBuilder;
|
|
146
|
+
return this.applyAggregation(column, alias, 'sum', (col, finalAlias) => this.aggregations.sum(col, finalAlias));
|
|
149
147
|
}
|
|
150
148
|
count(column, alias) {
|
|
151
|
-
|
|
152
|
-
newBuilder.config = this.aggregations.count(column, alias);
|
|
153
|
-
return newBuilder;
|
|
149
|
+
return this.applyAggregation(column, alias, 'count', (col, finalAlias) => this.aggregations.count(col, finalAlias));
|
|
154
150
|
}
|
|
155
151
|
avg(column, alias) {
|
|
156
|
-
|
|
157
|
-
newBuilder.config = this.aggregations.avg(column, alias);
|
|
158
|
-
return newBuilder;
|
|
152
|
+
return this.applyAggregation(column, alias, 'avg', (col, finalAlias) => this.aggregations.avg(col, finalAlias));
|
|
159
153
|
}
|
|
160
154
|
min(column, alias) {
|
|
161
|
-
|
|
162
|
-
newBuilder.config = this.aggregations.min(column, alias);
|
|
163
|
-
return newBuilder;
|
|
155
|
+
return this.applyAggregation(column, alias, 'min', (col, finalAlias) => this.aggregations.min(col, finalAlias));
|
|
164
156
|
}
|
|
165
157
|
max(column, alias) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
158
|
+
return this.applyAggregation(column, alias, 'max', (col, finalAlias) => this.aggregations.max(col, finalAlias));
|
|
159
|
+
}
|
|
160
|
+
applyAggregation(column, alias, suffix, updater) {
|
|
161
|
+
const columnName = String(column);
|
|
162
|
+
const finalAlias = (alias || `${columnName}_${suffix}`);
|
|
163
|
+
const nextState = {
|
|
164
|
+
...this.state,
|
|
165
|
+
output: {}
|
|
166
|
+
};
|
|
167
|
+
const nextConfig = updater(columnName, finalAlias);
|
|
168
|
+
return this.fork(nextState, nextConfig);
|
|
169
169
|
}
|
|
170
170
|
// Make needed properties accessible to features
|
|
171
171
|
getTableName() {
|
|
@@ -223,39 +223,52 @@ export class QueryBuilder {
|
|
|
223
223
|
if (advancedInOperators.includes(operator)) {
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
226
|
-
|
|
226
|
+
const columnName = String(column);
|
|
227
|
+
if (FilterValidator.validateJoinedColumn(columnName))
|
|
227
228
|
return;
|
|
228
|
-
const
|
|
229
|
-
|
|
229
|
+
const baseColumns = this.state.base;
|
|
230
|
+
const columnType = baseColumns[columnName];
|
|
231
|
+
FilterValidator.validateFilterCondition({ column: columnName, operator, value }, columnType);
|
|
230
232
|
}
|
|
231
233
|
where(columnOrColumns, operator, value) {
|
|
234
|
+
if (typeof columnOrColumns === 'function') {
|
|
235
|
+
const expression = columnOrColumns(createPredicateBuilder());
|
|
236
|
+
this.config = this.filtering.addExpressionCondition('AND', expression);
|
|
237
|
+
return this;
|
|
238
|
+
}
|
|
239
|
+
if (operator === undefined) {
|
|
240
|
+
throw new Error('Operator is required when specifying a column for where()');
|
|
241
|
+
}
|
|
232
242
|
// Handle tuple operations
|
|
233
243
|
if (Array.isArray(columnOrColumns) && (operator === 'inTuple' || operator === 'globalInTuple')) {
|
|
234
|
-
// For tuple operations, we need to handle the column array specially
|
|
235
244
|
const columns = columnOrColumns;
|
|
236
245
|
this.validateFilterValue(columns, operator, value);
|
|
237
|
-
this.config = this.filtering.addCondition('AND', columns, operator, value);
|
|
246
|
+
this.config = this.filtering.addCondition('AND', columns.map(String), operator, value);
|
|
238
247
|
return this;
|
|
239
248
|
}
|
|
240
|
-
// Handle regular operations
|
|
241
249
|
const column = columnOrColumns;
|
|
242
250
|
this.validateFilterValue(column, operator, value);
|
|
243
|
-
this.config = this.filtering.addCondition('AND', column, operator, value);
|
|
251
|
+
this.config = this.filtering.addCondition('AND', String(column), operator, value);
|
|
244
252
|
return this;
|
|
245
253
|
}
|
|
246
254
|
orWhere(columnOrColumns, operator, value) {
|
|
247
|
-
|
|
255
|
+
if (typeof columnOrColumns === 'function') {
|
|
256
|
+
const expression = columnOrColumns(createPredicateBuilder());
|
|
257
|
+
this.config = this.filtering.addExpressionCondition('OR', expression);
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
if (operator === undefined) {
|
|
261
|
+
throw new Error('Operator is required when specifying a column for orWhere()');
|
|
262
|
+
}
|
|
248
263
|
if (Array.isArray(columnOrColumns) && (operator === 'inTuple' || operator === 'globalInTuple')) {
|
|
249
|
-
// For tuple operations, we need to handle the column array specially
|
|
250
264
|
const columns = columnOrColumns;
|
|
251
265
|
this.validateFilterValue(columns, operator, value);
|
|
252
|
-
this.config = this.filtering.addCondition('OR', columns, operator, value);
|
|
266
|
+
this.config = this.filtering.addCondition('OR', columns.map(String), operator, value);
|
|
253
267
|
return this;
|
|
254
268
|
}
|
|
255
|
-
// Handle regular operations
|
|
256
269
|
const column = columnOrColumns;
|
|
257
270
|
this.validateFilterValue(column, operator, value);
|
|
258
|
-
this.config = this.filtering.addCondition('OR', column, operator, value);
|
|
271
|
+
this.config = this.filtering.addCondition('OR', String(column), operator, value);
|
|
259
272
|
return this;
|
|
260
273
|
}
|
|
261
274
|
/**
|
|
@@ -302,7 +315,8 @@ export class QueryBuilder {
|
|
|
302
315
|
* ```
|
|
303
316
|
*/
|
|
304
317
|
groupBy(columns) {
|
|
305
|
-
|
|
318
|
+
const normalized = Array.isArray(columns) ? columns.map(String) : String(columns);
|
|
319
|
+
this.config = this.modifiers.addGroupBy(normalized);
|
|
306
320
|
return this;
|
|
307
321
|
}
|
|
308
322
|
limit(count) {
|
|
@@ -324,7 +338,7 @@ export class QueryBuilder {
|
|
|
324
338
|
* ```
|
|
325
339
|
*/
|
|
326
340
|
orderBy(column, direction = 'ASC') {
|
|
327
|
-
this.config = this.modifiers.addOrderBy(column, direction);
|
|
341
|
+
this.config = this.modifiers.addOrderBy(String(column), direction);
|
|
328
342
|
return this;
|
|
329
343
|
}
|
|
330
344
|
/**
|
|
@@ -351,24 +365,24 @@ export class QueryBuilder {
|
|
|
351
365
|
return this.where(column, 'between', [min, max]);
|
|
352
366
|
}
|
|
353
367
|
innerJoin(table, leftColumn, rightColumn, alias) {
|
|
354
|
-
|
|
355
|
-
newBuilder.config = this.joins.addJoin('INNER', table, leftColumn, rightColumn, alias);
|
|
356
|
-
return newBuilder;
|
|
368
|
+
return this.applyJoin('INNER', table, leftColumn, rightColumn, alias);
|
|
357
369
|
}
|
|
358
370
|
leftJoin(table, leftColumn, rightColumn, alias) {
|
|
359
|
-
|
|
360
|
-
newBuilder.config = this.joins.addJoin('LEFT', table, leftColumn, rightColumn, alias);
|
|
361
|
-
return newBuilder;
|
|
371
|
+
return this.applyJoin('LEFT', table, leftColumn, rightColumn, alias);
|
|
362
372
|
}
|
|
363
373
|
rightJoin(table, leftColumn, rightColumn, alias) {
|
|
364
|
-
|
|
365
|
-
newBuilder.config = this.joins.addJoin('RIGHT', table, leftColumn, rightColumn, alias);
|
|
366
|
-
return newBuilder;
|
|
374
|
+
return this.applyJoin('RIGHT', table, leftColumn, rightColumn, alias);
|
|
367
375
|
}
|
|
368
376
|
fullJoin(table, leftColumn, rightColumn, alias) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
377
|
+
return this.applyJoin('FULL', table, leftColumn, rightColumn, alias);
|
|
378
|
+
}
|
|
379
|
+
applyJoin(type, table, leftColumn, rightColumn, alias) {
|
|
380
|
+
const nextState = {
|
|
381
|
+
...this.state,
|
|
382
|
+
aliases: alias ? { ...this.state.aliases, [alias]: table } : this.state.aliases
|
|
383
|
+
};
|
|
384
|
+
const nextConfig = this.joins.addJoin(type, table, String(leftColumn), rightColumn, alias);
|
|
385
|
+
return this.fork(nextState, nextConfig);
|
|
372
386
|
}
|
|
373
387
|
// Make config accessible to features
|
|
374
388
|
getConfig() {
|
|
@@ -412,7 +426,8 @@ export class QueryBuilder {
|
|
|
412
426
|
const type = options?.type || joinPath.type || 'INNER';
|
|
413
427
|
const alias = options?.alias || joinPath.alias;
|
|
414
428
|
const table = String(joinPath.to);
|
|
415
|
-
|
|
429
|
+
const rightColumn = `${table}.${joinPath.rightColumn}`;
|
|
430
|
+
this.config = this.joins.addJoin(type, table, joinPath.leftColumn, rightColumn, alias);
|
|
416
431
|
});
|
|
417
432
|
}
|
|
418
433
|
else {
|
|
@@ -420,7 +435,8 @@ export class QueryBuilder {
|
|
|
420
435
|
const type = options?.type || path.type || 'INNER';
|
|
421
436
|
const alias = options?.alias || path.alias;
|
|
422
437
|
const table = String(path.to);
|
|
423
|
-
|
|
438
|
+
const rightColumn = `${table}.${path.rightColumn}`;
|
|
439
|
+
this.config = this.joins.addJoin(type, table, path.leftColumn, rightColumn, alias);
|
|
424
440
|
}
|
|
425
441
|
return this;
|
|
426
442
|
}
|
|
@@ -429,10 +445,15 @@ export function createQueryBuilder(config) {
|
|
|
429
445
|
ClickHouseConnection.initialize(config);
|
|
430
446
|
return {
|
|
431
447
|
table(tableName) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
448
|
+
const state = {
|
|
449
|
+
schema: {},
|
|
450
|
+
tables: tableName,
|
|
451
|
+
output: {},
|
|
452
|
+
baseTable: tableName,
|
|
453
|
+
base: {},
|
|
454
|
+
aliases: {}
|
|
455
|
+
};
|
|
456
|
+
return new QueryBuilder(tableName, state);
|
|
436
457
|
}
|
|
437
458
|
};
|
|
438
459
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const initializeTestConnection: () => Promise<{
|
|
2
|
-
table<TableName extends never>(tableName: TableName): import("../../query-builder.js").
|
|
2
|
+
table<TableName extends never>(tableName: TableName): import("../../query-builder.js").SelectQB<import("../../types/builder-state.js").SchemaDefinition<unknown>, TableName, import("../../../index.js").TableRecord<import("../../types/builder-state.js").SchemaDefinition<unknown>[TableName]>, TableName>;
|
|
3
3
|
}>;
|
|
4
4
|
export declare const ensureConnectionInitialized: () => import("@clickhouse/client").ClickHouseClient | import("@clickhouse/client-web").ClickHouseClient;
|
|
5
5
|
export declare const isDockerAvailable: () => Promise<boolean>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SelectQB } from '../query-builder.js';
|
|
2
|
+
import type { TableRecord } from '../../types/schema.js';
|
|
2
3
|
export type TestTableSchema = {
|
|
3
4
|
id: 'Int32';
|
|
4
5
|
name: 'String';
|
|
@@ -38,6 +39,6 @@ export interface TestSchema {
|
|
|
38
39
|
users: UsersSchema;
|
|
39
40
|
}
|
|
40
41
|
export declare const TEST_SCHEMAS: TestSchema;
|
|
41
|
-
export declare function setupUsersBuilder():
|
|
42
|
-
export declare function setupTestBuilder():
|
|
42
|
+
export declare function setupUsersBuilder(): SelectQB<TestSchema, 'users', TableRecord<TestSchema['users']>, 'users'>;
|
|
43
|
+
export declare function setupTestBuilder(): SelectQB<TestSchema, 'test_table', TableRecord<TestSchema['test_table']>, 'test_table'>;
|
|
43
44
|
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tests/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tests/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,QAAQ,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IAEnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,qCAAqC,CAAC;IAChD,aAAa,EAAE,kBAAkB,CAAC;IAClC,UAAU,EAAE,+BAA+B,CAAC;IAC5C,aAAa,EAAE,4CAA4C,CAAC;IAC5D,aAAa,EAAE,yBAAyB,CAAC;IACzC,WAAW,EAAE,4BAA4B,CAAC;IAC1C,iBAAiB,EAAE,eAAe,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,QAAQ,CAAC;IACpB,KAAK,EAAE,QAAQ,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,WAAW,EAAE,+CAA+C,CAAC;IAC7D,KAAK,EAAE,+BAA+B,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,eAAe,CAAC;IAC5B,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,eAAO,MAAM,YAAY,EAAE,UAmC1B,CAAC;AAgBF,wBAAgB,iBAAiB,IAAI,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAU5G;AAED,wBAAgB,gBAAgB,IAAI,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,YAAY,CAAC,CAU1H"}
|
|
@@ -36,14 +36,24 @@ export const TEST_SCHEMAS = {
|
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
export function setupUsersBuilder() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
const state = {
|
|
40
|
+
schema: TEST_SCHEMAS,
|
|
41
|
+
tables: 'users',
|
|
42
|
+
output: {},
|
|
43
|
+
baseTable: 'users',
|
|
44
|
+
base: TEST_SCHEMAS.users,
|
|
45
|
+
aliases: {}
|
|
46
|
+
};
|
|
47
|
+
return new QueryBuilder('users', state);
|
|
43
48
|
}
|
|
44
49
|
export function setupTestBuilder() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
const state = {
|
|
51
|
+
schema: TEST_SCHEMAS,
|
|
52
|
+
tables: 'test_table',
|
|
53
|
+
output: {},
|
|
54
|
+
baseTable: 'test_table',
|
|
55
|
+
base: TEST_SCHEMAS.test_table,
|
|
56
|
+
aliases: {}
|
|
57
|
+
};
|
|
58
|
+
return new QueryBuilder('test_table', state);
|
|
49
59
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ColumnType, InferColumnType, TableRecord } from '../../types/schema.js';
|
|
2
|
+
import type { Simplify } from './type-helpers.js';
|
|
3
|
+
export type SchemaDefinition<Schema extends Record<string, any> = Record<string, any>> = {
|
|
4
|
+
[K in keyof Schema]: Record<string, ColumnType>;
|
|
5
|
+
};
|
|
6
|
+
export type BuilderState<Schema extends SchemaDefinition<Schema>, VisibleTables extends string, OutputRow, BaseTable extends keyof Schema, Aliases extends Partial<Record<string, keyof Schema>> = {}> = {
|
|
7
|
+
schema: Schema;
|
|
8
|
+
tables: VisibleTables;
|
|
9
|
+
output: OutputRow;
|
|
10
|
+
baseTable: BaseTable;
|
|
11
|
+
base: Schema[BaseTable];
|
|
12
|
+
aliases: Aliases;
|
|
13
|
+
};
|
|
14
|
+
export type AnyBuilderState = BuilderState<any, any, any, any, any>;
|
|
15
|
+
export type BaseRow<State extends AnyBuilderState> = Simplify<{
|
|
16
|
+
[K in keyof State['base']]: State['base'][K] extends ColumnType ? InferColumnType<State['base'][K]> : never;
|
|
17
|
+
}>;
|
|
18
|
+
export type WidenTables<State extends AnyBuilderState, Table extends keyof State['schema']> = BuilderState<State['schema'], State['tables'] | (Table & string), State['output'], State['baseTable'], State['aliases']>;
|
|
19
|
+
export type UpdateOutput<State extends AnyBuilderState, Output> = BuilderState<State['schema'], State['tables'], Output, State['baseTable'], State['aliases']>;
|
|
20
|
+
export type InitialState<Schema extends SchemaDefinition<Schema>, Table extends keyof Schema> = BuilderState<Schema, Table & string, TableRecord<Schema[Table]>, Table, {}>;
|
|
21
|
+
export type ExplicitSelectionState<State extends AnyBuilderState> = BaseRow<State> extends State['output'] ? State['output'] extends BaseRow<State> ? false : true : true;
|
|
22
|
+
export type AppendToOutput<State extends AnyBuilderState, Added> = UpdateOutput<State, ExplicitSelectionState<State> extends true ? Simplify<State['output'] & Added> : Simplify<Added>>;
|
|
23
|
+
export type AddAlias<State extends AnyBuilderState, Alias extends string, Table extends keyof State['schema']> = BuilderState<State['schema'], State['tables'] | Alias, State['output'], State['baseTable'], State['aliases'] & Record<Alias, Table>>;
|
|
24
|
+
export type ResolveTableSchema<State extends AnyBuilderState, Table extends string> = Table extends keyof State['schema'] ? State['schema'][Table] : Table extends keyof State['aliases'] ? State['schema'][State['aliases'][Table]] : never;
|
|
25
|
+
//# sourceMappingURL=builder-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder-state.d.ts","sourceRoot":"","sources":["../../../src/core/types/builder-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SqlExpression, AliasedExpression } from '../utils/sql-expressions.js';
|
|
2
|
+
import type { ColumnType, InferColumnType } from '../../types/schema.js';
|
|
3
|
+
import type { AnyBuilderState, BaseRow, ResolveTableSchema } from './builder-state.js';
|
|
4
|
+
import { Simplify, UnionToIntersection } from './type-helpers.js';
|
|
5
|
+
type TableIdentifiers<State extends AnyBuilderState> = State['tables'] & string;
|
|
6
|
+
type QualifiedColumnsFor<State extends AnyBuilderState, Table extends string> = ResolveTableSchema<State, Table> extends Record<string, ColumnType> ? `${Table}.${Extract<keyof ResolveTableSchema<State, Table>, string>}` : never;
|
|
7
|
+
export type QualifiedColumnKeys<State extends AnyBuilderState> = {
|
|
8
|
+
[Table in TableIdentifiers<State>]: QualifiedColumnsFor<State, Table>;
|
|
9
|
+
}[TableIdentifiers<State>];
|
|
10
|
+
export type BaseColumnKeys<State extends AnyBuilderState> = keyof BaseRow<State>;
|
|
11
|
+
export type OutputColumnKeys<State extends AnyBuilderState> = keyof State['output'];
|
|
12
|
+
export type SelectableColumn<State extends AnyBuilderState> = OutputColumnKeys<State> | BaseColumnKeys<State> | QualifiedColumnKeys<State>;
|
|
13
|
+
export type SelectableItem<State extends AnyBuilderState> = SelectableColumn<State> | SqlExpression;
|
|
14
|
+
export type ColumnSelectionKey<P> = P extends `${string}.${infer C}` ? C : P;
|
|
15
|
+
type QualifiedColumnValue<State extends AnyBuilderState, P> = P extends `${infer Table}.${infer Column}` ? ResolveTableSchema<State, Table> extends Record<string, ColumnType> ? Column extends keyof ResolveTableSchema<State, Table> ? ResolveTableSchema<State, Table>[Column] extends ColumnType ? InferColumnType<ResolveTableSchema<State, Table>[Column]> : never : never : never : never;
|
|
16
|
+
export type ColumnSelectionValue<State extends AnyBuilderState, P> = P extends OutputColumnKeys<State> ? State['output'][P] : P extends BaseColumnKeys<State> ? BaseRow<State>[P] : QualifiedColumnValue<State, P>;
|
|
17
|
+
export type ColumnSelectionRecord<State extends AnyBuilderState, K> = {
|
|
18
|
+
[P in Extract<K, SelectableColumn<State>> as ColumnSelectionKey<P>]: ColumnSelectionValue<State, P>;
|
|
19
|
+
};
|
|
20
|
+
export type ExpressionSelectionRecord<K> = UnionToIntersection<K extends AliasedExpression<infer R, infer A> ? {
|
|
21
|
+
[P in A]: R;
|
|
22
|
+
} : {}>;
|
|
23
|
+
export type SelectionResult<State extends AnyBuilderState, K> = Simplify<ColumnSelectionRecord<State, K> & ExpressionSelectionRecord<K>>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=select-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-types.d.ts","sourceRoot":"","sources":["../../../src/core/types/select-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-helpers.d.ts","sourceRoot":"","sources":["../../../src/core/types/type-helpers.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAC/B,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC;AAEpF,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AnyBuilderState, BaseRow } from '../types/builder-state.js';
|
|
2
|
+
import type { SelectableColumn } from '../types/select-types.js';
|
|
3
|
+
export type PredicatePrimitive = string | number | boolean | Date | null;
|
|
4
|
+
type PredicateValue = Exclude<PredicatePrimitive, string>;
|
|
5
|
+
export interface PredicateExpression<T = unknown> {
|
|
6
|
+
__type: 'predicate_expression';
|
|
7
|
+
sql: string;
|
|
8
|
+
parameters: any[];
|
|
9
|
+
readonly expressionType?: T | undefined;
|
|
10
|
+
}
|
|
11
|
+
export interface PredicateLiteral<T = PredicatePrimitive> {
|
|
12
|
+
__type: 'predicate_literal';
|
|
13
|
+
value: T;
|
|
14
|
+
}
|
|
15
|
+
export type ColumnReference<State extends AnyBuilderState> = keyof BaseRow<State> | keyof State['output'] | Extract<SelectableColumn<State>, string>;
|
|
16
|
+
export type PredicateArg<State extends AnyBuilderState> = ColumnReference<State> | PredicateExpression | PredicateLiteral | PredicateValue | PredicatePrimitive[];
|
|
17
|
+
export interface PredicateBuilder<State extends AnyBuilderState> {
|
|
18
|
+
fn<T = unknown>(name: string, ...args: Array<PredicateArg<State>>): PredicateExpression<T>;
|
|
19
|
+
col(column: ColumnReference<State>): PredicateExpression;
|
|
20
|
+
value<T extends PredicatePrimitive>(value: T): PredicateLiteral<T>;
|
|
21
|
+
literal<T extends PredicatePrimitive>(value: T): PredicateLiteral<T>;
|
|
22
|
+
array(values: Array<PredicatePrimitive | PredicateLiteral>): PredicateExpression;
|
|
23
|
+
raw(sql: string): PredicateExpression;
|
|
24
|
+
and(expressions: PredicateExpression[]): PredicateExpression<boolean>;
|
|
25
|
+
or(expressions: PredicateExpression[]): PredicateExpression<boolean>;
|
|
26
|
+
}
|
|
27
|
+
export declare function createPredicateBuilder<State extends AnyBuilderState>(): PredicateBuilder<State>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=predicate-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"predicate-builder.d.ts","sourceRoot":"","sources":["../../../src/core/utils/predicate-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;AACzE,KAAK,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;AAE1D,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC9C,MAAM,EAAE,sBAAsB,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,GAAG,EAAE,CAAC;IAClB,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,kBAAkB;IACtD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC;CACV;AAED,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,eAAe,IACrD,MAAM,OAAO,CAAC,KAAK,CAAC,GACpB,MAAM,KAAK,CAAC,QAAQ,CAAC,GACrB,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC;AAE7C,MAAM,MAAM,YAAY,CAAC,KAAK,SAAS,eAAe,IAClD,eAAe,CAAC,KAAK,CAAC,GACtB,mBAAmB,GACnB,gBAAgB,GAChB,cAAc,GACd,kBAAkB,EAAE,CAAC;AAEzB,MAAM,WAAW,gBAAgB,CAAC,KAAK,SAAS,eAAe;IAC7D,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAC3F,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,mBAAmB,CAAC;IACzD,KAAK,CAAC,CAAC,SAAS,kBAAkB,EAAE,KAAK,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,CAAC,SAAS,kBAAkB,EAAE,KAAK,EAAE,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;IACrE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,kBAAkB,GAAG,gBAAgB,CAAC,GAAG,mBAAmB,CAAC;IACjF,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACtC,GAAG,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtE,EAAE,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;CACtE;AA4GD,wBAAgB,sBAAsB,CAAC,KAAK,SAAS,eAAe,KAAK,gBAAgB,CAAC,KAAK,CAAC,CAY/F"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
function createExpression(sql, parameters = []) {
|
|
2
|
+
return {
|
|
3
|
+
__type: 'predicate_expression',
|
|
4
|
+
sql,
|
|
5
|
+
parameters,
|
|
6
|
+
expressionType: undefined
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function literal(value) {
|
|
10
|
+
return {
|
|
11
|
+
__type: 'predicate_literal',
|
|
12
|
+
value
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function isPredicateExpression(value) {
|
|
16
|
+
return value?.__type === 'predicate_expression';
|
|
17
|
+
}
|
|
18
|
+
function isPredicateLiteral(value) {
|
|
19
|
+
return value?.__type === 'predicate_literal';
|
|
20
|
+
}
|
|
21
|
+
function buildArrayLiteral(values) {
|
|
22
|
+
const parts = [];
|
|
23
|
+
const parameters = [];
|
|
24
|
+
values.forEach(value => {
|
|
25
|
+
const normalized = normalizeLiteralValue(value);
|
|
26
|
+
parts.push(normalized.sql);
|
|
27
|
+
parameters.push(...normalized.parameters);
|
|
28
|
+
});
|
|
29
|
+
return createExpression(`[${parts.join(', ')}]`, parameters);
|
|
30
|
+
}
|
|
31
|
+
function normalizeLiteralValue(value) {
|
|
32
|
+
if (isPredicateLiteral(value)) {
|
|
33
|
+
return createExpression('?', [value.value]);
|
|
34
|
+
}
|
|
35
|
+
if (value === null) {
|
|
36
|
+
return createExpression('NULL');
|
|
37
|
+
}
|
|
38
|
+
if (value instanceof Date || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string') {
|
|
39
|
+
return createExpression('?', [value]);
|
|
40
|
+
}
|
|
41
|
+
throw new Error('Unsupported literal value in predicate array');
|
|
42
|
+
}
|
|
43
|
+
function normalizeArgument(arg) {
|
|
44
|
+
if (isPredicateExpression(arg)) {
|
|
45
|
+
return arg;
|
|
46
|
+
}
|
|
47
|
+
if (isPredicateLiteral(arg)) {
|
|
48
|
+
return createExpression('?', [arg.value]);
|
|
49
|
+
}
|
|
50
|
+
if (Array.isArray(arg)) {
|
|
51
|
+
return buildArrayLiteral(arg);
|
|
52
|
+
}
|
|
53
|
+
if (arg === null) {
|
|
54
|
+
return createExpression('NULL');
|
|
55
|
+
}
|
|
56
|
+
if (arg instanceof Date || typeof arg === 'number' || typeof arg === 'boolean') {
|
|
57
|
+
return createExpression('?', [arg]);
|
|
58
|
+
}
|
|
59
|
+
if (typeof arg === 'string') {
|
|
60
|
+
return createExpression(arg);
|
|
61
|
+
}
|
|
62
|
+
throw new Error('Unsupported predicate argument type');
|
|
63
|
+
}
|
|
64
|
+
function buildFunctionExpression(name, args) {
|
|
65
|
+
const builtArgs = args.map(arg => normalizeArgument(arg));
|
|
66
|
+
const sql = `${name}(${builtArgs.map(arg => arg.sql).join(', ')})`;
|
|
67
|
+
const parameters = builtArgs.flatMap(arg => arg.parameters);
|
|
68
|
+
return createExpression(sql, parameters);
|
|
69
|
+
}
|
|
70
|
+
function buildLogical(operator, expressions) {
|
|
71
|
+
if (!expressions.length) {
|
|
72
|
+
throw new Error(`${operator} requires at least one expression`);
|
|
73
|
+
}
|
|
74
|
+
if (expressions.length === 1) {
|
|
75
|
+
return expressions[0];
|
|
76
|
+
}
|
|
77
|
+
const sql = expressions.map(expr => `(${expr.sql})`).join(` ${operator} `);
|
|
78
|
+
const parameters = expressions.flatMap(expr => expr.parameters);
|
|
79
|
+
return createExpression(sql, parameters);
|
|
80
|
+
}
|
|
81
|
+
export function createPredicateBuilder() {
|
|
82
|
+
return {
|
|
83
|
+
fn: (name, ...args) => buildFunctionExpression(name, args),
|
|
84
|
+
col: column => createExpression(String(column)),
|
|
85
|
+
value: value => literal(value),
|
|
86
|
+
literal: value => literal(value),
|
|
87
|
+
array: values => buildArrayLiteral(values),
|
|
88
|
+
raw: sql => createExpression(sql),
|
|
89
|
+
and: expressions => buildLogical('AND', expressions),
|
|
90
|
+
or: expressions => buildLogical('OR', expressions)
|
|
91
|
+
};
|
|
92
|
+
}
|