tranfi 0.0.2 → 0.2.0
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 -21
- package/NOTICE +8 -0
- package/README.md +627 -0
- package/app/assets/index-6quYZ5Ap.css +5 -0
- package/app/assets/index-BIAIKnrp.js +160 -0
- package/app/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- package/app/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- package/app/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- package/app/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- package/app/index.html +13 -0
- package/binding.gyp +121 -0
- package/csrc/arena.c +93 -0
- package/csrc/batch.c +976 -0
- package/csrc/buffer.c +154 -0
- package/csrc/cJSON.c +3386 -0
- package/csrc/cJSON.h +316 -0
- package/csrc/codec_csv.c +1951 -0
- package/csrc/codec_jsonl.c +1086 -0
- package/csrc/codec_table.c +248 -0
- package/csrc/codec_text.c +447 -0
- package/csrc/compiler.c +130 -0
- package/csrc/config.h +21 -0
- package/csrc/date_utils.h +94 -0
- package/csrc/dsl.c +5417 -0
- package/csrc/dsl.h +22 -0
- package/csrc/expr.c +1553 -0
- package/csrc/expr.h +58 -0
- package/csrc/internal.h +539 -0
- package/csrc/ir.c +166 -0
- package/csrc/ir.h +208 -0
- package/csrc/ir_schema.c +75 -0
- package/csrc/ir_serialize.c +166 -0
- package/csrc/ir_sql.c +1822 -0
- package/csrc/ir_validate.c +576 -0
- package/csrc/json_path.c +210 -0
- package/csrc/main.c +1241 -0
- package/csrc/memory_estimate.c +477 -0
- package/csrc/op_acf.c +283 -0
- package/csrc/op_across.c +477 -0
- package/csrc/op_anomaly.c +255 -0
- package/csrc/op_assert.c +761 -0
- package/csrc/op_bin.c +248 -0
- package/csrc/op_cast.c +523 -0
- package/csrc/op_clip.c +99 -0
- package/csrc/op_date_trunc.c +355 -0
- package/csrc/op_datetime.c +394 -0
- package/csrc/op_derive.c +216 -0
- package/csrc/op_diff.c +250 -0
- package/csrc/op_ewma.c +222 -0
- package/csrc/op_explode.c +206 -0
- package/csrc/op_fill_down.c +235 -0
- package/csrc/op_fill_null.c +268 -0
- package/csrc/op_filter.c +181 -0
- package/csrc/op_frequency.c +721 -0
- package/csrc/op_grep.c +181 -0
- package/csrc/op_group_agg.c +1956 -0
- package/csrc/op_hash.c +159 -0
- package/csrc/op_head.c +84 -0
- package/csrc/op_interpolate.c +445 -0
- package/csrc/op_join.c +2902 -0
- 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 +419 -0
- package/csrc/op_lag.c +181 -0
- package/csrc/op_lead.c +242 -0
- package/csrc/op_normalize.c +510 -0
- package/csrc/op_onehot.c +457 -0
- package/csrc/op_pivot.c +1754 -0
- package/csrc/op_quarantine.c +189 -0
- package/csrc/op_registry.c +3044 -0
- package/csrc/op_rename.c +129 -0
- package/csrc/op_replace.c +354 -0
- package/csrc/op_rleid.c +297 -0
- package/csrc/op_rowid.c +559 -0
- package/csrc/op_sample.c +158 -0
- package/csrc/op_schema.c +1341 -0
- package/csrc/op_schema_infer.c +252 -0
- package/csrc/op_select.c +340 -0
- package/csrc/op_set.c +3449 -0
- package/csrc/op_skip.c +95 -0
- package/csrc/op_sort.c +819 -0
- package/csrc/op_source_name.c +120 -0
- package/csrc/op_split.c +151 -0
- package/csrc/op_split_data.c +119 -0
- package/csrc/op_stack.c +271 -0
- package/csrc/op_stats.c +875 -0
- package/csrc/op_step.c +333 -0
- package/csrc/op_tail.c +105 -0
- package/csrc/op_tee.c +338 -0
- package/csrc/op_top.c +357 -0
- package/csrc/op_trim.c +138 -0
- package/csrc/op_unique.c +1343 -0
- package/csrc/op_unpivot.c +193 -0
- package/csrc/op_validate.c +648 -0
- package/csrc/op_window.c +591 -0
- package/csrc/path_policy.c +85 -0
- package/csrc/pipeline.c +1088 -0
- package/csrc/recipes.c +104 -0
- package/csrc/recipes.h +27 -0
- package/csrc/report.c +506 -0
- package/csrc/report.h +22 -0
- package/csrc/selector.c +1097 -0
- package/csrc/size_utils.c +348 -0
- package/csrc/spill.c +317 -0
- package/csrc/spill.h +21 -0
- package/csrc/tranfi.h +291 -0
- 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 +218 -0
- package/napi_api.c +534 -0
- package/napi_transform.c +1648 -0
- package/napi_transform.h +8 -0
- package/package.json +64 -59
- package/scripts/install-native.js +76 -0
- package/scripts/prepack.js +64 -0
- package/scripts/sync-csrc.js +23 -0
- package/src/cli.js +190 -0
- package/src/engines/duckdb.js +142 -0
- package/src/index.js +925 -0
- package/src/memory_policy.js +411 -0
- package/src/native.js +18 -0
- package/src/pipeline.js +709 -0
- package/src/recipe_json.js +80 -0
- package/src/server.js +279 -0
- package/src/transform.js +403 -0
- package/src/transform_error.js +10 -0
- package/src/wasm.js +21 -0
- package/wasm/index.js +732 -0
- package/wasm/package.json +1 -0
- package/wasm/tranfi_core.js +0 -0
- package/wasm/transform.js +1156 -0
- package/wasm/worker.js +786 -0
- package/dist/bundle.js +0 -1
- package/index.html +0 -18
- package/src/app.css +0 -169
- package/src/app.js +0 -203
- package/src/app.vue +0 -250
- package/src/bulma-input.vue +0 -110
- package/src/common-inputs.js +0 -28
- package/src/main.js +0 -20
- package/src/transforms.js +0 -166
- package/webpack.config.js +0 -108
package/csrc/op_lead.c
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* op_lead.c - Bounded lookahead.
|
|
3
|
+
*
|
|
4
|
+
* Config: {"column": "price", "offset": 1, "result": "next_price"}
|
|
5
|
+
*
|
|
6
|
+
* Delays output by `offset` rows so the appended value can come from rows ahead
|
|
7
|
+
* of the current row. On flush, emits the remaining pending rows with NULL lead
|
|
8
|
+
* values. Pending state is bounded by `offset` rows.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#include "internal.h"
|
|
12
|
+
#include "cJSON.h"
|
|
13
|
+
#include <stdlib.h>
|
|
14
|
+
#include <string.h>
|
|
15
|
+
#include <stdio.h>
|
|
16
|
+
|
|
17
|
+
typedef struct {
|
|
18
|
+
char *column;
|
|
19
|
+
char *result;
|
|
20
|
+
size_t offset;
|
|
21
|
+
tf_batch *pending;
|
|
22
|
+
} lead_state;
|
|
23
|
+
|
|
24
|
+
static int lead_set_error(tf_side_channels *side, const char *msg) {
|
|
25
|
+
return tf_side_write_error(side, msg);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static const tf_batch *source_at(const lead_state *st, const tf_batch *in,
|
|
29
|
+
size_t idx, size_t pend_count, size_t *row) {
|
|
30
|
+
if (idx < pend_count) {
|
|
31
|
+
*row = idx;
|
|
32
|
+
return st->pending;
|
|
33
|
+
}
|
|
34
|
+
*row = idx - pend_count;
|
|
35
|
+
return in;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static int copy_source_row(tf_batch *dst, size_t dst_row, const lead_state *st,
|
|
39
|
+
const tf_batch *in, size_t idx, size_t pend_count) {
|
|
40
|
+
size_t src_row = 0;
|
|
41
|
+
const tf_batch *src = source_at(st, in, idx, pend_count, &src_row);
|
|
42
|
+
return tf_batch_copy_row(dst, dst_row, src, src_row);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static int lead_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
46
|
+
tf_side_channels *side) {
|
|
47
|
+
lead_state *st = self->state;
|
|
48
|
+
*out = NULL;
|
|
49
|
+
|
|
50
|
+
int ci = tf_batch_col_index(in, st->column);
|
|
51
|
+
if (ci < 0) {
|
|
52
|
+
char msg[256];
|
|
53
|
+
snprintf(msg, sizeof(msg), "lead: column '%s' not found", st->column);
|
|
54
|
+
if (lead_set_error(side, msg) != TF_OK) return TF_ERROR;
|
|
55
|
+
return TF_ERROR;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
size_t pend_count = st->pending ? st->pending->n_rows : 0;
|
|
59
|
+
size_t total = pend_count + in->n_rows;
|
|
60
|
+
|
|
61
|
+
if (total <= st->offset) {
|
|
62
|
+
tf_batch *new_pend = tf_batch_create(in->n_cols, total);
|
|
63
|
+
if (!new_pend) return TF_ERROR;
|
|
64
|
+
if (tf_batch_clone_schema(new_pend, in) != TF_OK) {
|
|
65
|
+
tf_batch_free(new_pend);
|
|
66
|
+
return TF_ERROR;
|
|
67
|
+
}
|
|
68
|
+
size_t row = 0;
|
|
69
|
+
for (size_t r = 0; r < pend_count; r++) {
|
|
70
|
+
if (tf_batch_copy_row(new_pend, row++, st->pending, r) != TF_OK) {
|
|
71
|
+
tf_batch_free(new_pend);
|
|
72
|
+
return TF_ERROR;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (size_t r = 0; r < in->n_rows; r++) {
|
|
76
|
+
if (tf_batch_copy_row(new_pend, row++, in, r) != TF_OK) {
|
|
77
|
+
tf_batch_free(new_pend);
|
|
78
|
+
return TF_ERROR;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (total > 0 && tf_batch_expose_row(new_pend, total - 1) != TF_OK) {
|
|
82
|
+
tf_batch_free(new_pend);
|
|
83
|
+
return TF_ERROR;
|
|
84
|
+
}
|
|
85
|
+
if (st->pending) tf_batch_free(st->pending);
|
|
86
|
+
st->pending = new_pend;
|
|
87
|
+
return TF_OK;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
size_t emit_count = total - st->offset;
|
|
91
|
+
const char *extra_names[1] = {st->result};
|
|
92
|
+
tf_type extra_types[1] = {in->col_types[ci]};
|
|
93
|
+
tf_batch *ob = tf_batch_create(in->n_cols + 1, emit_count);
|
|
94
|
+
if (!ob) return TF_ERROR;
|
|
95
|
+
if (tf_batch_clone_with_extra_cols(ob, in, extra_names, extra_types, 1) != TF_OK) {
|
|
96
|
+
tf_batch_free(ob);
|
|
97
|
+
return TF_ERROR;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (size_t i = 0; i < emit_count; i++) {
|
|
101
|
+
if (copy_source_row(ob, i, st, in, i, pend_count) != TF_OK) {
|
|
102
|
+
tf_batch_free(ob);
|
|
103
|
+
return TF_ERROR;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
size_t lead_row = 0;
|
|
107
|
+
const tf_batch *lead_src = source_at(st, in, i + st->offset, pend_count, &lead_row);
|
|
108
|
+
int lead_ci = tf_batch_col_index(lead_src, st->column);
|
|
109
|
+
if (lead_ci < 0) {
|
|
110
|
+
tf_batch_free(ob);
|
|
111
|
+
if (lead_set_error(side, "lead: buffered schema lost selected column") != TF_OK) return TF_ERROR;
|
|
112
|
+
return TF_ERROR;
|
|
113
|
+
}
|
|
114
|
+
if (tf_batch_copy_cell(ob, i, in->n_cols, lead_src, lead_row, (size_t)lead_ci) != TF_OK) {
|
|
115
|
+
tf_batch_free(ob);
|
|
116
|
+
return TF_ERROR;
|
|
117
|
+
}
|
|
118
|
+
if (tf_batch_expose_row(ob, i) != TF_OK) {
|
|
119
|
+
tf_batch_free(ob);
|
|
120
|
+
return TF_ERROR;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
tf_batch *new_pend = tf_batch_create(in->n_cols, st->offset);
|
|
125
|
+
if (!new_pend) { tf_batch_free(ob); return TF_ERROR; }
|
|
126
|
+
if (tf_batch_clone_schema(new_pend, in) != TF_OK) {
|
|
127
|
+
tf_batch_free(new_pend);
|
|
128
|
+
tf_batch_free(ob);
|
|
129
|
+
return TF_ERROR;
|
|
130
|
+
}
|
|
131
|
+
for (size_t i = 0; i < st->offset; i++) {
|
|
132
|
+
size_t src_idx = total - st->offset + i;
|
|
133
|
+
if (copy_source_row(new_pend, i, st, in, src_idx, pend_count) != TF_OK) {
|
|
134
|
+
tf_batch_free(new_pend);
|
|
135
|
+
tf_batch_free(ob);
|
|
136
|
+
return TF_ERROR;
|
|
137
|
+
}
|
|
138
|
+
if (tf_batch_expose_row(new_pend, i) != TF_OK) {
|
|
139
|
+
tf_batch_free(new_pend);
|
|
140
|
+
tf_batch_free(ob);
|
|
141
|
+
return TF_ERROR;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (st->pending) tf_batch_free(st->pending);
|
|
146
|
+
st->pending = new_pend;
|
|
147
|
+
*out = ob;
|
|
148
|
+
return TF_OK;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static int lead_flush(tf_step *self, tf_batch **out, tf_side_channels *side) {
|
|
152
|
+
lead_state *st = self->state;
|
|
153
|
+
*out = NULL;
|
|
154
|
+
|
|
155
|
+
if (!st->pending || st->pending->n_rows == 0) return TF_OK;
|
|
156
|
+
|
|
157
|
+
tf_batch *pend = st->pending;
|
|
158
|
+
int ci = tf_batch_col_index(pend, st->column);
|
|
159
|
+
if (ci < 0) {
|
|
160
|
+
if (lead_set_error(side, "lead: buffered schema lost selected column") != TF_OK) return TF_ERROR;
|
|
161
|
+
return TF_ERROR;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const char *extra_names[1] = {st->result};
|
|
165
|
+
tf_type extra_types[1] = {pend->col_types[ci]};
|
|
166
|
+
tf_batch *ob = tf_batch_create(pend->n_cols + 1, pend->n_rows);
|
|
167
|
+
if (!ob) return TF_ERROR;
|
|
168
|
+
if (tf_batch_clone_with_extra_cols(ob, pend, extra_names, extra_types, 1) != TF_OK) {
|
|
169
|
+
tf_batch_free(ob);
|
|
170
|
+
return TF_ERROR;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for (size_t r = 0; r < pend->n_rows; r++) {
|
|
174
|
+
if (tf_batch_copy_row(ob, r, pend, r) != TF_OK) {
|
|
175
|
+
tf_batch_free(ob);
|
|
176
|
+
return TF_ERROR;
|
|
177
|
+
}
|
|
178
|
+
if (tf_batch_set_null(ob, r, pend->n_cols) != TF_OK) {
|
|
179
|
+
tf_batch_free(ob);
|
|
180
|
+
return TF_ERROR;
|
|
181
|
+
}
|
|
182
|
+
if (tf_batch_expose_row(ob, r) != TF_OK) {
|
|
183
|
+
tf_batch_free(ob);
|
|
184
|
+
return TF_ERROR;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
tf_batch_free(st->pending);
|
|
189
|
+
st->pending = NULL;
|
|
190
|
+
*out = ob;
|
|
191
|
+
return TF_OK;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
static void lead_destroy(tf_step *self) {
|
|
195
|
+
lead_state *st = self->state;
|
|
196
|
+
if (st) {
|
|
197
|
+
free(st->column);
|
|
198
|
+
free(st->result);
|
|
199
|
+
if (st->pending) tf_batch_free(st->pending);
|
|
200
|
+
free(st);
|
|
201
|
+
}
|
|
202
|
+
free(self);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
tf_step *tf_lead_create(const cJSON *args) {
|
|
206
|
+
if (!args) return NULL;
|
|
207
|
+
cJSON *col_j = cJSON_GetObjectItemCaseSensitive(args, "column");
|
|
208
|
+
if (!cJSON_IsString(col_j) || !col_j->valuestring[0]) return NULL;
|
|
209
|
+
|
|
210
|
+
lead_state *st = tf_callocarray_checked(1, sizeof(lead_state));
|
|
211
|
+
if (!st) return NULL;
|
|
212
|
+
st->column = tf_strdup_checked(col_j->valuestring);
|
|
213
|
+
if (!st->column) { free(st); return NULL; }
|
|
214
|
+
|
|
215
|
+
size_t offset = 1;
|
|
216
|
+
int has_offset = tf_json_get_size_arg(args, "offset",
|
|
217
|
+
1, TF_MAX_WINDOW_SIZE,
|
|
218
|
+
&offset, "lead");
|
|
219
|
+
if (has_offset < 0) { free(st->column); free(st); return NULL; }
|
|
220
|
+
st->offset = offset;
|
|
221
|
+
|
|
222
|
+
cJSON *res_j = cJSON_GetObjectItemCaseSensitive(args, "result");
|
|
223
|
+
if (cJSON_IsString(res_j) && res_j->valuestring[0]) {
|
|
224
|
+
st->result = tf_strdup_checked(res_j->valuestring);
|
|
225
|
+
} else {
|
|
226
|
+
st->result = tf_string_append_suffix_checked(st->column, "_lead");
|
|
227
|
+
}
|
|
228
|
+
if (!st->result) { free(st->column); free(st); return NULL; }
|
|
229
|
+
|
|
230
|
+
tf_step *step = tf_callocarray_checked(1, sizeof(tf_step));
|
|
231
|
+
if (!step) {
|
|
232
|
+
free(st->column);
|
|
233
|
+
free(st->result);
|
|
234
|
+
free(st);
|
|
235
|
+
return NULL;
|
|
236
|
+
}
|
|
237
|
+
step->process = lead_process;
|
|
238
|
+
step->flush = lead_flush;
|
|
239
|
+
step->destroy = lead_destroy;
|
|
240
|
+
step->state = st;
|
|
241
|
+
return step;
|
|
242
|
+
}
|