# LogicTest: local-opt

# ------------------------------------------------------------------------------
# Uncorrelated subqueries.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE abc (a INT PRIMARY KEY, b INT, c INT)

# Prevent the merge queue from immediately discarding our splits.
statement ok
SET CLUSTER SETTING kv.range_merge.queue_enabled = false;

query TTT
EXPLAIN ALTER TABLE abc SPLIT AT VALUES ((SELECT 42))
----
root                          ·             ·
 ├── split                    ·             ·
 │    └── values              ·             ·
 │                            size          1 column, 1 row
 └── subquery                 ·             ·
      │                       id            @S1
      │                       original sql  (SELECT 42)
      │                       exec mode     one row
      └── limit               ·             ·
           │                  count         2
           └── render         ·             ·
                └── emptyrow  ·             ·

statement ok
ALTER TABLE abc SPLIT AT VALUES ((SELECT 1))

query TTT
EXPLAIN SELECT EXISTS (SELECT a FROM abc)
----
root                ·             ·
 ├── render         ·             ·
 │    └── emptyrow  ·             ·
 └── subquery       ·             ·
      │             id            @S1
      │             original sql  EXISTS (SELECT a FROM abc)
      │             exec mode     exists
      └── scan      ·             ·
·                   table         abc@primary
·                   spans         ALL

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM abc WHERE a = (SELECT max(a) FROM abc WHERE EXISTS(SELECT * FROM abc WHERE c=a+3))
----
root                 ·             ·                                                                            (a, b, c)  ·
 ├── scan            ·             ·                                                                            (a, b, c)  ·
 │                   table         abc@primary                                                                  ·          ·
 │                   spans         ALL                                                                          ·          ·
 │                   filter        a = @S2                                                                      ·          ·
 ├── subquery        ·             ·                                                                            (a, b, c)  ·
 │    │              id            @S1                                                                          ·          ·
 │    │              original sql  EXISTS (SELECT * FROM abc WHERE c = (a + 3))                                 ·          ·
 │    │              exec mode     exists                                                                       ·          ·
 │    └── scan       ·             ·                                                                            (a, b, c)  ·
 │                   table         abc@primary                                                                  ·          ·
 │                   spans         ALL                                                                          ·          ·
 │                   filter        c = (a + 3)                                                                  ·          ·
 └── subquery        ·             ·                                                                            (a, b, c)  ·
      │              id            @S2                                                                          ·          ·
      │              original sql  (SELECT max(a) FROM abc WHERE EXISTS (SELECT * FROM abc WHERE c = (a + 3)))  ·          ·
      │              exec mode     one row                                                                      ·          ·
      └── group      ·             ·                                                                            (agg0)     ·
           │         aggregate 0   max(a)                                                                       ·          ·
           │         scalar        ·                                                                            ·          ·
           └── scan  ·             ·                                                                            (a)        ·
·                    table         abc@primary                                                                  ·          ·
·                    spans         ALL                                                                          ·          ·
·                    filter        @S1                                                                          ·          ·

# IN expression transformed into semi-join.
query TTTTT
EXPLAIN (VERBOSE) SELECT a FROM abc WHERE a IN (SELECT a FROM abc)
----
join       ·               ·            (a)  ·
 │         type            semi         ·    ·
 │         equality        (a) = (a)    ·    ·
 │         mergeJoinOrder  +"(a=a)"     ·    ·
 ├── scan  ·               ·            (a)  +a
 │         table           abc@primary  ·    ·
 │         spans           ALL          ·    ·
 └── scan  ·               ·            (a)  +a
·          table           abc@primary  ·    ·
·          spans           ALL          ·    ·

query TTT
EXPLAIN SELECT * FROM (SELECT * FROM (VALUES (1, 8, 8), (3, 1, 1), (2, 4, 4)) AS moo (moo1, moo2, moo3) ORDER BY moo2) as foo (foo1) ORDER BY foo1
----
sort         ·      ·
 │           order  +foo1
 └── values  ·      ·
·            size   3 columns, 3 rows

# the subquery's plan must be visible in EXPLAIN
query TTT
EXPLAIN VALUES (1), ((SELECT 2))
----
root                     ·             ·
 ├── values              ·             ·
 │                       size          1 column, 2 rows
 └── subquery            ·             ·
      │                  id            @S1
      │                  original sql  (SELECT 2)
      │                  exec mode     one row
      └── render         ·             ·
           └── emptyrow  ·             ·

# This test checks that the double sub-query plan expansion caused by a
# sub-expression being shared by two or more plan nodes does not
# panic.
statement ok
CREATE TABLE tab4(col0 INTEGER, col1 FLOAT, col3 INTEGER, col4 FLOAT)

statement ok
CREATE INDEX idx_tab4_0 ON tab4 (col4,col0)

query TTTTT
EXPLAIN (VERBOSE)
SELECT col0
FROM tab4
WHERE
    (col0 <= 0 AND col4 <= 5.38)
    OR (col4 IN (SELECT col1 FROM tab4 WHERE col1 > 8.27))
    AND (col3 <= 5 AND (col3 BETWEEN 7 AND 9))
----
root            ·             ·                                                                                                           (col0)              ·
 ├── render     ·             ·                                                                                                           (col0)              ·
 │    │         render 0      col0                                                                                                        ·                   ·
 │    └── scan  ·             ·                                                                                                           (col0, col3, col4)  ·
 │              table         tab4@primary                                                                                                ·                   ·
 │              spans         ALL                                                                                                         ·                   ·
 │              filter        ((col0 <= 0) AND (col4 <= 5.38)) OR ((((col4 = ANY @S1) AND (col3 <= 5)) AND (col3 >= 7)) AND (col3 <= 9))  ·                   ·
 └── subquery   ·             ·                                                                                                           (col0)              ·
      │         id            @S1                                                                                                         ·                   ·
      │         original sql  (SELECT col1 FROM tab4 WHERE col1 > 8.27)                                                                   ·                   ·
      │         exec mode     all rows normalized                                                                                         ·                   ·
      └── scan  ·             ·                                                                                                           (col1)              ·
·               table         tab4@primary                                                                                                ·                   ·
·               spans         ALL                                                                                                         ·                   ·
·               filter        col1 > 8.27                                                                                                 ·                   ·

# ------------------------------------------------------------------------------
# Correlated subqueries.
# ------------------------------------------------------------------------------
statement ok
CREATE TABLE a (x INT PRIMARY KEY, y INT);
CREATE TABLE b (x INT PRIMARY KEY, z INT);

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE EXISTS(SELECT * FROM b WHERE a.x=b.x)
----
join       ·               ·          (x, y)  ·
 │         type            semi       ·       ·
 │         equality        (x) = (x)  ·       ·
 │         mergeJoinOrder  +"(x=x)"   ·       ·
 ├── scan  ·               ·          (x, y)  +x
 │         table           a@primary  ·       ·
 │         spans           ALL        ·       ·
 └── scan  ·               ·          (x, z)  +x
·          table           b@primary  ·       ·
·          spans           ALL        ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE EXISTS(SELECT * FROM b WHERE b.x-1 = a.x)
----
join            ·         ·                (x, y)           ·
 │              type      semi             ·                ·
 │              equality  (x) = (column5)  ·                ·
 ├── scan       ·         ·                (x, y)           ·
 │              table     a@primary        ·                ·
 │              spans     ALL              ·                ·
 └── render     ·         ·                (column5, x, z)  ·
      │         render 0  x - 1            ·                ·
      │         render 1  x                ·                ·
      │         render 2  z                ·                ·
      └── scan  ·         ·                (x, z)           ·
·               table     b@primary        ·                ·
·               spans     ALL              ·                ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM a WHERE NOT EXISTS(SELECT * FROM b WHERE b.x = a.x)
----
join       ·               ·          (x, y)  ·
 │         type            anti       ·       ·
 │         equality        (x) = (x)  ·       ·
 │         mergeJoinOrder  +"(x=x)"   ·       ·
 ├── scan  ·               ·          (x, y)  +x
 │         table           a@primary  ·       ·
 │         spans           ALL        ·       ·
 └── scan  ·               ·          (x, z)  +x
·          table           b@primary  ·       ·
·          spans           ALL        ·       ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM b WHERE NOT EXISTS(SELECT * FROM a WHERE x-1 = b.x)
----
join            ·         ·                (x, z)           ·
 │              type      anti             ·                ·
 │              equality  (x) = (column5)  ·                ·
 ├── scan       ·         ·                (x, z)           ·
 │              table     b@primary        ·                ·
 │              spans     ALL              ·                ·
 └── render     ·         ·                (column5, x, y)  ·
      │         render 0  x - 1            ·                ·
      │         render 1  x                ·                ·
      │         render 2  y                ·                ·
      └── scan  ·         ·                (x, y)           ·
·               table     a@primary        ·                ·
·               spans     ALL              ·                ·

query TTTTT
EXPLAIN (VERBOSE) SELECT ARRAY(SELECT x FROM b)
----
root                 ·             ·                       ("array")  ·
 ├── render          ·             ·                       ("array")  ·
 │    │              render 0      COALESCE(@S1, ARRAY[])  ·          ·
 │    └── emptyrow   ·             ·                       ()         ·
 └── subquery        ·             ·                       ("array")  ·
      │              id            @S1                     ·          ·
      │              original sql  (SELECT x FROM b)       ·          ·
      │              exec mode     one row                 ·          ·
      └── group      ·             ·                       (agg0)     ·
           │         aggregate 0   array_agg(x)            ·          ·
           │         scalar        ·                       ·          ·
           └── scan  ·             ·                       (x)        ·
·                    table         b@primary               ·          ·
·                    spans         ALL                     ·          ·

# Case where the plan has an apply join.
query error could not decorrelate subquery
SELECT * FROM abc WHERE EXISTS(SELECT * FROM (VALUES (a), (b)) WHERE column1=a)

# Case where the EXISTS subquery still has outer columns in the subquery
# (regression test for #28816).
query error could not decorrelate subquery
SELECT
  subq_0.c1 AS c1
FROM
  (SELECT ref_0.attrs AS c1 FROM crdb_internal.kv_store_status AS ref_0) AS subq_0
WHERE
  5 >= CASE WHEN subq_0.c1 IS NOT NULL
    THEN 5
    ELSE pg_catalog.extract(
      CAST(
        CASE WHEN (
          EXISTS(
            SELECT ref_1.config_yaml AS c0
            FROM crdb_internal.zones AS ref_1
            WHERE subq_0.c1 IS NOT NULL
          )
        )
        THEN pg_catalog.version()
        ELSE pg_catalog.version()
        END
          AS STRING
      ),
      CAST(pg_catalog.current_date() AS DATE)
    )
    END

# Case where the ANY subquery still has outer columns.
query error could not decorrelate subquery
SELECT
  subq_0.c1 AS c1
FROM
  (SELECT ref_0.attrs AS c1 FROM crdb_internal.kv_store_status AS ref_0) AS subq_0
WHERE
  5 >= CASE WHEN subq_0.c1 IS NOT NULL
    THEN 5
    ELSE pg_catalog.extract(
      CAST(
        CASE
        WHEN (
          '12'::STRING
          = ANY (
              SELECT ref_1.config_yaml AS c0
              FROM crdb_internal.zones AS ref_1
              WHERE subq_0.c1 IS NOT NULL
            )
        )
        THEN pg_catalog.version()
        ELSE pg_catalog.version()
        END
          AS STRING
      ),
      CAST(pg_catalog.current_date() AS DATE)
    )
    END
