Skip to content
This repository was archived by the owner on Mar 21, 2021. It is now read-only.

Commit 3ae5230

Browse files
committed
Fix for join with parent with LIMIT
1 parent 97a8e5d commit 3ae5230

File tree

3 files changed

+115
-30
lines changed

3 files changed

+115
-30
lines changed

qc0/compile.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,14 @@ def __post_init__(self):
4747
if self.group_by_columns is None:
4848
object.__setattr__(self, "group_by_columns", ())
4949

50-
def join_at(self, from_obj, *by, outer=False):
50+
def join_at(self, from_obj, *by, outer=False, navigation=False):
5151
if self.current is None:
5252
assert not by
5353
from_obj = from_obj.alias()
5454

5555
return self.make(from_obj), from_obj
5656

57-
if self.limit is not None:
57+
if self.limit is not None and navigation:
5858
self = self.make(self.to_select(None).alias())
5959

6060
# NOTE(andreypopp): this is a hacky way to dedup existing, need to consider
@@ -162,6 +162,7 @@ def RelJoin_to_sql(rel: RelJoin, from_obj):
162162
from_obj, _ = from_obj.join_at(
163163
rel.fk.column.table,
164164
(rel.fk.parent.name, rel.fk.column.name),
165+
navigation=not isinstance(rel.rel, RelParent),
165166
)
166167
return val, from_obj
167168

@@ -187,6 +188,7 @@ def RelRevJoin_to_sql(rel: RelRevJoin, from_obj):
187188
from_obj, _ = from_obj.join_at(
188189
rel.fk.parent.table,
189190
(rel.fk.column.name, rel.fk.parent.name),
191+
navigation=True,
190192
)
191193
return value, from_obj
192194

@@ -337,9 +339,15 @@ def ExprOpAggregate_to_sql(op: ExprOpAggregate, from_obj):
337339
if inner_from_obj.limit is not None or inner_from_obj.order is not None:
338340
expr, inner_from_obj = op_to_sql(op.op, from_obj)
339341
inner_from_obj = From.make(inner_from_obj.to_select(expr).alias())
340-
value = op.sig.compile([inner_from_obj.at.c.value])
342+
value = sa.func.coalesce(
343+
op.sig.compile([inner_from_obj.at.c.value]),
344+
op.sig.unit,
345+
)
341346
else:
342-
value = op.sig.compile([expr])
347+
value = sa.func.coalesce(
348+
op.sig.compile([expr]),
349+
op.sig.unit,
350+
)
343351
sel = inner_from_obj.to_select(value).alias()
344352
if from_obj.at is not None:
345353
from_obj, at = from_obj.join_lateral(sel)

tests/snapshots/snap_test_qc0.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,28 @@
828828
snapshots['test_select_filter_end 1'] = '''- n: AFRICA
829829
'''
830830

831+
snapshots['test_select_link_then_take 1'] = '''- c: 51
832+
region: AFRICA
833+
- c: 50
834+
region: AMERICA
835+
- c: 63
836+
region: AMERICA
837+
- c: 48
838+
region: AMERICA
839+
- c: 56
840+
region: MIDDLE EAST
841+
- c: 44
842+
region: AFRICA
843+
- c: 32
844+
region: EUROPE
845+
- c: 41
846+
region: EUROPE
847+
- c: 52
848+
region: ASIA
849+
- c: 56
850+
region: ASIA
851+
'''
852+
831853
snapshots['test_select_nav_select_nav_column_ok 1'] = '''- AFRICA
832854
- AMERICA
833855
- ASIA

tests/test_qc0.py

Lines changed: 81 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def test_select_tables_ok(snapshot):
133133
"""
134134
SELECT jsonb_build_object('region', anon_1.value) AS value
135135
FROM
136-
(SELECT jsonb_agg(CAST(row(region_1.name) AS VARCHAR)) AS value
136+
(SELECT coalesce(jsonb_agg(CAST(row(region_1.name) AS VARCHAR)), CAST('[]' AS JSONB)) AS value
137137
FROM region AS region_1) AS anon_1
138138
"""
139139
)
@@ -186,7 +186,7 @@ def test_select_select_nav_one_ok(snapshot):
186186
"""
187187
SELECT jsonb_build_object('region_names', anon_1.value) AS value
188188
FROM
189-
(SELECT jsonb_agg(region_1.name) AS value
189+
(SELECT coalesce(jsonb_agg(region_1.name), CAST('[]' AS JSONB)) AS value
190190
FROM region AS region_1) AS anon_1
191191
"""
192192
)
@@ -199,7 +199,7 @@ def test_select_select_nav_nav_ok(snapshot):
199199
"""
200200
SELECT jsonb_build_object('region_names', anon_1.value) AS value
201201
FROM
202-
(SELECT jsonb_agg(region_1.name) AS value
202+
(SELECT coalesce(jsonb_agg(region_1.name), CAST('[]' AS JSONB)) AS value
203203
FROM nation AS nation_1
204204
JOIN region AS region_1 ON nation_1.region_id = region_1.id) AS anon_1
205205
"""
@@ -213,10 +213,10 @@ def test_select_select_multiple_ok(snapshot):
213213
"""
214214
SELECT jsonb_build_object('nation_names', anon_1.value, 'region_names', anon_2.value) AS value
215215
FROM
216-
(SELECT jsonb_agg(nation_1.name) AS value
216+
(SELECT coalesce(jsonb_agg(nation_1.name), CAST('[]' AS JSONB)) AS value
217217
FROM nation AS nation_1) AS anon_1
218218
JOIN
219-
(SELECT jsonb_agg(region_1.name) AS value
219+
(SELECT coalesce(jsonb_agg(region_1.name), CAST('[]' AS JSONB)) AS value
220220
FROM region AS region_1) AS anon_2 ON TRUE
221221
"""
222222
)
@@ -253,7 +253,7 @@ def test_select_nav_select_select_ok(snapshot):
253253
SELECT jsonb_build_object('nn', anon_1.value) AS value
254254
FROM region AS region_1
255255
LEFT OUTER JOIN LATERAL
256-
(SELECT jsonb_agg(anon_2.name) AS value
256+
(SELECT coalesce(jsonb_agg(anon_2.name), CAST('[]' AS JSONB)) AS value
257257
FROM
258258
(SELECT nation_1.id AS id,
259259
nation_1.name AS name,
@@ -273,7 +273,7 @@ def test_select_nav_select_select_select_ok(snapshot):
273273
SELECT jsonb_build_object('nnn', anon_1.value) AS value
274274
FROM region AS region_1
275275
LEFT OUTER JOIN LATERAL
276-
(SELECT jsonb_agg(anon_2.name) AS value
276+
(SELECT coalesce(jsonb_agg(anon_2.name), CAST('[]' AS JSONB)) AS value
277277
FROM
278278
(SELECT nation_1.id AS id,
279279
nation_1.name AS name,
@@ -345,7 +345,7 @@ def test_select_back_nav_ok(snapshot):
345345
SELECT jsonb_build_object('nation_names', anon_1.value) AS value
346346
FROM region AS region_1
347347
LEFT OUTER JOIN LATERAL
348-
(SELECT jsonb_agg(anon_2.name) AS value
348+
(SELECT coalesce(jsonb_agg(anon_2.name), CAST('[]' AS JSONB)) AS value
349349
FROM
350350
(SELECT nation_1.id AS id,
351351
nation_1.name AS name,
@@ -371,7 +371,7 @@ def test_select_back_nav_nested_ok(snapshot):
371371
SELECT jsonb_build_object('region_name', region_1.name, 'nations', anon_1.value) AS value
372372
FROM region AS region_1
373373
LEFT OUTER JOIN LATERAL
374-
(SELECT jsonb_agg(jsonb_build_object('nation_name', anon_2.name, 'customer_names', anon_3.value)) AS value
374+
(SELECT coalesce(jsonb_agg(jsonb_build_object('nation_name', anon_2.name, 'customer_names', anon_3.value)), CAST('[]' AS JSONB)) AS value
375375
FROM
376376
(SELECT nation_1.id AS id,
377377
nation_1.name AS name,
@@ -380,7 +380,7 @@ def test_select_back_nav_nested_ok(snapshot):
380380
FROM nation AS nation_1
381381
WHERE nation_1.region_id = region_1.id) AS anon_2
382382
LEFT OUTER JOIN LATERAL
383-
(SELECT jsonb_agg(anon_4.name) AS value
383+
(SELECT coalesce(jsonb_agg(anon_4.name), CAST('[]' AS JSONB)) AS value
384384
FROM
385385
(SELECT customer_1.id AS id,
386386
customer_1.name AS name,
@@ -404,7 +404,7 @@ def test_count_region_ok(snapshot):
404404
"""
405405
SELECT anon_1.value AS value
406406
FROM
407-
(SELECT count(*) AS value
407+
(SELECT coalesce(count(*), 0) AS value
408408
FROM region AS region_1) AS anon_1
409409
"""
410410
)
@@ -417,7 +417,7 @@ def test_count_region_via_opend_ok(snapshot):
417417
"""
418418
SELECT anon_1.value AS value
419419
FROM
420-
(SELECT count(*) AS value
420+
(SELECT coalesce(count(*), 0) AS value
421421
FROM region AS region_1) AS anon_1
422422
"""
423423
)
@@ -430,7 +430,7 @@ def test_count_nation_region_ok(snapshot):
430430
"""
431431
SELECT anon_1.value AS value
432432
FROM
433-
(SELECT count(*) AS value
433+
(SELECT coalesce(count(*), 0) AS value
434434
FROM nation AS nation_1
435435
JOIN region AS region_1 ON nation_1.region_id = region_1.id) AS anon_1
436436
"""
@@ -445,7 +445,7 @@ def test_count_region_select_nation_count_ok(snapshot):
445445
SELECT jsonb_build_object('nation_count', anon_1.value) AS value
446446
FROM region AS region_1
447447
LEFT OUTER JOIN LATERAL
448-
(SELECT count(*) AS value
448+
(SELECT coalesce(count(*), 0) AS value
449449
FROM
450450
(SELECT nation_1.id AS id,
451451
nation_1.name AS name,
@@ -485,7 +485,7 @@ def test_take_region_nation_ok(snapshot):
485485

486486
def test_take_region_x_nation_ok(snapshot):
487487
query = q.region.take(2).nation
488-
assert run(query) == n(
488+
assert run(query, print_op=True) == n(
489489
"""
490490
SELECT CAST(row(nation_1.name) AS VARCHAR) AS value
491491
FROM
@@ -507,7 +507,7 @@ def test_take_region_select_nation_ok(snapshot):
507507
SELECT jsonb_build_object('nation', anon_1.value) AS value
508508
FROM region AS region_1
509509
LEFT OUTER JOIN LATERAL
510-
(SELECT jsonb_agg(anon_2.value) AS value
510+
(SELECT coalesce(jsonb_agg(anon_2.value), CAST('[]' AS JSONB)) AS value
511511
FROM
512512
(SELECT anon_3.name AS value
513513
FROM
@@ -630,7 +630,7 @@ def test_filter_region_by_name_then_select_ok(snapshot):
630630
SELECT jsonb_build_object('name', region_1.name, 'nation_names', anon_1.value) AS value
631631
FROM region AS region_1
632632
LEFT OUTER JOIN LATERAL
633-
(SELECT jsonb_agg(anon_2.name) AS value
633+
(SELECT coalesce(jsonb_agg(anon_2.name), CAST('[]' AS JSONB)) AS value
634634
FROM
635635
(SELECT nation_1.id AS id,
636636
nation_1.name AS name,
@@ -692,7 +692,7 @@ def test_filter_customer_by_region_name_then_count_ok(snapshot):
692692
"""
693693
SELECT anon_1.value AS value
694694
FROM
695-
(SELECT count(*) AS value
695+
(SELECT coalesce(count(*), 0) AS value
696696
FROM customer AS customer_1
697697
JOIN nation AS nation_1 ON customer_1.nation_id = nation_1.id
698698
JOIN region AS region_1 ON nation_1.region_id = region_1.id
@@ -724,7 +724,7 @@ def test_filter_region_by_nation_count_ok(snapshot):
724724
SELECT CAST(row(region_1.name) AS VARCHAR) AS value
725725
FROM region AS region_1
726726
LEFT OUTER JOIN LATERAL
727-
(SELECT count(*) AS value
727+
(SELECT coalesce(count(*), 0) AS value
728728
FROM
729729
(SELECT nation_1.id AS id,
730730
nation_1.name AS name,
@@ -790,7 +790,7 @@ def test_add_lateral_columns_ok(snapshot):
790790
SELECT jsonb_build_object('names', anon_1.value) AS value
791791
FROM region AS region_1
792792
LEFT OUTER JOIN LATERAL
793-
(SELECT jsonb_agg(anon_2.name || '!') AS value
793+
(SELECT coalesce(jsonb_agg(anon_2.name || '!'), CAST('[]' AS JSONB)) AS value
794794
FROM
795795
(SELECT nation_1.id AS id,
796796
nation_1.name AS name,
@@ -900,6 +900,33 @@ def test_date_column_nav_ok(snapshot):
900900
# assert_result_matches(snapshot, query)
901901

902902

903+
def test_date_column_select_ok(snapshot):
904+
query = q.order.select(date=q.orderdate.year)
905+
assert run(query) == n(
906+
"""
907+
SELECT jsonb_build_object('date', EXTRACT(YEAR
908+
FROM order_1.orderdate)) AS value
909+
FROM "order" AS order_1
910+
"""
911+
)
912+
# Too big to test
913+
# assert_result_matches(snapshot, query)
914+
915+
916+
def test_date_column_nav_select_ok(snapshot):
917+
query = q.lineitem.select(date=q.order.orderdate.year)
918+
assert run(query, print_op=True) == n(
919+
"""
920+
SELECT jsonb_build_object('date', EXTRACT(YEAR
921+
FROM order_1.orderdate)) AS value
922+
FROM lineitem AS lineitem_1
923+
JOIN "order" AS order_1 ON lineitem_1.order_id = order_1.id
924+
"""
925+
)
926+
# Too big to test
927+
# assert_result_matches(snapshot, query)
928+
929+
903930
def test_json_literal_ok(snapshot):
904931
query = q.val({"hello": ["world"]})
905932
assert run(query) == n(
@@ -966,7 +993,7 @@ def test_group_region_by_nation_select_ok(snapshot):
966993
(SELECT anon_2.value AS reg
967994
FROM region AS region_1
968995
LEFT OUTER JOIN LATERAL
969-
(SELECT count(anon_3.name) AS value
996+
(SELECT coalesce(count(anon_3.name), 0) AS value
970997
FROM
971998
(SELECT nation_1.id AS id,
972999
nation_1.name AS name,
@@ -1159,7 +1186,7 @@ def test_group_select_nav_ok(snapshot):
11591186
"""
11601187
SELECT anon_1.value AS value
11611188
FROM
1162-
(SELECT count(*) AS value
1189+
(SELECT coalesce(count(*), 0) AS value
11631190
FROM nation AS nation_1) AS anon_1
11641191
"""
11651192
)
@@ -1372,7 +1399,7 @@ def test_around_ok(snapshot):
13721399
SELECT jsonb_build_object('n', region_1.name, 'nn', anon_1.value) AS value
13731400
FROM region AS region_1
13741401
LEFT OUTER JOIN LATERAL
1375-
(SELECT count(*) AS value
1402+
(SELECT coalesce(count(*), 0) AS value
13761403
FROM region AS region_1
13771404
WHERE SUBSTRING(region_1.name
13781405
FROM 1
@@ -1395,7 +1422,7 @@ def test_around_through_ok(snapshot):
13951422
SELECT jsonb_build_object('n', nation_1.name, 'nn', anon_1.value) AS value
13961423
FROM nation AS nation_1
13971424
LEFT OUTER JOIN LATERAL
1398-
(SELECT count(*) AS value
1425+
(SELECT coalesce(count(*), 0) AS value
13991426
FROM
14001427
(SELECT region.id AS id,
14011428
region.name AS name,
@@ -1559,7 +1586,7 @@ def test_sort_by_aggr_ok(snapshot):
15591586
SELECT jsonb_build_object('num_customers', anon_1.value, 'name', region_1.name) AS value
15601587
FROM region AS region_1
15611588
LEFT OUTER JOIN LATERAL
1562-
(SELECT count(*) AS value
1589+
(SELECT coalesce(count(*), 0) AS value
15631590
FROM
15641591
(SELECT nation_1.id AS id,
15651592
nation_1.name AS name,
@@ -1569,7 +1596,7 @@ def test_sort_by_aggr_ok(snapshot):
15691596
WHERE nation_1.region_id = region_1.id) AS anon_3
15701597
JOIN customer AS customer_1 ON anon_3.id = customer_1.nation_id) AS anon_2 ON TRUE
15711598
LEFT OUTER JOIN LATERAL
1572-
(SELECT count(*) AS value
1599+
(SELECT coalesce(count(*), 0) AS value
15731600
FROM
15741601
(SELECT nation_2.id AS id,
15751602
nation_2.name AS name,
@@ -1595,3 +1622,31 @@ def test_sort_then_nav_ok(snapshot):
15951622
"""
15961623
)
15971624
assert_result_matches(snapshot, query)
1625+
1626+
1627+
def test_select_link_then_take(snapshot):
1628+
query = q.nation.select(region=q.region.name, c=q.customer.count()).take(
1629+
10
1630+
)
1631+
assert run(query, print_op=True) == n(
1632+
"""
1633+
SELECT jsonb_build_object('region', region_1.name, 'c', anon_1.value) AS value
1634+
FROM nation AS nation_1
1635+
JOIN region AS region_1 ON nation_1.region_id = region_1.id
1636+
LEFT OUTER JOIN LATERAL
1637+
(SELECT coalesce(count(*), 0) AS value
1638+
FROM
1639+
(SELECT customer_1.id AS id,
1640+
customer_1.name AS name,
1641+
customer_1.address AS address,
1642+
customer_1.nation_id AS nation_id,
1643+
customer_1.phone AS phone,
1644+
customer_1.acctbal AS acctbal,
1645+
customer_1.mktsegment AS mktsegment,
1646+
customer_1.comment AS COMMENT
1647+
FROM customer AS customer_1
1648+
WHERE customer_1.nation_id = nation_1.id) AS anon_2) AS anon_1 ON TRUE
1649+
LIMIT 10
1650+
"""
1651+
)
1652+
assert_result_matches(snapshot, query)

0 commit comments

Comments
 (0)