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

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].