# LogicTest: local

statement ok
CREATE TABLE onecolumn (x INT); INSERT INTO onecolumn(x) VALUES (44), (NULL), (42)

statement ok
CREATE TABLE twocolumn (x INT, y INT); INSERT INTO twocolumn(x, y) VALUES (44,51), (NULL,52), (42,53), (45,45)

## Simple test cases for inner, left, right, and outer joins

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM onecolumn JOIN twocolumn USING(x)
]
----
render          ·         ·
 │              render 0  test.public.onecolumn.x
 │              render 1  test.public.twocolumn.y
 └── join       ·         ·
      │         type      inner
      │         equality  (x) = (x)
      ├── scan  ·         ·
      │         table     onecolumn@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     twocolumn@primary
·               spans     ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM twocolumn AS a JOIN twocolumn AS b ON a.x = b.y
]
----
render          ·         ·
 │              render 0  a.x
 │              render 1  a.y
 │              render 2  b.x
 │              render 3  b.y
 └── join       ·         ·
      │         type      inner
      │         equality  (x) = (y)
      ├── scan  ·         ·
      │         table     twocolumn@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     twocolumn@primary
·               spans     ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM twocolumn AS a JOIN twocolumn AS b ON a.x = 44
]
----
render          ·         ·
 │              render 0  a.x
 │              render 1  a.y
 │              render 2  b.x
 │              render 3  b.y
 └── join       ·         ·
      │         type      cross
      ├── scan  ·         ·
      │         table     twocolumn@primary
      │         spans     ALL
      │         filter    x = 44
      └── scan  ·         ·
·               table     twocolumn@primary
·               spans     ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM onecolumn AS a JOIN twocolumn AS b ON ((a.x)) = ((b.y))
]
----
render          ·         ·
 │              render 0  a.x
 │              render 1  b.x
 │              render 2  b.y
 └── join       ·         ·
      │         type      inner
      │         equality  (x) = (y)
      ├── scan  ·         ·
      │         table     onecolumn@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     twocolumn@primary
·               spans     ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM onecolumn JOIN twocolumn ON onecolumn.x = twocolumn.y
]
----
render          ·         ·
 │              render 0  test.public.onecolumn.x
 │              render 1  test.public.twocolumn.x
 │              render 2  test.public.twocolumn.y
 └── join       ·         ·
      │         type      inner
      │         equality  (x) = (y)
      ├── scan  ·         ·
      │         table     onecolumn@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     twocolumn@primary
·               spans     ALL


query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM (onecolumn CROSS JOIN twocolumn JOIN onecolumn AS a(b) ON a.b=twocolumn.x JOIN twocolumn AS c(d,e) ON a.b=c.d AND c.d=onecolumn.x) LIMIT 1
]
----
limit                          ·         ·
 │                             count     1
 └── render                    ·         ·
      │                        render 0  test.public.onecolumn.x
      │                        render 1  test.public.twocolumn.x
      │                        render 2  test.public.twocolumn.y
      │                        render 3  a.b
      │                        render 4  c.d
      │                        render 5  c.e
      └── join                 ·         ·
           │                   type      inner
           │                   equality  (b, x) = (d, d)
           ├── join            ·         ·
           │    │              type      inner
           │    │              equality  (x) = (b)
           │    ├── join       ·         ·
           │    │    │         type      cross
           │    │    ├── scan  ·         ·
           │    │    │         table     onecolumn@primary
           │    │    │         spans     ALL
           │    │    └── scan  ·         ·
           │    │              table     twocolumn@primary
           │    │              spans     ALL
           │    └── scan       ·         ·
           │                   table     onecolumn@primary
           │                   spans     ALL
           └── scan            ·         ·
·                              table     twocolumn@primary
·                              spans     ALL

# The following queries verify that only the necessary columns are scanned.
query TTTTT
EXPLAIN (VERBOSE) SELECT a.x, b.y FROM twocolumn AS a, twocolumn AS b
----
render          ·         ·                  (x, y)                                                                        ·
 │              render 0  a.x                ·                                                                             ·
 │              render 1  b.y                ·                                                                             ·
 └── join       ·         ·                  (x, y[omitted], rowid[hidden,omitted], x[omitted], y, rowid[hidden,omitted])  ·
      │         type      cross              ·                                                                             ·
      ├── scan  ·         ·                  (x, y[omitted], rowid[hidden,omitted])                                        rowid!=NULL; key(rowid)
      │         table     twocolumn@primary  ·                                                                             ·
      │         spans     ALL                ·                                                                             ·
      └── scan  ·         ·                  (x[omitted], y, rowid[hidden,omitted])                                        rowid!=NULL; key(rowid)
·               table     twocolumn@primary  ·                                                                             ·
·               spans     ALL                ·                                                                             ·

query TTTTT
EXPLAIN (VERBOSE) SELECT b.y FROM (twocolumn AS a JOIN twocolumn AS b USING(x))
----
render          ·         ·                  (y)                                                                                    ·
 │              render 0  b.y                ·                                                                                      ·
 └── join       ·         ·                  (x[omitted], y[omitted], rowid[hidden,omitted], x[omitted], y, rowid[hidden,omitted])  ·
      │         type      inner              ·                                                                                      ·
      │         equality  (x) = (x)          ·                                                                                      ·
      ├── scan  ·         ·                  (x, y[omitted], rowid[hidden,omitted])                                                 rowid!=NULL; key(rowid)
      │         table     twocolumn@primary  ·                                                                                      ·
      │         spans     ALL                ·                                                                                      ·
      └── scan  ·         ·                  (x, y, rowid[hidden,omitted])                                                          rowid!=NULL; key(rowid)
·               table     twocolumn@primary  ·                                                                                      ·
·               spans     ALL                ·                                                                                      ·

query TTTTT
EXPLAIN (VERBOSE) SELECT b.y FROM (twocolumn AS a JOIN twocolumn AS b ON a.x = b.x)
----
render          ·         ·                  (y)                                                                                    ·
 │              render 0  b.y                ·                                                                                      ·
 └── join       ·         ·                  (x[omitted], y[omitted], rowid[hidden,omitted], x[omitted], y, rowid[hidden,omitted])  ·
      │         type      inner              ·                                                                                      ·
      │         equality  (x) = (x)          ·                                                                                      ·
      ├── scan  ·         ·                  (x, y[omitted], rowid[hidden,omitted])                                                 rowid!=NULL; key(rowid)
      │         table     twocolumn@primary  ·                                                                                      ·
      │         spans     ALL                ·                                                                                      ·
      └── scan  ·         ·                  (x, y, rowid[hidden,omitted])                                                          rowid!=NULL; key(rowid)
·               table     twocolumn@primary  ·                                                                                      ·
·               spans     ALL                ·                                                                                      ·

query TTTTT
EXPLAIN (VERBOSE) SELECT a.x FROM (twocolumn AS a JOIN twocolumn AS b ON a.x < b.y)
----
render          ·         ·                  (x)                                                                                    ·
 │              render 0  a.x                ·                                                                                      ·
 └── join       ·         ·                  (x, y[omitted], rowid[hidden,omitted], x[omitted], y[omitted], rowid[hidden,omitted])  ·
      │         type      inner              ·                                                                                      ·
      │         pred      a.x < b.y          ·                                                                                      ·
      ├── scan  ·         ·                  (x, y[omitted], rowid[hidden,omitted])                                                 rowid!=NULL; key(rowid)
      │         table     twocolumn@primary  ·                                                                                      ·
      │         spans     ALL                ·                                                                                      ·
      └── scan  ·         ·                  (x[omitted], y, rowid[hidden,omitted])                                                 rowid!=NULL; key(rowid)
·               table     twocolumn@primary  ·                                                                                      ·
·               spans     ALL                ·                                                                                      ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT x, 2 two FROM onecolumn) NATURAL FULL JOIN (SELECT x, y+1 plus1 FROM twocolumn)
----
render                    ·         ·                            (x, two, plus1)                                        ·
 │                        render 0  x                            ·                                                      ·
 │                        render 1  two                          ·                                                      ·
 │                        render 2  plus1                        ·                                                      ·
 └── render               ·         ·                            (x, x[hidden,omitted], two, x[hidden,omitted], plus1)  ·
      │                   render 0  IFNULL(x, x)                 ·                                                      ·
      │                   render 1  NULL                         ·                                                      ·
      │                   render 2  two                          ·                                                      ·
      │                   render 3  NULL                         ·                                                      ·
      │                   render 4  plus1                        ·                                                      ·
      └── join            ·         ·                            (x, two, x, plus1)                                     ·
           │              type      full outer                   ·                                                      ·
           │              equality  (x) = (x)                    ·                                                      ·
           ├── render     ·         ·                            (x, two)                                               two=CONST
           │    │         render 0  test.public.onecolumn.x      ·                                                      ·
           │    │         render 1  2                            ·                                                      ·
           │    └── scan  ·         ·                            (x, rowid[hidden,omitted])                             rowid!=NULL; key(rowid)
           │              table     onecolumn@primary            ·                                                      ·
           │              spans     ALL                          ·                                                      ·
           └── render     ·         ·                            (x, plus1)                                             ·
                │         render 0  test.public.twocolumn.x      ·                                                      ·
                │         render 1  test.public.twocolumn.y + 1  ·                                                      ·
                └── scan  ·         ·                            (x, y, rowid[hidden,omitted])                          rowid!=NULL; key(rowid)
·                         table     twocolumn@primary            ·                                                      ·
·                         spans     ALL                          ·                                                      ·

# Ensure that the ordering information for the result of joins is sane. (#12037)
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT * FROM (VALUES (9, 1), (8, 2)) AS a (u, k) ORDER BY k)
                  INNER JOIN (VALUES (1, 1), (2, 2)) AS b (k, w) USING (k) ORDER BY u
----
sort                             ·              ·                  (k, u, w)                     +u
 │                               order          +u                 ·                             ·
 └── render                      ·              ·                  (k, u, w)                     ·
      │                          render 0       k                  ·                             ·
      │                          render 1       u                  ·                             ·
      │                          render 2       b.w                ·                             ·
      └── render                 ·              ·                  (k, u, k[hidden,omitted], w)  ·
           │                     render 0       k                  ·                             ·
           │                     render 1       u                  ·                             ·
           │                     render 2       NULL               ·                             ·
           │                     render 3       b.w                ·                             ·
           └── join              ·              ·                  (u, k, k[omitted], w)         ·
                │                type           inner              ·                             ·
                │                equality       (k) = (k)          ·                             ·
                ├── sort         ·              ·                  (u, k)                        +k
                │    │           order          +k                 ·                             ·
                │    └── values  ·              ·                  (u, k)                        ·
                │                size           2 columns, 2 rows  ·                             ·
                │                row 0, expr 0  9                  ·                             ·
                │                row 0, expr 1  1                  ·                             ·
                │                row 1, expr 0  8                  ·                             ·
                │                row 1, expr 1  2                  ·                             ·
                └── values       ·              ·                  (column1, column2)            ·
·                                size           2 columns, 2 rows  ·                             ·
·                                row 0, expr 0  1                  ·                             ·
·                                row 0, expr 1  1                  ·                             ·
·                                row 1, expr 0  2                  ·                             ·
·                                row 1, expr 1  2                  ·                             ·

# Ensure that large cross-joins are optimized somehow (#10633)
statement ok
CREATE TABLE customers(id INT PRIMARY KEY NOT NULL); CREATE TABLE orders(id INT, cust INT REFERENCES customers(id))

query ITTT
SELECT level, node_type, field, description FROM [EXPLAIN (VERBOSE) SELECT
       NULL::text  AS pktable_cat,
       pkn.nspname AS pktable_schem,
       pkc.relname AS pktable_name,
       pka.attname AS pkcolumn_name,
       NULL::text  AS fktable_cat,
       fkn.nspname AS fktable_schem,
       fkc.relname AS fktable_name,
       fka.attname AS fkcolumn_name,
       pos.n       AS key_seq,
       CASE con.confupdtype
            WHEN 'c' THEN 0
            WHEN 'n' THEN 2
            WHEN 'd' THEN 4
            WHEN 'r' THEN 1
            WHEN 'a' THEN 3
            ELSE NULL
       END AS update_rule,
       CASE con.confdeltype
            WHEN 'c' THEN 0
            WHEN 'n' THEN 2
            WHEN 'd' THEN 4
            WHEN 'r' THEN 1
            WHEN 'a' THEN 3
            ELSE NULL
       END          AS delete_rule,
       con.conname  AS fk_name,
       pkic.relname AS pk_name,
       CASE
            WHEN con.condeferrable
            AND      con.condeferred THEN 5
            WHEN con.condeferrable THEN 6
            ELSE 7
       END AS deferrability
  FROM     pg_catalog.pg_namespace pkn,
       pg_catalog.pg_class pkc,
       pg_catalog.pg_attribute pka,
       pg_catalog.pg_namespace fkn,
       pg_catalog.pg_class fkc,
       pg_catalog.pg_attribute fka,
       pg_catalog.pg_constraint con,
       pg_catalog.generate_series(1, 32) pos(n),
       pg_catalog.pg_depend dep,
       pg_catalog.pg_class pkic
  WHERE    pkn.oid = pkc.relnamespace
  AND      pkc.oid = pka.attrelid
  AND      pka.attnum = con.confkey[pos.n]
  AND      con.confrelid = pkc.oid
  AND      fkn.oid = fkc.relnamespace
  AND      fkc.oid = fka.attrelid
  AND      fka.attnum = con.conkey[pos.n]
  AND      con.conrelid = fkc.oid
  AND      con.contype = 'f'
  AND      con.oid = dep.objid
  AND      pkic.oid = dep.refobjid
  AND      pkic.relkind = 'i'
  AND      dep.classid = 'pg_constraint'::regclass::oid
  AND      dep.refclassid = 'pg_class'::regclass::oid
  AND      fkn.nspname = 'public'
  AND      fkc.relname = 'orders'
  ORDER BY pkn.nspname,
           pkc.relname,
           con.conname,
           pos.n
  ] WHERE node_type <> 'values' AND field <> 'size'
----
0   sort         ·          ·
0   ·            order      +pktable_schem,+pktable_name,+fk_name,+key_seq
1   render       ·          ·
1   ·            render 0   CAST(NULL AS STRING)
1   ·            render 1   pkn.nspname
1   ·            render 2   pkc.relname
1   ·            render 3   pka.attname
1   ·            render 4   CAST(NULL AS STRING)
1   ·            render 5   fkn.nspname
1   ·            render 6   fkc.relname
1   ·            render 7   fka.attname
1   ·            render 8   pos.n
1   ·            render 9   CASE con.confupdtype WHEN 'c' THEN 0 WHEN 'n' THEN 2 WHEN 'd' THEN 4 WHEN 'r' THEN 1 WHEN 'a' THEN 3 ELSE NULL END
1   ·            render 10  CASE con.confdeltype WHEN 'c' THEN 0 WHEN 'n' THEN 2 WHEN 'd' THEN 4 WHEN 'r' THEN 1 WHEN 'a' THEN 3 ELSE NULL END
1   ·            render 11  con.conname
1   ·            render 12  pkic.relname
1   ·            render 13  CASE WHEN con.condeferrable AND con.condeferred THEN 5 WHEN con.condeferrable THEN 6 ELSE 7 END
2   join         ·          ·
2   ·            type       inner
2   ·            equality   (oid) = (relnamespace)
3   join         ·          ·
3   ·            type       inner
3   ·            equality   (oid, oid) = (attrelid, confrelid)
4   join         ·          ·
4   ·            type       inner
4   ·            pred       pka.attnum = con.confkey[pos.n]
5   join         ·          ·
5   ·            type       inner
5   ·            equality   (oid) = (relnamespace)
6   filter       ·          ·
6   ·            filter     fkn.nspname = 'public'
6   join         ·          ·
6   ·            type       inner
6   ·            equality   (oid, oid) = (attrelid, conrelid)
7   filter       ·          ·
7   ·            filter     fkc.relname = 'orders'
7   join         ·          ·
7   ·            type       inner
7   ·            pred       fka.attnum = con.conkey[pos.n]
8   join         ·          ·
8   ·            type       inner
8   ·            equality   (oid) = (objid)
9   filter       ·          ·
9   ·            filter     con.contype = 'f'
9   join         ·          ·
9   ·            type       cross
10  project set  ·          ·
10  ·            render 0   generate_series(1, 32)
11  emptyrow     ·          ·
10  join         ·          ·
10  ·            type       inner
10  ·            equality   (refobjid) = (oid)
11  filter       ·          ·
11  ·            filter     (dep.classid = 139623798) AND (dep.refclassid = 1411792157)
11  filter       ·          ·
11  ·            filter     pkic.relkind = 'i'


# Tests for filter propagation through joins.

statement ok
CREATE TABLE square (n INT PRIMARY KEY, sq INT)

statement ok
CREATE TABLE pairs (a INT, b INT)

# The filter expression becomes an equality constraint.
query TTT
EXPLAIN SELECT * FROM pairs, square WHERE pairs.b = square.n
----
render          ·         ·
 └── join       ·         ·
      │         type      inner
      │         equality  (b) = (n)
      ├── scan  ·         ·
      │         table     pairs@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     square@primary
·               spans     ALL

# The filter expression becomes an ON predicate.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pairs, square WHERE pairs.a + pairs.b = square.sq
----
render          ·         ·                                                                    (a, b, n, sq)                         ·
 │              render 0  test.public.pairs.a                                                  ·                                     ·
 │              render 1  test.public.pairs.b                                                  ·                                     ·
 │              render 2  test.public.square.n                                                 ·                                     ·
 │              render 3  test.public.square.sq                                                ·                                     ·
 └── join       ·         ·                                                                    (a, b, rowid[hidden,omitted], n, sq)  ·
      │         type      inner                                                                ·                                     ·
      │         pred      (test.public.pairs.a + test.public.pairs.b) = test.public.square.sq  ·                                     ·
      ├── scan  ·         ·                                                                    (a, b, rowid[hidden,omitted])         rowid!=NULL; key(rowid)
      │         table     pairs@primary                                                        ·                                     ·
      │         spans     ALL                                                                  ·                                     ·
      └── scan  ·         ·                                                                    (n, sq)                               n!=NULL; key(n)
·               table     square@primary                                                       ·                                     ·
·               spans     ALL                                                                  ·                                     ·

# Query similar to the one above, but the filter refers to a rendered
# expression and can't "break through". See the comment for propagateFilters
# in fitler_opt.go for all the details.
query TTTTT
EXPLAIN (VERBOSE) SELECT a, b, n, sq FROM (SELECT a, b, a * b / 2 AS div, n, sq FROM pairs, square) WHERE div = sq
----
render                    ·         ·                                                (a, b, n, sq)                         sq!=NULL
 │                        render 0  a                                                ·                                     ·
 │                        render 1  b                                                ·                                     ·
 │                        render 2  n                                                ·                                     ·
 │                        render 3  sq                                               ·                                     ·
 └── filter               ·         ·                                                (a, b, div, n, sq)                    div=sq; div!=NULL; sq!=NULL
      │                   filter    div = sq                                         ·                                     ·
      └── render          ·         ·                                                (a, b, div, n, sq)                    ·
           │              render 0  test.public.pairs.a                              ·                                     ·
           │              render 1  test.public.pairs.b                              ·                                     ·
           │              render 2  (test.public.pairs.a * test.public.pairs.b) / 2  ·                                     ·
           │              render 3  test.public.square.n                             ·                                     ·
           │              render 4  test.public.square.sq                            ·                                     ·
           └── join       ·         ·                                                (a, b, rowid[hidden,omitted], n, sq)  ·
                │         type      cross                                            ·                                     ·
                ├── scan  ·         ·                                                (a, b, rowid[hidden,omitted])         rowid!=NULL; key(rowid)
                │         table     pairs@primary                                    ·                                     ·
                │         spans     ALL                                              ·                                     ·
                └── scan  ·         ·                                                (n, sq)                               n!=NULL; key(n)
·                         table     square@primary                                   ·                                     ·
·                         spans     ALL                                              ·                                     ·

# The filter expression must stay on top of the outer join.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pairs FULL OUTER JOIN square ON pairs.a + pairs.b = square.sq
----
render          ·         ·                                                                    (a, b, n, sq)                         ·
 │              render 0  test.public.pairs.a                                                  ·                                     ·
 │              render 1  test.public.pairs.b                                                  ·                                     ·
 │              render 2  test.public.square.n                                                 ·                                     ·
 │              render 3  test.public.square.sq                                                ·                                     ·
 └── join       ·         ·                                                                    (a, b, rowid[hidden,omitted], n, sq)  ·
      │         type      full outer                                                           ·                                     ·
      │         pred      (test.public.pairs.a + test.public.pairs.b) = test.public.square.sq  ·                                     ·
      ├── scan  ·         ·                                                                    (a, b, rowid[hidden,omitted])         rowid!=NULL; key(rowid)
      │         table     pairs@primary                                                        ·                                     ·
      │         spans     ALL                                                                  ·                                     ·
      └── scan  ·         ·                                                                    (n, sq)                               n!=NULL; key(n)
·               table     square@primary                                                       ·                                     ·
·               spans     ALL                                                                  ·                                     ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pairs FULL OUTER JOIN square ON pairs.a + pairs.b = square.sq WHERE pairs.b%2 <> square.sq%2
----
render               ·         ·                                                                    (a, b, n, sq)                         b!=NULL; sq!=NULL
 │                   render 0  test.public.pairs.a                                                  ·                                     ·
 │                   render 1  test.public.pairs.b                                                  ·                                     ·
 │                   render 2  test.public.square.n                                                 ·                                     ·
 │                   render 3  test.public.square.sq                                                ·                                     ·
 └── filter          ·         ·                                                                    (a, b, rowid[hidden,omitted], n, sq)  b!=NULL; sq!=NULL
      │              filter    (test.public.pairs.b % 2) != (test.public.square.sq % 2)             ·                                     ·
      └── join       ·         ·                                                                    (a, b, rowid[hidden,omitted], n, sq)  ·
           │         type      full outer                                                           ·                                     ·
           │         pred      (test.public.pairs.a + test.public.pairs.b) = test.public.square.sq  ·                                     ·
           ├── scan  ·         ·                                                                    (a, b, rowid[hidden,omitted])         rowid!=NULL; key(rowid)
           │         table     pairs@primary                                                        ·                                     ·
           │         spans     ALL                                                                  ·                                     ·
           └── scan  ·         ·                                                                    (n, sq)                               n!=NULL; key(n)
·                    table     square@primary                                                       ·                                     ·
·                    spans     ALL                                                                  ·                                     ·

# Filter propagation through outer joins.

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE)
SELECT *
  FROM (SELECT * FROM pairs LEFT JOIN square ON b = sq AND a > 1 AND n < 6)
 WHERE b > 1 AND (n IS NULL OR n > 1) AND (n IS NULL OR a  < sq)
]
----
render               ·         ·
 │                   render 0  test.public.pairs.a
 │                   render 1  test.public.pairs.b
 │                   render 2  test.public.square.n
 │                   render 3  test.public.square.sq
 └── filter          ·         ·
      │              filter    ((test.public.square.n IS NULL) OR (test.public.square.n > 1)) AND ((test.public.square.n IS NULL) OR (test.public.pairs.a < test.public.square.sq))
      └── join       ·         ·
           │         type      left outer
           │         equality  (b) = (sq)
           │         pred      test.public.pairs.a > 1
           ├── scan  ·         ·
           │         table     pairs@primary
           │         spans     ALL
           │         filter    b > 1
           └── scan  ·         ·
·                    table     square@primary
·                    spans     -/5/#
·                    filter    sq > 1

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE)
SELECT *
  FROM (SELECT * FROM pairs RIGHT JOIN square ON b = sq AND a > 1 AND n < 6)
 WHERE (a IS NULL OR a > 2) AND n > 1 AND (a IS NULL OR a < sq)
]
----
render               ·         ·
 │                   render 0  test.public.pairs.a
 │                   render 1  test.public.pairs.b
 │                   render 2  test.public.square.n
 │                   render 3  test.public.square.sq
 └── filter          ·         ·
      │              filter    ((test.public.pairs.a IS NULL) OR (test.public.pairs.a > 2)) AND ((test.public.pairs.a IS NULL) OR (test.public.pairs.a < test.public.square.sq))
      └── join       ·         ·
           │         type      right outer
           │         equality  (b) = (sq)
           │         pred      test.public.square.n < 6
           ├── scan  ·         ·
           │         table     pairs@primary
           │         spans     ALL
           │         filter    a > 1
           └── scan  ·         ·
·                    table     square@primary
·                    spans     /2-

# The simpler plan for an inner join, to compare.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE)
SELECT *
  FROM (SELECT * FROM pairs JOIN square ON b = sq AND a > 1 AND n < 6)
 WHERE (a IS NULL OR a > 2) AND n > 1 AND (a IS NULL OR a < sq)
]
----
render          ·         ·
 │              render 0  test.public.pairs.a
 │              render 1  test.public.pairs.b
 │              render 2  test.public.square.n
 │              render 3  test.public.square.sq
 └── join       ·         ·
      │         type      inner
      │         equality  (b) = (sq)
      ├── scan  ·         ·
      │         table     pairs@primary
      │         spans     ALL
      │         filter    ((a > 1) AND ((a IS NULL) OR (a > 2))) AND ((a IS NULL) OR (a < b))
      └── scan  ·         ·
·               table     square@primary
·               spans     /2-/5/#


statement ok
CREATE TABLE t1 (col1 INT, x INT, col2 INT, y INT)

statement ok
CREATE TABLE t2 (col3 INT, y INT, x INT, col4 INT)

query TTTTT
EXPLAIN (VERBOSE) SELECT x FROM t1 NATURAL JOIN (SELECT * FROM t2)
----
render                    ·         ·                 (x)                                                                                                                                       ·
 │                        render 0  test.public.t1.x  ·                                                                                                                                         ·
 └── render               ·         ·                 (x, y[omitted], col1[omitted], col2[omitted], rowid[hidden,omitted], col3[omitted], y[hidden,omitted], x[hidden,omitted], col4[omitted])  ·
      │                   render 0  test.public.t1.x  ·                                                                                                                                         ·
      │                   render 1  NULL              ·                                                                                                                                         ·
      │                   render 2  NULL              ·                                                                                                                                         ·
      │                   render 3  NULL              ·                                                                                                                                         ·
      │                   render 4  NULL              ·                                                                                                                                         ·
      │                   render 5  NULL              ·                                                                                                                                         ·
      │                   render 6  NULL              ·                                                                                                                                         ·
      │                   render 7  NULL              ·                                                                                                                                         ·
      │                   render 8  NULL              ·                                                                                                                                         ·
      └── join            ·         ·                 (col1[omitted], x, col2[omitted], y[omitted], rowid[hidden,omitted], col3[omitted], y[omitted], x[omitted], col4[omitted])                ·
           │              type      inner             ·                                                                                                                                         ·
           │              equality  (x, y) = (x, y)   ·                                                                                                                                         ·
           ├── scan       ·         ·                 (col1[omitted], x, col2[omitted], y, rowid[hidden,omitted])                                                                               rowid!=NULL; key(rowid)
           │              table     t1@primary        ·                                                                                                                                         ·
           │              spans     ALL               ·                                                                                                                                         ·
           └── render     ·         ·                 (col3[omitted], y, x, col4[omitted])                                                                                                      ·
                │         render 0  NULL              ·                                                                                                                                         ·
                │         render 1  test.public.t2.y  ·                                                                                                                                         ·
                │         render 2  test.public.t2.x  ·                                                                                                                                         ·
                │         render 3  NULL              ·                                                                                                                                         ·
                └── scan  ·         ·                 (col3[omitted], y, x, col4[omitted], rowid[hidden,omitted])                                                                               rowid!=NULL; key(rowid)
·                         table     t2@primary        ·                                                                                                                                         ·
·                         spans     ALL               ·                                                                                                                                         ·

# Tests for merge join ordering information.
statement ok
CREATE TABLE pkBA (a INT, b INT, c INT, d INT, PRIMARY KEY(b,a))

statement ok
CREATE TABLE pkBC (a INT, b INT, c INT, d INT, PRIMARY KEY(b,c))

statement ok
CREATE TABLE pkBAC (a INT, b INT, c INT, d INT, PRIMARY KEY(b,a,c))

statement ok
CREATE TABLE pkBAD (a INT, b INT, c INT, d INT, PRIMARY KEY(b,a,d))

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pkBA AS l JOIN pkBC AS r ON l.a = r.a AND l.b = r.b AND l.c = r.c
----
join       ·               ·                      (a, b, c, d, a, b, c, d)  a=a; b=b; c=c; a!=NULL; b!=NULL; c!=NULL; key(a,b); key(b,c)
 │         type            inner                  ·                         ·
 │         equality        (a, b, c) = (a, b, c)  ·                         ·
 │         mergeJoinOrder  +"(b=b)"               ·                         ·
 ├── scan  ·               ·                      (a, b, c, d)              a!=NULL; b!=NULL; key(a,b); +b
 │         table           pkba@primary           ·                         ·
 │         spans           ALL                    ·                         ·
 └── scan  ·               ·                      (a, b, c, d)              b!=NULL; c!=NULL; key(b,c); +b
·          table           pkbc@primary           ·                         ·
·          spans           ALL                    ·                         ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pkBA NATURAL JOIN pkBAD
----
render          ·               ·                            (a, b, c, d)                                                  a!=NULL; b!=NULL; c!=NULL; d!=NULL; key(a,b)
 │              render 0        test.public.pkba.a           ·                                                             ·
 │              render 1        test.public.pkba.b           ·                                                             ·
 │              render 2        test.public.pkba.c           ·                                                             ·
 │              render 3        test.public.pkba.d           ·                                                             ·
 └── join       ·               ·                            (a, b, c, d, a[omitted], b[omitted], c[omitted], d[omitted])  a=a; b=b; c=c; d=d; a!=NULL; b!=NULL; c!=NULL; d!=NULL; key(a,b)
      │         type            inner                        ·                                                             ·
      │         equality        (a, b, c, d) = (a, b, c, d)  ·                                                             ·
      │         mergeJoinOrder  +"(b=b)",+"(a=a)",+"(d=d)"   ·                                                             ·
      ├── scan  ·               ·                            (a, b, c, d)                                                  a!=NULL; b!=NULL; key(a,b); +b,+a
      │         table           pkba@primary                 ·                                                             ·
      │         spans           ALL                          ·                                                             ·
      └── scan  ·               ·                            (a, b, c, d)                                                  a!=NULL; b!=NULL; d!=NULL; key(a,b,d); +b,+a,+d
·               table           pkbad@primary                ·                                                             ·
·               spans           ALL                          ·                                                             ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pkBAC AS l JOIN pkBAC AS r USING(a, b, c)
----
render          ·               ·                           (a, b, c, d, d)                                      a!=NULL; b!=NULL; c!=NULL; key(a,b,c)
 │              render 0        l.a                         ·                                                    ·
 │              render 1        l.b                         ·                                                    ·
 │              render 2        l.c                         ·                                                    ·
 │              render 3        l.d                         ·                                                    ·
 │              render 4        r.d                         ·                                                    ·
 └── join       ·               ·                           (a, b, c, d, a[omitted], b[omitted], c[omitted], d)  a=a; b=b; c=c; a!=NULL; b!=NULL; c!=NULL; key(a,b,c)
      │         type            inner                       ·                                                    ·
      │         equality        (a, b, c) = (a, b, c)       ·                                                    ·
      │         mergeJoinOrder  +"(b=b)",+"(a=a)",+"(c=c)"  ·                                                    ·
      ├── scan  ·               ·                           (a, b, c, d)                                         a!=NULL; b!=NULL; c!=NULL; key(a,b,c); +b,+a,+c
      │         table           pkbac@primary               ·                                                    ·
      │         spans           ALL                         ·                                                    ·
      └── scan  ·               ·                           (a, b, c, d)                                         a!=NULL; b!=NULL; c!=NULL; key(a,b,c); +b,+a,+c
·               table           pkbac@primary               ·                                                    ·
·               spans           ALL                         ·                                                    ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM pkBAC AS l JOIN pkBAD AS r ON l.c = r.d AND l.a = r.a AND l.b = r.b
----
join       ·               ·                           (a, b, c, d, a, b, c, d)  a=a; b=b; c=d; a!=NULL; b!=NULL; c!=NULL; key(a,b,c)
 │         type            inner                       ·                         ·
 │         equality        (c, a, b) = (d, a, b)       ·                         ·
 │         mergeJoinOrder  +"(b=b)",+"(a=a)",+"(c=d)"  ·                         ·
 ├── scan  ·               ·                           (a, b, c, d)              a!=NULL; b!=NULL; c!=NULL; key(a,b,c); +b,+a,+c
 │         table           pkbac@primary               ·                         ·
 │         spans           ALL                         ·                         ·
 └── scan  ·               ·                           (a, b, c, d)              a!=NULL; b!=NULL; d!=NULL; key(a,b,d); +b,+a,+d
·          table           pkbad@primary               ·                         ·
·          spans           ALL                         ·                         ·

# Tests with joins with merged columns of collated string type.
statement ok
CREATE TABLE str1 (a INT PRIMARY KEY, s STRING COLLATE en_u_ks_level1)

statement ok
CREATE TABLE str2 (a INT PRIMARY KEY, s STRING COLLATE en_u_ks_level1)

query TTTTT
EXPLAIN (VERBOSE) SELECT s, str1.s, str2.s FROM str1 INNER JOIN str2 USING(s)
----
render               ·         ·                   (s, s, s)                               s=s
 │                   render 0  test.public.str1.s  ·                                       ·
 │                   render 1  test.public.str1.s  ·                                       ·
 │                   render 2  test.public.str2.s  ·                                       ·
 └── render          ·         ·                   (s, a[omitted], a[omitted], s[hidden])  ·
      │              render 0  test.public.str1.s  ·                                       ·
      │              render 1  NULL                ·                                       ·
      │              render 2  NULL                ·                                       ·
      │              render 3  test.public.str2.s  ·                                       ·
      └── join       ·         ·                   (a[omitted], s, a[omitted], s)          ·
           │         type      inner               ·                                       ·
           │         equality  (s) = (s)           ·                                       ·
           ├── scan  ·         ·                   (a[omitted], s)                         a!=NULL; key(a)
           │         table     str1@primary        ·                                       ·
           │         spans     ALL                 ·                                       ·
           └── scan  ·         ·                   (a[omitted], s)                         a!=NULL; key(a)
·                    table     str2@primary        ·                                       ·
·                    spans     ALL                 ·                                       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT s, str1.s, str2.s FROM str1 LEFT OUTER JOIN str2 USING(s)
----
render               ·         ·                   (s, s, s)                               s=s
 │                   render 0  test.public.str1.s  ·                                       ·
 │                   render 1  test.public.str1.s  ·                                       ·
 │                   render 2  test.public.str2.s  ·                                       ·
 └── render          ·         ·                   (s, a[omitted], a[omitted], s[hidden])  ·
      │              render 0  test.public.str1.s  ·                                       ·
      │              render 1  NULL                ·                                       ·
      │              render 2  NULL                ·                                       ·
      │              render 3  test.public.str2.s  ·                                       ·
      └── join       ·         ·                   (a[omitted], s, a[omitted], s)          ·
           │         type      left outer          ·                                       ·
           │         equality  (s) = (s)           ·                                       ·
           ├── scan  ·         ·                   (a[omitted], s)                         a!=NULL; key(a)
           │         table     str1@primary        ·                                       ·
           │         spans     ALL                 ·                                       ·
           └── scan  ·         ·                   (a[omitted], s)                         a!=NULL; key(a)
·                    table     str2@primary        ·                                       ·
·                    spans     ALL                 ·                                       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT s, str1.s, str2.s FROM str1 RIGHT OUTER JOIN str2 USING(s)
----
render               ·         ·                                               (s, s, s)                                          ·
 │                   render 0  s                                               ·                                                  ·
 │                   render 1  test.public.str1.s                              ·                                                  ·
 │                   render 2  test.public.str2.s                              ·                                                  ·
 └── render          ·         ·                                               (s, a[omitted], s[hidden], a[omitted], s[hidden])  ·
      │              render 0  IFNULL(test.public.str1.s, test.public.str2.s)  ·                                                  ·
      │              render 1  NULL                                            ·                                                  ·
      │              render 2  test.public.str1.s                              ·                                                  ·
      │              render 3  NULL                                            ·                                                  ·
      │              render 4  test.public.str2.s                              ·                                                  ·
      └── join       ·         ·                                               (a[omitted], s, a[omitted], s)                     ·
           │         type      right outer                                     ·                                                  ·
           │         equality  (s) = (s)                                       ·                                                  ·
           ├── scan  ·         ·                                               (a[omitted], s)                                    a!=NULL; key(a)
           │         table     str1@primary                                    ·                                                  ·
           │         spans     ALL                                             ·                                                  ·
           └── scan  ·         ·                                               (a[omitted], s)                                    a!=NULL; key(a)
·                    table     str2@primary                                    ·                                                  ·
·                    spans     ALL                                             ·                                                  ·

query TTTTT
EXPLAIN (VERBOSE) SELECT s, str1.s, str2.s FROM str1 FULL OUTER JOIN str2 USING(s)
----
render               ·         ·                                               (s, s, s)                                          ·
 │                   render 0  s                                               ·                                                  ·
 │                   render 1  test.public.str1.s                              ·                                                  ·
 │                   render 2  test.public.str2.s                              ·                                                  ·
 └── render          ·         ·                                               (s, a[omitted], s[hidden], a[omitted], s[hidden])  ·
      │              render 0  IFNULL(test.public.str1.s, test.public.str2.s)  ·                                                  ·
      │              render 1  NULL                                            ·                                                  ·
      │              render 2  test.public.str1.s                              ·                                                  ·
      │              render 3  NULL                                            ·                                                  ·
      │              render 4  test.public.str2.s                              ·                                                  ·
      └── join       ·         ·                                               (a[omitted], s, a[omitted], s)                     ·
           │         type      full outer                                      ·                                                  ·
           │         equality  (s) = (s)                                       ·                                                  ·
           ├── scan  ·         ·                                               (a[omitted], s)                                    a!=NULL; key(a)
           │         table     str1@primary                                    ·                                                  ·
           │         spans     ALL                                             ·                                                  ·
           └── scan  ·         ·                                               (a[omitted], s)                                    a!=NULL; key(a)
·                    table     str2@primary                                    ·                                                  ·
·                    spans     ALL                                             ·                                                  ·

# Verify that we resolve the merged column a to str2.a but use IFNULL for
# column s which is a collated string.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM str1 RIGHT OUTER JOIN str2 USING(a, s)
----
render               ·               ·                                               (a, s)                                                           ·
 │                   render 0        test.public.str2.a                              ·                                                                ·
 │                   render 1        s                                               ·                                                                ·
 └── render          ·               ·                                               (a, s, a[hidden,omitted], s[hidden,omitted], s[hidden,omitted])  ·
      │              render 0        test.public.str2.a                              ·                                                                ·
      │              render 1        IFNULL(test.public.str1.s, test.public.str2.s)  ·                                                                ·
      │              render 2        NULL                                            ·                                                                ·
      │              render 3        NULL                                            ·                                                                ·
      │              render 4        NULL                                            ·                                                                ·
      └── join       ·               ·                                               (a[omitted], s, a, s)                                            ·
           │         type            right outer                                     ·                                                                ·
           │         equality        (a, s) = (a, s)                                 ·                                                                ·
           │         mergeJoinOrder  +"(a=a)"                                        ·                                                                ·
           ├── scan  ·               ·                                               (a, s)                                                           a!=NULL; key(a); +a
           │         table           str1@primary                                    ·                                                                ·
           │         spans           ALL                                             ·                                                                ·
           └── scan  ·               ·                                               (a, s)                                                           a!=NULL; key(a); +a
·                    table           str2@primary                                    ·                                                                ·
·                    spans           ALL                                             ·                                                                ·


statement ok
CREATE TABLE xyu (x INT, y INT, u INT, PRIMARY KEY(x,y,u))

statement ok
CREATE TABLE xyv (x INT, y INT, v INT, PRIMARY KEY(x,y,v))

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu INNER JOIN xyv USING(x, y) WHERE x > 2
----
render          ·               ·                  (x, y, u, v)                          x!=NULL; y!=NULL
 │              render 0        test.public.xyu.x  ·                                     ·
 │              render 1        test.public.xyu.y  ·                                     ·
 │              render 2        test.public.xyu.u  ·                                     ·
 │              render 3        test.public.xyv.v  ·                                     ·
 └── join       ·               ·                  (x, y, u, x[omitted], y[omitted], v)  x=x; y=y; x!=NULL; y!=NULL
      │         type            inner              ·                                     ·
      │         equality        (x, y) = (x, y)    ·                                     ·
      │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                                     ·
      ├── scan  ·               ·                  (x, y, u)                             x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
      │         table           xyu@primary        ·                                     ·
      │         spans           /3-                ·                                     ·
      └── scan  ·               ·                  (x, y, v)                             x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·               table           xyv@primary        ·                                     ·
·               spans           /3-                ·                                     ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu LEFT OUTER JOIN xyv USING(x, y) WHERE x > 2
----
render          ·               ·                  (x, y, u, v)                          ·
 │              render 0        test.public.xyu.x  ·                                     ·
 │              render 1        test.public.xyu.y  ·                                     ·
 │              render 2        test.public.xyu.u  ·                                     ·
 │              render 3        test.public.xyv.v  ·                                     ·
 └── join       ·               ·                  (x, y, u, x[omitted], y[omitted], v)  ·
      │         type            left outer         ·                                     ·
      │         equality        (x, y) = (x, y)    ·                                     ·
      │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                                     ·
      ├── scan  ·               ·                  (x, y, u)                             x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
      │         table           xyu@primary        ·                                     ·
      │         spans           /3-                ·                                     ·
      └── scan  ·               ·                  (x, y, v)                             x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·               table           xyv@primary        ·                                     ·
·               spans           /3-                ·                                     ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu RIGHT OUTER JOIN xyv USING(x, y) WHERE x > 2
----
render               ·               ·                  (x, y, u, v)                                        ·
 │                   render 0        test.public.xyv.x  ·                                                   ·
 │                   render 1        test.public.xyv.y  ·                                                   ·
 │                   render 2        test.public.xyu.u  ·                                                   ·
 │                   render 3        test.public.xyv.v  ·                                                   ·
 └── render          ·               ·                  (x, y, x[hidden,omitted], y[hidden,omitted], u, v)  ·
      │              render 0        test.public.xyv.x  ·                                                   ·
      │              render 1        test.public.xyv.y  ·                                                   ·
      │              render 2        NULL               ·                                                   ·
      │              render 3        NULL               ·                                                   ·
      │              render 4        test.public.xyu.u  ·                                                   ·
      │              render 5        test.public.xyv.v  ·                                                   ·
      └── join       ·               ·                  (x[omitted], y[omitted], u, x, y, v)                ·
           │         type            right outer        ·                                                   ·
           │         equality        (x, y) = (x, y)    ·                                                   ·
           │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                                                   ·
           ├── scan  ·               ·                  (x, y, u)                                           x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
           │         table           xyu@primary        ·                                                   ·
           │         spans           /3-                ·                                                   ·
           └── scan  ·               ·                  (x, y, v)                                           x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·                    table           xyv@primary        ·                                                   ·
·                    spans           /3-                ·                                                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu FULL OUTER JOIN xyv USING(x, y) WHERE x > 2
----
render                    ·               ·                                             (x, y, u, v)                                                                              x!=NULL
 │                        render 0        x                                             ·                                                                                         ·
 │                        render 1        y                                             ·                                                                                         ·
 │                        render 2        test.public.xyu.u                             ·                                                                                         ·
 │                        render 3        test.public.xyv.v                             ·                                                                                         ·
 └── filter               ·               ·                                             (x, y, x[hidden,omitted], y[hidden,omitted], u, x[hidden,omitted], y[hidden,omitted], v)  x!=NULL
      │                   filter          x > 2                                         ·                                                                                         ·
      └── render          ·               ·                                             (x, y, x[hidden,omitted], y[hidden,omitted], u, x[hidden,omitted], y[hidden,omitted], v)  ·
           │              render 0        IFNULL(test.public.xyu.x, test.public.xyv.x)  ·                                                                                         ·
           │              render 1        IFNULL(test.public.xyu.y, test.public.xyv.y)  ·                                                                                         ·
           │              render 2        NULL                                          ·                                                                                         ·
           │              render 3        NULL                                          ·                                                                                         ·
           │              render 4        test.public.xyu.u                             ·                                                                                         ·
           │              render 5        NULL                                          ·                                                                                         ·
           │              render 6        NULL                                          ·                                                                                         ·
           │              render 7        test.public.xyv.v                             ·                                                                                         ·
           └── join       ·               ·                                             (x, y, u, x, y, v)                                                                        ·
                │         type            full outer                                    ·                                                                                         ·
                │         equality        (x, y) = (x, y)                               ·                                                                                         ·
                │         mergeJoinOrder  +"(x=x)",+"(y=y)"                             ·                                                                                         ·
                ├── scan  ·               ·                                             (x, y, u)                                                                                 x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
                │         table           xyu@primary                                   ·                                                                                         ·
                │         spans           ALL                                           ·                                                                                         ·
                └── scan  ·               ·                                             (x, y, v)                                                                                 x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·                         table           xyv@primary                                   ·                                                                                         ·
·                         spans           ALL                                           ·                                                                                         ·

# Verify that we transfer constraints between the two sides.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu INNER JOIN xyv ON xyu.x = xyv.x AND xyu.y = xyv.y WHERE xyu.x = 1 AND xyu.y < 10
----
join       ·               ·                  (x, y, u, x, y, v)  x=x; y=y; x=CONST; y!=NULL
 │         type            inner              ·                   ·
 │         equality        (x, y) = (x, y)    ·                   ·
 │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                   ·
 ├── scan  ·               ·                  (x, y, u)           x=CONST; y!=NULL; u!=NULL; key(y,u); +y
 │         table           xyu@primary        ·                   ·
 │         spans           /1-/1/10           ·                   ·
 └── scan  ·               ·                  (x, y, v)           x=CONST; y!=NULL; v!=NULL; key(y,v); +y
·          table           xyv@primary        ·                   ·
·          spans           /1-/1/10           ·                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu INNER JOIN xyv ON xyu.x = xyv.x AND xyu.y = xyv.y AND xyu.x = 1 AND xyu.y < 10
----
join       ·               ·                  (x, y, u, x, y, v)  x=x; y=y; x=CONST; y!=NULL
 │         type            inner              ·                   ·
 │         equality        (x, y) = (x, y)    ·                   ·
 │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                   ·
 ├── scan  ·               ·                  (x, y, u)           x=CONST; y!=NULL; u!=NULL; key(y,u); +y
 │         table           xyu@primary        ·                   ·
 │         spans           /1-/1/10           ·                   ·
 └── scan  ·               ·                  (x, y, v)           x=CONST; y!=NULL; v!=NULL; key(y,v); +y
·          table           xyv@primary        ·                   ·
·          spans           /1-/1/10           ·                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu LEFT OUTER JOIN xyv ON xyu.x = xyv.x AND xyu.y = xyv.y AND xyu.x = 1 AND xyu.y < 10
----
join       ·               ·                                                     (x, y, u, x, y, v)  ·
 │         type            left outer                                            ·                   ·
 │         equality        (x, y) = (x, y)                                       ·                   ·
 │         mergeJoinOrder  +"(x=x)",+"(y=y)"                                     ·                   ·
 │         pred            (test.public.xyu.x = 1) AND (test.public.xyu.y < 10)  ·                   ·
 ├── scan  ·               ·                                                     (x, y, u)           x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
 │         table           xyu@primary                                           ·                   ·
 │         spans           ALL                                                   ·                   ·
 └── scan  ·               ·                                                     (x, y, v)           x=CONST; y!=NULL; v!=NULL; key(y,v); +y
·          table           xyv@primary                                           ·                   ·
·          spans           /1-/1/10                                              ·                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu RIGHT OUTER JOIN xyv ON xyu.x = xyv.x AND xyu.y = xyv.y AND xyu.x = 1 AND xyu.y < 10
----
join       ·               ·                                                     (x, y, u, x, y, v)  ·
 │         type            right outer                                           ·                   ·
 │         equality        (x, y) = (x, y)                                       ·                   ·
 │         mergeJoinOrder  +"(x=x)",+"(y=y)"                                     ·                   ·
 │         pred            (test.public.xyv.x = 1) AND (test.public.xyv.y < 10)  ·                   ·
 ├── scan  ·               ·                                                     (x, y, u)           x=CONST; y!=NULL; u!=NULL; key(y,u); +y
 │         table           xyu@primary                                           ·                   ·
 │         spans           /1-/1/10                                              ·                   ·
 └── scan  ·               ·                                                     (x, y, v)           x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·          table           xyv@primary                                           ·                   ·
·          spans           ALL                                                   ·                   ·


# Test OUTER joins that are run in the distSQL merge joiner

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT * FROM xyu ORDER BY x, y) AS xyu LEFT OUTER JOIN (SELECT * FROM xyv ORDER BY x, y) AS xyv USING(x, y) WHERE x > 2
----
render          ·               ·                  (x, y, u, v)                          ·
 │              render 0        xyu.x              ·                                     ·
 │              render 1        xyu.y              ·                                     ·
 │              render 2        xyu.u              ·                                     ·
 │              render 3        xyv.v              ·                                     ·
 └── join       ·               ·                  (x, y, u, x[omitted], y[omitted], v)  ·
      │         type            left outer         ·                                     ·
      │         equality        (x, y) = (x, y)    ·                                     ·
      │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                                     ·
      ├── scan  ·               ·                  (x, y, u)                             x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
      │         table           xyu@primary        ·                                     ·
      │         spans           /3-                ·                                     ·
      └── scan  ·               ·                  (x, y, v)                             x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·               table           xyv@primary        ·                                     ·
·               spans           /3-                ·                                     ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT * FROM xyu ORDER BY x, y) AS xyu RIGHT OUTER JOIN (SELECT * FROM xyv ORDER BY x, y) AS xyv USING(x, y) WHERE x > 2
----
render               ·               ·                  (x, y, u, v)                                        ·
 │                   render 0        xyv.x              ·                                                   ·
 │                   render 1        xyv.y              ·                                                   ·
 │                   render 2        xyu.u              ·                                                   ·
 │                   render 3        xyv.v              ·                                                   ·
 └── render          ·               ·                  (x, y, x[hidden,omitted], y[hidden,omitted], u, v)  ·
      │              render 0        xyv.x              ·                                                   ·
      │              render 1        xyv.y              ·                                                   ·
      │              render 2        NULL               ·                                                   ·
      │              render 3        NULL               ·                                                   ·
      │              render 4        xyu.u              ·                                                   ·
      │              render 5        xyv.v              ·                                                   ·
      └── join       ·               ·                  (x[omitted], y[omitted], u, x, y, v)                ·
           │         type            right outer        ·                                                   ·
           │         equality        (x, y) = (x, y)    ·                                                   ·
           │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                                                   ·
           ├── scan  ·               ·                  (x, y, u)                                           x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
           │         table           xyu@primary        ·                                                   ·
           │         spans           /3-                ·                                                   ·
           └── scan  ·               ·                  (x, y, v)                                           x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·                    table           xyv@primary        ·                                                   ·
·                    spans           /3-                ·                                                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT * FROM xyu ORDER BY x, y) AS xyu FULL OUTER JOIN (SELECT * FROM xyv ORDER BY x, y) AS xyv USING(x, y) WHERE x > 2
----
render                    ·               ·                     (x, y, u, v)                                                                              x!=NULL
 │                        render 0        x                     ·                                                                                         ·
 │                        render 1        y                     ·                                                                                         ·
 │                        render 2        xyu.u                 ·                                                                                         ·
 │                        render 3        xyv.v                 ·                                                                                         ·
 └── filter               ·               ·                     (x, y, x[hidden,omitted], y[hidden,omitted], u, x[hidden,omitted], y[hidden,omitted], v)  x!=NULL
      │                   filter          x > 2                 ·                                                                                         ·
      └── render          ·               ·                     (x, y, x[hidden,omitted], y[hidden,omitted], u, x[hidden,omitted], y[hidden,omitted], v)  ·
           │              render 0        IFNULL(xyu.x, xyv.x)  ·                                                                                         ·
           │              render 1        IFNULL(xyu.y, xyv.y)  ·                                                                                         ·
           │              render 2        NULL                  ·                                                                                         ·
           │              render 3        NULL                  ·                                                                                         ·
           │              render 4        xyu.u                 ·                                                                                         ·
           │              render 5        NULL                  ·                                                                                         ·
           │              render 6        NULL                  ·                                                                                         ·
           │              render 7        xyv.v                 ·                                                                                         ·
           └── join       ·               ·                     (x, y, u, x, y, v)                                                                        ·
                │         type            full outer            ·                                                                                         ·
                │         equality        (x, y) = (x, y)       ·                                                                                         ·
                │         mergeJoinOrder  +"(x=x)",+"(y=y)"     ·                                                                                         ·
                ├── scan  ·               ·                     (x, y, u)                                                                                 x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
                │         table           xyu@primary           ·                                                                                         ·
                │         spans           ALL                   ·                                                                                         ·
                └── scan  ·               ·                     (x, y, v)                                                                                 x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·                         table           xyv@primary           ·                                                                                         ·
·                         spans           ALL                   ·                                                                                         ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT * FROM xyu ORDER BY x, y) AS xyu LEFT OUTER JOIN (SELECT * FROM xyv ORDER BY x, y) AS xyv ON xyu.x = xyv.x AND xyu.y = xyv.y AND xyu.x = 1 AND xyu.y < 10
----
join       ·               ·                             (x, y, u, x, y, v)  ·
 │         type            left outer                    ·                   ·
 │         equality        (x, y) = (x, y)               ·                   ·
 │         mergeJoinOrder  +"(x=x)",+"(y=y)"             ·                   ·
 │         pred            (xyu.x = 1) AND (xyu.y < 10)  ·                   ·
 ├── scan  ·               ·                             (x, y, u)           x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
 │         table           xyu@primary                   ·                   ·
 │         spans           ALL                           ·                   ·
 └── scan  ·               ·                             (x, y, v)           x=CONST; y!=NULL; v!=NULL; key(y,v); +y
·          table           xyv@primary                   ·                   ·
·          spans           /1-/1/10                      ·                   ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu RIGHT OUTER JOIN (SELECT * FROM xyv ORDER BY x, y) AS xyv ON xyu.x = xyv.x AND xyu.y = xyv.y AND xyu.x = 1 AND xyu.y < 10
----
join       ·               ·                             (x, y, u, x, y, v)  ·
 │         type            right outer                   ·                   ·
 │         equality        (x, y) = (x, y)               ·                   ·
 │         mergeJoinOrder  +"(x=x)",+"(y=y)"             ·                   ·
 │         pred            (xyv.x = 1) AND (xyv.y < 10)  ·                   ·
 ├── scan  ·               ·                             (x, y, u)           x=CONST; y!=NULL; u!=NULL; key(y,u); +y
 │         table           xyu@primary                   ·                   ·
 │         spans           /1-/1/10                      ·                   ·
 └── scan  ·               ·                             (x, y, v)           x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·          table           xyv@primary                   ·                   ·
·          spans           ALL                           ·                   ·

# Regression test for #20472: break up tuple inequalities.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM xyu JOIN xyv USING(x, y) WHERE (x, y, u) > (1, 2, 3)
----
render          ·               ·                  (x, y, u, v)                          x!=NULL; y!=NULL
 │              render 0        test.public.xyu.x  ·                                     ·
 │              render 1        test.public.xyu.y  ·                                     ·
 │              render 2        test.public.xyu.u  ·                                     ·
 │              render 3        test.public.xyv.v  ·                                     ·
 └── join       ·               ·                  (x, y, u, x[omitted], y[omitted], v)  x=x; y=y; x!=NULL; y!=NULL
      │         type            inner              ·                                     ·
      │         equality        (x, y) = (x, y)    ·                                     ·
      │         mergeJoinOrder  +"(x=x)",+"(y=y)"  ·                                     ·
      ├── scan  ·               ·                  (x, y, u)                             x!=NULL; y!=NULL; u!=NULL; key(x,y,u); +x,+y
      │         table           xyu@primary        ·                                     ·
      │         spans           /1/2/4-            ·                                     ·
      └── scan  ·               ·                  (x, y, v)                             x!=NULL; y!=NULL; v!=NULL; key(x,y,v); +x,+y
·               table           xyv@primary        ·                                     ·
·               spans           /1/2-              ·                                     ·


# Regression test for #20858.

statement ok
CREATE TABLE l (a INT PRIMARY KEY)

statement ok
CREATE TABLE r (a INT PRIMARY KEY)

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM l LEFT OUTER JOIN r USING(a) WHERE a = 3;
----
render          ·               ·                (a)              ·
 │              render 0        test.public.l.a  ·                ·
 └── join       ·               ·                (a, a[omitted])  ·
      │         type            left outer       ·                ·
      │         equality        (a) = (a)        ·                ·
      │         mergeJoinOrder  +"(a=a)"         ·                ·
      ├── scan  ·               ·                (a)              a=CONST; key()
      │         table           l@primary        ·                ·
      │         spans           /3-/3/#          ·                ·
      └── scan  ·               ·                (a)              a=CONST; key()
·               table           r@primary        ·                ·
·               spans           /3-/3/#          ·                ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM l LEFT OUTER JOIN r ON l.a = r.a WHERE l.a = 3;
----
join       ·               ·           (a, a)  ·
 │         type            left outer  ·       ·
 │         equality        (a) = (a)   ·       ·
 │         mergeJoinOrder  +"(a=a)"    ·       ·
 ├── scan  ·               ·           (a)     a=CONST; key()
 │         table           l@primary   ·       ·
 │         spans           /3-/3/#     ·       ·
 └── scan  ·               ·           (a)     a=CONST; key()
·          table           r@primary   ·       ·
·          spans           /3-/3/#     ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM l RIGHT OUTER JOIN r USING(a) WHERE a = 3;
----
render               ·               ·                (a)                     ·
 │                   render 0        test.public.r.a  ·                       ·
 └── render          ·               ·                (a, a[hidden,omitted])  ·
      │              render 0        test.public.r.a  ·                       ·
      │              render 1        NULL             ·                       ·
      └── join       ·               ·                (a[omitted], a)         ·
           │         type            right outer      ·                       ·
           │         equality        (a) = (a)        ·                       ·
           │         mergeJoinOrder  +"(a=a)"         ·                       ·
           ├── scan  ·               ·                (a)                     a=CONST; key()
           │         table           l@primary        ·                       ·
           │         spans           /3-/3/#          ·                       ·
           └── scan  ·               ·                (a)                     a=CONST; key()
·                    table           r@primary        ·                       ·
·                    spans           /3-/3/#          ·                       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM l RIGHT OUTER JOIN r ON l.a = r.a WHERE r.a = 3;
----
join       ·               ·            (a, a)  ·
 │         type            right outer  ·       ·
 │         equality        (a) = (a)    ·       ·
 │         mergeJoinOrder  +"(a=a)"     ·       ·
 ├── scan  ·               ·            (a)     a=CONST; key()
 │         table           l@primary    ·       ·
 │         spans           /3-/3/#      ·       ·
 └── scan  ·               ·            (a)     a=CONST; key()
·          table           r@primary    ·       ·
·          spans           /3-/3/#      ·       ·

# Regression tests for #21243
statement ok
CREATE TABLE abcdef (
  a INT NOT NULL,
  b INT NOT NULL,
  c INT NOT NULL,
  d INT NOT NULL,
  e INT NULL,
  f INT NULL,
  PRIMARY KEY (a ASC, b ASC, c DESC, d ASC)
)

statement ok
CREATE TABLE abg (
  a INT NOT NULL,
  b INT NOT NULL,
  g INT NULL,
  PRIMARY KEY (a ASC, b ASC)
);

query TTT
EXPLAIN SELECT * FROM abcdef join (select * from abg) USING (a,b) WHERE ((a,b)>(1,2) OR ((a,b)=(1,2) AND c < 6) OR ((a,b,c)=(1,2,6) AND d > 8))
----
render          ·               ·
 └── join       ·               ·
      │         type            inner
      │         equality        (a, b) = (a, b)
      │         mergeJoinOrder  +"(a=a)",+"(b=b)"
      ├── scan  ·               ·
      │         table           abcdef@primary
      │         spans           /1/2/6/9-
      │         filter          (((a, b) > (1, 2)) OR (((a = 1) AND (b = 2)) AND (c < 6))) OR ((((a = 1) AND (b = 2)) AND (c = 6)) AND (d > 8))
      └── scan  ·               ·
·               table           abg@primary
·               spans           /1/2-
·               filter          (((a, b) > (1, 2)) OR ((a = 1) AND (b = 2))) OR ((a = 1) AND (b = 2))

# Regression tests for mixed-type equality columns (#22514).
statement ok
CREATE TABLE foo (
  a INT,
  b INT,
  c FLOAT,
  d FLOAT
)

statement ok
CREATE TABLE bar (
  a INT,
  b FLOAT,
  c FLOAT,
  d INT
)

# Only a and c can be equality columns.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo NATURAL JOIN bar
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 └── join       ·         ·
      │         type      inner
      │         equality  (a, c) = (a, c)
      │         pred      (test.public.foo.b = test.public.bar.b) AND (test.public.foo.d = test.public.bar.d)
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

# b can't be an equality column.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo JOIN bar USING (b)
]
----
render               ·         ·
 │                   render 0  test.public.foo.b
 │                   render 1  test.public.foo.a
 │                   render 2  test.public.foo.c
 │                   render 3  test.public.foo.d
 │                   render 4  test.public.bar.a
 │                   render 5  test.public.bar.c
 │                   render 6  test.public.bar.d
 └── render          ·         ·
      │              render 0  test.public.foo.b
      │              render 1  test.public.foo.a
      │              render 2  test.public.foo.c
      │              render 3  test.public.foo.d
      │              render 4  NULL
      │              render 5  test.public.bar.a
      │              render 6  NULL
      │              render 7  test.public.bar.c
      │              render 8  test.public.bar.d
      │              render 9  NULL
      └── join       ·         ·
           │         type      inner
           │         pred      test.public.foo.b = test.public.bar.b
           ├── scan  ·         ·
           │         table     foo@primary
           │         spans     ALL
           └── scan  ·         ·
·                    table     bar@primary
·                    spans     ALL

# Only a can be an equality column.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo JOIN bar USING (a, b)
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.c
 │              render 5  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         equality  (a) = (a)
      │         pred      test.public.foo.b = test.public.bar.b
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

# Only a and c can be equality columns.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo JOIN bar USING (a, b, c)
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         equality  (a, c) = (a, c)
      │         pred      test.public.foo.b = test.public.bar.b
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

# b can't be an equality column.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo JOIN bar ON foo.b = bar.b
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.a
 │              render 5  test.public.bar.b
 │              render 6  test.public.bar.c
 │              render 7  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         pred      test.public.foo.b = test.public.bar.b
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

# Only a can be an equality column.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo JOIN bar ON foo.a = bar.a AND foo.b = bar.b
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.a
 │              render 5  test.public.bar.b
 │              render 6  test.public.bar.c
 │              render 7  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         equality  (a) = (a)
      │         pred      test.public.foo.b = test.public.bar.b
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo, bar WHERE foo.b = bar.b
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.a
 │              render 5  test.public.bar.b
 │              render 6  test.public.bar.c
 │              render 7  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         pred      test.public.foo.b = test.public.bar.b
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

# Only a can be an equality column.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo, bar WHERE foo.a = bar.a AND foo.b = bar.b
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.a
 │              render 5  test.public.bar.b
 │              render 6  test.public.bar.c
 │              render 7  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         equality  (a) = (a)
      │         pred      test.public.foo.b = test.public.bar.b
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL

# Only a and c can be equality columns.
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) SELECT * FROM foo JOIN bar USING (a,b) WHERE foo.c = bar.c AND foo.d = bar.d
]
----
render          ·         ·
 │              render 0  test.public.foo.a
 │              render 1  test.public.foo.b
 │              render 2  test.public.foo.c
 │              render 3  test.public.foo.d
 │              render 4  test.public.bar.c
 │              render 5  test.public.bar.d
 └── join       ·         ·
      │         type      inner
      │         equality  (a, c) = (a, c)
      │         pred      (test.public.foo.b = test.public.bar.b) AND (test.public.foo.d = test.public.bar.d)
      ├── scan  ·         ·
      │         table     foo@primary
      │         spans     ALL
      └── scan  ·         ·
·               table     bar@primary
·               spans     ALL
