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/op_filter.c
CHANGED
|
@@ -10,13 +10,48 @@
|
|
|
10
10
|
#include <stdlib.h>
|
|
11
11
|
#include <string.h>
|
|
12
12
|
#include <stdio.h>
|
|
13
|
+
#include <stdbool.h>
|
|
13
14
|
|
|
14
15
|
typedef struct {
|
|
15
16
|
tf_expr *expr;
|
|
17
|
+
char *expr_text;
|
|
16
18
|
size_t rows_in;
|
|
17
19
|
size_t rows_out;
|
|
20
|
+
size_t row_index;
|
|
21
|
+
size_t audit_limit;
|
|
22
|
+
size_t audit_emitted;
|
|
23
|
+
int audit;
|
|
24
|
+
tf_audit_options audit_opts;
|
|
18
25
|
} filter_state;
|
|
19
26
|
|
|
27
|
+
static int filter_emit_drop_audit(filter_state *st, const tf_batch *b, size_t row,
|
|
28
|
+
tf_side_channels *side, const char *reason) {
|
|
29
|
+
if (!st->audit || st->audit_emitted >= st->audit_limit || !side || !side->stats) return TF_OK;
|
|
30
|
+
cJSON *obj = cJSON_CreateObject();
|
|
31
|
+
if (!obj) return TF_ERROR;
|
|
32
|
+
int rc = TF_ERROR;
|
|
33
|
+
if (tf_json_add_string(obj, "type", "audit") != TF_OK ||
|
|
34
|
+
tf_json_add_string(obj, "op", "filter") != TF_OK ||
|
|
35
|
+
tf_json_add_string(obj, "event", "row_dropped") != TF_OK ||
|
|
36
|
+
tf_json_add_string(obj, "reason", reason ? reason : "predicate_false") != TF_OK ||
|
|
37
|
+
tf_json_add_string(obj, "channel", "audit") != TF_OK ||
|
|
38
|
+
tf_json_add_string(obj, "expr", st->expr_text ? st->expr_text : "") != TF_OK ||
|
|
39
|
+
tf_json_add_number(obj, "row", (double)st->row_index) != TF_OK) {
|
|
40
|
+
goto done;
|
|
41
|
+
}
|
|
42
|
+
cJSON *data = tf_audit_row_to_json(b, row, &st->audit_opts);
|
|
43
|
+
if (data) {
|
|
44
|
+
if (tf_json_add_item(obj, "data", data) != TF_OK) goto done;
|
|
45
|
+
} else if (st->audit_opts.include_row) {
|
|
46
|
+
goto done;
|
|
47
|
+
}
|
|
48
|
+
rc = tf_buffer_write_json_line(side->stats, obj);
|
|
49
|
+
done:
|
|
50
|
+
cJSON_Delete(obj);
|
|
51
|
+
if (rc == TF_OK) st->audit_emitted++;
|
|
52
|
+
return rc;
|
|
53
|
+
}
|
|
54
|
+
|
|
20
55
|
static int filter_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
21
56
|
tf_side_channels *side) {
|
|
22
57
|
filter_state *st = self->state;
|
|
@@ -25,55 +60,36 @@ static int filter_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
|
25
60
|
/* Create output batch with same schema */
|
|
26
61
|
tf_batch *ob = tf_batch_create(in->n_cols, in->n_rows);
|
|
27
62
|
if (!ob) return TF_ERROR;
|
|
28
|
-
|
|
29
|
-
|
|
63
|
+
if (tf_batch_clone_schema(ob, in) != TF_OK) {
|
|
64
|
+
tf_batch_free(ob);
|
|
65
|
+
return TF_ERROR;
|
|
30
66
|
}
|
|
31
67
|
|
|
32
68
|
/* Filter rows */
|
|
33
69
|
size_t out_row = 0;
|
|
34
70
|
for (size_t r = 0; r < in->n_rows; r++) {
|
|
71
|
+
st->row_index++;
|
|
35
72
|
bool keep = false;
|
|
36
|
-
|
|
37
|
-
if (!keep)
|
|
73
|
+
int eval_ok = tf_expr_eval(st->expr, in, r, &keep) == TF_OK;
|
|
74
|
+
if (!eval_ok || !keep) {
|
|
75
|
+
if (filter_emit_drop_audit(st, in, r, side,
|
|
76
|
+
eval_ok ? "predicate_false" : "predicate_error") != TF_OK) {
|
|
77
|
+
tf_batch_free(ob);
|
|
78
|
+
return TF_ERROR;
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
38
82
|
|
|
39
|
-
if (
|
|
83
|
+
if (tf_batch_copy_row(ob, out_row, in, r) != TF_OK) {
|
|
40
84
|
tf_batch_free(ob);
|
|
41
85
|
return TF_ERROR;
|
|
42
86
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (tf_batch_is_null(in, r, c)) {
|
|
47
|
-
tf_batch_set_null(ob, out_row, c);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
switch (in->col_types[c]) {
|
|
51
|
-
case TF_TYPE_BOOL:
|
|
52
|
-
tf_batch_set_bool(ob, out_row, c, tf_batch_get_bool(in, r, c));
|
|
53
|
-
break;
|
|
54
|
-
case TF_TYPE_INT64:
|
|
55
|
-
tf_batch_set_int64(ob, out_row, c, tf_batch_get_int64(in, r, c));
|
|
56
|
-
break;
|
|
57
|
-
case TF_TYPE_FLOAT64:
|
|
58
|
-
tf_batch_set_float64(ob, out_row, c, tf_batch_get_float64(in, r, c));
|
|
59
|
-
break;
|
|
60
|
-
case TF_TYPE_STRING:
|
|
61
|
-
tf_batch_set_string(ob, out_row, c, tf_batch_get_string(in, r, c));
|
|
62
|
-
break;
|
|
63
|
-
case TF_TYPE_DATE:
|
|
64
|
-
tf_batch_set_date(ob, out_row, c, tf_batch_get_date(in, r, c));
|
|
65
|
-
break;
|
|
66
|
-
case TF_TYPE_TIMESTAMP:
|
|
67
|
-
tf_batch_set_timestamp(ob, out_row, c, tf_batch_get_timestamp(in, r, c));
|
|
68
|
-
break;
|
|
69
|
-
default:
|
|
70
|
-
tf_batch_set_null(ob, out_row, c);
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
87
|
+
if (tf_batch_expose_row(ob, out_row) != TF_OK) {
|
|
88
|
+
tf_batch_free(ob);
|
|
89
|
+
return TF_ERROR;
|
|
73
90
|
}
|
|
74
91
|
out_row++;
|
|
75
92
|
}
|
|
76
|
-
ob->n_rows = out_row;
|
|
77
93
|
|
|
78
94
|
st->rows_in += in->n_rows;
|
|
79
95
|
st->rows_out += out_row;
|
|
@@ -82,9 +98,12 @@ static int filter_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
|
82
98
|
if (side && side->stats) {
|
|
83
99
|
char stats_buf[128];
|
|
84
100
|
snprintf(stats_buf, sizeof(stats_buf),
|
|
85
|
-
"{\"op\":\"filter\",\"rows_in\":%zu,\"rows_out\":%zu}
|
|
101
|
+
"{\"op\":\"filter\",\"rows_in\":%zu,\"rows_out\":%zu}",
|
|
86
102
|
in->n_rows, out_row);
|
|
87
|
-
|
|
103
|
+
if (tf_buffer_write_line(side->stats, stats_buf) != TF_OK) {
|
|
104
|
+
tf_batch_free(ob);
|
|
105
|
+
return TF_ERROR;
|
|
106
|
+
}
|
|
88
107
|
}
|
|
89
108
|
|
|
90
109
|
if (out_row > 0) {
|
|
@@ -105,6 +124,8 @@ static void filter_destroy(tf_step *self) {
|
|
|
105
124
|
filter_state *st = self->state;
|
|
106
125
|
if (st) {
|
|
107
126
|
tf_expr_free(st->expr);
|
|
127
|
+
free(st->expr_text);
|
|
128
|
+
tf_audit_options_free(&st->audit_opts);
|
|
108
129
|
free(st);
|
|
109
130
|
}
|
|
110
131
|
free(self);
|
|
@@ -121,9 +142,37 @@ tf_step *tf_filter_create(const cJSON *args) {
|
|
|
121
142
|
filter_state *st = calloc(1, sizeof(filter_state));
|
|
122
143
|
if (!st) { tf_expr_free(expr); return NULL; }
|
|
123
144
|
st->expr = expr;
|
|
145
|
+
st->expr_text = strdup(expr_json->valuestring);
|
|
146
|
+
st->audit_limit = 1000;
|
|
147
|
+
tf_audit_options_init(&st->audit_opts, 1);
|
|
148
|
+
cJSON *audit_json = cJSON_GetObjectItemCaseSensitive(args, "audit");
|
|
149
|
+
st->audit = cJSON_IsTrue(audit_json) ? 1 : 0;
|
|
150
|
+
cJSON *audit_limit_json = cJSON_GetObjectItemCaseSensitive(args, "audit_limit");
|
|
151
|
+
if (!audit_limit_json) audit_limit_json = cJSON_GetObjectItemCaseSensitive(args, "auditLimit");
|
|
152
|
+
if (audit_limit_json) {
|
|
153
|
+
size_t parsed_limit = 0;
|
|
154
|
+
if (tf_json_get_size_arg_any(args, "audit_limit", "auditLimit",
|
|
155
|
+
1, TF_MAX_AUDIT_RECORDS,
|
|
156
|
+
&parsed_limit, "filter") < 0) {
|
|
157
|
+
tf_expr_free(expr);
|
|
158
|
+
free(st->expr_text);
|
|
159
|
+
tf_audit_options_free(&st->audit_opts);
|
|
160
|
+
free(st);
|
|
161
|
+
return NULL;
|
|
162
|
+
}
|
|
163
|
+
st->audit_limit = parsed_limit;
|
|
164
|
+
}
|
|
165
|
+
if (tf_audit_options_parse(&st->audit_opts, args, "filter") != TF_OK) {
|
|
166
|
+
tf_expr_free(expr);
|
|
167
|
+
free(st->expr_text);
|
|
168
|
+
tf_audit_options_free(&st->audit_opts);
|
|
169
|
+
free(st);
|
|
170
|
+
return NULL;
|
|
171
|
+
}
|
|
172
|
+
if (!st->expr_text) { tf_expr_free(expr); tf_audit_options_free(&st->audit_opts); free(st); return NULL; }
|
|
124
173
|
|
|
125
|
-
tf_step *step =
|
|
126
|
-
if (!step) { tf_expr_free(expr); free(st); return NULL; }
|
|
174
|
+
tf_step *step = calloc(1, sizeof(tf_step));
|
|
175
|
+
if (!step) { tf_expr_free(expr); free(st->expr_text); tf_audit_options_free(&st->audit_opts); free(st); return NULL; }
|
|
127
176
|
step->process = filter_process;
|
|
128
177
|
step->flush = filter_flush;
|
|
129
178
|
step->destroy = filter_destroy;
|