fix(insights): cast toFloatOrDefault default value to float#58714
fix(insights): cast toFloatOrDefault default value to float#58714sampennington wants to merge 1 commit into
Conversation
ClickHouse's toFloat64OrDefault requires the default value to have the same type as the cast target (Float64). When a HogQL query passes an integer literal as the default (e.g. toFloatOrDefault(prop, 0)), the default is a UInt8 and ClickHouse fails with "Default value type should be same as cast type. Expected Float64. Actual UInt8" (code 36). Map toFloatOrDefault to a positional template that wraps the default in accurateCast(..., 'Float64'), so any numeric or string default literal works. The function now requires both arguments — a single-argument form is equivalent to toFloatOrZero. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
🎭 Playwright didn't run on this PR — your changes touch code that could affect E2E behavior, but Playwright is opt-in via label now to keep CI cost down. Add the Most PRs don't need this. Real regressions still get caught on master and fix-forward. |
Automated code reviewTightly scoped fix for a real, deterministic ClickHouse failure ( Needs discussion — the 2-arg requirement is a breaking change
The PR body argues single-arg is "degenerate" (equivalent to
Two lower-risk alternatives if any single-arg usage exists:
This is the one item I'd block on until the usage question is answered. Functional gap — Postgres backend silently ignores the default
This is pre-existing (not introduced by this PR), and the printer test at Minor
Positive
Verdict: Needs discussion — confirm there are no existing single-arg |
Problem
Insight queries (e.g. Trends with a
math_hogqlseries) that calltoFloatOrDefaultwith an integer default literal fail deterministically withDefault value type should be same as cast type. Expected Float64. Actual UInt8(code 36).ClickHouse's
toFloat64OrDefaultrequires the default value to already have the cast target type (Float64). HogQL passed the default through unchanged, so an integer literal like0reached ClickHouse as aUInt8.Part of an effort to reduce deterministic product-analytics query-builder failures — tracking dashboard: https://metabase.prod-us.posthog.dev/dashboard/207-product-analytics-insight-query-failures
Changes
Map
toFloatOrDefaultto a positional template that wraps the default inaccurateCast(..., 'Float64'), so any numeric or string default literal works. The function now requires both arguments — a single-argumenttoFloatOrDefaultwas degenerate (equivalent totoFloatOrZero). Updated the Postgres-translation printer test parameter to pass a default accordingly.How did you test this code?
I'm an agent. Added an executing HogQL test (
test_to_float_or_default_with_integer_default) that callstoFloatOrDefaultwith integer defaults and runs against ClickHouse. Verified it fails onorigin/masterwith the exactcode 36error and passes with the fix. Ran the fulltest_mapping.pysuite (including the existingtest_function_mappingwhich exercises float defaults) and the printer test suite — all pass. No snapshot files reference the function.Publish to changelog?
no
🤖 Agent context
Agent-authored (Claude Code, Opus 4.7). Requires human review.
Root cause traced from a production failing Trends query whose
math_hogqlseries containedcoalesce(toFloatOrDefault(properties.pause_duration_minutes, 0), 1). Considered keeping the 1-argument form, but it duplicatestoFloatOrZeroand a positional template cannot be variadic; requiring two arguments keeps the fix minimal and the template simple.