# LogicTest: default parallel-stmts distsql

# The join condition logic is tricky to get right with NULL
# values. Simple implementations can deal well with NULLs on the first
# or last row but fail to handle them in the middle. So the test table
# must contain at least 3 rows with a null in the middle. This test
# table also contains the pair 44/42 so that a test with a non-trivial
# ON condition can be written.
statement ok
CREATE TABLE onecolumn (x INT); INSERT INTO onecolumn(x) VALUES (44), (NULL), (42)

query II colnames,rowsort
SELECT * FROM onecolumn AS a(x) CROSS JOIN onecolumn AS b(y)
----
   x     y
  44    44
  44  NULL
  44    42
NULL    44
NULL  NULL
NULL    42
  42    44
  42  NULL
  42    42

# Check that name resolution chokes on ambiguity when it needs to.
query error column reference "x" is ambiguous
SELECT x FROM onecolumn AS a, onecolumn AS b

# Check that name resolution does not choke on ambiguity if an
# unqualified column name is requested and there is an anonymous
# source providing this name in addition to two or more named sources
# that also provide it.
query I colnames
SELECT x FROM (SELECT 1 AS x), onecolumn AS a, onecolumn AS b LIMIT 1
----
x
1

query II colnames,rowsort
SELECT * FROM onecolumn AS a(x) JOIN onecolumn AS b(y) ON a.x = b.y
----
 x  y
44 44
42 42

query I colnames
SELECT * FROM onecolumn AS a JOIN onecolumn as b USING(x) ORDER BY x
----
 x
42
44

query I colnames,rowsort
SELECT * FROM onecolumn AS a NATURAL JOIN onecolumn as b
----
 x
44
42

query II colnames,rowsort
SELECT * FROM onecolumn AS a(x) LEFT OUTER JOIN onecolumn AS b(y) ON a.x = b.y
----
   x     y
  44    44
NULL  NULL
  42    42

query I colnames
SELECT * FROM onecolumn AS a LEFT OUTER JOIN onecolumn AS b USING(x) ORDER BY x
----
   x
NULL
  42
  44

# Check that ORDER BY chokes on ambiguity if no table less columns
# were introduced by USING. (#12239)
query error ORDER BY "x" is ambiguous
SELECT * FROM onecolumn AS a, onecolumn AS b ORDER BY x

query I colnames,rowsort
SELECT * FROM onecolumn AS a NATURAL LEFT OUTER JOIN onecolumn AS b
----
   x
  44
NULL
  42

query II colnames,rowsort
SELECT * FROM onecolumn AS a(x) RIGHT OUTER JOIN onecolumn AS b(y) ON a.x = b.y
----
   x     y
  44    44
  42    42
NULL  NULL

query I colnames
SELECT * FROM onecolumn AS a RIGHT OUTER JOIN onecolumn AS b USING(x) ORDER BY x
----
   x
NULL
  42
  44

query I colnames,rowsort
SELECT * FROM onecolumn AS a NATURAL RIGHT OUTER JOIN onecolumn AS b
----
   x
  44
  42
NULL

statement ok
CREATE TABLE onecolumn_w(w INT); INSERT INTO onecolumn_w(w) VALUES (42),(43)

query II colnames,rowsort
SELECT * FROM onecolumn AS a NATURAL JOIN onecolumn_w as b
----
   x  w
  44  42
  44  43
NULL  42
NULL  43
  42  42
  42  43

statement ok
CREATE TABLE othercolumn (x INT); INSERT INTO othercolumn(x) VALUES (43),(42),(16)

query II colnames
SELECT * FROM onecolumn AS a FULL OUTER JOIN othercolumn AS b ON a.x = b.x ORDER BY a.x,b.x
----
x    x
NULL NULL
NULL 16
NULL 43
42   42
44   NULL

query I colnames
SELECT * FROM onecolumn AS a FULL OUTER JOIN othercolumn AS b USING(x) ORDER BY x
----
x
NULL
16
42
43
44

# Check that the source columns can be selected separately from the
# USING column (#12033).
query III colnames
SELECT x AS s, a.x, b.x FROM onecolumn AS a FULL OUTER JOIN othercolumn AS b USING(x) ORDER BY s
----
   s      x      x
NULL   NULL   NULL
  16   NULL     16
  42     42     42
  43   NULL     43
  44     44   NULL

query I colnames
SELECT * FROM onecolumn AS a NATURAL FULL OUTER JOIN othercolumn AS b ORDER BY x
----
x
NULL
16
42
43
44

# Check that a limit on the JOIN's result do not cause rows from the
# JOIN operands to become invisible to the JOIN.
query I colnames
SELECT * FROM (SELECT x FROM onecolumn ORDER BY x DESC) NATURAL JOIN (VALUES (42)) AS v(x) LIMIT 1
----
x
42

statement ok
CREATE TABLE empty (x INT)

query II
SELECT * FROM onecolumn AS a(x) CROSS JOIN empty AS b(y)
----

query II
SELECT * FROM empty AS a CROSS JOIN onecolumn AS b
----

query II
SELECT * FROM onecolumn AS a(x) JOIN empty AS b(y) ON a.x = b.y
----

query I
SELECT * FROM onecolumn AS a JOIN empty AS b USING(x)
----

query II
SELECT * FROM empty AS a(x) JOIN onecolumn AS b(y) ON a.x = b.y
----

query I
SELECT * FROM empty AS a JOIN onecolumn AS b USING(x)
----

query II colnames
SELECT * FROM onecolumn AS a(x) LEFT OUTER JOIN empty AS b(y) ON a.x = b.y ORDER BY a.x
----
x     y
NULL  NULL
42    NULL
44    NULL

query I colnames
SELECT * FROM onecolumn AS a LEFT OUTER JOIN empty AS b USING(x) ORDER BY x
----
x
NULL
42
44

query II
SELECT * FROM empty AS a(x) LEFT OUTER JOIN onecolumn AS b(y) ON a.x = b.y
----

query I
SELECT * FROM empty AS a LEFT OUTER JOIN onecolumn AS b USING(x)
----

query II
SELECT * FROM onecolumn AS a(x) RIGHT OUTER JOIN empty AS b(y) ON a.x = b.y
----

query I
SELECT * FROM onecolumn AS a RIGHT OUTER JOIN empty AS b USING(x)
----

query II colnames
SELECT * FROM empty AS a(x) FULL OUTER JOIN onecolumn AS b(y) ON a.x = b.y ORDER BY b.y
----
x     y
NULL  NULL
NULL  42
NULL  44

query I colnames
SELECT * FROM empty AS a FULL OUTER JOIN onecolumn AS b USING(x) ORDER BY x
----
x
NULL
42
44

query II colnames
SELECT * FROM onecolumn AS a(x) FULL OUTER JOIN empty AS b(y) ON a.x = b.y ORDER BY a.x
----
x     y
NULL  NULL
42    NULL
44    NULL

query I colnames
SELECT * FROM onecolumn AS a FULL OUTER JOIN empty AS b USING(x) ORDER BY x
----
x
NULL
42
44

query II colnames
SELECT * FROM empty AS a(x) FULL OUTER JOIN onecolumn AS b(y) ON a.x = b.y ORDER BY b.y
----
x     y
NULL  NULL
NULL  42
NULL  44

query I colnames
SELECT * FROM empty AS a FULL OUTER JOIN onecolumn AS b USING(x) ORDER BY x
----
x
NULL
42
44

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

# Natural joins with partial match
query II colnames,rowsort
SELECT * FROM onecolumn NATURAL JOIN twocolumn
----
x    y
44   51
42   53

query IIII rowsort
SELECT * FROM twocolumn AS a JOIN twocolumn AS b ON a.x = a.y
----
45  45  44    51
45  45  NULL  52
45  45  42    53
45  45  45    45

# Inner join with filter predicate
query II
SELECT o.x, t.y FROM onecolumn o INNER JOIN twocolumn t ON (o.x=t.x AND t.y=53)
----
42   53

# Outer joins with filter predicate
query II rowsort
SELECT o.x, t.y FROM onecolumn o LEFT OUTER JOIN twocolumn t ON (o.x=t.x AND t.y=53)
----
44   NULL
NULL NULL
42   53

query II rowsort
SELECT o.x, t.y FROM onecolumn o LEFT OUTER JOIN twocolumn t ON (o.x=t.x AND o.x=44)
----
44   51
NULL NULL
42   NULL

query II rowsort
SELECT o.x, t.y FROM onecolumn o LEFT OUTER JOIN twocolumn t ON (o.x=t.x AND t.x=44)
----
44   51
NULL NULL
42   NULL

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

statement ok
CREATE TABLE a (i int); INSERT INTO a VALUES (1), (2), (3)

statement ok
CREATE TABLE b (i int, b bool); INSERT INTO b VALUES (2, true), (3, true), (4, false)

query IIB rowsort
SELECT * FROM a INNER JOIN b ON a.i = b.i
----
2 2 true
3 3 true

query IIB rowsort
SELECT * FROM a LEFT OUTER JOIN b ON a.i = b.i
----
1 NULL NULL
2 2    true
3 3    true

query IIB rowsort
SELECT * FROM a RIGHT OUTER JOIN b ON a.i = b.i
----
2    2    true
3    3    true
NULL 4    false

query IIB rowsort
SELECT * FROM a FULL OUTER JOIN b ON a.i = b.i
----
1    NULL NULL
2    2    true
3    3    true
NULL 4    false

# Full outer join with filter predicate
query IIB
SELECT * FROM a FULL OUTER JOIN b ON (a.i = b.i and a.i>2) ORDER BY a.i, b.i
----
NULL 2    true
NULL 4    false
1    NULL NULL
2    NULL NULL
3    3    true

# Duplicate right matches for a single left row
statement ok
INSERT INTO b VALUES (3, false)

query IIB
SELECT * FROM a RIGHT OUTER JOIN b ON a.i=b.i ORDER BY b.i, b.b
----
2    2 true
3    3 false
3    3 true
NULL 4 false

query IIB
SELECT * FROM a FULL OUTER JOIN b ON a.i=b.i ORDER BY b.i, b.b
----
1    NULL NULL
2    2    true
3    3    false
3    3    true
NULL 4    false


# Check column orders and names.
query IIIIII colnames
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) ORDER BY 1 LIMIT 1
----
x  x  y  b  d  e
42 42 53 42 42 53


# Check EXPLAIN.
query ITTT
EXPLAIN (EXPRS) SELECT * FROM onecolumn JOIN twocolumn USING(x)
----
0  render
0                 render 0  x
0                 render 1  y
1  join
1                 type      inner
1                 equality  (x) = (x)
2  scan
2                 table     onecolumn@primary
2                 spans     ALL
2  scan
2                 table     twocolumn@primary
2                 spans     ALL

# Check EXPLAIN.
query ITTT
EXPLAIN (EXPRS) SELECT * FROM twocolumn AS a JOIN twocolumn AS b ON a.x = b.y
----
0  render
0                 render 0  x
0                 render 1  y
0                 render 2  x
0                 render 3  y
1  join
1                 type      inner
1                 equality  (x) = (y)
2  scan
2                 table     twocolumn@primary
2                 spans     ALL
2  scan
2                 table     twocolumn@primary
2                 spans     ALL

# Check EXPLAIN.
query ITTT
EXPLAIN (EXPRS) SELECT * FROM twocolumn AS a JOIN twocolumn AS b ON a.x = 44
----
0  render
0                 render 0  x
0                 render 1  y
0                 render 2  x
0                 render 3  y
1  join
1                 type      cross
2  scan
2                 table     twocolumn@primary
2                 spans     ALL
2                 filter    x = 44
2  scan
2                 table     twocolumn@primary
2                 spans     ALL

# Check EXPLAIN.
query ITTT
EXPLAIN (EXPRS) SELECT * FROM onecolumn AS a JOIN twocolumn AS b ON ((a.x)) = ((b.y))
----
0  render
0                 render 0  x
0                 render 1  x
0                 render 2  y
1  join
1                 type      inner
1                 equality  (x) = (y)
2  scan
2                 table     onecolumn@primary
2                 spans     ALL
2  scan
2                 table     twocolumn@primary
2                 spans     ALL

# Check EXPLAIN.
query ITTT
EXPLAIN (EXPRS) SELECT * FROM onecolumn JOIN twocolumn ON onecolumn.x = twocolumn.y
----
0  render
0                 render 0  x
0                 render 1  x
0                 render 2  y
1  join
1                 type      inner
1                 equality  (x) = (y)
2  scan
2                 table     onecolumn@primary
2                 spans     ALL
2  scan
2                 table     twocolumn@primary
2                 spans     ALL


query ITTT
EXPLAIN (EXPRS) 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
----
0  limit
0                 count     1
1  render
1                 render 0  x
1                 render 1  x
1                 render 2  y
1                 render 3  b
1                 render 4  d
1                 render 5  e
2  join
2                 type      inner
2                 equality  (b, x) = (d, d)
3  join
3                 type      inner
3                 equality  (x) = (b)
4  join
4                 type      cross
5  scan
5                 table     onecolumn@primary
5                 spans     ALL
5  scan
5                 table     twocolumn@primary
5                 spans     ALL
4  scan
4                 table     onecolumn@primary
4                 spans     ALL
3  scan
3                 table     twocolumn@primary
3                 spans     ALL

# Check sub-queries in ON conditions.
query III colnames
SELECT * FROM onecolumn JOIN twocolumn ON twocolumn.x = onecolumn.x AND onecolumn.x IN (SELECT x FROM twocolumn WHERE y >= 52)
----
x    x    y
42   42   53

# Check sub-queries as data sources.
query I colnames
SELECT * FROM onecolumn JOIN (VALUES (41),(42),(43)) AS a(x) USING(x)
----
x
42

query I colnames
SELECT * FROM onecolumn JOIN (SELECT x + 2 AS x FROM onecolumn) USING(x)
----
x
44

# Check that a single column can have multiple table aliases.
query IIII colnames
SELECT * FROM (twocolumn AS a JOIN twocolumn AS b USING(x) JOIN twocolumn AS c USING(x)) ORDER BY x LIMIT 1
----
x  y  y  y
42 53 53 53

query IIIIII colnames
SELECT a.x AS s, b.x, c.x, a.y, b.y, c.y FROM (twocolumn AS a JOIN twocolumn AS b USING(x) JOIN twocolumn AS c USING(x)) ORDER BY s
----
 s   x   x   y   y   y
 42  42  42  53  53  53
 44  44  44  51  51  51
 45  45  45  45  45  45

query error column "y" specified in USING clause does not exist
SELECT * FROM (onecolumn AS a JOIN onecolumn AS b USING(y))

query error column "x" appears more than once in USING clause
SELECT * FROM (onecolumn AS a JOIN onecolumn AS b USING(x, x))

statement ok
CREATE TABLE othertype (x TEXT)

query error JOIN/USING types.*cannot be matched
SELECT * FROM (onecolumn AS a JOIN othertype AS b USING(x))

query error cannot join columns from the same source name "onecolumn"
SELECT * FROM (onecolumn JOIN onecolumn USING(x))

query error cannot join columns from the same source name "onecolumn"
SELECT * FROM (onecolumn JOIN twocolumn USING(x) JOIN onecolumn USING(x))

# Check that star expansion works across anonymous sources.
query II rowsort
SELECT * FROM (SELECT * FROM onecolumn), (SELECT * FROM onecolumn)
----
  42     42
  42     44
  42   NULL
  44     42
  44     44
  44   NULL
NULL     42
NULL     44
NULL   NULL

# Check that anonymous sources are properly looked up without ambiguity.
query I
SELECT x FROM (onecolumn JOIN othercolumn USING (x)) JOIN (onecolumn AS a JOIN othercolumn AS b USING(x)) USING(x)
----
42

# Check that multiple anonymous sources cause proper ambiguity errors.
query error column reference "x" is ambiguous
SELECT x FROM (SELECT * FROM onecolumn), (SELECT * FROM onecolumn)

query error column reference "x" is ambiguous
SELECT * FROM (onecolumn AS a JOIN onecolumn AS b ON x > 32)

query error column name "a\.y" not found
SELECT * FROM (onecolumn AS a JOIN onecolumn AS b ON a.y > y)

statement ok
CREATE TABLE s(x INT); INSERT INTO s(x) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

# The following query demands at least 100GB of RAM if unoptimized.
query error memory budget exceeded
SELECT COUNT(a.x+b.x+c.x+d.x+e.x+f.x+g.x+h.x+i.x+j.x+k.x) FROM s AS a, s AS b, s AS c, s AS d, s AS e, s AS f, s AS g, s AS h, s AS i, s AS j, s AS k

# THe following queries verify that only the necessary columns are scanned.
query ITTTTT
EXPLAIN (METADATA) SELECT a.x, b.y FROM twocolumn AS a, twocolumn AS b
----
0  render                            (x, y)
1  join                              (x, y[omitted], rowid[hidden,omitted], x[omitted], y, rowid[hidden,omitted])
1          type   cross
2  scan                              (x, y[omitted], rowid[hidden,omitted])
2          table  twocolumn@primary
2          spans  ALL
2  scan                              (x[omitted], y, rowid[hidden,omitted])
2          table  twocolumn@primary
2          spans  ALL

query ITTTTT
EXPLAIN (METADATA) SELECT b.y FROM (twocolumn AS a JOIN twocolumn AS b USING(x))
----
0  render                               (y)
1  join                                 (x[omitted], x[hidden,omitted], y[omitted], rowid[hidden,omitted], x[hidden,omitted], y, rowid[hidden,omitted])
1          type      inner
1          equality  (x) = (x)
2  scan                                 (x, y[omitted], rowid[hidden,omitted])
2          table     twocolumn@primary
2          spans     ALL
2  scan                                 (x, y, rowid[hidden,omitted])
2          table     twocolumn@primary
2          spans     ALL

query ITTTTT
EXPLAIN (METADATA) SELECT b.y FROM (twocolumn AS a JOIN twocolumn AS b ON a.x = b.x)
----
0  render                               (y)
1  join                                 (x[omitted], y[omitted], rowid[hidden,omitted], x[omitted], y, rowid[hidden,omitted])
1          type      inner
1          equality  (x) = (x)
2  scan                                 (x, y[omitted], rowid[hidden,omitted])
2          table     twocolumn@primary
2          spans     ALL
2  scan                                 (x, y, rowid[hidden,omitted])
2          table     twocolumn@primary
2          spans     ALL

query ITTTTT
EXPLAIN (METADATA) SELECT a.x FROM (twocolumn AS a JOIN twocolumn AS b ON a.x < b.y)
----
0  render                            (x)
1  join                              (x, y[omitted], rowid[hidden,omitted], x[omitted], y[omitted], rowid[hidden,omitted])
1          type   inner
2  scan                              (x, y[omitted], rowid[hidden,omitted])
2          table  twocolumn@primary
2          spans  ALL
2  scan                              (x[omitted], y, rowid[hidden,omitted])
2          table  twocolumn@primary
2          spans  ALL

# Ensure that the ordering information for the result of joins is sane. (#12037)
query ITTTTT
EXPLAIN (METADATA) 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
----
0  sort                                 (k, u, w)                                        +u
0          order     +u
1  render                               (k, u, w)
2  join                                 (k, u, k[hidden,omitted], k[hidden,omitted], w)
2          type      inner
2          equality  (k) = (k)
3  sort                                 (u, k)                                           +k
3          order     +k
4  render                               (u, k)
5  values                               (column1, column2)
5          size      2 columns, 2 rows
3  values                               (column1, column2)
3          size      2 columns, 2 rows

# 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 * FROM [EXPLAIN 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 = 'test'
  AND      fkc.relname = 'orders'
  ORDER BY pkn.nspname,
	   pkc.relname,
	   con.conname,
	   pos.n
  ] WHERE type <> 'values' AND field <> 'size'
----
0   sort
0                  order     +pktable_schem,+pktable_name,+fk_name,+key_seq
1   render
2   join
2                  type      inner
2                  equality  (oid) = (relnamespace)
3   virtual table
3                  source    pg_catalog.pg_namespace
3   join
3                  type      inner
3                  equality  (oid, oid) = (attrelid, confrelid)
4   virtual table
4                  source    pg_catalog.pg_class
4   join
4                  type      inner
5   virtual table
5                  source    pg_catalog.pg_attribute
5   join
5                  type      inner
5                  equality  (oid) = (relnamespace)
6   filter
7   virtual table
7                  source    pg_catalog.pg_namespace
6   join
6                  type      inner
6                  equality  (oid, oid) = (attrelid, conrelid)
7   filter
8   virtual table
8                  source    pg_catalog.pg_class
7   join
7                  type      inner
8   virtual table
8                  source    pg_catalog.pg_attribute
8   join
8                  type      inner
8                  equality  (oid) = (objid)
9   filter
10  virtual table
10                 source    pg_catalog.pg_constraint
9   join
9                  type      cross
10  generator
10  join
10                 type      inner
10                 equality  (refobjid) = (oid)
11  filter
12  virtual table
12                 source    pg_catalog.pg_depend
11  filter
12  virtual table
12                 source    pg_catalog.pg_class

query TTTTTTTTIIITTI
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 = 'test'
  AND      fkc.relname = 'orders'
  ORDER BY pkn.nspname,
	   pkc.relname,
	   con.conname,
	   pos.n
----
NULL test customers id NULL test orders cust 1 3 3 fk_cust_ref_customers primary 7


# Tests for filter propagation through joins.

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

statement ok
INSERT INTO square VALUES (1,1), (2,4), (3,9), (4,16), (5,25), (6,36)

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

statement ok
INSERT INTO pairs VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (2,3), (2,4), (2,5), (2,6), (3,4), (3,5), (3,6), (4,5), (4,6)

# The filter expression becomes an equality constraint.
query ITTT
EXPLAIN SELECT * FROM pairs, square WHERE pairs.b = square.n
----
0  render
1  join
1        type      inner
1        equality  (b) = (n)
2  scan
2        table     pairs@primary
2        spans     ALL
2  scan
2        table     square@primary
2        spans     ALL

query IIII rowsort
SELECT * FROM pairs, square WHERE pairs.b = square.n
----
1  1  1  1
1  2  2  4
1  3  3  9
1  4  4  16
1  5  5  25
1  6  6  36
2  3  3  9
2  4  4  16
2  5  5  25
2  6  6  36
3  4  4  16
3  5  5  25
3  6  6  36
4  5  5  25
4  6  6  36

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

query IIII rowsort
SELECT * FROM pairs, square WHERE pairs.a + pairs.b = square.sq
----
1  3  2  4
3  6  3  9
4  5  3  9

# 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 ITTTTT
EXPLAIN (VERBOSE) SELECT a, b, n, sq FROM (SELECT a, b, a + b AS sum, n, sq FROM pairs, square) WHERE sum = sq
----
0  render                                         (a, b, n, sq)
0          render 0  a
0          render 1  b
0          render 2  n
0          render 3  sq
1  filter                                         (a, b, sum, n, sq)
1          filter    sum = sq
2  render                                         (a, b, sum, n, sq)
2          render 0  test.pairs.a
2          render 1  test.pairs.b
2          render 2  test.pairs.a + test.pairs.b
2          render 3  test.square.n
2          render 4  test.square.sq
3  join                                           (a, b, rowid[hidden,omitted], n, sq)
3          type      cross
4  scan                                           (a, b, rowid[hidden,omitted])
4          table     pairs@primary
4          spans     ALL
4  scan                                           (n, sq)
4          table     square@primary
4          spans     ALL

query IIII rowsort
SELECT a, b, n, sq FROM (SELECT a, b, a + b AS sum, n, sq FROM pairs, square) WHERE sum = sq
----
1  3  2  4
3  6  3  9
4  5  3  9

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

query IIII rowsort
SELECT * FROM pairs FULL OUTER JOIN square ON pairs.a + pairs.b = square.sq
----
1     1     NULL  NULL
1     2     NULL  NULL
1     3     2     4
1     4     NULL  NULL
1     5     NULL  NULL
1     6     NULL  NULL
2     3     NULL  NULL
2     4     NULL  NULL
2     5     NULL  NULL
2     6     NULL  NULL
3     4     NULL  NULL
3     5     NULL  NULL
3     6     3     9
4     5     3     9
4     6     NULL  NULL
NULL  NULL  1     1
NULL  NULL  4     16
NULL  NULL  5     25
NULL  NULL  6     36

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

query IIII rowsort
SELECT * FROM pairs FULL OUTER JOIN square ON pairs.a + pairs.b = square.sq WHERE pairs.b%2 <> square.sq%2
----
1     3     2     4
3     6     3     9
