# LogicTest: local-opt

statement ok
CREATE TABLE kv (
  k VARCHAR PRIMARY KEY,
  v VARCHAR,
  UNIQUE INDEX a (v),
  FAMILY (k),
  FAMILY (v)
)

statement ok
INSERT INTO kv VALUES ('A');
INSERT INTO kv (k) VALUES ('nil1');
INSERT INTO kv (k) VALUES ('nil2');
INSERT INTO kv VALUES ('nil3', NULL);
INSERT INTO kv VALUES ('nil4', NULL);
INSERT INTO kv (k,v) VALUES ('a', 'b'), ('c', 'd');

query T
SELECT v || 'hello' FROM [INSERT INTO kv VALUES ('e', 'f'), ('g', '') RETURNING v]
----
fhello
hello

statement ok
SET tracing = on,kv,results; SELECT * FROM kv; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/primary/'A' -> NULL
output row: ['A' NULL]
fetched: /kv/primary/'a' -> NULL
fetched: /kv/primary/'a'/v -> 'b'
output row: ['a' 'b']
fetched: /kv/primary/'c' -> NULL
fetched: /kv/primary/'c'/v -> 'd'
output row: ['c' 'd']
fetched: /kv/primary/'e' -> NULL
fetched: /kv/primary/'e'/v -> 'f'
output row: ['e' 'f']
fetched: /kv/primary/'g' -> NULL
fetched: /kv/primary/'g'/v -> ''
output row: ['g' '']
fetched: /kv/primary/'nil1' -> NULL
output row: ['nil1' NULL]
fetched: /kv/primary/'nil2' -> NULL
output row: ['nil2' NULL]
fetched: /kv/primary/'nil3' -> NULL
output row: ['nil3' NULL]
fetched: /kv/primary/'nil4' -> NULL
output row: ['nil4' NULL]

statement ok
SET tracing = on,kv,results; SELECT * FROM kv@a; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/a/NULL -> /'A'
output row: ['A' NULL]
fetched: /kv/a/NULL -> /'nil1'
output row: ['nil1' NULL]
fetched: /kv/a/NULL -> /'nil2'
output row: ['nil2' NULL]
fetched: /kv/a/NULL -> /'nil3'
output row: ['nil3' NULL]
fetched: /kv/a/NULL -> /'nil4'
output row: ['nil4' NULL]
fetched: /kv/a/'' -> /'g'
output row: ['g' '']
fetched: /kv/a/'b' -> /'a'
output row: ['a' 'b']
fetched: /kv/a/'d' -> /'c'
output row: ['c' 'd']
fetched: /kv/a/'f' -> /'e'
output row: ['e' 'f']

statement error pgcode 23505 duplicate key value \(v\)=\('f'\) violates unique constraint "a"
INSERT INTO kv VALUES ('h', 'f')

statement ok
SET tracing = on,kv,results; SELECT * FROM kv; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/primary/'A' -> NULL
output row: ['A' NULL]
fetched: /kv/primary/'a' -> NULL
fetched: /kv/primary/'a'/v -> 'b'
output row: ['a' 'b']
fetched: /kv/primary/'c' -> NULL
fetched: /kv/primary/'c'/v -> 'd'
output row: ['c' 'd']
fetched: /kv/primary/'e' -> NULL
fetched: /kv/primary/'e'/v -> 'f'
output row: ['e' 'f']
fetched: /kv/primary/'g' -> NULL
fetched: /kv/primary/'g'/v -> ''
output row: ['g' '']
fetched: /kv/primary/'nil1' -> NULL
output row: ['nil1' NULL]
fetched: /kv/primary/'nil2' -> NULL
output row: ['nil2' NULL]
fetched: /kv/primary/'nil3' -> NULL
output row: ['nil3' NULL]
fetched: /kv/primary/'nil4' -> NULL
output row: ['nil4' NULL]

statement ok
SET tracing = on,kv,results; SELECT * FROM kv@a; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/a/NULL -> /'A'
output row: ['A' NULL]
fetched: /kv/a/NULL -> /'nil1'
output row: ['nil1' NULL]
fetched: /kv/a/NULL -> /'nil2'
output row: ['nil2' NULL]
fetched: /kv/a/NULL -> /'nil3'
output row: ['nil3' NULL]
fetched: /kv/a/NULL -> /'nil4'
output row: ['nil4' NULL]
fetched: /kv/a/'' -> /'g'
output row: ['g' '']
fetched: /kv/a/'b' -> /'a'
output row: ['a' 'b']
fetched: /kv/a/'d' -> /'c'
output row: ['c' 'd']
fetched: /kv/a/'f' -> /'e'
output row: ['e' 'f']

statement ok
INSERT INTO kv VALUES ('f', 'g')

statement ok
SET tracing = on,kv,results; SELECT * FROM kv; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/primary/'A' -> NULL
output row: ['A' NULL]
fetched: /kv/primary/'a' -> NULL
fetched: /kv/primary/'a'/v -> 'b'
output row: ['a' 'b']
fetched: /kv/primary/'c' -> NULL
fetched: /kv/primary/'c'/v -> 'd'
output row: ['c' 'd']
fetched: /kv/primary/'e' -> NULL
fetched: /kv/primary/'e'/v -> 'f'
output row: ['e' 'f']
fetched: /kv/primary/'f' -> NULL
fetched: /kv/primary/'f'/v -> 'g'
output row: ['f' 'g']
fetched: /kv/primary/'g' -> NULL
fetched: /kv/primary/'g'/v -> ''
output row: ['g' '']
fetched: /kv/primary/'nil1' -> NULL
output row: ['nil1' NULL]
fetched: /kv/primary/'nil2' -> NULL
output row: ['nil2' NULL]
fetched: /kv/primary/'nil3' -> NULL
output row: ['nil3' NULL]
fetched: /kv/primary/'nil4' -> NULL
output row: ['nil4' NULL]

statement ok
SET tracing = on,kv,results; SELECT * FROM kv@a; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/a/NULL -> /'A'
output row: ['A' NULL]
fetched: /kv/a/NULL -> /'nil1'
output row: ['nil1' NULL]
fetched: /kv/a/NULL -> /'nil2'
output row: ['nil2' NULL]
fetched: /kv/a/NULL -> /'nil3'
output row: ['nil3' NULL]
fetched: /kv/a/NULL -> /'nil4'
output row: ['nil4' NULL]
fetched: /kv/a/'' -> /'g'
output row: ['g' '']
fetched: /kv/a/'b' -> /'a'
output row: ['a' 'b']
fetched: /kv/a/'d' -> /'c'
output row: ['c' 'd']
fetched: /kv/a/'f' -> /'e'
output row: ['e' 'f']
fetched: /kv/a/'g' -> /'f'
output row: ['f' 'g']

statement error duplicate key value \(v\)=\('g'\) violates unique constraint "a"
INSERT INTO kv VALUES ('h', 'g')

statement ok
SET tracing = on,kv,results; SELECT * FROM kv; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/primary/'A' -> NULL
output row: ['A' NULL]
fetched: /kv/primary/'a' -> NULL
fetched: /kv/primary/'a'/v -> 'b'
output row: ['a' 'b']
fetched: /kv/primary/'c' -> NULL
fetched: /kv/primary/'c'/v -> 'd'
output row: ['c' 'd']
fetched: /kv/primary/'e' -> NULL
fetched: /kv/primary/'e'/v -> 'f'
output row: ['e' 'f']
fetched: /kv/primary/'f' -> NULL
fetched: /kv/primary/'f'/v -> 'g'
output row: ['f' 'g']
fetched: /kv/primary/'g' -> NULL
fetched: /kv/primary/'g'/v -> ''
output row: ['g' '']
fetched: /kv/primary/'nil1' -> NULL
output row: ['nil1' NULL]
fetched: /kv/primary/'nil2' -> NULL
output row: ['nil2' NULL]
fetched: /kv/primary/'nil3' -> NULL
output row: ['nil3' NULL]
fetched: /kv/primary/'nil4' -> NULL
output row: ['nil4' NULL]

statement ok
SET tracing = on,kv,results; SELECT * FROM kv@a; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv/a/NULL -> /'A'
output row: ['A' NULL]
fetched: /kv/a/NULL -> /'nil1'
output row: ['nil1' NULL]
fetched: /kv/a/NULL -> /'nil2'
output row: ['nil2' NULL]
fetched: /kv/a/NULL -> /'nil3'
output row: ['nil3' NULL]
fetched: /kv/a/NULL -> /'nil4'
output row: ['nil4' NULL]
fetched: /kv/a/'' -> /'g'
output row: ['g' '']
fetched: /kv/a/'b' -> /'a'
output row: ['a' 'b']
fetched: /kv/a/'d' -> /'c'
output row: ['c' 'd']
fetched: /kv/a/'f' -> /'e'
output row: ['e' 'f']
fetched: /kv/a/'g' -> /'f'
output row: ['f' 'g']

statement ok
CREATE TABLE kv5 (
  k CHAR PRIMARY KEY,
  v CHAR,
  UNIQUE INDEX a (v, k)
)

statement ok
INSERT INTO kv5 VALUES ('a', NULL)

statement ok
SET tracing = on,kv,results; SELECT * FROM kv5@a; SET tracing = off

query T
SELECT message FROM [SHOW KV TRACE FOR SESSION]
 WHERE message LIKE 'fetched:%' OR message LIKE 'output row%'
----
fetched: /kv5/a/NULL/'a' -> NULL
output row: ['a' NULL]

statement ok
CREATE TABLE insert_t (x INT, v INT)

statement ok
CREATE TABLE select_t (x INT, v INT)

# Check that INSERT supports ORDER BY (MySQL extension)
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) INSERT INTO insert_t TABLE select_t ORDER BY v DESC LIMIT 10
]
----
count                          ·         ·
 └── insert                    ·         ·
      │                        into      insert_t(x, v, rowid)
      │                        strategy  inserter
      └── render               ·         ·
           │                   render 0  x
           │                   render 1  v
           │                   render 2  unique_rowid()
           └── limit           ·         ·
                │              count     10
                └── sort       ·         ·
                     │         order     -v
                     └── scan  ·         ·
·                              table     select_t@primary
·                              spans     ALL

# Check that INSERT supports LIMIT (MySQL extension)
query TTT
SELECT tree, field, description FROM [
EXPLAIN (VERBOSE) INSERT INTO insert_t SELECT * FROM select_t LIMIT 1
]
----
count                ·         ·
 └── insert          ·         ·
      │              into      insert_t(x, v, rowid)
      │              strategy  inserter
      └── render     ·         ·
           │         render 0  x
           │         render 1  v
           │         render 2  unique_rowid()
           └── scan  ·         ·
·                    table     select_t@primary
·                    spans     ALL
·                    limit     1

# Check the grouping of LIMIT and ORDER BY
query TTT
EXPLAIN (PLAN) INSERT INTO insert_t VALUES (1,1), (2,2) LIMIT 1
----
count                       ·         ·
 └── insert                 ·         ·
      │                     into      insert_t(x, v, rowid)
      │                     strategy  inserter
      └── render            ·         ·
           └── limit        ·         ·
                │           count     1
                └── values  ·         ·
·                           size      2 columns, 2 rows

query TTT
EXPLAIN (PLAN) INSERT INTO insert_t VALUES (1,1), (2,2) ORDER BY 2 LIMIT 1
----
count                            ·         ·
 └── insert                      ·         ·
      │                          into      insert_t(x, v, rowid)
      │                          strategy  inserter
      └── render                 ·         ·
           └── limit             ·         ·
                │                count     1
                └── sort         ·         ·
                     │           order     +column2
                     └── values  ·         ·
·                                size      2 columns, 2 rows

query TTT
EXPLAIN (PLAN) INSERT INTO insert_t (VALUES (1,1), (2,2) ORDER BY 2) LIMIT 1
----
count                            ·         ·
 └── insert                      ·         ·
      │                          into      insert_t(x, v, rowid)
      │                          strategy  inserter
      └── render                 ·         ·
           └── limit             ·         ·
                │                count     1
                └── sort         ·         ·
                     │           order     +column2
                     └── values  ·         ·
·                                size      2 columns, 2 rows

query TTT
EXPLAIN (PLAN) INSERT INTO insert_t (VALUES (1,1), (2,2) ORDER BY 2 LIMIT 1)
----
count                            ·         ·
 └── insert                      ·         ·
      │                          into      insert_t(x, v, rowid)
      │                          strategy  inserter
      └── render                 ·         ·
           └── limit             ·         ·
                │                count     1
                └── sort         ·         ·
                     │           order     +column2
                     └── values  ·         ·
·                                size      2 columns, 2 rows

# ORDER BY expression that's not inserted into table.
query TTTTT
EXPLAIN (VERBOSE)
INSERT INTO insert_t (SELECT length(k), 2 FROM kv ORDER BY k || v LIMIT 10) RETURNING x+v
----
render                                   ·         ·                      ("?column?")                   ·
 │                                       render 0  x + v                  ·                              ·
 └── run                                 ·         ·                      (x, v, rowid[hidden])          ·
      └── insert                         ·         ·                      (x, v, rowid[hidden])          ·
           │                             into      insert_t(x, v, rowid)  ·                              ·
           │                             strategy  inserter               ·                              ·
           └── render                    ·         ·                      (length, "?column?", column9)  ·
                │                        render 0  length                 ·                              ·
                │                        render 1  "?column?"             ·                              ·
                │                        render 2  unique_rowid()         ·                              ·
                └── limit                ·         ·                      (length, "?column?", column8)  +column8
                     │                   count     10                     ·                              ·
                     └── sort            ·         ·                      (length, "?column?", column8)  +column8
                          │              order     +column8               ·                              ·
                          └── render     ·         ·                      (length, "?column?", column8)  ·
                               │         render 0  length(k)              ·                              ·
                               │         render 1  2                      ·                              ·
                               │         render 2  k || v                 ·                              ·
                               └── scan  ·         ·                      (k, v)                         ·
·                                        table     kv@primary             ·                              ·
·                                        spans     ALL                    ·                              ·

# ------------------------------------------------------------------------------
# Insert rows into table during schema changes.
# ------------------------------------------------------------------------------

statement ok
CREATE TABLE mutation(x INT, y INT NOT NULL DEFAULT(10)); INSERT INTO mutation VALUES (1, 1)

statement ok
BEGIN; ALTER TABLE mutation DROP COLUMN y

# Ensure that default value is still inserted into y, since y is write-only.
query TTTTT
EXPLAIN (VERBOSE) INSERT INTO mutation(x) VALUES (2) RETURNING *
----
render                 ·              ·                      (x)                          ·
 │                     render 0       x                      ·                            ·
 └── run               ·              ·                      (x, rowid[hidden])           ·
      └── insert       ·              ·                      (x, rowid[hidden])           ·
           │           into           mutation(x, rowid, y)  ·                            ·
           │           strategy       inserter               ·                            ·
           └── values  ·              ·                      (column1, column5, column6)  ·
·                      size           3 columns, 1 row       ·                            ·
·                      row 0, expr 0  2                      ·                            ·
·                      row 0, expr 1  unique_rowid()         ·                            ·
·                      row 0, expr 2  10                     ·                            ·

statement ok
ROLLBACK

statement ok
BEGIN; ALTER TABLE mutation ADD COLUMN z INT AS (x + y) STORED

# Ensure that value is *not* inserted into z, since z is delete-only.
query TTTTT
EXPLAIN (VERBOSE) INSERT INTO mutation(x, y) VALUES (2, 2)
----
count             ·              ·                      ()                           ·
 └── insert       ·              ·                      ()                           ·
      │           into           mutation(x, y, rowid)  ·                            ·
      │           strategy       inserter               ·                            ·
      └── values  ·              ·                      (column1, column2, column7)  ·
·                 size           3 columns, 1 row       ·                            ·
·                 row 0, expr 0  2                      ·                            ·
·                 row 0, expr 1  2                      ·                            ·
·                 row 0, expr 2  unique_rowid()         ·                            ·

statement ok
ROLLBACK

# Regression test for #35564: make sure we use the Insert's input required
# ordering for the internal projection.

statement ok
CREATE TABLE abc (a INT, b INT, c INT, INDEX(c) STORING(a,b))

statement ok
CREATE TABLE xyz (x INT, y INT, z INT)

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM [INSERT INTO xyz SELECT a, b, c FROM abc RETURNING z] ORDER BY z
----
render                    ·         ·                    (z)                       +z
 │                        render 0  z                    ·                         ·
 └── run                  ·         ·                    (x, y, z, rowid[hidden])  ·
      └── insert          ·         ·                    (x, y, z, rowid[hidden])  ·
           │              into      xyz(x, y, z, rowid)  ·                         ·
           │              strategy  inserter             ·                         ·
           └── render     ·         ·                    (a, b, c, column9)        +c
                │         render 0  a                    ·                         ·
                │         render 1  b                    ·                         ·
                │         render 2  c                    ·                         ·
                │         render 3  unique_rowid()       ·                         ·
                └── scan  ·         ·                    (a, b, c)                 +c
·                         table     abc@abc_c_idx        ·                         ·
·                         spans     ALL                  ·                         ·

# ------------------------------------------------------------------------------
# Regression for #35364. This tests behavior that is different between the CBO
# and the HP. The CBO will (deliberately) round any input columns *before*
# evaluating any computed columns, as well as rounding the output.
# ------------------------------------------------------------------------------

statement ok
CREATE TABLE t35364(
    x DECIMAL(10,0) CHECK(round(x) = x) PRIMARY KEY,
    y DECIMAL(10,0) DEFAULT (1.5),
    z DECIMAL(10,0) AS (x+y+2.5) STORED CHECK(z >= 7)
)

query TTT
INSERT INTO t35364 (x) VALUES (1.5) RETURNING *
----
2  2  7
