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.
Files changed (151) hide show
  1. package/LICENSE +177 -21
  2. package/NOTICE +8 -0
  3. package/README.md +627 -0
  4. package/app/assets/index-6quYZ5Ap.css +5 -0
  5. package/app/assets/index-BIAIKnrp.js +160 -0
  6. package/app/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
  7. package/app/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
  8. package/app/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
  9. package/app/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
  10. package/app/index.html +13 -0
  11. package/binding.gyp +121 -0
  12. package/csrc/arena.c +93 -0
  13. package/csrc/batch.c +976 -0
  14. package/csrc/buffer.c +154 -0
  15. package/csrc/cJSON.c +3386 -0
  16. package/csrc/cJSON.h +316 -0
  17. package/csrc/codec_csv.c +1951 -0
  18. package/csrc/codec_jsonl.c +1086 -0
  19. package/csrc/codec_table.c +248 -0
  20. package/csrc/codec_text.c +447 -0
  21. package/csrc/compiler.c +130 -0
  22. package/csrc/config.h +21 -0
  23. package/csrc/date_utils.h +94 -0
  24. package/csrc/dsl.c +5417 -0
  25. package/csrc/dsl.h +22 -0
  26. package/csrc/expr.c +1553 -0
  27. package/csrc/expr.h +58 -0
  28. package/csrc/internal.h +539 -0
  29. package/csrc/ir.c +166 -0
  30. package/csrc/ir.h +208 -0
  31. package/csrc/ir_schema.c +75 -0
  32. package/csrc/ir_serialize.c +166 -0
  33. package/csrc/ir_sql.c +1822 -0
  34. package/csrc/ir_validate.c +576 -0
  35. package/csrc/json_path.c +210 -0
  36. package/csrc/main.c +1241 -0
  37. package/csrc/memory_estimate.c +477 -0
  38. package/csrc/op_acf.c +283 -0
  39. package/csrc/op_across.c +477 -0
  40. package/csrc/op_anomaly.c +255 -0
  41. package/csrc/op_assert.c +761 -0
  42. package/csrc/op_bin.c +248 -0
  43. package/csrc/op_cast.c +523 -0
  44. package/csrc/op_clip.c +99 -0
  45. package/csrc/op_date_trunc.c +355 -0
  46. package/csrc/op_datetime.c +394 -0
  47. package/csrc/op_derive.c +216 -0
  48. package/csrc/op_diff.c +250 -0
  49. package/csrc/op_ewma.c +222 -0
  50. package/csrc/op_explode.c +206 -0
  51. package/csrc/op_fill_down.c +235 -0
  52. package/csrc/op_fill_null.c +268 -0
  53. package/csrc/op_filter.c +181 -0
  54. package/csrc/op_frequency.c +721 -0
  55. package/csrc/op_grep.c +181 -0
  56. package/csrc/op_group_agg.c +1956 -0
  57. package/csrc/op_hash.c +159 -0
  58. package/csrc/op_head.c +84 -0
  59. package/csrc/op_interpolate.c +445 -0
  60. package/csrc/op_join.c +2902 -0
  61. package/csrc/op_json_extract.c +227 -0
  62. package/csrc/op_json_filter.c +384 -0
  63. package/csrc/op_json_flatten.c +293 -0
  64. package/csrc/op_json_schema.c +503 -0
  65. package/csrc/op_label_encode.c +419 -0
  66. package/csrc/op_lag.c +181 -0
  67. package/csrc/op_lead.c +242 -0
  68. package/csrc/op_normalize.c +510 -0
  69. package/csrc/op_onehot.c +457 -0
  70. package/csrc/op_pivot.c +1754 -0
  71. package/csrc/op_quarantine.c +189 -0
  72. package/csrc/op_registry.c +3044 -0
  73. package/csrc/op_rename.c +129 -0
  74. package/csrc/op_replace.c +354 -0
  75. package/csrc/op_rleid.c +297 -0
  76. package/csrc/op_rowid.c +559 -0
  77. package/csrc/op_sample.c +158 -0
  78. package/csrc/op_schema.c +1341 -0
  79. package/csrc/op_schema_infer.c +252 -0
  80. package/csrc/op_select.c +340 -0
  81. package/csrc/op_set.c +3449 -0
  82. package/csrc/op_skip.c +95 -0
  83. package/csrc/op_sort.c +819 -0
  84. package/csrc/op_source_name.c +120 -0
  85. package/csrc/op_split.c +151 -0
  86. package/csrc/op_split_data.c +119 -0
  87. package/csrc/op_stack.c +271 -0
  88. package/csrc/op_stats.c +875 -0
  89. package/csrc/op_step.c +333 -0
  90. package/csrc/op_tail.c +105 -0
  91. package/csrc/op_tee.c +338 -0
  92. package/csrc/op_top.c +357 -0
  93. package/csrc/op_trim.c +138 -0
  94. package/csrc/op_unique.c +1343 -0
  95. package/csrc/op_unpivot.c +193 -0
  96. package/csrc/op_validate.c +648 -0
  97. package/csrc/op_window.c +591 -0
  98. package/csrc/path_policy.c +85 -0
  99. package/csrc/pipeline.c +1088 -0
  100. package/csrc/recipes.c +104 -0
  101. package/csrc/recipes.h +27 -0
  102. package/csrc/report.c +506 -0
  103. package/csrc/report.h +22 -0
  104. package/csrc/selector.c +1097 -0
  105. package/csrc/size_utils.c +348 -0
  106. package/csrc/spill.c +317 -0
  107. package/csrc/spill.h +21 -0
  108. package/csrc/tranfi.h +291 -0
  109. package/csrc/transform.h +209 -0
  110. package/csrc/transform_api.c +2237 -0
  111. package/csrc/transform_categorical.c +923 -0
  112. package/csrc/transform_internal.h +472 -0
  113. package/csrc/transform_json.c +3812 -0
  114. package/csrc/transform_numeric.c +1966 -0
  115. package/csrc/transform_sha256.c +154 -0
  116. package/csrc/transform_wasm.h +162 -0
  117. package/csrc/transform_wasm_api.c +1373 -0
  118. package/csrc/wasm_api.c +218 -0
  119. package/napi_api.c +534 -0
  120. package/napi_transform.c +1648 -0
  121. package/napi_transform.h +8 -0
  122. package/package.json +64 -59
  123. package/scripts/install-native.js +76 -0
  124. package/scripts/prepack.js +64 -0
  125. package/scripts/sync-csrc.js +23 -0
  126. package/src/cli.js +190 -0
  127. package/src/engines/duckdb.js +142 -0
  128. package/src/index.js +925 -0
  129. package/src/memory_policy.js +411 -0
  130. package/src/native.js +18 -0
  131. package/src/pipeline.js +709 -0
  132. package/src/recipe_json.js +80 -0
  133. package/src/server.js +279 -0
  134. package/src/transform.js +403 -0
  135. package/src/transform_error.js +10 -0
  136. package/src/wasm.js +21 -0
  137. package/wasm/index.js +732 -0
  138. package/wasm/package.json +1 -0
  139. package/wasm/tranfi_core.js +0 -0
  140. package/wasm/transform.js +1156 -0
  141. package/wasm/worker.js +786 -0
  142. package/dist/bundle.js +0 -1
  143. package/index.html +0 -18
  144. package/src/app.css +0 -169
  145. package/src/app.js +0 -203
  146. package/src/app.vue +0 -250
  147. package/src/bulma-input.vue +0 -110
  148. package/src/common-inputs.js +0 -28
  149. package/src/main.js +0 -20
  150. package/src/transforms.js +0 -166
  151. package/webpack.config.js +0 -108
package/csrc/expr.h ADDED
@@ -0,0 +1,58 @@
1
+ /*
2
+ * expr.h — Expression AST types (shared between expr.c and ir_sql.c).
3
+ */
4
+
5
+ #ifndef TF_EXPR_H
6
+ #define TF_EXPR_H
7
+
8
+ #include <stdint.h>
9
+
10
+ typedef enum {
11
+ EXPR_LIT_INT,
12
+ EXPR_LIT_FLOAT,
13
+ EXPR_LIT_STR,
14
+ EXPR_LIT_BOOL,
15
+ EXPR_COL_REF,
16
+ EXPR_CMP,
17
+ EXPR_AND,
18
+ EXPR_OR,
19
+ EXPR_NOT,
20
+ EXPR_ADD,
21
+ EXPR_SUB,
22
+ EXPR_MUL,
23
+ EXPR_DIV,
24
+ EXPR_NEG,
25
+ EXPR_FUNC_CALL,
26
+ } expr_kind;
27
+
28
+ typedef enum {
29
+ CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_EQ, CMP_NE,
30
+ } cmp_op;
31
+
32
+ struct tf_expr {
33
+ expr_kind kind;
34
+ union {
35
+ int64_t lit_int;
36
+ double lit_float;
37
+ char *lit_str;
38
+ int lit_bool;
39
+ char *col_name; /* for EXPR_COL_REF */
40
+ struct { /* for EXPR_CMP */
41
+ struct tf_expr *left;
42
+ struct tf_expr *right;
43
+ cmp_op op;
44
+ } cmp;
45
+ struct { /* for EXPR_AND, EXPR_OR, EXPR_ADD, EXPR_SUB, EXPR_MUL, EXPR_DIV */
46
+ struct tf_expr *left;
47
+ struct tf_expr *right;
48
+ } binary;
49
+ struct tf_expr *child; /* for EXPR_NOT, EXPR_NEG */
50
+ struct { /* for EXPR_FUNC_CALL */
51
+ char *name;
52
+ struct tf_expr **args;
53
+ int n_args;
54
+ } func;
55
+ };
56
+ };
57
+
58
+ #endif /* TF_EXPR_H */
@@ -0,0 +1,539 @@
1
+ /*
2
+ * internal.h — Internal types for the Tranfi core.
3
+ * Not part of the public API.
4
+ */
5
+
6
+ #ifndef TF_INTERNAL_H
7
+ #define TF_INTERNAL_H
8
+
9
+ #include "tranfi.h"
10
+ #include "ir.h"
11
+ #include <stddef.h>
12
+ #include <stdint.h>
13
+ #include <stdbool.h>
14
+
15
+ typedef struct cJSON cJSON;
16
+
17
+ #define TF_MAX_BATCH_ROWS ((size_t)64u * 1024u)
18
+ #define TF_MAX_OUTPUT_ROWS_PER_BATCH ((size_t)1024u * 1024u)
19
+ #define TF_MAX_EXPANDING_ROWS_PER_INPUT TF_MAX_OUTPUT_ROWS_PER_BATCH
20
+ #define TF_MAX_EXPLODE_TOKENS_PER_ROW TF_MAX_OUTPUT_ROWS_PER_BATCH
21
+ #define TF_MAX_COLUMNS ((size_t)64u * 1024u)
22
+ #define TF_MAX_RECORD_BYTES ((size_t)1024u * 1024u * 1024u)
23
+ #define TF_MAX_CELL_BYTES ((size_t)64u * 1024u * 1024u)
24
+ #define TF_MAX_COLUMN_NAME_BYTES ((size_t)4096u)
25
+ #define TF_MAX_SCHEMA_BYTES ((size_t)16u * 1024u * 1024u)
26
+ #define TF_MAX_ERROR_BYTES ((size_t)64u * 1024u * 1024u)
27
+ #define TF_MAX_REGEX_PATTERN_BYTES ((size_t)4096u)
28
+ #define TF_MAX_REGEX_CELL_BYTES ((size_t)64u * 1024u)
29
+ #if SIZE_MAX > 9007199254740991ULL
30
+ #define TF_MAX_SAFE_SIZE_ARG ((size_t)9007199254740991ULL)
31
+ #else
32
+ #define TF_MAX_SAFE_SIZE_ARG ((size_t)SIZE_MAX)
33
+ #endif
34
+ #define TF_MAX_COUNT_ARG TF_MAX_SAFE_SIZE_ARG
35
+ #define TF_MAX_STATE_BYTES TF_MAX_SAFE_SIZE_ARG
36
+ #define TF_MAX_SPILL_MEMORY_BYTES TF_MAX_SAFE_SIZE_ARG
37
+ #define TF_MAX_SPILL_RUN_ROWS TF_MAX_COUNT_ARG
38
+ #define TF_MAX_SPILL_OUTPUT_ROWS TF_MAX_BATCH_ROWS
39
+ #define TF_MAX_AUDIT_RECORDS ((size_t)1000u * 1000u)
40
+ #define TF_MAX_TABLE_WIDTH ((size_t)4096u)
41
+ #define TF_MAX_TABLE_ROWS TF_MAX_COUNT_ARG
42
+ #define TF_MAX_WINDOW_SIZE TF_MAX_OUTPUT_ROWS_PER_BATCH
43
+ #define TF_FLOAT64_ROUNDTRIP_FORMAT "%.17g"
44
+
45
+ #if defined(__GNUC__) || defined(__clang__)
46
+ #define TF_WARN_UNUSED __attribute__((warn_unused_result))
47
+ #else
48
+ #define TF_WARN_UNUSED
49
+ #endif
50
+
51
+ TF_WARN_UNUSED int tf_format_float64(char *buf, size_t buf_size, double value);
52
+ TF_WARN_UNUSED int tf_size_add(size_t a, size_t b, size_t *out);
53
+ TF_WARN_UNUSED int tf_size_mul(size_t a, size_t b, size_t *out);
54
+ TF_WARN_UNUSED int tf_size_align(size_t x, size_t align, size_t *out);
55
+ TF_WARN_UNUSED int tf_size_grow_pow2(size_t current, size_t min_value, size_t min_capacity, size_t *out);
56
+ TF_WARN_UNUSED void *tf_mallocarray_checked(size_t count, size_t elem_size);
57
+ TF_WARN_UNUSED void *tf_callocarray_checked(size_t count, size_t elem_size);
58
+ TF_WARN_UNUSED void *tf_reallocarray_checked(void *ptr, size_t count, size_t elem_size);
59
+ TF_WARN_UNUSED char *tf_strdup_checked(const char *s);
60
+ TF_WARN_UNUSED char *tf_string_append_suffix_checked(const char *prefix, const char *suffix);
61
+ TF_WARN_UNUSED int tf_check_byte_limit(size_t n, size_t max_value,
62
+ const char *context, const char *name);
63
+ TF_WARN_UNUSED int tf_string_length_bounded(const char *s, size_t max_value,
64
+ size_t *out, const char *context,
65
+ const char *name);
66
+ TF_WARN_UNUSED int tf_json_get_size_arg(const cJSON *args, const char *name,
67
+ size_t min_value, size_t max_value,
68
+ size_t *out, const char *context);
69
+ TF_WARN_UNUSED int tf_json_size_value(const cJSON *item, const char *name,
70
+ size_t min_value, size_t max_value,
71
+ size_t *out, const char *context);
72
+ TF_WARN_UNUSED int tf_json_get_size_arg_any(const cJSON *args, const char *name,
73
+ const char *alt_name,
74
+ size_t min_value, size_t max_value,
75
+ size_t *out, const char *context);
76
+
77
+ typedef int (*tf_index_compare_fn)(const void *ctx, size_t a, size_t b);
78
+ void tf_sort_indices(size_t *indices, size_t n, tf_index_compare_fn compare, const void *ctx);
79
+
80
+ /* ---- Arena allocator ---- */
81
+
82
+ typedef struct tf_arena_block {
83
+ uint8_t *data;
84
+ size_t used;
85
+ size_t cap;
86
+ struct tf_arena_block *next;
87
+ } tf_arena_block;
88
+
89
+ typedef struct tf_arena {
90
+ tf_arena_block *head;
91
+ tf_arena_block *current;
92
+ size_t block_size; /* default block capacity */
93
+ } tf_arena;
94
+
95
+ tf_arena *tf_arena_create(size_t block_size);
96
+ void *tf_arena_alloc(tf_arena *a, size_t size);
97
+ char *tf_arena_strdup(tf_arena *a, const char *s);
98
+ void tf_arena_reset(tf_arena *a);
99
+ void tf_arena_free(tf_arena *a);
100
+
101
+ /* ---- Growable byte buffer ---- */
102
+
103
+ typedef struct tf_buffer {
104
+ uint8_t *data;
105
+ size_t len; /* bytes written */
106
+ size_t cap; /* allocated capacity */
107
+ size_t read_pos; /* consumer read position */
108
+ } tf_buffer;
109
+
110
+ void tf_buffer_init(tf_buffer *b);
111
+ TF_WARN_UNUSED int tf_buffer_write(tf_buffer *b, const uint8_t *data, size_t len);
112
+ size_t tf_buffer_read(tf_buffer *b, uint8_t *out, size_t len);
113
+ size_t tf_buffer_readable(const tf_buffer *b);
114
+ void tf_buffer_compact(tf_buffer *b);
115
+ TF_WARN_UNUSED int tf_buffer_write_str(tf_buffer *b, const char *s);
116
+ TF_WARN_UNUSED int tf_buffer_write_line(tf_buffer *b, const char *s);
117
+ TF_WARN_UNUSED int tf_buffer_write_json_line(tf_buffer *b, const cJSON *obj);
118
+ void tf_buffer_free(tf_buffer *b);
119
+ TF_WARN_UNUSED int tf_json_add_string(cJSON *obj, const char *name, const char *value);
120
+ TF_WARN_UNUSED int tf_json_add_number(cJSON *obj, const char *name, double value);
121
+ TF_WARN_UNUSED int tf_json_add_bool(cJSON *obj, const char *name, int value);
122
+ TF_WARN_UNUSED int tf_json_add_null(cJSON *obj, const char *name);
123
+ TF_WARN_UNUSED int tf_json_add_item(cJSON *obj, const char *name, cJSON *item);
124
+ TF_WARN_UNUSED int tf_json_add_array_item(cJSON *arr, cJSON *item);
125
+
126
+ /* ---- Columnar batch ---- */
127
+ /* (tf_type is defined in ir.h, included above) */
128
+
129
+ typedef struct tf_batch {
130
+ char **col_names; /* array of column name strings (arena-allocated) */
131
+ tf_type *col_types; /* per-column type */
132
+ size_t n_cols;
133
+ size_t n_rows;
134
+ size_t capacity; /* allocated row slots per column */
135
+ void **columns; /* array of typed column arrays */
136
+ uint8_t **nulls; /* null bitmap per column (1 byte per row for simplicity) */
137
+ tf_arena *arena; /* owns all memory for this batch */
138
+ size_t schema_name_bytes;
139
+ } tf_batch;
140
+
141
+ typedef union tf_cell_value {
142
+ bool b;
143
+ int64_t i64;
144
+ double f64;
145
+ const char *str;
146
+ int32_t date;
147
+ } tf_cell_value;
148
+
149
+ /* Owned string variant used by spill rows before copying into a batch arena. */
150
+ typedef union tf_owned_cell_value {
151
+ uint8_t b;
152
+ int64_t i64;
153
+ double f64;
154
+ int32_t date;
155
+ char *str;
156
+ } tf_owned_cell_value;
157
+
158
+ tf_batch *tf_batch_create(size_t n_cols, size_t capacity);
159
+ TF_WARN_UNUSED int tf_batch_set_schema(tf_batch *b, size_t col, const char *name, tf_type type);
160
+ TF_WARN_UNUSED int tf_batch_ensure_capacity(tf_batch *b, size_t min_rows);
161
+ TF_WARN_UNUSED int tf_batch_expose_row(tf_batch *b, size_t row);
162
+
163
+ /* Set a value in a specific cell. String values are copied into the arena. */
164
+ TF_WARN_UNUSED int tf_batch_set_null(tf_batch *b, size_t row, size_t col);
165
+ TF_WARN_UNUSED int tf_batch_set_bool(tf_batch *b, size_t row, size_t col, bool val);
166
+ TF_WARN_UNUSED int tf_batch_set_int64(tf_batch *b, size_t row, size_t col, int64_t val);
167
+ TF_WARN_UNUSED int tf_batch_set_float64(tf_batch *b, size_t row, size_t col, double val);
168
+ TF_WARN_UNUSED int tf_batch_set_string(tf_batch *b, size_t row, size_t col, const char *val);
169
+ TF_WARN_UNUSED int tf_batch_set_string_len(tf_batch *b, size_t row, size_t col,
170
+ const char *val, size_t len);
171
+ TF_WARN_UNUSED int tf_batch_set_date(tf_batch *b, size_t row, size_t col, int32_t val);
172
+ TF_WARN_UNUSED int tf_batch_set_timestamp(tf_batch *b, size_t row, size_t col, int64_t val);
173
+ TF_WARN_UNUSED int tf_batch_set_cell_value(tf_batch *b, size_t row, size_t col,
174
+ tf_type type, int is_null,
175
+ const tf_cell_value *value);
176
+ TF_WARN_UNUSED int tf_batch_set_owned_cell_value(tf_batch *b, size_t row, size_t col,
177
+ tf_type type, int is_null,
178
+ const tf_owned_cell_value *value);
179
+
180
+ /* Get values from a cell. */
181
+ bool tf_batch_is_null(const tf_batch *b, size_t row, size_t col);
182
+ bool tf_batch_get_bool(const tf_batch *b, size_t row, size_t col);
183
+ int64_t tf_batch_get_int64(const tf_batch *b, size_t row, size_t col);
184
+ double tf_batch_get_float64(const tf_batch *b, size_t row, size_t col);
185
+ const char *tf_batch_get_string(const tf_batch *b, size_t row, size_t col);
186
+ int32_t tf_batch_get_date(const tf_batch *b, size_t row, size_t col);
187
+ int64_t tf_batch_get_timestamp(const tf_batch *b, size_t row, size_t col);
188
+
189
+ /* Find column index by name. Returns -1 if not found. */
190
+ int tf_batch_col_index(const tf_batch *b, const char *name);
191
+
192
+ /* Schema and row-copy helpers. */
193
+ typedef enum tf_cell_string_format {
194
+ TF_CELL_STRING_ROUNDTRIP, /* round-trip floats, ISO dates/timestamps */
195
+ TF_CELL_STRING_HUMAN, /* short floats, ISO dates/timestamps */
196
+ TF_CELL_STRING_NUMERIC_TIME /* round-trip floats, numeric dates/timestamps */
197
+ } tf_cell_string_format;
198
+
199
+ TF_WARN_UNUSED int tf_batch_clone_schema(tf_batch *dst, const tf_batch *src);
200
+ TF_WARN_UNUSED int tf_batch_clone_with_extra_cols(tf_batch *dst, const tf_batch *src,
201
+ const char **names, const tf_type *types,
202
+ size_t n_extra);
203
+ TF_WARN_UNUSED int tf_batch_copy_cell(tf_batch *dst, size_t dst_row, size_t dst_col,
204
+ const tf_batch *src, size_t src_row, size_t src_col);
205
+ TF_WARN_UNUSED int tf_batch_copy_cell_index(tf_batch *dst, size_t dst_row, size_t dst_col,
206
+ const tf_batch *src, size_t src_row, int src_col);
207
+ TF_WARN_UNUSED int tf_batch_format_cell_as_string(const tf_batch *src, size_t src_row, size_t src_col,
208
+ tf_cell_string_format format,
209
+ char *buf, size_t buf_size,
210
+ const char **out);
211
+ TF_WARN_UNUSED int tf_batch_copy_cell_as_string(tf_batch *dst, size_t dst_row, size_t dst_col,
212
+ const tf_batch *src, size_t src_row, size_t src_col);
213
+ TF_WARN_UNUSED int tf_batch_copy_selected_row(tf_batch *dst, size_t dst_row,
214
+ const tf_batch *src, size_t src_row,
215
+ const size_t *cols, size_t n_cols);
216
+ TF_WARN_UNUSED int tf_batch_copy_selected_columns(tf_batch *dst,
217
+ const tf_batch *src,
218
+ const size_t *cols,
219
+ size_t n_cols);
220
+ TF_WARN_UNUSED int tf_batch_copy_row(tf_batch *dst, size_t dst_row,
221
+ const tf_batch *src, size_t src_row);
222
+ TF_WARN_UNUSED int tf_batch_clone_with_selected_extra_cols(tf_batch *dst,
223
+ const tf_batch *src,
224
+ const tf_batch *extra,
225
+ const int *extra_cols,
226
+ size_t n_extra);
227
+ TF_WARN_UNUSED int tf_batch_append_row(tf_batch *dst, const tf_batch *src,
228
+ size_t src_row);
229
+ TF_WARN_UNUSED int tf_batch_append_row_with_selected_extra(tf_batch *dst,
230
+ const tf_batch *left,
231
+ size_t left_row,
232
+ const tf_batch *extra,
233
+ size_t extra_row,
234
+ const int *extra_cols,
235
+ size_t n_extra);
236
+ TF_WARN_UNUSED int tf_batch_append_row_with_null_extra(tf_batch *dst,
237
+ const tf_batch *left,
238
+ size_t left_row,
239
+ size_t n_extra);
240
+
241
+ void tf_batch_free(tf_batch *b);
242
+ void tf_batch_array_free_items(tf_batch **batches, size_t n_batches);
243
+ void tf_batch_array_free(tf_batch **batches, size_t n_batches);
244
+
245
+ /* ---- Audit / side-channel row serialization helpers ---- */
246
+
247
+ typedef struct tf_audit_options {
248
+ int include_row;
249
+ char **columns;
250
+ size_t n_columns;
251
+ char **redact_columns;
252
+ size_t n_redact_columns;
253
+ char **hash_columns;
254
+ size_t n_hash_columns;
255
+ size_t max_bytes;
256
+ size_t max_cell_bytes;
257
+ } tf_audit_options;
258
+
259
+ void tf_audit_options_init(tf_audit_options *opts, int default_include_row);
260
+ int tf_audit_options_parse(tf_audit_options *opts, const cJSON *args, const char *context);
261
+ void tf_audit_options_free(tf_audit_options *opts);
262
+ int tf_audit_column_is_redacted(const tf_audit_options *opts, const char *column);
263
+ int tf_audit_column_is_hashed(const tf_audit_options *opts, const char *column);
264
+ int tf_audit_hash_string(const char *value, char *out, size_t out_size);
265
+ const char *tf_audit_format_string_for_column(const tf_audit_options *opts, const char *column,
266
+ const char *value, char *buf, size_t buf_size);
267
+ TF_WARN_UNUSED char *tf_audit_format_string_dup_for_column(const tf_audit_options *opts,
268
+ const char *column,
269
+ const char *value);
270
+ cJSON *tf_audit_string_to_json_for_column(const tf_audit_options *opts, const char *column,
271
+ const char *value);
272
+ TF_WARN_UNUSED int tf_json_add_audit_string(cJSON *obj, const char *name,
273
+ const tf_audit_options *opts,
274
+ const char *column, const char *value);
275
+ cJSON *tf_audit_cell_to_json(const tf_batch *b, size_t row, size_t col, const tf_audit_options *opts);
276
+ cJSON *tf_audit_row_to_json(const tf_batch *b, size_t row, const tf_audit_options *opts);
277
+
278
+ /* ---- Column selector helpers ---- */
279
+
280
+ int tf_json_path_validate(const char *path);
281
+ const cJSON *tf_json_path_resolve(const cJSON *root, const char *path);
282
+
283
+ int tf_column_selector_has_syntax(const char *raw);
284
+ int tf_column_selectors_have_syntax_json(const cJSON *selectors);
285
+ int tf_column_selectors_resolve(char **selectors, size_t n_selectors,
286
+ char **names, const tf_type *types, size_t n_cols,
287
+ int **out_indices, size_t *out_n,
288
+ char **error);
289
+ int tf_column_selectors_resolve_json(const cJSON *selectors,
290
+ char **names, const tf_type *types, size_t n_cols,
291
+ int **out_indices, size_t *out_n,
292
+ char **error);
293
+
294
+ int tf_estimate_step_state_bytes(const tf_ir_node *node, size_t *out,
295
+ char *reason, size_t reason_size);
296
+ int tf_estimate_key_state_plan_bytes(const tf_ir_plan *ir, size_t *out,
297
+ const tf_ir_node **failed_node,
298
+ char *reason, size_t reason_size);
299
+
300
+ /* ---- Step interface (transforms) ---- */
301
+
302
+ /*
303
+ * Side-channel callback: steps call this to emit data to side channels.
304
+ * Owned by the pipeline and passed to steps during processing.
305
+ */
306
+ typedef struct tf_side_channels {
307
+ tf_buffer *errors;
308
+ tf_buffer *stats;
309
+ tf_buffer *samples;
310
+ const char *source_name;
311
+ } tf_side_channels;
312
+
313
+ TF_WARN_UNUSED int tf_side_write_error(tf_side_channels *side, const char *msg);
314
+
315
+ /* Hidden IR args added by the built-in workspace_root resolver. */
316
+ #define TF_POLICY_VALIDATED_FILE_PATH_ARG "_tf_validated_file_path"
317
+ #define TF_POLICY_VALIDATED_RULES_FILE_PATH_ARG "_tf_validated_rules_file_path"
318
+
319
+ const char *tf_policy_validated_path_arg(const cJSON *args, const char *path_arg);
320
+ FILE *tf_policy_fopen_read(const char *path, const char *validated_path);
321
+
322
+ typedef struct tf_step {
323
+ /* Process one input batch, produce zero or one output batch.
324
+ * *out is set to a new batch (caller frees) or NULL if filtered away. */
325
+ int (*process)(struct tf_step *self, tf_batch *in, tf_batch **out,
326
+ tf_side_channels *side);
327
+ /* Flush any buffered state. */
328
+ int (*flush)(struct tf_step *self, tf_batch **out, tf_side_channels *side);
329
+ /* Optional continuation for flush-latent steps that emit multiple batches. */
330
+ int (*flush_next)(struct tf_step *self, tf_batch **out, tf_side_channels *side);
331
+ /* Optional JSON stats hook. Appends comma-prefixed fields to step_stats. */
332
+ int (*append_stats)(struct tf_step *self, tf_buffer *out);
333
+ /* Free all resources. */
334
+ void (*destroy)(struct tf_step *self);
335
+ void *state;
336
+ } tf_step;
337
+
338
+ #define TF_STEP_WARN_BLOCKING (1u << 0)
339
+ #define TF_STEP_WARN_FLUSH_LATENT (1u << 1)
340
+ #define TF_STEP_WARN_UNBOUNDED_STATE (1u << 2)
341
+ #define TF_STEP_WARN_DATA_DEPENDENT_SCHEMA (1u << 3)
342
+
343
+ typedef struct tf_step_run_stats {
344
+ char *op;
345
+ char *state_estimate;
346
+ char *state_bytes_reason;
347
+ char *execution_target;
348
+ size_t node_index;
349
+ size_t state_bytes_estimate;
350
+ int has_state_bytes_estimate;
351
+ uint32_t warnings;
352
+ tf_memory_class memory_class;
353
+ tf_emit_class emit_class;
354
+ tf_schema_class schema_class;
355
+ size_t batches_in;
356
+ size_t batches_out;
357
+ size_t rows_in;
358
+ size_t rows_out;
359
+ } tf_step_run_stats;
360
+
361
+ /* ---- Decoder interface (bytes → batches) ---- */
362
+
363
+ typedef struct tf_decoder {
364
+ /*
365
+ * Decode bytes. May produce 0..N batches.
366
+ * *out is set to a malloc'd array of tf_batch*, *n_out to its length.
367
+ * Caller frees the array and each batch.
368
+ */
369
+ int (*decode)(struct tf_decoder *self, const uint8_t *data, size_t len,
370
+ tf_batch ***out, size_t *n_out, tf_side_channels *side);
371
+ /* Flush remaining data (e.g. last partial line). */
372
+ int (*flush)(struct tf_decoder *self, tf_batch ***out, size_t *n_out,
373
+ tf_side_channels *side);
374
+ void (*destroy)(struct tf_decoder *self);
375
+ void *state;
376
+ } tf_decoder;
377
+
378
+ /* ---- Encoder interface (batches → bytes) ---- */
379
+
380
+ typedef struct tf_encoder {
381
+ /*
382
+ * Encode a batch to bytes. Appends to the provided buffer.
383
+ */
384
+ int (*encode)(struct tf_encoder *self, tf_batch *in, tf_buffer *out);
385
+ /* Flush any trailing data. */
386
+ int (*flush)(struct tf_encoder *self, tf_buffer *out);
387
+ void (*destroy)(struct tf_encoder *self);
388
+ void *state;
389
+ } tf_encoder;
390
+
391
+ /* ---- Pipeline struct ---- */
392
+
393
+ struct tf_pipeline {
394
+ tf_decoder *decoder;
395
+ tf_step **steps;
396
+ size_t n_steps;
397
+ tf_step_run_stats *step_stats;
398
+ size_t n_step_stats;
399
+ tf_encoder *encoder;
400
+ tf_buffer output[TF_NUM_CHANNELS];
401
+ tf_pipeline_sink_fn sinks[TF_NUM_CHANNELS];
402
+ void *sink_users[TF_NUM_CHANNELS];
403
+ tf_pipeline_batch_sink_fn batch_sink;
404
+ void *batch_sink_user;
405
+ int encode_output;
406
+ tf_pipeline_progress_fn progress_cb;
407
+ void *progress_user;
408
+ size_t progress_interval_rows;
409
+ size_t progress_last_rows_in;
410
+ size_t progress_last_rows_out;
411
+ tf_side_channels side;
412
+ size_t rows_in;
413
+ size_t rows_out;
414
+ size_t batches_in;
415
+ size_t batches_out;
416
+ size_t bytes_in;
417
+ size_t bytes_out;
418
+ char *source_name;
419
+ char *error;
420
+ int finished;
421
+ int finish_started;
422
+ int finish_phase;
423
+ tf_batch **finish_batches;
424
+ size_t finish_n_batches;
425
+ size_t finish_batch_index;
426
+ size_t finish_step_index;
427
+ int finish_step_in_next;
428
+ };
429
+
430
+ /* ---- Codec constructors (used by plan parser) ---- */
431
+
432
+ tf_decoder *tf_csv_decoder_create(const cJSON *args);
433
+ tf_encoder *tf_csv_encoder_create(const cJSON *args);
434
+ tf_decoder *tf_jsonl_decoder_create(const cJSON *args);
435
+ tf_encoder *tf_jsonl_encoder_create(const cJSON *args);
436
+ tf_decoder *tf_text_decoder_create(const cJSON *args);
437
+ tf_encoder *tf_text_encoder_create(const cJSON *args);
438
+
439
+ /* ---- Transform constructors ---- */
440
+
441
+ tf_step *tf_filter_create(const cJSON *args);
442
+ tf_step *tf_select_create(const cJSON *args);
443
+ tf_step *tf_relocate_create(const cJSON *args);
444
+ tf_step *tf_rename_create(const cJSON *args);
445
+ tf_step *tf_head_create(const cJSON *args);
446
+ tf_step *tf_skip_create(const cJSON *args);
447
+ tf_step *tf_derive_create(const cJSON *args);
448
+ tf_step *tf_source_name_create(const cJSON *args);
449
+ tf_step *tf_across_create(const cJSON *args);
450
+ tf_step *tf_stats_create(const cJSON *args);
451
+ tf_step *tf_scan_create(const cJSON *args);
452
+ tf_step *tf_unique_create(const cJSON *args);
453
+ tf_step *tf_sort_create(const cJSON *args);
454
+ tf_step *tf_validate_create(const cJSON *args);
455
+ tf_step *tf_assert_create(const cJSON *args);
456
+ tf_step *tf_quarantine_create(const cJSON *args);
457
+ tf_step *tf_schema_create(const cJSON *args);
458
+ tf_step *tf_schema_infer_create(const cJSON *args);
459
+ tf_step *tf_tee_create(const cJSON *args);
460
+ tf_step *tf_trim_create(const cJSON *args);
461
+ tf_step *tf_fill_null_create(const cJSON *args);
462
+ tf_step *tf_cast_create(const cJSON *args);
463
+ tf_step *tf_clip_create(const cJSON *args);
464
+ tf_step *tf_replace_create(const cJSON *args);
465
+ tf_step *tf_hash_create(const cJSON *args);
466
+ tf_step *tf_bin_create(const cJSON *args);
467
+ tf_step *tf_fill_down_create(const cJSON *args);
468
+ tf_step *tf_step_create(const cJSON *args);
469
+ tf_step *tf_window_create(const cJSON *args);
470
+ tf_step *tf_rolling_sum_create(const cJSON *args);
471
+ tf_step *tf_rolling_mean_create(const cJSON *args);
472
+ tf_step *tf_rolling_min_create(const cJSON *args);
473
+ tf_step *tf_rolling_max_create(const cJSON *args);
474
+ tf_step *tf_rolling_any_create(const cJSON *args);
475
+ tf_step *tf_rolling_all_create(const cJSON *args);
476
+ tf_step *tf_explode_create(const cJSON *args);
477
+ tf_step *tf_split_create(const cJSON *args);
478
+ tf_step *tf_unpivot_create(const cJSON *args);
479
+ tf_step *tf_tail_create(const cJSON *args);
480
+ tf_step *tf_top_create(const cJSON *args);
481
+ tf_step *tf_top_k_create(const cJSON *args);
482
+ tf_step *tf_bottom_k_create(const cJSON *args);
483
+ tf_step *tf_slice_min_create(const cJSON *args);
484
+ tf_step *tf_slice_max_create(const cJSON *args);
485
+ tf_step *tf_sample_create(const cJSON *args);
486
+ tf_step *tf_group_agg_create(const cJSON *args);
487
+ tf_step *tf_frequency_create(const cJSON *args);
488
+ tf_step *tf_datetime_create(const cJSON *args);
489
+ tf_step *tf_grep_create(const cJSON *args);
490
+ tf_step *tf_json_extract_create(const cJSON *args);
491
+ tf_step *tf_json_filter_create(const cJSON *args);
492
+ tf_step *tf_json_schema_create(const cJSON *args);
493
+ tf_step *tf_json_flatten_create(const cJSON *args);
494
+ tf_step *tf_pivot_create(const cJSON *args);
495
+ tf_step *tf_join_create(const cJSON *args);
496
+ tf_step *tf_semi_join_create(const cJSON *args);
497
+ tf_step *tf_anti_join_create(const cJSON *args);
498
+ tf_step *tf_intersect_create(const cJSON *args);
499
+ tf_step *tf_setdiff_create(const cJSON *args);
500
+ tf_step *tf_intersect_all_create(const cJSON *args);
501
+ tf_step *tf_setdiff_all_create(const cJSON *args);
502
+ tf_step *tf_union_create(const cJSON *args);
503
+ tf_step *tf_union_all_create(const cJSON *args);
504
+ tf_step *tf_stack_create(const cJSON *args);
505
+ tf_step *tf_lead_create(const cJSON *args);
506
+ tf_step *tf_lag_create(const cJSON *args);
507
+ tf_step *tf_shift_create(const cJSON *args);
508
+ tf_step *tf_rowid_create(const cJSON *args);
509
+ tf_step *tf_rleid_create(const cJSON *args);
510
+ tf_step *tf_date_trunc_create(const cJSON *args);
511
+ tf_step *tf_onehot_create(const cJSON *args);
512
+ tf_step *tf_label_encode_create(const cJSON *args);
513
+ tf_step *tf_ewma_create(const cJSON *args);
514
+ tf_step *tf_diff_create(const cJSON *args);
515
+ tf_step *tf_anomaly_create(const cJSON *args);
516
+ tf_step *tf_split_data_create(const cJSON *args);
517
+ tf_step *tf_interpolate_create(const cJSON *args);
518
+ tf_step *tf_normalize_create(const cJSON *args);
519
+ tf_step *tf_acf_create(const cJSON *args);
520
+
521
+ /* ---- Table encoder ---- */
522
+
523
+ tf_encoder *tf_table_encoder_create(const cJSON *args);
524
+
525
+ /* ---- Expression evaluator ---- */
526
+
527
+ typedef struct tf_expr tf_expr;
528
+
529
+ tf_expr *tf_expr_parse(const char *text);
530
+ int tf_expr_eval(const tf_expr *e, const tf_batch *batch, size_t row, bool *result);
531
+ int tf_expr_eval_val(const tf_expr *e, const tf_batch *batch, size_t row,
532
+ tf_eval_result *result);
533
+ void tf_expr_free(tf_expr *e);
534
+
535
+ /* ---- Global error ---- */
536
+
537
+ void tf_set_last_error(const char *msg);
538
+
539
+ #endif /* TF_INTERNAL_H */