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
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* op_unpivot.c — Wide to long. Adds variable + value columns, multiplies rows.
|
|
3
|
+
*
|
|
4
|
+
* Config: {"columns": ["q1", "q2", "q3"]}
|
|
5
|
+
* Keeps non-listed columns, melts listed columns into variable/value pairs.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include "internal.h"
|
|
9
|
+
#include "cJSON.h"
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
#include <stdio.h>
|
|
13
|
+
|
|
14
|
+
typedef struct {
|
|
15
|
+
char **cols;
|
|
16
|
+
size_t n_cols;
|
|
17
|
+
size_t max_output_rows_per_input_row;
|
|
18
|
+
size_t max_output_rows_per_batch;
|
|
19
|
+
} unpivot_state;
|
|
20
|
+
|
|
21
|
+
static int unpivot_set_cap_error(const char *name, size_t limit) {
|
|
22
|
+
char msg[160];
|
|
23
|
+
snprintf(msg, sizeof(msg), "unpivot: %s=%zu exceeded", name, limit);
|
|
24
|
+
tf_set_last_error(msg);
|
|
25
|
+
return TF_ERROR;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static int unpivot_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
29
|
+
tf_side_channels *side) {
|
|
30
|
+
(void)side;
|
|
31
|
+
unpivot_state *st = self->state;
|
|
32
|
+
*out = NULL;
|
|
33
|
+
|
|
34
|
+
/* Determine which columns are value columns and which are id columns */
|
|
35
|
+
int *is_value = tf_callocarray_checked(in->n_cols ? in->n_cols : 1, sizeof(int));
|
|
36
|
+
if (!is_value) return TF_ERROR;
|
|
37
|
+
size_t n_value = 0;
|
|
38
|
+
for (size_t c = 0; c < in->n_cols; c++) {
|
|
39
|
+
for (size_t k = 0; k < st->n_cols; k++) {
|
|
40
|
+
if (strcmp(in->col_names[c], st->cols[k]) == 0) {
|
|
41
|
+
is_value[c] = 1;
|
|
42
|
+
n_value++;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
size_t n_id = in->n_cols - n_value;
|
|
48
|
+
if (n_value == 0) { free(is_value); return TF_OK; }
|
|
49
|
+
|
|
50
|
+
/* Output: id columns + "variable" + "value" */
|
|
51
|
+
size_t out_n_cols = 0;
|
|
52
|
+
if (tf_size_add(n_id, 2, &out_n_cols) != TF_OK) { free(is_value); return TF_ERROR; }
|
|
53
|
+
if (n_value > st->max_output_rows_per_input_row) {
|
|
54
|
+
unpivot_set_cap_error("max_output_rows_per_input_row", st->max_output_rows_per_input_row);
|
|
55
|
+
free(is_value);
|
|
56
|
+
return TF_ERROR;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
size_t *id_cols = NULL;
|
|
60
|
+
if (n_id > 0) {
|
|
61
|
+
id_cols = tf_callocarray_checked(n_id, sizeof(size_t));
|
|
62
|
+
if (!id_cols) { free(is_value); return TF_ERROR; }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
size_t max_rows = 0;
|
|
66
|
+
if (tf_size_mul(in->n_rows, n_value, &max_rows) != TF_OK ||
|
|
67
|
+
max_rows > st->max_output_rows_per_batch) {
|
|
68
|
+
unpivot_set_cap_error("max_output_rows_per_batch", st->max_output_rows_per_batch);
|
|
69
|
+
free(id_cols);
|
|
70
|
+
free(is_value);
|
|
71
|
+
return TF_ERROR;
|
|
72
|
+
}
|
|
73
|
+
tf_batch *ob = tf_batch_create(out_n_cols, max_rows > 0 ? max_rows : 16);
|
|
74
|
+
if (!ob) { free(id_cols); free(is_value); return TF_ERROR; }
|
|
75
|
+
|
|
76
|
+
size_t oc = 0;
|
|
77
|
+
for (size_t c = 0; c < in->n_cols; c++) {
|
|
78
|
+
if (!is_value[c]) {
|
|
79
|
+
id_cols[oc] = c;
|
|
80
|
+
if (tf_batch_set_schema(ob, oc++, in->col_names[c], in->col_types[c]) != TF_OK) goto fail;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (tf_batch_set_schema(ob, oc, "variable", TF_TYPE_STRING) != TF_OK ||
|
|
84
|
+
tf_batch_set_schema(ob, oc + 1, "value", TF_TYPE_STRING) != TF_OK) goto fail;
|
|
85
|
+
|
|
86
|
+
size_t out_row = 0;
|
|
87
|
+
for (size_t r = 0; r < in->n_rows; r++) {
|
|
88
|
+
for (size_t c = 0; c < in->n_cols; c++) {
|
|
89
|
+
if (!is_value[c]) continue;
|
|
90
|
+
|
|
91
|
+
if (out_row >= st->max_output_rows_per_batch) {
|
|
92
|
+
unpivot_set_cap_error("max_output_rows_per_batch", st->max_output_rows_per_batch);
|
|
93
|
+
goto fail;
|
|
94
|
+
}
|
|
95
|
+
size_t need_rows = 0;
|
|
96
|
+
if (tf_size_add(out_row, 1, &need_rows) != TF_OK ||
|
|
97
|
+
tf_batch_ensure_capacity(ob, need_rows) != TF_OK) goto fail;
|
|
98
|
+
|
|
99
|
+
/* Copy id columns */
|
|
100
|
+
if (n_id > 0 &&
|
|
101
|
+
tf_batch_copy_selected_row(ob, out_row, in, r, id_cols, n_id) != TF_OK) goto fail;
|
|
102
|
+
|
|
103
|
+
/* Set variable name */
|
|
104
|
+
if (tf_batch_set_string(ob, out_row, n_id, in->col_names[c]) != TF_OK) goto fail;
|
|
105
|
+
|
|
106
|
+
if (tf_batch_copy_cell_as_string(ob, out_row, n_id + 1, in, r, c) != TF_OK)
|
|
107
|
+
goto fail;
|
|
108
|
+
|
|
109
|
+
if (tf_batch_expose_row(ob, out_row) != TF_OK) goto fail;
|
|
110
|
+
out_row++;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
free(id_cols);
|
|
115
|
+
free(is_value);
|
|
116
|
+
if (out_row > 0) *out = ob;
|
|
117
|
+
else tf_batch_free(ob);
|
|
118
|
+
return TF_OK;
|
|
119
|
+
|
|
120
|
+
fail:
|
|
121
|
+
free(id_cols);
|
|
122
|
+
free(is_value);
|
|
123
|
+
tf_batch_free(ob);
|
|
124
|
+
return TF_ERROR;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static int unpivot_flush(tf_step *self, tf_batch **out, tf_side_channels *side) {
|
|
128
|
+
(void)self; (void)side; *out = NULL; return TF_OK;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static void unpivot_state_free(unpivot_state *st) {
|
|
132
|
+
if (st) {
|
|
133
|
+
if (st->cols) {
|
|
134
|
+
for (size_t i = 0; i < st->n_cols; i++) free(st->cols[i]);
|
|
135
|
+
}
|
|
136
|
+
free(st->cols); free(st);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static void unpivot_destroy(tf_step *self) {
|
|
141
|
+
unpivot_state_free(self->state);
|
|
142
|
+
free(self);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
tf_step *tf_unpivot_create(const cJSON *args) {
|
|
146
|
+
if (!args) return NULL;
|
|
147
|
+
cJSON *columns = cJSON_GetObjectItemCaseSensitive(args, "columns");
|
|
148
|
+
if (!columns || !cJSON_IsArray(columns)) {
|
|
149
|
+
tf_set_last_error("unpivot: columns must be a non-empty array");
|
|
150
|
+
return NULL;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
int n = cJSON_GetArraySize(columns);
|
|
154
|
+
if (n <= 0) {
|
|
155
|
+
tf_set_last_error("unpivot: columns must be a non-empty array");
|
|
156
|
+
return NULL;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
unpivot_state *st = calloc(1, sizeof(unpivot_state));
|
|
160
|
+
if (!st) return NULL;
|
|
161
|
+
st->max_output_rows_per_input_row = TF_MAX_EXPANDING_ROWS_PER_INPUT;
|
|
162
|
+
st->max_output_rows_per_batch = TF_MAX_OUTPUT_ROWS_PER_BATCH;
|
|
163
|
+
|
|
164
|
+
size_t parsed_size = 0;
|
|
165
|
+
int has_size = tf_json_get_size_arg(args, "max_output_rows_per_input_row", 1, TF_MAX_EXPANDING_ROWS_PER_INPUT, &parsed_size, "unpivot");
|
|
166
|
+
if (has_size < 0) { free(st); return NULL; }
|
|
167
|
+
if (has_size > 0) st->max_output_rows_per_input_row = parsed_size;
|
|
168
|
+
has_size = tf_json_get_size_arg(args, "max_output_rows_per_batch", 1, TF_MAX_OUTPUT_ROWS_PER_BATCH, &parsed_size, "unpivot");
|
|
169
|
+
if (has_size < 0) { free(st); return NULL; }
|
|
170
|
+
if (has_size > 0) st->max_output_rows_per_batch = parsed_size;
|
|
171
|
+
|
|
172
|
+
st->cols = tf_callocarray_checked((size_t)n, sizeof(char *));
|
|
173
|
+
if (!st->cols) { free(st); return NULL; }
|
|
174
|
+
st->n_cols = (size_t)n;
|
|
175
|
+
for (int i = 0; i < n; i++) {
|
|
176
|
+
cJSON *item = cJSON_GetArrayItem(columns, i);
|
|
177
|
+
if (!cJSON_IsString(item) || !item->valuestring || item->valuestring[0] == '\0') {
|
|
178
|
+
tf_set_last_error("unpivot: column names must be non-empty strings");
|
|
179
|
+
unpivot_state_free(st);
|
|
180
|
+
return NULL;
|
|
181
|
+
}
|
|
182
|
+
st->cols[i] = strdup(item->valuestring);
|
|
183
|
+
if (!st->cols[i]) { unpivot_state_free(st); return NULL; }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
tf_step *step = calloc(1, sizeof(tf_step));
|
|
187
|
+
if (!step) { unpivot_state_free(st); return NULL; }
|
|
188
|
+
step->process = unpivot_process;
|
|
189
|
+
step->flush = unpivot_flush;
|
|
190
|
+
step->destroy = unpivot_destroy;
|
|
191
|
+
step->state = st;
|
|
192
|
+
return step;
|
|
193
|
+
}
|