Skip to content

Commit 35d743c

Browse files
committed
Fix binding index and in
1 parent 04fe463 commit 35d743c

File tree

4 files changed

+27
-10
lines changed

4 files changed

+27
-10
lines changed

lib/parser.ex

+11-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ defmodule SQL.Parser do
99
def context(?[), do: :"[]"
1010
def context(?(), do: :"()"
1111

12+
def type(%param{}), do: param
13+
def type(param) when is_float(param), do: :float
14+
def type(param) when is_integer(param), do: :integer
15+
def type(param) when is_map(param), do: :map
16+
def type(param) when is_list(param), do: {:list, Enum.uniq(Enum.map(param, &type/1))}
17+
def type(param) when is_binary(param), do: :string
18+
def type(_param), do: nil
19+
1220
def type(?., :integer), do: :float
1321
def type(b, type) when b in ?0..?9 and type in ~w[nil integer float]a, do: type || :integer
1422
def type(_b, _type), do: :ident
@@ -229,12 +237,12 @@ defmodule SQL.Parser do
229237
parse(rest, binary, opts, end_line, end_column, nil, data, unit ++ [{:"\#{}", [line: line, column: column, end_line: end_line, end_column: end_column], [result]}], context, metadata, acc, root)
230238
{rest, end_line, end_column, result} when is_atom(result) ->
231239
if param = binding[result] do
232-
parse(rest, binary, update_in(opts, [:params], &(&1++[param])), end_line, end_column, nil, data, unit ++ [{:binding, [line: line, column: column, end_line: end_line, end_column: end_column], [length(opts[:params])]}], context, metadata, acc, root)
240+
parse(rest, binary, update_in(opts, [:params], &(&1++[param])), end_line, end_column, nil, data, unit ++ [{:binding, [type: type(param), line: line, column: column, end_line: end_line, end_column: end_column], [length(opts[:params])+1]}], context, metadata, acc, root)
233241
else
234242
raise ArgumentError, "The variable #{result} is not defined"
235243
end
236-
{rest, end_line, end_column, {result, _}} ->
237-
parse(rest, binary, update_in(opts, [:params], &(&1++[result])), end_line, end_column, nil, data, unit ++ [{:binding, [line: line, column: column, end_line: end_line, end_column: end_column], [length(opts[:params])]}], context, metadata, acc, root)
244+
{rest, end_line, end_column, {param, _}} ->
245+
parse(rest, binary, update_in(opts, [:params], &(&1++[param])), end_line, end_column, nil, data, unit ++ [{:binding, [type: type(param), line: line, column: column, end_line: end_line, end_column: end_column], [length(opts[:params])+1]}], context, metadata, acc, root)
238246
end
239247
end
240248
def parse(<<?), rest::binary>>, _binary, opts, line, column, type, data, unit, :"()" = context, metadata, acc, root) do

lib/string.ex

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ defmodule SQL.String do
2626
def token_to_sql({:"\#{}", _, [value]}, _mod) do
2727
"\#{#{value}}"
2828
end
29+
def token_to_sql({:in, _, [right, {:binding, _, _} = left]}, mod) do
30+
"#{mod.token_to_sql(right)} = ANY(#{mod.token_to_sql(left)})"
31+
end
2932
def token_to_sql({tag, _, value}, mod) when tag in ~w[; ,]a do
3033
"#{mod.token_to_sql(value)}#{mod.token_to_sql(tag)}"
3134
end

test/sql_test.exs

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ defmodule SQLTest do
4242

4343
test "to_sql/1" do
4444
45-
assert {"select id, email from users where email = $0", ["[email protected]"]} == to_sql(~SQL"""
45+
assert {"select id, email from users where email = $1", ["[email protected]"]} == to_sql(~SQL"""
4646
select id, email
4747
where email = #{email}
4848
from users
@@ -51,7 +51,7 @@ defmodule SQLTest do
5151

5252
test "can parse multiple queries" do
5353
54-
assert {"select id, email where email = $0 from users; select id from users", [email]} == to_sql(~SQL"""
54+
assert {"select id, email where email = $1 from users; select id from users", [email]} == to_sql(~SQL"""
5555
select id, email
5656
where email = #{email}
5757
from users;
@@ -282,8 +282,8 @@ defmodule SQLTest do
282282

283283
test "interpolation" do
284284
var = 1
285-
assert [{:select, _, [{:binding, _, [0]}]}] = ~SQL[select #{var}].tokens
286-
assert [{:select, _, [{:binding, _, [0]}]}] = ~SQL[select #{
285+
assert [{:select, _, [{:binding, _, [1]}]}] = ~SQL[select #{var}].tokens
286+
assert [{:select, _, [{:binding, _, [1]}]}] = ~SQL[select #{
287287
{}
288288
}].tokens
289289
end

test/string_test.exs

+9-3
Original file line numberDiff line numberDiff line change
@@ -195,20 +195,26 @@ defmodule SQL.StringTest do
195195
assert ["id"] == var2.params
196196
sql = ~SQL[select #{var2}, #{var1}]
197197
assert [var2, 1] == sql.params
198-
assert "select $0, $1" == to_string(sql)
198+
assert "select $1, $2" == to_string(sql)
199199
end
200200

201201
test ". syntax" do
202202
map = %{k: "v"}
203203
sql = ~SQL[select #{map.k <> "v"}]
204204
assert ["vv"] == sql.params
205-
assert "select $0" == to_string(sql)
205+
assert "select $1" == to_string(sql)
206206
end
207207

208208
test "code" do
209209
sql = ~SQL[select #{0}, #{%{k: 1}}]
210210
assert [0, %{k: 1}] == sql.params
211-
assert "select $0, $1" == to_string(sql)
211+
assert "select $1, $2" == to_string(sql)
212+
end
213+
214+
test "in" do
215+
sql = ~SQL"select #{1} in #{[1, 2]}"
216+
assert [1, [1, 2]] == sql.params
217+
assert "select $1 = ANY($2)" == to_string(sql)
212218
end
213219
end
214220

0 commit comments

Comments
 (0)