exec-ddl
CREATE TABLE abcd (a INT, b INT, c INT, INDEX (a,b))
----

exec-ddl
CREATE TABLE small (m INT, n INT)
----

exec-ddl
ALTER TABLE small INJECT STATISTICS '[
  {
    "columns": ["m"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10,
    "distinct_count": 10
  }
]'
----

# We can only test lookup stat generation when using non-covering indexes
# (that's when we create a group with LookupJoin). We can compare the
# logical properties against those of the top-level join.

opt
SELECT * FROM small JOIN abcd ON a=m
----
inner-join (lookup abcd)
 ├── columns: m:1(int!null) n:2(int) a:6(int!null) b:7(int) c:8(int)
 ├── key columns: [9] = [9]
 ├── lookup columns are key
 ├── fd: (1)==(6), (6)==(1)
 ├── prune: (2,7,8)
 ├── interesting orderings: (+6,+7)
 ├── inner-join (lookup abcd@abcd_a_b_idx)
 │    ├── columns: m:1(int!null) n:2(int) a:6(int!null) b:7(int) abcd.rowid:9(int!null)
 │    ├── key columns: [1] = [6]
 │    ├── fd: (9)-->(6,7), (1)==(6), (6)==(1)
 │    ├── scan small
 │    │    ├── columns: m:1(int) n:2(int)
 │    │    ├── prune: (1,2)
 │    │    └── unfiltered-cols: (1-5)
 │    └── filters (true)
 └── filters (true)

# Filter that gets pushed down on both sides, but comes back into the ON
# condition for the lookup side.
opt
SELECT * FROM small JOIN abcd ON a=m WHERE n > 2
----
inner-join (lookup abcd)
 ├── columns: m:1(int!null) n:2(int!null) a:6(int!null) b:7(int) c:8(int)
 ├── key columns: [9] = [9]
 ├── lookup columns are key
 ├── fd: (1)==(6), (6)==(1)
 ├── prune: (7,8)
 ├── interesting orderings: (+6,+7)
 ├── inner-join (lookup abcd@abcd_a_b_idx)
 │    ├── columns: m:1(int!null) n:2(int!null) a:6(int!null) b:7(int) abcd.rowid:9(int!null)
 │    ├── key columns: [1] = [6]
 │    ├── fd: (9)-->(6,7), (1)==(6), (6)==(1)
 │    ├── select
 │    │    ├── columns: m:1(int) n:2(int!null)
 │    │    ├── prune: (1)
 │    │    ├── scan small
 │    │    │    ├── columns: m:1(int) n:2(int)
 │    │    │    └── prune: (1,2)
 │    │    └── filters
 │    │         └── gt [type=bool, outer=(2), constraints=(/2: [/3 - ]; tight)]
 │    │              ├── variable: n:2 [type=int]
 │    │              └── const: 2 [type=int]
 │    └── filters (true)
 └── filters (true)

# Filter that applies to the right side and gets pulled back into the ON
# condition.
opt
SELECT * FROM small JOIN abcd ON a=m WHERE b > 2
----
inner-join (lookup abcd)
 ├── columns: m:1(int!null) n:2(int) a:6(int!null) b:7(int!null) c:8(int)
 ├── key columns: [9] = [9]
 ├── lookup columns are key
 ├── fd: (1)==(6), (6)==(1)
 ├── prune: (2,8)
 ├── interesting orderings: (+6,+7)
 ├── inner-join (lookup abcd@abcd_a_b_idx)
 │    ├── columns: m:1(int!null) n:2(int) a:6(int!null) b:7(int!null) abcd.rowid:9(int!null)
 │    ├── lookup expression
 │    │    └── filters
 │    │         ├── gt [type=bool, outer=(7), constraints=(/7: [/3 - ]; tight)]
 │    │         │    ├── variable: b:7 [type=int]
 │    │         │    └── const: 2 [type=int]
 │    │         └── eq [type=bool, outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
 │    │              ├── variable: m:1 [type=int]
 │    │              └── variable: a:6 [type=int]
 │    ├── fd: (9)-->(6,7), (1)==(6), (6)==(1)
 │    ├── scan small
 │    │    ├── columns: m:1(int) n:2(int)
 │    │    ├── prune: (1,2)
 │    │    └── unfiltered-cols: (1-5)
 │    └── filters (true)
 └── filters (true)

# Filter that can only be applied after the primary index join.
opt
SELECT * FROM small JOIN abcd ON a=m WHERE c>2
----
inner-join (lookup abcd)
 ├── columns: m:1(int!null) n:2(int) a:6(int!null) b:7(int) c:8(int!null)
 ├── key columns: [9] = [9]
 ├── lookup columns are key
 ├── fd: (1)==(6), (6)==(1)
 ├── prune: (2,7)
 ├── interesting orderings: (+6,+7)
 ├── inner-join (lookup abcd@abcd_a_b_idx)
 │    ├── columns: m:1(int!null) n:2(int) a:6(int!null) b:7(int) abcd.rowid:9(int!null)
 │    ├── key columns: [1] = [6]
 │    ├── fd: (9)-->(6,7), (1)==(6), (6)==(1)
 │    ├── scan small
 │    │    ├── columns: m:1(int) n:2(int)
 │    │    ├── prune: (1,2)
 │    │    └── unfiltered-cols: (1-5)
 │    └── filters (true)
 └── filters
      └── gt [type=bool, outer=(8), constraints=(/8: [/3 - ]; tight)]
           ├── variable: c:8 [type=int]
           └── const: 2 [type=int]

# Multiple equalities.
opt
SELECT * FROM small JOIN abcd ON a=m AND b=n WHERE c>2
----
inner-join (lookup abcd)
 ├── columns: m:1(int!null) n:2(int!null) a:6(int!null) b:7(int!null) c:8(int!null)
 ├── key columns: [9] = [9]
 ├── lookup columns are key
 ├── fd: (1)==(6), (6)==(1), (2)==(7), (7)==(2)
 ├── interesting orderings: (+6,+7)
 ├── inner-join (lookup abcd@abcd_a_b_idx)
 │    ├── columns: m:1(int!null) n:2(int!null) a:6(int!null) b:7(int!null) abcd.rowid:9(int!null)
 │    ├── key columns: [1 2] = [6 7]
 │    ├── fd: (9)-->(6,7), (1)==(6), (6)==(1), (2)==(7), (7)==(2)
 │    ├── scan small
 │    │    ├── columns: m:1(int) n:2(int)
 │    │    ├── prune: (1,2)
 │    │    └── unfiltered-cols: (1-5)
 │    └── filters (true)
 └── filters
      └── gt [type=bool, outer=(8), constraints=(/8: [/3 - ]; tight)]
           ├── variable: c:8 [type=int]
           └── const: 2 [type=int]
