a03675113a
- .claude/agents/fn-orquestador/SKILL.md - .claude/commands/fn_claude.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - .claude/rules/ids_naming.md - CHANGELOG.md - apps/dag_engine/README.md - apps/dag_engine/api.go - apps/dag_engine/dags_migrated/example.yaml - apps/dag_engine/dags_migrated/example_lineage_tracking.yaml - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
96 lines
4.5 KiB
Markdown
96 lines
4.5 KiB
Markdown
---
|
|
group: cpp-tables
|
|
tag: cpp-tables
|
|
lang: cpp
|
|
domain: core
|
|
n: 10
|
|
description: "Table Query Language: pipeline de transformacion tabular pura (filter, group, agg, sort, join, stats, formulas Lua, emit/apply round-trip) + render UI completa (data_table)."
|
|
---
|
|
|
|
# cpp-tables — Table Query Language (C++ puro)
|
|
|
|
Stack de transformacion tabular C++. Nucleo headless (filtros, agrupacion, stats, joins, formulas Lua, round-trip TQL). Entry-point de render via `data_table_cpp_viz` que compone todo el stack con UI ImGui completa. Apps migran desde el playground cambiando solo el include path.
|
|
|
|
## Funciones del grupo
|
|
|
|
| ID | Firma corta | Que hace |
|
|
|---|---|---|
|
|
| `auto_detect_type_cpp_core` | `ColumnType auto_detect_type(cells, rows, cols, col, sample_n=64)` | Infiere ColumnType escaneando hasta N celdas no-vacias |
|
|
| `compute_column_stats_cpp_core` | `ColStats compute_column_stats(cells, rows, cols, col, ...)` | Mean, p25/p50/p75, hist 24 bins, top-8 categorias |
|
|
| `compute_stage_cpp_core` | `StageOutput compute_stage(cells, rows, cols, headers, types, stage)` | Ejecuta un Stage TQL: filter → group+agg → sort |
|
|
| `compute_pipeline_cpp_core` | `StageOutput compute_pipeline(cells, rows, cols, headers, types, stages)` | Encadena N stages secuencialmente |
|
|
| `join_tables_cpp_core` | `StageOutput join_tables(left..., right, jn)` | Hash join multi-key (inner/left/right/full) |
|
|
| `lua_engine_cpp_core` | `Engine* get(); string eval(engine, id, ctx, err)` | Motor Lua 5.4 sandbox para formulas de columnas derivadas |
|
|
| `tql_emit_cpp_core` | `std::string tql::emit(state, headers, types)` | Serializa State a texto Lua TQL v1 |
|
|
| `tql_apply_cpp_core` | `ApplyResult tql::apply(lua_text, available_headers)` | Parsea texto TQL v1 y produce State + warnings |
|
|
| `tql_helpers_cpp_core` | `op_label, view_mode_token, agg_fn_token, ...` | Conversiones puras enum↔token usadas por emit/apply |
|
|
|
|
## Tipos usados
|
|
|
|
- `data_table_types_cpp_core` — enums y structs base: `ColumnType`, `Op`, `Stage`, `StageOutput`, `Filter`, `Aggregation`, `Join`, `TableInput`, `ViewMode`, `VizPanel`, `ViewConfig`, `State`, etc.
|
|
|
|
## Ejemplo canonico end-to-end
|
|
|
|
```cpp
|
|
// 1. Datos raw (row-major, 4 filas x 3 cols)
|
|
#include "core/auto_detect_type.h"
|
|
#include "core/compute_pipeline.h"
|
|
#include "core/tql_emit.h"
|
|
#include "core/tql_apply.h"
|
|
using namespace data_table;
|
|
|
|
const char* raw[] = {
|
|
"EU","A","100",
|
|
"US","A","200",
|
|
"EU","B","300",
|
|
"EU","A","50"
|
|
};
|
|
std::vector<std::string> hdrs = {"region","type","revenue"};
|
|
|
|
// 2. Auto-detectar tipos
|
|
std::vector<ColumnType> types;
|
|
for (int c = 0; c < 3; ++c) types.push_back(auto_detect_type(raw, 4, 3, c));
|
|
|
|
// 3. Pipeline: filtrar EU, agrupar por type, sumar revenue
|
|
Stage s0;
|
|
s0.filters.push_back({0, Op::Eq, "EU"});
|
|
|
|
Stage s1;
|
|
s1.breakouts = {"type"};
|
|
Aggregation agg; agg.fn = AggFn::Sum; agg.col = "revenue"; s1.aggregations.push_back(agg);
|
|
s1.sorts.push_back({"sum_revenue", true});
|
|
|
|
// 4. Ejecutar pipeline
|
|
StageOutput out = compute_pipeline(raw, 4, 3, hdrs, types, {s0, s1});
|
|
// out.rows==2: [B,300] [A,150]
|
|
|
|
// 5. Persistir estado como TQL (para guardar en BD o portapapeles)
|
|
State st;
|
|
st.stages = {s0, s1};
|
|
st.display = ViewMode::Bar;
|
|
std::string tql_text = tql::emit(st, hdrs, types);
|
|
|
|
// 6. Restaurar desde TQL
|
|
tql::ApplyResult res = tql::apply(tql_text, hdrs);
|
|
if (res.ok) {
|
|
// res.state listo — compilar formulas derivadas con lua_engine si las hay
|
|
}
|
|
```
|
|
|
|
| `data_table_cpp_viz` | `void data_table::render(id, tables, st, show_chrome=true)` | Render UI completa: chips bar, tabla, viz panels, drill, TQL editor, Ask AI. Entry-point publica del stack. |
|
|
|
|
## Fronteras del grupo headless (core)
|
|
|
|
- NO incluye render: ningun include de ImGui, ImPlot ni tipos de ventana.
|
|
- NO incluye I/O: no lee archivos CSV, no escribe a disco.
|
|
- El motor Lua (`lua_engine`) es la unica funcion impura del grupo — gestiona estado del interprete.
|
|
- `tql_apply` abre/cierra su propio `lua_State` por llamada (no usa lua_engine internamente). Fórmulas en `DerivedColumn.formula` se almacenan verbatim; el caller las compila con `lua_engine::compile()`.
|
|
- La deteccion de fechas solo reconoce ISO 8601 (`YYYY-MM-DD`). Otros formatos caen en String.
|
|
- Los joins trabajan sobre `TableInput` en memoria; no hay join lazy ni streaming.
|
|
|
|
## Prerequisitos
|
|
|
|
- `data_table_types_cpp_core` debe estar en el include path (`cpp/functions/`).
|
|
- Para `lua_engine` y `tql_apply`: linkar contra la lib Lua 5.4 vendored (`cpp/vendor/lua/`, target `lua54`).
|
|
- Para tests headless: usar `add_fn_test` del `cpp/tests/CMakeLists.txt` — no necesita fn_framework ni ImGui context.
|