Comparison with `nil` forbidden with `coalesce/2`

I have a query that has a fallback if the result is nil:

def my_function(query, field, value) when not is_nil(value) do
  from(row in query,
    where: field(row, ^field) < ^value,
    order_by: [desc: field(row, ^field)],
    limit: 1,
    select: field(row, ^field)
  )
  |> Repo.one()
  |> Kernel.||(value)
end

EDIT: This query works currently works just fine.

Imporant: note how value is guaranteed to be non-nil.

I would like to use this query as a sub-query, but that requires implementing the fallback in SQL. I assumed coalesce was the right approach:

from(row in query,
  where: field(row, ^field) < ^value,
  order_by: [desc: field(row, ^field)],
  limit: 1,
  select: field(row, ^field) |> coalesce(^value) # fallback has moved here
)
|> Repo.one()

But this raises an error I don’t understand:

** (ArgumentError) comparing `field(row, ^field)` with `nil` is forbidden as it is unsafe. If you want to check if a value is nil, use is_nil/1 instead

I know that nil comparison is generally disallowed by Ecto. But isn’t a comparison with nil the whole point of coalesce? What am I missing?

No coalesce here.

But then why wouldn’t the first query raise too?

EDIT: Oh, I never said that the first query works in the OP. I’ll clarify.

1 Like