Namespaced macros inside the Ecto queries

I’m looking to define a couple of macros in different modules to use them in my ecto queries, as part of the where conditions inside a Ecto.Query.from call. The problem I’m facing is how to call the macros by their fully qualified name (i.e. MyModule.my_macro), without importing the module and using the short name.
A simplified example of what I tried:

defmodule Order do
  schema "orders" do … end

  defmacro recent(o) do
    quote do
      unquote(o).inserted_at > ago(5, "day")

defmodule Quote do
  schema "quotes do … end

  defmacro recent(q) do
    quote do
      unquote(q).inserted_at > ago(3, "day")
# my_context.ex

> require Quote
> Repo.all(from(q in Quote, where: Quote.recent(q))
# ** (Ecto.Query.CompileError) `Quote.recent(q)` is not a valid query expression. If you want to invoke Quote.recent/1 in a query, make sure that the module Quote is required and that recent/1 is a macro

> require Order
> Repo.all(from(o in Order, where: Order.recent(o))

I’m afraid this is a limitation of the way Ecto.Query.from/2 uses Macro.postwalk to parse the query expressions. But I would like someone to confirm (or refute) my suspicion. And could Ecto theoretically be extended to support this case, or is it a hard limitation?

Thank you.

I realize this is a bit of a tangent, but the more normal way to compose queries is:

def recent(queryable \\ __MODULE__) do
  from q in queryable, where: q.inserted_at > ago(3, "day")

Order |> Order.recent() |> Repo.all

# or

from o in Order.recent(), where: == :bar # if you want to filter other things too

Can you elaborate on what you’re trying to achieve here with the macro?

Hi Ben, thanks for your suggestion. Unfortunately it doesn’t fit my needs, as the part which I want to put in a macro would be nested somewhere deep in a query among other “where” conditions. It doesn’t lend itself to the easy composition like in your example. I realize I could use dynamic, so there is a way to do what I need. But I’m rather exploring what else is possible.