Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Primitive and incomplete SQL SELECT query generation

  • Loading branch information...
commit 0882b0f7bc6fa771646c12a525b373c6e4cb9ecd 1 parent f2c9856
@yrashk authored
View
38 lib/condition.ex
@@ -0,0 +1,38 @@
+defmodule ExQL.Op do
+ def __binary__(record, op, l,r) do
+ quote do
+ unquote(record).new op: unquote(op), exprs: [unquote(l),unquote(r)]
+ end
+ end
+ defmacro __using__(ops) do
+ arity_ops = lc op inlist ops, do: {op, 2}
+ head =
+ quote do
+ import ExQL.Op, only: [__binary__: 4]
+ def __ops__, do: unquote(arity_ops)
+ end
+ tail = lc op inlist ops do
+ quote do
+ defmacro unquote(op).(l,r) do
+ __binary__(unquote(__CALLER__.module), unquote(op), l, r)
+ end
+ end
+ end
+ {:__block__, 0, [head|tail]}
+ end
+end
+defrecord ExQL.Condition, op: nil, exprs: [] do
+ use ExQL.Op, [:<, :<=, :>=, :>, :==, :and, :or]
+
+
+ def to_string(type, condition) do
+ delim = to_binary(op(condition))
+ [[_, first]|rest] = lc value inlist exprs(condition), do: [delim, ExQL.Expression.join(value, type, delim)]
+ ["(",[first|rest],")"]
+ end
+
+end
+
+defimpl ExQL.Expression, for: ExQL.Condition do
+ def join(condition, type, _delim), do: ExQL.Condition.to_string(type, condition)
+end
View
26 lib/expr.ex
@@ -0,0 +1,26 @@
+defprotocol ExQL.Expression do
+ @only [BitString, Number, Atom, List, Record]
+ def join(value, type, delim)
+end
+
+defimpl ExQL.Expression, for: BitString do
+ def join(value, :value, _delim), do: {:value, value}
+ def join(value, :raw, _delim), do: %b{'#{value}'}
+end
+
+defimpl ExQL.Expression, for: Number do
+ def join(value, :value, _delim), do: {:value, value}
+ def join(value, :raw, _delim), do: %b{#{value}}
+end
+
+defimpl ExQL.Expression, for: Atom do
+ def join(value, _, _delim), do: atom_to_binary(value)
+end
+
+defimpl ExQL.Expression, for: List do
+ def join([], _, _), do: nil
+ def join(list, type, delim) do
+ [[_, first]|rest] = lc value inlist list, do: [delim, ExQL.Expression.join(value, type, delim)]
+ [first|rest]
+ end
+end
View
24 lib/exql.ex
@@ -1,5 +1,25 @@
defmodule ExQL do
- def select(options // []) do
- ExQL.Select.new(options)
+ defmacro __using__(_) do
+ quote do
+ import ExQL
+ end
end
+
+ defmacro select(options // []) do
+ quote do
+ ExQL.Select.new(unquote(options))
+ end
+ end
+
+ defmacro expr(c) do
+ quote do
+ f = fn() ->
+ import Elixir.Builtin, except: unquote(ExQL.Condition.__ops__)
+ import ExQL.Condition, only: unquote(ExQL.Condition.__ops__)
+ unquote(c)
+ end
+ f.()
+ end
+ end
+
end
View
27 lib/queries/select.ex
@@ -1,4 +1,4 @@
-defrecord ExQL.Select, [fields: "*",
+defrecord ExQL.Select, [fields: :*,
from: [],
modifiers: [],
joins: [],
@@ -8,4 +8,29 @@ defrecord ExQL.Select, [fields: "*",
group: []
] do
use ExQL.Query
+
+ def statement(:modifiers, query) do
+ ExQL.Expression.join(modifiers(query), :raw, " ")
+ end
+
+ def statement(:fields, query) do
+ ExQL.Expression.join(fields(query), :raw, ", ")
+ end
+
+ def statement(:from, query) do
+ ["FROM", ExQL.Expression.join(from(query), :raw, ", ")]
+ end
+
+ def statement(:where, query) do
+ case where(query) do
+ [] -> nil
+ conds -> ["WHERE", ExQL.Expression.join(conds, :value, " AND ")]
+ end
+ end
+
+ def statement(query) do
+ ExQL.Utils.space(
+ ["SELECT", statement(:modifiers, query), statement(:fields, query),
+ statement(:from, query), statement(:where, query)])
+ end
end
View
11 lib/utils.ex
@@ -0,0 +1,11 @@
+defmodule ExQL.Utils do
+
+ def space([]), do: []
+ def space(list) when is_list(list) do
+ [[_|first]|last] = lc i inlist Enum.filter(list, fn(x) -> x != nil end), do: [" " , space(i)]
+ [first|last]
+ end
+ def space(string) when is_binary(string), do: string
+ def space(other), do: other
+
+end
View
1  rebar.config
@@ -1,3 +1,4 @@
{plugins, [rebar_elixir_compiler]}.
{lib_dirs, ["deps","deps/elixir/rel/elixir/lib"]}.
{pre_hooks, [{compile, "make prepare"}]}.
+{ex_first_files, ["lib/exql.ex","lib/expr.ex"]}.
Please sign in to comment.
Something went wrong with that request. Please try again.