Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/sql/src/plan/lowering/variadic_left.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ pub(crate) fn attempt_left_join_magic(
inc_metrics("voj_5");
return Ok(None);
}
// Only columns not from the outer scope introduce bindings.
if left >= oa {
// Only columns not from the outer scope introduce bindings (`oa <= left`)
// And `left` needs to be a column in the left relation (`left < oa + ba`)
if oa <= left && left < oa + ba {
if let Some(bound) = bound_input {
// If left references come from different inputs, bail out.
if bound_to[left] != bound {
Expand Down
200 changes: 200 additions & 0 deletions test/sqllogictest/variadic_outer_join.slt
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# Copyright Materialize, Inc. and contributors. All rights reserved.
#
# Use of this software is governed by the Business Source License
# included in the LICENSE file at the root of this repository.
#
# As of the Change Date specified in that file, in accordance with
# the Business Source License, use of this software will be governed
# by the Apache License, Version 2.0.

mode cockroach

statement ok
CREATE TABLE a (k int)

statement ok
CREATE TABLE b (x int, y int, k int)

statement ok
CREATE TABLE c (k int)

statement ok
INSERT INTO a VALUES (1)

# Only (5, 5, 100) satisfies the b.x = b.y filter.
statement ok
INSERT INTO b VALUES (5, 5, 100), (3, 7, 200)

statement ok
INSERT INTO c VALUES (100)

# Baseline: with the variadic LEFT JOIN lowering disabled, the generic
# outer-join lowering classifies `b.x = b.y` as a right-local filter and
# produces the correct single-row result.
simple conn=mz_system,user=mz_system
ALTER SYSTEM SET enable_variadic_left_join_lowering TO false
----
COMPLETE 0

query T multiline
EXPLAIN OPTIMIZED PLAN FOR
SELECT a.k, b.x, b.y, b.k, c.k
FROM (a LEFT JOIN b ON b.x = b.y) LEFT JOIN c ON b.k = c.k
----
Explained Query:
With
cte l0 =
CrossJoin type=differential
ArrangeBy keys=[[]]
ReadStorage materialize.public.a
ArrangeBy keys=[[]]
Filter (#0 = #1)
ReadStorage materialize.public.b
cte l1 =
Union
Get l0
Project (#0, #2..=#4)
Map (null, null, null)
Join on=(#0 = #1) type=differential
ArrangeBy keys=[[#0]]
Union
Negate
Distinct project=[#0]
Project (#0)
Get l0
Distinct project=[#0]
ReadStorage materialize.public.a
ArrangeBy keys=[[#0]]
ReadStorage materialize.public.a
cte l2 =
ArrangeBy keys=[[#3{k}]]
Filter (#3{k}) IS NOT NULL
Get l1
cte l3 =
Project (#0..=#3)
Join on=(#3{k} = #4{k}) type=differential
Get l2
ArrangeBy keys=[[#0{k}]]
Filter (#0{k}) IS NOT NULL
ReadStorage materialize.public.c
Return
Union
Map (null)
Union
Negate
Project (#0..=#3)
Join on=(#3{k} = #4) type=differential
Get l2
ArrangeBy keys=[[#0]]
Distinct project=[#0]
Project (#3)
Get l3
Get l1
Project (#0..=#3, #3)
Get l3

Source materialize.public.a
Source materialize.public.b
filter=((#0 = #1))
Source materialize.public.c
filter=((#0{k}) IS NOT NULL)

Target cluster: quickstart

EOF

query IIIII rowsort
SELECT a.k, b.x, b.y, b.k, c.k
FROM (a LEFT JOIN b ON b.x = b.y) LEFT JOIN c ON b.k = c.k
----
1 5 5 100 100

# Re-enable the variadic lowering (the system default) and re-run the
# same query. The expected result is unchanged.
# But we have observed a buggy extra NULL-enriched row (in comments below)

simple conn=mz_system,user=mz_system
ALTER SYSTEM SET enable_variadic_left_join_lowering TO true
----
COMPLETE 0

query T multiline
EXPLAIN OPTIMIZED PLAN FOR
SELECT a.k, b.x, b.y, b.k, c.k
FROM (a LEFT JOIN b ON b.x = b.y) LEFT JOIN c ON b.k = c.k
----
Explained Query:
With
cte l0 =
CrossJoin type=differential
ArrangeBy keys=[[]]
ReadStorage materialize.public.a
ArrangeBy keys=[[]]
Filter (#0 = #1)
ReadStorage materialize.public.b
cte l1 =
Union
Get l0
Project (#0, #2..=#4)
Map (null, null, null)
Join on=(#0 = #1) type=differential
ArrangeBy keys=[[#0]]
Union
Negate
Distinct project=[#0]
Project (#0)
Get l0
Distinct project=[#0]
ReadStorage materialize.public.a
ArrangeBy keys=[[#0]]
ReadStorage materialize.public.a
cte l2 =
ArrangeBy keys=[[#3{k}]]
Filter (#3{k}) IS NOT NULL
Get l1
cte l3 =
Project (#0..=#3)
Join on=(#3{k} = #4{k}) type=differential
Get l2
ArrangeBy keys=[[#0{k}]]
Filter (#0{k}) IS NOT NULL
ReadStorage materialize.public.c
Return
Union
Map (null)
Union
Negate
Project (#0..=#3)
Join on=(#3{k} = #4) type=differential
Get l2
ArrangeBy keys=[[#0]]
Distinct project=[#0]
Project (#3)
Get l3
Get l1
Project (#0..=#3, #3)
Get l3

Source materialize.public.a
Source materialize.public.b
filter=((#0 = #1))
Source materialize.public.c
filter=((#0{k}) IS NOT NULL)

Target cluster: quickstart

EOF

query IIIII rowsort
SELECT a.k, b.x, b.y, b.k, c.k
FROM (a LEFT JOIN b ON b.x = b.y) LEFT JOIN c ON b.k = c.k
----
1 5 5 100 100

# 1 NULL NULL NULL NULL

query IIII rowsort
SELECT a.k, b.k, b.x, c.k
FROM (a LEFT JOIN b ON a.k = b.k AND b.x = b.y) LEFT JOIN c ON a.k = c.k
----
1 NULL NULL NULL
Loading