Skip to content

Commit 7328320

Browse files
committed
right and full join
1 parent 3377121 commit 7328320

3 files changed

Lines changed: 114 additions & 2 deletions

File tree

abstra_json_sql/apply.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,8 +561,8 @@ def apply_from(
561561
)
562562
]
563563

564-
if join.join_type == "LEFT":
565-
data += [
564+
if join.join_type == "LEFT" or join.join_type == "FULL":
565+
left_data = [
566566
{
567567
**add_scope_to_keys(table.name, row),
568568
**add_scope_to_keys(
@@ -583,6 +583,30 @@ def apply_from(
583583
for join_row in join_table.data
584584
)
585585
]
586+
data.extend(left_data)
587+
if join.join_type == "RIGHT" or join.join_type == "FULL":
588+
right_data = [
589+
{
590+
**add_scope_to_keys(join_table.name, join_row),
591+
**add_scope_to_keys(
592+
table.name,
593+
{table_col.name: None for table_col in table.columns},
594+
),
595+
}
596+
for join_row in join_table.data
597+
if not any(
598+
apply_expression(
599+
join.on,
600+
{
601+
**ctx,
602+
**add_scope_to_keys(table.name, row),
603+
**add_scope_to_keys(join_table.name, join_row),
604+
},
605+
)
606+
for row in table.data
607+
)
608+
]
609+
data.extend(right_data)
586610
else:
587611
data = [{**add_scope_to_keys(table.name, row)} for row in table.data]
588612
return data

abstra_json_sql/eval_test.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,93 @@ def test_left_outer_join(self):
578578
],
579579
)
580580

581+
def test_right_join(self):
582+
code = "select a.foo, b.bar from a right outer join b on a.id = b.a_id"
583+
tables = InMemoryTables(
584+
tables=[
585+
Table(
586+
name="a",
587+
columns=[
588+
Column(name="id", type="int"),
589+
Column(name="foo", type="text"),
590+
],
591+
data=[
592+
{"id": 1, "foo": "a1"},
593+
{"id": 2, "foo": "a2"},
594+
{"id": 3, "foo": "a3"},
595+
],
596+
),
597+
Table(
598+
name="b",
599+
columns=[
600+
Column(name="a_id", type="int"),
601+
Column(name="bar", type="text"),
602+
],
603+
data=[
604+
{"a_id": 1, "bar": "b1"},
605+
{"a_id": 2, "bar": "b2"},
606+
{"a_id": 2, "bar": "b3"},
607+
{"a_id": 4, "bar": "b4"},
608+
],
609+
),
610+
],
611+
)
612+
ctx = {}
613+
result = eval_sql(code=code, tables=tables, ctx=ctx)
614+
self.assertEqual(
615+
result,
616+
[
617+
{"foo": "a1", "bar": "b1"},
618+
{"foo": "a2", "bar": "b2"},
619+
{"foo": "a2", "bar": "b3"},
620+
{"foo": None, "bar": "b4"},
621+
],
622+
)
623+
624+
def test_full_join(self):
625+
code = "select a.foo, b.bar from a full outer join b on a.id = b.a_id"
626+
tables = InMemoryTables(
627+
tables=[
628+
Table(
629+
name="a",
630+
columns=[
631+
Column(name="id", type="int"),
632+
Column(name="foo", type="text"),
633+
],
634+
data=[
635+
{"id": 1, "foo": "a1"},
636+
{"id": 2, "foo": "a2"},
637+
{"id": 3, "foo": "a3"},
638+
],
639+
),
640+
Table(
641+
name="b",
642+
columns=[
643+
Column(name="a_id", type="int"),
644+
Column(name="bar", type="text"),
645+
],
646+
data=[
647+
{"a_id": 1, "bar": "b1"},
648+
{"a_id": 2, "bar": "b2"},
649+
{"a_id": 2, "bar": "b3"},
650+
{"a_id": 4, "bar": "b4"},
651+
],
652+
),
653+
],
654+
)
655+
ctx = {}
656+
result = eval_sql(code=code, tables=tables, ctx=ctx)
657+
self.assertEqual(
658+
result,
659+
[
660+
{"foo": "a1", "bar": "b1"},
661+
{"foo": "a2", "bar": "b2"},
662+
{"foo": "a2", "bar": "b3"},
663+
{"foo": "a3", "bar": None},
664+
{"foo": None, "bar": "b4"},
665+
],
666+
)
667+
581668
def test_complete(self):
582669
code = "\n".join(
583670
[

abstra_json_sql/tokens.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"LEFT JOIN",
4747
"RIGHT JOIN",
4848
"FULL JOIN",
49+
"FULL OUTER JOIN",
4950
"CROSS JOIN",
5051
"NATURAL JOIN",
5152
"JOIN",

0 commit comments

Comments
 (0)