Skip to content

Commit 3377121

Browse files
committed
left outer join
1 parent 4dcbd11 commit 3377121

2 files changed

Lines changed: 70 additions & 3 deletions

File tree

abstra_json_sql/apply.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,6 @@ def apply_from(
539539
table = tables.get_table(from_part.table)
540540
if not table:
541541
raise ValueError(f"Table {from_part.table} not found")
542-
data = table.data
543542
if from_part.join:
544543
for join in from_part.join:
545544
join_table = tables.get_table(join.table)
@@ -550,7 +549,7 @@ def apply_from(
550549
**add_scope_to_keys(table.name, row),
551550
**add_scope_to_keys(join_table.name, join_row),
552551
}
553-
for row in data
552+
for row in table.data
554553
for join_row in join_table.data
555554
if apply_expression(
556555
join.on,
@@ -561,8 +560,31 @@ def apply_from(
561560
},
562561
)
563562
]
563+
564+
if join.join_type == "LEFT":
565+
data += [
566+
{
567+
**add_scope_to_keys(table.name, row),
568+
**add_scope_to_keys(
569+
join_table.name,
570+
{join_col.name: None for join_col in join_table.columns},
571+
),
572+
}
573+
for row in table.data
574+
if not any(
575+
apply_expression(
576+
join.on,
577+
{
578+
**ctx,
579+
**add_scope_to_keys(table.name, row),
580+
**add_scope_to_keys(join_table.name, join_row),
581+
},
582+
)
583+
for join_row in join_table.data
584+
)
585+
]
564586
else:
565-
data = [{**add_scope_to_keys(table.name, row)} for row in data]
587+
data = [{**add_scope_to_keys(table.name, row)} for row in table.data]
566588
return data
567589

568590

abstra_json_sql/eval_test.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ def test_join(self):
508508
data=[
509509
{"id": 1, "foo": "a1"},
510510
{"id": 2, "foo": "a2"},
511+
{"id": 3, "foo": "a3"},
511512
],
512513
),
513514
Table(
@@ -519,6 +520,7 @@ def test_join(self):
519520
data=[
520521
{"a_id": 1, "bar": "b1"},
521522
{"a_id": 2, "bar": "b2"},
523+
{"a_id": 2, "bar": "b3"},
522524
],
523525
),
524526
],
@@ -530,6 +532,49 @@ def test_join(self):
530532
[
531533
{"foo": "a1", "bar": "b1"},
532534
{"foo": "a2", "bar": "b2"},
535+
{"foo": "a2", "bar": "b3"},
536+
],
537+
)
538+
539+
def test_left_outer_join(self):
540+
code = "select a.foo, b.bar from a left outer join b on a.id = b.a_id"
541+
tables = InMemoryTables(
542+
tables=[
543+
Table(
544+
name="a",
545+
columns=[
546+
Column(name="id", type="int"),
547+
Column(name="foo", type="text"),
548+
],
549+
data=[
550+
{"id": 1, "foo": "a1"},
551+
{"id": 2, "foo": "a2"},
552+
{"id": 3, "foo": "a3"},
553+
],
554+
),
555+
Table(
556+
name="b",
557+
columns=[
558+
Column(name="a_id", type="int"),
559+
Column(name="bar", type="text"),
560+
],
561+
data=[
562+
{"a_id": 1, "bar": "b1"},
563+
{"a_id": 2, "bar": "b2"},
564+
{"a_id": 2, "bar": "b3"},
565+
],
566+
),
567+
],
568+
)
569+
ctx = {}
570+
result = eval_sql(code=code, tables=tables, ctx=ctx)
571+
self.assertEqual(
572+
result,
573+
[
574+
{"foo": "a1", "bar": "b1"},
575+
{"foo": "a2", "bar": "b2"},
576+
{"foo": "a2", "bar": "b3"},
577+
{"foo": "a3", "bar": None},
533578
],
534579
)
535580

0 commit comments

Comments
 (0)