chore: auto-commit (5 archivos)

- playground/tables/CMakeLists.txt
- playground/tables/data_table.cpp
- playground/tables/self_test.cpp
- playground/tables/tql_duckdb.cpp
- playground/tables/tql_duckdb.h

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 01:22:02 +02:00
parent 100aeaa1fc
commit dc373e4b2b
5 changed files with 384 additions and 6 deletions
+86
View File
@@ -11,6 +11,9 @@
#include "lua_engine.h"
#include "tql.h"
#include "tql_to_sql.h"
#ifdef FN_TQL_DUCKDB
# include "tql_duckdb.h"
#endif
#include <cmath>
#include <cstdio>
@@ -2830,6 +2833,89 @@ return {
putenv((char*)"FN_LLM_MOCK_RESPONSE=");
}
#ifdef FN_TQL_DUCKDB
// === phase11 round-trip TQL emit -> DuckDB execute -> match compute_stage ===
{
// Setup tabla "users" con 5 rows.
const char* cells[] = {
"go", "10",
"go", "20",
"py", "30",
"py", "40",
"cpp", "50",
};
TableInput t;
t.name = "users";
t.headers = {"lang", "n"};
t.types = {ColumnType::String, ColumnType::Int};
t.cells = cells;
t.rows = 5;
t.cols = 2;
std::vector<TableInput> tables = {t};
// Caso A: stage 0 simple SELECT
{
State st;
st.stages.resize(1);
auto e = tql_to_sql::emit_sql(st, tables);
check(e.error.empty(), "phase11 rt: stage0 emit OK");
auto r = tql_duckdb::execute(e.sql, e.params, tables);
check(r.error.empty(), "phase11 rt: stage0 execute OK");
check(r.out.rows == 5, "phase11 rt: stage0 5 rows");
check(r.out.cols == 2, "phase11 rt: stage0 2 cols");
}
// Caso B: stage 1 group by lang + count
{
State st;
st.stages.resize(2);
st.stages[1].breakouts.push_back("lang");
st.stages[1].aggregations.push_back({AggFn::Count});
st.active_stage = 1;
auto e = tql_to_sql::emit_sql(st, tables);
check(e.error.empty(), "phase11 rt: group emit OK");
auto r = tql_duckdb::execute(e.sql, e.params, tables);
check(r.error.empty(), "phase11 rt: group execute OK");
check(r.out.rows == 3, "phase11 rt: 3 grupos (go/py/cpp)");
check(r.out.cols == 2, "phase11 rt: cols = lang + count");
}
// Caso C: filter Op::Eq
{
State st;
st.stages.resize(1);
st.stages[0].filters.push_back({0, Op::Eq, "go"});
auto e = tql_to_sql::emit_sql(st, tables);
check(e.error.empty(), "phase11 rt: filter emit OK");
auto r = tql_duckdb::execute(e.sql, e.params, tables);
check(r.error.empty(), "phase11 rt: filter execute OK");
check(r.out.rows == 2, "phase11 rt: filter -> 2 rows go");
}
// Caso D: aggregation sum
{
State st;
st.stages.resize(2);
st.stages[1].breakouts.push_back("lang");
st.stages[1].aggregations.push_back({AggFn::Sum, "n"});
st.active_stage = 1;
auto e = tql_to_sql::emit_sql(st, tables);
check(e.error.empty(), "phase11 rt: sum emit OK");
auto r = tql_duckdb::execute(e.sql, e.params, tables);
check(r.error.empty(), "phase11 rt: sum execute OK");
check(r.out.rows == 3, "phase11 rt: sum 3 grupos");
// Verifica que sum_n para "go" es 30 (10+20)
bool found_go_30 = false;
for (int rr = 0; rr < r.out.rows; ++rr) {
std::string lang = r.out.cells[rr * 2 + 0];
std::string sum = r.out.cells[rr * 2 + 1];
if (lang == "go" && (sum == "30" || sum == "30.0")) found_go_30 = true;
}
check(found_go_30, "phase11 rt: sum_n(go) = 30");
}
}
#endif
std::printf("\n=== %d passed, %d failed ===\n", passed, failed);
return failed == 0 ? 0 : 1;
}