69 lines
2.0 KiB
Elixir
69 lines
2.0 KiB
Elixir
defmodule ExpressionToEcto do
|
|
import Ecto.Query
|
|
|
|
def to_dynamic([]), do: true
|
|
|
|
def to_dynamic([single]), do: build_dynamic(single)
|
|
|
|
def to_dynamic(ast), do: build_dynamic(ast)
|
|
|
|
# Operadores lógicos
|
|
defp build_dynamic({:or, left, right}) do
|
|
dynamic([q], ^build_dynamic(left) or ^build_dynamic(right))
|
|
end
|
|
|
|
defp build_dynamic({:and, left, right}) do
|
|
dynamic([q], ^build_dynamic(left) and ^build_dynamic(right))
|
|
end
|
|
|
|
# Comparaciones con número
|
|
defp build_dynamic({:comparison, [{:field, field}, op, {:number, val}]}) do
|
|
field_atom = String.to_atom(field)
|
|
|
|
case op do
|
|
:== -> dynamic([q], field(q, ^field_atom) == ^val)
|
|
:!= -> dynamic([q], field(q, ^field_atom) != ^val)
|
|
:> -> dynamic([q], field(q, ^field_atom) > ^val)
|
|
:< -> dynamic([q], field(q, ^field_atom) < ^val)
|
|
:>= -> dynamic([q], field(q, ^field_atom) >= ^val)
|
|
:<= -> dynamic([q], field(q, ^field_atom) <= ^val)
|
|
other -> raise "Operador no soportado: #{inspect(other)}"
|
|
end
|
|
end
|
|
|
|
# Comparaciones con string
|
|
defp build_dynamic({:comparison, [{:field, field}, op, {:string, val}]}) when op in [:==, :!=] do
|
|
field_atom = String.to_atom(field)
|
|
case op do
|
|
:== -> dynamic([q], field(q, ^field_atom) == ^val)
|
|
:!= -> dynamic([q], field(q, ^field_atom) != ^val)
|
|
end
|
|
end
|
|
|
|
# ILIKE
|
|
defp build_dynamic({:comparison, [{:field, field}, :ilike, {:string, val}]}) do
|
|
field_atom = String.to_atom(field)
|
|
pattern = "#{val}"
|
|
dynamic([q], ilike(field(q, ^field_atom), ^pattern))
|
|
end
|
|
|
|
# IN
|
|
defp build_dynamic({:comparison, [{:field, field}, :in, {:list, vals}]}) when is_list(vals) do
|
|
field_atom = String.to_atom(field)
|
|
|
|
parsed_vals =
|
|
Enum.map(vals, fn
|
|
{:string, val} -> val
|
|
{:number, val} -> val
|
|
other -> raise "Tipo de dato no soportado en IN: #{inspect(other)}"
|
|
end)
|
|
|
|
dynamic([q], field(q, ^field_atom) in ^parsed_vals)
|
|
end
|
|
|
|
|
|
defp build_dynamic(other) do
|
|
raise "AST no soportado o mal formado: #{inspect(other)}"
|
|
end
|
|
end
|