- tableview.{h,cpp}: capa C sobre DuckDB v1.1.3.
* tableview_smoke_test (SELECT 42).
* tableview_count (con sql_filter opcional).
* tableview_page (LEFT JOIN sobre ops.entities via ATTACH para flag promoted).
* tableview_create (inserta entidad type_ref='Table' con metadata pointer).
* tableview_refresh_counts (lee Table entities, count cada DuckDB y cachea
por user_data hash).
* tableview_resolve_path (rel a dirname(ops_db) o absoluto).
- AppState::table_node_counts cache, refrescado tras load_input y mutaciones.
- views_table_overlay: rectangulo redondeado overlay ("Table N") encima
de cada nodo type_ref='Table'. Sigue camara via cam_x/cam_y/zoom.
- main.cpp:
* --test-duckdb <path> smoke (SELECT 42).
* --test-tableview <path> bulk test (1M rows count + page offset).
* Refresh de counts tras load + reload_after_mutation.
* Llamada a views_table_overlay despues de graph_labels_draw.
- CMakeLists.txt: link DuckDB::DuckDB + duckdb_copy_runtime.
Smoke tests:
- 1M rows count + page(offset=500k, limit=10) en 0.65 s end-to-end.
- Operations.db con un nodo Table apuntando a duckdb 1M filas: refresh
reporta correctamente "1 tables, 1000000 total rows".
3.3 KiB
id, title, status, priority, created, revised, completed, depends_on
| id | title | status | priority | created | revised | completed | depends_on | |||
|---|---|---|---|---|---|---|---|---|---|---|
| 0010 | Nodo tabla — DuckDB foundation + render colapsado | completed | high | 2026-04-30 | 2026-05-01 | 2026-05-01 |
|
Objetivo
Tier de almacenamiento tabular para nodos Table que pueden contener millones
de filas sin saturar operations.db ni el grafo. Las "filas" viven en un
.duckdb por proyecto (o por tabla) y se promueven a entidades reales del
grafo solo cuando se necesita interactuar con ellas individualmente
(relaciones, edicion, etc.).
Esta issue cubre fase 1 — vendoring de DuckDB, funciones tableview_*
core, y render colapsado del nodo Table en el viewport. La fase 2 (UI
expandida, paginacion, promote/demote, ingesta CSV/Parquet) va en issue
0011.
Modelo de datos
Dos tiers por proyecto:
projects/<proj>/apps/graph_explorer/
operations.db # SQLite — grafo (entities + relations + filas promovidas)
tables/
<slug>.duckdb # DuckDB — bulk tabular (millones de filas)
El nodo Table es una entidad normal con type_ref = 'Table' y metadata que
apunta a su dataset DuckDB. No contiene filas internamente — es una vista.
{
"duckdb_path": "tables/sospechosos.duckdb",
"table_name": "people",
"row_type": "Person",
"id_column": "id",
"label_column": "name",
"columns": ["name","age","email"],
"filter_sql": "",
"expanded": false
}
Una fila promovida es una entidad en operations.db con metadata de origen:
{
"source": {
"duckdb": "tables/sospechosos.duckdb",
"table": "people",
"row_id": "p_42"
},
"name": "Ana Lopez",
"age": 33
}
Cambios en codigo
- Vendor DuckDB en
cpp/vendor/duckdb/(amalgamation o precompiled). Add library encpp/CMakeLists.txt. - Nuevo paquete
cpp/functions/duck/:duck_open(path) -> duckdb_database(conduckdb_open+duckdb_connect).duck_query(conn, sql, params) -> resultwrapper.
entity_ops(otableview.{h,cpp}en la app) — funciones a nivel de app:tableview_create(ops_db, duckdb_path, duck_table, row_type, char* out_id)crea entidadTablecon metadata + commit enoperations.db.tableview_count(duckdb_path, sql_filter, int64_t* out).tableview_page(duckdb_path, sql_filter, offset, limit, vector<TablePageRow>* out).TablePageRowlleva los campos delcolumns[]resueltos a string +promoted(LEFT JOIN contraops.entities).
graph_load_from_operations: filtrar relacionesCONTAINS_ROW(heredado del modelo viejo, ya no se emiten pero por si se topa con dbs antiguas).views.cpp:- Detectar nodos
type_ref == "Table"al renderizar etiquetas/contadores. - Overlay con
ImGui::GetForegroundDrawList()por cada nodo Table: rectangulo redondeado + label "Table · N filas".
- Detectar nodos
Definicion de hecho
- DuckDB compila y linka en linux + windows (cmake target).
- Smoke test: abrir un
.duckdbvacio, crear tabla con 1M filas (CTAS desderange), correrSELECT COUNT(*)< 100 ms. tableview_create+tableview_count+tableview_pagecon tests.- Un nodo
type_ref='Table'en el grafo se renderiza con un cuadrado overlay encima del circulo GPU, con contador de filas obtenido portableview_count. - El contador refresca al recargar el grafo o tras un INSERT en su DuckDB.