fix(tesseract): cast bound param on measure filters#11176
Conversation
Measure filters rendered a HAVING comparison without the numeric cast
that the per-dialect templates emit, so on BigQuery a bound value stayed
a raw string and the engine rejected the comparison (INT64 vs STRING).
Resolve a measure filter member to the "number" cast type ("boolean"
for boolean measures) so the param is wrapped per dialect, e.g.
CAST(? AS FLOAT64) on BigQuery.
CORE-541
Instead of casting every non-boolean measure to a number, derive the cast type from the measure type: string and time measures are not numeric scalars and must not be coerced, so they render without a cast. Aggregations, count, rank and number measures stay numeric; min/max fall through to the numeric default since their operand type isn't known here.
|
Claude finished @waralexrom's task in 2m 22s —— View job Code ReviewReview: ✅ LGTM — small note on min/max fallback. 0 high, 0 medium, 1 low.
SummaryThe fix is correct and minimal. The bug was that Correctness
Tests
Low —
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #11176 +/- ##
==========================================
- Coverage 83.70% 83.70% -0.01%
==========================================
Files 257 257
Lines 79465 79465
==========================================
- Hits 66517 66513 -4
- Misses 12948 12952 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
Under the Tesseract native SQL planner (
CUBEJS_TESSERACT_SQL_PLANNER=true), filtering on an aggregate measure produced aHAVINGcomparison with a raw bound parameter and no numeric cast. On BigQuery the param stayed a string, so the engine rejected the comparison (No matching signature for operator < for argument types: INT64, STRING). The standard planner emitsCAST(? AS FLOAT64)here; Tesseract did not. Fixes #11031.Changes
numbercast type (booleanfor boolean measures), so the bound value is wrapped by the per-dialect cast template — e.g.CAST(? AS FLOAT64)on BigQuery,CAST(? AS DOUBLE)on Presto, and no cast where the dialect template is a no-op (Postgres).stringandtimemeasures are not numeric scalars and now render without a numeric cast (the standard planner coerces them to float). Aggregations, count, rank and number measures stay numeric;min/maxfall through to the numeric default since their operand type isn't known at this point.Testing
cargo test -p cubesqlplanner— 1057 passed. New filter tests intests/filter/to_sql.rscover a numeric measure filter (cast applied) and a string measure filter (no cast).CAST(? AS FLOAT64)under the native planner.