Problem with a query when upgrading from Ecto 3.5.0

I have this query that worked in Ecto 3.4.6 but does not work in Ecto 3.5.0 or later
EDIT: I wrongly assumed that setting ecto_sql at 3.5.0 also sets ecto at 3.5.0 but it was higher.

from cm in q,
  where:
    not exists(
      fragment(
        """
        SELECT *
        FROM member_tag_assignments
        WHERE tag_id = ANY(?) AND club_member_id = ?
        """,
        type(^secondary_lookup.tag_ids, {:array, :binary_id}),
        cm.id
      )
    )

After upgrade it says:

== Compilation error in file lib/clubbase/club_member_search/club_member_search.ex ==
** (CompileError) lib/clubbase/club_member_search/club_member_search.ex:339: cannot use ^secondary_lookup.tag_ids outside of match clauses

I understand that Elixir thinks it is outside of query but I don’t know why. I have import Ecto.Query at the top. Other queries work OK - only that particular combination of exists and fragment is problematic.

The exists is custom

  defmacro exists(arg) do
    quote do: fragment("EXISTS(?)", unquote(arg))
  end

because it was not yet available back in 3.5

I also tried assigning extracting tag_ids to a variable so that I am not using . inside type but it doesn’t make a difference.

I can’t pinpoint what happened in 3.5 that breaks the query.

The error message seems to indicate that Elixir is not expanding the from correctly. So Elixir then proceeds to expand the arguments and find an invalid ^.

2 Likes

As a start, try and format the from call with parentheses and see if that fixes it?

If not, rename your macro to something not builtin inside Ecto, e.g. our_exists (temporarily!) and use it as before – does that fix it?

To me it looks like it should be working. :thinking:

That is great solution! Awesome advice.