Skip to content
Merged
6 changes: 5 additions & 1 deletion pkg/sql/opt/memo/logical_props_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,11 @@ func (b *logicalPropsBuilder) buildJoinProps(ev ExprView) props.Logical {
// 2. Apply ON predicate filter on resulting rows.
// 3. For outer joins, add non-matching rows, extended with NULL values
// for the null-supplying side of the join.
relational.FuncDeps.MakeProduct(&rightProps.FuncDeps)
if ev.IsJoinApply() {
relational.FuncDeps.MakeApply(&rightProps.FuncDeps)
} else {
relational.FuncDeps.MakeProduct(&rightProps.FuncDeps)
}

notNullCols := leftProps.NotNullCols.Union(rightProps.NotNullCols)

Expand Down
12 changes: 6 additions & 6 deletions pkg/sql/opt/memo/testdata/logprops/constraints
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ scan c@v
├── stats: [rows=0.00612244898, distinct(2)=0.00612244898, distinct(3)=0.00612244898]
├── cost: 0.00648979592
├── key: (1)
├── fd: (1)-->(2,3), ()-->(3)
├── fd: ()-->(3), (1)-->(2)
├── prune: (1)
└── interesting orderings: (+1) (+3,+2,+1)

Expand All @@ -691,7 +691,7 @@ scan c@v
├── stats: [rows=0.00612244898, distinct(2)=0.00612244898, distinct(3)=0.00612244898]
├── cost: 0.00648979592
├── key: (1)
├── fd: (1)-->(2,3), ()-->(2)
├── fd: ()-->(2), (1)-->(3)
├── prune: (1)
└── interesting orderings: (+1) (+3,+2,+1)

Expand All @@ -717,7 +717,7 @@ scan c@v
├── stats: [rows=0.00612244898, distinct(2)=0.00612244898, distinct(3)=0.00612244898]
├── cost: 0.00648979592
├── key: (1)
├── fd: (1)-->(2,3), ()-->(3)
├── fd: ()-->(3), (1)-->(2)
├── prune: (1)
└── interesting orderings: (+1) (+3,+2,+1)

Expand All @@ -730,7 +730,7 @@ scan c@v
├── stats: [rows=0.00612244898, distinct(2)=0.00612244898, distinct(3)=0.00612244898]
├── cost: 0.00648979592
├── key: (1)
├── fd: (1)-->(2,3), ()-->(2)
├── fd: ()-->(2), (1)-->(3)
├── prune: (1)
└── interesting orderings: (+1) (+3,+2,+1)

Expand Down Expand Up @@ -877,7 +877,7 @@ select
├── stats: [rows=0.00612244898, distinct(2)=0.00612244898, distinct(3)=0.00612244898]
├── cost: 1070
├── key: (1)
├── fd: (1)-->(2,3), ()-->(2)
├── fd: ()-->(2), (1)-->(3)
├── prune: (1)
├── interesting orderings: (+1)
├── scan d
Expand Down Expand Up @@ -912,7 +912,7 @@ select
├── stats: [rows=0.00612244898, distinct(2)=0.00612244898, distinct(3)=0.00612244898]
├── cost: 1070
├── key: (1)
├── fd: (1)-->(2,3), ()-->(3)
├── fd: ()-->(3), (1)-->(2)
├── prune: (1)
├── interesting orderings: (+1)
├── scan d
Expand Down
3 changes: 0 additions & 3 deletions pkg/sql/opt/memo/testdata/logprops/groupby
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,9 @@ project
├── grouping columns: z:3(float!null) s:4(string)
├── stats: [rows=1000, distinct(3,4)=1000]
├── key: (3,4)
├── fd: (1)-->(3,4), (3,4)~~>(1) [removed: (1)]
└── project
├── columns: z:3(float!null) s:4(string)
├── stats: [rows=1000, distinct(3,4)=1000]
├── fd: (1)-->(3,4), (3,4)~~>(1) [removed: (1)]
└── scan xyzs
├── columns: x:1(int!null) y:2(int) z:3(float!null) s:4(string)
├── stats: [rows=1000, distinct(3,4)=1000]
Expand Down Expand Up @@ -140,7 +138,6 @@ group-by
├── project
│ ├── columns: z:3(float!null) s:4(string)
│ ├── stats: [rows=1000, distinct(3)=700]
│ ├── fd: (1)-->(3,4), (3,4)~~>(1) [removed: (1)]
│ └── scan xyzs
│ ├── columns: x:1(int!null) y:2(int) z:3(float!null) s:4(string)
│ ├── stats: [rows=1000, distinct(3)=700]
Expand Down
62 changes: 54 additions & 8 deletions pkg/sql/opt/memo/testdata/logprops/index-join
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,50 @@ TABLE a
├── s string
└── x int not null (storing)

# In order to actually create new logical props for the lookup join, we
# need to call ConstructLookupJoin, which only happens when where is a
# remaining filter.
exec-ddl
CREATE TABLE abc (
a INT,
b INT,
c INT,
d INT,
PRIMARY KEY (a, b),
INDEX (c)
)
----
TABLE abc
├── a int not null
├── b int not null
├── c int
├── d int
├── INDEX primary
│ ├── a int not null
│ └── b int not null
└── INDEX secondary
├── c int
├── a int not null
└── b int not null

# In order to actually create new logical props for the index join, we need to
# call ConstructLookupJoin, which only happens when where is a remaining filter.
opt
SELECT * FROM a WHERE s = 'foo' AND x + y = 10
----
select
├── columns: x:1(int!null) y:2(int) s:3(string!null) d:4(decimal!null)
├── stats: [rows=0.476190476, distinct(3)=0.476190476]
├── key: (1)
├── fd: (1)-->(2-4), (3,4)-->(1,2), (2,3)~~>(1,4), ()-->(3)
├── fd: ()-->(3), (1)-->(2,4), (4)-->(1,2), (2,3)~~>(1,4)
├── index-join a
│ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null)
│ ├── stats: [rows=1.42857143]
│ ├── key: (1)
│ ├── fd: (1)-->(2-4), (3,4)-->(1), ()-->(3), (3,4)~~>(1,2), (2,3)~~>(1,4)
│ ├── fd: ()-->(3), (1)-->(2,4), (4)-->(1), (3,4)~~>(1,2), (2,3)~~>(1,4)
│ └── scan a@secondary
│ ├── columns: x:1(int!null) s:3(string!null) d:4(decimal!null)
│ ├── constraint: /-3/4: [/'foo' - /'foo']
│ ├── stats: [rows=1.42857143, distinct(3)=1]
│ ├── key: (1)
│ └── fd: (1)-->(3,4), (3,4)-->(1), ()-->(3)
│ └── fd: ()-->(3), (1)-->(4), (4)-->(1)
└── filters [type=bool, outer=(1,2)]
└── eq [type=bool, outer=(1,2)]
├── plus [type=int, outer=(1,2)]
Expand All @@ -63,12 +85,12 @@ project
├── columns: x:1(int!null) y:2(int) s:3(string!null)
├── stats: [rows=0.476190476, distinct(3)=0.476190476]
├── key: (1)
├── fd: (1)-->(2,3), (2,3)~~>(1), ()-->(3)
├── fd: ()-->(3), (1)-->(2), (2,3)~~>(1)
├── index-join a
│ ├── columns: x:1(int!null) y:2(int) s:3(string)
│ ├── stats: [rows=1.42857143]
│ ├── key: (1)
│ ├── fd: ()-->(3), (1)-->(2,3), (2,3)~~>(1)
│ ├── fd: ()-->(3), (1)-->(2), (2,3)~~>(1)
│ └── scan a@secondary
│ ├── columns: x:1(int!null) s:3(string!null)
│ ├── constraint: /-3/4: [/'foo' - /'foo']
Expand All @@ -81,3 +103,27 @@ project
│ ├── variable: a.x [type=int, outer=(1)]
│ └── variable: a.y [type=int, outer=(2)]
└── const: 10 [type=int]

# Use secondary index to join to multi-valued primary index, but project only
# a subset of the primary columns.
opt
SELECT b, c, d FROM abc WHERE c=1 AND d=2
----
select
├── columns: b:2(int!null) c:3(int!null) d:4(int!null)
├── stats: [rows=0.00204081633, distinct(3)=0.00204081633, distinct(4)=0.00204081633]
├── fd: ()-->(3,4)
├── index-join abc
│ ├── columns: b:2(int!null) c:3(int) d:4(int)
│ ├── stats: [rows=1.42857143]
│ ├── fd: ()-->(3)
│ └── scan abc@secondary
│ ├── columns: a:1(int!null) b:2(int!null) c:3(int!null)
│ ├── constraint: /3/1/2: [/1 - /1]
│ ├── stats: [rows=1.42857143, distinct(3)=1]
│ ├── key: (1,2)
│ └── fd: ()-->(3)
└── filters [type=bool, outer=(4), constraints=(/4: [/2 - /2]; tight), fd=()-->(4)]
└── eq [type=bool, outer=(4), constraints=(/4: [/2 - /2]; tight)]
├── variable: abc.d [type=int, outer=(4)]
└── const: 2 [type=int]
40 changes: 13 additions & 27 deletions pkg/sql/opt/memo/testdata/logprops/join
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@ SELECT (SELECT (VALUES (x), (y))) FROM xysd
project
├── columns: column1:7(int)
├── stats: [rows=1000]
├── fd: ()-->(5), (5)-->(7) [removed: (5)]
├── inner-join-apply
│ ├── columns: x:1(int!null) y:2(int) column1:5(int)
│ ├── stats: [rows=1000]
│ ├── key: (1)
│ ├── fd: (1)-->(2), ()-->(5)
│ ├── fd: (1)-->(2,5)
│ ├── scan xysd
│ │ ├── columns: x:1(int!null) y:2(int)
│ │ ├── stats: [rows=1000]
Expand Down Expand Up @@ -122,7 +121,7 @@ project
├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null) u:5(int!null)
├── stats: [rows=1000]
├── key: (1)
├── fd: (1)-->(2-4), (3,4)~~>(1,2), ()-->(5)
├── fd: (1)-->(2-5), (3,4)~~>(1,2)
├── scan xysd
│ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null)
│ ├── stats: [rows=1000]
Expand All @@ -146,11 +145,10 @@ project
│ │ ├── columns: u:5(int!null)
│ │ ├── outer: (1)
│ │ ├── stats: [rows=111.111111]
│ │ ├── fd: (5)==(1), (1)==(5) [removed: (1)]
│ │ ├── scan uv
│ │ │ ├── columns: u:5(int)
│ │ │ └── stats: [rows=1000]
│ │ └── filters [type=bool, outer=(1,5), constraints=(/1: (/NULL - ]; /5: (/NULL - ]), fd=(5)==(1), (1)==(5)]
│ │ └── filters [type=bool, outer=(1,5), constraints=(/1: (/NULL - ]; /5: (/NULL - ]), fd=(1)==(5), (5)==(1)]
│ │ └── eq [type=bool, outer=(1,5), constraints=(/1: (/NULL - ]; /5: (/NULL - ])]
│ │ ├── variable: uv.u [type=int, outer=(5)]
│ │ └── variable: xysd.x [type=int, outer=(1)]
Expand Down Expand Up @@ -201,12 +199,12 @@ right-join
│ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null) uv.u:8(int)
│ ├── stats: [rows=1000, distinct(8)=1]
│ ├── key: (1)
│ ├── fd: (1)-->(2-4,8), (3,4)~~>(1,2), ()-->(8)
│ ├── fd: ()-->(8), (1)-->(2-4), (3,4)~~>(1,2)
│ ├── left-join-apply
│ │ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null) uv.u:8(int)
│ │ ├── stats: [rows=1000, distinct(8)=1]
│ │ ├── key: (1)
│ │ ├── fd: (1)-->(2-4,8), (3,4)~~>(1,2), ()~~>(8)
│ │ ├── fd: (1)-->(2-4,8), (3,4)~~>(1,2)
│ │ ├── scan xysd
│ │ │ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null)
│ │ │ ├── stats: [rows=1000]
Expand All @@ -223,16 +221,14 @@ right-join
│ │ │ ├── columns: uv.u:8(int!null)
│ │ │ ├── outer: (1)
│ │ │ ├── stats: [rows=110.111111]
│ │ │ ├── fd: (8)==(1), (1)==(8) [removed: (1)]
│ │ │ ├── select
│ │ │ │ ├── columns: uv.u:8(int!null)
│ │ │ │ ├── outer: (1)
│ │ │ │ ├── stats: [rows=111.111111]
│ │ │ │ ├── fd: (8)==(1), (1)==(8) [removed: (1)]
│ │ │ │ ├── scan uv
│ │ │ │ │ ├── columns: uv.u:8(int)
│ │ │ │ │ └── stats: [rows=1000]
│ │ │ │ └── filters [type=bool, outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(8)==(1), (1)==(8)]
│ │ │ │ └── filters [type=bool, outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(1)==(8), (8)==(1)]
│ │ │ │ └── eq [type=bool, outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ])]
│ │ │ │ ├── variable: uv.u [type=int, outer=(8)]
│ │ │ │ └── variable: xysd.x [type=int, outer=(1)]
Expand Down Expand Up @@ -307,16 +303,14 @@ project
│ │ ├── columns: uv.u:8(int!null)
│ │ ├── outer: (1)
│ │ ├── stats: [rows=110.111111]
│ │ ├── fd: (8)==(1), (1)==(8) [removed: (1)]
│ │ ├── select
│ │ │ ├── columns: uv.u:8(int!null)
│ │ │ ├── outer: (1)
│ │ │ ├── stats: [rows=111.111111]
│ │ │ ├── fd: (8)==(1), (1)==(8) [removed: (1)]
│ │ │ ├── scan uv
│ │ │ │ ├── columns: uv.u:8(int)
│ │ │ │ └── stats: [rows=1000]
│ │ │ └── filters [type=bool, outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(8)==(1), (1)==(8)]
│ │ │ └── filters [type=bool, outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ]), fd=(1)==(8), (8)==(1)]
│ │ │ └── eq [type=bool, outer=(1,8), constraints=(/1: (/NULL - ]; /8: (/NULL - ])]
│ │ │ ├── variable: uv.u [type=int, outer=(8)]
│ │ │ └── variable: xysd.x [type=int, outer=(1)]
Expand All @@ -335,7 +329,7 @@ semi-join
├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null)
├── stats: [rows=100000]
├── key: (1)
├── fd: (1)-->(2-4), (3,4)~~>(1,2), (1)==(5), (5)==(1) [removed: (5)]
├── fd: (1)-->(2-4), (3,4)~~>(1,2)
├── scan xysd
│ ├── columns: x:1(int!null) y:2(int) s:3(string) d:4(decimal!null)
│ ├── stats: [rows=1000]
Expand Down Expand Up @@ -367,16 +361,14 @@ semi-join-apply
│ ├── columns: u:5(int) v:6(int!null)
│ ├── outer: (1)
│ ├── stats: [rows=110.111111]
│ ├── fd: (6)==(1), (1)==(6) [removed: (1)]
│ ├── select
│ │ ├── columns: u:5(int) v:6(int!null)
│ │ ├── outer: (1)
│ │ ├── stats: [rows=111.111111]
│ │ ├── fd: (6)==(1), (1)==(6) [removed: (1)]
│ │ ├── scan uv
│ │ │ ├── columns: u:5(int) v:6(int!null)
│ │ │ └── stats: [rows=1000]
│ │ └── filters [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(6)==(1), (1)==(6)]
│ │ └── filters [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
│ │ └── eq [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ])]
│ │ ├── variable: uv.v [type=int, outer=(6)]
│ │ └── variable: xysd.x [type=int, outer=(1)]
Expand Down Expand Up @@ -423,16 +415,14 @@ anti-join-apply
│ ├── columns: u:5(int) v:6(int!null)
│ ├── outer: (1)
│ ├── stats: [rows=110.111111]
│ ├── fd: (6)==(1), (1)==(6) [removed: (1)]
│ ├── select
│ │ ├── columns: u:5(int) v:6(int!null)
│ │ ├── outer: (1)
│ │ ├── stats: [rows=111.111111]
│ │ ├── fd: (6)==(1), (1)==(6) [removed: (1)]
│ │ ├── scan uv
│ │ │ ├── columns: u:5(int) v:6(int!null)
│ │ │ └── stats: [rows=1000]
│ │ └── filters [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(6)==(1), (1)==(6)]
│ │ └── filters [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
│ │ └── eq [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ])]
│ │ ├── variable: uv.v [type=int, outer=(6)]
│ │ └── variable: xysd.x [type=int, outer=(1)]
Expand Down Expand Up @@ -598,12 +588,10 @@ semi-join-apply
│ ├── outer: (1)
│ ├── cardinality: [0 - 5]
│ ├── stats: [rows=5]
│ ├── fd: (1)==(5), (5)==(1) [removed: (1)]
│ ├── select
│ │ ├── columns: u:5(int!null) v:6(int!null)
│ │ ├── outer: (1)
│ │ ├── stats: [rows=111.111111]
│ │ ├── fd: (1)==(5), (5)==(1) [removed: (1)]
│ │ ├── scan uv
│ │ │ ├── columns: u:5(int) v:6(int!null)
│ │ │ └── stats: [rows=1000]
Expand Down Expand Up @@ -635,7 +623,7 @@ anti-join
├── scan uv
│ ├── columns: u:2(int) v:3(int!null)
│ └── stats: [rows=1000]
└── filters [type=bool, outer=(1,2), constraints=(/1: (/NULL - ]; /2: (/NULL - ]), fd=(2)==(1), (1)==(2)]
└── filters [type=bool, outer=(1,2), constraints=(/1: (/NULL - ]; /2: (/NULL - ]), fd=(1)==(2), (2)==(1)]
└── eq [type=bool, outer=(1,2), constraints=(/1: (/NULL - ]; /2: (/NULL - ])]
├── variable: uv.u [type=int, outer=(2)]
└── variable: column1 [type=int, outer=(1)]
Expand All @@ -661,12 +649,10 @@ anti-join-apply
│ ├── outer: (1)
│ ├── cardinality: [0 - 5]
│ ├── stats: [rows=5]
│ ├── fd: (1)==(5), (5)==(1) [removed: (1)]
│ ├── select
│ │ ├── columns: u:5(int!null) v:6(int!null)
│ │ ├── outer: (1)
│ │ ├── stats: [rows=111.111111]
│ │ ├── fd: (1)==(5), (5)==(1) [removed: (1)]
│ │ ├── scan uv
│ │ │ ├── columns: u:5(int) v:6(int!null)
│ │ │ └── stats: [rows=1000]
Expand Down Expand Up @@ -979,7 +965,7 @@ right-join
├── columns: u:1(int) sum:4(decimal) x:5(int!null) y:6(int) s:7(string) d:8(decimal!null)
├── stats: [rows=70000]
├── key: (1,5)
├── fd: (1)~~>(4), (5)-->(6-8), (7,8)~~>(5,6), (1,5)-->(4)
├── fd: (5)-->(6-8), (7,8)~~>(5,6), (1)~~>(4), (1,5)-->(4)
├── group-by
│ ├── columns: u:1(int) sum:4(decimal)
│ ├── grouping columns: u:1(int)
Expand Down Expand Up @@ -1094,7 +1080,7 @@ full-join
├── columns: u:1(int) sum:4(decimal) x:5(int) y:6(int) s:7(string) d:8(decimal)
├── stats: [rows=70000]
├── key: (1,5)
├── fd: (1)~~>(4), (5)-->(6-8), (7,8)~~>(5,6), (1,5)-->(4)
├── fd: (5)-->(6-8), (7,8)~~>(5,6), (1)~~>(4), (1,5)-->(4)
├── group-by
│ ├── columns: u:1(int) sum:4(decimal)
│ ├── grouping columns: u:1(int)
Expand Down
Loading