tranfi 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +177 -0
- package/NOTICE +8 -0
- package/README.md +443 -51
- package/app/assets/{index-pDFMluyz.js → index-BIAIKnrp.js} +1 -1
- package/app/index.html +1 -1
- package/binding.gyp +55 -3
- package/csrc/arena.c +7 -5
- package/csrc/batch.c +818 -71
- package/csrc/buffer.c +84 -8
- package/csrc/cJSON.c +262 -19
- package/csrc/cJSON.h +17 -1
- package/csrc/codec_csv.c +1074 -181
- package/csrc/codec_jsonl.c +830 -118
- package/csrc/codec_table.c +108 -78
- package/csrc/codec_text.c +286 -68
- package/csrc/compiler.c +31 -3
- package/csrc/config.h +21 -0
- package/csrc/dsl.c +4722 -485
- package/csrc/expr.c +363 -55
- package/csrc/expr.h +2 -0
- package/csrc/internal.h +316 -27
- package/csrc/ir.c +65 -18
- package/csrc/ir.h +41 -0
- package/csrc/ir_schema.c +20 -5
- package/csrc/ir_serialize.c +68 -6
- package/csrc/ir_sql.c +796 -185
- package/csrc/ir_validate.c +462 -6
- package/csrc/json_path.c +210 -0
- package/csrc/main.c +879 -30
- package/csrc/memory_estimate.c +477 -0
- package/csrc/op_acf.c +171 -21
- package/csrc/op_across.c +477 -0
- package/csrc/op_anomaly.c +167 -32
- package/csrc/op_assert.c +761 -0
- package/csrc/op_bin.c +168 -29
- package/csrc/op_cast.c +383 -55
- package/csrc/op_clip.c +30 -19
- package/csrc/op_date_trunc.c +208 -34
- package/csrc/op_datetime.c +259 -77
- package/csrc/op_derive.c +65 -97
- package/csrc/op_diff.c +146 -30
- package/csrc/op_ewma.c +149 -30
- package/csrc/op_explode.c +124 -26
- package/csrc/op_fill_down.c +125 -53
- package/csrc/op_fill_null.c +176 -31
- package/csrc/op_filter.c +89 -40
- package/csrc/op_frequency.c +571 -43
- package/csrc/op_grep.c +36 -18
- package/csrc/op_group_agg.c +1790 -119
- package/csrc/op_hash.c +48 -15
- package/csrc/op_head.c +21 -86
- package/csrc/op_interpolate.c +268 -62
- package/csrc/op_join.c +2700 -182
- package/csrc/op_json_extract.c +227 -0
- package/csrc/op_json_filter.c +384 -0
- package/csrc/op_json_flatten.c +293 -0
- package/csrc/op_json_schema.c +503 -0
- package/csrc/op_label_encode.c +328 -53
- package/csrc/op_lag.c +181 -0
- package/csrc/op_lead.c +141 -89
- package/csrc/op_normalize.c +363 -79
- package/csrc/op_onehot.c +345 -73
- package/csrc/op_pivot.c +1546 -162
- package/csrc/op_quarantine.c +189 -0
- package/csrc/op_registry.c +2062 -166
- package/csrc/op_rename.c +41 -50
- package/csrc/op_replace.c +270 -118
- package/csrc/op_rleid.c +297 -0
- package/csrc/op_rowid.c +559 -0
- package/csrc/op_sample.c +80 -23
- package/csrc/op_schema.c +1341 -0
- package/csrc/op_schema_infer.c +252 -0
- package/csrc/op_select.c +265 -65
- package/csrc/op_set.c +3449 -0
- package/csrc/op_skip.c +30 -87
- package/csrc/op_sort.c +670 -124
- package/csrc/op_source_name.c +120 -0
- package/csrc/op_split.c +65 -28
- package/csrc/op_split_data.c +41 -9
- package/csrc/op_stack.c +178 -222
- package/csrc/op_stats.c +206 -110
- package/csrc/op_step.c +217 -55
- package/csrc/op_tail.c +21 -12
- package/csrc/op_tee.c +338 -0
- package/csrc/op_top.c +260 -53
- package/csrc/op_trim.c +48 -19
- package/csrc/op_unique.c +1193 -150
- package/csrc/op_unpivot.c +100 -66
- package/csrc/op_validate.c +601 -24
- package/csrc/op_window.c +492 -51
- package/csrc/path_policy.c +85 -0
- package/csrc/pipeline.c +872 -99
- package/csrc/recipes.c +3 -1
- package/csrc/report.c +73 -30
- package/csrc/selector.c +1097 -0
- package/csrc/size_utils.c +352 -0
- package/csrc/spill.c +317 -0
- package/csrc/spill.h +21 -0
- package/csrc/tranfi.h +169 -1
- package/csrc/transform.h +209 -0
- package/csrc/transform_api.c +2237 -0
- package/csrc/transform_categorical.c +923 -0
- package/csrc/transform_internal.h +472 -0
- package/csrc/transform_json.c +3812 -0
- package/csrc/transform_numeric.c +1966 -0
- package/csrc/transform_sha256.c +154 -0
- package/csrc/transform_wasm.h +162 -0
- package/csrc/transform_wasm_api.c +1373 -0
- package/csrc/wasm_api.c +70 -9
- package/napi_api.c +219 -11
- package/napi_transform.c +1648 -0
- package/napi_transform.h +8 -0
- package/package.json +27 -11
- package/scripts/install-native.js +76 -0
- package/scripts/prepack.js +64 -0
- package/scripts/sync-csrc.js +23 -0
- package/src/cli.js +81 -41
- package/src/engines/duckdb.js +45 -12
- package/src/index.js +661 -42
- package/src/memory_policy.js +411 -0
- package/src/native.js +1 -5
- package/src/pipeline.js +454 -31
- package/src/recipe_json.js +80 -0
- package/src/server.js +10 -8
- package/src/transform.js +403 -0
- package/src/transform_error.js +10 -0
- package/src/wasm.js +6 -4
- package/wasm/index.js +498 -10
- package/wasm/tranfi_core.js +0 -0
- package/wasm/transform.js +1156 -0
- package/wasm/worker.js +786 -0
- package/csrc/plan.c +0 -206
package/csrc/ir.h
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#ifndef TF_IR_H
|
|
9
9
|
#define TF_IR_H
|
|
10
10
|
|
|
11
|
+
#include "config.h"
|
|
11
12
|
#include <stddef.h>
|
|
12
13
|
#include <stdint.h>
|
|
13
14
|
#include <stdbool.h>
|
|
@@ -16,6 +17,7 @@
|
|
|
16
17
|
typedef struct cJSON cJSON;
|
|
17
18
|
typedef struct tf_ir_node tf_ir_node;
|
|
18
19
|
typedef struct tf_schema tf_schema;
|
|
20
|
+
typedef struct tf_host_policy tf_host_policy;
|
|
19
21
|
|
|
20
22
|
/* ---- Capability flags ---- */
|
|
21
23
|
|
|
@@ -41,6 +43,29 @@ typedef enum {
|
|
|
41
43
|
TF_OP_TRANSFORM,
|
|
42
44
|
} tf_op_kind;
|
|
43
45
|
|
|
46
|
+
/* ---- Streaming contract metadata ---- */
|
|
47
|
+
|
|
48
|
+
typedef enum {
|
|
49
|
+
TF_MEM_ROW_LOCAL, /* O(batch_rows * columns) */
|
|
50
|
+
TF_MEM_BOUNDED_STATE, /* O(parameter), e.g. window K or tail N */
|
|
51
|
+
TF_MEM_KEY_STATE, /* O(distinct keys/categories) */
|
|
52
|
+
TF_MEM_BLOCKING, /* needs full input in native mode */
|
|
53
|
+
TF_MEM_EXTERNAL, /* uses spill/SQL/external bounded storage */
|
|
54
|
+
} tf_memory_class;
|
|
55
|
+
|
|
56
|
+
typedef enum {
|
|
57
|
+
TF_EMIT_PER_BATCH, /* can emit during push() */
|
|
58
|
+
TF_EMIT_ON_FLUSH, /* emits only at finish(), e.g. tail/top/stats */
|
|
59
|
+
TF_EMIT_SIDE_ONLY, /* writes side channels, not main output */
|
|
60
|
+
TF_EMIT_MIXED, /* emits both during push() and flush/side output */
|
|
61
|
+
} tf_emit_class;
|
|
62
|
+
|
|
63
|
+
typedef enum {
|
|
64
|
+
TF_SCHEMA_STABLE, /* output columns known from input schema/args */
|
|
65
|
+
TF_SCHEMA_PARAMETRIC, /* output schema depends on explicit parameters */
|
|
66
|
+
TF_SCHEMA_DATA_DEPENDENT, /* output schema depends on observed data */
|
|
67
|
+
} tf_schema_class;
|
|
68
|
+
|
|
44
69
|
/* ---- Argument descriptor ---- */
|
|
45
70
|
|
|
46
71
|
typedef struct {
|
|
@@ -52,6 +77,8 @@ typedef struct {
|
|
|
52
77
|
|
|
53
78
|
/* ---- Value types (shared with batch system) ---- */
|
|
54
79
|
|
|
80
|
+
#ifndef TF_TYPE_DEFINED
|
|
81
|
+
#define TF_TYPE_DEFINED
|
|
55
82
|
typedef enum tf_type {
|
|
56
83
|
TF_TYPE_NULL = 0,
|
|
57
84
|
TF_TYPE_BOOL,
|
|
@@ -61,6 +88,7 @@ typedef enum tf_type {
|
|
|
61
88
|
TF_TYPE_DATE, /* int32_t: days since 1970-01-01 */
|
|
62
89
|
TF_TYPE_TIMESTAMP, /* int64_t: microseconds since 1970-01-01T00:00:00Z */
|
|
63
90
|
} tf_type;
|
|
91
|
+
#endif
|
|
64
92
|
|
|
65
93
|
/* ---- Schema ---- */
|
|
66
94
|
|
|
@@ -73,6 +101,7 @@ struct tf_schema {
|
|
|
73
101
|
|
|
74
102
|
void tf_schema_free(tf_schema *s);
|
|
75
103
|
void tf_schema_copy(tf_schema *dst, const tf_schema *src);
|
|
104
|
+
int tf_schema_copy_checked(tf_schema *dst, const tf_schema *src);
|
|
76
105
|
|
|
77
106
|
/* ---- Op registry entry ---- */
|
|
78
107
|
|
|
@@ -81,6 +110,10 @@ typedef struct {
|
|
|
81
110
|
tf_op_kind kind;
|
|
82
111
|
tf_op_tier tier;
|
|
83
112
|
uint32_t caps; /* TF_CAP_* bitfield */
|
|
113
|
+
tf_memory_class memory_class;
|
|
114
|
+
tf_emit_class emit_class;
|
|
115
|
+
tf_schema_class schema_class;
|
|
116
|
+
const char *state_estimate; /* Big-O state retained by the op */
|
|
84
117
|
tf_arg_desc *args;
|
|
85
118
|
size_t n_args;
|
|
86
119
|
/* Schema transform: given input schema, compute output schema.
|
|
@@ -97,6 +130,9 @@ typedef struct {
|
|
|
97
130
|
const tf_op_entry *tf_op_registry_find(const char *name);
|
|
98
131
|
size_t tf_op_registry_count(void);
|
|
99
132
|
const tf_op_entry *tf_op_registry_get(size_t index);
|
|
133
|
+
const char *tf_memory_class_name(tf_memory_class cls);
|
|
134
|
+
const char *tf_emit_class_name(tf_emit_class cls);
|
|
135
|
+
const char *tf_schema_class_name(tf_schema_class cls);
|
|
100
136
|
|
|
101
137
|
/* ---- IR node ---- */
|
|
102
138
|
|
|
@@ -106,6 +142,10 @@ struct tf_ir_node {
|
|
|
106
142
|
tf_schema input_schema;
|
|
107
143
|
tf_schema output_schema;
|
|
108
144
|
uint32_t caps; /* resolved capability flags from registry */
|
|
145
|
+
tf_memory_class memory_class;
|
|
146
|
+
tf_emit_class emit_class;
|
|
147
|
+
tf_schema_class schema_class;
|
|
148
|
+
const char *state_estimate; /* Big-O state estimate, static string */
|
|
109
149
|
size_t index; /* position in plan */
|
|
110
150
|
};
|
|
111
151
|
|
|
@@ -138,6 +178,7 @@ char *tf_ir_to_sql(const tf_ir_plan *plan, char **error);
|
|
|
138
178
|
/* ---- IR passes ---- */
|
|
139
179
|
|
|
140
180
|
int tf_ir_validate(tf_ir_plan *plan);
|
|
181
|
+
int tf_ir_validate_with_host_policy(tf_ir_plan *plan, const tf_host_policy *policy);
|
|
141
182
|
int tf_ir_infer_schema(tf_ir_plan *plan);
|
|
142
183
|
|
|
143
184
|
/* ---- Expression eval result ---- */
|
package/csrc/ir_schema.c
CHANGED
|
@@ -25,16 +25,27 @@ int tf_ir_infer_schema(tf_ir_plan *plan) {
|
|
|
25
25
|
|
|
26
26
|
/* Copy current schema as this node's input */
|
|
27
27
|
tf_schema_free(&node->input_schema);
|
|
28
|
-
|
|
28
|
+
if (tf_schema_copy_checked(&node->input_schema, ¤t) != TF_OK) {
|
|
29
|
+
tf_schema_free(¤t);
|
|
30
|
+
plan->schema_inferred = false;
|
|
31
|
+
return TF_ERROR;
|
|
32
|
+
}
|
|
29
33
|
|
|
30
34
|
if (entry && entry->infer_schema) {
|
|
31
35
|
/* Clear old output schema */
|
|
32
36
|
tf_schema_free(&node->output_schema);
|
|
33
|
-
entry->infer_schema(node, ¤t, &node->output_schema)
|
|
37
|
+
if (entry->infer_schema(node, ¤t, &node->output_schema) != TF_OK) {
|
|
38
|
+
tf_schema_free(¤t);
|
|
39
|
+
plan->schema_inferred = false;
|
|
40
|
+
return TF_ERROR;
|
|
41
|
+
}
|
|
34
42
|
|
|
35
43
|
/* Advance current to this node's output */
|
|
36
44
|
tf_schema_free(¤t);
|
|
37
|
-
|
|
45
|
+
if (tf_schema_copy_checked(¤t, &node->output_schema) != TF_OK) {
|
|
46
|
+
plan->schema_inferred = false;
|
|
47
|
+
return TF_ERROR;
|
|
48
|
+
}
|
|
38
49
|
} else {
|
|
39
50
|
/* No schema inference available — propagate unknown */
|
|
40
51
|
tf_schema_free(&node->output_schema);
|
|
@@ -48,8 +59,12 @@ int tf_ir_infer_schema(tf_ir_plan *plan) {
|
|
|
48
59
|
tf_schema_free(&plan->final_schema);
|
|
49
60
|
if (plan->n_nodes >= 2) {
|
|
50
61
|
/* The schema before the encoder is the second-to-last node's output */
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
if (tf_schema_copy_checked(&plan->final_schema,
|
|
63
|
+
&plan->nodes[plan->n_nodes - 2].output_schema) != TF_OK) {
|
|
64
|
+
tf_schema_free(¤t);
|
|
65
|
+
plan->schema_inferred = false;
|
|
66
|
+
return TF_ERROR;
|
|
67
|
+
}
|
|
53
68
|
} else {
|
|
54
69
|
plan->final_schema.known = false;
|
|
55
70
|
}
|
package/csrc/ir_serialize.c
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* }
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
#include "
|
|
14
|
+
#include "internal.h"
|
|
15
15
|
#include "cJSON.h"
|
|
16
16
|
#include <stdlib.h>
|
|
17
17
|
#include <string.h>
|
|
@@ -84,18 +84,80 @@ tf_ir_plan *tf_ir_from_json(const char *json, size_t len, char **error) {
|
|
|
84
84
|
|
|
85
85
|
char *tf_ir_to_json(const tf_ir_plan *plan) {
|
|
86
86
|
cJSON *root = cJSON_CreateObject();
|
|
87
|
-
|
|
87
|
+
if (!root) return NULL;
|
|
88
|
+
cJSON *steps = cJSON_CreateArray();
|
|
89
|
+
if (!steps || tf_json_add_item(root, "steps", steps) != TF_OK) {
|
|
90
|
+
cJSON_Delete(root);
|
|
91
|
+
return NULL;
|
|
92
|
+
}
|
|
88
93
|
|
|
89
94
|
for (size_t i = 0; i < plan->n_nodes; i++) {
|
|
90
95
|
const tf_ir_node *node = &plan->nodes[i];
|
|
91
96
|
cJSON *step = cJSON_CreateObject();
|
|
92
|
-
|
|
97
|
+
if (!step) {
|
|
98
|
+
cJSON_Delete(root);
|
|
99
|
+
return NULL;
|
|
100
|
+
}
|
|
101
|
+
if (tf_json_add_string(step, "op", node->op) != TF_OK) {
|
|
102
|
+
cJSON_Delete(step);
|
|
103
|
+
cJSON_Delete(root);
|
|
104
|
+
return NULL;
|
|
105
|
+
}
|
|
93
106
|
if (node->args) {
|
|
94
|
-
|
|
107
|
+
cJSON *args = cJSON_Duplicate(node->args, 1);
|
|
108
|
+
if (args) {
|
|
109
|
+
cJSON_DeleteItemFromObjectCaseSensitive(args, TF_POLICY_VALIDATED_FILE_PATH_ARG);
|
|
110
|
+
cJSON_DeleteItemFromObjectCaseSensitive(args, TF_POLICY_VALIDATED_RULES_FILE_PATH_ARG);
|
|
111
|
+
}
|
|
112
|
+
if (!args || tf_json_add_item(step, "args", args) != TF_OK) {
|
|
113
|
+
cJSON_Delete(step);
|
|
114
|
+
cJSON_Delete(root);
|
|
115
|
+
return NULL;
|
|
116
|
+
}
|
|
95
117
|
} else {
|
|
96
|
-
|
|
118
|
+
cJSON *args = cJSON_CreateObject();
|
|
119
|
+
if (!args || tf_json_add_item(step, "args", args) != TF_OK) {
|
|
120
|
+
cJSON_Delete(step);
|
|
121
|
+
cJSON_Delete(root);
|
|
122
|
+
return NULL;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (tf_json_add_string(step, "memory_class", tf_memory_class_name(node->memory_class)) != TF_OK ||
|
|
126
|
+
tf_json_add_string(step, "emit_class", tf_emit_class_name(node->emit_class)) != TF_OK ||
|
|
127
|
+
tf_json_add_string(step, "schema_class", tf_schema_class_name(node->schema_class)) != TF_OK ||
|
|
128
|
+
tf_json_add_string(step, "state_estimate",
|
|
129
|
+
node->state_estimate ? node->state_estimate : "unknown") != TF_OK) {
|
|
130
|
+
cJSON_Delete(step);
|
|
131
|
+
cJSON_Delete(root);
|
|
132
|
+
return NULL;
|
|
133
|
+
}
|
|
134
|
+
size_t state_bytes = 0;
|
|
135
|
+
char state_reason[192] = {0};
|
|
136
|
+
if (tf_estimate_step_state_bytes(node, &state_bytes, state_reason, sizeof(state_reason))) {
|
|
137
|
+
if (tf_json_add_number(step, "state_bytes_estimate", (double)state_bytes) != TF_OK) {
|
|
138
|
+
cJSON_Delete(step);
|
|
139
|
+
cJSON_Delete(root);
|
|
140
|
+
return NULL;
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
if (tf_json_add_null(step, "state_bytes_estimate") != TF_OK) {
|
|
144
|
+
cJSON_Delete(step);
|
|
145
|
+
cJSON_Delete(root);
|
|
146
|
+
return NULL;
|
|
147
|
+
}
|
|
148
|
+
if (node->memory_class == TF_MEM_KEY_STATE || node->memory_class == TF_MEM_BLOCKING) {
|
|
149
|
+
if (tf_json_add_string(step, "state_bytes_reason",
|
|
150
|
+
state_reason[0] ? state_reason : "no native byte estimator") != TF_OK) {
|
|
151
|
+
cJSON_Delete(step);
|
|
152
|
+
cJSON_Delete(root);
|
|
153
|
+
return NULL;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (tf_json_add_array_item(steps, step) != TF_OK) {
|
|
158
|
+
cJSON_Delete(root);
|
|
159
|
+
return NULL;
|
|
97
160
|
}
|
|
98
|
-
cJSON_AddItemToArray(steps, step);
|
|
99
161
|
}
|
|
100
162
|
|
|
101
163
|
char *out = cJSON_PrintUnformatted(root);
|