From c049794dcba785b6a0df997171932296f9227821 Mon Sep 17 00:00:00 2001 From: Diogo Martins Date: Wed, 27 May 2026 19:07:08 +0100 Subject: [PATCH] test: add failing test for cond/if calculation in query filters 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. --- test/calculation_test.exs | 25 +++++++++++++++++++++++++ test/support/resources/post.ex | 14 ++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/test/calculation_test.exs b/test/calculation_test.exs index 5e06c479..c84f8f51 100644 --- a/test/calculation_test.exs +++ b/test/calculation_test.exs @@ -1100,6 +1100,31 @@ defmodule AshPostgres.CalculationTest do assert full_name == "name" end + test "cond/if calculation can be used in query filters" do + post = + Post + |> Ash.Changeset.for_create(:create, %{title: "match", score: 75}) + |> Ash.create!() + + # Loading the cond-based calculation works fine + post = Ash.load!(post, :score_category) + assert post.score_category == 2 + + # Filtering by a cond-based calculation should also work. + # This currently fails with DBConnection.EncodeError because the THEN + # clause literals in the generated CASE WHEN are not type-cast when the + # expression appears in a WHERE clause (they ARE cast in SELECT). + assert [_] = + Post + |> Ash.Query.filter(score_category == 2) + |> Ash.read!() + + assert [] = + Post + |> Ash.Query.filter(score_category == 3) + |> Ash.read!() + end + test "calculation with fragment and cond returning integer doesn't cause Postgrex encoding error" do Post |> Ash.Changeset.for_create(:create, %{title: "hello ash lovers"}) diff --git a/test/support/resources/post.ex b/test/support/resources/post.ex index 14b8c261..706c2e3d 100644 --- a/test/support/resources/post.ex +++ b/test/support/resources/post.ex @@ -1124,6 +1124,20 @@ defmodule AshPostgres.Test.Post do calculate(:c_times_p, :integer, expr(count_of_comments * count_of_linked_posts)) + + calculate( + :score_category, + :integer, + expr( + cond do + score > 100 -> 3 + score > 50 -> 2 + score > 0 -> 1 + true -> 0 + end + ) + ) + calculate( :literal_map_in_expr, :map,