Has anyone needed to use Ecto.Repo.prepare_query/3 to modify queries?

Hi Folks.

I was trying to use Ecto.Repo.prepare_query/3 : https://hexdocs.pm/ecto/Ecto.Repo.html#c:prepare_query/3

My goal is very similar to the example presented on the docs. I want to add soft delete when retrieving data from the database, but I noticed every Repo.get, Repo.get_by, Repo.one sends the operation variable of this callback as :all … so it does not matter which operation I am doing… it will always end up like :all…

I also noticed that migrations are trigging this callback too…

My questions are:

Is there a way to do pattern match against specific operations such as: :one, :get_by, :get and so on?

Is there a way to skip migrations when using this?

Thanks in advance.


However in your use case I would check if the DB views aren’t better choice by the chance. This will give you better control and will be similarly explicit when you would need to query data from the “all” table.

1 Like

Thank you

There is, but be sure you have the required ecto and ecto_sql version installed:

Thank you. I am not sure if this is the exactly solution because I’d like something to avoid developers have to remember to pass an option… my solution was that:

@doc "Skip migrations when running query modifications"
      @spec prepare_query(atom(), Ecto.Query.t(), any()) :: {Ecto.Query.t(), any()}
      def prepare_query(_operation, %{from: %{source: {"schema_migrations", _}}} = query, opts) do
        {query, opts}

It‘s not the same, as your code will only work for repo changes which target that one table, and only if it‘s not cofigured to a different name. This is besides the fact that ecto queries are opaque and not safe to be inspected like that.

Can you please clarify how to use it properly?

I have calls like that: Repo.get, Repo.one, Repo.all and so on… spread over the entire codebase.

I don’t want other developers have to remember to set any kind of option when using those functions above, but I still want to skip all migrations when using prepare_query to get only valid calls.

How can I do this by using this option?


When you run migrations then opts in prepare_query will have :schema_migration set to true. So you can skip enforcing whatever you’re doing for anything being done in migrations.

1 Like

Now I got it… thank you very much.