data-finder-ts 0.1.3 → 0.1.5
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 +17 -55
- package/dist/chunk-BGEX377Q.js +230 -0
- package/dist/chunk-BGEX377Q.js.map +1 -0
- package/dist/chunk-BKPWV3OF.js +962 -0
- package/dist/chunk-BKPWV3OF.js.map +1 -0
- package/dist/{chunk-EYXBYV2X.js → chunk-GPHWC533.js} +2 -2
- package/dist/chunk-KAK75RVS.js +198 -0
- package/dist/chunk-KAK75RVS.js.map +1 -0
- package/dist/chunk-MGEL5RWM.js +628 -0
- package/dist/chunk-MGEL5RWM.js.map +1 -0
- package/dist/chunk-PF6EJZHB.js +1015 -0
- package/dist/chunk-PF6EJZHB.js.map +1 -0
- package/dist/datafinder/attribute.cjs +595 -18
- package/dist/datafinder/attribute.cjs.map +1 -1
- package/dist/datafinder/attribute.d.cts +73 -10
- package/dist/datafinder/attribute.d.ts +73 -10
- package/dist/datafinder/attribute.js +2 -2
- package/dist/datafinder/runner.cjs +1589 -288
- package/dist/datafinder/runner.cjs.map +1 -1
- package/dist/datafinder/runner.d.cts +41 -7
- package/dist/datafinder/runner.d.ts +41 -7
- package/dist/datafinder/runner.js +12 -6
- package/dist/datafinder/sql-generator.cjs +1484 -281
- package/dist/datafinder/sql-generator.cjs.map +1 -1
- package/dist/datafinder/sql-generator.d.cts +19 -14
- package/dist/datafinder/sql-generator.d.ts +19 -14
- package/dist/datafinder/sql-generator.js +9 -7
- package/dist/datafinder/typed-attributes.cjs +856 -93
- package/dist/datafinder/typed-attributes.cjs.map +1 -1
- package/dist/datafinder/typed-attributes.d.cts +3 -135
- package/dist/datafinder/typed-attributes.d.ts +3 -135
- package/dist/datafinder/typed-attributes.js +3 -3
- package/dist/dialect-CogGPm_y.d.cts +38 -0
- package/dist/dialect-aaG1bDi5.d.ts +38 -0
- package/dist/index.cjs +2080 -480
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +119 -14
- package/dist/index.d.ts +119 -14
- package/dist/index.js +362 -12
- package/dist/index.js.map +1 -1
- package/dist/model/milestoning.cjs +529 -0
- package/dist/model/milestoning.cjs.map +1 -1
- package/dist/model/milestoning.js +2 -2
- package/dist/model/relational.cjs +608 -12
- package/dist/model/relational.cjs.map +1 -1
- package/dist/model/relational.d.cts +456 -47
- package/dist/model/relational.d.ts +456 -47
- package/dist/model/relational.js +61 -3
- package/dist/typed-attributes-CUTf_6Ru.d.ts +328 -0
- package/dist/typed-attributes-CdWXq_78.d.cts +328 -0
- package/package.json +5 -2
- package/dist/chunk-3SSWFES4.js +0 -448
- package/dist/chunk-3SSWFES4.js.map +0 -1
- package/dist/chunk-5K2Z3YDY.js +0 -393
- package/dist/chunk-5K2Z3YDY.js.map +0 -1
- package/dist/chunk-6QTCGJWX.js +0 -98
- package/dist/chunk-6QTCGJWX.js.map +0 -1
- package/dist/chunk-DFYZVBII.js +0 -652
- package/dist/chunk-DFYZVBII.js.map +0 -1
- package/dist/chunk-V647VNMY.js +0 -135
- package/dist/chunk-V647VNMY.js.map +0 -1
- /package/dist/{chunk-EYXBYV2X.js.map → chunk-GPHWC533.js.map} +0 -0
|
@@ -20,37 +20,73 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/datafinder/runner.ts
|
|
21
21
|
var runner_exports = {};
|
|
22
22
|
__export(runner_exports, {
|
|
23
|
+
DEFAULT_TIMEOUT_MS: () => DEFAULT_TIMEOUT_MS,
|
|
23
24
|
FinderResult: () => FinderResult,
|
|
25
|
+
QueryTimeoutError: () => QueryTimeoutError,
|
|
24
26
|
clearRunner: () => clearRunner,
|
|
25
27
|
convertInputsAndSelect: () => convertInputsAndSelect,
|
|
28
|
+
convertInputsAndSelectForDateRange: () => convertInputsAndSelectForDateRange,
|
|
26
29
|
getRunner: () => getRunner,
|
|
27
30
|
registerRunner: () => registerRunner
|
|
28
31
|
});
|
|
29
32
|
module.exports = __toCommonJS(runner_exports);
|
|
30
33
|
|
|
31
34
|
// src/model/relational.ts
|
|
35
|
+
var LIKE_ESCAPE = "!";
|
|
36
|
+
function escapeLike(value) {
|
|
37
|
+
return value.replaceAll(LIKE_ESCAPE, LIKE_ESCAPE + LIKE_ESCAPE).replaceAll("%", LIKE_ESCAPE + "%").replaceAll("_", LIKE_ESCAPE + "_");
|
|
38
|
+
}
|
|
32
39
|
var RelationalOperationElement = class {
|
|
33
40
|
};
|
|
34
41
|
var Operation = class extends RelationalOperationElement {
|
|
35
|
-
|
|
42
|
+
/** Name this column in the result: `f.price().sum().alias('Total')`, `f.age().gt(30).alias('Adult')`. */
|
|
43
|
+
alias(name) {
|
|
44
|
+
return new Alias(this, name);
|
|
45
|
+
}
|
|
46
|
+
and(other) {
|
|
36
47
|
return new LogicalOperation(this, "AND" /* AND */, other);
|
|
37
48
|
}
|
|
49
|
+
/** Combine with `other` using OR. A chain reads left to right: `a.or(b).and(c)` is `(a OR b) AND c`. */
|
|
50
|
+
or(other) {
|
|
51
|
+
return new LogicalOperation(this, "OR" /* OR */, other);
|
|
52
|
+
}
|
|
38
53
|
};
|
|
39
54
|
var NoOperation = class extends Operation {
|
|
40
|
-
|
|
55
|
+
and(other) {
|
|
41
56
|
return other;
|
|
42
57
|
}
|
|
58
|
+
/** No filter matches every row, so OR-ing anything with it still matches every row. */
|
|
59
|
+
or(_other) {
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
43
62
|
};
|
|
44
63
|
var ConstantOperation = class extends RelationalOperationElement {
|
|
64
|
+
/** Name this column in the result. */
|
|
65
|
+
alias(name) {
|
|
66
|
+
return new Alias(this, name);
|
|
67
|
+
}
|
|
68
|
+
/** Sort by this expression, smallest first. */
|
|
69
|
+
ascending() {
|
|
70
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
71
|
+
}
|
|
72
|
+
/** Sort by this expression, largest first. */
|
|
73
|
+
descending() {
|
|
74
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var NumericConstantOperation = class extends ConstantOperation {
|
|
78
|
+
arithmeticOperand() {
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
45
81
|
};
|
|
46
|
-
var IntegerConstantOperation = class extends
|
|
82
|
+
var IntegerConstantOperation = class extends NumericConstantOperation {
|
|
47
83
|
constructor(value) {
|
|
48
84
|
super();
|
|
49
85
|
this.value = value;
|
|
50
86
|
}
|
|
51
87
|
value;
|
|
52
88
|
};
|
|
53
|
-
var FloatConstantOperation = class extends
|
|
89
|
+
var FloatConstantOperation = class extends NumericConstantOperation {
|
|
54
90
|
constructor(value) {
|
|
55
91
|
super();
|
|
56
92
|
this.value = value;
|
|
@@ -64,6 +100,9 @@ var StringConstantOperation = class extends ConstantOperation {
|
|
|
64
100
|
}
|
|
65
101
|
value;
|
|
66
102
|
};
|
|
103
|
+
var DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
104
|
+
var DateOnly = class extends Date {
|
|
105
|
+
};
|
|
67
106
|
var DateConstantOperation = class extends ConstantOperation {
|
|
68
107
|
constructor(value) {
|
|
69
108
|
super();
|
|
@@ -78,7 +117,7 @@ var DateTimeConstantOperation = class extends ConstantOperation {
|
|
|
78
117
|
}
|
|
79
118
|
value;
|
|
80
119
|
};
|
|
81
|
-
var DecimalConstantOperation = class extends
|
|
120
|
+
var DecimalConstantOperation = class extends NumericConstantOperation {
|
|
82
121
|
constructor(value) {
|
|
83
122
|
super();
|
|
84
123
|
this.value = value;
|
|
@@ -112,6 +151,20 @@ var IsNullOperation = class extends UnaryOperation {
|
|
|
112
151
|
};
|
|
113
152
|
var IsNotNullOperation = class extends UnaryOperation {
|
|
114
153
|
};
|
|
154
|
+
var InOperation = class extends UnaryOperation {
|
|
155
|
+
constructor(element, values) {
|
|
156
|
+
super(element);
|
|
157
|
+
this.values = values;
|
|
158
|
+
}
|
|
159
|
+
values;
|
|
160
|
+
};
|
|
161
|
+
var NotInOperation = class extends UnaryOperation {
|
|
162
|
+
constructor(element, values) {
|
|
163
|
+
super(element);
|
|
164
|
+
this.values = values;
|
|
165
|
+
}
|
|
166
|
+
values;
|
|
167
|
+
};
|
|
115
168
|
var ComparisonOperation = class extends BinaryOperation {
|
|
116
169
|
constructor(left, operator, right) {
|
|
117
170
|
super(left, right);
|
|
@@ -135,21 +188,41 @@ var WindowSpecification = class {
|
|
|
135
188
|
orderBy;
|
|
136
189
|
};
|
|
137
190
|
var AggregateOperation = class _AggregateOperation extends UnaryOperation {
|
|
138
|
-
constructor(element, operator, displayName, window) {
|
|
191
|
+
constructor(element, operator, displayName, window, separator, orderBy = []) {
|
|
139
192
|
super(element);
|
|
140
193
|
this.operator = operator;
|
|
141
194
|
this.displayName = displayName;
|
|
142
195
|
this.window = window;
|
|
196
|
+
this.separator = separator;
|
|
197
|
+
this.orderBy = orderBy;
|
|
143
198
|
}
|
|
144
199
|
operator;
|
|
145
200
|
displayName;
|
|
146
201
|
window;
|
|
202
|
+
separator;
|
|
203
|
+
orderBy;
|
|
204
|
+
/** Sort by this expression, smallest first. */
|
|
205
|
+
ascending() {
|
|
206
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
207
|
+
}
|
|
208
|
+
/** Sort by this expression, largest first. */
|
|
209
|
+
descending() {
|
|
210
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
211
|
+
}
|
|
212
|
+
arithmeticOperand() {
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
comparisonOperand() {
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
147
218
|
over(partitionBy, orderBy) {
|
|
148
219
|
return new _AggregateOperation(
|
|
149
220
|
this.element,
|
|
150
221
|
this.operator,
|
|
151
222
|
this.displayName,
|
|
152
|
-
new WindowSpecification(partitionBy ?? [], orderBy ?? [])
|
|
223
|
+
new WindowSpecification(partitionBy ?? [], orderBy ?? []),
|
|
224
|
+
this.separator,
|
|
225
|
+
this.orderBy
|
|
153
226
|
);
|
|
154
227
|
}
|
|
155
228
|
};
|
|
@@ -167,6 +240,14 @@ var WindowFunctionOperation = class _WindowFunctionOperation extends UnaryOperat
|
|
|
167
240
|
secondArg;
|
|
168
241
|
extraArgs;
|
|
169
242
|
window;
|
|
243
|
+
/** Sort by this expression, smallest first. */
|
|
244
|
+
ascending() {
|
|
245
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
246
|
+
}
|
|
247
|
+
/** Sort by this expression, largest first. */
|
|
248
|
+
descending() {
|
|
249
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
250
|
+
}
|
|
170
251
|
over(partitionBy, orderBy) {
|
|
171
252
|
return new _WindowFunctionOperation(
|
|
172
253
|
this.element,
|
|
@@ -190,7 +271,38 @@ var ScalarFunctionOperation = class extends UnaryOperation {
|
|
|
190
271
|
displayName;
|
|
191
272
|
secondArg;
|
|
192
273
|
extraArgs;
|
|
274
|
+
/** Sort by this expression, smallest first. */
|
|
275
|
+
ascending() {
|
|
276
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
277
|
+
}
|
|
278
|
+
/** Sort by this expression, largest first. */
|
|
279
|
+
descending() {
|
|
280
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
281
|
+
}
|
|
282
|
+
/** This expression as an operand of a comparison. */
|
|
283
|
+
comparisonOperand() {
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
arithmeticOperand() {
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
/** Only a function that gives a number can be used in arithmetic. */
|
|
290
|
+
assertNumeric() {
|
|
291
|
+
if (!NUMERIC_FUNCTIONS.has(this.func)) {
|
|
292
|
+
throw new TypeError(`${this.func} does not give a number, so it cannot be used in arithmetic`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
193
295
|
};
|
|
296
|
+
var NUMERIC_FUNCTIONS = /* @__PURE__ */ new Set([
|
|
297
|
+
"ABS" /* ABS */,
|
|
298
|
+
"CEILING" /* CEILING */,
|
|
299
|
+
"FLOOR" /* FLOOR */,
|
|
300
|
+
"MOD" /* MOD */,
|
|
301
|
+
"POWER" /* POWER */,
|
|
302
|
+
"SQRT" /* SQRT */,
|
|
303
|
+
"ROUND" /* ROUND */,
|
|
304
|
+
"LENGTH" /* LENGTH */
|
|
305
|
+
]);
|
|
194
306
|
var DateExtractOperation = class extends UnaryOperation {
|
|
195
307
|
constructor(element, part, displayName) {
|
|
196
308
|
super(element);
|
|
@@ -199,6 +311,34 @@ var DateExtractOperation = class extends UnaryOperation {
|
|
|
199
311
|
}
|
|
200
312
|
part;
|
|
201
313
|
displayName;
|
|
314
|
+
/** Sort by this expression, smallest first. */
|
|
315
|
+
ascending() {
|
|
316
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
317
|
+
}
|
|
318
|
+
/** Sort by this expression, largest first. */
|
|
319
|
+
descending() {
|
|
320
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
var DateTruncOperation = class extends UnaryOperation {
|
|
324
|
+
constructor(element, part, displayName) {
|
|
325
|
+
super(element);
|
|
326
|
+
this.part = part;
|
|
327
|
+
this.displayName = displayName;
|
|
328
|
+
}
|
|
329
|
+
part;
|
|
330
|
+
displayName;
|
|
331
|
+
/** Sort by this expression, earliest first. */
|
|
332
|
+
ascending() {
|
|
333
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
334
|
+
}
|
|
335
|
+
/** Sort by this expression, latest first. */
|
|
336
|
+
descending() {
|
|
337
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
338
|
+
}
|
|
339
|
+
comparisonOperand() {
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
202
342
|
};
|
|
203
343
|
var DateArithmeticOperation = class extends UnaryOperation {
|
|
204
344
|
constructor(element, n, unit, isAdd = true, displayName) {
|
|
@@ -212,6 +352,14 @@ var DateArithmeticOperation = class extends UnaryOperation {
|
|
|
212
352
|
unit;
|
|
213
353
|
isAdd;
|
|
214
354
|
displayName;
|
|
355
|
+
/** Sort by this expression, smallest first. */
|
|
356
|
+
ascending() {
|
|
357
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
358
|
+
}
|
|
359
|
+
/** Sort by this expression, largest first. */
|
|
360
|
+
descending() {
|
|
361
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
362
|
+
}
|
|
215
363
|
};
|
|
216
364
|
var DateDiffOperation = class extends UnaryOperation {
|
|
217
365
|
constructor(element, other, unit, displayName) {
|
|
@@ -223,20 +371,31 @@ var DateDiffOperation = class extends UnaryOperation {
|
|
|
223
371
|
other;
|
|
224
372
|
unit;
|
|
225
373
|
displayName;
|
|
374
|
+
/** Sort by this expression, smallest first. */
|
|
375
|
+
ascending() {
|
|
376
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
377
|
+
}
|
|
378
|
+
/** Sort by this expression, largest first. */
|
|
379
|
+
descending() {
|
|
380
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
381
|
+
}
|
|
226
382
|
};
|
|
227
383
|
var Column = class extends RelationalOperationElement {
|
|
228
|
-
constructor(name, type, owner, primaryKey = false) {
|
|
384
|
+
constructor(name, type, owner, primaryKey = false, nullable = true) {
|
|
229
385
|
super();
|
|
230
386
|
this.name = name;
|
|
231
387
|
this.type = type;
|
|
232
388
|
this.owner = owner;
|
|
233
389
|
this.primaryKey = primaryKey;
|
|
390
|
+
this.nullable = nullable && !primaryKey;
|
|
234
391
|
}
|
|
235
392
|
name;
|
|
236
393
|
type;
|
|
237
394
|
owner;
|
|
238
395
|
primaryKey;
|
|
239
396
|
table;
|
|
397
|
+
/** Whether the column may hold NULL. As in Legend, a primary key is never null. */
|
|
398
|
+
nullable;
|
|
240
399
|
};
|
|
241
400
|
var Table = class {
|
|
242
401
|
constructor(name, columns, schema) {
|
|
@@ -265,13 +424,28 @@ var Table = class {
|
|
|
265
424
|
}
|
|
266
425
|
};
|
|
267
426
|
var ColumnWithJoin = class extends RelationalOperationElement {
|
|
268
|
-
|
|
427
|
+
/**
|
|
428
|
+
* `embedded` is an alternate reference to a flat (denormalized) column on the owning table that
|
|
429
|
+
* holds the same value without the join; the SQL generator uses it when the join can be elided.
|
|
430
|
+
*/
|
|
431
|
+
constructor(column, parent, embedded, _optional = false) {
|
|
269
432
|
super();
|
|
270
433
|
this.column = column;
|
|
271
434
|
this.parent = parent;
|
|
435
|
+
this.embedded = embedded;
|
|
436
|
+
this._optional = _optional;
|
|
272
437
|
}
|
|
273
438
|
column;
|
|
274
439
|
parent;
|
|
440
|
+
embedded;
|
|
441
|
+
_optional;
|
|
442
|
+
/** Whether the value can be missing: its property is optional, or a navigation on the way to it is. */
|
|
443
|
+
get optional() {
|
|
444
|
+
for (let node = this.parent; node !== void 0; node = node.parent) {
|
|
445
|
+
if (node.optional) return true;
|
|
446
|
+
}
|
|
447
|
+
return this._optional;
|
|
448
|
+
}
|
|
275
449
|
};
|
|
276
450
|
var SortOperation = class {
|
|
277
451
|
constructor(column, direction) {
|
|
@@ -287,19 +461,366 @@ var CountAllOperation = class extends RelationalOperationElement {
|
|
|
287
461
|
this.table = table;
|
|
288
462
|
}
|
|
289
463
|
table;
|
|
464
|
+
/** Name this column in the result. */
|
|
465
|
+
alias(name) {
|
|
466
|
+
return new Alias(this, name);
|
|
467
|
+
}
|
|
468
|
+
/** Sort by this expression, smallest first. */
|
|
469
|
+
ascending() {
|
|
470
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
471
|
+
}
|
|
472
|
+
/** Sort by this expression, largest first. */
|
|
473
|
+
descending() {
|
|
474
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
475
|
+
}
|
|
476
|
+
comparisonOperand() {
|
|
477
|
+
return this;
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
var Alias = class _Alias extends RelationalOperationElement {
|
|
481
|
+
constructor(element, name) {
|
|
482
|
+
super();
|
|
483
|
+
this.element = element;
|
|
484
|
+
this.name = name;
|
|
485
|
+
}
|
|
486
|
+
element;
|
|
487
|
+
name;
|
|
488
|
+
alias(name) {
|
|
489
|
+
return new _Alias(this.element, name);
|
|
490
|
+
}
|
|
491
|
+
/** Sorts by the column the alias names. */
|
|
492
|
+
ascending() {
|
|
493
|
+
return new SortOperation(this.element, "ASC" /* ASC */);
|
|
494
|
+
}
|
|
495
|
+
/** Sorts by the column the alias names. */
|
|
496
|
+
descending() {
|
|
497
|
+
return new SortOperation(this.element, "DESC" /* DESC */);
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
var CaseOperation = class extends Operation {
|
|
501
|
+
constructor(condition, then, fallback, displayName) {
|
|
502
|
+
super();
|
|
503
|
+
this.condition = condition;
|
|
504
|
+
this.then = then;
|
|
505
|
+
this.fallback = fallback;
|
|
506
|
+
this.displayName = displayName;
|
|
507
|
+
}
|
|
508
|
+
condition;
|
|
509
|
+
then;
|
|
510
|
+
fallback;
|
|
511
|
+
displayName;
|
|
290
512
|
};
|
|
513
|
+
var ExistsOperation = class extends RelationalOperationElement {
|
|
514
|
+
constructor(node) {
|
|
515
|
+
super();
|
|
516
|
+
this.node = node;
|
|
517
|
+
}
|
|
518
|
+
node;
|
|
519
|
+
/** Name this column in the result. */
|
|
520
|
+
alias(name) {
|
|
521
|
+
return new Alias(this, name);
|
|
522
|
+
}
|
|
523
|
+
and(other) {
|
|
524
|
+
return new LogicalOperation(this, "AND" /* AND */, other);
|
|
525
|
+
}
|
|
526
|
+
or(other) {
|
|
527
|
+
return new LogicalOperation(this, "OR" /* OR */, other);
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
var NotExistsOperation = class extends RelationalOperationElement {
|
|
531
|
+
constructor(node) {
|
|
532
|
+
super();
|
|
533
|
+
this.node = node;
|
|
534
|
+
}
|
|
535
|
+
node;
|
|
536
|
+
/** Name this column in the result. */
|
|
537
|
+
alias(name) {
|
|
538
|
+
return new Alias(this, name);
|
|
539
|
+
}
|
|
540
|
+
and(other) {
|
|
541
|
+
return new LogicalOperation(this, "AND" /* AND */, other);
|
|
542
|
+
}
|
|
543
|
+
or(other) {
|
|
544
|
+
return new LogicalOperation(this, "OR" /* OR */, other);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
var SelectOperation = class {
|
|
548
|
+
constructor(display, filter, orderBy = [], groupBy = [], limit, table, joinFilters = /* @__PURE__ */ new Map(), distinct = false, offset, having) {
|
|
549
|
+
this.display = display;
|
|
550
|
+
this.filter = filter;
|
|
551
|
+
this.orderBy = orderBy;
|
|
552
|
+
this.groupBy = groupBy;
|
|
553
|
+
this.limit = limit;
|
|
554
|
+
this.table = table;
|
|
555
|
+
this.joinFilters = joinFilters;
|
|
556
|
+
this.distinct = distinct;
|
|
557
|
+
this.offset = offset;
|
|
558
|
+
this.having = having;
|
|
559
|
+
}
|
|
560
|
+
display;
|
|
561
|
+
filter;
|
|
562
|
+
orderBy;
|
|
563
|
+
groupBy;
|
|
564
|
+
limit;
|
|
565
|
+
table;
|
|
566
|
+
joinFilters;
|
|
567
|
+
distinct;
|
|
568
|
+
offset;
|
|
569
|
+
having;
|
|
570
|
+
};
|
|
571
|
+
function containsAggregateOrWindow(op) {
|
|
572
|
+
if (op instanceof AggregateOperation || op instanceof WindowFunctionOperation || op instanceof CountAllOperation) return true;
|
|
573
|
+
if (op instanceof BinaryOperation) return containsAggregateOrWindow(op.left) || containsAggregateOrWindow(op.right);
|
|
574
|
+
if (op instanceof UnaryOperation || op instanceof Alias) return containsAggregateOrWindow(op.element);
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
function containsAggregate(op) {
|
|
578
|
+
if (op instanceof AggregateOperation || op instanceof CountAllOperation) return true;
|
|
579
|
+
if (op instanceof BinaryOperation) return containsAggregate(op.left) || containsAggregate(op.right);
|
|
580
|
+
if (op instanceof UnaryOperation || op instanceof Alias) return containsAggregate(op.element);
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
function valueOperand(value) {
|
|
584
|
+
if (typeof value === "boolean") return new BooleanConstantOperation(value);
|
|
585
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
586
|
+
return Number.isInteger(value) ? new IntegerConstantOperation(value) : new FloatConstantOperation(value);
|
|
587
|
+
}
|
|
588
|
+
if (typeof value === "string") return new StringConstantOperation(value);
|
|
589
|
+
if (value instanceof DateOnly) return new DateConstantOperation(value);
|
|
590
|
+
if (value instanceof Date) return new DateTimeConstantOperation(value);
|
|
591
|
+
throw new TypeError(`A value to compare with is a boolean, a finite number, a string or a date, not ${value === null ? "null" : typeof value}`);
|
|
592
|
+
}
|
|
593
|
+
function operandOf(other) {
|
|
594
|
+
if (other instanceof RelationalOperationElement) return other;
|
|
595
|
+
if (typeof other?.cwj === "function") return other.cwj();
|
|
596
|
+
return valueOperand(other);
|
|
597
|
+
}
|
|
598
|
+
var Comparable = class {
|
|
599
|
+
_compared(operator, other) {
|
|
600
|
+
return new ComparisonOperation(this.comparisonOperand(), operator, operandOf(other));
|
|
601
|
+
}
|
|
602
|
+
/** Filter to rows where this expression equals `other`. */
|
|
603
|
+
eq(other) {
|
|
604
|
+
return this._compared("EQUAL" /* EQUAL */, other);
|
|
605
|
+
}
|
|
606
|
+
/** Filter to rows where this expression does not equal `other`. */
|
|
607
|
+
ne(other) {
|
|
608
|
+
return this._compared("NOT_EQUAL" /* NOT_EQUAL */, other);
|
|
609
|
+
}
|
|
610
|
+
/** Filter to rows where this expression is less than `other`. */
|
|
611
|
+
lt(other) {
|
|
612
|
+
return this._compared("LESS_THAN" /* LESS_THAN */, other);
|
|
613
|
+
}
|
|
614
|
+
/** Filter to rows where this expression is at most `other`. */
|
|
615
|
+
lte(other) {
|
|
616
|
+
return this._compared("LESS_THAN_OR_EQUAL_TO" /* LESS_THAN_OR_EQUAL_TO */, other);
|
|
617
|
+
}
|
|
618
|
+
/** Filter to rows where this expression is greater than `other`. */
|
|
619
|
+
gt(other) {
|
|
620
|
+
return this._compared("GREATER_THAN" /* GREATER_THAN */, other);
|
|
621
|
+
}
|
|
622
|
+
/** Filter to rows where this expression is at least `other`. */
|
|
623
|
+
gte(other) {
|
|
624
|
+
return this._compared("GREATER_THAN_OR_EQUAL_TO" /* GREATER_THAN_OR_EQUAL_TO */, other);
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
function sample(ddof) {
|
|
628
|
+
if (ddof !== 0 && ddof !== 1) throw new RangeError(`ddof is 0 (population) or 1 (sample), not ${ddof}`);
|
|
629
|
+
return ddof === 1;
|
|
630
|
+
}
|
|
631
|
+
var StringPredicates = class {
|
|
632
|
+
_like(pattern) {
|
|
633
|
+
return new ComparisonOperation(this.comparisonOperand(), "LIKE" /* LIKE */, new StringConstantOperation(pattern));
|
|
634
|
+
}
|
|
635
|
+
/** Filter to rows where this text contains `value`. */
|
|
636
|
+
contains(value) {
|
|
637
|
+
return this._like(`%${escapeLike(value)}%`);
|
|
638
|
+
}
|
|
639
|
+
/** Filter to rows where this text starts with `prefix`. */
|
|
640
|
+
startsWith(prefix) {
|
|
641
|
+
return this._like(`${escapeLike(prefix)}%`);
|
|
642
|
+
}
|
|
643
|
+
/** Filter to rows where this text ends with `suffix`. */
|
|
644
|
+
endsWith(suffix) {
|
|
645
|
+
return this._like(`%${escapeLike(suffix)}`);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
var Aggregates = class {
|
|
649
|
+
_aggregate(operator, label) {
|
|
650
|
+
return new AggregateOperation(this, operator, label + " Expression");
|
|
651
|
+
}
|
|
652
|
+
/** Sum of the values in the group. */
|
|
653
|
+
sum() {
|
|
654
|
+
return this._aggregate("SUM" /* SUM */, "Sum");
|
|
655
|
+
}
|
|
656
|
+
/** Smallest value in the group. */
|
|
657
|
+
min() {
|
|
658
|
+
return this._aggregate("MIN" /* MIN */, "Min");
|
|
659
|
+
}
|
|
660
|
+
/** Largest value in the group. */
|
|
661
|
+
max() {
|
|
662
|
+
return this._aggregate("MAX" /* MAX */, "Max");
|
|
663
|
+
}
|
|
664
|
+
/** Arithmetic mean of the values in the group. */
|
|
665
|
+
average() {
|
|
666
|
+
return this._aggregate("AVERAGE" /* AVERAGE */, "Average");
|
|
667
|
+
}
|
|
668
|
+
/** Number of non-null values in the group. */
|
|
669
|
+
count() {
|
|
670
|
+
return this._aggregate("COUNT" /* COUNT */, "Count");
|
|
671
|
+
}
|
|
672
|
+
/** Standard deviation of the values in the group: the sample one by default, `ddof = 0` for the population one. */
|
|
673
|
+
std(ddof = 1) {
|
|
674
|
+
return this._aggregate(sample(ddof) ? "STDDEV_SAMP" /* STDDEV_SAMP */ : "STDDEV_POP" /* STDDEV_POP */, "Std");
|
|
675
|
+
}
|
|
676
|
+
/** Variance of the values in the group: the sample one by default, `ddof = 0` for the population one. */
|
|
677
|
+
var(ddof = 1) {
|
|
678
|
+
return this._aggregate(sample(ddof) ? "VAR_SAMP" /* VAR_SAMP */ : "VAR_POP" /* VAR_POP */, "Var");
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
var BooleanAggregates = class {
|
|
682
|
+
/** True for a group where every row satisfies the condition. */
|
|
683
|
+
all() {
|
|
684
|
+
return new AggregateOperation(this, "BOOL_AND" /* BOOL_AND */, "All Expression");
|
|
685
|
+
}
|
|
686
|
+
/** True for a group where at least one row satisfies the condition. */
|
|
687
|
+
any() {
|
|
688
|
+
return new AggregateOperation(this, "BOOL_OR" /* BOOL_OR */, "Any Expression");
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
function applyMixins(derived, bases) {
|
|
692
|
+
for (const base of bases) {
|
|
693
|
+
for (const name of Object.getOwnPropertyNames(base.prototype)) {
|
|
694
|
+
if (name === "constructor" || Object.prototype.hasOwnProperty.call(derived.prototype, name)) continue;
|
|
695
|
+
Object.defineProperty(derived.prototype, name, Object.getOwnPropertyDescriptor(base.prototype, name));
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
var Arithmetic = class {
|
|
700
|
+
/** Raises if this expression is not a number. */
|
|
701
|
+
assertNumeric() {
|
|
702
|
+
}
|
|
703
|
+
_arithmetic(operator, other) {
|
|
704
|
+
this.assertNumeric();
|
|
705
|
+
let operand;
|
|
706
|
+
if (typeof other === "number") {
|
|
707
|
+
if (!Number.isFinite(other)) throw new TypeError("Arithmetic is between numbers and numeric columns, not a non-finite number");
|
|
708
|
+
operand = valueOperand(other);
|
|
709
|
+
} else if (other !== null && typeof other === "object" && typeof other.arithmeticOperand === "function") {
|
|
710
|
+
other.assertNumeric?.();
|
|
711
|
+
operand = other.arithmeticOperand();
|
|
712
|
+
} else {
|
|
713
|
+
throw new TypeError(`Arithmetic is between numbers and numeric columns, not ${other === null ? "null" : typeof other}`);
|
|
714
|
+
}
|
|
715
|
+
return new ArithmeticOperation(this.arithmeticOperand(), operator, operand);
|
|
716
|
+
}
|
|
717
|
+
/** `this + other`. */
|
|
718
|
+
plus(other) {
|
|
719
|
+
return this._arithmetic("+" /* ADD */, other);
|
|
720
|
+
}
|
|
721
|
+
/** `this - other`. */
|
|
722
|
+
minus(other) {
|
|
723
|
+
return this._arithmetic("-" /* SUBTRACT */, other);
|
|
724
|
+
}
|
|
725
|
+
/** `this * other`. */
|
|
726
|
+
times(other) {
|
|
727
|
+
return this._arithmetic("*" /* MULTIPLY */, other);
|
|
728
|
+
}
|
|
729
|
+
/** `this / other`. */
|
|
730
|
+
dividedBy(other) {
|
|
731
|
+
return this._arithmetic("/" /* DIVIDE */, other);
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
var ArithmeticOperation = class extends BinaryOperation {
|
|
735
|
+
constructor(left, operator, right, displayName) {
|
|
736
|
+
super(left, right);
|
|
737
|
+
this.operator = operator;
|
|
738
|
+
this.displayName = displayName;
|
|
739
|
+
}
|
|
740
|
+
operator;
|
|
741
|
+
displayName;
|
|
742
|
+
/** Sort by this expression, smallest first. */
|
|
743
|
+
ascending() {
|
|
744
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
745
|
+
}
|
|
746
|
+
/** Sort by this expression, largest first. */
|
|
747
|
+
descending() {
|
|
748
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
749
|
+
}
|
|
750
|
+
arithmeticOperand() {
|
|
751
|
+
return this;
|
|
752
|
+
}
|
|
753
|
+
comparisonOperand() {
|
|
754
|
+
return this;
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
var ConcatOperation = class extends Operation {
|
|
758
|
+
constructor(parts, displayName) {
|
|
759
|
+
super();
|
|
760
|
+
this.parts = parts;
|
|
761
|
+
this.displayName = displayName;
|
|
762
|
+
}
|
|
763
|
+
parts;
|
|
764
|
+
displayName;
|
|
765
|
+
/** Join more text on the end: `f.first().concat(' ', f.last())`. A concatenation joins into one. */
|
|
766
|
+
concat(...more) {
|
|
767
|
+
return concat(this, ...more);
|
|
768
|
+
}
|
|
769
|
+
/** Sort by this expression, smallest first. */
|
|
770
|
+
ascending() {
|
|
771
|
+
return new SortOperation(this, "ASC" /* ASC */);
|
|
772
|
+
}
|
|
773
|
+
/** Sort by this expression, largest first. */
|
|
774
|
+
descending() {
|
|
775
|
+
return new SortOperation(this, "DESC" /* DESC */);
|
|
776
|
+
}
|
|
777
|
+
comparisonOperand() {
|
|
778
|
+
return this;
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
function concat(...parts) {
|
|
782
|
+
const partsOf = (part) => {
|
|
783
|
+
if (part instanceof ConcatOperation) return part.parts;
|
|
784
|
+
if (typeof part === "string") return [new StringConstantOperation(part)];
|
|
785
|
+
if (part instanceof RelationalOperationElement) return [part];
|
|
786
|
+
if (part !== null && typeof part === "object" && typeof part.functionInput === "function") return [part.functionInput()];
|
|
787
|
+
throw new TypeError(`Text is joined with text, not ${part === null ? "null" : typeof part}`);
|
|
788
|
+
};
|
|
789
|
+
return new ConcatOperation(parts.flatMap(partsOf));
|
|
790
|
+
}
|
|
791
|
+
applyMixins(ConcatOperation, [Comparable, StringPredicates]);
|
|
792
|
+
applyMixins(DateTruncOperation, [Comparable]);
|
|
793
|
+
applyMixins(ArithmeticOperation, [Arithmetic, Comparable]);
|
|
794
|
+
applyMixins(ScalarFunctionOperation, [Comparable, Arithmetic, StringPredicates]);
|
|
795
|
+
applyMixins(AggregateOperation, [Arithmetic, Comparable, StringPredicates]);
|
|
796
|
+
applyMixins(CountAllOperation, [Comparable]);
|
|
797
|
+
applyMixins(NumericConstantOperation, [Arithmetic]);
|
|
798
|
+
applyMixins(ConstantOperation, [Aggregates]);
|
|
799
|
+
applyMixins(ArithmeticOperation, [Aggregates]);
|
|
800
|
+
applyMixins(ScalarFunctionOperation, [Aggregates]);
|
|
801
|
+
applyMixins(CaseOperation, [Aggregates]);
|
|
802
|
+
applyMixins(IsNullOperation, [BooleanAggregates]);
|
|
803
|
+
applyMixins(IsNotNullOperation, [BooleanAggregates]);
|
|
804
|
+
applyMixins(InOperation, [BooleanAggregates]);
|
|
805
|
+
applyMixins(NotInOperation, [BooleanAggregates]);
|
|
806
|
+
applyMixins(ComparisonOperation, [BooleanAggregates]);
|
|
807
|
+
applyMixins(LogicalOperation, [BooleanAggregates]);
|
|
291
808
|
|
|
292
809
|
// src/datafinder/attribute.ts
|
|
293
|
-
var Attribute = class {
|
|
810
|
+
var Attribute = class _Attribute {
|
|
294
811
|
_displayName;
|
|
295
812
|
_column;
|
|
296
813
|
_owner;
|
|
297
814
|
_parent;
|
|
298
|
-
|
|
815
|
+
_embedded;
|
|
816
|
+
_optional;
|
|
817
|
+
constructor(displayName, columnName, columnDbType, owner, parent, embedded, nullable = true, optional = false) {
|
|
818
|
+
this._optional = optional;
|
|
299
819
|
this._displayName = displayName;
|
|
300
|
-
this._column = new Column(columnName, columnDbType, owner);
|
|
820
|
+
this._column = new Column(columnName, columnDbType, owner, false, nullable);
|
|
301
821
|
this._owner = owner;
|
|
302
822
|
this._parent = parent;
|
|
823
|
+
this._embedded = embedded;
|
|
303
824
|
}
|
|
304
825
|
column() {
|
|
305
826
|
return this._column;
|
|
@@ -313,33 +834,102 @@ var Attribute = class {
|
|
|
313
834
|
displayName() {
|
|
314
835
|
return this._displayName;
|
|
315
836
|
}
|
|
837
|
+
/** Alternate attribute on a flat column of the owning table, used in place of this one when its join is elided. */
|
|
838
|
+
embedded() {
|
|
839
|
+
return this._embedded;
|
|
840
|
+
}
|
|
841
|
+
/** @internal The expression a function of this attribute applies to: its column. */
|
|
842
|
+
functionInput() {
|
|
843
|
+
return this.cwj();
|
|
844
|
+
}
|
|
845
|
+
/** @internal What a function of this attribute is labelled after: its display name. */
|
|
846
|
+
functionLabel() {
|
|
847
|
+
return this._displayName;
|
|
848
|
+
}
|
|
849
|
+
/** @internal This attribute as an operand of arithmetic: its column. */
|
|
850
|
+
arithmeticOperand() {
|
|
851
|
+
return this.cwj();
|
|
852
|
+
}
|
|
316
853
|
cwj() {
|
|
317
|
-
return new ColumnWithJoin(this._column, this._parent);
|
|
854
|
+
return new ColumnWithJoin(this._column, this._parent, this._embedded?.cwj(), this._optional);
|
|
318
855
|
}
|
|
856
|
+
/** Count the number of non-null values. Use in a projection with `groupBy` to aggregate per group. */
|
|
319
857
|
count() {
|
|
320
858
|
return new AggregateOperation(
|
|
321
|
-
|
|
859
|
+
this.cwj(),
|
|
322
860
|
"COUNT" /* COUNT */,
|
|
323
861
|
this._displayName + " Count"
|
|
324
862
|
);
|
|
325
863
|
}
|
|
864
|
+
/** Name this column in the result: `f.price().sum().alias('Total')`. */
|
|
865
|
+
alias(name) {
|
|
866
|
+
return new Alias(this, name);
|
|
867
|
+
}
|
|
868
|
+
/** The number of different non-NULL values in the group: `COUNT(DISTINCT column)`. Use with `groupBy` to count per group. */
|
|
869
|
+
countDistinct() {
|
|
870
|
+
return new AggregateOperation(this.cwj(), "COUNT_DISTINCT" /* COUNT_DISTINCT */, this._displayName + " Count Distinct");
|
|
871
|
+
}
|
|
872
|
+
/** The value, or `defaultValue` when it is NULL: `name().orElse('N/A')`. Like `COALESCE` in SQL. */
|
|
873
|
+
orElse(defaultValue) {
|
|
874
|
+
if (!["string", "number", "boolean"].includes(typeof defaultValue)) {
|
|
875
|
+
throw new TypeError(`An orElse default is a string, number or boolean, not ${defaultValue === null ? "null" : typeof defaultValue}`);
|
|
876
|
+
}
|
|
877
|
+
return new ScalarFunctionOperation(this.cwj(), "COALESCE" /* COALESCE */, "Or Else " + this._displayName, void 0, [defaultValue]);
|
|
878
|
+
}
|
|
879
|
+
/** Sort this attribute in ascending order. Pass to `orderBy` or a window function's `orderBy`. */
|
|
326
880
|
ascending() {
|
|
327
|
-
return new SortOperation(
|
|
881
|
+
return new SortOperation(this.cwj(), "ASC" /* ASC */);
|
|
328
882
|
}
|
|
883
|
+
/** Sort this attribute in descending order. Pass to `orderBy` or a window function's `orderBy`. */
|
|
329
884
|
descending() {
|
|
330
|
-
return new SortOperation(
|
|
885
|
+
return new SortOperation(this.cwj(), "DESC" /* DESC */);
|
|
331
886
|
}
|
|
887
|
+
/** Filter to rows where this attribute has no value. */
|
|
332
888
|
isNull() {
|
|
333
|
-
return new IsNullOperation(
|
|
889
|
+
return new IsNullOperation(this.cwj());
|
|
334
890
|
}
|
|
891
|
+
/** Filter to rows where this attribute has a value. */
|
|
335
892
|
isNotNull() {
|
|
336
|
-
return new IsNotNullOperation(
|
|
893
|
+
return new IsNotNullOperation(this.cwj());
|
|
894
|
+
}
|
|
895
|
+
/** Wrap a value as a constant of this attribute's type. Overridden by the typed attributes. */
|
|
896
|
+
toConstant(_value) {
|
|
897
|
+
throw new TypeError(`${this.constructor.name} does not support isIn / isNotIn`);
|
|
898
|
+
}
|
|
899
|
+
_constants(values) {
|
|
900
|
+
const constants = values.map((v) => this.toConstant(v));
|
|
901
|
+
if (constants.length === 0) throw new Error("isIn / isNotIn need at least one value");
|
|
902
|
+
return constants;
|
|
903
|
+
}
|
|
904
|
+
/** Filter to rows where this attribute equals any of `values`. */
|
|
905
|
+
isIn(values) {
|
|
906
|
+
return new InOperation(this.cwj(), this._constants(values));
|
|
907
|
+
}
|
|
908
|
+
/** Filter to rows where this attribute equals none of `values`. Rows with no value are excluded, as in SQL. */
|
|
909
|
+
isNotIn(values) {
|
|
910
|
+
return new NotInOperation(this.cwj(), this._constants(values));
|
|
337
911
|
}
|
|
338
912
|
_windowSpec(partitionBy, orderBy) {
|
|
339
|
-
const
|
|
913
|
+
const pbArr = partitionBy === void 0 ? [] : Array.isArray(partitionBy) ? partitionBy : [partitionBy];
|
|
914
|
+
const pb = pbArr.map((x) => x instanceof _Attribute ? x.cwj() : x);
|
|
340
915
|
const ob = orderBy === void 0 ? [] : Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
341
916
|
return new WindowSpecification(pb, ob);
|
|
342
917
|
}
|
|
918
|
+
/**
|
|
919
|
+
* Assign a rank to each row within the ordered window, following pandas `Series.rank` conventions.
|
|
920
|
+
*
|
|
921
|
+
* `method` controls tie-breaking (default `'min'`):
|
|
922
|
+
* - `'min'` — tied rows share the lowest rank; the next rank skips.
|
|
923
|
+
* - `'dense'` — like `'min'` but ranks are contiguous (no gaps).
|
|
924
|
+
* - `'first'` — each row gets a unique sequential integer (no ties).
|
|
925
|
+
* - `'max'` — only meaningful with `pct: true` (see below).
|
|
926
|
+
*
|
|
927
|
+
* When `pct: true` the result is a relative rank between 0 and 1:
|
|
928
|
+
* - `method: 'min'` (default) → fraction of values strictly below this row (PERCENT_RANK).
|
|
929
|
+
* - `method: 'max'` → fraction of values at or below this row (cumulative distribution).
|
|
930
|
+
*
|
|
931
|
+
* `partitionBy` restarts the ranking within each group of distinct values.
|
|
932
|
+
*/
|
|
343
933
|
rank(opts = {}) {
|
|
344
934
|
const { method = "min", pct = false, partitionBy, orderBy } = opts;
|
|
345
935
|
let func;
|
|
@@ -364,6 +954,11 @@ var Attribute = class {
|
|
|
364
954
|
}
|
|
365
955
|
return new WindowFunctionOperation(null, func, name, void 0, [], this._windowSpec(partitionBy, orderBy));
|
|
366
956
|
}
|
|
957
|
+
/**
|
|
958
|
+
* Split rows into `buckets` equal-sized quantile bins ordered by `orderBy`.
|
|
959
|
+
* Each row receives a bucket number from 1 (lowest) to `buckets` (highest).
|
|
960
|
+
* Named after `pandas.qcut`.
|
|
961
|
+
*/
|
|
367
962
|
qcut(buckets, opts = {}) {
|
|
368
963
|
return new WindowFunctionOperation(
|
|
369
964
|
null,
|
|
@@ -374,12 +969,17 @@ var Attribute = class {
|
|
|
374
969
|
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
375
970
|
);
|
|
376
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* Return the value of this attribute from `periods` rows earlier (positive) or later (negative)
|
|
974
|
+
* within the ordered window, following `pandas.Series.shift`.
|
|
975
|
+
* Rows with no neighbour at the given offset return `null` (or `fillValue` if provided).
|
|
976
|
+
*/
|
|
377
977
|
shift(periods = 1, opts = {}) {
|
|
378
978
|
const extraArgs = opts.fillValue !== void 0 ? [opts.fillValue] : [];
|
|
379
979
|
const func = periods >= 0 ? "LAG" /* LAG */ : "LEAD" /* LEAD */;
|
|
380
980
|
const label = periods >= 0 ? "Lag" : "Lead";
|
|
381
981
|
return new WindowFunctionOperation(
|
|
382
|
-
|
|
982
|
+
this.cwj(),
|
|
383
983
|
func,
|
|
384
984
|
label + " " + this._displayName,
|
|
385
985
|
Math.abs(periods),
|
|
@@ -387,9 +987,13 @@ var Attribute = class {
|
|
|
387
987
|
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
388
988
|
);
|
|
389
989
|
}
|
|
990
|
+
/**
|
|
991
|
+
* Return the first value of this attribute in the window frame.
|
|
992
|
+
* Use `partitionBy` to restart the frame for each group.
|
|
993
|
+
*/
|
|
390
994
|
first(opts = {}) {
|
|
391
995
|
return new WindowFunctionOperation(
|
|
392
|
-
|
|
996
|
+
this.cwj(),
|
|
393
997
|
"FIRST_VALUE" /* FIRST_VALUE */,
|
|
394
998
|
"First " + this._displayName,
|
|
395
999
|
void 0,
|
|
@@ -397,9 +1001,13 @@ var Attribute = class {
|
|
|
397
1001
|
this._windowSpec(opts.partitionBy, opts.orderBy)
|
|
398
1002
|
);
|
|
399
1003
|
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Return the last value of this attribute in the window frame.
|
|
1006
|
+
* Use `partitionBy` to restart the frame for each group.
|
|
1007
|
+
*/
|
|
400
1008
|
last(opts = {}) {
|
|
401
1009
|
return new WindowFunctionOperation(
|
|
402
|
-
|
|
1010
|
+
this.cwj(),
|
|
403
1011
|
"LAST_VALUE" /* LAST_VALUE */,
|
|
404
1012
|
"Last " + this._displayName,
|
|
405
1013
|
void 0,
|
|
@@ -486,217 +1094,538 @@ var MilestonedTable = class extends Table {
|
|
|
486
1094
|
milestoningColumns;
|
|
487
1095
|
};
|
|
488
1096
|
|
|
1097
|
+
// src/datafinder/scalar-functions.ts
|
|
1098
|
+
var StringFunctionOperation = class extends ScalarFunctionOperation {
|
|
1099
|
+
functionInput() {
|
|
1100
|
+
return this;
|
|
1101
|
+
}
|
|
1102
|
+
functionLabel() {
|
|
1103
|
+
return labelOf(this);
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
1106
|
+
var NumericFunctionOperation = class extends ScalarFunctionOperation {
|
|
1107
|
+
functionInput() {
|
|
1108
|
+
return this;
|
|
1109
|
+
}
|
|
1110
|
+
functionLabel() {
|
|
1111
|
+
return labelOf(this);
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
function labelOf(operation) {
|
|
1115
|
+
return operation.displayName ?? operation.func.charAt(0) + operation.func.slice(1).toLowerCase();
|
|
1116
|
+
}
|
|
1117
|
+
function stringFunction(element, func, label, secondArg, extraArgs = []) {
|
|
1118
|
+
return new StringFunctionOperation(element, func, label, secondArg, extraArgs);
|
|
1119
|
+
}
|
|
1120
|
+
function numberFunction(element, func, label, secondArg) {
|
|
1121
|
+
return new NumericFunctionOperation(element, func, label, secondArg);
|
|
1122
|
+
}
|
|
1123
|
+
var StringFunctions = class {
|
|
1124
|
+
/** Join text on the end: `f.first().concat(' ', f.last())`. A NULL part makes the whole NULL. */
|
|
1125
|
+
concat(...more) {
|
|
1126
|
+
return concat(this, ...more);
|
|
1127
|
+
}
|
|
1128
|
+
/** Convert every character to uppercase. */
|
|
1129
|
+
toUpperCase() {
|
|
1130
|
+
return stringFunction(this.functionInput(), "UPPER" /* UPPER */, "Upper " + this.functionLabel());
|
|
1131
|
+
}
|
|
1132
|
+
/** Convert every character to lowercase. */
|
|
1133
|
+
toLowerCase() {
|
|
1134
|
+
return stringFunction(this.functionInput(), "LOWER" /* LOWER */, "Lower " + this.functionLabel());
|
|
1135
|
+
}
|
|
1136
|
+
/** Remove leading and trailing whitespace. */
|
|
1137
|
+
trim() {
|
|
1138
|
+
return stringFunction(this.functionInput(), "TRIM" /* TRIM */, "Trim " + this.functionLabel());
|
|
1139
|
+
}
|
|
1140
|
+
/** Remove leading whitespace. */
|
|
1141
|
+
trimStart() {
|
|
1142
|
+
return stringFunction(this.functionInput(), "LTRIM" /* LTRIM */, "Trim Start " + this.functionLabel());
|
|
1143
|
+
}
|
|
1144
|
+
/** Remove trailing whitespace. */
|
|
1145
|
+
trimEnd() {
|
|
1146
|
+
return stringFunction(this.functionInput(), "RTRIM" /* RTRIM */, "Trim End " + this.functionLabel());
|
|
1147
|
+
}
|
|
1148
|
+
/** Return the number of characters in the string. */
|
|
1149
|
+
length() {
|
|
1150
|
+
return numberFunction(this.functionInput(), "LENGTH" /* LENGTH */, "Length " + this.functionLabel());
|
|
1151
|
+
}
|
|
1152
|
+
/** Return the string with characters in reverse order. */
|
|
1153
|
+
reverse() {
|
|
1154
|
+
return stringFunction(this.functionInput(), "REVERSE" /* REVERSE */, "Reverse " + this.functionLabel());
|
|
1155
|
+
}
|
|
1156
|
+
/** Return the first `n` characters. */
|
|
1157
|
+
left(n) {
|
|
1158
|
+
return stringFunction(this.functionInput(), "LEFT" /* LEFT */, "Left " + this.functionLabel(), n);
|
|
1159
|
+
}
|
|
1160
|
+
/** Return the last `n` characters. */
|
|
1161
|
+
right(n) {
|
|
1162
|
+
return stringFunction(this.functionInput(), "RIGHT" /* RIGHT */, "Right " + this.functionLabel(), n);
|
|
1163
|
+
}
|
|
1164
|
+
/** Return the string repeated `n` times. */
|
|
1165
|
+
repeat(n) {
|
|
1166
|
+
return stringFunction(this.functionInput(), "REPEAT" /* REPEAT */, "Repeat " + this.functionLabel(), n);
|
|
1167
|
+
}
|
|
1168
|
+
/** Replace all occurrences of `fromStr` with `toStr`. */
|
|
1169
|
+
replace(fromStr, toStr) {
|
|
1170
|
+
return stringFunction(this.functionInput(), "REPLACE" /* REPLACE */, "Replace " + this.functionLabel(), void 0, [fromStr, toStr]);
|
|
1171
|
+
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Extract a portion of the string.
|
|
1174
|
+
* `start` is zero-based (following Python convention); `length` is optional.
|
|
1175
|
+
*/
|
|
1176
|
+
substring(start, length) {
|
|
1177
|
+
const args = length !== void 0 ? [start + 1, length] : [start + 1];
|
|
1178
|
+
return stringFunction(this.functionInput(), "SUBSTRING" /* SUBSTRING */, "Substring " + this.functionLabel(), void 0, args);
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
var NumericFunctions = class {
|
|
1182
|
+
/** Absolute value (distance from zero, always non-negative). */
|
|
1183
|
+
abs() {
|
|
1184
|
+
return numberFunction(this.functionInput(), "ABS" /* ABS */, "Abs " + this.functionLabel());
|
|
1185
|
+
}
|
|
1186
|
+
/** Round up to the nearest integer. */
|
|
1187
|
+
ceil() {
|
|
1188
|
+
return numberFunction(this.functionInput(), "CEILING" /* CEILING */, "Ceil " + this.functionLabel());
|
|
1189
|
+
}
|
|
1190
|
+
/** Round down to the nearest integer. */
|
|
1191
|
+
floor() {
|
|
1192
|
+
return numberFunction(this.functionInput(), "FLOOR" /* FLOOR */, "Floor " + this.functionLabel());
|
|
1193
|
+
}
|
|
1194
|
+
/** Square root. */
|
|
1195
|
+
sqrt() {
|
|
1196
|
+
return numberFunction(this.functionInput(), "SQRT" /* SQRT */, "Sqrt " + this.functionLabel());
|
|
1197
|
+
}
|
|
1198
|
+
/** Remainder after dividing by `n`. */
|
|
1199
|
+
mod(n) {
|
|
1200
|
+
return numberFunction(this.functionInput(), "MOD" /* MOD */, "Mod " + this.functionLabel(), n);
|
|
1201
|
+
}
|
|
1202
|
+
/** Raise to the power of `n`. */
|
|
1203
|
+
power(n) {
|
|
1204
|
+
return numberFunction(this.functionInput(), "POWER" /* POWER */, "Power " + this.functionLabel(), n);
|
|
1205
|
+
}
|
|
1206
|
+
/** Round to `d` decimal places, or to the nearest integer when `d` is omitted. */
|
|
1207
|
+
round(d) {
|
|
1208
|
+
return numberFunction(this.functionInput(), "ROUND" /* ROUND */, "Round " + this.functionLabel(), d);
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
applyMixins(StringFunctionOperation, [StringFunctions]);
|
|
1212
|
+
applyMixins(NumericFunctionOperation, [NumericFunctions]);
|
|
1213
|
+
|
|
489
1214
|
// src/datafinder/typed-attributes.ts
|
|
1215
|
+
var MinMax = class {
|
|
1216
|
+
/** Smallest value in the group. */
|
|
1217
|
+
min() {
|
|
1218
|
+
return new AggregateOperation(this.cwj(), "MIN" /* MIN */, "Min " + this.displayName());
|
|
1219
|
+
}
|
|
1220
|
+
/** Largest value in the group. */
|
|
1221
|
+
max() {
|
|
1222
|
+
return new AggregateOperation(this.cwj(), "MAX" /* MAX */, "Max " + this.displayName());
|
|
1223
|
+
}
|
|
1224
|
+
};
|
|
1225
|
+
var StringAttribute = class extends Attribute {
|
|
1226
|
+
constructor(displayName, columnName, columnDbType, owner, parent, embedded, nullable = true, optional = false) {
|
|
1227
|
+
super(displayName, columnName, columnDbType, owner, parent, embedded, nullable, optional);
|
|
1228
|
+
}
|
|
1229
|
+
toConstant(value) {
|
|
1230
|
+
return new StringConstantOperation(String(value));
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Join the values of a group into one text with `separator` between them. `orderBy` is the order they are
|
|
1234
|
+
* joined in (`[f.name().ascending()]`); without it the order is not defined. Missing values are skipped.
|
|
1235
|
+
*/
|
|
1236
|
+
join(separator = "", orderBy = []) {
|
|
1237
|
+
return new AggregateOperation(this.cwj(), "STRING_AGG" /* STRING_AGG */, "Join " + this.displayName(), void 0, separator, orderBy);
|
|
1238
|
+
}
|
|
1239
|
+
/** Filter to rows where this attribute equals `value`. */
|
|
1240
|
+
eq(value) {
|
|
1241
|
+
return new ComparisonOperation(this.cwj(), "EQUAL" /* EQUAL */, new StringConstantOperation(value));
|
|
1242
|
+
}
|
|
1243
|
+
/** Filter to rows where this attribute does not equal `value`. */
|
|
1244
|
+
ne(value) {
|
|
1245
|
+
return new ComparisonOperation(this.cwj(), "NOT_EQUAL" /* NOT_EQUAL */, new StringConstantOperation(value));
|
|
1246
|
+
}
|
|
1247
|
+
/** Filter to rows where this attribute contains `value` as a substring. */
|
|
1248
|
+
contains(value) {
|
|
1249
|
+
return new ComparisonOperation(this.cwj(), "LIKE" /* LIKE */, new StringConstantOperation(`%${escapeLike(value)}%`));
|
|
1250
|
+
}
|
|
1251
|
+
/** Filter to rows where this attribute begins with `prefix`. */
|
|
1252
|
+
startsWith(prefix) {
|
|
1253
|
+
return new ComparisonOperation(this.cwj(), "LIKE" /* LIKE */, new StringConstantOperation(`${escapeLike(prefix)}%`));
|
|
1254
|
+
}
|
|
1255
|
+
/** Filter to rows where this attribute ends with `suffix`. */
|
|
1256
|
+
endsWith(suffix) {
|
|
1257
|
+
return new ComparisonOperation(this.cwj(), "LIKE" /* LIKE */, new StringConstantOperation(`%${escapeLike(suffix)}`));
|
|
1258
|
+
}
|
|
1259
|
+
/** Filter to rows where this attribute does not contain `value` as a substring. */
|
|
1260
|
+
notContains(value) {
|
|
1261
|
+
return new ComparisonOperation(this.cwj(), "NOT_LIKE" /* NOT_LIKE */, new StringConstantOperation(`%${escapeLike(value)}%`));
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
applyMixins(StringAttribute, [MinMax, StringFunctions]);
|
|
1265
|
+
var NumericAttribute = class extends Attribute {
|
|
1266
|
+
constructor(displayName, columnName, columnDbType, owner, parent, embedded, nullable = true, optional = false) {
|
|
1267
|
+
super(displayName, columnName, columnDbType, owner, parent, embedded, nullable, optional);
|
|
1268
|
+
}
|
|
1269
|
+
/** Sum of all values in the group. */
|
|
1270
|
+
sum() {
|
|
1271
|
+
return new AggregateOperation(this.cwj(), "SUM" /* SUM */, "Sum " + this.displayName());
|
|
1272
|
+
}
|
|
1273
|
+
/** Arithmetic mean of all values in the group. */
|
|
1274
|
+
average() {
|
|
1275
|
+
return new AggregateOperation(this.cwj(), "AVERAGE" /* AVERAGE */, "Average " + this.displayName());
|
|
1276
|
+
}
|
|
1277
|
+
/** Standard deviation of the values in the group: the sample one by default, `ddof = 0` for the population one, as `Series.std`. */
|
|
1278
|
+
std(ddof = 1) {
|
|
1279
|
+
const operator = sample(ddof) ? "STDDEV_SAMP" /* STDDEV_SAMP */ : "STDDEV_POP" /* STDDEV_POP */;
|
|
1280
|
+
return new AggregateOperation(this.cwj(), operator, "Std " + this.displayName());
|
|
1281
|
+
}
|
|
1282
|
+
/** Variance of the values in the group: the sample one by default, `ddof = 0` for the population one, as `Series.var`. */
|
|
1283
|
+
var(ddof = 1) {
|
|
1284
|
+
const operator = sample(ddof) ? "VAR_SAMP" /* VAR_SAMP */ : "VAR_POP" /* VAR_POP */;
|
|
1285
|
+
return new AggregateOperation(this.cwj(), operator, "Var " + this.displayName());
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
applyMixins(NumericAttribute, [MinMax, NumericFunctions, Arithmetic]);
|
|
490
1289
|
function parseDate(value) {
|
|
491
1290
|
if (value instanceof Date) return value;
|
|
492
1291
|
const d = new Date(value);
|
|
493
1292
|
if (isNaN(d.getTime())) throw new Error(`Cannot parse date: ${value}`);
|
|
494
1293
|
return d;
|
|
495
1294
|
}
|
|
1295
|
+
function temporalConstant(value) {
|
|
1296
|
+
if (typeof value === "string" && DATE_ONLY_PATTERN.test(value)) return new DateConstantOperation(new DateOnly(value));
|
|
1297
|
+
const date = parseDate(value);
|
|
1298
|
+
return date instanceof DateOnly ? new DateConstantOperation(date) : new DateTimeConstantOperation(date);
|
|
1299
|
+
}
|
|
496
1300
|
var DateAttribute = class extends Attribute {
|
|
497
|
-
constructor(displayName, columnName, columnDbType, owner, parent) {
|
|
498
|
-
super(displayName, columnName, columnDbType, owner, parent);
|
|
1301
|
+
constructor(displayName, columnName, columnDbType, owner, parent, embedded, nullable = true, optional = false) {
|
|
1302
|
+
super(displayName, columnName, columnDbType, owner, parent, embedded, nullable, optional);
|
|
1303
|
+
}
|
|
1304
|
+
toConstant(value) {
|
|
1305
|
+
return new DateConstantOperation(parseDate(value));
|
|
499
1306
|
}
|
|
1307
|
+
/** Filter to rows where this date equals `value`. */
|
|
500
1308
|
eq(value) {
|
|
501
1309
|
return new ComparisonOperation(this.cwj(), "EQUAL" /* EQUAL */, new DateConstantOperation(parseDate(value)));
|
|
502
1310
|
}
|
|
1311
|
+
/** Filter to rows where this date does not equal `value`. */
|
|
503
1312
|
ne(value) {
|
|
504
1313
|
return new ComparisonOperation(this.cwj(), "NOT_EQUAL" /* NOT_EQUAL */, new DateConstantOperation(parseDate(value)));
|
|
505
1314
|
}
|
|
1315
|
+
/** Filter to rows where this date is after `value`. */
|
|
506
1316
|
gt(value) {
|
|
507
1317
|
return new ComparisonOperation(this.cwj(), "GREATER_THAN" /* GREATER_THAN */, new DateConstantOperation(parseDate(value)));
|
|
508
1318
|
}
|
|
1319
|
+
/** Filter to rows where this date is before `value`. */
|
|
509
1320
|
lt(value) {
|
|
510
1321
|
return new ComparisonOperation(this.cwj(), "LESS_THAN" /* LESS_THAN */, new DateConstantOperation(parseDate(value)));
|
|
511
1322
|
}
|
|
1323
|
+
/** Filter to rows where this date is on or after `value`. */
|
|
512
1324
|
gte(value) {
|
|
513
1325
|
return new ComparisonOperation(this.cwj(), "GREATER_THAN_OR_EQUAL_TO" /* GREATER_THAN_OR_EQUAL_TO */, new DateConstantOperation(parseDate(value)));
|
|
514
1326
|
}
|
|
1327
|
+
/** Filter to rows where this date is on or before `value`. */
|
|
515
1328
|
lte(value) {
|
|
516
1329
|
return new ComparisonOperation(this.cwj(), "LESS_THAN_OR_EQUAL_TO" /* LESS_THAN_OR_EQUAL_TO */, new DateConstantOperation(parseDate(value)));
|
|
517
1330
|
}
|
|
1331
|
+
/** Extract the four-digit calendar year. */
|
|
518
1332
|
year() {
|
|
519
1333
|
return new DateExtractOperation(this.cwj(), "YEAR" /* YEAR */, "Year " + this.displayName());
|
|
520
1334
|
}
|
|
1335
|
+
/** Extract the month number (1–12). */
|
|
521
1336
|
month() {
|
|
522
1337
|
return new DateExtractOperation(this.cwj(), "MONTH" /* MONTH */, "Month " + this.displayName());
|
|
523
1338
|
}
|
|
1339
|
+
/** Extract the day of the month (1–31). */
|
|
524
1340
|
day() {
|
|
525
1341
|
return new DateExtractOperation(this.cwj(), "DAY" /* DAY */, "Day " + this.displayName());
|
|
526
1342
|
}
|
|
1343
|
+
/** Extract the quarter (1–4). */
|
|
527
1344
|
quarter() {
|
|
528
1345
|
return new DateExtractOperation(this.cwj(), "QUARTER" /* QUARTER */, "Quarter " + this.displayName());
|
|
529
1346
|
}
|
|
1347
|
+
/** Extract the ISO week number (1–53). */
|
|
530
1348
|
week() {
|
|
531
1349
|
return new DateExtractOperation(this.cwj(), "WEEK" /* WEEK */, "Week " + this.displayName());
|
|
532
1350
|
}
|
|
1351
|
+
/** Extract the day of the week (0 = Sunday through 6 = Saturday). */
|
|
533
1352
|
dayOfWeek() {
|
|
534
1353
|
return new DateExtractOperation(this.cwj(), "DOW" /* DOW */, "Day Of Week " + this.displayName());
|
|
535
1354
|
}
|
|
1355
|
+
/** The date of the first day of the week the date falls in (a Monday). */
|
|
1356
|
+
firstDayOfWeek() {
|
|
1357
|
+
return new DateTruncOperation(this.cwj(), "WEEK" /* WEEK */, "First Day Of Week " + this.displayName());
|
|
1358
|
+
}
|
|
1359
|
+
/** The date of the first day of the month the date falls in. */
|
|
1360
|
+
firstDayOfMonth() {
|
|
1361
|
+
return new DateTruncOperation(this.cwj(), "MONTH" /* MONTH */, "First Day Of Month " + this.displayName());
|
|
1362
|
+
}
|
|
1363
|
+
/** The date of the first day of the quarter the date falls in. */
|
|
1364
|
+
firstDayOfQuarter() {
|
|
1365
|
+
return new DateTruncOperation(this.cwj(), "QUARTER" /* QUARTER */, "First Day Of Quarter " + this.displayName());
|
|
1366
|
+
}
|
|
1367
|
+
/** The date of the first day of the year the date falls in. */
|
|
1368
|
+
firstDayOfYear() {
|
|
1369
|
+
return new DateTruncOperation(this.cwj(), "YEAR" /* YEAR */, "First Day Of Year " + this.displayName());
|
|
1370
|
+
}
|
|
1371
|
+
/** Add `n` days to this date. */
|
|
536
1372
|
addDays(n) {
|
|
537
1373
|
return new DateArithmeticOperation(this.cwj(), n, "DAY" /* DAY */, true, "Add Days " + this.displayName());
|
|
538
1374
|
}
|
|
1375
|
+
/** Add `n` months to this date. */
|
|
539
1376
|
addMonths(n) {
|
|
540
1377
|
return new DateArithmeticOperation(this.cwj(), n, "MONTH" /* MONTH */, true, "Add Months " + this.displayName());
|
|
541
1378
|
}
|
|
1379
|
+
/** Add `n` years to this date. */
|
|
542
1380
|
addYears(n) {
|
|
543
1381
|
return new DateArithmeticOperation(this.cwj(), n, "YEAR" /* YEAR */, true, "Add Years " + this.displayName());
|
|
544
1382
|
}
|
|
1383
|
+
/** Subtract `n` days from this date. */
|
|
545
1384
|
subtractDays(n) {
|
|
546
1385
|
return new DateArithmeticOperation(this.cwj(), n, "DAY" /* DAY */, false, "Subtract Days " + this.displayName());
|
|
547
1386
|
}
|
|
1387
|
+
/** Subtract `n` months from this date. */
|
|
548
1388
|
subtractMonths(n) {
|
|
549
1389
|
return new DateArithmeticOperation(this.cwj(), n, "MONTH" /* MONTH */, false, "Subtract Months " + this.displayName());
|
|
550
1390
|
}
|
|
1391
|
+
/** Subtract `n` years from this date. */
|
|
551
1392
|
subtractYears(n) {
|
|
552
1393
|
return new DateArithmeticOperation(this.cwj(), n, "YEAR" /* YEAR */, false, "Subtract Years " + this.displayName());
|
|
553
1394
|
}
|
|
1395
|
+
/** Number of whole days between this date and `other`. */
|
|
554
1396
|
diffDays(other) {
|
|
555
1397
|
return new DateDiffOperation(this.cwj(), other, "DAY" /* DAY */, "Diff Days " + this.displayName());
|
|
556
1398
|
}
|
|
1399
|
+
/** Number of whole months between this date and `other`. */
|
|
557
1400
|
diffMonths(other) {
|
|
558
1401
|
return new DateDiffOperation(this.cwj(), other, "MONTH" /* MONTH */, "Diff Months " + this.displayName());
|
|
559
1402
|
}
|
|
1403
|
+
/** Number of whole years between this date and `other`. */
|
|
560
1404
|
diffYears(other) {
|
|
561
1405
|
return new DateDiffOperation(this.cwj(), other, "YEAR" /* YEAR */, "Diff Years " + this.displayName());
|
|
562
1406
|
}
|
|
563
1407
|
};
|
|
564
1408
|
var DateTimeAttribute = class extends Attribute {
|
|
565
|
-
constructor(displayName, columnName, columnDbType, owner, parent) {
|
|
566
|
-
super(displayName, columnName, columnDbType, owner, parent);
|
|
1409
|
+
constructor(displayName, columnName, columnDbType, owner, parent, embedded, nullable = true, optional = false) {
|
|
1410
|
+
super(displayName, columnName, columnDbType, owner, parent, embedded, nullable, optional);
|
|
1411
|
+
}
|
|
1412
|
+
toConstant(value) {
|
|
1413
|
+
return temporalConstant(value);
|
|
567
1414
|
}
|
|
1415
|
+
/** Filter to rows where this timestamp equals `value`. */
|
|
568
1416
|
eq(value) {
|
|
569
|
-
return new ComparisonOperation(this.cwj(), "EQUAL" /* EQUAL */,
|
|
1417
|
+
return new ComparisonOperation(this.cwj(), "EQUAL" /* EQUAL */, temporalConstant(value));
|
|
570
1418
|
}
|
|
1419
|
+
/** Filter to rows where this timestamp does not equal `value`. */
|
|
571
1420
|
ne(value) {
|
|
572
|
-
return new ComparisonOperation(this.cwj(), "NOT_EQUAL" /* NOT_EQUAL */,
|
|
1421
|
+
return new ComparisonOperation(this.cwj(), "NOT_EQUAL" /* NOT_EQUAL */, temporalConstant(value));
|
|
573
1422
|
}
|
|
1423
|
+
/** Filter to rows where this timestamp is after `value`. */
|
|
574
1424
|
gt(value) {
|
|
575
|
-
return new ComparisonOperation(this.cwj(), "GREATER_THAN" /* GREATER_THAN */,
|
|
1425
|
+
return new ComparisonOperation(this.cwj(), "GREATER_THAN" /* GREATER_THAN */, temporalConstant(value));
|
|
576
1426
|
}
|
|
1427
|
+
/** Filter to rows where this timestamp is before `value`. */
|
|
577
1428
|
lt(value) {
|
|
578
|
-
return new ComparisonOperation(this.cwj(), "LESS_THAN" /* LESS_THAN */,
|
|
1429
|
+
return new ComparisonOperation(this.cwj(), "LESS_THAN" /* LESS_THAN */, temporalConstant(value));
|
|
579
1430
|
}
|
|
1431
|
+
/** Filter to rows where this timestamp is on or after `value`. */
|
|
580
1432
|
gte(value) {
|
|
581
|
-
return new ComparisonOperation(this.cwj(), "GREATER_THAN_OR_EQUAL_TO" /* GREATER_THAN_OR_EQUAL_TO */,
|
|
1433
|
+
return new ComparisonOperation(this.cwj(), "GREATER_THAN_OR_EQUAL_TO" /* GREATER_THAN_OR_EQUAL_TO */, temporalConstant(value));
|
|
582
1434
|
}
|
|
1435
|
+
/** Filter to rows where this timestamp is on or before `value`. */
|
|
583
1436
|
lte(value) {
|
|
584
|
-
return new ComparisonOperation(this.cwj(), "LESS_THAN_OR_EQUAL_TO" /* LESS_THAN_OR_EQUAL_TO */,
|
|
1437
|
+
return new ComparisonOperation(this.cwj(), "LESS_THAN_OR_EQUAL_TO" /* LESS_THAN_OR_EQUAL_TO */, temporalConstant(value));
|
|
585
1438
|
}
|
|
1439
|
+
/** Extract the four-digit calendar year. */
|
|
586
1440
|
year() {
|
|
587
1441
|
return new DateExtractOperation(this.cwj(), "YEAR" /* YEAR */, "Year " + this.displayName());
|
|
588
1442
|
}
|
|
1443
|
+
/** Extract the month number (1–12). */
|
|
589
1444
|
month() {
|
|
590
1445
|
return new DateExtractOperation(this.cwj(), "MONTH" /* MONTH */, "Month " + this.displayName());
|
|
591
1446
|
}
|
|
1447
|
+
/** Extract the day of the month (1–31). */
|
|
592
1448
|
day() {
|
|
593
1449
|
return new DateExtractOperation(this.cwj(), "DAY" /* DAY */, "Day " + this.displayName());
|
|
594
1450
|
}
|
|
1451
|
+
/** Extract the hour (0–23). */
|
|
595
1452
|
hour() {
|
|
596
1453
|
return new DateExtractOperation(this.cwj(), "HOUR" /* HOUR */, "Hour " + this.displayName());
|
|
597
1454
|
}
|
|
1455
|
+
/** Extract the minute (0–59). */
|
|
598
1456
|
minute() {
|
|
599
1457
|
return new DateExtractOperation(this.cwj(), "MINUTE" /* MINUTE */, "Minute " + this.displayName());
|
|
600
1458
|
}
|
|
1459
|
+
/** Extract the second (0–59). */
|
|
601
1460
|
second() {
|
|
602
1461
|
return new DateExtractOperation(this.cwj(), "SECOND" /* SECOND */, "Second " + this.displayName());
|
|
603
1462
|
}
|
|
1463
|
+
/** Extract the quarter (1–4). */
|
|
604
1464
|
quarter() {
|
|
605
1465
|
return new DateExtractOperation(this.cwj(), "QUARTER" /* QUARTER */, "Quarter " + this.displayName());
|
|
606
1466
|
}
|
|
1467
|
+
/** Extract the ISO week number (1–53). */
|
|
607
1468
|
week() {
|
|
608
1469
|
return new DateExtractOperation(this.cwj(), "WEEK" /* WEEK */, "Week " + this.displayName());
|
|
609
1470
|
}
|
|
1471
|
+
/** Extract the day of the week (0 = Sunday through 6 = Saturday). */
|
|
610
1472
|
dayOfWeek() {
|
|
611
1473
|
return new DateExtractOperation(this.cwj(), "DOW" /* DOW */, "Day Of Week " + this.displayName());
|
|
612
1474
|
}
|
|
1475
|
+
/** The date of the first day of the week the date falls in (a Monday). */
|
|
1476
|
+
firstDayOfWeek() {
|
|
1477
|
+
return new DateTruncOperation(this.cwj(), "WEEK" /* WEEK */, "First Day Of Week " + this.displayName());
|
|
1478
|
+
}
|
|
1479
|
+
/** The date of the first day of the month the date falls in. */
|
|
1480
|
+
firstDayOfMonth() {
|
|
1481
|
+
return new DateTruncOperation(this.cwj(), "MONTH" /* MONTH */, "First Day Of Month " + this.displayName());
|
|
1482
|
+
}
|
|
1483
|
+
/** The date of the first day of the quarter the date falls in. */
|
|
1484
|
+
firstDayOfQuarter() {
|
|
1485
|
+
return new DateTruncOperation(this.cwj(), "QUARTER" /* QUARTER */, "First Day Of Quarter " + this.displayName());
|
|
1486
|
+
}
|
|
1487
|
+
/** The date of the first day of the year the date falls in. */
|
|
1488
|
+
firstDayOfYear() {
|
|
1489
|
+
return new DateTruncOperation(this.cwj(), "YEAR" /* YEAR */, "First Day Of Year " + this.displayName());
|
|
1490
|
+
}
|
|
1491
|
+
/** Add `n` days to this timestamp. */
|
|
613
1492
|
addDays(n) {
|
|
614
1493
|
return new DateArithmeticOperation(this.cwj(), n, "DAY" /* DAY */, true, "Add Days " + this.displayName());
|
|
615
1494
|
}
|
|
1495
|
+
/** Add `n` months to this timestamp. */
|
|
616
1496
|
addMonths(n) {
|
|
617
1497
|
return new DateArithmeticOperation(this.cwj(), n, "MONTH" /* MONTH */, true, "Add Months " + this.displayName());
|
|
618
1498
|
}
|
|
1499
|
+
/** Add `n` years to this timestamp. */
|
|
619
1500
|
addYears(n) {
|
|
620
1501
|
return new DateArithmeticOperation(this.cwj(), n, "YEAR" /* YEAR */, true, "Add Years " + this.displayName());
|
|
621
1502
|
}
|
|
1503
|
+
/** Add `n` hours to this timestamp. */
|
|
622
1504
|
addHours(n) {
|
|
623
1505
|
return new DateArithmeticOperation(this.cwj(), n, "HOUR" /* HOUR */, true, "Add Hours " + this.displayName());
|
|
624
1506
|
}
|
|
1507
|
+
/** Add `n` minutes to this timestamp. */
|
|
625
1508
|
addMinutes(n) {
|
|
626
1509
|
return new DateArithmeticOperation(this.cwj(), n, "MINUTE" /* MINUTE */, true, "Add Minutes " + this.displayName());
|
|
627
1510
|
}
|
|
1511
|
+
/** Add `n` seconds to this timestamp. */
|
|
628
1512
|
addSeconds(n) {
|
|
629
1513
|
return new DateArithmeticOperation(this.cwj(), n, "SECOND" /* SECOND */, true, "Add Seconds " + this.displayName());
|
|
630
1514
|
}
|
|
1515
|
+
/** Subtract `n` days from this timestamp. */
|
|
631
1516
|
subtractDays(n) {
|
|
632
1517
|
return new DateArithmeticOperation(this.cwj(), n, "DAY" /* DAY */, false, "Subtract Days " + this.displayName());
|
|
633
1518
|
}
|
|
1519
|
+
/** Subtract `n` months from this timestamp. */
|
|
634
1520
|
subtractMonths(n) {
|
|
635
1521
|
return new DateArithmeticOperation(this.cwj(), n, "MONTH" /* MONTH */, false, "Subtract Months " + this.displayName());
|
|
636
1522
|
}
|
|
1523
|
+
/** Subtract `n` years from this timestamp. */
|
|
637
1524
|
subtractYears(n) {
|
|
638
1525
|
return new DateArithmeticOperation(this.cwj(), n, "YEAR" /* YEAR */, false, "Subtract Years " + this.displayName());
|
|
639
1526
|
}
|
|
1527
|
+
/** Subtract `n` hours from this timestamp. */
|
|
640
1528
|
subtractHours(n) {
|
|
641
1529
|
return new DateArithmeticOperation(this.cwj(), n, "HOUR" /* HOUR */, false, "Subtract Hours " + this.displayName());
|
|
642
1530
|
}
|
|
1531
|
+
/** Subtract `n` minutes from this timestamp. */
|
|
643
1532
|
subtractMinutes(n) {
|
|
644
1533
|
return new DateArithmeticOperation(this.cwj(), n, "MINUTE" /* MINUTE */, false, "Subtract Minutes " + this.displayName());
|
|
645
1534
|
}
|
|
1535
|
+
/** Subtract `n` seconds from this timestamp. */
|
|
646
1536
|
subtractSeconds(n) {
|
|
647
1537
|
return new DateArithmeticOperation(this.cwj(), n, "SECOND" /* SECOND */, false, "Subtract Seconds " + this.displayName());
|
|
648
1538
|
}
|
|
1539
|
+
/** Number of whole days between this timestamp and `other`. */
|
|
649
1540
|
diffDays(other) {
|
|
650
1541
|
return new DateDiffOperation(this.cwj(), other, "DAY" /* DAY */, "Diff Days " + this.displayName());
|
|
651
1542
|
}
|
|
1543
|
+
/** Number of whole months between this timestamp and `other`. */
|
|
652
1544
|
diffMonths(other) {
|
|
653
1545
|
return new DateDiffOperation(this.cwj(), other, "MONTH" /* MONTH */, "Diff Months " + this.displayName());
|
|
654
1546
|
}
|
|
1547
|
+
/** Number of whole years between this timestamp and `other`. */
|
|
655
1548
|
diffYears(other) {
|
|
656
1549
|
return new DateDiffOperation(this.cwj(), other, "YEAR" /* YEAR */, "Diff Years " + this.displayName());
|
|
657
1550
|
}
|
|
1551
|
+
/** Number of whole hours between this timestamp and `other`. */
|
|
658
1552
|
diffHours(other) {
|
|
659
1553
|
return new DateDiffOperation(this.cwj(), other, "HOUR" /* HOUR */, "Diff Hours " + this.displayName());
|
|
660
1554
|
}
|
|
1555
|
+
/** Number of whole minutes between this timestamp and `other`. */
|
|
661
1556
|
diffMinutes(other) {
|
|
662
1557
|
return new DateDiffOperation(this.cwj(), other, "MINUTE" /* MINUTE */, "Diff Minutes " + this.displayName());
|
|
663
1558
|
}
|
|
1559
|
+
/** Number of whole seconds between this timestamp and `other`. */
|
|
664
1560
|
diffSeconds(other) {
|
|
665
1561
|
return new DateDiffOperation(this.cwj(), other, "SECOND" /* SECOND */, "Diff Seconds " + this.displayName());
|
|
666
1562
|
}
|
|
667
1563
|
};
|
|
1564
|
+
applyMixins(DateAttribute, [MinMax]);
|
|
1565
|
+
applyMixins(DateTimeAttribute, [MinMax]);
|
|
668
1566
|
|
|
669
|
-
// src/datafinder/
|
|
670
|
-
var
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
1567
|
+
// src/datafinder/dialect.ts
|
|
1568
|
+
var doubleQuoted = (name) => '"' + name.replaceAll('"', '""') + '"';
|
|
1569
|
+
var quoted = (value) => "'" + value.replaceAll("'", "''") + "'";
|
|
1570
|
+
var SECONDS_PER = { ["HOUR" /* HOUR */]: 3600, ["MINUTE" /* MINUTE */]: 60, ["SECOND" /* SECOND */]: 1 };
|
|
1571
|
+
var POSTGRES = {
|
|
1572
|
+
name: "postgres",
|
|
1573
|
+
quoteIdentifier: doubleQuoted,
|
|
1574
|
+
stringLiteral: quoted,
|
|
1575
|
+
orderDirection: (direction) => direction === "ASC" /* ASC */ ? " ASC" : " DESC",
|
|
1576
|
+
doubleType: "DOUBLE PRECISION",
|
|
1577
|
+
dayOfWeek: (expression) => `EXTRACT(DOW FROM ${expression})`,
|
|
1578
|
+
dateDiff(unit, from, to) {
|
|
1579
|
+
const start = `CAST(${from} AS TIMESTAMP)`;
|
|
1580
|
+
const end = `CAST(${to} AS TIMESTAMP)`;
|
|
1581
|
+
switch (unit) {
|
|
1582
|
+
case "DAY" /* DAY */:
|
|
1583
|
+
return `(CAST(${to} AS DATE) - CAST(${from} AS DATE))`;
|
|
1584
|
+
case "MONTH" /* MONTH */:
|
|
1585
|
+
return `CAST(EXTRACT(YEAR FROM AGE(${end}, ${start})) * 12 + EXTRACT(MONTH FROM AGE(${end}, ${start})) AS BIGINT)`;
|
|
1586
|
+
case "YEAR" /* YEAR */:
|
|
1587
|
+
return `CAST(EXTRACT(YEAR FROM AGE(${end}, ${start})) AS BIGINT)`;
|
|
1588
|
+
default: {
|
|
1589
|
+
const seconds = SECONDS_PER[unit];
|
|
1590
|
+
if (seconds === void 0) throw new Error(`Cannot take the difference in ${unit}`);
|
|
1591
|
+
return `CAST(FLOOR(EXTRACT(EPOCH FROM (${end} - ${start})) / ${seconds}) AS BIGINT)`;
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
},
|
|
1595
|
+
stringAgg: (expression, separator, orderBy) => `STRING_AGG(${expression}, ${separator}${orderBy.length > 0 ? " ORDER BY " + orderBy.join(", ") : ""})`
|
|
679
1596
|
};
|
|
680
|
-
var
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
1597
|
+
var DUCKDB = {
|
|
1598
|
+
...POSTGRES,
|
|
1599
|
+
name: "duckdb",
|
|
1600
|
+
// DuckDB sorts nulls last whichever way the sort goes
|
|
1601
|
+
orderDirection: (direction) => direction === "ASC" /* ASC */ ? " ASC" : " DESC NULLS FIRST",
|
|
1602
|
+
doubleType: "DOUBLE",
|
|
1603
|
+
dateDiff: (unit, from, to) => `DATE_DIFF('${unit.toLowerCase()}', ${from}, ${to})`
|
|
1604
|
+
};
|
|
1605
|
+
var DATABRICKS = {
|
|
1606
|
+
name: "databricks",
|
|
1607
|
+
// a double-quoted token is a string in Databricks; identifiers take backticks
|
|
1608
|
+
quoteIdentifier: (name) => "`" + name.replaceAll("`", "``") + "`",
|
|
1609
|
+
// a backslash starts an escape in a Databricks string literal, and a doubled quote is not one: Spark reads
|
|
1610
|
+
// 'it''s' as the two literals 'it' and 's' and joins them, losing the quote. A quote is escaped with a backslash.
|
|
1611
|
+
stringLiteral: (value) => "'" + value.replaceAll("\\", "\\\\").replaceAll("'", "\\'") + "'",
|
|
1612
|
+
// Databricks sorts nulls first when ascending, last when descending
|
|
1613
|
+
orderDirection: (direction) => direction === "ASC" /* ASC */ ? " ASC NULLS LAST" : " DESC NULLS FIRST",
|
|
1614
|
+
doubleType: "DOUBLE",
|
|
1615
|
+
// DAYOFWEEK is 1 = Sunday through 7 = Saturday
|
|
1616
|
+
dayOfWeek: (expression) => `(DAYOFWEEK(${expression}) - 1)`,
|
|
1617
|
+
dateDiff: (unit, from, to) => `DATEDIFF(${unit}, ${from}, ${to})`,
|
|
1618
|
+
stringAgg: (expression, separator, orderBy) => `LISTAGG(${expression}, ${separator})${orderBy.length > 0 ? " WITHIN GROUP (ORDER BY " + orderBy.join(", ") + ")" : ""}`
|
|
689
1619
|
};
|
|
1620
|
+
var DIALECTS = { postgres: POSTGRES, duckdb: DUCKDB, databricks: DATABRICKS };
|
|
1621
|
+
function dialectOf(dialect) {
|
|
1622
|
+
if (typeof dialect !== "string") return dialect;
|
|
1623
|
+
const found = DIALECTS[dialect];
|
|
1624
|
+
if (found === void 0) throw new Error(`Unknown SQL dialect '${dialect}': one of ${Object.keys(DIALECTS).join(", ")}`);
|
|
1625
|
+
return found;
|
|
1626
|
+
}
|
|
690
1627
|
|
|
691
1628
|
// src/datafinder/sql-generator.ts
|
|
692
|
-
var Alias = class {
|
|
693
|
-
constructor(element, name) {
|
|
694
|
-
this.element = element;
|
|
695
|
-
this.name = name;
|
|
696
|
-
}
|
|
697
|
-
element;
|
|
698
|
-
name;
|
|
699
|
-
};
|
|
700
1629
|
var TableAlias = class {
|
|
701
1630
|
constructor(table, alias) {
|
|
702
1631
|
this.table = table;
|
|
@@ -723,22 +1652,12 @@ var Join = class {
|
|
|
723
1652
|
source;
|
|
724
1653
|
target;
|
|
725
1654
|
filterOp;
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
this.orderBy = orderBy;
|
|
732
|
-
this.groupBy = groupBy;
|
|
733
|
-
this.limit = limit;
|
|
734
|
-
this.table = table;
|
|
1655
|
+
/** `source = target`, written with the key column first as Legend writes a join defined as key = foreign key. */
|
|
1656
|
+
condition() {
|
|
1657
|
+
let [first, second] = [this.source, this.target];
|
|
1658
|
+
if (second.column.primaryKey && !first.column.primaryKey) [first, second] = [second, first];
|
|
1659
|
+
return first.tableAlias.alias + "." + first.column.name + " = " + second.tableAlias.alias + "." + second.column.name;
|
|
735
1660
|
}
|
|
736
|
-
display;
|
|
737
|
-
filter;
|
|
738
|
-
orderBy;
|
|
739
|
-
groupBy;
|
|
740
|
-
limit;
|
|
741
|
-
table;
|
|
742
1661
|
};
|
|
743
1662
|
function sqlFormatDatetime(value) {
|
|
744
1663
|
const pad = (n, w = 2) => String(n).padStart(w, "0");
|
|
@@ -765,6 +1684,13 @@ var COMPARISON_OPERATOR_STR = {
|
|
|
765
1684
|
var AGGREGATE_SQL_NAMES = {
|
|
766
1685
|
["AVERAGE" /* AVERAGE */]: "AVG"
|
|
767
1686
|
};
|
|
1687
|
+
var GUARDED_COMPARISONS = /* @__PURE__ */ new Set([
|
|
1688
|
+
"LESS_THAN" /* LESS_THAN */,
|
|
1689
|
+
"GREATER_THAN" /* GREATER_THAN */,
|
|
1690
|
+
"LESS_THAN_OR_EQUAL_TO" /* LESS_THAN_OR_EQUAL_TO */,
|
|
1691
|
+
"GREATER_THAN_OR_EQUAL_TO" /* GREATER_THAN_OR_EQUAL_TO */,
|
|
1692
|
+
"LIKE" /* LIKE */
|
|
1693
|
+
]);
|
|
768
1694
|
var WINDOW_SQL_NAMES = {
|
|
769
1695
|
["ROW_NUMBER" /* ROW_NUMBER */]: "ROW_NUMBER",
|
|
770
1696
|
["RANK" /* RANK */]: "RANK",
|
|
@@ -796,31 +1722,63 @@ var SCALAR_SQL_NAMES = {
|
|
|
796
1722
|
["RIGHT" /* RIGHT */]: "RIGHT",
|
|
797
1723
|
["REPEAT" /* REPEAT */]: "REPEAT",
|
|
798
1724
|
["REPLACE" /* REPLACE */]: "REPLACE",
|
|
799
|
-
["SUBSTRING" /* SUBSTRING */]: "SUBSTRING"
|
|
1725
|
+
["SUBSTRING" /* SUBSTRING */]: "SUBSTRING",
|
|
1726
|
+
["COALESCE" /* COALESCE */]: "COALESCE"
|
|
800
1727
|
};
|
|
801
|
-
function constantValueString(op) {
|
|
802
|
-
if (op instanceof StringConstantOperation) return
|
|
1728
|
+
function constantValueString(op, d) {
|
|
1729
|
+
if (op instanceof StringConstantOperation) return d.stringLiteral(op.value);
|
|
803
1730
|
if (op instanceof DateConstantOperation) return sqlFormatDate(op.value);
|
|
804
1731
|
if (op instanceof DateTimeConstantOperation) return sqlFormatDatetime(op.value);
|
|
805
1732
|
if (op instanceof IntegerConstantOperation) return String(op.value);
|
|
806
|
-
if (op instanceof FloatConstantOperation) return String(op.value);
|
|
1733
|
+
if (op instanceof FloatConstantOperation) return Number.isInteger(op.value) && Math.abs(op.value) < 1e21 ? op.value.toFixed(1) : String(op.value);
|
|
807
1734
|
if (op instanceof BooleanConstantOperation) return op.value ? "TRUE" : "FALSE";
|
|
808
1735
|
if (op instanceof DecimalConstantOperation) return String(op.value);
|
|
809
1736
|
throw new Error("Unknown constant operation");
|
|
810
1737
|
}
|
|
811
|
-
function
|
|
1738
|
+
function selectedConstantString(op, d) {
|
|
1739
|
+
if (op instanceof FloatConstantOperation) return "CAST(" + constantValueString(op, d) + " AS " + d.doubleType + ")";
|
|
1740
|
+
if (op instanceof DateTimeConstantOperation) return "TIMESTAMP " + constantValueString(op, d);
|
|
1741
|
+
if (op instanceof DateConstantOperation) return "DATE " + constantValueString(op, d);
|
|
1742
|
+
return constantValueString(op, d);
|
|
1743
|
+
}
|
|
1744
|
+
function windowSpecToString(window, d) {
|
|
812
1745
|
const parts = [];
|
|
813
1746
|
if (window.partitionBy.length > 0) {
|
|
814
|
-
parts.push("PARTITION BY " + window.partitionBy.map((p) => sqlOperationToString(p)).join(", "));
|
|
1747
|
+
parts.push("PARTITION BY " + window.partitionBy.map((p) => sqlOperationToString(p, d)).join(", "));
|
|
815
1748
|
}
|
|
816
1749
|
if (window.orderBy.length > 0) {
|
|
817
1750
|
parts.push("ORDER BY " + window.orderBy.map(
|
|
818
|
-
(s) => sqlOperationToString(s.column) + (s.direction
|
|
1751
|
+
(s) => sqlOperationToString(s.column, d) + d.orderDirection(s.direction)
|
|
819
1752
|
).join(", "));
|
|
820
1753
|
}
|
|
821
1754
|
return "OVER (" + parts.join(" ") + ")";
|
|
822
1755
|
}
|
|
823
|
-
|
|
1756
|
+
var ARITHMETIC_PRECEDENCE = {
|
|
1757
|
+
["+" /* ADD */]: 1,
|
|
1758
|
+
["-" /* SUBTRACT */]: 1,
|
|
1759
|
+
["*" /* MULTIPLY */]: 2,
|
|
1760
|
+
["/" /* DIVIDE */]: 2
|
|
1761
|
+
};
|
|
1762
|
+
function arithmeticNeedsParentheses(parent, child, onRight) {
|
|
1763
|
+
if (!(child instanceof ArithmeticOperation)) return false;
|
|
1764
|
+
const here = ARITHMETIC_PRECEDENCE[parent.operator];
|
|
1765
|
+
const there = ARITHMETIC_PRECEDENCE[child.operator];
|
|
1766
|
+
return there < here || there === here && onRight && (parent.operator === "-" /* SUBTRACT */ || parent.operator === "/" /* DIVIDE */);
|
|
1767
|
+
}
|
|
1768
|
+
function operandString(operation, d) {
|
|
1769
|
+
return operation instanceof ConstantOperation ? constantValueString(operation, d) : sqlOperationToString(operation, d);
|
|
1770
|
+
}
|
|
1771
|
+
var RenderedSql = class extends RelationalOperationElement {
|
|
1772
|
+
constructor(sql) {
|
|
1773
|
+
super();
|
|
1774
|
+
this.sql = sql;
|
|
1775
|
+
}
|
|
1776
|
+
sql;
|
|
1777
|
+
};
|
|
1778
|
+
function isCondition(op) {
|
|
1779
|
+
return op instanceof ComparisonOperation || op instanceof LogicalOperation || op instanceof IsNullOperation || op instanceof IsNotNullOperation || op instanceof InOperation || op instanceof NotInOperation || op instanceof ExistsOperation || op instanceof NotExistsOperation;
|
|
1780
|
+
}
|
|
1781
|
+
function sqlOperationToString(operation, d) {
|
|
824
1782
|
if (operation instanceof TableAliasColumn) {
|
|
825
1783
|
return operation.tableAlias.alias + "." + operation.column.name;
|
|
826
1784
|
}
|
|
@@ -828,49 +1786,77 @@ function sqlOperationToString(operation) {
|
|
|
828
1786
|
const fn = WINDOW_SQL_NAMES[operation.func];
|
|
829
1787
|
const parts = [];
|
|
830
1788
|
if (operation.element !== null && operation.element !== void 0) {
|
|
831
|
-
parts.push(sqlOperationToString(operation.element));
|
|
1789
|
+
parts.push(sqlOperationToString(operation.element, d));
|
|
832
1790
|
}
|
|
833
1791
|
if (operation.secondArg !== void 0) parts.push(String(operation.secondArg));
|
|
834
1792
|
for (const arg of operation.extraArgs) {
|
|
835
|
-
parts.push(typeof arg === "string" ?
|
|
1793
|
+
parts.push(typeof arg === "string" ? d.stringLiteral(arg) : String(arg));
|
|
836
1794
|
}
|
|
837
1795
|
const sql = fn + "(" + parts.join(", ") + ")";
|
|
838
|
-
return sql + (operation.window !== void 0 ? " " + windowSpecToString(operation.window) : " OVER ()");
|
|
1796
|
+
return sql + (operation.window !== void 0 ? " " + windowSpecToString(operation.window, d) : " OVER ()");
|
|
1797
|
+
}
|
|
1798
|
+
if (operation instanceof AggregateOperation && operation.operator === "COUNT_DISTINCT" /* COUNT_DISTINCT */) {
|
|
1799
|
+
return "COUNT(DISTINCT " + sqlOperationToString(operation.element, d) + ")";
|
|
1800
|
+
}
|
|
1801
|
+
if (operation instanceof AggregateOperation && operation.operator === "STRING_AGG" /* STRING_AGG */) {
|
|
1802
|
+
let sql = d.stringAgg(
|
|
1803
|
+
sqlOperationToString(operation.element, d),
|
|
1804
|
+
d.stringLiteral(operation.separator ?? ""),
|
|
1805
|
+
operation.orderBy.map((s) => sqlOperationToString(s.column, d) + d.orderDirection(s.direction))
|
|
1806
|
+
);
|
|
1807
|
+
if (operation.window !== void 0) sql += " " + windowSpecToString(operation.window, d);
|
|
1808
|
+
return sql;
|
|
839
1809
|
}
|
|
840
1810
|
if (operation instanceof AggregateOperation) {
|
|
841
1811
|
const fn = AGGREGATE_SQL_NAMES[operation.operator] ?? operation.operator;
|
|
842
|
-
let sql = fn + "(" + sqlOperationToString(operation.element) + ")";
|
|
1812
|
+
let sql = fn + "(" + sqlOperationToString(operation.element, d) + ")";
|
|
843
1813
|
if (operation.window !== void 0) {
|
|
844
|
-
sql += " " + windowSpecToString(operation.window);
|
|
1814
|
+
sql += " " + windowSpecToString(operation.window, d);
|
|
845
1815
|
}
|
|
846
1816
|
return sql;
|
|
847
1817
|
}
|
|
848
1818
|
if (operation instanceof ScalarFunctionOperation) {
|
|
849
1819
|
const fn = SCALAR_SQL_NAMES[operation.func];
|
|
850
|
-
const parts = [sqlOperationToString(operation.element)];
|
|
1820
|
+
const parts = [sqlOperationToString(operation.element, d)];
|
|
851
1821
|
if (operation.secondArg !== void 0) parts.push(String(operation.secondArg));
|
|
852
1822
|
for (const arg of operation.extraArgs) {
|
|
853
|
-
parts.push(typeof arg === "string" ?
|
|
1823
|
+
parts.push(typeof arg === "string" ? d.stringLiteral(arg) : String(arg));
|
|
854
1824
|
}
|
|
855
1825
|
return fn + "(" + parts.join(", ") + ")";
|
|
856
1826
|
}
|
|
857
1827
|
if (operation instanceof DateExtractOperation) {
|
|
858
|
-
|
|
1828
|
+
const element = sqlOperationToString(operation.element, d);
|
|
1829
|
+
return operation.part === "DOW" /* DOW */ ? d.dayOfWeek(element) : "EXTRACT(" + operation.part + " FROM " + element + ")";
|
|
1830
|
+
}
|
|
1831
|
+
if (operation instanceof DateTruncOperation) {
|
|
1832
|
+
return "CAST(DATE_TRUNC('" + operation.part.toLowerCase() + "', " + sqlOperationToString(operation.element, d) + ") AS DATE)";
|
|
859
1833
|
}
|
|
860
1834
|
if (operation instanceof DateArithmeticOperation) {
|
|
861
1835
|
const op = operation.isAdd ? "+" : "-";
|
|
862
|
-
return sqlOperationToString(operation.element) + " " + op + " INTERVAL " + operation.n + " " + operation.unit;
|
|
1836
|
+
return sqlOperationToString(operation.element, d) + " " + op + " INTERVAL '" + operation.n + "' " + operation.unit;
|
|
863
1837
|
}
|
|
864
1838
|
if (operation instanceof DateDiffOperation) {
|
|
865
|
-
|
|
866
|
-
return "DATE_DIFF('" + operation.unit.toLowerCase() + "', " + sqlOperationToString(operation.element) + ", " + otherSql + ")";
|
|
1839
|
+
return d.dateDiff(operation.unit, sqlOperationToString(operation.element, d), "TIMESTAMP " + sqlFormatDatetime(operation.other));
|
|
867
1840
|
}
|
|
868
1841
|
if (operation instanceof CountAllOperation) return "COUNT(*)";
|
|
1842
|
+
if (operation instanceof ConstantOperation) return selectedConstantString(operation, d);
|
|
1843
|
+
if (operation instanceof RenderedSql) return operation.sql;
|
|
1844
|
+
if (operation instanceof ConcatOperation) return operation.parts.map((part) => operandString(part, d)).join(" || ");
|
|
1845
|
+
if (operation instanceof ArithmeticOperation) {
|
|
1846
|
+
let left = operandString(operation.left, d);
|
|
1847
|
+
let right = operandString(operation.right, d);
|
|
1848
|
+
if (arithmeticNeedsParentheses(operation, operation.left, false)) left = "(" + left + ")";
|
|
1849
|
+
if (arithmeticNeedsParentheses(operation, operation.right, true)) right = "(" + right + ")";
|
|
1850
|
+
return left + " " + operation.operator + " " + right;
|
|
1851
|
+
}
|
|
869
1852
|
if (operation instanceof Alias) {
|
|
870
|
-
return sqlOperationToString(operation.element) +
|
|
1853
|
+
return sqlOperationToString(operation.element, d) + " AS " + d.quoteIdentifier(operation.name);
|
|
871
1854
|
}
|
|
872
1855
|
throw new TypeError("Unknown operation in sqlOperationToString: " + operation.constructor.name);
|
|
873
1856
|
}
|
|
1857
|
+
function embeddedOf(ref) {
|
|
1858
|
+
return ref instanceof Attribute ? ref.embedded() : ref.embedded;
|
|
1859
|
+
}
|
|
874
1860
|
function findColumn(operation) {
|
|
875
1861
|
if (operation instanceof UnaryOperation) return findColumn(operation.element);
|
|
876
1862
|
if (operation instanceof ColumnWithJoin) return operation;
|
|
@@ -884,89 +1870,195 @@ function openEndClause(endAttr, value, infiniteDatetime) {
|
|
|
884
1870
|
}
|
|
885
1871
|
return gtOp;
|
|
886
1872
|
}
|
|
1873
|
+
function andAll(ops) {
|
|
1874
|
+
const present = ops.filter((op) => op !== null);
|
|
1875
|
+
if (present.length === 0) return null;
|
|
1876
|
+
return present.slice(1).reduce((left, right) => new LogicalOperation(left, "AND" /* AND */, right), present[0]);
|
|
1877
|
+
}
|
|
1878
|
+
function processingPredicate(mc, processingDatetime, joinNode) {
|
|
1879
|
+
if (!(mc instanceof ProcessingTemporalColumns || mc instanceof BusinessDateAndProcessingTemporalColumns || mc instanceof BiTemporalColumns) || processingDatetime === null) return null;
|
|
1880
|
+
const startAt = new DateTimeAttribute("start_at", mc.startAtColumn.name, mc.startAtColumn.type, mc.startAtColumn.table.qualifiedName, joinNode);
|
|
1881
|
+
const endAt = new DateTimeAttribute("end_at", mc.endAtColumn.name, mc.endAtColumn.type, mc.endAtColumn.table.qualifiedName, joinNode);
|
|
1882
|
+
return new LogicalOperation(startAt.lte(processingDatetime), "AND" /* AND */, openEndClause(endAt, processingDatetime, mc.infiniteDatetime));
|
|
1883
|
+
}
|
|
1884
|
+
function businessPredicate(mc, businessDate, joinNode) {
|
|
1885
|
+
if (businessDate === null) return null;
|
|
1886
|
+
if (mc instanceof BiTemporalColumns) {
|
|
1887
|
+
const dateFrom = new DateAttribute("business_date_from", mc.businessDateFromColumn.name, mc.businessDateFromColumn.type, mc.businessDateFromColumn.table.qualifiedName, joinNode);
|
|
1888
|
+
const dateTo = new DateAttribute("business_date_to", mc.businessDateToColumn.name, mc.businessDateToColumn.type, mc.businessDateToColumn.table.qualifiedName, joinNode);
|
|
1889
|
+
return new LogicalOperation(dateFrom.lte(businessDate), "AND" /* AND */, openEndClause(dateTo, businessDate, mc.infiniteDatetime));
|
|
1890
|
+
}
|
|
1891
|
+
if (mc instanceof BusinessDateAndProcessingTemporalColumns || mc instanceof SingleBusinessDateColumn) {
|
|
1892
|
+
const businessAtt = new DateAttribute("business_date", mc.businessDateColumn.name, mc.businessDateColumn.type, mc.businessDateColumn.table.qualifiedName, joinNode);
|
|
1893
|
+
return businessAtt.eq(businessDate);
|
|
1894
|
+
}
|
|
1895
|
+
return null;
|
|
1896
|
+
}
|
|
1897
|
+
function businessRangePredicate(mc, businessDateFrom, businessDateTo, joinNode) {
|
|
1898
|
+
if (businessDateFrom === null || businessDateTo === null) return null;
|
|
1899
|
+
if (mc instanceof BiTemporalColumns) {
|
|
1900
|
+
const dateFrom = new DateAttribute("business_date_from", mc.businessDateFromColumn.name, mc.businessDateFromColumn.type, mc.businessDateFromColumn.table.qualifiedName, joinNode);
|
|
1901
|
+
const dateTo = new DateAttribute("business_date_to", mc.businessDateToColumn.name, mc.businessDateToColumn.type, mc.businessDateToColumn.table.qualifiedName, joinNode);
|
|
1902
|
+
return new LogicalOperation(dateFrom.lte(businessDateTo), "AND" /* AND */, openEndClause(dateTo, businessDateFrom, mc.infiniteDatetime));
|
|
1903
|
+
}
|
|
1904
|
+
if (mc instanceof BusinessDateAndProcessingTemporalColumns || mc instanceof SingleBusinessDateColumn) {
|
|
1905
|
+
const businessAtt = new DateAttribute("business_date", mc.businessDateColumn.name, mc.businessDateColumn.type, mc.businessDateColumn.table.qualifiedName, joinNode);
|
|
1906
|
+
return new LogicalOperation(businessAtt.gte(businessDateFrom), "AND" /* AND */, businessAtt.lte(businessDateTo));
|
|
1907
|
+
}
|
|
1908
|
+
return null;
|
|
1909
|
+
}
|
|
887
1910
|
function buildMilestoningFilterOperation(businessDate, processingDatetime, table, joinNode) {
|
|
888
1911
|
const mc = table.milestoningColumns;
|
|
1912
|
+
return andAll([processingPredicate(mc, processingDatetime, joinNode), businessPredicate(mc, businessDate, joinNode)]);
|
|
1913
|
+
}
|
|
1914
|
+
function buildMilestoningFilterOperationForDateRange(businessDateFrom, businessDateTo, processingDatetime, table, joinNode) {
|
|
1915
|
+
const mc = table.milestoningColumns;
|
|
1916
|
+
return andAll([
|
|
1917
|
+
processingPredicate(mc, processingDatetime, joinNode),
|
|
1918
|
+
businessRangePredicate(mc, businessDateFrom, businessDateTo, joinNode)
|
|
1919
|
+
]);
|
|
1920
|
+
}
|
|
1921
|
+
function walkRefs(op, visit, visitExists) {
|
|
1922
|
+
if (op === null || op === void 0) return;
|
|
1923
|
+
if (op instanceof Attribute || op instanceof ColumnWithJoin) {
|
|
1924
|
+
visit(op);
|
|
1925
|
+
} else if (op instanceof ExistsOperation || op instanceof NotExistsOperation) {
|
|
1926
|
+
visitExists?.(op.node);
|
|
1927
|
+
} else if (op instanceof AggregateOperation) {
|
|
1928
|
+
walkRefs(op.element, visit, visitExists);
|
|
1929
|
+
if (op.window) walkWindowSpec(op.window, visit, visitExists);
|
|
1930
|
+
for (const sort of op.orderBy) walkRefs(sort, visit, visitExists);
|
|
1931
|
+
} else if (op instanceof WindowFunctionOperation) {
|
|
1932
|
+
if (op.element) walkRefs(op.element, visit, visitExists);
|
|
1933
|
+
if (op.window) walkWindowSpec(op.window, visit, visitExists);
|
|
1934
|
+
} else if (op instanceof ScalarFunctionOperation || op instanceof DateExtractOperation || op instanceof DateTruncOperation || op instanceof DateArithmeticOperation || op instanceof DateDiffOperation || op instanceof IsNullOperation || op instanceof IsNotNullOperation || op instanceof InOperation || op instanceof NotInOperation) {
|
|
1935
|
+
walkRefs(op.element, visit, visitExists);
|
|
1936
|
+
} else if (op instanceof Alias) {
|
|
1937
|
+
walkRefs(op.element, visit, visitExists);
|
|
1938
|
+
} else if (op instanceof ConcatOperation) {
|
|
1939
|
+
for (const part of op.parts) walkRefs(part, visit, visitExists);
|
|
1940
|
+
} else if (op instanceof ArithmeticOperation) {
|
|
1941
|
+
walkRefs(op.left, visit, visitExists);
|
|
1942
|
+
walkRefs(op.right, visit, visitExists);
|
|
1943
|
+
} else if (op instanceof CaseOperation) {
|
|
1944
|
+
walkRefs(op.condition, visit, visitExists);
|
|
1945
|
+
walkRefs(op.then, visit, visitExists);
|
|
1946
|
+
walkRefs(op.fallback, visit, visitExists);
|
|
1947
|
+
} else if (op instanceof SortOperation) {
|
|
1948
|
+
walkRefs(op.column, visit, visitExists);
|
|
1949
|
+
} else if (op instanceof LogicalOperation || op instanceof ComparisonOperation) {
|
|
1950
|
+
walkRefs(op.left, visit, visitExists);
|
|
1951
|
+
walkRefs(op.right, visit, visitExists);
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
function walkWindowSpec(window, visit, visitExists) {
|
|
1955
|
+
for (const p of window.partitionBy) walkRefs(p, visit, visitExists);
|
|
1956
|
+
for (const s of window.orderBy) walkRefs(s.column, visit, visitExists);
|
|
1957
|
+
}
|
|
1958
|
+
function buildJoinFilterFromProperties(node, filter, columnMap) {
|
|
889
1959
|
const ops = [];
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
ops.push(new LogicalOperation(dateFrom.lte(businessDate), "AND" /* AND */, openEndClause(dateTo, businessDate, mc.infiniteDatetime)));
|
|
895
|
-
}
|
|
896
|
-
if (processingDatetime !== null) {
|
|
897
|
-
const startAt = new DateTimeAttribute("start_at", mc.startAtColumn.name, mc.startAtColumn.type, mc.startAtColumn.table.qualifiedName, joinNode);
|
|
898
|
-
const endAt = new DateTimeAttribute("end_at", mc.endAtColumn.name, mc.endAtColumn.type, mc.endAtColumn.table.qualifiedName, joinNode);
|
|
899
|
-
ops.push(new LogicalOperation(startAt.lte(processingDatetime), "AND" /* AND */, openEndClause(endAt, processingDatetime, mc.infiniteDatetime)));
|
|
900
|
-
}
|
|
901
|
-
} else if (mc instanceof BusinessDateAndProcessingTemporalColumns) {
|
|
902
|
-
if (businessDate !== null) {
|
|
903
|
-
const businessAtt = new DateAttribute("business_date", mc.businessDateColumn.name, mc.businessDateColumn.type, mc.businessDateColumn.table.qualifiedName, joinNode);
|
|
904
|
-
ops.push(businessAtt.eq(businessDate));
|
|
905
|
-
}
|
|
906
|
-
if (processingDatetime !== null) {
|
|
907
|
-
const startAt = new DateTimeAttribute("start_at", mc.startAtColumn.name, mc.startAtColumn.type, mc.startAtColumn.table.qualifiedName, joinNode);
|
|
908
|
-
const endAt = new DateTimeAttribute("end_at", mc.endAtColumn.name, mc.endAtColumn.type, mc.endAtColumn.table.qualifiedName, joinNode);
|
|
909
|
-
ops.push(new LogicalOperation(startAt.lte(processingDatetime), "AND" /* AND */, openEndClause(endAt, processingDatetime, mc.infiniteDatetime)));
|
|
1960
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
1961
|
+
const entry = columnMap[key];
|
|
1962
|
+
if (entry === void 0) {
|
|
1963
|
+
throw new Error(`Unknown property '${key}' \u2014 valid properties are: ${Object.keys(columnMap).sort().join(", ")}`);
|
|
910
1964
|
}
|
|
911
|
-
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
return new LogicalOperation(ops[0], "AND" /* AND */, ops[1]);
|
|
1965
|
+
const [name, type, table] = entry;
|
|
1966
|
+
const col = new ColumnWithJoin(new Column(name, type, table), node);
|
|
1967
|
+
let constant;
|
|
1968
|
+
if (typeof value === "boolean") constant = new BooleanConstantOperation(value);
|
|
1969
|
+
else if (typeof value === "number") constant = Number.isInteger(value) ? new IntegerConstantOperation(value) : new FloatConstantOperation(value);
|
|
1970
|
+
else if (value instanceof Date) constant = type.toUpperCase() === "DATE" ? new DateConstantOperation(value) : new DateTimeConstantOperation(value);
|
|
1971
|
+
else constant = new StringConstantOperation(String(value));
|
|
1972
|
+
ops.push(new ComparisonOperation(col, "EQUAL" /* EQUAL */, constant));
|
|
1973
|
+
}
|
|
1974
|
+
return ops.reduce((acc, op) => new LogicalOperation(acc, "AND" /* AND */, op));
|
|
922
1975
|
}
|
|
923
|
-
function
|
|
1976
|
+
function withAncestors(nodes) {
|
|
1977
|
+
const ordered = /* @__PURE__ */ new Set();
|
|
1978
|
+
const add = (node) => {
|
|
1979
|
+
if (ordered.has(node)) return;
|
|
1980
|
+
if (node.parent !== void 0) add(node.parent);
|
|
1981
|
+
ordered.add(node);
|
|
1982
|
+
};
|
|
1983
|
+
for (const node of nodes) add(node);
|
|
1984
|
+
return [...ordered];
|
|
1985
|
+
}
|
|
1986
|
+
function buildQueryOperation(businessDate, processingDatetime, columns, table, op, orderBy = [], groupBy = [], limit, businessDateTo = null, distinct = false, offset, having) {
|
|
924
1987
|
let filter = op;
|
|
1988
|
+
const milestoningFor = (t, node) => businessDateTo !== null ? buildMilestoningFilterOperationForDateRange(businessDate, businessDateTo, processingDatetime, t, node) : buildMilestoningFilterOperation(businessDate, processingDatetime, t, node);
|
|
925
1989
|
if (table instanceof MilestonedTable) {
|
|
926
|
-
const milestonedOp =
|
|
1990
|
+
const milestonedOp = milestoningFor(table);
|
|
927
1991
|
if (milestonedOp !== null) {
|
|
928
1992
|
filter = filter instanceof NoOperation ? milestonedOp : new LogicalOperation(filter, "AND" /* AND */, milestonedOp);
|
|
929
1993
|
}
|
|
930
1994
|
}
|
|
931
|
-
const requiredJoins =
|
|
932
|
-
const
|
|
933
|
-
|
|
934
|
-
if (
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1995
|
+
const requiredJoins = /* @__PURE__ */ new Set();
|
|
1996
|
+
const collect = (ref) => {
|
|
1997
|
+
const parent = ref instanceof Attribute ? ref.parent() : ref.parent;
|
|
1998
|
+
if (parent !== void 0) requiredJoins.add(parent);
|
|
1999
|
+
};
|
|
2000
|
+
const collectNode = (node) => requiredJoins.add(node);
|
|
2001
|
+
for (const col of columns) walkRefs(col, collect, collectNode);
|
|
2002
|
+
for (const expr of groupBy) walkRefs(expr, collect, collectNode);
|
|
2003
|
+
for (const sort of orderBy) walkRefs(sort, collect, collectNode);
|
|
2004
|
+
walkRefs(op, collect, collectNode);
|
|
2005
|
+
const joinFilters = /* @__PURE__ */ new Map();
|
|
2006
|
+
for (const node of withAncestors(requiredJoins)) {
|
|
2007
|
+
let combined;
|
|
2008
|
+
if (Object.keys(node.join.filterKwargs).length > 0) {
|
|
2009
|
+
combined = buildJoinFilterFromProperties(node, node.join.filterKwargs, node.join.filterColumnMap);
|
|
940
2010
|
}
|
|
941
|
-
if (node !== void 0 && !requiredJoinIds.has(node)) {
|
|
942
|
-
requiredJoinIds.add(node);
|
|
943
|
-
requiredJoins.push(node);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
for (const node of requiredJoins) {
|
|
947
2011
|
if (node.join.target instanceof MilestonedTable) {
|
|
948
|
-
const milestonedOp =
|
|
2012
|
+
const milestonedOp = milestoningFor(node.join.target, node);
|
|
949
2013
|
if (milestonedOp !== null) {
|
|
950
|
-
|
|
2014
|
+
combined = combined === void 0 ? milestonedOp : new LogicalOperation(combined, "AND" /* AND */, milestonedOp);
|
|
951
2015
|
}
|
|
952
2016
|
}
|
|
2017
|
+
if (combined !== void 0) joinFilters.set(node, combined);
|
|
953
2018
|
}
|
|
954
|
-
return new SelectOperation(columns, filter, orderBy, groupBy, limit, table);
|
|
2019
|
+
return new SelectOperation(columns, filter, orderBy, groupBy, limit, table, joinFilters, distinct, offset, having);
|
|
2020
|
+
}
|
|
2021
|
+
function needsParentheses(parent, child) {
|
|
2022
|
+
return child instanceof LogicalOperation && child.operator !== parent.operator;
|
|
2023
|
+
}
|
|
2024
|
+
function reachesToMany(op) {
|
|
2025
|
+
if (op instanceof ColumnWithJoin) {
|
|
2026
|
+
for (let node = op.parent; node !== void 0; node = node.parent) if (node.many) return true;
|
|
2027
|
+
return false;
|
|
2028
|
+
}
|
|
2029
|
+
if (op instanceof UnaryOperation || op instanceof Alias) return reachesToMany(op.element);
|
|
2030
|
+
if (op instanceof BinaryOperation) return reachesToMany(op.left) || reachesToMany(op.right);
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
function unaliased(op) {
|
|
2034
|
+
return op instanceof Alias ? unaliased(op.element) : op;
|
|
955
2035
|
}
|
|
956
2036
|
var SQLQueryGenerator = class {
|
|
2037
|
+
constructor(_dialect) {
|
|
2038
|
+
this._dialect = _dialect;
|
|
2039
|
+
}
|
|
2040
|
+
_dialect;
|
|
957
2041
|
_select = [];
|
|
958
2042
|
_from = /* @__PURE__ */ new Set();
|
|
959
2043
|
_join = [];
|
|
960
2044
|
_groupByParts = [];
|
|
2045
|
+
_having = "";
|
|
961
2046
|
_orderByParts = [];
|
|
962
2047
|
_where = "";
|
|
963
2048
|
_limit;
|
|
2049
|
+
_distinct = false;
|
|
2050
|
+
_offset;
|
|
964
2051
|
_tableAliasIncr = 0;
|
|
965
2052
|
_tableAliasesByTable = /* @__PURE__ */ new Map();
|
|
966
2053
|
_addedJoinIds = /* @__PURE__ */ new Set();
|
|
967
2054
|
_rootTable;
|
|
2055
|
+
_elidableNodes = /* @__PURE__ */ new Set();
|
|
2056
|
+
_joinFilters = /* @__PURE__ */ new Map();
|
|
2057
|
+
_guardOptional = true;
|
|
968
2058
|
generate(select) {
|
|
969
2059
|
this._rootTable = select.table;
|
|
2060
|
+
this._elidableNodes = this._computeElidableNodes(select);
|
|
2061
|
+
this._joinFilters = select.joinFilters;
|
|
970
2062
|
if (this._rootTable !== void 0) {
|
|
971
2063
|
this._from.add(this._tableAliasForTable(this._rootTable.qualifiedName, this._rootTable.qualifiedName));
|
|
972
2064
|
}
|
|
@@ -979,46 +2071,104 @@ var SQLQueryGenerator = class {
|
|
|
979
2071
|
for (const node of groupByJoins.values()) {
|
|
980
2072
|
this._addJoin(node);
|
|
981
2073
|
}
|
|
982
|
-
this._groupByParts =
|
|
2074
|
+
this._groupByParts = this._groupByPartsFor(select);
|
|
2075
|
+
this._having = "";
|
|
2076
|
+
if (select.having !== void 0) {
|
|
2077
|
+
const havingJoins = /* @__PURE__ */ new Map();
|
|
2078
|
+
this._collectRequiredJoins(select.having, havingJoins);
|
|
2079
|
+
for (const node of havingJoins.values()) this._addJoin(node);
|
|
2080
|
+
this._guardOptional = false;
|
|
2081
|
+
try {
|
|
2082
|
+
this._having = this.buildFilter(select.having);
|
|
2083
|
+
} finally {
|
|
2084
|
+
this._guardOptional = true;
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
983
2087
|
this._orderByParts = select.orderBy.map(
|
|
984
|
-
(s) => this.
|
|
2088
|
+
(s) => this._sortExpression(s.column) + this._dialect.orderDirection(s.direction)
|
|
985
2089
|
);
|
|
986
2090
|
this._limit = select.limit;
|
|
2091
|
+
this._distinct = select.distinct;
|
|
2092
|
+
this._offset = select.offset;
|
|
2093
|
+
}
|
|
2094
|
+
/**
|
|
2095
|
+
* The GROUP BY of a query: the grouping it was given, else the grouping its columns imply.
|
|
2096
|
+
*
|
|
2097
|
+
* Columns that are not aggregated are what the aggregates are computed for, so a query that selects both is
|
|
2098
|
+
* grouped by those columns (as a DataFrame's `groupby(columns).agg(...)` does). An aggregate read through a
|
|
2099
|
+
* to-many association is computed for each row of the root table, as Legend does, so the root's primary key
|
|
2100
|
+
* is grouped by too. A query that selects only aggregates over the root's own columns is not grouped: the
|
|
2101
|
+
* aggregate covers every row. A constant needs no grouping: a bare
|
|
2102
|
+
* `GROUP BY 7` would be a column position.
|
|
2103
|
+
*/
|
|
2104
|
+
_groupByPartsFor(select) {
|
|
2105
|
+
if (select.groupBy.length > 0) return select.groupBy.map((a) => this._attrToColString(a));
|
|
2106
|
+
const aggregates = select.display.filter(containsAggregate);
|
|
2107
|
+
if (aggregates.length === 0) return [];
|
|
2108
|
+
const perRoot = select.table !== void 0 && aggregates.some(reachesToMany);
|
|
2109
|
+
const keys = perRoot ? select.table.columns.filter((c) => c.primaryKey).map((c) => this._columnToString(c)) : [];
|
|
2110
|
+
const grouped = select.display.map((column, i) => ({ column, shown: this._select[i] })).filter(({ column }) => !containsAggregateOrWindow(column) && !(unaliased(column) instanceof ConstantOperation)).map(({ shown }) => sqlOperationToString(shown.element, this._dialect));
|
|
2111
|
+
return [.../* @__PURE__ */ new Set([...keys, ...grouped])];
|
|
2112
|
+
}
|
|
2113
|
+
/** What a sort orders by: a column, or an expression such as an aggregate. */
|
|
2114
|
+
_sortExpression(expression) {
|
|
2115
|
+
if (expression instanceof ColumnWithJoin || expression instanceof Attribute) return this.buildFilter(expression);
|
|
2116
|
+
return sqlOperationToString(this._rewriteOperation(expression), this._dialect);
|
|
2117
|
+
}
|
|
2118
|
+
_columnToString(column) {
|
|
2119
|
+
return this._tableAliasForTable(column.owner, column.owner).alias + "." + column.name;
|
|
987
2120
|
}
|
|
988
2121
|
_attrToColString(attr) {
|
|
989
|
-
const
|
|
990
|
-
const ta = this._tableAliasForTable(
|
|
991
|
-
return ta.alias + "." +
|
|
2122
|
+
const { column, parent } = this._resolve(attr);
|
|
2123
|
+
const ta = this._tableAliasForTable(column.owner, parent ?? column.owner);
|
|
2124
|
+
return ta.alias + "." + column.name;
|
|
992
2125
|
}
|
|
993
2126
|
_collectRequiredJoins(op, out) {
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
2127
|
+
walkRefs(op, (ref) => {
|
|
2128
|
+
const { parent } = this._resolve(ref);
|
|
2129
|
+
if (parent !== void 0) out.set(parent, parent);
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
/**
|
|
2133
|
+
* Determine upfront which join nodes can be satisfied entirely by embedded (join-less) alternates:
|
|
2134
|
+
* a node is elidable when every reference to it has an embedded alternate. A reference without one
|
|
2135
|
+
* (e.g. a milestoning column) keeps the join for every reference to that node.
|
|
2136
|
+
*/
|
|
2137
|
+
_computeElidableNodes(select) {
|
|
2138
|
+
const refsByNode = /* @__PURE__ */ new Map();
|
|
2139
|
+
const record = (ref) => {
|
|
2140
|
+
const parent = ref instanceof Attribute ? ref.parent() : ref.parent;
|
|
2141
|
+
if (parent === void 0) return;
|
|
2142
|
+
const refs = refsByNode.get(parent);
|
|
2143
|
+
if (refs) refs.push(ref);
|
|
2144
|
+
else refsByNode.set(parent, [ref]);
|
|
2145
|
+
};
|
|
2146
|
+
for (const col of select.display) walkRefs(col, record);
|
|
2147
|
+
for (const expr of select.groupBy) walkRefs(expr, record);
|
|
2148
|
+
for (const sort of select.orderBy) walkRefs(sort, record);
|
|
2149
|
+
walkRefs(select.filter, record);
|
|
2150
|
+
const elidable = /* @__PURE__ */ new Set();
|
|
2151
|
+
for (const [node, refs] of refsByNode) {
|
|
2152
|
+
if (refs.every((ref) => embeddedOf(ref) !== void 0)) elidable.add(node);
|
|
1013
2153
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
2154
|
+
return elidable;
|
|
2155
|
+
}
|
|
2156
|
+
/** The (column, parent) a reference should resolve to, substituting its embedded alternate when its join is elided. */
|
|
2157
|
+
_resolve(ref) {
|
|
2158
|
+
const column = ref instanceof Attribute ? ref.column() : ref.column;
|
|
2159
|
+
const parent = ref instanceof Attribute ? ref.parent() : ref.parent;
|
|
2160
|
+
if (parent !== void 0 && this._elidableNodes.has(parent)) {
|
|
2161
|
+
const embedded = embeddedOf(ref);
|
|
2162
|
+
if (embedded !== void 0) return this._resolve(embedded);
|
|
1018
2163
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
2164
|
+
return { column, parent };
|
|
2165
|
+
}
|
|
2166
|
+
/** Whether the value `op` reads can be missing, in the join or embedded form that is used for it. */
|
|
2167
|
+
_resolveOptional(op) {
|
|
2168
|
+
if (op.parent !== void 0 && this._elidableNodes.has(op.parent) && op.embedded !== void 0) {
|
|
2169
|
+
return this._resolveOptional(op.embedded);
|
|
1021
2170
|
}
|
|
2171
|
+
return op.optional;
|
|
1022
2172
|
}
|
|
1023
2173
|
_rewriteWindowSpec(window) {
|
|
1024
2174
|
const partitionBy = window.partitionBy.map((p) => this._rewriteOperation(p));
|
|
@@ -1026,13 +2176,9 @@ var SQLQueryGenerator = class {
|
|
|
1026
2176
|
return new WindowSpecification(partitionBy, orderBy);
|
|
1027
2177
|
}
|
|
1028
2178
|
_rewriteOperation(op) {
|
|
1029
|
-
if (op instanceof Attribute) {
|
|
1030
|
-
const
|
|
1031
|
-
return new TableAliasColumn(
|
|
1032
|
-
}
|
|
1033
|
-
if (op instanceof ColumnWithJoin) {
|
|
1034
|
-
const ta = op.parent !== void 0 ? this._tableAliasForTable(op.column.owner, op.parent) : this._tableAliasForTable(op.column.owner, op.column.owner);
|
|
1035
|
-
return new TableAliasColumn(op.column, ta);
|
|
2179
|
+
if (op instanceof Attribute || op instanceof ColumnWithJoin) {
|
|
2180
|
+
const { column, parent } = this._resolve(op);
|
|
2181
|
+
return new TableAliasColumn(column, this._tableAliasForTable(column.owner, parent ?? column.owner));
|
|
1036
2182
|
}
|
|
1037
2183
|
if (op instanceof Column) {
|
|
1038
2184
|
const ta = this._tableAliasForTable(op.owner, op.owner);
|
|
@@ -1043,9 +2189,17 @@ var SQLQueryGenerator = class {
|
|
|
1043
2189
|
this._rewriteOperation(op.element),
|
|
1044
2190
|
op.operator,
|
|
1045
2191
|
op.displayName,
|
|
1046
|
-
op.window ? this._rewriteWindowSpec(op.window) : void 0
|
|
2192
|
+
op.window ? this._rewriteWindowSpec(op.window) : void 0,
|
|
2193
|
+
op.separator,
|
|
2194
|
+
op.orderBy.map((s) => new SortOperation(this._rewriteOperation(s.column), s.direction))
|
|
1047
2195
|
);
|
|
1048
2196
|
}
|
|
2197
|
+
if (op instanceof CaseOperation) return new RenderedSql(this._caseSql(op));
|
|
2198
|
+
if (isCondition(op)) return new RenderedSql(this.buildFilter(op));
|
|
2199
|
+
if (op instanceof ConcatOperation) return new ConcatOperation(op.parts.map((part) => this._rewriteOperation(part)), op.displayName);
|
|
2200
|
+
if (op instanceof ArithmeticOperation) {
|
|
2201
|
+
return new ArithmeticOperation(this._rewriteOperation(op.left), op.operator, this._rewriteOperation(op.right), op.displayName);
|
|
2202
|
+
}
|
|
1049
2203
|
if (op instanceof WindowFunctionOperation) {
|
|
1050
2204
|
const el = op.element ? this._rewriteOperation(op.element) : null;
|
|
1051
2205
|
return new WindowFunctionOperation(
|
|
@@ -1063,6 +2217,9 @@ var SQLQueryGenerator = class {
|
|
|
1063
2217
|
if (op instanceof DateExtractOperation) {
|
|
1064
2218
|
return new DateExtractOperation(this._rewriteOperation(op.element), op.part, op.displayName);
|
|
1065
2219
|
}
|
|
2220
|
+
if (op instanceof DateTruncOperation) {
|
|
2221
|
+
return new DateTruncOperation(this._rewriteOperation(op.element), op.part, op.displayName);
|
|
2222
|
+
}
|
|
1066
2223
|
if (op instanceof DateArithmeticOperation) {
|
|
1067
2224
|
return new DateArithmeticOperation(this._rewriteOperation(op.element), op.n, op.unit, op.isAdd, op.displayName);
|
|
1068
2225
|
}
|
|
@@ -1071,6 +2228,13 @@ var SQLQueryGenerator = class {
|
|
|
1071
2228
|
}
|
|
1072
2229
|
return op;
|
|
1073
2230
|
}
|
|
2231
|
+
/** The CASE written out now: its condition can only be rendered while the query is being built. */
|
|
2232
|
+
_caseSql(op) {
|
|
2233
|
+
const branch = (value) => value instanceof ConstantOperation ? constantValueString(value, this._dialect) : sqlOperationToString(this._rewriteOperation(value), this._dialect);
|
|
2234
|
+
let sql = "CASE WHEN " + this.buildFilter(op.condition) + " THEN " + branch(op.then);
|
|
2235
|
+
if (op.fallback !== void 0) sql += " ELSE " + branch(op.fallback);
|
|
2236
|
+
return sql + " END";
|
|
2237
|
+
}
|
|
1074
2238
|
processSelect(cols) {
|
|
1075
2239
|
const requiredJoins = /* @__PURE__ */ new Map();
|
|
1076
2240
|
for (const col of cols) {
|
|
@@ -1079,88 +2243,96 @@ var SQLQueryGenerator = class {
|
|
|
1079
2243
|
for (const node of requiredJoins.values()) {
|
|
1080
2244
|
this._addJoin(node);
|
|
1081
2245
|
}
|
|
1082
|
-
for (const col of cols)
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
);
|
|
1123
|
-
this._select.push(new Alias(rewrittenAgg, alias));
|
|
1124
|
-
} else if (col instanceof ScalarFunctionOperation) {
|
|
1125
|
-
const colNested = findColumn(col);
|
|
1126
|
-
const node = colNested.parent;
|
|
1127
|
-
let ta;
|
|
1128
|
-
if (node !== void 0) {
|
|
1129
|
-
ta = this._tableAliasForTable(colNested.column.owner, node);
|
|
1130
|
-
} else {
|
|
1131
|
-
ta = this._tableAliasForTable(colNested.column.owner, colNested.column.owner);
|
|
1132
|
-
this._from.add(ta);
|
|
1133
|
-
}
|
|
1134
|
-
const alias = col.displayName ?? col.func + " " + colNested.column.name;
|
|
1135
|
-
this._select.push(new Alias(
|
|
1136
|
-
new ScalarFunctionOperation(new TableAliasColumn(colNested.column, ta), col.func, void 0, col.secondArg, col.extraArgs),
|
|
1137
|
-
alias
|
|
1138
|
-
));
|
|
1139
|
-
} else if (col instanceof DateExtractOperation || col instanceof DateArithmeticOperation || col instanceof DateDiffOperation) {
|
|
1140
|
-
const colNested = findColumn(col);
|
|
1141
|
-
const node = colNested.parent;
|
|
1142
|
-
let ta;
|
|
1143
|
-
if (node !== void 0) {
|
|
1144
|
-
ta = this._tableAliasForTable(colNested.column.owner, node);
|
|
1145
|
-
} else {
|
|
1146
|
-
ta = this._tableAliasForTable(colNested.column.owner, colNested.column.owner);
|
|
1147
|
-
this._from.add(ta);
|
|
1148
|
-
}
|
|
1149
|
-
const alias = col.displayName ?? colNested.column.name;
|
|
1150
|
-
let aliasedOp;
|
|
1151
|
-
if (col instanceof DateExtractOperation) {
|
|
1152
|
-
aliasedOp = new DateExtractOperation(new TableAliasColumn(colNested.column, ta), col.part);
|
|
1153
|
-
} else if (col instanceof DateArithmeticOperation) {
|
|
1154
|
-
aliasedOp = new DateArithmeticOperation(new TableAliasColumn(colNested.column, ta), col.n, col.unit, col.isAdd);
|
|
1155
|
-
} else {
|
|
1156
|
-
aliasedOp = new DateDiffOperation(new TableAliasColumn(colNested.column, ta), col.other, col.unit);
|
|
1157
|
-
}
|
|
1158
|
-
this._select.push(new Alias(aliasedOp, alias));
|
|
1159
|
-
} else if (col instanceof CountAllOperation) {
|
|
1160
|
-
const ta = this._tableAliasForTable(col.table, col.table);
|
|
2246
|
+
for (const col of cols) this._selectColumn(col);
|
|
2247
|
+
}
|
|
2248
|
+
/** Add one column to the select list. An alias reads the column it wraps, then names the entry. */
|
|
2249
|
+
_selectColumn(col) {
|
|
2250
|
+
if (col instanceof Alias) {
|
|
2251
|
+
this._selectColumn(col.element);
|
|
2252
|
+
const read = this._select.pop();
|
|
2253
|
+
this._select.push(new Alias(read.element, col.name));
|
|
2254
|
+
} else if (col instanceof Attribute) {
|
|
2255
|
+
const { column, parent: node } = this._resolve(col);
|
|
2256
|
+
let ta;
|
|
2257
|
+
if (node !== void 0) {
|
|
2258
|
+
ta = this._tableAliasForTable(column.owner, node);
|
|
2259
|
+
} else {
|
|
2260
|
+
ta = this._tableAliasForTable(column.owner, column.owner);
|
|
2261
|
+
this._from.add(ta);
|
|
2262
|
+
}
|
|
2263
|
+
this._select.push(new Alias(new TableAliasColumn(column, ta), col.displayName()));
|
|
2264
|
+
} else if (col instanceof WindowFunctionOperation) {
|
|
2265
|
+
const rewritten = this._rewriteOperation(col);
|
|
2266
|
+
let alias;
|
|
2267
|
+
if (col.displayName) {
|
|
2268
|
+
alias = col.displayName;
|
|
2269
|
+
} else if (["ROW_NUMBER" /* ROW_NUMBER */, "RANK" /* RANK */, "DENSE_RANK" /* DENSE_RANK */].includes(col.func)) {
|
|
2270
|
+
alias = col.func.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
2271
|
+
} else if (col.element) {
|
|
2272
|
+
alias = col.func + " " + findColumn(col).column.name;
|
|
2273
|
+
} else {
|
|
2274
|
+
alias = col.func;
|
|
2275
|
+
}
|
|
2276
|
+
this._select.push(new Alias(rewritten, alias));
|
|
2277
|
+
} else if (col instanceof AggregateOperation && !(col.element instanceof ColumnWithJoin)) {
|
|
2278
|
+
this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? "Expression"));
|
|
2279
|
+
} else if (col instanceof AggregateOperation) {
|
|
2280
|
+
const colNested = this._resolve(findColumn(col));
|
|
2281
|
+
const node = colNested.parent;
|
|
2282
|
+
let ta;
|
|
2283
|
+
if (node !== void 0) {
|
|
2284
|
+
ta = this._tableAliasForTable(colNested.column.owner, node);
|
|
2285
|
+
} else {
|
|
2286
|
+
ta = this._tableAliasForTable(colNested.column.owner, colNested.column.owner);
|
|
1161
2287
|
this._from.add(ta);
|
|
1162
|
-
this._select.push(new Alias(col, "Count"));
|
|
1163
2288
|
}
|
|
2289
|
+
const alias = col.displayName ?? col.operator + " " + findColumn(col).column.name;
|
|
2290
|
+
const rewrittenAgg = new AggregateOperation(
|
|
2291
|
+
new TableAliasColumn(colNested.column, ta),
|
|
2292
|
+
col.operator,
|
|
2293
|
+
void 0,
|
|
2294
|
+
col.window ? this._rewriteWindowSpec(col.window) : void 0,
|
|
2295
|
+
col.separator,
|
|
2296
|
+
col.orderBy.map((s) => new SortOperation(this._rewriteOperation(s.column), s.direction))
|
|
2297
|
+
);
|
|
2298
|
+
this._select.push(new Alias(rewrittenAgg, alias));
|
|
2299
|
+
} else if (col instanceof ScalarFunctionOperation) {
|
|
2300
|
+
this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? col.func + " " + findColumn(col).column.name));
|
|
2301
|
+
} else if (col instanceof DateExtractOperation || col instanceof DateArithmeticOperation || col instanceof DateDiffOperation) {
|
|
2302
|
+
const colNested = this._resolve(findColumn(col));
|
|
2303
|
+
const node = colNested.parent;
|
|
2304
|
+
let ta;
|
|
2305
|
+
if (node !== void 0) {
|
|
2306
|
+
ta = this._tableAliasForTable(colNested.column.owner, node);
|
|
2307
|
+
} else {
|
|
2308
|
+
ta = this._tableAliasForTable(colNested.column.owner, colNested.column.owner);
|
|
2309
|
+
this._from.add(ta);
|
|
2310
|
+
}
|
|
2311
|
+
const alias = col.displayName ?? findColumn(col).column.name;
|
|
2312
|
+
let aliasedOp;
|
|
2313
|
+
if (col instanceof DateExtractOperation) {
|
|
2314
|
+
aliasedOp = new DateExtractOperation(new TableAliasColumn(colNested.column, ta), col.part);
|
|
2315
|
+
} else if (col instanceof DateArithmeticOperation) {
|
|
2316
|
+
aliasedOp = new DateArithmeticOperation(new TableAliasColumn(colNested.column, ta), col.n, col.unit, col.isAdd);
|
|
2317
|
+
} else {
|
|
2318
|
+
aliasedOp = new DateDiffOperation(new TableAliasColumn(colNested.column, ta), col.other, col.unit);
|
|
2319
|
+
}
|
|
2320
|
+
this._select.push(new Alias(aliasedOp, alias));
|
|
2321
|
+
} else if (col instanceof CaseOperation) {
|
|
2322
|
+
this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? "Expression"));
|
|
2323
|
+
} else if (col instanceof ConcatOperation) {
|
|
2324
|
+
this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? "Expression"));
|
|
2325
|
+
} else if (col instanceof ArithmeticOperation) {
|
|
2326
|
+
this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? "Expression"));
|
|
2327
|
+
} else if (col instanceof DateTruncOperation) {
|
|
2328
|
+
this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? findColumn(col).column.name));
|
|
2329
|
+
} else if (isCondition(col)) {
|
|
2330
|
+
this._select.push(new Alias(new RenderedSql(this.buildFilter(col)), "Expression"));
|
|
2331
|
+
} else if (col instanceof ConstantOperation) {
|
|
2332
|
+
this._select.push(new Alias(col, "Constant"));
|
|
2333
|
+
} else if (col instanceof CountAllOperation) {
|
|
2334
|
+
if (col.table !== "") this._from.add(this._tableAliasForTable(col.table, col.table));
|
|
2335
|
+
this._select.push(new Alias(col, "Count"));
|
|
1164
2336
|
}
|
|
1165
2337
|
}
|
|
1166
2338
|
_addJoin(node) {
|
|
@@ -1174,7 +2346,9 @@ var SQLQueryGenerator = class {
|
|
|
1174
2346
|
const sc = new TableAliasColumn(left, srcTa);
|
|
1175
2347
|
const right = join.right;
|
|
1176
2348
|
const tc = new TableAliasColumn(right, this._tableAliasForTable(right.owner, node));
|
|
1177
|
-
this.
|
|
2349
|
+
const queryFilter = this._joinFilters.get(node);
|
|
2350
|
+
const filterOp = join.filter !== void 0 && queryFilter !== void 0 ? new LogicalOperation(join.filter, "AND" /* AND */, queryFilter) : join.filter ?? queryFilter;
|
|
2351
|
+
this._join.push(new Join(sc, tc, filterOp));
|
|
1178
2352
|
}
|
|
1179
2353
|
buildFilter(op) {
|
|
1180
2354
|
if (op instanceof NoOperation) return "";
|
|
@@ -1186,29 +2360,53 @@ var SQLQueryGenerator = class {
|
|
|
1186
2360
|
const col = op.node.join.right;
|
|
1187
2361
|
return this.buildFilter(new ColumnWithJoin(col, op.node)) + " IS NULL";
|
|
1188
2362
|
}
|
|
2363
|
+
if (op instanceof InOperation) {
|
|
2364
|
+
return this.buildFilter(op.element) + " IN (" + op.values.map((value) => constantValueString(value, this._dialect)).join(", ") + ")";
|
|
2365
|
+
}
|
|
2366
|
+
if (op instanceof NotInOperation) {
|
|
2367
|
+
const column = this.buildFilter(op.element);
|
|
2368
|
+
const sql = column + " NOT IN (" + op.values.map((value) => constantValueString(value, this._dialect)).join(", ") + ")";
|
|
2369
|
+
if (op.element instanceof ColumnWithJoin && this._resolve(op.element).column.nullable) {
|
|
2370
|
+
return "(" + sql + " OR " + column + " IS NULL)";
|
|
2371
|
+
}
|
|
2372
|
+
return sql;
|
|
2373
|
+
}
|
|
1189
2374
|
if (op instanceof IsNotNullOperation) return this.buildFilter(op.element) + " IS NOT NULL";
|
|
1190
2375
|
if (op instanceof IsNullOperation) return this.buildFilter(op.element) + " IS NULL";
|
|
1191
2376
|
if (op instanceof LogicalOperation) {
|
|
1192
2377
|
let left = this.buildFilter(op.left);
|
|
1193
2378
|
let right = this.buildFilter(op.right);
|
|
1194
|
-
if (op.left
|
|
1195
|
-
if (op.right
|
|
2379
|
+
if (needsParentheses(op, op.left)) left = "(" + left + ")";
|
|
2380
|
+
if (needsParentheses(op, op.right)) right = "(" + right + ")";
|
|
1196
2381
|
return left + LOGICAL_OPERATOR_STR[op.operator] + right;
|
|
1197
2382
|
}
|
|
1198
2383
|
if (op instanceof ComparisonOperation) {
|
|
1199
|
-
|
|
2384
|
+
let sql = this.buildFilter(op.left) + COMPARISON_OPERATOR_STR[op.operator] + this.buildFilter(op.right);
|
|
2385
|
+
if ((op.operator === "LIKE" /* LIKE */ || op.operator === "NOT_LIKE" /* NOT_LIKE */) && op.right instanceof StringConstantOperation && (op.right.value.includes(LIKE_ESCAPE) || op.right.value.includes("\\"))) {
|
|
2386
|
+
sql += " ESCAPE '" + LIKE_ESCAPE + "'";
|
|
2387
|
+
}
|
|
2388
|
+
if (this._guardOptional && GUARDED_COMPARISONS.has(op.operator) && op.left instanceof ColumnWithJoin && this._resolveOptional(op.left)) {
|
|
2389
|
+
sql = "(" + this.buildFilter(op.left) + " IS NOT NULL AND " + sql + ")";
|
|
2390
|
+
}
|
|
2391
|
+
return sql;
|
|
2392
|
+
}
|
|
2393
|
+
if (op instanceof ConstantOperation) return constantValueString(op, this._dialect);
|
|
2394
|
+
if (op instanceof ScalarFunctionOperation || op instanceof ArithmeticOperation || op instanceof ConcatOperation || op instanceof DateTruncOperation || op instanceof AggregateOperation || op instanceof CountAllOperation) {
|
|
2395
|
+
const required = /* @__PURE__ */ new Map();
|
|
2396
|
+
this._collectRequiredJoins(op, required);
|
|
2397
|
+
for (const node of required.values()) this._addJoin(node);
|
|
2398
|
+
return sqlOperationToString(this._rewriteOperation(op), this._dialect);
|
|
1200
2399
|
}
|
|
1201
|
-
if (op instanceof ConstantOperation) return constantValueString(op);
|
|
1202
2400
|
if (op instanceof ColumnWithJoin) {
|
|
1203
|
-
const node = op
|
|
2401
|
+
const { column, parent: node } = this._resolve(op);
|
|
1204
2402
|
let ta;
|
|
1205
2403
|
if (node !== void 0) {
|
|
1206
|
-
ta = this._tableAliasForTable(
|
|
2404
|
+
ta = this._tableAliasForTable(column.owner, node);
|
|
1207
2405
|
this._addJoin(node);
|
|
1208
2406
|
} else {
|
|
1209
|
-
ta = this._tableAliasForTable(
|
|
2407
|
+
ta = this._tableAliasForTable(column.owner, column.owner);
|
|
1210
2408
|
}
|
|
1211
|
-
return ta.alias + "." +
|
|
2409
|
+
return ta.alias + "." + column.name;
|
|
1212
2410
|
}
|
|
1213
2411
|
if (op instanceof Column) {
|
|
1214
2412
|
const ta = this._tableAliasForTable(op.owner, op.owner);
|
|
@@ -1226,9 +2424,9 @@ var SQLQueryGenerator = class {
|
|
|
1226
2424
|
}
|
|
1227
2425
|
buildQueryString() {
|
|
1228
2426
|
const joins = this._join.map(
|
|
1229
|
-
(j) => " LEFT OUTER JOIN " + j.target.tableAlias.table + " AS " + j.target.tableAlias.alias + " ON " + j.
|
|
2427
|
+
(j) => " LEFT OUTER JOIN " + j.target.tableAlias.table + " AS " + j.target.tableAlias.alias + " ON (" + j.condition() + (j.filterOp ? " AND " + this.buildFilter(j.filterOp) : "") + ")"
|
|
1230
2428
|
);
|
|
1231
|
-
return "SELECT " + this._select.map((ca) => sqlOperationToString(ca)).join(",") + " FROM " + Array.from(this._from).map((ta) => ta.table + " AS " + ta.alias).join(",") + joins.join("") + this._buildWhere() + this._buildGroupBy() + this._buildOrderBy() + this._buildLimit();
|
|
2429
|
+
return (this._distinct ? "SELECT DISTINCT " : "SELECT ") + this._select.map((ca) => sqlOperationToString(ca, this._dialect)).join(",") + " FROM " + Array.from(this._from).map((ta) => ta.table + " AS " + ta.alias).join(",") + joins.join("") + this._buildWhere() + this._buildGroupBy() + this._buildHaving() + this._buildOrderBy() + this._buildLimit() + this._buildOffset();
|
|
1232
2430
|
}
|
|
1233
2431
|
_buildWhere() {
|
|
1234
2432
|
return this._where.length > 0 ? " WHERE " + this._where : "";
|
|
@@ -1236,24 +2434,39 @@ var SQLQueryGenerator = class {
|
|
|
1236
2434
|
_buildGroupBy() {
|
|
1237
2435
|
return this._groupByParts.length > 0 ? " GROUP BY " + this._groupByParts.join(", ") : "";
|
|
1238
2436
|
}
|
|
2437
|
+
_buildHaving() {
|
|
2438
|
+
return this._having.length > 0 ? " HAVING " + this._having : "";
|
|
2439
|
+
}
|
|
1239
2440
|
_buildOrderBy() {
|
|
1240
2441
|
return this._orderByParts.length > 0 ? " ORDER BY " + this._orderByParts.join(", ") : "";
|
|
1241
2442
|
}
|
|
2443
|
+
_buildOffset() {
|
|
2444
|
+
return this._offset !== void 0 ? " OFFSET " + this._offset : "";
|
|
2445
|
+
}
|
|
1242
2446
|
_buildLimit() {
|
|
1243
2447
|
return this._limit !== void 0 ? " LIMIT " + this._limit : "";
|
|
1244
2448
|
}
|
|
1245
2449
|
};
|
|
1246
|
-
function selectSqlToString(selectOperation) {
|
|
1247
|
-
const qg = new SQLQueryGenerator();
|
|
2450
|
+
function selectSqlToString(selectOperation, dialect = "postgres") {
|
|
2451
|
+
const qg = new SQLQueryGenerator(dialectOf(dialect));
|
|
1248
2452
|
qg.generate(selectOperation);
|
|
1249
2453
|
return qg.buildQueryString();
|
|
1250
2454
|
}
|
|
1251
|
-
function toSql(businessDate, processingDatetime, columns, table, op, orderBy = [], groupBy = [], limit) {
|
|
1252
|
-
const selectOp = buildQueryOperation(businessDate, processingDatetime, columns, table, op, orderBy, groupBy, limit);
|
|
1253
|
-
return selectSqlToString(selectOp);
|
|
2455
|
+
function toSql(businessDate, processingDatetime, columns, table, op, orderBy = [], groupBy = [], limit, businessDateTo = null, distinct = false, offset, having, dialect = "postgres") {
|
|
2456
|
+
const selectOp = buildQueryOperation(businessDate, processingDatetime, columns, table, op, orderBy, groupBy, limit, businessDateTo, distinct, offset, having);
|
|
2457
|
+
return selectSqlToString(selectOp, dialect);
|
|
1254
2458
|
}
|
|
1255
2459
|
|
|
1256
2460
|
// src/datafinder/runner.ts
|
|
2461
|
+
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
2462
|
+
var QueryTimeoutError = class extends Error {
|
|
2463
|
+
constructor(timeoutMs) {
|
|
2464
|
+
super(`Query exceeded ${timeoutMs}ms timeout`);
|
|
2465
|
+
this.timeoutMs = timeoutMs;
|
|
2466
|
+
this.name = "QueryTimeoutError";
|
|
2467
|
+
}
|
|
2468
|
+
timeoutMs;
|
|
2469
|
+
};
|
|
1257
2470
|
var _runner = null;
|
|
1258
2471
|
function registerRunner(runner) {
|
|
1259
2472
|
_runner = runner;
|
|
@@ -1265,27 +2478,50 @@ function getRunner() {
|
|
|
1265
2478
|
if (!_runner) throw new Error("No query runner registered. Call registerRunner() first.");
|
|
1266
2479
|
return _runner;
|
|
1267
2480
|
}
|
|
2481
|
+
var expressionIds = /* @__PURE__ */ new WeakMap();
|
|
2482
|
+
var nextExpressionId = 1;
|
|
2483
|
+
function sortTarget(sort) {
|
|
2484
|
+
const column = sort.column;
|
|
2485
|
+
if (!(column instanceof ColumnWithJoin)) {
|
|
2486
|
+
if (!expressionIds.has(column)) expressionIds.set(column, nextExpressionId++);
|
|
2487
|
+
return JSON.stringify(["expression", expressionIds.get(column)]);
|
|
2488
|
+
}
|
|
2489
|
+
const joins = [];
|
|
2490
|
+
for (let node = column.parent; node !== void 0; node = node.parent) joins.push(node.join.name);
|
|
2491
|
+
return JSON.stringify([column.column.owner, column.column.name, joins]);
|
|
2492
|
+
}
|
|
1268
2493
|
var FinderResult = class {
|
|
1269
|
-
constructor(_businessDate, _processingDatetime, _columns, _table, _op) {
|
|
2494
|
+
constructor(_businessDate, _processingDatetime, _columns, _table, _op, _businessDateTo = null) {
|
|
1270
2495
|
this._businessDate = _businessDate;
|
|
1271
2496
|
this._processingDatetime = _processingDatetime;
|
|
1272
2497
|
this._columns = _columns;
|
|
1273
2498
|
this._table = _table;
|
|
1274
2499
|
this._op = _op;
|
|
2500
|
+
this._businessDateTo = _businessDateTo;
|
|
1275
2501
|
}
|
|
1276
2502
|
_businessDate;
|
|
1277
2503
|
_processingDatetime;
|
|
1278
2504
|
_columns;
|
|
1279
2505
|
_table;
|
|
1280
2506
|
_op;
|
|
2507
|
+
_businessDateTo;
|
|
1281
2508
|
_orderBy = [];
|
|
1282
2509
|
_groupBy = [];
|
|
1283
2510
|
_limit;
|
|
1284
|
-
|
|
1285
|
-
|
|
2511
|
+
_distinct = false;
|
|
2512
|
+
_offset;
|
|
2513
|
+
_having;
|
|
2514
|
+
_timeoutMs = DEFAULT_TIMEOUT_MS;
|
|
2515
|
+
/**
|
|
2516
|
+
* Order the rows. Calls accumulate: the sorts of the latest call take priority and earlier ones order the
|
|
2517
|
+
* rows it leaves tied, as in a chain of `sortBy` calls. Sorting a column again replaces its earlier direction.
|
|
2518
|
+
*/
|
|
2519
|
+
orderBy(...sorts) {
|
|
2520
|
+
const resorted = new Set(sorts.map(sortTarget));
|
|
2521
|
+
this._orderBy = [...sorts, ...this._orderBy.filter((s) => !resorted.has(sortTarget(s)))];
|
|
1286
2522
|
return this;
|
|
1287
2523
|
}
|
|
1288
|
-
|
|
2524
|
+
groupBy(...attrs) {
|
|
1289
2525
|
this._groupBy = attrs;
|
|
1290
2526
|
return this;
|
|
1291
2527
|
}
|
|
@@ -1293,7 +2529,40 @@ var FinderResult = class {
|
|
|
1293
2529
|
this._limit = n;
|
|
1294
2530
|
return this;
|
|
1295
2531
|
}
|
|
1296
|
-
|
|
2532
|
+
/** Skip the first `n` rows. Sort the rows first: without an order, which rows are first is not defined. */
|
|
2533
|
+
offset(n) {
|
|
2534
|
+
if (!Number.isInteger(n) || n < 0) throw new Error("offset cannot be negative");
|
|
2535
|
+
this._offset = n;
|
|
2536
|
+
return this;
|
|
2537
|
+
}
|
|
2538
|
+
/** Rows `start` up to but not including `stop`, counting from 0: `offset(start).limit(stop - start)`. */
|
|
2539
|
+
slice(start, stop) {
|
|
2540
|
+
if (!Number.isInteger(start) || !Number.isInteger(stop) || start < 0 || stop < start) {
|
|
2541
|
+
throw new Error("slice needs 0 <= start <= stop");
|
|
2542
|
+
}
|
|
2543
|
+
return this.offset(start).limit(stop - start);
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* Keep the groups for which every condition holds: `HAVING`. A condition tests an aggregate or a grouping column:
|
|
2547
|
+
* `f.findAll(null, null, [f.category(), countAll()]).groupBy(f.category()).having(countAll().gt(1))`.
|
|
2548
|
+
* Calls accumulate, as `and` does.
|
|
2549
|
+
*/
|
|
2550
|
+
having(...conditions) {
|
|
2551
|
+
for (const condition of conditions) this._having = this._having === void 0 ? condition : this._having.and(condition);
|
|
2552
|
+
return this;
|
|
2553
|
+
}
|
|
2554
|
+
/** Return each distinct row once: `SELECT DISTINCT`. A sort on a distinct query has to use a selected column. */
|
|
2555
|
+
distinct() {
|
|
2556
|
+
this._distinct = true;
|
|
2557
|
+
return this;
|
|
2558
|
+
}
|
|
2559
|
+
/** Abort the query and throw QueryTimeoutError if it runs longer than `milliseconds` (default 60000). */
|
|
2560
|
+
timeout(milliseconds) {
|
|
2561
|
+
this._timeoutMs = milliseconds;
|
|
2562
|
+
return this;
|
|
2563
|
+
}
|
|
2564
|
+
/** The query as SQL, in Postgres unless a dialect is given: `toSql('databricks')`. Nothing is run. */
|
|
2565
|
+
toSql(dialect = "postgres") {
|
|
1297
2566
|
return toSql(
|
|
1298
2567
|
this._businessDate,
|
|
1299
2568
|
this._processingDatetime,
|
|
@@ -1302,7 +2571,12 @@ var FinderResult = class {
|
|
|
1302
2571
|
this._op,
|
|
1303
2572
|
this._orderBy,
|
|
1304
2573
|
this._groupBy,
|
|
1305
|
-
this._limit
|
|
2574
|
+
this._limit,
|
|
2575
|
+
this._businessDateTo,
|
|
2576
|
+
this._distinct,
|
|
2577
|
+
this._offset,
|
|
2578
|
+
this._having,
|
|
2579
|
+
dialect
|
|
1306
2580
|
);
|
|
1307
2581
|
}
|
|
1308
2582
|
async toRows() {
|
|
@@ -1314,14 +2588,25 @@ var FinderResult = class {
|
|
|
1314
2588
|
this._op,
|
|
1315
2589
|
this._orderBy,
|
|
1316
2590
|
this._groupBy,
|
|
1317
|
-
this._limit
|
|
2591
|
+
this._limit,
|
|
2592
|
+
this._timeoutMs,
|
|
2593
|
+
this._businessDateTo,
|
|
2594
|
+
this._distinct,
|
|
2595
|
+
this._offset,
|
|
2596
|
+
this._having
|
|
1318
2597
|
);
|
|
1319
2598
|
}
|
|
1320
2599
|
};
|
|
2600
|
+
function convertProcessingDate(value) {
|
|
2601
|
+
if (typeof value === "string" && DATE_ONLY_PATTERN.test(value)) return new DateOnly(value + "T00:00:00Z");
|
|
2602
|
+
return convertDate(value);
|
|
2603
|
+
}
|
|
1321
2604
|
function convertDate(value) {
|
|
1322
2605
|
if (value === null) return null;
|
|
1323
2606
|
if (value instanceof Date) return value;
|
|
1324
|
-
|
|
2607
|
+
let normalized = value;
|
|
2608
|
+
if (DATE_ONLY_PATTERN.test(value)) normalized = value + "T00:00:00Z";
|
|
2609
|
+
else if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(value)) normalized = value.replace(" ", "T") + "Z";
|
|
1325
2610
|
const d = new Date(normalized);
|
|
1326
2611
|
if (isNaN(d.getTime())) throw new Error(`Cannot parse date: ${value}`);
|
|
1327
2612
|
return d;
|
|
@@ -1329,17 +2614,33 @@ function convertDate(value) {
|
|
|
1329
2614
|
function convertInputsAndSelect(businessDate, processingDatetime, columns, table, op = new NoOperation()) {
|
|
1330
2615
|
return new FinderResult(
|
|
1331
2616
|
convertDate(businessDate),
|
|
1332
|
-
|
|
2617
|
+
convertProcessingDate(processingDatetime),
|
|
1333
2618
|
columns,
|
|
1334
2619
|
table,
|
|
1335
2620
|
op
|
|
1336
2621
|
);
|
|
1337
2622
|
}
|
|
2623
|
+
function convertInputsAndSelectForDateRange(businessDateFrom, businessDateTo, processingDatetime, columns, table, op = new NoOperation()) {
|
|
2624
|
+
if (businessDateFrom == null) throw new Error("businessDateFrom is required for findForDateRange");
|
|
2625
|
+
if (businessDateTo == null) throw new Error("businessDateTo is required for findForDateRange");
|
|
2626
|
+
if (processingDatetime == null) throw new Error("processingValidAt is required for findForDateRange");
|
|
2627
|
+
return new FinderResult(
|
|
2628
|
+
convertDate(businessDateFrom),
|
|
2629
|
+
convertProcessingDate(processingDatetime),
|
|
2630
|
+
columns,
|
|
2631
|
+
table,
|
|
2632
|
+
op,
|
|
2633
|
+
convertDate(businessDateTo)
|
|
2634
|
+
);
|
|
2635
|
+
}
|
|
1338
2636
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1339
2637
|
0 && (module.exports = {
|
|
2638
|
+
DEFAULT_TIMEOUT_MS,
|
|
1340
2639
|
FinderResult,
|
|
2640
|
+
QueryTimeoutError,
|
|
1341
2641
|
clearRunner,
|
|
1342
2642
|
convertInputsAndSelect,
|
|
2643
|
+
convertInputsAndSelectForDateRange,
|
|
1343
2644
|
getRunner,
|
|
1344
2645
|
registerRunner
|
|
1345
2646
|
});
|