Where
src/ui/app.js — runTile(sql) calls paramArgs(sql, app.state.varValues) with a favorite's raw, possibly multi-statement SQL. paramArgs (src/core/query-params.js) gates on isRowReturning(stmt)/detectParams(stmt) over the whole string — it does not call splitStatements first, unlike readStatementParams (which dashboardParams, unfilledParams, and the dashboard filter bar all use).
Why deferred
For a hypothetical multi-statement favorite (e.g. SET x = 1; SELECT {year:UInt16} FROM t), dashboardParams/unfilledParams correctly detect year via per-statement splitting and would render/gate a filter field for it, but paramArgs(sql, …) — seeing the whole blob's leading statement — could omit param_year even when the field is filled, since it doesn't split first.
In practice this is currently unreachable: dashboardTileSql (src/core/dashboard.js) sends a favorite's raw SQL as a single HTTP POST body, and ClickHouse's HTTP interface already rejects true multi-statement text before param substitution would ever matter — so a multi-statement favorite fails at the CH level regardless of this inconsistency. Filed as a known latent gap in the code (found during #152's review) that would need to be closed if a future phase adds multi-statement dashboard-tile support, not because it's user-visible today.
Suggested fix (future)
Either have runTile compute paramArgs over the same per-statement split dashboardParams/readStatementParams use, or make paramArgs itself split via splitStatements and OR the per-statement gates — whichever keeps a single source of truth for "does this SQL need param substitution."
Where
src/ui/app.js—runTile(sql)callsparamArgs(sql, app.state.varValues)with a favorite's raw, possibly multi-statement SQL.paramArgs(src/core/query-params.js) gates onisRowReturning(stmt)/detectParams(stmt)over the whole string — it does not callsplitStatementsfirst, unlikereadStatementParams(whichdashboardParams,unfilledParams, and the dashboard filter bar all use).Why deferred
For a hypothetical multi-statement favorite (e.g.
SET x = 1; SELECT {year:UInt16} FROM t),dashboardParams/unfilledParamscorrectly detectyearvia per-statement splitting and would render/gate a filter field for it, butparamArgs(sql, …)— seeing the whole blob's leading statement — could omitparam_yeareven when the field is filled, since it doesn't split first.In practice this is currently unreachable:
dashboardTileSql(src/core/dashboard.js) sends a favorite's raw SQL as a single HTTP POST body, and ClickHouse's HTTP interface already rejects true multi-statement text before param substitution would ever matter — so a multi-statement favorite fails at the CH level regardless of this inconsistency. Filed as a known latent gap in the code (found during #152's review) that would need to be closed if a future phase adds multi-statement dashboard-tile support, not because it's user-visible today.Suggested fix (future)
Either have
runTilecomputeparamArgsover the same per-statement splitdashboardParams/readStatementParamsuse, or makeparamArgsitself split viasplitStatementsand OR the per-statement gates — whichever keeps a single source of truth for "does this SQL need param substitution."