Ecto.Query.API.fragment
fragment
, go back to Ecto.Query.API module for more information.
Send fragments directly to the database.
It is not possible to represent all possible database queries using Ecto's query syntax. When such is required, it is possible to use fragments to send any expression to the database:
def unpublished_by_title(title) do
from p in Post,
where: is_nil(p.published_at) and
fragment("lower(?)", p.title) == ^title
end
Every occurrence of the ?
character will be interpreted as a place
for additional argument. If the literal character ?
is required,
it can be escaped with \\?
(one escape for strings, another for
fragment).
In the example above, we are using the lower procedure in the database to downcase the title column.
It is very important to keep in mind that Ecto is unable to do any
type casting described above when fragments are used. You can
however use the type/2
function to give Ecto some hints:
fragment("lower(?)", p.title) == type(^title, :string)
Or even say the right side is of the same type as p.title
:
fragment("lower(?)", p.title) == type(^title, p.title)
Keyword fragments
In order to support databases that do not have string-based queries, like MongoDB, fragments also allow keywords to be given:
from p in Post,
where: fragment(title: ["$eq": ^some_value])
Defining custom functions using macros and fragment
You can add a custom Ecto query function using macros. For example to expose SQL's coalesce function you can define this macro:
defmodule CustomFunctions do
defmacro coalesce(left, right) do
quote do
fragment("coalesce(?, ?)", unquote(left), unquote(right))
end
end
end
To have coalesce/2 available, just import the module that defines it.
import CustomFunctions
The only downside is that it will show up as a fragment when inspecting the Elixir query. Other than that, it should be equivalent to a built-in Ecto query function.