api-v2/lib/api/parser/expression_to_ecto.ex

60 lines
1.8 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}]}) do
field_atom = String.to_atom(field)
dynamic([q], field(q, ^field_atom) in ^vals)
end
defp build_dynamic(other) do
raise "AST no soportado o mal formado: #{inspect(other)}"
end
end