Skip to content

Commit 04fe463

Browse files
committed
Fix code interpolation
1 parent bcab56d commit 04fe463

File tree

2 files changed

+43
-22
lines changed

2 files changed

+43
-22
lines changed

lib/parser.ex

+20-17
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ defmodule SQL.Parser do
222222
def parse(<<?#, ?{, rest::binary>>, binary, opts, line, column, _type, data, unit, context, metadata, acc, root) do
223223
column = column+2
224224
binding = opts[:binding]
225-
case interpolation(rest, line, column) do
225+
case interpolation(rest, binding, line, column) do
226226
{:error, "", end_line, end_column, _acc} ->
227227
error!([line: line, column: column, end_line: end_line, end_column: end_column, file: "", snippet: binary, opening_delimiter: :"\#{", expected_delimiter: :"}"])
228228
{rest, end_line, end_column, result} when binding == false ->
@@ -233,7 +233,7 @@ defmodule SQL.Parser do
233233
else
234234
raise ArgumentError, "The variable #{result} is not defined"
235235
end
236-
{rest, end_line, end_column, result} ->
236+
{rest, end_line, end_column, {result, _}} ->
237237
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)
238238
end
239239
end
@@ -287,27 +287,30 @@ defmodule SQL.Parser do
287287
parse(rest, binary, opts, line, column+1, type(b, type), data ++ [b], unit, context, metadata, acc, root)
288288
end
289289

290-
def interpolation(binary, line, column, type \\ :var, acc \\ [], n \\ 0)
291-
def interpolation("" = rest, line, column, _type, acc, 0), do: {:error, rest, line, column, acc}
292-
def interpolation(<<?}, rest::binary>>, line, column, :var, acc, 0) do
290+
def interpolation(binary, binding, line, column, type \\ :var, acc \\ [], n \\ 0)
291+
def interpolation("" = rest, _binding, line, column, _type, acc, 0), do: {:error, rest, line, column, acc}
292+
def interpolation(<<?}, rest::binary>>, _binding, line, column, :var, acc, 0) do
293293
{<<rest::binary>>, line, column+1, List.to_atom(acc)}
294294
end
295-
def interpolation(<<?}, rest::binary>>, line, column, :code, acc, 0) do
296-
{<<rest::binary>>, line, column+1, acc}
295+
def interpolation(<<?}, rest::binary>>, binding, line, column, :code, acc, 0) do
296+
{<<rest::binary>>, line, column+1, Code.eval_string("#{acc}", binding)}
297+
end
298+
def interpolation(<<?{, rest::binary>>, binding, line, column, _type, acc, n) do
299+
interpolation(rest, binding, line, column, :code, acc ++ [?{], n+1)
297300
end
298-
def interpolation(<<?{, rest::binary>>, line, column, _type, acc, n) do
299-
interpolation(rest, line, column, :code, acc ++ [?{], n+1)
301+
def interpolation(<<?}, rest::binary>>, binding, line, column, type, acc, n) do
302+
interpolation(rest, binding, line, column+1, type, acc ++ [?}], n-1)
300303
end
301-
def interpolation(<<?}, rest::binary>>, line, column, type, acc, n) do
302-
interpolation(rest, line, column+1, type, acc ++ [?}], n-1)
304+
def interpolation(<<v, rest::binary>>, binding, line, column, :var = type, acc, n) when v in ?0..?9 and acc != [] do
305+
interpolation(rest, binding, line+1, column, type, acc ++ [v], n)
303306
end
304-
def interpolation(<<v, rest::binary>>, line, column, :var = type, acc, n) when v in ?a..?z or v in ?A..?Z or (v == ?_ and acc != []) do
305-
interpolation(rest, line+1, column, type, acc ++ [v], n)
307+
def interpolation(<<v, rest::binary>>, binding, line, column, :var = type, acc, n) when v in ?a..?z or v in ?A..?Z or (v == ?_ and acc != []) do
308+
interpolation(rest, binding, line+1, column, type, acc ++ [v], n)
306309
end
307-
def interpolation(<<?\n, rest::binary>>, line, column, _type, acc, n) do
308-
interpolation(rest, line+1, column, :code, acc ++ [?\n], n)
310+
def interpolation(<<?\n, rest::binary>>, binding, line, column, _type, acc, n) do
311+
interpolation(rest, binding, line+1, column, :code, acc ++ [?\n], n)
309312
end
310-
def interpolation(<<v, rest::binary>>, line, column, _type, acc, n) do
311-
interpolation(rest, line, column+1, :code, acc ++ [v], n)
313+
def interpolation(<<v, rest::binary>>, binding, line, column, _type, acc, n) do
314+
interpolation(rest, binding, line, column+1, :code, acc ++ [v], n)
312315
end
313316
end

test/string_test.exs

+23-5
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,29 @@ defmodule SQL.StringTest do
187187
end
188188
end
189189

190-
test "interpolation" do
191-
var1 = 1
192-
var0 = "id"
193-
var2 = ~SQL[select #{var0}]
194-
assert "select $0, $1" == to_string(~SQL[select #{var2}, #{var1}])
190+
describe "interpolation" do
191+
test "binding" do
192+
var1 = 1
193+
var0 = "id"
194+
var2 = ~SQL[select #{var0}]
195+
assert ["id"] == var2.params
196+
sql = ~SQL[select #{var2}, #{var1}]
197+
assert [var2, 1] == sql.params
198+
assert "select $0, $1" == to_string(sql)
199+
end
200+
201+
test ". syntax" do
202+
map = %{k: "v"}
203+
sql = ~SQL[select #{map.k <> "v"}]
204+
assert ["vv"] == sql.params
205+
assert "select $0" == to_string(sql)
206+
end
207+
208+
test "code" do
209+
sql = ~SQL[select #{0}, #{%{k: 1}}]
210+
assert [0, %{k: 1}] == sql.params
211+
assert "select $0, $1" == to_string(sql)
212+
end
195213
end
196214

197215
describe "operators" do

0 commit comments

Comments
 (0)