No-Code query builder
Besides the Dataset/Chart layer, a widget can also be built directly — visually, with no SQL written — through the No-Code query builder.
Endpoints
| Route | Purpose |
|---|---|
POST /api/dashboards/builder/schema |
return the DB schema for the builder (tables, columns, suggested relationships) |
POST /api/dashboards/builder/suggest_joins |
heuristic JOIN suggestions based on column naming |
POST /api/dashboards/builder/compile |
compile a visual spec (QuerySpec) into SQL |
POST /api/dashboards/builder/preview |
compile and run it (read-only), returning a row preview |
Saved table relationships
Guessing a JOIN from column naming every single time is wasteful once you already know that orders.customer_id is a foreign key into customers.id. POST /api/dashboards/relations saves that relationship once (in table_relations.json, scoped to one database); a saved relationship is offered in /builder/schema's response ahead of the naming heuristic. POST /api/dashboards/relations/test lets you check a relationship before saving it — it compiles and runs the proposed JOIN as an aggregate COUNT through the same read-only executor as the rest of the module, and reports either a match count or a clear reason it didn't compile or run.
The only source that supports global filters
A widget built from a No-Code spec is the only kind a dashboard can safely graft a global filter onto — that just means adding a condition to a copy of the spec, without touching any query text. Global filters do not apply to raw-SQL widgets (hand-written or from the AI assistant) — rewriting arbitrary SQL text to safely insert a WHERE clause is a much more fragile problem than extending an already-structured spec; this is a deliberate limitation, not a gap.