xcraft-core-pickaxe 0.1.27 → 0.1.30
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/lib/operator-to-sql.js +36 -4
- package/lib/operators.js +32 -3
- package/lib/pick-operators.js +33 -4
- package/lib/picks.js +63 -0
- package/lib/query-builder.js +31 -10
- package/lib/query-to-sql.js +11 -4
- package/package.json +1 -1
- package/test/sql.spec.js +3 -3
package/lib/operator-to-sql.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const {isAnyPick, BasePick} = require('./picks.js');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
+
* @typedef {import("./query-builder.js").DbTable} DbTable
|
|
6
7
|
* @typedef {import("./operators.js").Expression} Expression
|
|
7
8
|
*/
|
|
8
9
|
|
|
@@ -103,6 +104,14 @@ const operators = {
|
|
|
103
104
|
return `LENGTH(${sql(value, context)})`;
|
|
104
105
|
},
|
|
105
106
|
|
|
107
|
+
lower({value}, context) {
|
|
108
|
+
return `LOWER(${sql(value, context)})`;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
upper({value}, context) {
|
|
112
|
+
return `UPPER(${sql(value, context)})`;
|
|
113
|
+
},
|
|
114
|
+
|
|
106
115
|
substr({value, start, length}, context) {
|
|
107
116
|
const valueSql = sql(value, context);
|
|
108
117
|
const startSql = sql(start, context);
|
|
@@ -192,11 +201,14 @@ const operators = {
|
|
|
192
201
|
if (!conditionSql) {
|
|
193
202
|
return '';
|
|
194
203
|
}
|
|
195
|
-
return `WHEN (${conditionSql}) THEN
|
|
204
|
+
return `WHEN (${conditionSql}) THEN ${sql(value, context)}`;
|
|
196
205
|
})
|
|
197
206
|
.filter(Boolean)
|
|
198
207
|
.join(' ');
|
|
199
|
-
|
|
208
|
+
if (!whenSql) {
|
|
209
|
+
return sql(elseValue, context);
|
|
210
|
+
}
|
|
211
|
+
return `CASE ${whenSql} ELSE ${sql(elseValue, context)} END`;
|
|
200
212
|
},
|
|
201
213
|
|
|
202
214
|
abs({value}, context) {
|
|
@@ -243,7 +255,11 @@ const operators = {
|
|
|
243
255
|
|
|
244
256
|
query({query}, context) {
|
|
245
257
|
const {queryToSql} = require('./query-to-sql.js');
|
|
246
|
-
return `(${
|
|
258
|
+
return `(${
|
|
259
|
+
queryToSql(query, context.values, {
|
|
260
|
+
useTableNames: context.useTableNames,
|
|
261
|
+
}).sql
|
|
262
|
+
})`;
|
|
247
263
|
},
|
|
248
264
|
|
|
249
265
|
each({value}, context) {
|
|
@@ -280,6 +296,14 @@ const operators = {
|
|
|
280
296
|
return `${sql(value, context)} DESC`;
|
|
281
297
|
},
|
|
282
298
|
|
|
299
|
+
nullsFirst({value}, context) {
|
|
300
|
+
return `${sql(value, context)} NULLS FIRST`;
|
|
301
|
+
},
|
|
302
|
+
|
|
303
|
+
nullsLast({value}, context) {
|
|
304
|
+
return `${sql(value, context)} NULLS LAST`;
|
|
305
|
+
},
|
|
306
|
+
|
|
283
307
|
count({field, distinct}, context) {
|
|
284
308
|
if (!field) {
|
|
285
309
|
return `COUNT(*)`;
|
|
@@ -303,7 +327,13 @@ const operators = {
|
|
|
303
327
|
return `SUM(${distinct ? 'DISTINCT ' : ''}${sql(field, context)})`;
|
|
304
328
|
},
|
|
305
329
|
|
|
306
|
-
groupArray({field}, context) {
|
|
330
|
+
groupArray({field, orderBy}, context) {
|
|
331
|
+
if (orderBy) {
|
|
332
|
+
return `json_group_array(${sql(field, context)} ORDER BY ${sql(
|
|
333
|
+
orderBy,
|
|
334
|
+
context
|
|
335
|
+
)})`;
|
|
336
|
+
}
|
|
307
337
|
return `json_group_array(${sql(field, context)})`;
|
|
308
338
|
},
|
|
309
339
|
};
|
|
@@ -322,6 +352,7 @@ function getExpression(expressionOrPick) {
|
|
|
322
352
|
/**
|
|
323
353
|
* @typedef {{
|
|
324
354
|
* values: any[] | null,
|
|
355
|
+
* tablesUsed: DbTable[],
|
|
325
356
|
* scope?: any,
|
|
326
357
|
* useTableNames?: boolean,
|
|
327
358
|
* equalOperator: 'IS' | '=',
|
|
@@ -345,6 +376,7 @@ function sql(expressionOrPick, context) {
|
|
|
345
376
|
function expressionToSql(operator) {
|
|
346
377
|
const context = {
|
|
347
378
|
values: [],
|
|
379
|
+
tablesUsed: [],
|
|
348
380
|
};
|
|
349
381
|
return {
|
|
350
382
|
sql: sql(operator, context),
|
package/lib/operators.js
CHANGED
|
@@ -90,6 +90,20 @@ const operators = {
|
|
|
90
90
|
});
|
|
91
91
|
},
|
|
92
92
|
|
|
93
|
+
lower(value) {
|
|
94
|
+
return /** @type {const} */ ({
|
|
95
|
+
operator: 'lower',
|
|
96
|
+
value: op(value),
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
upper(value) {
|
|
101
|
+
return /** @type {const} */ ({
|
|
102
|
+
operator: 'upper',
|
|
103
|
+
value: op(value),
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
|
|
93
107
|
substr(value, start, length) {
|
|
94
108
|
value = op(value);
|
|
95
109
|
start = op(start);
|
|
@@ -206,14 +220,14 @@ const operators = {
|
|
|
206
220
|
and(...conditions) {
|
|
207
221
|
return /** @type {const} */ ({
|
|
208
222
|
operator: 'and',
|
|
209
|
-
conditions,
|
|
223
|
+
conditions: conditions.map(op),
|
|
210
224
|
});
|
|
211
225
|
},
|
|
212
226
|
|
|
213
227
|
or(...conditions) {
|
|
214
228
|
return /** @type {const} */ ({
|
|
215
229
|
operator: 'or',
|
|
216
|
-
conditions,
|
|
230
|
+
conditions: conditions.map(op),
|
|
217
231
|
});
|
|
218
232
|
},
|
|
219
233
|
|
|
@@ -350,6 +364,20 @@ const operators = {
|
|
|
350
364
|
});
|
|
351
365
|
},
|
|
352
366
|
|
|
367
|
+
nullsFirst(value) {
|
|
368
|
+
return /** @type {const} */ ({
|
|
369
|
+
operator: 'nullsFirst',
|
|
370
|
+
value,
|
|
371
|
+
});
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
nullsLast(value) {
|
|
375
|
+
return /** @type {const} */ ({
|
|
376
|
+
operator: 'nullsLast',
|
|
377
|
+
value,
|
|
378
|
+
});
|
|
379
|
+
},
|
|
380
|
+
|
|
353
381
|
count(field, distinct) {
|
|
354
382
|
return /** @type {const} */ ({
|
|
355
383
|
operator: 'count',
|
|
@@ -386,10 +414,11 @@ const operators = {
|
|
|
386
414
|
});
|
|
387
415
|
},
|
|
388
416
|
|
|
389
|
-
groupArray(field) {
|
|
417
|
+
groupArray(field, orderBy) {
|
|
390
418
|
return /** @type {const} */ ({
|
|
391
419
|
operator: 'groupArray',
|
|
392
420
|
field,
|
|
421
|
+
orderBy,
|
|
393
422
|
});
|
|
394
423
|
},
|
|
395
424
|
};
|
package/lib/pick-operators.js
CHANGED
|
@@ -8,6 +8,8 @@ const {
|
|
|
8
8
|
union,
|
|
9
9
|
UnionType,
|
|
10
10
|
any,
|
|
11
|
+
string,
|
|
12
|
+
StringType,
|
|
11
13
|
} = require('xcraft-core-stones');
|
|
12
14
|
const $o = require('./operators.js');
|
|
13
15
|
const {
|
|
@@ -17,6 +19,7 @@ const {
|
|
|
17
19
|
NumberPick,
|
|
18
20
|
makePick,
|
|
19
21
|
ArrayPick,
|
|
22
|
+
StringPick,
|
|
20
23
|
} = require('./picks.js');
|
|
21
24
|
const {getPickOrValueType} = require('./pick-or-value.js');
|
|
22
25
|
|
|
@@ -53,7 +56,7 @@ const pickOperators = {
|
|
|
53
56
|
},
|
|
54
57
|
|
|
55
58
|
/**
|
|
56
|
-
* @param {BooleanPick[]} conditions
|
|
59
|
+
* @param {(BooleanPick | boolean)[]} conditions
|
|
57
60
|
* @returns {BooleanPick}
|
|
58
61
|
*/
|
|
59
62
|
and(...conditions) {
|
|
@@ -61,7 +64,7 @@ const pickOperators = {
|
|
|
61
64
|
},
|
|
62
65
|
|
|
63
66
|
/**
|
|
64
|
-
* @param {BooleanPick[]} conditions
|
|
67
|
+
* @param {(BooleanPick | boolean)[]} conditions
|
|
65
68
|
* @returns {BooleanPick}
|
|
66
69
|
*/
|
|
67
70
|
or(...conditions) {
|
|
@@ -105,6 +108,31 @@ const pickOperators = {
|
|
|
105
108
|
return new ValuePick(newType, $o.case(whenConditions, elseValue));
|
|
106
109
|
},
|
|
107
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @template {StringPick | string} T
|
|
113
|
+
* @typedef {T extends StringPick<infer U> ? U : T} StringValue
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @template {(StringPick | string)[]} T
|
|
118
|
+
* @typedef {{[K in keyof T]: StringValue<T[K]>}} StringValues
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @template {string[]} T
|
|
123
|
+
* @typedef {T extends [infer First extends string, ...infer Rest extends string[]] ? `${First}${ConcatStringLiterals<Rest>}`: ''} ConcatStringLiterals
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @template {(StringPick | string)[]} T
|
|
128
|
+
* @param {T} values
|
|
129
|
+
* @returns {StringPick<ConcatStringLiterals<StringValues<T>>>}
|
|
130
|
+
*/
|
|
131
|
+
stringConcat(...values) {
|
|
132
|
+
const type = /** @type {StringType<ConcatStringLiterals<StringValues<T>>>} */ (string);
|
|
133
|
+
return new StringPick(type, $o.stringConcat(...values));
|
|
134
|
+
},
|
|
135
|
+
|
|
108
136
|
/**
|
|
109
137
|
* @param {BasePick} [field]
|
|
110
138
|
* @param {boolean} [distinct]
|
|
@@ -146,9 +174,10 @@ const pickOperators = {
|
|
|
146
174
|
/**
|
|
147
175
|
* @template {AnyTypeOrShape} T
|
|
148
176
|
* @param {ValuePick<T>} field
|
|
177
|
+
* @param {BasePick} [orderBy]
|
|
149
178
|
*/
|
|
150
|
-
groupArray(field) {
|
|
151
|
-
return new ArrayPick(array(field.type), $o.groupArray(field));
|
|
179
|
+
groupArray(field, orderBy) {
|
|
180
|
+
return new ArrayPick(array(field.type), $o.groupArray(field, orderBy));
|
|
152
181
|
},
|
|
153
182
|
};
|
|
154
183
|
|
package/lib/picks.js
CHANGED
|
@@ -86,6 +86,14 @@ class ValuePick extends BasePick {
|
|
|
86
86
|
super(type, expression);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* @template {AnyTypeOrShape} T
|
|
91
|
+
* @param {T} type
|
|
92
|
+
*/
|
|
93
|
+
as(type) {
|
|
94
|
+
return makePick(type, this.expression);
|
|
95
|
+
}
|
|
96
|
+
|
|
89
97
|
/**
|
|
90
98
|
* @template {AnyObjectShape} T
|
|
91
99
|
* @param {T} shape
|
|
@@ -179,6 +187,14 @@ class StringPick extends ValuePick {
|
|
|
179
187
|
return new NumberPick(number, $o.stringLength(this.expression));
|
|
180
188
|
}
|
|
181
189
|
|
|
190
|
+
lower() {
|
|
191
|
+
return new StringPick(this.type, $o.lower(this.expression));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
upper() {
|
|
195
|
+
return new StringPick(this.type, $o.upper(this.expression));
|
|
196
|
+
}
|
|
197
|
+
|
|
182
198
|
/**
|
|
183
199
|
* @param {number | BasePick<NumberType>} start
|
|
184
200
|
* @param {number | BasePick<NumberType>} [length]
|
|
@@ -438,6 +454,53 @@ class ArrayPick extends BasePick {
|
|
|
438
454
|
);
|
|
439
455
|
}
|
|
440
456
|
|
|
457
|
+
/**
|
|
458
|
+
* @param {(value: PickOf<T>) => BooleanPick} func
|
|
459
|
+
*/
|
|
460
|
+
filter(func) {
|
|
461
|
+
return new ArrayPick(
|
|
462
|
+
this.type,
|
|
463
|
+
$o.query({
|
|
464
|
+
from: $o.each(this.expression),
|
|
465
|
+
select: [$o.groupArray($o.eachValue())],
|
|
466
|
+
where: func(makePick(this.type.valuesType, $o.eachValue())),
|
|
467
|
+
})
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* @template {AnyTypeOrShape} U
|
|
473
|
+
* @param {(value: PickOf<T>) => BasePick<U>} func
|
|
474
|
+
*/
|
|
475
|
+
map(func) {
|
|
476
|
+
const newValuePick = func(makePick(this.type.valuesType, $o.eachValue()));
|
|
477
|
+
return new ArrayPick(
|
|
478
|
+
array(newValuePick.type),
|
|
479
|
+
$o.query({
|
|
480
|
+
from: $o.each(this.expression),
|
|
481
|
+
select: [$o.groupArray(newValuePick)],
|
|
482
|
+
})
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* @param {(value: PickOf<T>) => BasePick} [func]
|
|
488
|
+
*/
|
|
489
|
+
sort(func = (pick) => pick) {
|
|
490
|
+
return new ArrayPick(
|
|
491
|
+
this.type,
|
|
492
|
+
$o.query({
|
|
493
|
+
from: $o.each(this.expression),
|
|
494
|
+
select: [
|
|
495
|
+
$o.groupArray(
|
|
496
|
+
$o.eachValue(),
|
|
497
|
+
func(makePick(this.type.valuesType, $o.eachValue()))
|
|
498
|
+
),
|
|
499
|
+
],
|
|
500
|
+
})
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
|
|
441
504
|
/**
|
|
442
505
|
* @param {(value: PickOf<T>) => BooleanPick} func
|
|
443
506
|
*/
|
package/lib/query-builder.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
const path = require('node:path');
|
|
3
4
|
const {
|
|
4
5
|
ObjectType,
|
|
5
6
|
ArrayType,
|
|
@@ -43,11 +44,15 @@ const partialObjectShape = require('./partial-object-shape.js');
|
|
|
43
44
|
*/
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
* @typedef {{db?: string,
|
|
47
|
+
* @typedef {{db?: string, dbId?: string, table: string, alias?: string}} DbTable
|
|
47
48
|
*/
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* @typedef {
|
|
51
|
+
* @typedef {{db?: undefined, dbId?: undefined, table: Subquery, alias?: string}} SubqueryAndAlias
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {string | Subquery | DbTable | SubqueryAndAlias} QueryTable
|
|
51
56
|
*/
|
|
52
57
|
|
|
53
58
|
/**
|
|
@@ -55,6 +60,7 @@ const partialObjectShape = require('./partial-object-shape.js');
|
|
|
55
60
|
* @template {AnyObjectShape} U
|
|
56
61
|
* @typedef {{
|
|
57
62
|
* db?: string,
|
|
63
|
+
* dbId?: string,
|
|
58
64
|
* table: string,
|
|
59
65
|
* alias?: string,
|
|
60
66
|
* shape?: T,
|
|
@@ -281,9 +287,15 @@ function getTableName(table) {
|
|
|
281
287
|
* @template {AnyObjectShape} T
|
|
282
288
|
* @param {AnyTableSchema} tableSchema
|
|
283
289
|
* @param {T} shape
|
|
284
|
-
* @returns {{pick: RowPick<GetShape<T>>, condition: BooleanPick | null}}
|
|
290
|
+
* @returns {{table: DbTable, pick: RowPick<GetShape<T>>, condition: BooleanPick | null}}
|
|
285
291
|
*/
|
|
286
292
|
function useTableSchema(tableSchema, shape) {
|
|
293
|
+
const table = {
|
|
294
|
+
db: tableSchema.db,
|
|
295
|
+
dbId: tableSchema.dbId,
|
|
296
|
+
table: tableSchema.table,
|
|
297
|
+
alias: tableSchema.alias,
|
|
298
|
+
};
|
|
287
299
|
const type = toObjectType(shape);
|
|
288
300
|
const tableName = getTableName(tableSchema);
|
|
289
301
|
let pick = rowPick(type, tableName);
|
|
@@ -295,7 +307,7 @@ function useTableSchema(tableSchema, shape) {
|
|
|
295
307
|
}
|
|
296
308
|
pick = tableSchema.scope(basePick).toRowPick();
|
|
297
309
|
}
|
|
298
|
-
return {pick, condition};
|
|
310
|
+
return {table, pick, condition};
|
|
299
311
|
}
|
|
300
312
|
|
|
301
313
|
/**
|
|
@@ -456,6 +468,15 @@ class FinalQuery {
|
|
|
456
468
|
return queryToSql(this.#queryParts, null).sql;
|
|
457
469
|
}
|
|
458
470
|
|
|
471
|
+
json() {
|
|
472
|
+
const {sql, values, tables} = queryToSql(this.#queryParts);
|
|
473
|
+
return {sql, values, tables};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
getMapRow() {
|
|
477
|
+
return this.#getMapRow();
|
|
478
|
+
}
|
|
479
|
+
|
|
459
480
|
/**
|
|
460
481
|
* @returns {R | undefined}
|
|
461
482
|
*/
|
|
@@ -693,14 +714,14 @@ class FromQuery {
|
|
|
693
714
|
*/
|
|
694
715
|
_join(joinOperator, tableName, shape, joinFct, mergePicks) {
|
|
695
716
|
const tableSchema = this.#getTableSchema(tableName, shape);
|
|
696
|
-
const {pick, condition} = useTableSchema(tableSchema, shape);
|
|
717
|
+
const {table, pick, condition} = useTableSchema(tableSchema, shape);
|
|
697
718
|
|
|
698
719
|
const joinCondition = joinFct(...this.#picks, pick, pickOperators);
|
|
699
720
|
const queryParts = {
|
|
700
721
|
...this.#queryParts,
|
|
701
722
|
joins: mergeJoin(this.#queryParts.joins, {
|
|
702
723
|
operator: joinOperator,
|
|
703
|
-
table
|
|
724
|
+
table,
|
|
704
725
|
constraint: condition
|
|
705
726
|
? pickOperators.and(condition, joinCondition)
|
|
706
727
|
: joinCondition,
|
|
@@ -845,7 +866,7 @@ class FromQuery {
|
|
|
845
866
|
}
|
|
846
867
|
|
|
847
868
|
/**
|
|
848
|
-
* @returns {SelectQuery<T, T[number]>}
|
|
869
|
+
* @returns {SelectQuery<T, {object: T[number]}>}
|
|
849
870
|
*/
|
|
850
871
|
selectAll() {
|
|
851
872
|
const isRoot = this.#picks.every((pick) => pick.isRoot());
|
|
@@ -945,12 +966,11 @@ class QueryBuilder {
|
|
|
945
966
|
*/
|
|
946
967
|
from(tableName, shape) {
|
|
947
968
|
const tableSchema = this.#getTableSchema(tableName, shape);
|
|
948
|
-
const
|
|
969
|
+
const {table, pick, condition} = useTableSchema(tableSchema, shape);
|
|
949
970
|
const queryParts = {
|
|
950
|
-
from,
|
|
971
|
+
from: table,
|
|
951
972
|
withs: this.#withs,
|
|
952
973
|
};
|
|
953
|
-
const {pick, condition} = useTableSchema(tableSchema, shape);
|
|
954
974
|
if (condition) {
|
|
955
975
|
queryParts.where = condition;
|
|
956
976
|
}
|
|
@@ -966,4 +986,5 @@ class QueryBuilder {
|
|
|
966
986
|
module.exports = {
|
|
967
987
|
QueryBuilder,
|
|
968
988
|
FromQuery,
|
|
989
|
+
FinalQuery,
|
|
969
990
|
};
|
package/lib/query-to-sql.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/**
|
|
3
|
+
* @typedef {import("./query-builder.js").DbTable} DbTable
|
|
3
4
|
* @typedef {import("./query-builder.js").QueryObj} QueryObj
|
|
4
5
|
* @typedef {import("./operator-to-sql.js").ExpressionToSqlContext} ExpressionToSqlContext
|
|
5
6
|
*/
|
|
@@ -21,7 +22,8 @@ function withSql(withs, context) {
|
|
|
21
22
|
.map(({name, query}) => {
|
|
22
23
|
let sql = '';
|
|
23
24
|
sql += `${name} AS (\n`;
|
|
24
|
-
sql += queryToSql(query, context.values)
|
|
25
|
+
sql += queryToSql(query, context.values, {tablesUsed: context.tablesUsed})
|
|
26
|
+
.sql;
|
|
25
27
|
sql += '\n)';
|
|
26
28
|
return sql;
|
|
27
29
|
})
|
|
@@ -37,6 +39,7 @@ function withSql(withs, context) {
|
|
|
37
39
|
function tableSql(table, context) {
|
|
38
40
|
// Note: table is not validated
|
|
39
41
|
if (typeof table === 'string') {
|
|
42
|
+
context.tablesUsed.push({table});
|
|
40
43
|
return table;
|
|
41
44
|
}
|
|
42
45
|
if (!('table' in table)) {
|
|
@@ -44,6 +47,7 @@ function tableSql(table, context) {
|
|
|
44
47
|
}
|
|
45
48
|
let resultSql = '';
|
|
46
49
|
if (typeof table.table === 'string') {
|
|
50
|
+
context.tablesUsed.push(table);
|
|
47
51
|
if (typeof table.db === 'string') {
|
|
48
52
|
resultSql += `${table.db}.`;
|
|
49
53
|
}
|
|
@@ -122,15 +126,18 @@ function groupByFields(groupBy, context) {
|
|
|
122
126
|
/**
|
|
123
127
|
* @param {QueryObj} query
|
|
124
128
|
* @param {any[] | null} [values]
|
|
125
|
-
* @
|
|
129
|
+
* @param {Partial<ExpressionToSqlContext>} [options]
|
|
130
|
+
* @returns {{sql: string, values: any[] | null, tables: DbTable[]}}
|
|
126
131
|
*/
|
|
127
|
-
function queryToSql(query, values = []) {
|
|
132
|
+
function queryToSql(query, values = [], options = {}) {
|
|
128
133
|
/** @type {ExpressionToSqlContext} */
|
|
129
134
|
const context = {
|
|
130
135
|
values,
|
|
136
|
+
tablesUsed: [],
|
|
131
137
|
scope: query.scope,
|
|
132
138
|
useTableNames: query.joins && query.joins.length > 0,
|
|
133
139
|
equalOperator: 'IS',
|
|
140
|
+
...options,
|
|
134
141
|
};
|
|
135
142
|
const explain = query.explain ? 'EXPLAIN QUERY PLAN\n' : '';
|
|
136
143
|
const withs = withSql(query.withs, context);
|
|
@@ -167,7 +174,7 @@ function queryToSql(query, values = []) {
|
|
|
167
174
|
}
|
|
168
175
|
result += '\n' + `OFFSET ${query.offset}`;
|
|
169
176
|
}
|
|
170
|
-
return {sql: result, values};
|
|
177
|
+
return {sql: result, values, tables: context.tablesUsed};
|
|
171
178
|
}
|
|
172
179
|
|
|
173
180
|
module.exports = {
|
package/package.json
CHANGED
package/test/sql.spec.js
CHANGED
|
@@ -412,9 +412,9 @@ describe('xcraft.pickaxe', function () {
|
|
|
412
412
|
id,
|
|
413
413
|
(firstname || lastname) AS fullname,
|
|
414
414
|
CASE
|
|
415
|
-
WHEN age < 13 THEN 'kid'
|
|
416
|
-
WHEN age < 18 THEN 'teenager'
|
|
417
|
-
WHEN age < 65 THEN 'adult'
|
|
415
|
+
WHEN (age < 13) THEN 'kid'
|
|
416
|
+
WHEN (age < 18) THEN 'teenager'
|
|
417
|
+
WHEN (age < 65) THEN 'adult'
|
|
418
418
|
ELSE 'elder'
|
|
419
419
|
END AS kind
|
|
420
420
|
FROM test_table
|