@platforma-sdk/workflow-tengo 5.3.3 → 5.3.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/dist/index.cjs +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/tengo/lib/exec.lib.tengo +4 -0
- package/dist/tengo/lib/exec.monetization_internal.lib.tengo +8 -0
- package/dist/tengo/lib/pframes.spec.lib.tengo +6 -0
- package/dist/tengo/lib/pframes.util.lib.tengo +404 -1
- package/dist/tengo/lib/pframes.xsv.lib.tengo +117 -65
- package/dist/tengo/lib/pt.expression.lib.tengo +828 -268
- package/dist/tengo/lib/pt.lib.tengo +567 -216
- package/dist/tengo/lib/pt.util.lib.tengo +231 -15
- package/dist/tengo/lib/slices.lib.tengo +20 -1
- package/dist/tengo/lib/smart.lib.tengo +0 -1
- package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
- package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
- package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
- package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
- package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
- package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
- package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
- package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
- package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
- package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
- package/dist/tengo/tpl/pt.import-dir.plj.gz +0 -0
- package/dist/tengo/tpl/pt.workflow-run.plj.gz +0 -0
- package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
- package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
- package/package.json +4 -4
- package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
|
@@ -3,11 +3,15 @@ maps := import("@platforma-sdk/workflow-tengo:maps")
|
|
|
3
3
|
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
4
4
|
validation := import("@platforma-sdk/workflow-tengo:validation")
|
|
5
5
|
fmt := import("fmt")
|
|
6
|
+
objects := import("@platforma-sdk/workflow-tengo:objects")
|
|
7
|
+
oop := import("@platforma-sdk/workflow-tengo:oop")
|
|
8
|
+
pframesSpec := import("@platforma-sdk/workflow-tengo:pframes.spec")
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
_newExpression := undefined
|
|
10
13
|
_newWindowExpression := undefined
|
|
14
|
+
axis := undefined
|
|
11
15
|
col := undefined
|
|
12
16
|
lit := undefined
|
|
13
17
|
allHorizontal := undefined
|
|
@@ -37,16 +41,16 @@ _validateOptions := func(options, schema, functionName) {
|
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
_isExpression := func(item) {
|
|
40
|
-
return ll.isMap(item) && ll.methodExists(item, "
|
|
44
|
+
return ll.isMap(item) && ll.methodExists(item, "_getExpression")
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
|
|
44
48
|
_isAggregation := func(item) {
|
|
45
|
-
return ll.isMap(item) && ll.methodExists(item, "
|
|
49
|
+
return ll.isMap(item) && ll.methodExists(item, "_getAggregation")
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
|
|
49
|
-
_mapToExpressionStructList := func(itemsList, stringInterpretation) {
|
|
53
|
+
_mapToExpressionStructList := func(itemsList, stringInterpretation, ctx) {
|
|
50
54
|
if !is_array(itemsList) {
|
|
51
55
|
itemsList = [itemsList] // Allow single item to be passed
|
|
52
56
|
}
|
|
@@ -57,12 +61,12 @@ _mapToExpressionStructList := func(itemsList, stringInterpretation) {
|
|
|
57
61
|
return slices.map(itemsList, func(item) {
|
|
58
62
|
if is_string(item) {
|
|
59
63
|
if stringInterpretation == "col" {
|
|
60
|
-
return col(item).
|
|
64
|
+
return col(item)._getExpression(ctx)
|
|
61
65
|
} else { // Must be "lit" due to the check above
|
|
62
|
-
return lit(item).
|
|
66
|
+
return lit(item)._getExpression(ctx)
|
|
63
67
|
}
|
|
64
68
|
} else if _isExpression(item) {
|
|
65
|
-
return item.
|
|
69
|
+
return item._getExpression(ctx)
|
|
66
70
|
} else {
|
|
67
71
|
ll.panic("Invalid item type in list: %T. Must be a string (interpreted as '%s') or an expression object.", item, stringInterpretation)
|
|
68
72
|
return undefined // Unreachable
|
|
@@ -70,16 +74,16 @@ _mapToExpressionStructList := func(itemsList, stringInterpretation) {
|
|
|
70
74
|
})
|
|
71
75
|
}
|
|
72
76
|
|
|
73
|
-
_mapToSingleExpressionStruct := func(item, stringInterpretation) {
|
|
77
|
+
_mapToSingleExpressionStruct := func(item, stringInterpretation, ctx) {
|
|
74
78
|
if _isExpression(item) {
|
|
75
|
-
return item.
|
|
79
|
+
return item._getExpression(ctx)
|
|
76
80
|
} else if is_int(item) || is_float(item) || is_bool(item) { // These are always literals
|
|
77
|
-
return lit(item).
|
|
81
|
+
return lit(item)._getExpression(ctx)
|
|
78
82
|
} else if is_string(item) {
|
|
79
83
|
if stringInterpretation == "col" {
|
|
80
|
-
return col(item).
|
|
84
|
+
return col(item)._getExpression(ctx)
|
|
81
85
|
} else if stringInterpretation == "lit" {
|
|
82
|
-
return lit(item).
|
|
86
|
+
return lit(item)._getExpression(ctx)
|
|
83
87
|
} else { // stringInterpretation is undefined or an invalid value
|
|
84
88
|
ll.panic("String item '%v' provided, but its interpretation as 'col' or 'lit' was not specified or is not applicable in this context. (stringInterpretation: '%v')", item, stringInterpretation)
|
|
85
89
|
return undefined
|
|
@@ -99,26 +103,28 @@ _mapToSingleExpressionStruct := func(item, stringInterpretation) {
|
|
|
99
103
|
_newWindowExpression = func(expression, aggregation, currentAlias) {
|
|
100
104
|
self := undefined
|
|
101
105
|
self = ll.toStrict({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
_getExpression: func(ctx) {
|
|
111
|
+
ll.assert(is_map(ctx), "ctx must be a map")
|
|
112
|
+
ll.assert(!is_undefined(expression), "Using this operation as a window expression is not allowed. Use it as a group by expression instead. %v", aggregation)
|
|
113
|
+
ll.assert(!is_undefined(currentAlias), "Alias is not defined for this window expression.")
|
|
114
|
+
|
|
115
|
+
valueExpr := expression(ctx)
|
|
116
|
+
return {type: "alias", value: valueExpr, name: currentAlias}
|
|
108
117
|
},
|
|
109
118
|
|
|
110
|
-
|
|
119
|
+
_getAggregation: func(ctx) {
|
|
111
120
|
if aggregation == undefined {
|
|
112
121
|
ll.panic("Using this operation as a group by expression is not allowed, most probably because you applied .over() to it. %v", expression)
|
|
113
122
|
}
|
|
114
|
-
return maps.deepMerge(aggregation, {name: self.getAlias()})
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
getAlias: func() {
|
|
118
123
|
if currentAlias == undefined {
|
|
119
124
|
ll.panic("Alias is not defined for this window expression.")
|
|
120
125
|
}
|
|
121
|
-
|
|
126
|
+
aggStruct := aggregation(ctx)
|
|
127
|
+
return maps.deepMerge(aggStruct, {name: currentAlias})
|
|
122
128
|
},
|
|
123
129
|
|
|
124
130
|
|
|
@@ -128,6 +134,7 @@ _newWindowExpression = func(expression, aggregation, currentAlias) {
|
|
|
128
134
|
|
|
129
135
|
|
|
130
136
|
alias: func(newAlias) {
|
|
137
|
+
ll.assert(is_string(newAlias), "alias must be a string")
|
|
131
138
|
return _newWindowExpression(expression, aggregation, newAlias)
|
|
132
139
|
},
|
|
133
140
|
|
|
@@ -139,15 +146,20 @@ _newWindowExpression = func(expression, aggregation, currentAlias) {
|
|
|
139
146
|
over: func(partitionBy) {
|
|
140
147
|
ll.assert(is_array(partitionBy) || is_string(partitionBy) || _isExpression(partitionBy), "partitionBy must be an array of strings/expressions or a single string/expression")
|
|
141
148
|
|
|
142
|
-
if len(expression.partitionBy) > 0 {
|
|
143
|
-
ll.warn("partitionBy already set on this window expression, overriding.")
|
|
144
|
-
}
|
|
145
149
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
})
|
|
150
|
+
newExpr := func(ctx) {
|
|
151
|
+
baseExpr := expression(ctx)
|
|
149
152
|
|
|
150
|
-
|
|
153
|
+
if len(baseExpr.partitionBy) > 0 {
|
|
154
|
+
ll.warn("partitionBy already set on this window expression, overriding.")
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return maps.deepMerge(baseExpr, {
|
|
158
|
+
partitionBy: _mapToExpressionStructList(partitionBy, "col", ctx)
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return _newWindowExpression(newExpr, undefined, currentAlias)
|
|
151
163
|
}
|
|
152
164
|
})
|
|
153
165
|
return self
|
|
@@ -157,48 +169,58 @@ _newWindowExpression = func(expression, aggregation, currentAlias) {
|
|
|
157
169
|
|
|
158
170
|
|
|
159
171
|
|
|
160
|
-
|
|
161
|
-
_newExpression = func(expression, currentAlias) {
|
|
172
|
+
_newExpression = func(expression) {
|
|
162
173
|
self := undefined // forward declaration
|
|
163
174
|
|
|
164
175
|
|
|
165
176
|
binaryOp := func(opType, other) {
|
|
166
|
-
rhsExprStruct := undefined
|
|
167
|
-
if _isExpression(other) {
|
|
168
|
-
rhsExprStruct = other.getExpression()
|
|
169
|
-
} else if is_int(other) || is_float(other) || is_bool(other) || is_string(other) {
|
|
170
|
-
rhsExprStruct = lit(other).getExpression()
|
|
171
|
-
} else {
|
|
172
|
-
ll.panic(opType + " expects an expression object or a literal (number, boolean, null) as argument. Got type: %T", other)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
177
|
return _newExpression(
|
|
176
|
-
{
|
|
177
|
-
|
|
178
|
+
func(ctx) {
|
|
179
|
+
lhsExpr := self._getExpression(ctx)
|
|
180
|
+
rhsExpr := undefined
|
|
181
|
+
if _isExpression(other) {
|
|
182
|
+
rhsExpr = other._getExpression(ctx)
|
|
183
|
+
} else if is_int(other) || is_float(other) || is_bool(other) || is_string(other) {
|
|
184
|
+
rhsExpr = lit(other)._getExpression(ctx)
|
|
185
|
+
} else {
|
|
186
|
+
ll.panic(opType + " expects an expression object or a literal (number, boolean, null) as argument. Got type: %T", other)
|
|
187
|
+
}
|
|
188
|
+
return {type: opType, lhs: lhsExpr, rhs: rhsExpr}
|
|
189
|
+
}
|
|
178
190
|
)
|
|
179
191
|
}
|
|
180
192
|
|
|
181
193
|
|
|
182
194
|
unaryOp := func(opType) {
|
|
183
195
|
return _newExpression(
|
|
184
|
-
{
|
|
185
|
-
|
|
196
|
+
func(ctx) {
|
|
197
|
+
valueExpr := self._getExpression(ctx)
|
|
198
|
+
return {type: opType, value: valueExpr}
|
|
199
|
+
}
|
|
186
200
|
)
|
|
187
201
|
}
|
|
188
202
|
|
|
189
203
|
|
|
190
204
|
unaryStrOp := func(opType) {
|
|
191
205
|
return _newExpression(
|
|
192
|
-
{
|
|
193
|
-
|
|
206
|
+
func(ctx) {
|
|
207
|
+
valueExpr := self._getExpression(ctx)
|
|
208
|
+
return {type: opType, value: valueExpr}
|
|
209
|
+
}
|
|
194
210
|
)
|
|
195
211
|
}
|
|
196
212
|
|
|
197
213
|
|
|
198
214
|
aggOp := func(aggType) {
|
|
199
215
|
return _newWindowExpression(
|
|
200
|
-
{
|
|
201
|
-
|
|
216
|
+
func(ctx) {
|
|
217
|
+
valueExpr := self._getExpression(ctx)
|
|
218
|
+
return {type: "aggregate", aggregation: aggType, value: valueExpr, partitionBy: []}
|
|
219
|
+
},
|
|
220
|
+
func(ctx) {
|
|
221
|
+
valueExpr := self._getExpression(ctx)
|
|
222
|
+
return {aggregation: aggType, expression: valueExpr}
|
|
223
|
+
},
|
|
202
224
|
undefined // Alias of underlying col, window expression itself is typically aliased later
|
|
203
225
|
)
|
|
204
226
|
}
|
|
@@ -206,20 +228,19 @@ _newExpression = func(expression, currentAlias) {
|
|
|
206
228
|
aggOpBy := func(aggType, by) {
|
|
207
229
|
return _newWindowExpression(
|
|
208
230
|
undefined,
|
|
209
|
-
|
|
231
|
+
func(ctx) {
|
|
232
|
+
baseExpr := self._getExpression(ctx)
|
|
233
|
+
return {aggregation: aggType, expression: baseExpr, by: _mapToExpressionStructList(by, "col", {})}
|
|
234
|
+
},
|
|
210
235
|
undefined // Alias of underlying col, window expression itself is typically aliased later
|
|
211
236
|
)
|
|
212
237
|
}
|
|
213
238
|
|
|
214
239
|
self = ll.toStrict({
|
|
215
240
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if currentAlias == undefined {
|
|
220
|
-
ll.panic("Alias is not defined for this expression.")
|
|
221
|
-
}
|
|
222
|
-
return currentAlias
|
|
241
|
+
_getExpression: func(ctx) {
|
|
242
|
+
ll.assert(is_map(ctx), "ctx must be a map")
|
|
243
|
+
return expression(ctx)
|
|
223
244
|
},
|
|
224
245
|
|
|
225
246
|
|
|
@@ -228,7 +249,10 @@ _newExpression = func(expression, currentAlias) {
|
|
|
228
249
|
|
|
229
250
|
|
|
230
251
|
alias: func(newAlias) {
|
|
231
|
-
return _newExpression(
|
|
252
|
+
return _newExpression(func (ctx) {
|
|
253
|
+
valueExpr := self._getExpression(ctx)
|
|
254
|
+
return {type: "alias", value: valueExpr, name: newAlias}
|
|
255
|
+
})
|
|
232
256
|
},
|
|
233
257
|
|
|
234
258
|
|
|
@@ -294,10 +318,10 @@ _newExpression = func(expression, currentAlias) {
|
|
|
294
318
|
if !is_undefined(ops.strict) {
|
|
295
319
|
strictVal = ops.strict
|
|
296
320
|
}
|
|
297
|
-
return _newExpression(
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
)
|
|
321
|
+
return _newExpression(func(ctx) {
|
|
322
|
+
valueExpr := self._getExpression(ctx)
|
|
323
|
+
return {type: "cast", value: valueExpr, dtype: dtype, strict: strictVal}
|
|
324
|
+
})
|
|
301
325
|
},
|
|
302
326
|
|
|
303
327
|
|
|
@@ -382,21 +406,23 @@ _newExpression = func(expression, currentAlias) {
|
|
|
382
406
|
}, "structField")
|
|
383
407
|
|
|
384
408
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
409
|
+
return _newExpression(func(ctx) {
|
|
410
|
+
structExpr := {
|
|
411
|
+
type: "struct_field",
|
|
412
|
+
struct: self._getExpression(ctx),
|
|
413
|
+
fields: fields
|
|
414
|
+
}
|
|
390
415
|
|
|
391
416
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
417
|
+
if !is_undefined(ops.default) {
|
|
418
|
+
structExpr.default = ops.default
|
|
419
|
+
}
|
|
420
|
+
if !is_undefined(ops.dtype) {
|
|
421
|
+
structExpr.dtype = ops.dtype
|
|
422
|
+
}
|
|
398
423
|
|
|
399
|
-
|
|
424
|
+
return structExpr
|
|
425
|
+
})
|
|
400
426
|
},
|
|
401
427
|
|
|
402
428
|
|
|
@@ -420,12 +446,8 @@ _newExpression = func(expression, currentAlias) {
|
|
|
420
446
|
strSlice: func(start, ...args) {
|
|
421
447
|
ll.assert(len(args) <= 1, "strSlice expects at most one additional argument.")
|
|
422
448
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
value: expression,
|
|
426
|
-
start: _mapToSingleExpressionStruct(start, "col")
|
|
427
|
-
}
|
|
428
|
-
|
|
449
|
+
length := undefined
|
|
450
|
+
end := undefined
|
|
429
451
|
if len(args) > 0 {
|
|
430
452
|
arg := args[0]
|
|
431
453
|
if is_map(arg) {
|
|
@@ -438,17 +460,33 @@ _newExpression = func(expression, currentAlias) {
|
|
|
438
460
|
ll.panic("strSlice cannot have both 'length' and 'end' options.")
|
|
439
461
|
}
|
|
440
462
|
if !is_undefined(ops.length) {
|
|
441
|
-
|
|
463
|
+
length = ops.length
|
|
442
464
|
}
|
|
443
465
|
if !is_undefined(ops.end) {
|
|
444
|
-
|
|
466
|
+
end = ops.end
|
|
445
467
|
}
|
|
446
468
|
} else {
|
|
447
|
-
|
|
469
|
+
length = arg
|
|
448
470
|
}
|
|
449
471
|
}
|
|
450
472
|
|
|
451
|
-
return _newExpression(
|
|
473
|
+
return _newExpression(func(ctx) {
|
|
474
|
+
valueExpr := self._getExpression(ctx)
|
|
475
|
+
expr := {
|
|
476
|
+
type: "substring",
|
|
477
|
+
value: valueExpr,
|
|
478
|
+
start: _mapToSingleExpressionStruct(start, "col", ctx)
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if !is_undefined(length) {
|
|
482
|
+
expr.length = _mapToSingleExpressionStruct(length, "col", ctx)
|
|
483
|
+
}
|
|
484
|
+
if !is_undefined(end) {
|
|
485
|
+
expr.end = _mapToSingleExpressionStruct(end, "col", ctx)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return expr
|
|
489
|
+
})
|
|
452
490
|
},
|
|
453
491
|
|
|
454
492
|
|
|
@@ -476,14 +514,17 @@ _newExpression = func(expression, currentAlias) {
|
|
|
476
514
|
literalVal = ops.literal
|
|
477
515
|
}
|
|
478
516
|
|
|
479
|
-
return _newExpression({
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
517
|
+
return _newExpression(func(ctx) {
|
|
518
|
+
valueExpr := self._getExpression(ctx)
|
|
519
|
+
return {
|
|
520
|
+
type: "str_replace",
|
|
521
|
+
value: valueExpr,
|
|
522
|
+
pattern: _mapToSingleExpressionStruct(pattern, "lit", ctx),
|
|
523
|
+
replacement: _mapToSingleExpressionStruct(replacement, "lit", ctx),
|
|
524
|
+
replaceAll: replaceAllVal,
|
|
525
|
+
literal: literalVal
|
|
526
|
+
}
|
|
527
|
+
})
|
|
487
528
|
},
|
|
488
529
|
|
|
489
530
|
|
|
@@ -527,13 +568,16 @@ _newExpression = func(expression, currentAlias) {
|
|
|
527
568
|
strictVal = ops.strict
|
|
528
569
|
}
|
|
529
570
|
|
|
530
|
-
return _newExpression({
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
571
|
+
return _newExpression(func(ctx) {
|
|
572
|
+
valueExpr := self._getExpression(ctx)
|
|
573
|
+
return {
|
|
574
|
+
type: "str_contains",
|
|
575
|
+
value: valueExpr,
|
|
576
|
+
pattern: _mapToSingleExpressionStruct(pattern, "lit", ctx),
|
|
577
|
+
literal: literalVal,
|
|
578
|
+
strict: strictVal
|
|
579
|
+
}
|
|
580
|
+
})
|
|
537
581
|
},
|
|
538
582
|
|
|
539
583
|
|
|
@@ -558,12 +602,15 @@ _newExpression = func(expression, currentAlias) {
|
|
|
558
602
|
asciiCaseInsensitiveVal = ops.asciiCaseInsensitive
|
|
559
603
|
}
|
|
560
604
|
|
|
561
|
-
return _newExpression({
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
605
|
+
return _newExpression(func(ctx) {
|
|
606
|
+
valueExpr := self._getExpression(ctx)
|
|
607
|
+
return {
|
|
608
|
+
type: "str_contains_any",
|
|
609
|
+
value: valueExpr,
|
|
610
|
+
patterns: patterns,
|
|
611
|
+
asciiCaseInsensitive: asciiCaseInsensitiveVal
|
|
612
|
+
}
|
|
613
|
+
})
|
|
567
614
|
},
|
|
568
615
|
|
|
569
616
|
|
|
@@ -584,12 +631,15 @@ _newExpression = func(expression, currentAlias) {
|
|
|
584
631
|
literalVal = ops.literal
|
|
585
632
|
}
|
|
586
633
|
|
|
587
|
-
return _newExpression({
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
634
|
+
return _newExpression(func(ctx) {
|
|
635
|
+
valueExpr := self._getExpression(ctx)
|
|
636
|
+
return {
|
|
637
|
+
type: "str_count_matches",
|
|
638
|
+
value: valueExpr,
|
|
639
|
+
pattern: _mapToSingleExpressionStruct(pattern, "lit", ctx),
|
|
640
|
+
literal: literalVal
|
|
641
|
+
}
|
|
642
|
+
})
|
|
593
643
|
},
|
|
594
644
|
|
|
595
645
|
|
|
@@ -610,12 +660,15 @@ _newExpression = func(expression, currentAlias) {
|
|
|
610
660
|
groupIndexVal = ops.groupIndex
|
|
611
661
|
}
|
|
612
662
|
|
|
613
|
-
return _newExpression({
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
663
|
+
return _newExpression(func(ctx) {
|
|
664
|
+
valueExpr := self._getExpression(ctx)
|
|
665
|
+
return {
|
|
666
|
+
type: "str_extract",
|
|
667
|
+
value: valueExpr,
|
|
668
|
+
pattern: _mapToSingleExpressionStruct(pattern, "lit", ctx),
|
|
669
|
+
groupIndex: groupIndexVal
|
|
670
|
+
}
|
|
671
|
+
})
|
|
619
672
|
},
|
|
620
673
|
|
|
621
674
|
|
|
@@ -624,11 +677,14 @@ _newExpression = func(expression, currentAlias) {
|
|
|
624
677
|
|
|
625
678
|
|
|
626
679
|
strStartsWith: func(prefix) {
|
|
627
|
-
return _newExpression({
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
680
|
+
return _newExpression(func(ctx) {
|
|
681
|
+
valueExpr := self._getExpression(ctx)
|
|
682
|
+
return {
|
|
683
|
+
type: "str_starts_with",
|
|
684
|
+
value: valueExpr,
|
|
685
|
+
prefix: _mapToSingleExpressionStruct(prefix, "lit", ctx)
|
|
686
|
+
}
|
|
687
|
+
})
|
|
632
688
|
},
|
|
633
689
|
|
|
634
690
|
|
|
@@ -637,11 +693,14 @@ _newExpression = func(expression, currentAlias) {
|
|
|
637
693
|
|
|
638
694
|
|
|
639
695
|
strEndsWith: func(suffix) {
|
|
640
|
-
return _newExpression({
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
696
|
+
return _newExpression(func(ctx) {
|
|
697
|
+
valueExpr := self._getExpression(ctx)
|
|
698
|
+
return {
|
|
699
|
+
type: "str_ends_with",
|
|
700
|
+
value: valueExpr,
|
|
701
|
+
suffix: _mapToSingleExpressionStruct(suffix, "lit", ctx)
|
|
702
|
+
}
|
|
703
|
+
})
|
|
645
704
|
},
|
|
646
705
|
|
|
647
706
|
|
|
@@ -662,13 +721,17 @@ _newExpression = func(expression, currentAlias) {
|
|
|
662
721
|
returnSimilarityVal = returnSimilarity
|
|
663
722
|
}
|
|
664
723
|
|
|
665
|
-
return _newExpression({
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
724
|
+
return _newExpression(func(ctx) {
|
|
725
|
+
lhsExpr := self._getExpression(ctx)
|
|
726
|
+
rhsExpr := string2._getExpression(ctx)
|
|
727
|
+
return {
|
|
728
|
+
type: "string_distance",
|
|
729
|
+
string1: lhsExpr,
|
|
730
|
+
string2: rhsExpr,
|
|
731
|
+
metric: metric,
|
|
732
|
+
returnSimilarity: returnSimilarityVal
|
|
733
|
+
}
|
|
734
|
+
})
|
|
672
735
|
},
|
|
673
736
|
|
|
674
737
|
|
|
@@ -684,13 +747,17 @@ _newExpression = func(expression, currentAlias) {
|
|
|
684
747
|
ll.assert(is_string(metric), "metric must be a string")
|
|
685
748
|
ll.assert(is_int(bound) || is_float(bound), "bound must be a number")
|
|
686
749
|
|
|
687
|
-
return _newExpression({
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
750
|
+
return _newExpression(func(ctx) {
|
|
751
|
+
lhsExpr := self._getExpression(ctx)
|
|
752
|
+
rhsExpr := patternExpr._getExpression(ctx)
|
|
753
|
+
return {
|
|
754
|
+
type: "fuzzy_string_filter",
|
|
755
|
+
value: lhsExpr,
|
|
756
|
+
pattern: rhsExpr,
|
|
757
|
+
metric: metric,
|
|
758
|
+
bound: bound
|
|
759
|
+
}
|
|
760
|
+
})
|
|
694
761
|
},
|
|
695
762
|
|
|
696
763
|
|
|
@@ -708,16 +775,19 @@ _newExpression = func(expression, currentAlias) {
|
|
|
708
775
|
ll.assert(is_int(bits), "bits must be a number")
|
|
709
776
|
}
|
|
710
777
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
778
|
+
return _newExpression(func(ctx) {
|
|
779
|
+
valueExpr := self._getExpression(ctx)
|
|
780
|
+
hashExpr := {
|
|
781
|
+
type: "hash",
|
|
782
|
+
value: valueExpr,
|
|
783
|
+
hashType: hashType,
|
|
784
|
+
encoding: encoding
|
|
785
|
+
}
|
|
786
|
+
if bits != undefined {
|
|
787
|
+
hashExpr.bits = bits
|
|
788
|
+
}
|
|
789
|
+
return hashExpr
|
|
790
|
+
})
|
|
721
791
|
},
|
|
722
792
|
|
|
723
793
|
|
|
@@ -727,10 +797,14 @@ _newExpression = func(expression, currentAlias) {
|
|
|
727
797
|
|
|
728
798
|
|
|
729
799
|
fillNull: func(fillValueExpr) {
|
|
730
|
-
return _newExpression(
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
800
|
+
return _newExpression(func(ctx) {
|
|
801
|
+
valueExpr := self._getExpression(ctx)
|
|
802
|
+
return {
|
|
803
|
+
type: "fill_null",
|
|
804
|
+
input: valueExpr,
|
|
805
|
+
fillValue: _mapToSingleExpressionStruct(fillValueExpr, "lit", ctx)
|
|
806
|
+
}
|
|
807
|
+
})
|
|
734
808
|
},
|
|
735
809
|
|
|
736
810
|
|
|
@@ -739,10 +813,14 @@ _newExpression = func(expression, currentAlias) {
|
|
|
739
813
|
|
|
740
814
|
|
|
741
815
|
fillNaN: func(fillValueExpr) {
|
|
742
|
-
return _newExpression(
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
816
|
+
return _newExpression(func(ctx) {
|
|
817
|
+
valueExpr := self._getExpression(ctx)
|
|
818
|
+
return {
|
|
819
|
+
type: "fill_nan",
|
|
820
|
+
input: valueExpr,
|
|
821
|
+
fillValue: _mapToSingleExpressionStruct(fillValueExpr, "lit", ctx)
|
|
822
|
+
}
|
|
823
|
+
})
|
|
746
824
|
},
|
|
747
825
|
|
|
748
826
|
|
|
@@ -787,11 +865,14 @@ _newExpression = func(expression, currentAlias) {
|
|
|
787
865
|
ll.assert(is_bool(descendingArgs[0]), "descending argument for rank must be a boolean")
|
|
788
866
|
descendingVal = descendingArgs[0]
|
|
789
867
|
}
|
|
790
|
-
return _newWindowExpression({
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
868
|
+
return _newWindowExpression(func(ctx) {
|
|
869
|
+
valueExpr := self._getExpression(ctx)
|
|
870
|
+
return {
|
|
871
|
+
type: "rank",
|
|
872
|
+
orderBy: [valueExpr],
|
|
873
|
+
partitionBy: [], // To be set by .over()
|
|
874
|
+
descending: descendingVal
|
|
875
|
+
}
|
|
795
876
|
}, undefined)
|
|
796
877
|
},
|
|
797
878
|
|
|
@@ -819,7 +900,11 @@ _newExpression = func(expression, currentAlias) {
|
|
|
819
900
|
}, "cumsum")
|
|
820
901
|
actualArgs = args[0:len(args)-1]
|
|
821
902
|
if !is_undefined(ops.orderBy) {
|
|
822
|
-
|
|
903
|
+
if is_array(ops.orderBy) {
|
|
904
|
+
additionalOrderByVal = ops.orderBy
|
|
905
|
+
} else {
|
|
906
|
+
additionalOrderByVal = [ops.orderBy]
|
|
907
|
+
}
|
|
823
908
|
}
|
|
824
909
|
if !is_undefined(ops.descending) {
|
|
825
910
|
descendingVal = ops.descending
|
|
@@ -829,7 +914,11 @@ _newExpression = func(expression, currentAlias) {
|
|
|
829
914
|
|
|
830
915
|
if len(additionalOrderByVal) == 0 && len(actualArgs) > 0 {
|
|
831
916
|
if is_array(actualArgs[0]) || is_string(actualArgs[0]) || _isExpression(actualArgs[0]) {
|
|
832
|
-
|
|
917
|
+
if is_array(actualArgs[0]) {
|
|
918
|
+
additionalOrderByVal = actualArgs[0]
|
|
919
|
+
} else {
|
|
920
|
+
additionalOrderByVal = [actualArgs[0]]
|
|
921
|
+
}
|
|
833
922
|
if len(actualArgs) > 1 && is_bool(actualArgs[1]) {
|
|
834
923
|
descendingVal = actualArgs[1]
|
|
835
924
|
}
|
|
@@ -840,20 +929,107 @@ _newExpression = func(expression, currentAlias) {
|
|
|
840
929
|
}
|
|
841
930
|
}
|
|
842
931
|
|
|
843
|
-
return _newWindowExpression({
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
932
|
+
return _newWindowExpression(func(ctx) {
|
|
933
|
+
valueExpr := self._getExpression(ctx)
|
|
934
|
+
return {
|
|
935
|
+
type: "cumsum",
|
|
936
|
+
value: valueExpr,
|
|
937
|
+
additionalOrderBy: _mapToExpressionStructList(additionalOrderByVal, "col", ctx),
|
|
938
|
+
partitionBy: [],
|
|
939
|
+
descending: descendingVal
|
|
940
|
+
}
|
|
849
941
|
}, undefined, undefined)
|
|
850
942
|
},
|
|
851
943
|
|
|
852
|
-
|
|
853
|
-
|
|
854
944
|
|
|
855
945
|
toString: func() {
|
|
856
946
|
return self.cast("string")
|
|
947
|
+
},
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
inSet: func(...values) {
|
|
955
|
+
ll.assert(len(values) > 0, "inSet method requires at least one value.")
|
|
956
|
+
|
|
957
|
+
set := []
|
|
958
|
+
for v in values {
|
|
959
|
+
ll.assert(
|
|
960
|
+
is_undefined(v) || is_bool(v) || is_int(v) || is_float(v) || is_string(v),
|
|
961
|
+
"Invalid argument in inSet: Expected primitive value, got %T", v)
|
|
962
|
+
set = append(set, v)
|
|
963
|
+
}
|
|
964
|
+
uniqueSet := slices.sortUnique(set)
|
|
965
|
+
|
|
966
|
+
return _newExpression(func(ctx) {
|
|
967
|
+
valueExpr := self._getExpression(ctx)
|
|
968
|
+
return {
|
|
969
|
+
type: "in_set",
|
|
970
|
+
value: valueExpr,
|
|
971
|
+
set: uniqueSet
|
|
972
|
+
}
|
|
973
|
+
})
|
|
974
|
+
},
|
|
975
|
+
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
matchesEcmaRegex: func(ecmaRegex) {
|
|
982
|
+
ll.assert(is_string(ecmaRegex) && len(ecmaRegex) > 0, "ecma_regex must be a non-empty string.")
|
|
983
|
+
|
|
984
|
+
return _newExpression(func(ctx) {
|
|
985
|
+
valueExpr := self._getExpression(ctx)
|
|
986
|
+
return {
|
|
987
|
+
type: "matches_ecma_regex",
|
|
988
|
+
value: valueExpr,
|
|
989
|
+
ecmaRegex: ecmaRegex
|
|
990
|
+
}
|
|
991
|
+
})
|
|
992
|
+
},
|
|
993
|
+
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
containsFuzzyMatch: func(reference, maxEdits, ...args) {
|
|
1004
|
+
ll.assert(is_string(reference) && len(reference) > 0, "pattern must be a non-empty string.")
|
|
1005
|
+
ll.assert(is_int(maxEdits) && maxEdits > 0, "maxEdits must be a positive integer.")
|
|
1006
|
+
|
|
1007
|
+
wildcard := undefined
|
|
1008
|
+
substitutionsOnly := undefined
|
|
1009
|
+
if len(args) > 0 {
|
|
1010
|
+
ops := _validateOptions(args, {
|
|
1011
|
+
"__options__,closed": "",
|
|
1012
|
+
"wildcard,?": "string",
|
|
1013
|
+
"substitutionsOnly,?": "bool"
|
|
1014
|
+
}, "containsFuzzyMatch")
|
|
1015
|
+
if !is_undefined(ops.wildcard) {
|
|
1016
|
+
ll.assert(len(ops.wildcard) == 1, "wildcard must be a single character.")
|
|
1017
|
+
}
|
|
1018
|
+
wildcard = ops.wildcard
|
|
1019
|
+
substitutionsOnly = ops.substitutionsOnly
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
return _newExpression(func(ctx) {
|
|
1023
|
+
valueExpr := self._getExpression(ctx)
|
|
1024
|
+
return objects.deleteUndefined({
|
|
1025
|
+
type: "contains_fuzzy_match",
|
|
1026
|
+
value: valueExpr,
|
|
1027
|
+
reference: reference,
|
|
1028
|
+
maxEdits: maxEdits,
|
|
1029
|
+
wildcard: wildcard,
|
|
1030
|
+
substitutionsOnly: substitutionsOnly
|
|
1031
|
+
})
|
|
1032
|
+
})
|
|
857
1033
|
}
|
|
858
1034
|
})
|
|
859
1035
|
return self
|
|
@@ -868,12 +1044,71 @@ _newExpression = func(expression, currentAlias) {
|
|
|
868
1044
|
|
|
869
1045
|
|
|
870
1046
|
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
axis = func(matcher) {
|
|
1053
|
+
processedMatcher := undefined
|
|
1054
|
+
if is_string(matcher) {
|
|
1055
|
+
processedMatcher = { name: matcher, domain: {} }
|
|
1056
|
+
} else if is_map(matcher) {
|
|
1057
|
+
processedMatcher = pframesSpec.axisSpecToMatcher(matcher)
|
|
1058
|
+
} else {
|
|
1059
|
+
ll.panic("Matcher for axis must be a string (axis name) or an AxisSpec-like map (with at least 'name' and 'type' fields).")
|
|
1060
|
+
}
|
|
1061
|
+
return _newExpression(func(ctx) {
|
|
1062
|
+
ll.assert(!is_undefined(ctx.specDistiller), "specDistiller must be defined")
|
|
1063
|
+
ll.assert(is_map(ctx.distilledAxesSpecs), "distilledAxesSpecs must be a map")
|
|
1064
|
+
|
|
1065
|
+
distilledMatcher := ctx.specDistiller.distill(processedMatcher)
|
|
1066
|
+
discriminativeDomains := ctx.specDistiller.getDiscriminativeDomainsSet(distilledMatcher.name)
|
|
1067
|
+
if ((!is_undefined(distilledMatcher.domain) && len(distilledMatcher.domain) > 0) != (!is_undefined(discriminativeDomains) && len(discriminativeDomains) > 0)) ||
|
|
1068
|
+
(!is_undefined(distilledMatcher.domain) && !is_undefined(discriminativeDomains) && len(distilledMatcher.domain) != len(discriminativeDomains)) {
|
|
1069
|
+
ll.panic("Axis matcher %v is not specific enough. Expected discriminative domains %v, got %v", distilledMatcher.name, discriminativeDomains, distilledMatcher.domain)
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
axisSpec := undefined
|
|
1073
|
+
for spec in ctx.distilledAxesSpecs[distilledMatcher.name] {
|
|
1074
|
+
if !is_undefined(distilledMatcher.type) {
|
|
1075
|
+
if distilledMatcher.type != spec.type {
|
|
1076
|
+
continue
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
if !is_undefined(distilledMatcher.domain) {
|
|
1080
|
+
if is_undefined(spec.domain) || len(spec.domain) < len(distilledMatcher.domain) {
|
|
1081
|
+
continue
|
|
1082
|
+
}
|
|
1083
|
+
for domainKey, domainValue in distilledMatcher.domain {
|
|
1084
|
+
if spec.domain[domainKey] != domainValue {
|
|
1085
|
+
continue
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
axisSpec = spec
|
|
1090
|
+
break
|
|
1091
|
+
}
|
|
1092
|
+
return {
|
|
1093
|
+
type: "axis",
|
|
1094
|
+
spec: axisSpec
|
|
1095
|
+
}
|
|
1096
|
+
})
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
|
|
871
1104
|
col = func(name) {
|
|
872
1105
|
ll.assert(is_string(name), "col name must be a string")
|
|
873
|
-
return _newExpression({
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1106
|
+
return _newExpression(func(ctx) {
|
|
1107
|
+
return {
|
|
1108
|
+
type: "col",
|
|
1109
|
+
name: name
|
|
1110
|
+
}
|
|
1111
|
+
})
|
|
877
1112
|
}
|
|
878
1113
|
|
|
879
1114
|
|
|
@@ -882,10 +1117,12 @@ col = func(name) {
|
|
|
882
1117
|
|
|
883
1118
|
|
|
884
1119
|
lit = func(value) {
|
|
885
|
-
return _newExpression({
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
1120
|
+
return _newExpression(func(ctx) {
|
|
1121
|
+
return {
|
|
1122
|
+
type: "const",
|
|
1123
|
+
value: value
|
|
1124
|
+
}
|
|
1125
|
+
})
|
|
889
1126
|
}
|
|
890
1127
|
|
|
891
1128
|
|
|
@@ -908,11 +1145,13 @@ concatStr := func(expressions, ...options) {
|
|
|
908
1145
|
delimiterVal = ops.delimiter
|
|
909
1146
|
}
|
|
910
1147
|
|
|
911
|
-
return _newExpression({
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1148
|
+
return _newExpression(func(ctx) {
|
|
1149
|
+
return {
|
|
1150
|
+
type: "str_join",
|
|
1151
|
+
operands: _mapToExpressionStructList(expressions, "lit", ctx),
|
|
1152
|
+
delimiter: delimiterVal
|
|
1153
|
+
}
|
|
1154
|
+
})
|
|
916
1155
|
}
|
|
917
1156
|
|
|
918
1157
|
|
|
@@ -923,10 +1162,12 @@ concatStr := func(expressions, ...options) {
|
|
|
923
1162
|
minHorizontal := func(expressions) {
|
|
924
1163
|
ll.assert(is_array(expressions), "Argument to minHorizontal must be an array of expressions")
|
|
925
1164
|
ll.assert(len(expressions) > 0, "Expression array for minHorizontal cannot be empty")
|
|
926
|
-
return _newExpression({
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1165
|
+
return _newExpression(func(ctx) {
|
|
1166
|
+
return {
|
|
1167
|
+
type: "min",
|
|
1168
|
+
operands: _mapToExpressionStructList(expressions, "col", ctx)
|
|
1169
|
+
}
|
|
1170
|
+
})
|
|
930
1171
|
}
|
|
931
1172
|
|
|
932
1173
|
|
|
@@ -937,10 +1178,12 @@ minHorizontal := func(expressions) {
|
|
|
937
1178
|
maxHorizontal := func(expressions) {
|
|
938
1179
|
ll.assert(is_array(expressions), "Argument to maxHorizontal must be an array of expressions")
|
|
939
1180
|
ll.assert(len(expressions) > 0, "Expression array for maxHorizontal cannot be empty")
|
|
940
|
-
return _newExpression({
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1181
|
+
return _newExpression(func(ctx) {
|
|
1182
|
+
return {
|
|
1183
|
+
type: "max",
|
|
1184
|
+
operands: _mapToExpressionStructList(expressions, "col", ctx)
|
|
1185
|
+
}
|
|
1186
|
+
})
|
|
944
1187
|
}
|
|
945
1188
|
|
|
946
1189
|
|
|
@@ -949,30 +1192,32 @@ maxHorizontal := func(expressions) {
|
|
|
949
1192
|
|
|
950
1193
|
|
|
951
1194
|
allHorizontal = func(...args){
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1195
|
+
return _newExpression(func(ctx) {
|
|
1196
|
+
processedOperands := []
|
|
1197
|
+
for arg in args {
|
|
1198
|
+
exprStruct := undefined
|
|
1199
|
+
if _isExpression(arg) {
|
|
1200
|
+
exprStruct = arg._getExpression(ctx)
|
|
1201
|
+
} else if is_string(arg) {
|
|
1202
|
+
exprStruct = col(arg)._getExpression(ctx)
|
|
1203
|
+
} else {
|
|
1204
|
+
ll.panic("Invalid argument type for allHorizontal: %T. Must be an expression object or string.", arg)
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
if exprStruct.type == "and" && is_array(exprStruct.operands) {
|
|
1208
|
+
processedOperands = append(processedOperands, exprStruct.operands...)
|
|
1209
|
+
} else {
|
|
1210
|
+
processedOperands = append(processedOperands, exprStruct)
|
|
1211
|
+
}
|
|
961
1212
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1213
|
+
if len(processedOperands) == 0 {
|
|
1214
|
+
ll.panic("allHorizontal requires at least one expression.")
|
|
1215
|
+
}
|
|
1216
|
+
return {
|
|
1217
|
+
type: "and",
|
|
1218
|
+
operands: processedOperands
|
|
967
1219
|
}
|
|
968
|
-
}
|
|
969
|
-
if len(processedOperands) == 0 {
|
|
970
|
-
ll.panic("allHorizontal requires at least one expression.")
|
|
971
|
-
}
|
|
972
|
-
return _newExpression({
|
|
973
|
-
type: "and",
|
|
974
|
-
operands: processedOperands
|
|
975
|
-
}, undefined)
|
|
1220
|
+
})
|
|
976
1221
|
}
|
|
977
1222
|
|
|
978
1223
|
|
|
@@ -981,30 +1226,32 @@ allHorizontal = func(...args){
|
|
|
981
1226
|
|
|
982
1227
|
|
|
983
1228
|
anyHorizontal = func(...args){
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1229
|
+
return _newExpression(func(ctx) {
|
|
1230
|
+
processedOperands := []
|
|
1231
|
+
for arg in args {
|
|
1232
|
+
exprStruct := undefined
|
|
1233
|
+
if _isExpression(arg) {
|
|
1234
|
+
exprStruct = arg._getExpression(ctx)
|
|
1235
|
+
} else if is_string(arg) {
|
|
1236
|
+
exprStruct = col(arg)._getExpression(ctx)
|
|
1237
|
+
} else {
|
|
1238
|
+
ll.panic("Invalid argument type for anyHorizontal: %T. Must be an expression object or string.", arg)
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
if exprStruct.type == "or" && is_array(exprStruct.operands) {
|
|
1242
|
+
processedOperands = append(processedOperands, exprStruct.operands...)
|
|
1243
|
+
} else {
|
|
1244
|
+
processedOperands = append(processedOperands, exprStruct)
|
|
1245
|
+
}
|
|
993
1246
|
}
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
processedOperands = append(processedOperands, exprStruct.operands...)
|
|
997
|
-
} else {
|
|
998
|
-
processedOperands = append(processedOperands, exprStruct)
|
|
1247
|
+
if len(processedOperands) == 0 {
|
|
1248
|
+
ll.panic("anyHorizontal requires at least one expression.")
|
|
999
1249
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
type: "or",
|
|
1006
|
-
operands: processedOperands
|
|
1007
|
-
}, undefined)
|
|
1250
|
+
return {
|
|
1251
|
+
type: "or",
|
|
1252
|
+
operands: processedOperands
|
|
1253
|
+
}
|
|
1254
|
+
})
|
|
1008
1255
|
}
|
|
1009
1256
|
|
|
1010
1257
|
|
|
@@ -1049,8 +1296,6 @@ rank = func(orderByExpressions, ...options) {
|
|
|
1049
1296
|
descendingVal := false
|
|
1050
1297
|
|
|
1051
1298
|
ll.assert(orderByExpressions != undefined, "rank() requires orderByExpressions (single expression/string or array of them).")
|
|
1052
|
-
orderByVal = _mapToExpressionStructList(orderByExpressions, "col")
|
|
1053
|
-
ll.assert(len(orderByVal) > 0, "rank() 'orderBy' list cannot be empty after processing arguments.")
|
|
1054
1299
|
|
|
1055
1300
|
ops := _validateOptions(options, {
|
|
1056
1301
|
"__options__,closed": "",
|
|
@@ -1060,11 +1305,15 @@ rank = func(orderByExpressions, ...options) {
|
|
|
1060
1305
|
descendingVal = ops.descending
|
|
1061
1306
|
}
|
|
1062
1307
|
|
|
1063
|
-
return _newWindowExpression({
|
|
1064
|
-
|
|
1065
|
-
orderBy
|
|
1066
|
-
|
|
1067
|
-
|
|
1308
|
+
return _newWindowExpression(func(ctx) {
|
|
1309
|
+
orderByVal := _mapToExpressionStructList(orderByExpressions, "col", ctx)
|
|
1310
|
+
ll.assert(len(orderByVal) > 0, "rank() 'orderBy' list cannot be empty after processing arguments.")
|
|
1311
|
+
return {
|
|
1312
|
+
type: "rank",
|
|
1313
|
+
orderBy: orderByVal,
|
|
1314
|
+
partitionBy: [],
|
|
1315
|
+
descending: descendingVal
|
|
1316
|
+
}
|
|
1068
1317
|
}, undefined, undefined)
|
|
1069
1318
|
}
|
|
1070
1319
|
|
|
@@ -1082,14 +1331,17 @@ _newWhenThenBuilder := func(currentClauses, currentWhenExprOrUndefined) {
|
|
|
1082
1331
|
ll.assert(_isExpression(thenExpr), ".then() expects an expression object argument.")
|
|
1083
1332
|
|
|
1084
1333
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1334
|
+
newClausesExpr := func(ctx) {
|
|
1335
|
+
existingClauses := currentClauses(ctx)
|
|
1336
|
+
newClauses := maps.clone(existingClauses) // Deep copy existing clauses
|
|
1337
|
+
return append(newClauses, {
|
|
1338
|
+
when: currentWhenExprOrUndefined._getExpression(ctx),
|
|
1339
|
+
then: thenExpr._getExpression(ctx)
|
|
1340
|
+
})
|
|
1341
|
+
}
|
|
1090
1342
|
|
|
1091
1343
|
|
|
1092
|
-
return _newWhenThenBuilder(
|
|
1344
|
+
return _newWhenThenBuilder(newClausesExpr, undefined)
|
|
1093
1345
|
},
|
|
1094
1346
|
|
|
1095
1347
|
|
|
@@ -1113,16 +1365,18 @@ _newWhenThenBuilder := func(currentClauses, currentWhenExprOrUndefined) {
|
|
|
1113
1365
|
|
|
1114
1366
|
otherwise: func(otherwiseExpr) {
|
|
1115
1367
|
ll.assert(currentWhenExprOrUndefined == undefined, ".otherwise() must follow a .then() call.")
|
|
1116
|
-
ll.assert(len(currentClauses) > 0, "At least one .when().then() clause is required before .otherwise().")
|
|
1117
1368
|
ll.assert(_isExpression(otherwiseExpr), ".otherwise() expects an expression object argument.")
|
|
1118
1369
|
|
|
1119
1370
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1371
|
+
return _newExpression(func(ctx) {
|
|
1372
|
+
finalClauses := maps.clone(currentClauses(ctx))
|
|
1373
|
+
ll.assert(len(finalClauses) > 0, "At least one .when().then() clause is required before .otherwise().")
|
|
1374
|
+
return {
|
|
1375
|
+
type: "when_then_otherwise",
|
|
1376
|
+
conditions: finalClauses,
|
|
1377
|
+
otherwise: otherwiseExpr._getExpression(ctx)
|
|
1378
|
+
}
|
|
1379
|
+
})
|
|
1126
1380
|
}
|
|
1127
1381
|
})
|
|
1128
1382
|
return builderSelf
|
|
@@ -1140,7 +1394,7 @@ _newWhenThenBuilder := func(currentClauses, currentWhenExprOrUndefined) {
|
|
|
1140
1394
|
|
|
1141
1395
|
when = func(conditionExpr) {
|
|
1142
1396
|
ll.assert(_isExpression(conditionExpr), "Initial when() expects an expression object argument.")
|
|
1143
|
-
return _newWhenThenBuilder([], conditionExpr)
|
|
1397
|
+
return _newWhenThenBuilder(func(ctx) { return [] }, conditionExpr)
|
|
1144
1398
|
}
|
|
1145
1399
|
|
|
1146
1400
|
|
|
@@ -1153,18 +1407,322 @@ when = func(conditionExpr) {
|
|
|
1153
1407
|
|
|
1154
1408
|
|
|
1155
1409
|
|
|
1156
|
-
|
|
1157
|
-
rawExp := func(expression, ...alias) {
|
|
1158
|
-
ll.assert(len(alias) <= 1, "rawExpression expects at most one alias argument")
|
|
1159
|
-
aliasVal := undefined
|
|
1160
|
-
if len(alias) > 0 {
|
|
1161
|
-
aliasVal = alias[0]
|
|
1162
|
-
}
|
|
1410
|
+
rawExp := func(expression) {
|
|
1163
1411
|
ll.assert(is_map(expression), "rawExpression expects a map as argument")
|
|
1164
|
-
return _newExpression(expression
|
|
1412
|
+
return _newExpression(func(ctx) { return expression })
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
_isSelector := func(expression) {
|
|
1416
|
+
return _isExpression(expression) && ll.methodExists(expression, "complement")
|
|
1165
1417
|
}
|
|
1166
1418
|
|
|
1419
|
+
_newSelectorExpression := func(expression) {
|
|
1420
|
+
self := undefined
|
|
1421
|
+
newExpression := _newExpression(expression)
|
|
1422
|
+
self = ll.toStrict(oop.inherit(newExpression, {
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
|
|
1428
|
+
complement: func() {
|
|
1429
|
+
return _newSelectorExpression(func(ctx) {
|
|
1430
|
+
return {
|
|
1431
|
+
type: "selector_complement",
|
|
1432
|
+
selector: self._getExpression(ctx)
|
|
1433
|
+
}
|
|
1434
|
+
})
|
|
1435
|
+
},
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
union: func(...others) {
|
|
1444
|
+
ll.assert(len(others) > 0, "union requires at least one other selector")
|
|
1445
|
+
return _newSelectorExpression(func(ctx) {
|
|
1446
|
+
selectors := [self._getExpression(ctx)]
|
|
1447
|
+
for other in others {
|
|
1448
|
+
ll.assert(_isSelector(other), "union requires selector expressions, got: %T", other)
|
|
1449
|
+
selectors = append(selectors, other._getExpression(ctx))
|
|
1450
|
+
}
|
|
1451
|
+
return {
|
|
1452
|
+
type: "selector_union",
|
|
1453
|
+
selectors: selectors
|
|
1454
|
+
}
|
|
1455
|
+
})
|
|
1456
|
+
},
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
|
|
1464
|
+
intersection: func(...others) {
|
|
1465
|
+
ll.assert(len(others) > 0, "intersection requires at least one other selector")
|
|
1466
|
+
return _newSelectorExpression(func(ctx) {
|
|
1467
|
+
selectors := [self._getExpression(ctx)]
|
|
1468
|
+
for other in others {
|
|
1469
|
+
ll.assert(_isSelector(other), "intersection requires selector expressions, got: %T", other)
|
|
1470
|
+
selectors = append(selectors, other._getExpression(ctx))
|
|
1471
|
+
}
|
|
1472
|
+
return {
|
|
1473
|
+
type: "selector_intersection",
|
|
1474
|
+
selectors: selectors
|
|
1475
|
+
}
|
|
1476
|
+
})
|
|
1477
|
+
},
|
|
1478
|
+
|
|
1479
|
+
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
|
|
1485
|
+
difference: func(...others) {
|
|
1486
|
+
ll.assert(len(others) > 0, "difference requires at least one other selector")
|
|
1487
|
+
return _newSelectorExpression(func(ctx) {
|
|
1488
|
+
selectors := [self._getExpression(ctx)]
|
|
1489
|
+
for other in others {
|
|
1490
|
+
ll.assert(_isSelector(other), "difference requires selector expressions, got: %T", other)
|
|
1491
|
+
selectors = append(selectors, other._getExpression(ctx))
|
|
1492
|
+
}
|
|
1493
|
+
return {
|
|
1494
|
+
type: "selector_difference",
|
|
1495
|
+
selectors: selectors
|
|
1496
|
+
}
|
|
1497
|
+
})
|
|
1498
|
+
},
|
|
1499
|
+
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
symmetricDifference: func(...others) {
|
|
1507
|
+
ll.assert(len(others) > 0, "symmetricDifference requires at least one other selector")
|
|
1508
|
+
return _newSelectorExpression(func(ctx) {
|
|
1509
|
+
selectors := [self._getExpression(ctx)]
|
|
1510
|
+
for other in others {
|
|
1511
|
+
ll.assert(_isSelector(other), "symmetricDifference requires selector expressions, got: %T", other)
|
|
1512
|
+
selectors = append(selectors, other._getExpression(ctx))
|
|
1513
|
+
}
|
|
1514
|
+
return {
|
|
1515
|
+
type: "selector_symmetric_difference",
|
|
1516
|
+
selectors: selectors
|
|
1517
|
+
}
|
|
1518
|
+
})
|
|
1519
|
+
}
|
|
1520
|
+
}))
|
|
1521
|
+
return self
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
sc := ll.toStrict({
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
all: func() {
|
|
1536
|
+
return _newSelectorExpression(func(ctx) {
|
|
1537
|
+
return {type: "selector_all"}
|
|
1538
|
+
})
|
|
1539
|
+
},
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
|
|
1547
|
+
string: func() {
|
|
1548
|
+
return _newSelectorExpression(func(ctx) {
|
|
1549
|
+
return {type: "selector_string"}
|
|
1550
|
+
})
|
|
1551
|
+
},
|
|
1552
|
+
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
|
|
1559
|
+
numeric: func() {
|
|
1560
|
+
return _newSelectorExpression(func(ctx) {
|
|
1561
|
+
return {type: "selector_numeric"}
|
|
1562
|
+
})
|
|
1563
|
+
},
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
|
|
1571
|
+
integer: func() {
|
|
1572
|
+
return _newSelectorExpression(func(ctx) {
|
|
1573
|
+
return {type: "selector_integer"}
|
|
1574
|
+
})
|
|
1575
|
+
},
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
|
|
1582
|
+
|
|
1583
|
+
float: func() {
|
|
1584
|
+
return _newSelectorExpression(func(ctx) {
|
|
1585
|
+
return {type: "selector_float"}
|
|
1586
|
+
})
|
|
1587
|
+
},
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
startsWith: func(prefix) {
|
|
1597
|
+
ll.assert(is_string(prefix), "startsWith requires a string argument, got: %T", prefix)
|
|
1598
|
+
return _newSelectorExpression(func(ctx) {
|
|
1599
|
+
return {
|
|
1600
|
+
type: "selector_starts_with",
|
|
1601
|
+
prefix: prefix
|
|
1602
|
+
}
|
|
1603
|
+
})
|
|
1604
|
+
},
|
|
1605
|
+
|
|
1606
|
+
|
|
1607
|
+
|
|
1608
|
+
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
endsWith: func(suffix) {
|
|
1614
|
+
ll.assert(is_string(suffix), "endsWith requires a string argument, got: %T", suffix)
|
|
1615
|
+
return _newSelectorExpression(func(ctx) {
|
|
1616
|
+
return {
|
|
1617
|
+
type: "selector_ends_with",
|
|
1618
|
+
suffix: suffix
|
|
1619
|
+
}
|
|
1620
|
+
})
|
|
1621
|
+
},
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
contains: func(substring) {
|
|
1631
|
+
ll.assert(is_string(substring), "contains requires a string argument, got: %T", substring)
|
|
1632
|
+
return _newSelectorExpression(func(ctx) {
|
|
1633
|
+
return {
|
|
1634
|
+
type: "selector_contains",
|
|
1635
|
+
substring: substring
|
|
1636
|
+
}
|
|
1637
|
+
})
|
|
1638
|
+
},
|
|
1639
|
+
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
|
|
1645
|
+
|
|
1646
|
+
|
|
1647
|
+
matches: func(pattern) {
|
|
1648
|
+
ll.assert(is_string(pattern), "matches requires a string argument, got: %T", pattern)
|
|
1649
|
+
return _newSelectorExpression(func(ctx) {
|
|
1650
|
+
return {
|
|
1651
|
+
type: "selector_matches",
|
|
1652
|
+
pattern: pattern
|
|
1653
|
+
}
|
|
1654
|
+
})
|
|
1655
|
+
},
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
|
|
1663
|
+
|
|
1664
|
+
exclude: func(...columns) {
|
|
1665
|
+
ll.assert(len(columns) > 0, "exclude requires at least one column name")
|
|
1666
|
+
for col in columns {
|
|
1667
|
+
ll.assert(is_string(col), "exclude requires string arguments, got: %T", col)
|
|
1668
|
+
}
|
|
1669
|
+
return _newSelectorExpression(func(ctx) {
|
|
1670
|
+
return {
|
|
1671
|
+
type: "selector_exclude",
|
|
1672
|
+
columns: columns
|
|
1673
|
+
}
|
|
1674
|
+
})
|
|
1675
|
+
},
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
|
|
1679
|
+
|
|
1680
|
+
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
|
|
1684
|
+
byName: func(...names) {
|
|
1685
|
+
ll.assert(len(names) > 0, "byName requires at least one column name")
|
|
1686
|
+
for name in names {
|
|
1687
|
+
ll.assert(is_string(name), "byName requires string arguments, got: %T", name)
|
|
1688
|
+
}
|
|
1689
|
+
return _newSelectorExpression(func(ctx) {
|
|
1690
|
+
return {
|
|
1691
|
+
type: "selector_by_name",
|
|
1692
|
+
names: names
|
|
1693
|
+
}
|
|
1694
|
+
})
|
|
1695
|
+
},
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
|
|
1699
|
+
|
|
1700
|
+
|
|
1701
|
+
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
axis: func(spec) {
|
|
1705
|
+
validation.assertType(spec, pframesSpec.P_AXIS_SPEC_SCHEMA)
|
|
1706
|
+
return _newSelectorExpression(func(ctx) {
|
|
1707
|
+
return {type: "selector_axis", spec: spec}
|
|
1708
|
+
})
|
|
1709
|
+
},
|
|
1710
|
+
|
|
1711
|
+
|
|
1712
|
+
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
|
|
1717
|
+
nested: func() {
|
|
1718
|
+
return _newSelectorExpression(func(ctx) {
|
|
1719
|
+
return {type: "selector_nested"}
|
|
1720
|
+
})
|
|
1721
|
+
}
|
|
1722
|
+
})
|
|
1723
|
+
|
|
1167
1724
|
export ll.toStrict({
|
|
1725
|
+
axis: axis,
|
|
1168
1726
|
col: col,
|
|
1169
1727
|
lit: lit,
|
|
1170
1728
|
concatStr: concatStr,
|
|
@@ -1177,6 +1735,8 @@ export ll.toStrict({
|
|
|
1177
1735
|
rank: rank,
|
|
1178
1736
|
when: when,
|
|
1179
1737
|
rawExp: rawExp,
|
|
1738
|
+
sc: sc,
|
|
1739
|
+
_newExpression: _newExpression,
|
|
1180
1740
|
_isExpression: _isExpression,
|
|
1181
1741
|
_isAggregation: _isAggregation,
|
|
1182
1742
|
_mapToExpressionStructList: _mapToExpressionStructList,
|