Skip to content

Commit 3119462

Browse files
authored
fix cte in update bug (#15)
1 parent fc19401 commit 3119462

File tree

3 files changed

+72
-0
lines changed

3 files changed

+72
-0
lines changed

lib/mix/tasks/sql.gen.parser.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ defmodule Mix.Tasks.Sql.Gen.Parser do
156156
def insert_node({:with = tag, meta, []}, [{:ident, _, _} = l, {:parens, _, _} = r, {:as = t2, m2, a}], [], context, root) do
157157
{[], [], context, root ++ [{tag, meta, [{t2, m2, [[l, r] | a]}]}]}
158158
end
159+
def insert_node({:with = tag, meta, []}, unit, acc, context, root) do
160+
{[], [], context, root ++ [{tag, meta, unit ++ acc}]}
161+
end
159162
def insert_node({tag, meta, []}, unit, acc, context, root) when tag in ~w[by in references]a do
160163
{[{tag, meta, predicate(unit ++ acc)}], [], context, root}
161164
end

lib/parser.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ defmodule SQL.Parser do
126126
def insert_node({:with = tag, meta, []}, [{:ident, _, _} = l, {:parens, _, _} = r, {:as = t2, m2, a}], [], context, root) do
127127
{[], [], context, root ++ [{tag, meta, [{t2, m2, [[l, r] | a]}]}]}
128128
end
129+
def insert_node({:with = tag, meta, []}, unit, acc, context, root) do
130+
{[], [], context, root ++ [{tag, meta, unit ++ acc}]}
131+
end
129132
def insert_node({tag, meta, []}, unit, acc, context, root) when tag in ~w[by in references]a do
130133
{[{tag, meta, predicate(unit ++ acc)}], [], context, root}
131134
end

test/sql_test.exs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,72 @@ defmodule SQLTest do
142142
test "regular" do
143143
assert "with temp (n, fact) as (select 0, 1 union all select n + 1, (n + 1) * fact from temp where n < 9)" == to_string(~SQL[with temp (n, fact) as (select 0, 1 union all select n+1, (n+1)*fact from temp where n < 9)])
144144
end
145+
146+
test "complex with" do
147+
sql = ~SQL[
148+
with customer_rankings as(
149+
select customer_id,
150+
sum(amount) as total_spent,
151+
rank() over(order by sum(amount) desc) as spending_rank
152+
from transactions
153+
group by customer_id
154+
),
155+
top_customers as(
156+
select c.customer_id,
157+
c.name,
158+
cr.total_spent,
159+
cr.spending_rank
160+
from customer_rankings cr
161+
join customers c on c.customer_id = cr.customer_id
162+
where cr.spending_rank <= 10
163+
)
164+
select tc.name,
165+
tc.total_spent,
166+
tc.spending_rank
167+
from top_customers tc
168+
order by tc.spending_rank
169+
]
170+
171+
output = to_string(sql)
172+
assert output == "with customer_rankings as(select customer_id, sum(amount) as total_spent, rank() over(order by sum(amount) desc) as spending_rank from transactions group by customer_id), top_customers as(select c.customer_id, c.name, cr.total_spent, cr.spending_rank from customer_rankings cr join customers c on c.customer_id = cr.customer_id where cr.spending_rank <= 10) select tc.name, tc.total_spent, tc.spending_rank from top_customers tc order by tc.spending_rank"
173+
end
174+
175+
test "complex with multiple ctes" do
176+
sql = ~SQL[
177+
with customer_rankings as (
178+
select
179+
customer_id,
180+
sum(amount) as total_spent,
181+
rank() over (order by sum(amount) desc) as spending_rank
182+
from transactions
183+
group by customer_id
184+
),
185+
top_customers as (
186+
select
187+
c.customer_id,
188+
c.name,
189+
cr.total_spent,
190+
cr.spending_rank
191+
from customer_rankings cr
192+
join customers c on c.customer_id = cr.customer_id
193+
where cr.spending_rank <= 10
194+
)
195+
select
196+
tc.name,
197+
tc.total_spent,
198+
tc.spending_rank,
199+
case
200+
when tc.total_spent > tc.avg_amount * 2 then 'High Value'
201+
when tc.total_spent > tc.avg_amount then 'Medium Value'
202+
else 'Low Value'
203+
end as customer_segment
204+
from top_customers tc
205+
order by tc.spending_rank, tc.month
206+
]
207+
208+
output = to_string(sql)
209+
assert output == "with customer_rankings as(select customer_id, sum(amount) as total_spent, rank() over(order by sum(amount) desc) as spending_rank from transactions group by customer_id), top_customers as(select c.customer_id, c.name, cr.total_spent, cr.spending_rank from customer_rankings cr join customers c on c.customer_id = cr.customer_id where cr.spending_rank <= 10) select tc.name, tc.total_spent, tc.spending_rank, case when tc.total_spent > tc.avg_amount * 2 then 'High Value' when tc.total_spent > tc.avg_amount then 'Medium Value' else 'Low Value' end as customer_segment from top_customers tc order by tc.spending_rank, tc.month"
210+
end
145211
end
146212

147213
describe "combinations" do

0 commit comments

Comments
 (0)