diff --git a/src/sqerl.erl b/src/sqerl.erl index c1d95d6..533b0e6 100644 --- a/src/sqerl.erl +++ b/src/sqerl.erl @@ -356,10 +356,24 @@ expr({Table, Field}, _Safe) when is_atom(Table), is_atom(Field) -> [convert(Table), $., convert(Field)]; expr({Expr1, as, Alias}, Safe) when is_atom(Alias) -> [expr2(Expr1, Safe), <<" AS ">>, convert(Alias)]; +expr({select, _} = Subquery, Safe) -> + [$(, sql2(Subquery, Safe), $) ]; +expr({select, _, _} = Subquery, Safe) -> + [$(, sql2(Subquery, Safe), $)]; +expr({select, _, _, _} = Subquery, Safe) -> + [$(, sql2(Subquery, Safe), $)]; +expr({select, _, _, _, _} = Subquery, Safe) -> + [$(, sql2(Subquery, Safe), $)]; +expr({select, _, _, _, _, _} = Subquery, Safe) -> + [$(, sql2(Subquery, Safe), $)]; +expr({select, _, _, _, _, _, _} = Subquery, Safe) -> + [$(, sql2(Subquery, Safe), $)]; expr({call, FuncName, []}, _Safe) -> [convert(FuncName), <<"()">>]; expr({call, FuncName, Params}, _Safe) -> [convert(FuncName), $(, make_list(Params, fun param/1), $)]; +expr({over, Left, Right}, Safe) -> + [expr2(Left, Safe), <<" OVER ">>, $(, extra_clause(Right, Safe) ,$)]; expr({Val, Op, {select, _} = Subquery}, Safe) -> subquery(Val, Op, Subquery, Safe); expr({Val, Op, {select, _, _} = Subquery}, Safe) -> @@ -429,9 +443,16 @@ expr2(Expr, _Safe) when is_atom(Expr) -> convert(Expr); expr2(Expr, Safe) -> expr(Expr, Safe). param({Key, Value}) when is_atom(Key) -> - [convert(Key), <<" := ">>, encode(Value)]; + case Value of + {call, _FuncName, _Params} = Call -> + [convert(Key), <<" := ">>, expr(Call, undefined)]; + _ -> + [convert(Key), <<" := ">>, encode(Value)] + end; param(Key) when is_atom(Key) -> convert(Key); +param({call, _FuncName, _Params} = Call) -> + expr(Call, undefined); param(Value) -> encode(Value). diff --git a/test/sqerl_tests.erl b/test/sqerl_tests.erl index baff481..c4aaf37 100644 --- a/test/sqerl_tests.erl +++ b/test/sqerl_tests.erl @@ -137,8 +137,8 @@ safe_test_() -> {select,distinct,name,{from,gymnast}}}}}) }, - {<<"SELECT name FROM developer WHERE name IN ((SELECT DISTINCT name FROM gymnast)" - "UNION (SELECT name FROM dancer WHERE ((name LIKE 'Mikhail%') OR (country = 'Russia')))" + {<<"SELECT name FROM developer WHERE name IN ((SELECT DISTINCT name FROM gymnast) " + "UNION (SELECT name FROM dancer WHERE ((name LIKE 'Mikhail%') OR (country = 'Russia'))) " "WHERE (name LIKE 'M%') ORDER BY name DESC LIMIT 5, 10)">>, ?_safe_test({select,name, {from,developer}, @@ -186,6 +186,14 @@ safe_test_() -> {<<"SELECT name FROM search_people(age := 18)">>, ?_safe_test({select,name,{from,{call,search_people,[{age, 18}]}}}) + }, + + {<<"SELECT * FROM search_people(age := 18, area := postal_area(code := 1234))">>, + ?_safe_test({select,'*',{from,{call,search_people,[{age, 18},{area,{call,postal_area,[{code, 1234}]}}]}}}) + }, + + {<<"SELECT * FROM outer_function(column1, inner_function())">>, + ?_safe_test({select,'*',{from,{call,outer_function,[column1,{call,inner_function,[]}]}}}) } ] }. @@ -280,6 +288,14 @@ unsafe_test_() -> {<<"SELECT NOT (foo = bar)">>, ?_unsafe_test({select,{'!',"foo = bar"}}) + }, + + {<<"SELECT row_number() OVER ( ORDER BY id DESC), bar FROM lol">>, + ?_unsafe_test({select, [{over, {call, row_number, []}, {order_by, [{id, desc}]}}, bar], {from, lol}}) + }, + + {<<"SELECT foo FROM (SELECT foo FROM bar) AS baz">>, + ?_unsafe_test({select, [foo], {from, {{select, [foo], {from, bar}}, as, baz}}}) } ] }.