Skip to content

Commit d0b9a86

Browse files
committed
fix cte in update bug
1 parent fc19401 commit d0b9a86

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ 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
162+
def insert_node({:as = tag, meta, []}, [l, r], acc, context, root) do
163+
{[{tag, meta, [l, r]}], acc, context, root}
164+
end
159165
def insert_node({tag, meta, []}, unit, acc, context, root) when tag in ~w[by in references]a do
160166
{[{tag, meta, predicate(unit ++ acc)}], [], context, root}
161167
end

lib/parser.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ 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
132+
def insert_node({:as = tag, meta, []}, [l, r], acc, context, root) do
133+
{[{tag, meta, [l, r]}], acc, context, root}
134+
end
129135
def insert_node({tag, meta, []}, unit, acc, context, root) when tag in ~w[by in references]a do
130136
{[{tag, meta, predicate(unit ++ acc)}], [], context, root}
131137
end

test/sql_test.exs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,64 @@ 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 "debug complex with" do
147+
sql = ~SQL[
148+
with subset as (
149+
select distinct on (e.id) e.id as row_id
150+
from "pacman.public".entities as e
151+
join "pacman.public".transactions as t on t.entity_id = e.id
152+
where e.status = 'done'
153+
and t.strategy = 'unknown'
154+
and t.sell_record_id is null
155+
and t.buy_date < now() - interval '365 days'
156+
)
157+
update "pacman.public".entities
158+
set status = 'stale'
159+
from subset
160+
where id = subset.row_id
161+
]
162+
163+
output = to_string(sql)
164+
assert output == "with subset as(select distinct on (e.id) e.id as row_id from \"pacman.public\".entities as e join \"pacman.public\".transactions as t on t.entity_id = e.id where e.status = 'done' and t.strategy = 'unknown' and t.sell_record_id is null and t.buy_date < now () - interval '365 days') update \"pacman.public\".entities set status = 'stale' from subset where id = subset.row_id"
165+
end
166+
167+
test "complex with multiple ctes" do
168+
sql = ~SQL[
169+
with customer_rankings as (
170+
select
171+
customer_id,
172+
sum(amount) as total_spent,
173+
rank() over (order by sum(amount) desc) as spending_rank
174+
from transactions
175+
group by customer_id
176+
),
177+
top_customers as (
178+
select
179+
c.customer_id,
180+
c.name,
181+
cr.total_spent,
182+
cr.spending_rank
183+
from customer_rankings cr
184+
join customers c on c.customer_id = cr.customer_id
185+
where cr.spending_rank <= 10
186+
)
187+
select
188+
tc.name,
189+
tc.total_spent,
190+
tc.spending_rank,
191+
case
192+
when tc.total_spent > tc.avg_amount * 2 then 'High Value'
193+
when tc.total_spent > tc.avg_amount then 'Medium Value'
194+
else 'Low Value'
195+
end as customer_segment
196+
from top_customers tc
197+
order by tc.spending_rank, tc.month
198+
]
199+
200+
output = to_string(sql)
201+
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"
202+
end
145203
end
146204

147205
describe "combinations" do

0 commit comments

Comments
 (0)