mikl

mikl

Ecto dynamic query (with join) uses wrong table qualifier?

So I have this run-of-the-mill data table with some filtering options, and I’m trying to use dynamic queries to filter it, but I can’t figure out how to get Ecto to use the right table placeholders:

The query:

  def list_company_onboarding_status(sort_direction, sort_field, where_params) do
    Repo.all(
      from os in OnboardingStatus,
        join: c in TorskCompany,
        on: os.company_id == c.id,
        select: {os, c},
        where: ^company_onboarding_status_where_query(where_params),
        order_by: [{^sort_direction, ^sort_field}]
    )
  end

and the dynamic where query generator:

defp company_onboarding_status_where_query(params) do
    Enum.reduce(params, dynamic(true), fn
      {:funnel_step, step}, dynamic ->
        dynamic([os], ^dynamic and os.current_funnel_step == ^step)

      {:migration_cluster, nil}, dynamic ->
        dynamic([c], ^dynamic and is_nil(c.migration_cluster))

      {:migration_cluster, value}, dynamic ->
        dynamic([c], ^dynamic and c.migration_cluster == ^value)

      {:migration_charge, nil}, dynamic ->
        dynamic([c], ^dynamic and is_nil(c.migration_charge))

      {:migration_charge, value}, dynamic ->
        dynamic([c], ^dynamic and c.migration_charge == ^value)

      {_, _}, dynamic ->
        # Not a where parameter
        dynamic
    end)
  end

When I run this, the dynamic where function generates something like dynamic([c], true and c.migration_cluster == ^99), but the query is generated with the wrong placeholder, and errors like this:

[error] GenServer #PID<0.1104.0> terminating
** (Ecto.QueryError) lib/marsvin/companies.ex:254: field `migration_cluster` in `where` does not exist in schema Marsvin.Companies.OnboardingStatus in query:

from o0 in Marsvin.Companies.OnboardingStatus,
  join: t1 in Marsvin.Companies.TorskCompany,
  on: o0.company_id == t1.id,
  where: true and o0.migration_cluster == ^99,
  order_by: [desc_nulls_last: o0.newest_change_at],
  select: {o0, t1}

    (elixir 1.11.3) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3

The problem is that despite my dynamic part using the c prefix for the where, indicating that it’s a column from the TorskCompany table, not the OnboardingStatus table, the generated query uses the o0 prefix for that column instead of the correct t1, causing the error since it’s looking at the wrong table.

How do I get Ecto to generate the query correctly?

Marked As Solved

mikl

mikl

Ah, I figured it out, the dynamic part has to list both placeholders for Ecto to understand it correctly, like this:

  defp company_onboarding_status_where_query(params) do
    Enum.reduce(params, dynamic(true), fn
      {:funnel_step, step}, dynamic ->
        dynamic([os, c], ^dynamic and os.current_funnel_step == ^step)

      {:migration_cluster, nil}, dynamic ->
        dynamic([os, c], ^dynamic and is_nil(c.migration_cluster))

      {:migration_cluster, value}, dynamic ->
        dynamic([os, c], ^dynamic and c.migration_cluster == ^value)

      {:migration_charge, nil}, dynamic ->
        dynamic([os, c], ^dynamic and is_nil(c.migration_charge))

      {:migration_charge, value}, dynamic ->
        dynamic([os, c], ^dynamic and c.migration_charge == ^value)

      {_, _}, dynamic ->
        # Not a where parameter
        dynamic
    end)
  end

The change here is that every dynamic line now starts with dynamic([os, c] rather than just dynamic([c].

Where Next?

Popular in Questions Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 131117 1222
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40165 209
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement