fix: cond/if calculation in query filters causes DBConnection.EncodeError#766
Merged
zachdaniel merged 1 commit intoMay 28, 2026
Merged
Conversation
cond/if expressions used in query filters produce a
DBConnection.EncodeError because the THEN clause literals in the
generated CASE WHEN are not type-cast (e.g. THEN 3) when the
expression appears in a WHERE clause, while they ARE properly cast
(e.g. THEN 3::bigint) in a SELECT clause.
The root cause is in ash_sql's expr.ex: when embedded? is true
(which it is for cond/if expression nodes), the literal handler
at default_dynamic_expr/6 skips type casting entirely, so the
Fragment parameters end up as {value, :any}. Postgrex then cannot
infer the correct encoding from context and defaults to text,
causing the binary vs integer mismatch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Using a
condorifexpression calculation in a query filter causes aDBConnection.EncodeErrorbecause the THEN/ELSE clause literals in the generated SQLCASE WHENare not type-cast in the WHERE context, while they are properly cast in SELECT.Reproduction
The PR adds a failing test that demonstrates the issue. A
score_categorycalculation usingcondis added to thePosttest resource:Loading the calculation works fine — the SQL correctly casts THEN values:
Filtering on the same calculation fails:
The missing
::bigintcasts on the THEN literals cause Postgrex to fail parameter encoding.Root cause
The bug is in
ash_sql(deps/ash_sql/lib/expr.ex).When Ash converts
condto nestedIfnodes, the%If{}struct hasembedded?: true. TheIfhandler indefault_dynamic_expr/6callsdo_dynamic_exprfor each THEN/ELSE value, passing the resolved type (e.g.:integer). However, becauseembedded?istrue, the call dispatches to thedefault_dynamic_expr(query, other, bindings, true, acc, type)clause (line ~2990), which callshandle_literalbut does not apply type casting — unlike theembedded? = falseclause (line ~3037) which does callparameterized_type+type_expr.This means the THEN value
3is passed as a raw integer into the Fragment's:casted_exprparameter with type:any. Postgrex cannot infer the correct encoding from the CASE context and defaults totext, producing the binary-vs-integer mismatch.Impact
Any
cond/ifexpression calculation (returning integers, floats, etc.) that is used in anAsh.Query.filterwill fail. This also affects Ash policyFilterCheckmodules that reference such calculations, breaking authorization on bulk operations.