Convert Abacus expression into Ecto DSL expressions, and use them for where, selects, order_by, group_by or having clauses.




This library combines abacus and ecto.

Pipe user-supplied abacus terms into queries like this:

from(b in BlogPost) 
|> AbacusSql.where(~S[title == "abacus"])
|> AbacusSql.select("author", "author.name")

and you'll get a query that will not only filter for the posts title, but also automatically joins to the users table, adding the name of the author to the select list:

#Ecto.Query<from b in AbacusSqlTest.BlogPost, left_join: a in assoc(b, :author),
 where: b.title == ^"abacus", select: %{"author" => a.name}>


Allow additional type casts as such:

config :abacus_sql, :allowed_casts, [
  :unit, :my_custom_type

These casts will be available as function calls: unit("30 m") and will be converted into a cast expression: fragment("(?)::text::unit", type(^"30 m", :string)).

Allow additional SQL functions:

config :abacus_sql, :allowed_function_calls, [
  :extract, :coalesce, :st_buffer

These SQL functions will be available as normal function calls.

To add your own convert_ast clauses, configure a macro_module:

config :abacus_sql, :macro_module, MyApp.MacroModule

defmodule MyApp.MacroModule do
  import AbacusSql.Term
  @spec convert_ast(any, Ecto.Query.t, list, integer) :: {any, Ecto.Query.t, list}
  # don't add a catch-all here, a FunctionClauseError on this function will automatically be handled gracefully
  def convert_ast({{"my_macro", _, nil}, ctx, args}, query, params, root_id) do
    {[arg0 | _rest], query, params} = reduce_args(args, query, params, root_id)
    ast = {:frament, ctx, [
      raw: "MY MACRO IS ",
      expr: arg0,
      raw: " YEAH"
    {ast, query, params}


If available in Hex, the package can be installed by adding abacus_sql to your list of dependencies in mix.exs:

def deps do
    {:abacus_sql, "~> 0.1.0"}

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/abacus_sql.