You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Recursive CTE silently casts recursive term to the static term's type, producing wrong results or a non-terminating query #25893
A recursive CTE silently casts the recursive term's output to the static term's types, even when the cast loses data (for example Float64 → Int64). The query returns wrong values. If the stop condition depends on the lost part, the query never terminates.
LogicalPlanBuilder::to_recursive_query calls coerce_plan_expr_for_schema(recursive_term, static_schema), which casts to any castable type (added for #9794).
To Reproduce
Tested on main (1d9be2e), default dialect, datafusion-cli:
-- Wrong result: expected n = 1, 1.5, 2, 2.5
WITH RECURSIVE r AS (
SELECT1AS n, 0AS i
UNION ALLSELECT n +0.5, i +1FROM r WHERE i <3
) SELECT n, arrow_typeof(n) FROM r ORDER BY i;
-- 1 Int64 / 1 Int64 / 1 Int64 / 1 Int64
-- Never terminates: n is truncated from 1.5 back to 1, so n < 2 stays true
WITH RECURSIVE r AS (
SELECT1AS n
UNION ALLSELECT n +0.5FROM r WHERE n <2
) SELECTcount(*) FROM r;
EXPLAIN shows the recursive term as CAST(CAST(n AS Float64) + 0.5 AS Int64).
Expected behavior
An error at planning time, as PostgreSQL does:
ERROR: recursive query "r" column 1 has type integer in non-recursive term but type numeric overall
HINT: Cast the output of the non-recursive term to the correct type.
Additional context
Suggested fix: in to_recursive_query, return a planning error when the cast from the recursive type to the static type can lose data — float/decimal → integer, and changes of type category such as Utf8 → Int64. Keep the current cast for integer → integer so the existing #9794 test (a::bigint + 2 into Int32) still passes. The error message should tell the user to cast the non-recursive term.
Alternative: widen both terms to their common type, as UNION does. That requires planning the recursive term again against the widened work-table schema.
Activity
goutamadwant commentedon Oct 2, 2026
I have a fix in #25893. Pls take a look and let me know if this looks good. thanks!
fix: validate recursive CTE column coercion (apache#25956)