@platforma-sdk/workflow-tengo 6.16.0 → 6.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/tengo/lib/pframes.util.lib.tengo +6 -0
  2. package/dist/tengo/lib/pframes.xsv-import-pt.lib.tengo +100 -56
  3. package/dist/tengo/lib/pt.lib.tengo +57 -0
  4. package/dist/tengo/lib/pt.util.lib.tengo +42 -0
  5. package/dist/tengo/lib/slices.lib.tengo +49 -26
  6. package/dist/tengo/tpl/annotations.compute.plj.gz +0 -0
  7. package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
  8. package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
  9. package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
  10. package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
  11. package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
  12. package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
  13. package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
  14. package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
  15. package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
  16. package/dist/tengo/tpl/exec.conda.create-env.plj.gz +0 -0
  17. package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
  18. package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
  19. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  20. package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
  21. package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
  22. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  23. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  24. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  25. package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
  26. package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
  27. package/dist/tengo/tpl/pframes.build-table.plj.gz +0 -0
  28. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  29. package/dist/tengo/tpl/pframes.export-parquet-pcolumn-chunk.plj.gz +0 -0
  30. package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
  31. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  32. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  33. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  34. package/dist/tengo/tpl/pframes.merge-resource-maps.plj.gz +0 -0
  35. package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
  36. package/dist/tengo/tpl/pframes.process-pcolumn-batch-split.plj.gz +0 -0
  37. package/dist/tengo/tpl/pframes.process-pcolumn-batch.plj.gz +0 -0
  38. package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
  39. package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
  40. package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
  41. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  42. package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
  43. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  44. package/dist/tengo/tpl/pt.import-dir.plj.gz +0 -0
  45. package/dist/tengo/tpl/pt.workflow-run.plj.gz +0 -0
  46. package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
  47. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  48. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  49. package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
  50. package/dist/tengo/tpl/workflow.query-context-filter.plj.gz +0 -0
  51. package/package.json +9 -4
@@ -186,6 +186,12 @@ PFCONV_IMPORT_CFG_SCHEMA := {
186
186
  `storageFormat,?` : `string,regex=Binary|Json|Parquet`,
187
187
 
188
188
 
189
+
190
+
191
+
192
+ `importEngine,?` : `string,regex=polars|duckdb`,
193
+
194
+
189
195
  `partitionKeyLength,?` : `number`
190
196
  }
191
197
 
@@ -47,6 +47,66 @@ applyNaRegex := func(colExpr, naRegex, colType) {
47
47
 
48
48
 
49
49
 
50
+ _duckdbEligible := func(spec, xsvType) {
51
+ if spec.importEngine != "duckdb" || xsvType != "parquet" {
52
+ return false
53
+ }
54
+ if !is_undefined(spec.index) {
55
+ return false
56
+ }
57
+ for ax in spec.axes {
58
+ if !is_undefined(ax.preProcess) || !is_undefined(ax.naRegex) || !is_undefined(ax.filterOutRegex) {
59
+ return false
60
+ }
61
+ }
62
+ for col in spec.columns {
63
+ if !is_undefined(col.preProcess) || !is_undefined(col.naRegex) || !is_undefined(col.filterOutRegex) {
64
+ return false
65
+ }
66
+ }
67
+ return true
68
+ }
69
+
70
+
71
+
72
+
73
+
74
+ _buildResult := func(pf, spec, ops) {
75
+ if ops.dataOnly {
76
+ pfd := smart.mapBuilder()
77
+ for col in spec.columns {
78
+ colId := util.xsvColumnId(col)
79
+ colData := pf.getFutureInputField(col.column + ".data")
80
+ pfd.createInputField(colId).set(colData)
81
+ }
82
+ return pfd.lockAndBuild()
83
+ }
84
+
85
+ result := {}
86
+ axesSpec := slices.map(spec.axes, func(ax) { return ax.spec })
87
+ for col in spec.columns {
88
+ colId := util.xsvColumnId(col)
89
+ colSpec := getColumnSpec(axesSpec, col)
90
+ colData := pf.getFutureInputField(col.column + ".data")
91
+ if ops.splitDataAndSpec {
92
+ result[colId] = {
93
+ spec: colSpec,
94
+ data: colData
95
+ }
96
+ } else {
97
+ result[colId + ".spec"] = colSpec
98
+ result[colId + ".data"] = colData
99
+ }
100
+ }
101
+ return result
102
+ }
103
+
104
+
105
+
106
+
107
+
108
+
109
+
50
110
 
51
111
 
52
112
 
@@ -107,6 +167,43 @@ importFileParquet := func(xsvFile, xsvType, spec, ops) {
107
167
  wf.cacheInputs(ops.inputCache)
108
168
  }
109
169
 
170
+
171
+ saveParams := {
172
+ axes: [],
173
+ columns: [],
174
+ partitionKeyLength: 0
175
+ }
176
+ if !is_undefined(spec.partitionKeyLength) {
177
+ saveParams.partitionKeyLength = spec.partitionKeyLength
178
+ }
179
+ for ax in spec.axes {
180
+ saveParams.axes = append(saveParams.axes, {
181
+ column: ax.column,
182
+ spec: maps.deepMerge({ name: ax.column }, ax.spec)
183
+ })
184
+ }
185
+ notNullColumns := []
186
+ for col in spec.columns {
187
+ saveParams.columns = append(saveParams.columns, {
188
+ column: col.column,
189
+ spec: maps.deepMerge({ name: col.column }, col.spec)
190
+ })
191
+ if col.allowNA == false {
192
+
193
+ notNullColumns = append(notNullColumns, col.column)
194
+ }
195
+ }
196
+
197
+ frameName := "xsv_import_output"
198
+
199
+
200
+
201
+
202
+ if _duckdbEligible(spec, xsvType) {
203
+ wf.importParquetFrame(xsvFile, frameName, saveParams, notNullColumns)
204
+ return _buildResult(wf.run().getFrameDirect(frameName), spec, ops)
205
+ }
206
+
110
207
  schema := []
111
208
  for ax in spec.axes {
112
209
  schema = append(schema, {
@@ -169,68 +266,15 @@ importFileParquet := func(xsvFile, xsvType, spec, ops) {
169
266
  notNullConditions := []
170
267
 
171
268
 
172
- for col in spec.columns {
173
- if col.allowNA == false {
174
-
175
- notNullConditions = append(notNullConditions, pt.col(col.column).isNotNull())
176
- }
269
+ for column in notNullColumns {
270
+ notNullConditions = append(notNullConditions, pt.col(column).isNotNull())
177
271
  }
178
272
  if len(notNullConditions) > 0 {
179
273
  df = df.filter(pt.and(notNullConditions...))
180
274
  }
181
275
 
182
- saveParams := {
183
- axes: [],
184
- columns: [],
185
- partitionKeyLength: 0
186
- }
187
- if !is_undefined(spec.partitionKeyLength) {
188
- saveParams.partitionKeyLength = spec.partitionKeyLength
189
- }
190
- for ax in spec.axes {
191
- saveParams.axes = append(saveParams.axes, {
192
- column: ax.column,
193
- spec: maps.deepMerge({ name: ax.column }, ax.spec)
194
- })
195
- }
196
- for col in spec.columns {
197
- saveParams.columns = append(saveParams.columns, {
198
- column: col.column,
199
- spec: maps.deepMerge({ name: col.column }, col.spec)
200
- })
201
- }
202
-
203
- frameName := "xsv_import_output"
204
276
  df.saveFrameDirect(frameName, saveParams)
205
- pf := wf.run().getFrameDirect(frameName)
206
-
207
- if ops.dataOnly {
208
- pfd := smart.mapBuilder()
209
- for col in spec.columns {
210
- colId := util.xsvColumnId(col)
211
- colData := pf.getFutureInputField(col.column + ".data")
212
- pfd.createInputField(colId).set(colData)
213
- }
214
- return pfd.lockAndBuild()
215
- }
216
-
217
- result := {}
218
- axesSpec := slices.map(spec.axes, func(ax) { return ax.spec })
219
- for col in spec.columns {
220
- colId := util.xsvColumnId(col)
221
- colSpec := getColumnSpec(axesSpec, col)
222
- colData := pf.getFutureInputField(col.column + ".data")
223
- if ops.splitDataAndSpec {
224
- result[colId] = {
225
- spec: colSpec,
226
- data: colData
227
- }
228
- } else {
229
- result[colId + ".spec"] = colSpec
230
- result[colId + ".data"] = colData
231
- }
232
- }
233
- return result
277
+ return _buildResult(wf.run().getFrameDirect(frameName), spec, ops)
234
278
  }
235
279
 
236
280
  export ll.toStrict({
@@ -453,6 +453,63 @@ workflow := func() {
453
453
 
454
454
 
455
455
 
456
+
457
+
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470
+ importParquetFrame: func(fileRef, frameName, params, ...notNullColumns) {
471
+ ll.assert(len(frameName) > 0, "frameName must be a non-empty string")
472
+ ll.assert(smart.isReference(fileRef),
473
+ "fileRef must be a valid resource reference, got: %v", fileRef)
474
+ util.validateParamsForSaveFrameDirect(params)
475
+
476
+ fileName := self._newAnonymousFileId("parquet")
477
+ inFiles = append(inFiles, { file: fileRef, name: fileName })
478
+
479
+
480
+
481
+ translation := {}
482
+ columnCount := 0
483
+ for ax in params.axes {
484
+ columnCount += 1
485
+ translation[ax.column] = "col" + string(columnCount)
486
+ }
487
+ for col in params.columns {
488
+ columnCount += 1
489
+ translation[col.column] = "col" + string(columnCount)
490
+ }
491
+
492
+ notNullSet := {}
493
+ if len(notNullColumns) > 0 {
494
+ ll.assert(is_array(notNullColumns[0]),
495
+ "notNullColumns must be an array of column names, got: %v", notNullColumns[0])
496
+ for column in notNullColumns[0] {
497
+ notNullSet[column] = true
498
+ }
499
+ }
500
+
501
+ colInfo := util.makeFrameColumnInfo(params, translation)
502
+ sequentialFrameName := self._newUniquePFrameName()
503
+ self._saveFrameInfo(frameName, sequentialFrameName, colInfo)
504
+
505
+ self.addRawStep(util.makeImportParquetFrameStep(
506
+ sequentialFrameName, fileName, params, translation, notNullSet))
507
+
508
+ return self
509
+ },
510
+
511
+
512
+
456
513
  _testGetLastRawStep: func() {
457
514
  ll.assert(len(steps) > 0, "_testGetLastRawStep: no steps registered")
458
515
  return steps[len(steps)-1](undefined)
@@ -171,6 +171,47 @@ makeWriteFrameStep := func(frameName, dfName, params, translation) {
171
171
  return step
172
172
  }
173
173
 
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+ makeImportParquetFrameStep := func(frameName, fileName, params, translation, notNullSet) {
184
+ step := {
185
+ type: "import_parquet_frame",
186
+ file: fileName,
187
+ frameName: frameName,
188
+ axes: slices.map(params.axes, func(entry) {
189
+ return {
190
+ column: translation[entry.column],
191
+ source: entry.column,
192
+ type: entry.spec.type
193
+ }
194
+ }),
195
+ columns: slices.map(params.columns, func(entry) {
196
+ return {
197
+ column: translation[entry.column],
198
+ source: entry.column,
199
+ type: entry.spec.valueType,
200
+ notNull: !is_undefined(notNullSet[entry.column])
201
+ }
202
+ }),
203
+ partitionKeyLength: 0,
204
+ strict: false
205
+ }
206
+ if !is_undefined(params.partitionKeyLength) {
207
+ step.partitionKeyLength = params.partitionKeyLength
208
+ }
209
+ if !is_undefined(params.strict) {
210
+ step.strict = params.strict
211
+ }
212
+ return step
213
+ }
214
+
174
215
  makeFrameColumnRef := func(frameName, columnId) {
175
216
  return canonical.encode({
176
217
  frame: frameName,
@@ -464,6 +505,7 @@ export ll.toStrict({
464
505
  validateParamsForFrameFromColumnBundle: validateParamsForFrameFromColumnBundle,
465
506
  makeFrameColumnInfo: makeFrameColumnInfo,
466
507
  makeWriteFrameStep: makeWriteFrameStep,
508
+ makeImportParquetFrameStep: makeImportParquetFrameStep,
467
509
  makeFrameColumnRef: makeFrameColumnRef,
468
510
  renameSpecQueryColumns: renameSpecQueryColumns,
469
511
  validateAxisFilters: validateAxisFilters
@@ -213,45 +213,68 @@ every := func(slice, fn) {
213
213
 
214
214
 
215
215
 
216
+
217
+
218
+
219
+
220
+
216
221
  _quickSortFn := func(arr, left, right, less) {
217
- if is_undefined(arr) || len(arr) <= 1 || left < 0 || left >= len(arr) || right < 0 || right >= len(arr) || left >= right {
222
+ if is_undefined(arr) || len(arr) <= 1 || left < 0 || left >= len(arr) || right < 0 || right >= len(arr) {
218
223
  return arr
219
224
  }
220
- idx := left
221
- for i := left; i < right; i++ {
222
- if less(arr[i], arr[right]) {
223
- temp := arr[i]
224
- arr[i] = arr[idx]
225
- arr[idx] = temp
226
- idx++
225
+ for left < right {
226
+ pivot := arr[left + (right - left) / 2]
227
+ i := left
228
+ j := right
229
+ for i <= j {
230
+ for less(arr[i], pivot) { i++ }
231
+ for less(pivot, arr[j]) { j-- }
232
+ if i <= j {
233
+ temp := arr[i]
234
+ arr[i] = arr[j]
235
+ arr[j] = temp
236
+ i++
237
+ j--
238
+ }
239
+ }
240
+ if j - left < right - i {
241
+ _quickSortFn(arr, left, j, less)
242
+ left = i
243
+ } else {
244
+ _quickSortFn(arr, i, right, less)
245
+ right = j
227
246
  }
228
247
  }
229
- temp := arr[right]
230
- arr[right] = arr[idx]
231
- arr[idx] = temp
232
- _quickSortFn(arr, left, idx-1, less)
233
- _quickSortFn(arr, idx+1, right, less)
234
248
  return arr
235
249
  }
236
250
 
237
251
  _quickSort := func(arr, left, right) {
238
- if is_undefined(arr) || len(arr) <= 1 || left < 0 || left >= len(arr) || right < 0 || right >= len(arr) || left >= right {
252
+ if is_undefined(arr) || len(arr) <= 1 || left < 0 || left >= len(arr) || right < 0 || right >= len(arr) {
239
253
  return arr
240
254
  }
241
- idx := left
242
- for i := left; i < right; i++ {
243
- if arr[i] < arr[right] {
244
- temp := arr[i]
245
- arr[i] = arr[idx]
246
- arr[idx] = temp
247
- idx++
255
+ for left < right {
256
+ pivot := arr[left + (right - left) / 2]
257
+ i := left
258
+ j := right
259
+ for i <= j {
260
+ for arr[i] < pivot { i++ }
261
+ for pivot < arr[j] { j-- }
262
+ if i <= j {
263
+ temp := arr[i]
264
+ arr[i] = arr[j]
265
+ arr[j] = temp
266
+ i++
267
+ j--
268
+ }
269
+ }
270
+ if j - left < right - i {
271
+ _quickSort(arr, left, j)
272
+ left = i
273
+ } else {
274
+ _quickSort(arr, i, right)
275
+ right = j
248
276
  }
249
277
  }
250
- temp := arr[right]
251
- arr[right] = arr[idx]
252
- arr[idx] = temp
253
- _quickSort(arr, left, idx-1)
254
- _quickSort(arr, idx+1, right)
255
278
  return arr
256
279
  }
257
280
 
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/workflow-tengo",
3
- "version": "6.16.0",
3
+ "version": "6.17.1",
4
4
  "description": "Tengo SDK library",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -19,11 +19,16 @@
19
19
  "@milaboratories/pframes-rs-wasip2": "1.1.61",
20
20
  "@milaboratories/software-pframes-conv": "2.2.9",
21
21
  "@platforma-open/milaboratories.software-small-binaries": "^2.1.1",
22
- "@platforma-open/milaboratories.software-ptexter": "1.2.6",
23
- "@platforma-open/milaboratories.software-ptabler": "2.1.14"
22
+ "@platforma-open/milaboratories.software-ptabler": "2.2.0",
23
+ "@platforma-open/milaboratories.software-ptexter": "1.2.6"
24
24
  },
25
25
  "devDependencies": {
26
- "@platforma-sdk/tengo-builder": "4.1.11"
26
+ "@platforma-sdk/tengo-builder": "4.1.13"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/milaboratory/platforma.git",
31
+ "directory": "sdk/workflow-tengo"
27
32
  },
28
33
  "scripts": {
29
34
  "types:check": "pl-tengo imports && pl-tengo check",