I am trying to better understand how
Ecto.Query.API.fragment/1 works under the hood. I was wondering if anyone could help me with the following:
Why is the parity 1 when in examples like below, it looks like the parity is 2:
from p in Post,
where: is_nil(p.published_at) and
fragment("lower(?)", p.title) == ^title
When I look for the implementation of this function in the source code, it says the function is for documentation purposes only. How can I learn how the function is implemented?
Refer to a named atom binding in the parent query.
This is available only inside subqueries.
See the "Named binding" section in `Ecto.Query` for more information.
def parent_as(binding), do: doc! [binding]
defp doc!(_) do
raise "the functions in Ecto.Query.API should not be invoked directly, " <>
"they serve for documentation purposes only"
Do fragments prevent sql injections? If so, is it similar to how a prepared statement works? The syntax looks similar.
August 26, 2020, 5:29am
Fragment is part of the Ecto DSL which is implemented with macros. This is why the “function” (it’s not a function call) can actually take in any amount of arguments. The documentation generator requires a specified arity (not parity), so 1 is used there (not sure why they’re documented as functions and not macros though).
The meat of fragments is implemented in
https://github.com/elixir-ecto/ecto/blob/a33f79fb577ac765f5b6c70b7f4be9fab94c9ebb/lib/ecto/query/builder.ex#L133-L156 – but as it’s macro stuff, it’s pretty difficult to read for a first timer.
Fragments indeed don’t use string interpolation if you add the inputs as parameters to the call like in the examples, so it prevents injection AFAIK.