@balena/abstract-sql-compiler 10.5.0-build-joshbwlng-date-trunc-456a4a82262ae24000cf4427451b6ef107b876b3-1 → 11.0.0-build-11-x-db9cd30f6ec498e5293df9e060f5531cd960b1cc-1
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/.versionbot/CHANGELOG.yml +28 -7
- package/CHANGELOG.md +4 -2
- package/out/AbstractSQLCompiler.d.ts +6 -5
- package/out/AbstractSQLCompiler.js +45 -57
- package/out/AbstractSQLCompiler.js.map +1 -1
- package/out/AbstractSQLOptimiser.d.ts +1 -1
- package/out/AbstractSQLOptimiser.js +8 -56
- package/out/AbstractSQLOptimiser.js.map +1 -1
- package/out/AbstractSQLRules2SQL.d.ts +2 -2
- package/out/AbstractSQLRules2SQL.js +206 -229
- package/out/AbstractSQLRules2SQL.js.map +1 -1
- package/out/AbstractSQLSchemaOptimiser.d.ts +2 -2
- package/out/AbstractSQLSchemaOptimiser.js +14 -21
- package/out/AbstractSQLSchemaOptimiser.js.map +1 -1
- package/out/referenced-fields.d.ts +1 -1
- package/out/referenced-fields.js +17 -24
- package/out/referenced-fields.js.map +1 -1
- package/package.json +4 -4
- package/src/AbstractSQLCompiler.ts +22 -18
- package/src/AbstractSQLOptimiser.ts +6 -22
- package/src/AbstractSQLRules2SQL.ts +6 -11
- package/src/AbstractSQLSchemaOptimiser.ts +6 -5
- package/src/referenced-fields.ts +4 -4
- package/test/abstract-sql/aggregate-json.ts +1 -1
- package/test/abstract-sql/aggregate.ts +25 -10
- package/test/abstract-sql/and-or-boolean-optimisations.ts +1 -1
- package/test/abstract-sql/case-when-else.ts +5 -2
- package/test/abstract-sql/cast.ts +1 -1
- package/test/abstract-sql/coalesce.ts +1 -1
- package/test/abstract-sql/comparisons.ts +1 -1
- package/test/abstract-sql/dates.ts +10 -27
- package/test/abstract-sql/duration.ts +1 -1
- package/test/abstract-sql/empty-query-optimisations.ts +2 -2
- package/test/abstract-sql/functions_wrapper.ts +1 -1
- package/test/abstract-sql/get-referenced-fields.ts +1 -1
- package/test/abstract-sql/get-rule-referenced-fields.ts +1 -1
- package/test/abstract-sql/insert-query.ts +1 -1
- package/test/abstract-sql/is-distinct.ts +1 -1
- package/test/abstract-sql/joins.ts +1 -1
- package/test/abstract-sql/json.ts +1 -1
- package/test/abstract-sql/math.ts +1 -1
- package/test/abstract-sql/nested-in-optimisations.ts +1 -1
- package/test/abstract-sql/not-not-optimisations.ts +1 -1
- package/test/abstract-sql/schema-checks.ts +1 -1
- package/test/abstract-sql/schema-informative-reference.ts +1 -1
- package/test/abstract-sql/schema-rule-optimization.ts +1 -1
- package/test/abstract-sql/schema-rule-to-check.ts +1 -1
- package/test/abstract-sql/schema-views.ts +37 -2
- package/test/abstract-sql/test.ts +1 -1
- package/test/abstract-sql/text.ts +1 -1
- package/test/odata/expand.ts +3 -3
- package/test/odata/filterby.ts +8 -4
- package/test/odata/orderby.ts +2 -2
- package/test/odata/paging.ts +2 -2
- package/test/odata/resource_parsing.ts +5 -5
- package/test/odata/select.ts +2 -2
- package/test/odata/stress.ts +2 -2
- package/test/odata/test.ts +24 -20
- package/test/sbvr/pilots.ts +3 -3
- package/test/sbvr/reference-type.ts +3 -3
- package/test/sbvr/test.ts +12 -10
@@ -1,17 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
};
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.checkMinArgs = exports.checkArgs = exports.getAbstractSqlQuery = exports.isAbstractSqlQuery = exports.isNotNullable = exports.isDurationValue = exports.isJSONValue = exports.isArrayValue = exports.isDateValue = exports.isBooleanValue = exports.isNumericValue = exports.isTextValue = exports.comparisons = void 0;
|
7
|
-
exports.AbstractSQLRules2SQL = AbstractSQLRules2SQL;
|
8
|
-
const sbvr_types_1 = __importDefault(require("@balena/sbvr-types"));
|
9
|
-
const AbstractSQLCompiler_1 = require("./AbstractSQLCompiler");
|
1
|
+
import $sbvrTypes from '@balena/sbvr-types';
|
2
|
+
const { default: sbvrTypes } = $sbvrTypes;
|
3
|
+
import { isFieldTypeNode } from './AbstractSQLCompiler.js';
|
10
4
|
let fieldOrderings = [];
|
11
5
|
let fieldOrderingsLookup = {};
|
12
6
|
let engine = "postgres";
|
13
7
|
let noBinds = false;
|
14
|
-
|
8
|
+
export const comparisons = {
|
15
9
|
Equals: ' = ',
|
16
10
|
GreaterThan: ' > ',
|
17
11
|
GreaterThanOrEqual: ' >= ',
|
@@ -25,12 +19,12 @@ const escapeField = (field) => field === '*' ? '*' : `"${field}"`;
|
|
25
19
|
const AnyValue = (args, indent) => {
|
26
20
|
const [type, ...rest] = args;
|
27
21
|
for (const matcher of [
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
isJSONValue,
|
23
|
+
isDateValue,
|
24
|
+
isTextValue,
|
25
|
+
isNumericValue,
|
26
|
+
isBooleanValue,
|
27
|
+
isDurationValue,
|
34
28
|
]) {
|
35
29
|
if (matcher(type)) {
|
36
30
|
return typeRules[type](rest, indent);
|
@@ -70,7 +64,7 @@ const MatchValue = (matcher) => (args, indent) => {
|
|
70
64
|
}
|
71
65
|
return UnknownValue(args, indent);
|
72
66
|
};
|
73
|
-
const isTextValue = (type) => {
|
67
|
+
export const isTextValue = (type) => {
|
74
68
|
return (type === 'Text' ||
|
75
69
|
type === 'EmbeddedText' ||
|
76
70
|
type === 'Concatenate' ||
|
@@ -84,9 +78,8 @@ const isTextValue = (type) => {
|
|
84
78
|
type === 'Right' ||
|
85
79
|
type === 'EscapeForLike');
|
86
80
|
};
|
87
|
-
|
88
|
-
const
|
89
|
-
const isNumericValue = (type) => {
|
81
|
+
const TextValue = MatchValue(isTextValue);
|
82
|
+
export const isNumericValue = (type) => {
|
90
83
|
return (type === 'Number' ||
|
91
84
|
type === 'Real' ||
|
92
85
|
type === 'Integer' ||
|
@@ -114,9 +107,8 @@ const isNumericValue = (type) => {
|
|
114
107
|
type === 'Sum' ||
|
115
108
|
type === 'SubtractDateDate');
|
116
109
|
};
|
117
|
-
|
118
|
-
const
|
119
|
-
const isBooleanValue = (type) => {
|
110
|
+
const NumericValue = MatchValue(isNumericValue);
|
111
|
+
export const isBooleanValue = (type) => {
|
120
112
|
return (type === 'Boolean' ||
|
121
113
|
type === 'Not' ||
|
122
114
|
type === 'And' ||
|
@@ -137,9 +129,8 @@ const isBooleanValue = (type) => {
|
|
137
129
|
type === 'IsDistinctFrom' ||
|
138
130
|
type === 'StartsWith');
|
139
131
|
};
|
140
|
-
|
141
|
-
const
|
142
|
-
const isDateValue = (type) => {
|
132
|
+
const BooleanValue = MatchValue(isBooleanValue);
|
133
|
+
export const isDateValue = (type) => {
|
143
134
|
return (type === 'Date' ||
|
144
135
|
type === 'ToDate' ||
|
145
136
|
type === 'ToTime' ||
|
@@ -151,24 +142,20 @@ const isDateValue = (type) => {
|
|
151
142
|
type === 'SubtractDateDuration' ||
|
152
143
|
type === 'SubtractDateNumber');
|
153
144
|
};
|
154
|
-
|
155
|
-
const
|
156
|
-
const isArrayValue = (type) => {
|
145
|
+
const DateValue = MatchValue(isDateValue);
|
146
|
+
export const isArrayValue = (type) => {
|
157
147
|
return type === 'TextArray';
|
158
148
|
};
|
159
|
-
|
160
|
-
const isJSONValue = (type) => {
|
149
|
+
export const isJSONValue = (type) => {
|
161
150
|
return type === 'AggregateJSON' || type === 'ToJSON';
|
162
151
|
};
|
163
|
-
|
164
|
-
const
|
165
|
-
const isDurationValue = (type) => {
|
152
|
+
const JSONValue = MatchValue(isJSONValue);
|
153
|
+
export const isDurationValue = (type) => {
|
166
154
|
return type === 'Duration';
|
167
155
|
};
|
168
|
-
|
169
|
-
const DurationValue = MatchValue(exports.isDurationValue);
|
156
|
+
const DurationValue = MatchValue(isDurationValue);
|
170
157
|
const Field = (args, indent) => {
|
171
|
-
if (
|
158
|
+
if (isFieldTypeNode(args)) {
|
172
159
|
const [type, ...rest] = args;
|
173
160
|
return typeRules[type](rest, indent);
|
174
161
|
}
|
@@ -176,7 +163,7 @@ const Field = (args, indent) => {
|
|
176
163
|
throw new SyntaxError(`Invalid field type: ${args[0]}`);
|
177
164
|
}
|
178
165
|
};
|
179
|
-
const isNotNullable = (node) => {
|
166
|
+
export const isNotNullable = (node) => {
|
180
167
|
switch (node[0]) {
|
181
168
|
case 'EmbeddedText':
|
182
169
|
case 'Boolean':
|
@@ -194,14 +181,13 @@ const isNotNullable = (node) => {
|
|
194
181
|
case 'NotExists':
|
195
182
|
return true;
|
196
183
|
case 'Coalesce':
|
197
|
-
return node.slice(1).some((n) =>
|
184
|
+
return node.slice(1).some((n) => isNotNullable(n));
|
198
185
|
case 'Not':
|
199
|
-
return
|
186
|
+
return isNotNullable(node[1]);
|
200
187
|
}
|
201
188
|
return false;
|
202
189
|
};
|
203
|
-
|
204
|
-
const isAtomicNode = (n) => (0, AbstractSQLCompiler_1.isFieldTypeNode)(n) ||
|
190
|
+
const isAtomicNode = (n) => isFieldTypeNode(n) ||
|
205
191
|
n[0] === 'Bind' ||
|
206
192
|
n[0] === 'Null' ||
|
207
193
|
n[0] === 'Value' ||
|
@@ -211,8 +197,8 @@ const isAtomicNode = (n) => (0, AbstractSQLCompiler_1.isFieldTypeNode)(n) ||
|
|
211
197
|
n[0] === 'Integer' ||
|
212
198
|
n[0] === 'Boolean';
|
213
199
|
const isNotDistinctFrom = (args, indent) => {
|
214
|
-
const a =
|
215
|
-
const b =
|
200
|
+
const a = getAbstractSqlQuery(args, 0);
|
201
|
+
const b = getAbstractSqlQuery(args, 1);
|
216
202
|
let aSql = AnyValue(a, indent);
|
217
203
|
let bSql = AnyValue(b, indent);
|
218
204
|
if (!isAtomicNode(a)) {
|
@@ -222,8 +208,8 @@ const isNotDistinctFrom = (args, indent) => {
|
|
222
208
|
bSql = `(${bSql})`;
|
223
209
|
}
|
224
210
|
if (engine === "postgres") {
|
225
|
-
const aIsNotNullable =
|
226
|
-
const bIsNotNullable =
|
211
|
+
const aIsNotNullable = isNotNullable(a);
|
212
|
+
const bIsNotNullable = isNotNullable(b);
|
227
213
|
if (aIsNotNullable && bIsNotNullable) {
|
228
214
|
return `${aSql} = ${bSql}`;
|
229
215
|
}
|
@@ -249,29 +235,27 @@ const isNotDistinctFrom = (args, indent) => {
|
|
249
235
|
throw new SyntaxError(`IsDistinctFrom/IsNotDistinctFrom not supported on: ${engine}`);
|
250
236
|
}
|
251
237
|
};
|
252
|
-
const isAbstractSqlQuery = (x) => {
|
238
|
+
export const isAbstractSqlQuery = (x) => {
|
253
239
|
return Array.isArray(x);
|
254
240
|
};
|
255
|
-
|
256
|
-
const getAbstractSqlQuery = (args, index) => {
|
241
|
+
export const getAbstractSqlQuery = (args, index) => {
|
257
242
|
const abstractSqlQuery = args[index];
|
258
|
-
if (!
|
243
|
+
if (!isAbstractSqlQuery(abstractSqlQuery)) {
|
259
244
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof abstractSqlQuery}`);
|
260
245
|
}
|
261
246
|
return abstractSqlQuery;
|
262
247
|
};
|
263
|
-
exports.getAbstractSqlQuery = getAbstractSqlQuery;
|
264
248
|
const Comparison = (comparison) => {
|
265
249
|
return (args, indent) => {
|
266
|
-
|
250
|
+
checkArgs(comparison, args, 2);
|
267
251
|
const a = precedenceSafeOpValue(comparison, AnyValue, args, 0, indent);
|
268
252
|
const b = precedenceSafeOpValue(comparison, AnyValue, args, 1, indent);
|
269
|
-
return a +
|
253
|
+
return a + comparisons[comparison] + b;
|
270
254
|
};
|
271
255
|
};
|
272
256
|
const NumberMatch = (type) => {
|
273
257
|
return (args) => {
|
274
|
-
|
258
|
+
checkArgs(type, args, 1);
|
275
259
|
const n = args[0];
|
276
260
|
if (typeof n !== 'number') {
|
277
261
|
throw new SyntaxError(`${type} expected number but got ${typeof n}`);
|
@@ -304,15 +288,15 @@ const JoinMatch = (joinType) => {
|
|
304
288
|
if (args.length !== 1 && args.length !== 2) {
|
305
289
|
throw new SyntaxError(`"${joinType}" requires 1/2 arg(s)`);
|
306
290
|
}
|
307
|
-
const from = MaybeAlias(
|
291
|
+
const from = MaybeAlias(getAbstractSqlQuery(args, 0), indent, FromMatch);
|
308
292
|
if (args.length === 1) {
|
309
293
|
return sqlJoinType + from;
|
310
294
|
}
|
311
|
-
const [type, ...rest] =
|
295
|
+
const [type, ...rest] = getAbstractSqlQuery(args, 1);
|
312
296
|
switch (type) {
|
313
297
|
case 'On': {
|
314
|
-
|
315
|
-
const ruleBody = BooleanValue(
|
298
|
+
checkArgs('On', rest, 1);
|
299
|
+
const ruleBody = BooleanValue(getAbstractSqlQuery(rest, 0), NestedIndent(indent));
|
316
300
|
return sqlJoinType + from + ' ON ' + ruleBody;
|
317
301
|
}
|
318
302
|
default:
|
@@ -337,19 +321,19 @@ const mathOperatorNodeTypes = new Set([
|
|
337
321
|
'SubtractDateNumber',
|
338
322
|
]);
|
339
323
|
const precedenceSafeOpValue = (parentNodeType, valueMatchFn, args, index, indent) => {
|
340
|
-
const operandAbstractSql =
|
324
|
+
const operandAbstractSql = getAbstractSqlQuery(args, index);
|
341
325
|
const valueExpr = valueMatchFn(operandAbstractSql, indent);
|
342
326
|
const [childNodeType] = operandAbstractSql;
|
343
327
|
if ((mathOperatorNodeTypes.has(parentNodeType) &&
|
344
328
|
mathOperatorNodeTypes.has(childNodeType)) ||
|
345
|
-
(parentNodeType in
|
329
|
+
(parentNodeType in comparisons && childNodeType in comparisons)) {
|
346
330
|
return `(${valueExpr})`;
|
347
331
|
}
|
348
332
|
return valueExpr;
|
349
333
|
};
|
350
334
|
const MathOp = (type) => {
|
351
335
|
return (args, indent) => {
|
352
|
-
|
336
|
+
checkArgs(type, args, 2);
|
353
337
|
const a = precedenceSafeOpValue(type, NumericValue, args, 0, indent);
|
354
338
|
const b = precedenceSafeOpValue(type, NumericValue, args, 1, indent);
|
355
339
|
return `${a} ${mathOps[type]} ${b}`;
|
@@ -386,8 +370,8 @@ const dateFormats = {
|
|
386
370
|
};
|
387
371
|
const ExtractNumericDatePart = (type) => {
|
388
372
|
return (args, indent) => {
|
389
|
-
|
390
|
-
const date = DateValue(
|
373
|
+
checkArgs(type, args, 1);
|
374
|
+
const date = DateValue(getAbstractSqlQuery(args, 0), indent);
|
391
375
|
if (engine === "websql") {
|
392
376
|
return websqlDateFormats[type](date);
|
393
377
|
}
|
@@ -397,7 +381,7 @@ const ExtractNumericDatePart = (type) => {
|
|
397
381
|
};
|
398
382
|
};
|
399
383
|
const Text = (args) => {
|
400
|
-
|
384
|
+
checkArgs('Text', args, 1);
|
401
385
|
if (noBinds) {
|
402
386
|
return `'${args[0]}'`;
|
403
387
|
}
|
@@ -405,20 +389,18 @@ const Text = (args) => {
|
|
405
389
|
return AddBind(['Text', args[0]]);
|
406
390
|
}
|
407
391
|
};
|
408
|
-
const checkArgs = (matchName, args, num) => {
|
392
|
+
export const checkArgs = (matchName, args, num) => {
|
409
393
|
if (args.length !== num) {
|
410
394
|
throw new SyntaxError(`"${matchName}" requires ${num} arg(s)`);
|
411
395
|
}
|
412
396
|
};
|
413
|
-
|
414
|
-
const checkMinArgs = (matchName, args, num) => {
|
397
|
+
export const checkMinArgs = (matchName, args, num) => {
|
415
398
|
if (args.length < num) {
|
416
399
|
throw new SyntaxError(`"${matchName}" requires at least ${num} arg(s)`);
|
417
400
|
}
|
418
401
|
};
|
419
|
-
exports.checkMinArgs = checkMinArgs;
|
420
402
|
const AddDateNumber = (args, indent) => {
|
421
|
-
|
403
|
+
checkArgs('AddDateNumber', args, 2);
|
422
404
|
const a = precedenceSafeOpValue('AddDateNumber', DateValue, args, 0, indent);
|
423
405
|
const b = precedenceSafeOpValue('AddDateNumber', NumericValue, args, 1, indent);
|
424
406
|
if (engine === "postgres") {
|
@@ -432,7 +414,7 @@ const AddDateNumber = (args, indent) => {
|
|
432
414
|
}
|
433
415
|
};
|
434
416
|
const AddDateDuration = (args, indent) => {
|
435
|
-
|
417
|
+
checkArgs('AddDateDuration', args, 2);
|
436
418
|
const a = precedenceSafeOpValue('AddDateDuration', DateValue, args, 0, indent);
|
437
419
|
const b = precedenceSafeOpValue('AddDateDuration', DurationValue, args, 1, indent);
|
438
420
|
if (engine === "postgres") {
|
@@ -446,7 +428,7 @@ const AddDateDuration = (args, indent) => {
|
|
446
428
|
}
|
447
429
|
};
|
448
430
|
const SubtractDateDuration = (args, indent) => {
|
449
|
-
|
431
|
+
checkArgs('SubtractDateDuration', args, 2);
|
450
432
|
const a = precedenceSafeOpValue('SubtractDateDuration', DateValue, args, 0, indent);
|
451
433
|
const b = precedenceSafeOpValue('SubtractDateDuration', DurationValue, args, 1, indent);
|
452
434
|
if (engine === "postgres") {
|
@@ -460,7 +442,7 @@ const SubtractDateDuration = (args, indent) => {
|
|
460
442
|
}
|
461
443
|
};
|
462
444
|
const SubtractDateNumber = (args, indent) => {
|
463
|
-
|
445
|
+
checkArgs('SubtractDateNumber', args, 2);
|
464
446
|
const a = precedenceSafeOpValue('SubtractDateNumber', DateValue, args, 0, indent);
|
465
447
|
const b = precedenceSafeOpValue('SubtractDateNumber', NumericValue, args, 1, indent);
|
466
448
|
if (engine === "postgres") {
|
@@ -474,7 +456,7 @@ const SubtractDateNumber = (args, indent) => {
|
|
474
456
|
}
|
475
457
|
};
|
476
458
|
const SubtractDateDate = (args, indent) => {
|
477
|
-
|
459
|
+
checkArgs('SubtractDateDate', args, 2);
|
478
460
|
const a = precedenceSafeOpValue('SubtractDateDate', DateValue, args, 0, indent);
|
479
461
|
const b = precedenceSafeOpValue('SubtractDateDate', DateValue, args, 1, indent);
|
480
462
|
if (engine === "postgres") {
|
@@ -528,7 +510,7 @@ const FromMatch = (args, indent) => {
|
|
528
510
|
return '(' + nestedindent + query + indent + ')';
|
529
511
|
}
|
530
512
|
case 'Table': {
|
531
|
-
|
513
|
+
checkArgs('Table', rest, 1);
|
532
514
|
const [table] = rest;
|
533
515
|
if (typeof table !== 'string') {
|
534
516
|
throw new SyntaxError('`Table` table must be a string');
|
@@ -543,8 +525,8 @@ const MaybeAlias = (args, indent, matchFn) => {
|
|
543
525
|
const [type, ...rest] = args;
|
544
526
|
switch (type) {
|
545
527
|
case 'Alias': {
|
546
|
-
|
547
|
-
const field = matchFn(
|
528
|
+
checkArgs('Alias', rest, 2);
|
529
|
+
const field = matchFn(getAbstractSqlQuery(rest, 0), indent);
|
548
530
|
return `${field} AS "${rest[1]}"`;
|
549
531
|
}
|
550
532
|
default:
|
@@ -575,10 +557,10 @@ const AddBind = (bind) => {
|
|
575
557
|
};
|
576
558
|
const typeRules = {
|
577
559
|
UnionQuery: (args, indent) => {
|
578
|
-
|
560
|
+
checkMinArgs('UnionQuery', args, 2);
|
579
561
|
return args
|
580
562
|
.map((arg) => {
|
581
|
-
if (!
|
563
|
+
if (!isAbstractSqlQuery(arg)) {
|
582
564
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
583
565
|
}
|
584
566
|
const [type, ...rest] = arg;
|
@@ -605,7 +587,7 @@ const typeRules = {
|
|
605
587
|
Offset: '',
|
606
588
|
};
|
607
589
|
for (const arg of args) {
|
608
|
-
if (!
|
590
|
+
if (!isAbstractSqlQuery(arg)) {
|
609
591
|
throw new SyntaxError('`SelectQuery` args must all be arrays');
|
610
592
|
}
|
611
593
|
const [type, ...rest] = arg;
|
@@ -660,14 +642,14 @@ const typeRules = {
|
|
660
642
|
groups.Offset);
|
661
643
|
},
|
662
644
|
Select: (args, indent) => {
|
663
|
-
|
664
|
-
args =
|
645
|
+
checkArgs('Select', args, 1);
|
646
|
+
args = getAbstractSqlQuery(args, 0);
|
665
647
|
if (args.length === 0) {
|
666
648
|
return '1';
|
667
649
|
}
|
668
650
|
return args
|
669
651
|
.map((arg) => {
|
670
|
-
if (!
|
652
|
+
if (!isAbstractSqlQuery(arg)) {
|
671
653
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
672
654
|
}
|
673
655
|
return MaybeAlias(arg, indent, SelectMatch);
|
@@ -675,21 +657,21 @@ const typeRules = {
|
|
675
657
|
.join(', ');
|
676
658
|
},
|
677
659
|
From: (args, indent) => {
|
678
|
-
|
679
|
-
return MaybeAlias(
|
660
|
+
checkArgs('From', args, 1);
|
661
|
+
return MaybeAlias(getAbstractSqlQuery(args, 0), indent, FromMatch);
|
680
662
|
},
|
681
663
|
Join: JoinMatch('Join'),
|
682
664
|
LeftJoin: JoinMatch('LeftJoin'),
|
683
665
|
RightJoin: JoinMatch('RightJoin'),
|
684
666
|
FullJoin: JoinMatch('FullJoin'),
|
685
667
|
CrossJoin: (args, indent) => {
|
686
|
-
|
687
|
-
const from = MaybeAlias(
|
668
|
+
checkArgs('CrossJoin', args, 1);
|
669
|
+
const from = MaybeAlias(getAbstractSqlQuery(args, 0), indent, FromMatch);
|
688
670
|
return `CROSS JOIN ${from}`;
|
689
671
|
},
|
690
672
|
Where: (args, indent) => {
|
691
|
-
|
692
|
-
const boolNode =
|
673
|
+
checkArgs('Where', args, 1);
|
674
|
+
const boolNode = getAbstractSqlQuery(args, 0);
|
693
675
|
if (boolNode[0] === 'Boolean') {
|
694
676
|
return `WHERE ${boolNode[1] ? 'true' : 'false'}`;
|
695
677
|
}
|
@@ -697,61 +679,61 @@ const typeRules = {
|
|
697
679
|
return 'WHERE ' + ruleBody;
|
698
680
|
},
|
699
681
|
GroupBy: (args, indent) => {
|
700
|
-
|
701
|
-
const groups =
|
702
|
-
|
682
|
+
checkArgs('GroupBy', args, 1);
|
683
|
+
const groups = getAbstractSqlQuery(args, 0);
|
684
|
+
checkMinArgs('GroupBy groups', groups, 1);
|
703
685
|
return ('GROUP BY ' +
|
704
686
|
groups.map((arg) => AnyValue(arg, indent)).join(', '));
|
705
687
|
},
|
706
688
|
Having: (args, indent) => {
|
707
|
-
|
708
|
-
const havingBody = BooleanValue(
|
689
|
+
checkArgs('Having', args, 1);
|
690
|
+
const havingBody = BooleanValue(getAbstractSqlQuery(args, 0), indent);
|
709
691
|
return `HAVING ${havingBody}`;
|
710
692
|
},
|
711
693
|
OrderBy: (args, indent) => {
|
712
|
-
|
694
|
+
checkMinArgs('OrderBy', args, 1);
|
713
695
|
return ('ORDER BY ' +
|
714
696
|
args
|
715
697
|
.map((arg) => {
|
716
|
-
|
698
|
+
checkMinArgs('OrderBy ordering', arg, 2);
|
717
699
|
const order = arg[0];
|
718
700
|
if (order !== 'ASC' && order !== 'DESC') {
|
719
701
|
throw new SyntaxError(`Can only order by "ASC" or "DESC"`);
|
720
702
|
}
|
721
|
-
const value = AnyValue(
|
703
|
+
const value = AnyValue(getAbstractSqlQuery(arg, 1), indent);
|
722
704
|
return `${value} ${order}`;
|
723
705
|
})
|
724
706
|
.join(',' + NestedIndent(indent)));
|
725
707
|
},
|
726
708
|
Limit: (args, indent) => {
|
727
|
-
|
728
|
-
const num = NumericValue(
|
709
|
+
checkArgs('Limit', args, 1);
|
710
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
729
711
|
return `LIMIT ${num}`;
|
730
712
|
},
|
731
713
|
Offset: (args, indent) => {
|
732
|
-
|
733
|
-
const num = NumericValue(
|
714
|
+
checkArgs('Offset', args, 1);
|
715
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
734
716
|
return `OFFSET ${num}`;
|
735
717
|
},
|
736
718
|
Count: (args) => {
|
737
|
-
|
719
|
+
checkArgs('Count', args, 1);
|
738
720
|
if (args[0] !== '*') {
|
739
721
|
throw new SyntaxError('"Count" only supports "*"');
|
740
722
|
}
|
741
723
|
return 'COUNT(*)';
|
742
724
|
},
|
743
725
|
Average: (args, indent) => {
|
744
|
-
|
745
|
-
const num = NumericValue(
|
726
|
+
checkArgs('Average', args, 1);
|
727
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
746
728
|
return `AVG(${num})`;
|
747
729
|
},
|
748
730
|
Sum: (args, indent) => {
|
749
|
-
|
750
|
-
const num = NumericValue(
|
731
|
+
checkArgs('Sum', args, 1);
|
732
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
751
733
|
return `SUM(${num})`;
|
752
734
|
},
|
753
735
|
Field: (args) => {
|
754
|
-
|
736
|
+
checkArgs('Field', args, 1);
|
755
737
|
const [field] = args;
|
756
738
|
if (typeof field !== 'string') {
|
757
739
|
throw new SyntaxError('`Field` field must be a string');
|
@@ -759,7 +741,7 @@ const typeRules = {
|
|
759
741
|
return escapeField(field);
|
760
742
|
},
|
761
743
|
ReferencedField: (args) => {
|
762
|
-
|
744
|
+
checkArgs('ReferencedField', args, 2);
|
763
745
|
const [table, field] = args;
|
764
746
|
if (typeof table !== 'string') {
|
765
747
|
throw new SyntaxError('`ReferencedField` table must be a string');
|
@@ -770,14 +752,14 @@ const typeRules = {
|
|
770
752
|
return `"${table}".${escapeField(field)}`;
|
771
753
|
},
|
772
754
|
Cast: (args, indent) => {
|
773
|
-
|
774
|
-
const value = AnyValue(
|
755
|
+
checkArgs('Cast', args, 2);
|
756
|
+
const value = AnyValue(getAbstractSqlQuery(args, 0), indent);
|
775
757
|
const typeName = args[1];
|
776
|
-
if (!
|
758
|
+
if (!sbvrTypes[typeName]?.types[engine]) {
|
777
759
|
throw new SyntaxError(`Invalid cast type: ${typeName}`);
|
778
760
|
}
|
779
761
|
let type;
|
780
|
-
const dbType =
|
762
|
+
const dbType = sbvrTypes[typeName].types[engine];
|
781
763
|
if (typeof dbType === 'function') {
|
782
764
|
type = dbType.castType;
|
783
765
|
}
|
@@ -796,7 +778,7 @@ const typeRules = {
|
|
796
778
|
Real: NumberMatch('Real'),
|
797
779
|
Integer: NumberMatch('Integer'),
|
798
780
|
Boolean: (args) => {
|
799
|
-
|
781
|
+
checkArgs('Boolean', args, 1);
|
800
782
|
const b = args[0];
|
801
783
|
if (typeof b !== 'boolean') {
|
802
784
|
throw new SyntaxError(`Boolean expected boolean but got ${typeof b}`);
|
@@ -804,12 +786,12 @@ const typeRules = {
|
|
804
786
|
return b ? 'TRUE' : 'FALSE';
|
805
787
|
},
|
806
788
|
EmbeddedText: (args) => {
|
807
|
-
|
789
|
+
checkArgs('EmbeddedText', args, 1);
|
808
790
|
return `'${args[0]}'`;
|
809
791
|
},
|
810
792
|
TextArray: (args, indent) => {
|
811
793
|
const values = args.map((arg) => {
|
812
|
-
if (!
|
794
|
+
if (!isAbstractSqlQuery(arg)) {
|
813
795
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
814
796
|
}
|
815
797
|
return TextValue(arg, indent);
|
@@ -819,29 +801,29 @@ const typeRules = {
|
|
819
801
|
: 'CAST(ARRAY[] as TEXT[])';
|
820
802
|
},
|
821
803
|
Null: (args) => {
|
822
|
-
|
804
|
+
checkArgs('Null', args, 0);
|
823
805
|
return 'NULL';
|
824
806
|
},
|
825
807
|
CurrentTimestamp: (args) => {
|
826
|
-
|
808
|
+
checkArgs('CurrentTimestamp', args, 0);
|
827
809
|
return 'CURRENT_TIMESTAMP';
|
828
810
|
},
|
829
811
|
CurrentDate: (args) => {
|
830
|
-
|
812
|
+
checkArgs('CurrentDate', args, 0);
|
831
813
|
return 'CURRENT_DATE';
|
832
814
|
},
|
833
815
|
AggregateJSON: (args, indent) => {
|
834
|
-
|
816
|
+
checkArgs('AggregateJSON', args, 1);
|
835
817
|
if (engine !== "postgres") {
|
836
818
|
throw new SyntaxError('AggregateJSON not supported on: ' + engine);
|
837
819
|
}
|
838
|
-
const field = Field(
|
820
|
+
const field = Field(getAbstractSqlQuery(args, 0), indent);
|
839
821
|
return `COALESCE(JSON_AGG(${field}), '[]')`;
|
840
822
|
},
|
841
823
|
Equals: Comparison('Equals'),
|
842
824
|
EqualsAny: (args, indent) => {
|
843
|
-
|
844
|
-
return `${AnyValue(
|
825
|
+
checkArgs('EqualsAny', args, 2);
|
826
|
+
return `${AnyValue(getAbstractSqlQuery(args, 0), indent)} = ANY(${AnyValue(getAbstractSqlQuery(args, 1), indent)})`;
|
845
827
|
},
|
846
828
|
GreaterThan: Comparison('GreaterThan'),
|
847
829
|
GreaterThanOrEqual: Comparison('GreaterThanOrEqual'),
|
@@ -850,18 +832,18 @@ const typeRules = {
|
|
850
832
|
NotEquals: Comparison('NotEquals'),
|
851
833
|
Like: Comparison('Like'),
|
852
834
|
IsNotDistinctFrom: (args, indent) => {
|
853
|
-
|
835
|
+
checkArgs('IsNotDistinctFrom', args, 2);
|
854
836
|
return isNotDistinctFrom(args, indent);
|
855
837
|
},
|
856
838
|
IsDistinctFrom: (args, indent) => {
|
857
|
-
|
839
|
+
checkArgs('IsDistinctFrom', args, 2);
|
858
840
|
return 'NOT(' + isNotDistinctFrom(args, indent) + ')';
|
859
841
|
},
|
860
842
|
Between: (args, indent) => {
|
861
|
-
|
862
|
-
const v = AnyValue(
|
863
|
-
const a = AnyValue(
|
864
|
-
const b = AnyValue(
|
843
|
+
checkArgs('Between', args, 3);
|
844
|
+
const v = AnyValue(getAbstractSqlQuery(args, 0), indent);
|
845
|
+
const a = AnyValue(getAbstractSqlQuery(args, 1), indent);
|
846
|
+
const b = AnyValue(getAbstractSqlQuery(args, 2), indent);
|
865
847
|
return `${v} BETWEEN ${a} AND (${b})`;
|
866
848
|
},
|
867
849
|
Add: MathOp('Add'),
|
@@ -883,8 +865,8 @@ const typeRules = {
|
|
883
865
|
Second: ExtractNumericDatePart('Second'),
|
884
866
|
Fractionalseconds: ExtractNumericDatePart('Fractionalseconds'),
|
885
867
|
Totalseconds: (args, indent) => {
|
886
|
-
|
887
|
-
const duration = DurationValue(
|
868
|
+
checkArgs('Totalseconds', args, 1);
|
869
|
+
const duration = DurationValue(getAbstractSqlQuery(args, 0), indent);
|
888
870
|
if (engine === "postgres") {
|
889
871
|
return `EXTRACT(EPOCH FROM ${duration})`;
|
890
872
|
}
|
@@ -896,9 +878,9 @@ const typeRules = {
|
|
896
878
|
}
|
897
879
|
},
|
898
880
|
Concatenate: (args, indent) => {
|
899
|
-
|
881
|
+
checkMinArgs('Concatenate', args, 1);
|
900
882
|
const comparators = args.map((arg) => {
|
901
|
-
if (!
|
883
|
+
if (!isAbstractSqlQuery(arg)) {
|
902
884
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
903
885
|
}
|
904
886
|
return TextValue(arg, indent);
|
@@ -911,9 +893,9 @@ const typeRules = {
|
|
911
893
|
}
|
912
894
|
},
|
913
895
|
ConcatenateWithSeparator: (args, indent) => {
|
914
|
-
|
896
|
+
checkMinArgs('ConcatenateWithSeparator', args, 2);
|
915
897
|
const textParts = args.map((arg) => {
|
916
|
-
if (!
|
898
|
+
if (!isAbstractSqlQuery(arg)) {
|
917
899
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
918
900
|
}
|
919
901
|
return TextValue(arg, indent);
|
@@ -924,24 +906,24 @@ const typeRules = {
|
|
924
906
|
return `CONCAT_WS(${textParts.join(', ')})`;
|
925
907
|
},
|
926
908
|
Replace: (args, indent) => {
|
927
|
-
|
928
|
-
const str = TextValue(
|
929
|
-
const find = TextValue(
|
930
|
-
const replacement = TextValue(
|
909
|
+
checkArgs('Replace', args, 3);
|
910
|
+
const str = TextValue(getAbstractSqlQuery(args, 0), indent);
|
911
|
+
const find = TextValue(getAbstractSqlQuery(args, 1), indent);
|
912
|
+
const replacement = TextValue(getAbstractSqlQuery(args, 2), indent);
|
931
913
|
return `REPLACE(${str}, ${find}, ${replacement})`;
|
932
914
|
},
|
933
915
|
ExtractJSONPathAsText: (args, indent) => {
|
934
|
-
|
916
|
+
checkMinArgs('ExtractJSONPathAsText', args, 1);
|
935
917
|
if (engine !== "postgres") {
|
936
918
|
throw new SyntaxError('ExtractJSONPathAsText not supported on: ' + engine);
|
937
919
|
}
|
938
|
-
const json = JSONValue(
|
939
|
-
const path = TextValue(
|
920
|
+
const json = JSONValue(getAbstractSqlQuery(args, 0), indent);
|
921
|
+
const path = TextValue(getAbstractSqlQuery(args, 1), indent);
|
940
922
|
return `${json} #>> ${path}`;
|
941
923
|
},
|
942
924
|
CharacterLength: (args, indent) => {
|
943
|
-
|
944
|
-
const text = TextValue(
|
925
|
+
checkArgs('CharacterLength', args, 1);
|
926
|
+
const text = TextValue(getAbstractSqlQuery(args, 0), indent);
|
945
927
|
if (engine === "mysql") {
|
946
928
|
return `CHAR_LENGTH(${text})`;
|
947
929
|
}
|
@@ -950,9 +932,9 @@ const typeRules = {
|
|
950
932
|
}
|
951
933
|
},
|
952
934
|
StrPos: (args, indent) => {
|
953
|
-
|
954
|
-
const haystack = TextValue(
|
955
|
-
const needle = TextValue(
|
935
|
+
checkArgs('StrPos', args, 2);
|
936
|
+
const haystack = TextValue(getAbstractSqlQuery(args, 0), indent);
|
937
|
+
const needle = TextValue(getAbstractSqlQuery(args, 1), indent);
|
956
938
|
if (engine === "postgres") {
|
957
939
|
return `STRPOS(${haystack}, ${needle})`;
|
958
940
|
}
|
@@ -961,9 +943,9 @@ const typeRules = {
|
|
961
943
|
}
|
962
944
|
},
|
963
945
|
StartsWith: (args, indent) => {
|
964
|
-
|
965
|
-
const haystack = TextValue(
|
966
|
-
const needle = TextValue(
|
946
|
+
checkArgs('StartsWith', args, 2);
|
947
|
+
const haystack = TextValue(getAbstractSqlQuery(args, 0), indent);
|
948
|
+
const needle = TextValue(getAbstractSqlQuery(args, 1), indent);
|
967
949
|
if (engine === "postgres") {
|
968
950
|
return `STARTS_WITH(${haystack}, ${needle})`;
|
969
951
|
}
|
@@ -975,10 +957,10 @@ const typeRules = {
|
|
975
957
|
}
|
976
958
|
},
|
977
959
|
Substring: (args, indent) => {
|
978
|
-
|
979
|
-
const str = TextValue(
|
960
|
+
checkMinArgs('Substring', args, 2);
|
961
|
+
const str = TextValue(getAbstractSqlQuery(args, 0), indent);
|
980
962
|
const nums = args.slice(1).map((arg) => {
|
981
|
-
if (!
|
963
|
+
if (!isAbstractSqlQuery(arg)) {
|
982
964
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
983
965
|
}
|
984
966
|
return NumericValue(arg, indent);
|
@@ -986,9 +968,9 @@ const typeRules = {
|
|
986
968
|
return `SUBSTRING(${[str, ...nums].join(', ')})`;
|
987
969
|
},
|
988
970
|
Right: (args, indent) => {
|
989
|
-
|
990
|
-
const str = TextValue(
|
991
|
-
const n = NumericValue(
|
971
|
+
checkArgs('Right', args, 2);
|
972
|
+
const str = TextValue(getAbstractSqlQuery(args, 0), indent);
|
973
|
+
const n = NumericValue(getAbstractSqlQuery(args, 1), indent);
|
992
974
|
if (engine === "websql") {
|
993
975
|
return `SUBSTRING(${str}, -${n})`;
|
994
976
|
}
|
@@ -997,51 +979,46 @@ const typeRules = {
|
|
997
979
|
}
|
998
980
|
},
|
999
981
|
Lower: (args, indent) => {
|
1000
|
-
|
1001
|
-
const str = TextValue(
|
982
|
+
checkArgs('Lower', args, 1);
|
983
|
+
const str = TextValue(getAbstractSqlQuery(args, 0), indent);
|
1002
984
|
return `LOWER(${str})`;
|
1003
985
|
},
|
1004
986
|
Upper: (args, indent) => {
|
1005
|
-
|
1006
|
-
const str = TextValue(
|
987
|
+
checkArgs('Upper', args, 1);
|
988
|
+
const str = TextValue(getAbstractSqlQuery(args, 0), indent);
|
1007
989
|
return `UPPER(${str})`;
|
1008
990
|
},
|
1009
991
|
Trim: (args, indent) => {
|
1010
|
-
|
1011
|
-
const str = TextValue(
|
992
|
+
checkArgs('Trim', args, 1);
|
993
|
+
const str = TextValue(getAbstractSqlQuery(args, 0), indent);
|
1012
994
|
return `TRIM(${str})`;
|
1013
995
|
},
|
1014
996
|
Round: (args, indent) => {
|
1015
|
-
|
1016
|
-
const num = NumericValue(
|
997
|
+
checkArgs('Round', args, 1);
|
998
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
1017
999
|
return `ROUND(${num})`;
|
1018
1000
|
},
|
1019
1001
|
Floor: (args, indent) => {
|
1020
|
-
|
1021
|
-
const num = NumericValue(
|
1002
|
+
checkArgs('Floor', args, 1);
|
1003
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
1022
1004
|
return `FLOOR(${num})`;
|
1023
1005
|
},
|
1024
1006
|
Ceiling: (args, indent) => {
|
1025
|
-
|
1026
|
-
const num = NumericValue(
|
1007
|
+
checkArgs('Ceiling', args, 1);
|
1008
|
+
const num = NumericValue(getAbstractSqlQuery(args, 0), indent);
|
1027
1009
|
return `CEILING(${num})`;
|
1028
1010
|
},
|
1029
1011
|
ToDate: (args, indent) => {
|
1030
|
-
|
1031
|
-
const date = DateValue(
|
1012
|
+
checkArgs('ToDate', args, 1);
|
1013
|
+
const date = DateValue(getAbstractSqlQuery(args, 0), indent);
|
1032
1014
|
return `DATE(${date})`;
|
1033
1015
|
},
|
1034
1016
|
DateTrunc: (args, indent) => {
|
1035
|
-
(
|
1036
|
-
const precision = TextValue(
|
1037
|
-
const date = DateValue(
|
1017
|
+
checkArgs('DateTrunc', args, 2);
|
1018
|
+
const precision = TextValue(getAbstractSqlQuery(args, 0), indent);
|
1019
|
+
const date = DateValue(getAbstractSqlQuery(args, 1), indent);
|
1038
1020
|
if (engine === "postgres") {
|
1039
|
-
|
1040
|
-
? TextValue((0, exports.getAbstractSqlQuery)(args, 2), indent)
|
1041
|
-
: undefined;
|
1042
|
-
return timeZone
|
1043
|
-
? `DATE_TRUNC(${precision}, ${date}, ${timeZone})`
|
1044
|
-
: `DATE_TRUNC(${precision}, ${date})`;
|
1021
|
+
return `DATE_TRUNC(${precision}, ${date})`;
|
1045
1022
|
}
|
1046
1023
|
else if (precision === "'milliseconds'" ||
|
1047
1024
|
precision === "'microseconds'") {
|
@@ -1052,8 +1029,8 @@ const typeRules = {
|
|
1052
1029
|
}
|
1053
1030
|
},
|
1054
1031
|
ToTime: (args, indent) => {
|
1055
|
-
|
1056
|
-
const date = DateValue(
|
1032
|
+
checkArgs('ToTime', args, 1);
|
1033
|
+
const date = DateValue(getAbstractSqlQuery(args, 0), indent);
|
1057
1034
|
if (engine === "postgres") {
|
1058
1035
|
return `CAST(${date} AS TIME)`;
|
1059
1036
|
}
|
@@ -1062,26 +1039,26 @@ const typeRules = {
|
|
1062
1039
|
}
|
1063
1040
|
},
|
1064
1041
|
ToJSON: (args, indent) => {
|
1065
|
-
|
1042
|
+
checkMinArgs('ToJSON', args, 1);
|
1066
1043
|
if (engine !== "postgres") {
|
1067
1044
|
throw new SyntaxError('ToJSON not supported on: ' + engine);
|
1068
1045
|
}
|
1069
|
-
const value = AnyValue(
|
1046
|
+
const value = AnyValue(getAbstractSqlQuery(args, 0), indent);
|
1070
1047
|
return `TO_JSON(${value})`;
|
1071
1048
|
},
|
1072
1049
|
Any: (args, indent) => {
|
1073
|
-
|
1050
|
+
checkArgs('Any', args, 2);
|
1074
1051
|
if (engine !== "postgres") {
|
1075
1052
|
throw new SyntaxError('Any not supported on: ' + engine);
|
1076
1053
|
}
|
1077
|
-
const value = AnyValue(
|
1078
|
-
const innerType =
|
1054
|
+
const value = AnyValue(getAbstractSqlQuery(args, 0), indent);
|
1055
|
+
const innerType = sbvrTypes[args[1]].types[engine];
|
1079
1056
|
return `ANY(CAST(${value} AS ${innerType}[]))`;
|
1080
1057
|
},
|
1081
1058
|
Coalesce: (args, indent) => {
|
1082
|
-
|
1059
|
+
checkMinArgs('Coalesce', args, 2);
|
1083
1060
|
const comparators = args.map((arg) => {
|
1084
|
-
if (!
|
1061
|
+
if (!isAbstractSqlQuery(arg)) {
|
1085
1062
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
1086
1063
|
}
|
1087
1064
|
return AnyValue(arg, indent);
|
@@ -1089,27 +1066,27 @@ const typeRules = {
|
|
1089
1066
|
return 'COALESCE(' + comparators.join(', ') + ')';
|
1090
1067
|
},
|
1091
1068
|
Case: (args, indent) => {
|
1092
|
-
|
1069
|
+
checkMinArgs('Case', args, 1);
|
1093
1070
|
const nestedIndent = NestedIndent(indent);
|
1094
1071
|
const clauses = args
|
1095
1072
|
.map((arg, index) => {
|
1096
|
-
if (!
|
1073
|
+
if (!isAbstractSqlQuery(arg)) {
|
1097
1074
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
1098
1075
|
}
|
1099
1076
|
const [type, ...rest] = arg;
|
1100
1077
|
switch (type) {
|
1101
1078
|
case 'When': {
|
1102
|
-
|
1103
|
-
const matches = BooleanValue(
|
1104
|
-
const resultValue = AnyValue(
|
1079
|
+
checkArgs('When', rest, 2);
|
1080
|
+
const matches = BooleanValue(getAbstractSqlQuery(rest, 0), NestedIndent(nestedIndent));
|
1081
|
+
const resultValue = AnyValue(getAbstractSqlQuery(rest, 1), nestedIndent);
|
1105
1082
|
return 'WHEN ' + matches + ' THEN ' + resultValue;
|
1106
1083
|
}
|
1107
1084
|
case 'Else':
|
1108
1085
|
if (index !== args.length - 1) {
|
1109
1086
|
throw new SyntaxError('Else must be the last element of a Case');
|
1110
1087
|
}
|
1111
|
-
|
1112
|
-
return ('ELSE ' + AnyValue(
|
1088
|
+
checkArgs('Else', rest, 1);
|
1089
|
+
return ('ELSE ' + AnyValue(getAbstractSqlQuery(rest, 0), nestedIndent));
|
1113
1090
|
default:
|
1114
1091
|
throw new SyntaxError('Case can only contain When/Else');
|
1115
1092
|
}
|
@@ -1118,10 +1095,10 @@ const typeRules = {
|
|
1118
1095
|
return 'CASE' + nestedIndent + clauses + indent + 'END';
|
1119
1096
|
},
|
1120
1097
|
And: (args, indent) => {
|
1121
|
-
|
1098
|
+
checkMinArgs('And', args, 2);
|
1122
1099
|
return args
|
1123
1100
|
.map((arg) => {
|
1124
|
-
if (!
|
1101
|
+
if (!isAbstractSqlQuery(arg)) {
|
1125
1102
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
1126
1103
|
}
|
1127
1104
|
return BooleanValue(arg, indent);
|
@@ -1129,11 +1106,11 @@ const typeRules = {
|
|
1129
1106
|
.join(indent + 'AND ');
|
1130
1107
|
},
|
1131
1108
|
Or: (args, indent) => {
|
1132
|
-
|
1109
|
+
checkMinArgs('Or', args, 2);
|
1133
1110
|
return ('(' +
|
1134
1111
|
args
|
1135
1112
|
.map((arg) => {
|
1136
|
-
if (!
|
1113
|
+
if (!isAbstractSqlQuery(arg)) {
|
1137
1114
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
1138
1115
|
}
|
1139
1116
|
return BooleanValue(arg, indent);
|
@@ -1142,17 +1119,17 @@ const typeRules = {
|
|
1142
1119
|
')');
|
1143
1120
|
},
|
1144
1121
|
Bind: (args) => {
|
1145
|
-
|
1122
|
+
checkArgs('Bind', args, 1);
|
1146
1123
|
const bind = args[0];
|
1147
1124
|
return AddBind(['Bind', bind]);
|
1148
1125
|
},
|
1149
1126
|
Text,
|
1150
1127
|
Date: (args) => {
|
1151
|
-
|
1128
|
+
checkArgs('Date', args, 1);
|
1152
1129
|
return AddBind(['Date', args[0]]);
|
1153
1130
|
},
|
1154
1131
|
Duration: (args) => {
|
1155
|
-
|
1132
|
+
checkArgs('Duration', args, 1);
|
1156
1133
|
if (engine === "websql") {
|
1157
1134
|
throw new SyntaxError('Durations not supported on: ' + engine);
|
1158
1135
|
}
|
@@ -1180,8 +1157,8 @@ const typeRules = {
|
|
1180
1157
|
(engine === "mysql" ? ' DAY_MICROSECOND' : ''));
|
1181
1158
|
},
|
1182
1159
|
Exists: (args, indent) => {
|
1183
|
-
|
1184
|
-
const arg =
|
1160
|
+
checkArgs('Exists', args, 1);
|
1161
|
+
const arg = getAbstractSqlQuery(args, 0);
|
1185
1162
|
const [type, ...rest] = arg;
|
1186
1163
|
switch (type) {
|
1187
1164
|
case 'SelectQuery':
|
@@ -1195,8 +1172,8 @@ const typeRules = {
|
|
1195
1172
|
}
|
1196
1173
|
},
|
1197
1174
|
NotExists: (args, indent) => {
|
1198
|
-
|
1199
|
-
const arg =
|
1175
|
+
checkArgs('NotExists', args, 1);
|
1176
|
+
const arg = getAbstractSqlQuery(args, 0);
|
1200
1177
|
const [type, ...rest] = arg;
|
1201
1178
|
switch (type) {
|
1202
1179
|
case 'SelectQuery':
|
@@ -1210,16 +1187,16 @@ const typeRules = {
|
|
1210
1187
|
}
|
1211
1188
|
},
|
1212
1189
|
Not: (args, indent) => {
|
1213
|
-
|
1190
|
+
checkArgs('Not', args, 1);
|
1214
1191
|
const nestedIndent = NestedIndent(indent);
|
1215
|
-
const bool = BooleanValue(
|
1192
|
+
const bool = BooleanValue(getAbstractSqlQuery(args, 0), nestedIndent);
|
1216
1193
|
return 'NOT (' + nestedIndent + bool + indent + ')';
|
1217
1194
|
},
|
1218
1195
|
In: (args, indent) => {
|
1219
|
-
|
1220
|
-
const field = Field(
|
1196
|
+
checkMinArgs('In', args, 2);
|
1197
|
+
const field = Field(getAbstractSqlQuery(args, 0), indent);
|
1221
1198
|
const vals = args.slice(1).map((arg) => {
|
1222
|
-
if (!
|
1199
|
+
if (!isAbstractSqlQuery(arg)) {
|
1223
1200
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
1224
1201
|
}
|
1225
1202
|
return AnyValue(arg, indent);
|
@@ -1227,10 +1204,10 @@ const typeRules = {
|
|
1227
1204
|
return field + ' IN (' + vals.join(', ') + ')';
|
1228
1205
|
},
|
1229
1206
|
NotIn: (args, indent) => {
|
1230
|
-
|
1231
|
-
const field = Field(
|
1207
|
+
checkMinArgs('NotIn', args, 2);
|
1208
|
+
const field = Field(getAbstractSqlQuery(args, 0), indent);
|
1232
1209
|
const vals = args.slice(1).map((arg) => {
|
1233
|
-
if (!
|
1210
|
+
if (!isAbstractSqlQuery(arg)) {
|
1234
1211
|
throw new SyntaxError(`Expected AbstractSqlQuery array but got ${typeof arg}`);
|
1235
1212
|
}
|
1236
1213
|
return AnyValue(arg, indent);
|
@@ -1242,7 +1219,7 @@ const typeRules = {
|
|
1242
1219
|
let fields = [];
|
1243
1220
|
let values = [];
|
1244
1221
|
for (const arg of args) {
|
1245
|
-
if (!
|
1222
|
+
if (!isAbstractSqlQuery(arg)) {
|
1246
1223
|
throw new SyntaxError('`InsertQuery` args must all be arrays');
|
1247
1224
|
}
|
1248
1225
|
const [type, ...rest] = arg;
|
@@ -1251,14 +1228,14 @@ const typeRules = {
|
|
1251
1228
|
if (fields.length !== 0) {
|
1252
1229
|
throw new SyntaxError(`'InsertQuery' can only accept one '${type}'`);
|
1253
1230
|
}
|
1254
|
-
|
1255
|
-
fields =
|
1231
|
+
checkMinArgs('Update fields', rest, 1);
|
1232
|
+
fields = getAbstractSqlQuery(rest, 0).map(escapeField);
|
1256
1233
|
break;
|
1257
1234
|
case 'Values': {
|
1258
1235
|
if (values.length !== 0) {
|
1259
1236
|
throw new SyntaxError(`'InsertQuery' can only accept one '${type}'`);
|
1260
1237
|
}
|
1261
|
-
const valuesArray =
|
1238
|
+
const valuesArray = getAbstractSqlQuery(rest, 0);
|
1262
1239
|
if (valuesArray.length > 0) {
|
1263
1240
|
const [valuesType, ...valuesRest] = valuesArray;
|
1264
1241
|
switch (valuesType) {
|
@@ -1304,7 +1281,7 @@ const typeRules = {
|
|
1304
1281
|
let values = [];
|
1305
1282
|
let where = '';
|
1306
1283
|
for (const arg of args) {
|
1307
|
-
if (!
|
1284
|
+
if (!isAbstractSqlQuery(arg)) {
|
1308
1285
|
throw new SyntaxError('`UpdateQuery` args must all be arrays');
|
1309
1286
|
}
|
1310
1287
|
const [type, ...rest] = arg;
|
@@ -1313,16 +1290,16 @@ const typeRules = {
|
|
1313
1290
|
if (fields.length !== 0) {
|
1314
1291
|
throw new SyntaxError(`'UpdateQuery' can only accept one '${type}'`);
|
1315
1292
|
}
|
1316
|
-
|
1317
|
-
fields =
|
1293
|
+
checkMinArgs('Update fields', rest, 1);
|
1294
|
+
fields = getAbstractSqlQuery(rest, 0).map(escapeField);
|
1318
1295
|
break;
|
1319
1296
|
case 'Values': {
|
1320
1297
|
if (values.length !== 0) {
|
1321
1298
|
throw new SyntaxError(`'UpdateQuery' can only accept one '${type}'`);
|
1322
1299
|
}
|
1323
|
-
|
1324
|
-
const valuesArray =
|
1325
|
-
|
1300
|
+
checkArgs('Update values', rest, 1);
|
1301
|
+
const valuesArray = getAbstractSqlQuery(rest, 0);
|
1302
|
+
checkMinArgs('Update values array', valuesArray, 1);
|
1326
1303
|
values = valuesArray.map((v) => Value(v, indent));
|
1327
1304
|
break;
|
1328
1305
|
}
|
@@ -1354,7 +1331,7 @@ const typeRules = {
|
|
1354
1331
|
const tables = [];
|
1355
1332
|
let where = '';
|
1356
1333
|
for (const arg of args) {
|
1357
|
-
if (!
|
1334
|
+
if (!isAbstractSqlQuery(arg)) {
|
1358
1335
|
throw new SyntaxError('`DeleteQuery` args must all be arrays');
|
1359
1336
|
}
|
1360
1337
|
const [type, ...rest] = arg;
|
@@ -1375,8 +1352,8 @@ const typeRules = {
|
|
1375
1352
|
return 'DELETE FROM ' + tables.join(', ') + where;
|
1376
1353
|
},
|
1377
1354
|
EscapeForLike: (args, indent) => {
|
1378
|
-
|
1379
|
-
const textTypeNode =
|
1355
|
+
checkArgs('EscapeForLike', args, 1);
|
1356
|
+
const textTypeNode = getAbstractSqlQuery(args, 0);
|
1380
1357
|
return typeRules.Replace([
|
1381
1358
|
[
|
1382
1359
|
'Replace',
|
@@ -1403,7 +1380,7 @@ const toSqlResult = (query) => {
|
|
1403
1380
|
bindings: fieldOrderings,
|
1404
1381
|
};
|
1405
1382
|
};
|
1406
|
-
function AbstractSQLRules2SQL(abstractSQL, $engine, $noBinds = false) {
|
1383
|
+
export function AbstractSQLRules2SQL(abstractSQL, $engine, $noBinds = false) {
|
1407
1384
|
engine = $engine;
|
1408
1385
|
noBinds = $noBinds;
|
1409
1386
|
fieldOrderings = [];
|
@@ -1420,9 +1397,9 @@ function AbstractSQLRules2SQL(abstractSQL, $engine, $noBinds = false) {
|
|
1420
1397
|
return toSqlResult(query);
|
1421
1398
|
}
|
1422
1399
|
case 'UpsertQuery': {
|
1423
|
-
|
1424
|
-
const insertQuery =
|
1425
|
-
const updateQuery =
|
1400
|
+
checkArgs('UpsertQuery', rest, 2);
|
1401
|
+
const insertQuery = getAbstractSqlQuery(rest, 0);
|
1402
|
+
const updateQuery = getAbstractSqlQuery(rest, 1);
|
1426
1403
|
if (insertQuery[0] !== 'InsertQuery' ||
|
1427
1404
|
updateQuery[0] !== 'UpdateQuery') {
|
1428
1405
|
throw new SyntaxError('UpsertQuery must have [InsertQuery, UpdateQuery] provided');
|