statement ok
CREATE TABLE other (b INT PRIMARY KEY)

statement ok
INSERT INTO other VALUES (9)

statement ok
CREATE TABLE t (a INT PRIMARY KEY CHECK(a > 0), f INT REFERENCES other, INDEX (f))

statement ok
INSERT INTO t VALUES (1, 9)

statement error at or near "\*": syntax error
ALTER TABLE t RENAME TO t.*

statement ok
ALTER TABLE t ADD b INT

query TTBTTTB colnames,rowsort
SHOW COLUMNS FROM t
----
column_name  data_type  is_nullable  column_default  generation_expression  indices           is_hidden
a            INT8       false        NULL            ·                      {t_f_idx,t_pkey}  false
f            INT8       true         NULL            ·                      {t_f_idx,t_pkey}  false
b            INT8       true         NULL            ·                      {t_pkey}          false

statement ok
ALTER TABLE t ADD CONSTRAINT foo UNIQUE (b)

statement ok
ALTER TABLE t ADD CONSTRAINT IF NOT EXISTS foo UNIQUE (b)

statement ok
ALTER TABLE t ADD CONSTRAINT IF NOT EXISTS foo UNIQUE (f)

query TTTRT
SELECT description, user_name, status, fraction_completed, error
FROM crdb_internal.jobs
WHERE job_type in ('NEW SCHEMA CHANGE', 'SCHEMA CHANGE')
ORDER BY created DESC
LIMIT 1
----
ALTER TABLE test.public.t ADD CONSTRAINT foo UNIQUE (b)  root  succeeded  1  ·

statement error pgcode 42P07 .* name \"foo\" already exists
ALTER TABLE t ADD CONSTRAINT foo UNIQUE (b)

statement error pq: multiple primary keys for table "t" are not allowed
ALTER TABLE t ADD CONSTRAINT bar PRIMARY KEY (b)

query TTBITTTBBBF colnames,rowsort
SHOW INDEXES FROM t
----
table_name  index_name  non_unique  seq_in_index  column_name  definition  direction  storing  implicit  visible  visibility
t           foo         false       1             b            b           ASC        false    false     true     1
t           foo         false       2             a            a           ASC        true     true      true     1
t           t_f_idx     true        1             f            f           ASC        false    false     true     1
t           t_f_idx     true        2             a            a           ASC        false    true      true     1
t           t_pkey      false       1             a            a           ASC        false    false     true     1
t           t_pkey      false       2             f            f           N/A        true     false     true     1
t           t_pkey      false       3             b            b           N/A        true     false     true     1

query III
SELECT * FROM t
----
1 9 NULL

statement ok
ALTER TABLE t ADD c INT

statement ok
INSERT INTO t VALUES (2, 9, 1, 1), (3, 9, 2, 1)

statement error pgcode 23505 violates unique constraint "bar"
ALTER TABLE t ADD CONSTRAINT bar UNIQUE (c)

statement error pgcode 42703 column "dne" does not exist
ALTER TABLE t ADD CONSTRAINT dne_unique UNIQUE (dne)

# Test that rollback was successful
#
# We ignore the job status because GC for temporary indexes used
# during backfills may already running rather than waiting for the GC
# TTL depending on the timing.
onlyif config local-legacy-schema-changer
query TTT
SELECT job_type, regexp_replace(description, 'JOB \d+', 'JOB ...'), user_name
FROM crdb_internal.jobs
WHERE job_type = 'SCHEMA CHANGE' OR job_type = 'SCHEMA CHANGE GC'
ORDER BY created DESC, 2 DESC
LIMIT 3
----
SCHEMA CHANGE GC  GC for temporary index used during index backfill                           root
SCHEMA CHANGE GC  GC for ROLLBACK of ALTER TABLE test.public.t ADD CONSTRAINT bar UNIQUE (c)  root
SCHEMA CHANGE     ALTER TABLE test.public.t ADD CONSTRAINT bar UNIQUE (c)                     root

query IIII colnames,rowsort
SELECT * FROM t
----
a f b    c
1 9 NULL NULL
2 9 1    1
3 9 2    1

query TTTTB colnames,nosort
SHOW CONSTRAINTS FROM t
----
table_name  constraint_name  constraint_type  details                              validated
t           check_a          CHECK            CHECK ((a > 0))                      true
t           foo              UNIQUE           UNIQUE (b ASC)                       true
t           t_f_fkey         FOREIGN KEY      FOREIGN KEY (f) REFERENCES other(b)  true
t           t_pkey           PRIMARY KEY      PRIMARY KEY (a ASC)                  true

statement error CHECK
INSERT INTO t (a, f) VALUES (-2, 9)

statement ok
ALTER TABLE t DROP CONSTRAINT check_a

statement ok
INSERT INTO t (a, f) VALUES (-2, 9)

statement error validation of CHECK "a > 0:::INT8" failed on row: a=-2, f=9, b=NULL, c=NULL
ALTER TABLE t ADD CONSTRAINT check_a CHECK (a > 0)

statement ok
DELETE FROM t WHERE a = -2

statement ok
ALTER TABLE t ADD CONSTRAINT IF NOT EXISTS check_a CHECK (a > 0)

statement error CHECK
INSERT INTO t (a) VALUES (-3)

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_a   CHECK        CHECK ((a > 0))                      true
t  foo       UNIQUE       UNIQUE (b ASC)                       true
t  t_f_fkey  FOREIGN KEY  FOREIGN KEY (f) REFERENCES other(b)  true
t  t_pkey    PRIMARY KEY  PRIMARY KEY (a ASC)                  true

statement error duplicate constraint name
ALTER TABLE t ADD CONSTRAINT check_a CHECK (a > 0)

statement ok
ALTER TABLE t ADD CONSTRAINT IF NOT EXISTS check_a CHECK (a < 0)

statement error duplicate constraint name
ALTER TABLE t ADD CONSTRAINT t_f_fkey FOREIGN KEY (a) REFERENCES other (b)

# Should be a no-op.
statement ok
ALTER TABLE t ADD CONSTRAINT IF NOT EXISTS t_f_fkey FOREIGN KEY (a) REFERENCES other (b)

# Should be a no-op.
statement ok
ALTER TABLE t ADD CONSTRAINT IF NOT EXISTS t_f_fkey CHECK (a < 0)

# added constraints with generated names avoid name collisions.
statement ok
ALTER TABLE t ADD CHECK (a > 0)

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_a   CHECK        CHECK ((a > 0))                      true
t  check_a1  CHECK        CHECK ((a > 0))                      true
t  foo       UNIQUE       UNIQUE (b ASC)                       true
t  t_f_fkey  FOREIGN KEY  FOREIGN KEY (f) REFERENCES other(b)  true
t  t_pkey    PRIMARY KEY  PRIMARY KEY (a ASC)                  true

statement error constraint "typo" of relation "t" does not exist
ALTER TABLE t VALIDATE CONSTRAINT typo

# TODO(erik): re-enable test when unvalidated checks can be added
#statement error validation of CHECK "a > 0" failed on row: a=-2, f=9, b=NULL, c=NULL
#ALTER TABLE t VALIDATE CONSTRAINT check_a

#statement ok
#DELETE FROM t WHERE a = -2

statement ok
ALTER TABLE t VALIDATE CONSTRAINT check_a

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_a   CHECK        CHECK ((a > 0))                      true
t  check_a1  CHECK        CHECK ((a > 0))                      true
t  foo       UNIQUE       UNIQUE (b ASC)                       true
t  t_f_fkey  FOREIGN KEY  FOREIGN KEY (f) REFERENCES other(b)  true
t  t_pkey    PRIMARY KEY  PRIMARY KEY (a ASC)                  true

statement ok
ALTER TABLE t DROP CONSTRAINT check_a, DROP CONSTRAINT check_a1

statement error pgcode 42703 column "d" does not exist
ALTER TABLE t DROP d

statement ok
ALTER TABLE t DROP IF EXISTS d

statement error column "a" is referenced by the primary key
ALTER TABLE t DROP a

statement error constraint "bar" of relation "t" does not exist
ALTER TABLE t DROP CONSTRAINT bar

statement ok
ALTER TABLE t DROP CONSTRAINT IF EXISTS bar

statement error cannot drop UNIQUE constraint \"foo\" using ALTER TABLE DROP CONSTRAINT, use DROP INDEX CASCADE instead
ALTER TABLE t DROP CONSTRAINT foo

statement ok
DROP INDEX foo CASCADE

onlyif config local-legacy-schema-changer
query TTTTRT retry
SELECT job_type, description, user_name, status, fraction_completed, error
FROM crdb_internal.jobs
WHERE job_type = 'SCHEMA CHANGE' OR job_type = 'SCHEMA CHANGE GC'
ORDER BY created DESC
LIMIT 2
----
SCHEMA CHANGE GC  GC for DROP INDEX test.public.t@foo CASCADE  root  running    0  ·
SCHEMA CHANGE     DROP INDEX test.public.t@foo CASCADE         root  succeeded  1  ·


skipif config local-legacy-schema-changer
query TTTTRT retry
SELECT job_type, description, user_name, status, fraction_completed, error
FROM crdb_internal.jobs
WHERE job_type = 'NEW SCHEMA CHANGE' OR job_type = 'SCHEMA CHANGE GC'
ORDER BY created DESC
LIMIT 2
----
SCHEMA CHANGE GC   GC for DROP INDEX test.public.t@foo CASCADE  node  running    0  ·
NEW SCHEMA CHANGE  DROP INDEX test.public.t@foo CASCADE         root  succeeded  1  ·



query TTBITTTBBBF colnames,rowsort
SHOW INDEXES FROM t
----
table_name  index_name  non_unique  seq_in_index  column_name  definition  direction  storing  implicit  visible  visibility
t           t_f_idx     true        1             f            f           ASC        false    false     true     1
t           t_f_idx     true        2             a            a           ASC        false    true      true     1
t           t_pkey      false       1             a            a           ASC        false    false     true     1
t           t_pkey      false       2             f            f           N/A        true     false     true     1
t           t_pkey      false       3             b            b           N/A        true     false     true     1
t           t_pkey      false       4             c            c           N/A        true     false     true     1

statement ok
ALTER TABLE t DROP b, DROP c

query II rowsort
SELECT * FROM t
----
1  9
2  9
3  9

statement ok
ALTER TABLE t ADD d INT UNIQUE

statement ok
INSERT INTO t VALUES (4, 9, 1)

statement error duplicate key value violates unique constraint \"t_d_key\"\nDETAIL: Key \(d\)=\(1\) already exists\.
INSERT INTO t VALUES (5, 9, 1)

# Add a column with no default value
statement ok
ALTER TABLE t ADD COLUMN x DECIMAL

# Add a non NULL column with a default value
statement ok
ALTER TABLE t ADD COLUMN y DECIMAL NOT NULL DEFAULT (DECIMAL '1.3')

statement error could not parse "1-3" as type decimal
ALTER TABLE t ADD COLUMN p DECIMAL NOT NULL DEFAULT (DECIMAL '1-3')

# Add a non NULL column with no default value
statement error pgcode 23502 null value in column \"q\" violates not-null constraint
ALTER TABLE t ADD COLUMN q DECIMAL NOT NULL

statement ok
ALTER TABLE t ADD COLUMN z DECIMAL DEFAULT (DECIMAL '1.4')

statement ok
INSERT INTO t VALUES (11, 9, 12, DECIMAL '1.0')

statement ok
INSERT INTO t (a, d) VALUES (13, 14)

statement ok
INSERT INTO t (a, d, y) VALUES (21, 22, DECIMAL '1.0')

statement ok
INSERT INTO t (a, d) VALUES (23, 24)

statement error foreign key
INSERT INTO t VALUES (31, 7, 32)

statement ok
ALTER TABLE t DROP CONSTRAINT t_f_fkey

statement  ok
INSERT INTO t VALUES (31, 7, 32)

statement ok
INSERT INTO t (a, d, x, y, z) VALUES (33, 34, DECIMAL '2.0', DECIMAL '2.1', DECIMAL '2.2')

statement ok
DROP INDEX t@t_f_idx

onlyif config local-legacy-schema-changer
query TTTTRT retry
SELECT job_type, description, user_name, status, fraction_completed, error
FROM crdb_internal.jobs
WHERE job_type = 'SCHEMA CHANGE' OR job_type = 'SCHEMA CHANGE GC'
ORDER BY created DESC
LIMIT 2
----
SCHEMA CHANGE GC  GC for DROP INDEX test.public.t@t_f_idx  root  running    0  ·
SCHEMA CHANGE     DROP INDEX test.public.t@t_f_idx         root  succeeded  1  ·

skipif config local-legacy-schema-changer
query TTTTRT retry
SELECT job_type, description, user_name, status, fraction_completed, error
FROM crdb_internal.jobs
WHERE job_type = 'NEW SCHEMA CHANGE' OR job_type = 'SCHEMA CHANGE GC'
ORDER BY created DESC
LIMIT 2
----
SCHEMA CHANGE GC   GC for DROP INDEX test.public.t@t_f_idx  node  running    0  ·
NEW SCHEMA CHANGE  DROP INDEX test.public.t@t_f_idx         root  succeeded  1  ·

statement ok
ALTER TABLE t DROP COLUMN f

query IITTT colnames,rowsort
SELECT * FROM t
----
a   d     x     y     z
1   NULL  NULL  1.3   1.4
2   NULL  NULL  1.3   1.4
3   NULL  NULL  1.3   1.4
4   1     NULL  1.3   1.4
11  12    1.0   1.3   1.4
13  14    NULL  1.3   1.4
21  22    NULL  1.0   1.4
23  24    NULL  1.3   1.4
31  32    NULL  1.3   1.4
33  34    2.0   2.1   2.2

statement ok
ALTER TABLE t DROP COLUMN d

statement ok
ALTER TABLE t ADD COLUMN e INT; ALTER TABLE t ADD COLUMN d INT

statement ok
CREATE VIEW v AS SELECT x, y FROM t WHERE e > 5

statement error cannot drop column "x" because view "v" depends on it
ALTER TABLE t DROP COLUMN x

statement error cannot drop column "y" because view "v" depends on it
ALTER TABLE t DROP COLUMN y

statement error cannot drop column "e" because view "v" depends on it
ALTER TABLE t DROP COLUMN e

statement ok
ALTER TABLE t DROP COLUMN e CASCADE

statement ok
ALTER TABLE t ADD COLUMN e INT

statement ok
CREATE VIEW v AS SELECT x, y FROM t WHERE e > 5

statement ok
ALTER TABLE t DROP COLUMN IF EXISTS q

statement error cannot drop column "e" because view "v" depends on it
ALTER TABLE t DROP COLUMN IF EXISTS e

# Negative test to assert that NOTICEs are NOT emitted if there are no indexes
# being dropped.
# Weak isolation levels emit extra notices, so skip them.
skipif config weak-iso-level-configs
statement notice ^$
ALTER TABLE t DROP COLUMN IF EXISTS e CASCADE

onlyif config weak-iso-level-configs
statement ok
ALTER TABLE t DROP COLUMN IF EXISTS e CASCADE

statement ok
ALTER TABLE t ADD COLUMN g INT UNIQUE

statement ok
CREATE TABLE o (gf INT REFERENCES t (g), h INT, i INT, INDEX oi (i), INDEX oh (h), INDEX oih (i) STORING (h))

statement error "t_g_key" is referenced by foreign key from table "o"
ALTER TABLE t DROP COLUMN g

statement notice NOTICE: dropping index "t_g_key" which depends on column "g"
ALTER TABLE t DROP COLUMN g CASCADE

# Dropping columns that are indexed or stored in indexes drops those indexes
# too. Excuse the nasty regex, the legacy schema changer emits additional
# NOTICEs about GCing. We're not testing for that, so we just "eat" them.
# Example: "NOTICE: the data for dropped indexes is reclaimed
# asynchronously\nHINT: The reclamation delay can be customized in the zone
# configuration for the table."
statement notice (NOTICE: dropping index "(oh|oih)" which depends on column "h"(\nNOTICE: .+\nHINT: .+\n)?\n?){2}
ALTER TABLE o DROP COLUMN h

query TTBITTTBBBF colnames,rowsort
SHOW INDEXES FROM o
----
table_name  index_name  non_unique  seq_in_index  column_name  definition  direction  storing  implicit  visible  visibility
o           o_pkey      false       1             rowid        rowid       ASC        false    false     true     1
o           o_pkey      false       2             gf           gf          N/A        true     false     true     1
o           o_pkey      false       3             i            i           N/A        true     false     true     1
o           oi          true        1             i            i           ASC        false    false     true     1
o           oi          true        2             rowid        rowid       ASC        false    true      true     1

statement ok
ALTER TABLE t ADD f INT CHECK (f > 1)

statement ok
ALTER TABLE t ADD g INT DEFAULT 1 CHECK (g > 0)

statement ok
ALTER TABLE t ADD h INT CHECK (h > 0) CHECK (h < 10) UNIQUE

statement error pq: validation of CHECK "i < 0:::INT8" failed on row:.* i=1
ALTER TABLE t ADD i INT DEFAULT 1 CHECK (i < 0)

statement error pq: validation of CHECK "i < g" failed on row:.* g=1.* i=1
ALTER TABLE t ADD i INT DEFAULT 1 CHECK (i < g)

statement error pq: validation of CHECK "i > 0:::INT8" failed on row:.* g=1.* i=0
ALTER TABLE t ADD i INT AS (g - 1) STORED CHECK (i > 0)

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_f   CHECK        CHECK ((f > 1))      true
t  check_g   CHECK        CHECK ((g > 0))      true
t  check_h   CHECK        CHECK ((h > 0))      true
t  check_h1  CHECK        CHECK ((h < 10))     true
t  t_h_key   UNIQUE       UNIQUE (h ASC)       true
t  t_pkey    PRIMARY KEY  PRIMARY KEY (a ASC)  true

statement ok
DROP TABLE t

# Test that more than one column with constraints can be added in the same
# statement. The constraints added here are on columns that are new and both
# columns and constraints run through the schema change process together.

statement ok
CREATE TABLE t (a INT PRIMARY KEY)

statement ok
INSERT INTO t VALUES (1)

# Check references column added in same statement
statement ok
ALTER TABLE t ADD b INT DEFAULT 1, ADD c INT DEFAULT 2 CHECK (c > b)

statement ok
ALTER TABLE t ADD d INT UNIQUE, ADD e INT UNIQUE, ADD f INT

# Check references column added in same statement
statement error pq: validation of CHECK "g = h" failed on row:.* g=3.* h=2
ALTER TABLE t ADD g INT DEFAULT 3, ADD h INT DEFAULT 2 CHECK (g = h)

# Multiple unique columns can be added, followed by other commands (#35011)
statement ok
ALTER TABLE t ADD COLUMN u INT UNIQUE, ADD COLUMN v INT UNIQUE, ADD CONSTRAINT ck CHECK (a > 0);

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_c_b  CHECK        CHECK ((c > b))      true
t  ck         CHECK        CHECK ((a > 0))      true
t  t_d_key    UNIQUE       UNIQUE (d ASC)       true
t  t_e_key    UNIQUE       UNIQUE (e ASC)       true
t  t_pkey     PRIMARY KEY  PRIMARY KEY (a ASC)  true
t  t_u_key    UNIQUE       UNIQUE (u ASC)       true
t  t_v_key    UNIQUE       UNIQUE (v ASC)       true

statement ok
DROP TABLE t

# Subsequent operations succeed because the table is empty
statement ok
CREATE TABLE tt (a INT PRIMARY KEY)

statement ok
ALTER TABLE tt ADD COLUMN q DECIMAL NOT NULL

statement ok
ALTER table tt ADD COLUMN r DECIMAL

# Ensure that a UNIQUE NOT NULL COLUMN can be added when there is no data in
# the table.
statement ok
ALTER TABLE tt ADD COLUMN s DECIMAL UNIQUE NOT NULL

statement ok
ALTER TABLE tt ADD t DECIMAL UNIQUE DEFAULT 4.0

query TTBTTTB colnames,rowsort
SHOW COLUMNS FROM tt
----
column_name  data_type  is_nullable  column_default  generation_expression  indices                      is_hidden
a            INT8       false        NULL            ·                      {tt_pkey,tt_s_key,tt_t_key}  false
q            DECIMAL    false        NULL            ·                      {tt_pkey}                    false
r            DECIMAL    true         NULL            ·                      {tt_pkey}                    false
s            DECIMAL    false        NULL            ·                      {tt_pkey,tt_s_key}           false
t            DECIMAL    true         4.0             ·                      {tt_pkey,tt_t_key}           false

# Default values can be added and changed after table creation.
statement ok
CREATE TABLE add_default (a int primary key, b int not null)

statement error null value in column "b" violates not-null constraint
INSERT INTO add_default (a) VALUES (1)

statement ok
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT 42

query TTBTTTB colnames,rowsort
SHOW COLUMNS FROM add_default
----
column_name  data_type  is_nullable  column_default  generation_expression  indices             is_hidden
a            INT8       false        NULL            ·                      {add_default_pkey}  false
b            INT8       false        42              ·                      {add_default_pkey}  false

statement ok
INSERT INTO add_default (a) VALUES (2)

statement ok
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT 10

statement error pgcode 42804 expected DEFAULT \(in SET DEFAULT\) expression to have type int, but ''i'::STRING' has type string
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT 'i'::string

statement ok
INSERT INTO add_default (a) VALUES (3)

statement error could not parse "foo" as type int
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT 'foo'

statement error variable sub-expressions are not allowed in DEFAULT
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT c

statement error variable sub-expressions are not allowed in DEFAULT
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT (SELECT 1)

statement ok
ALTER TABLE add_default ALTER COLUMN b DROP DEFAULT

statement error null value in column "b" violates not-null constraint
INSERT INTO add_default (a) VALUES (4)

statement ok
ALTER TABLE add_default ALTER COLUMN b SET DEFAULT NULL

statement error null value in column "b" violates not-null constraint
INSERT INTO add_default (a) VALUES (4)

# Each row gets the default value from the time it was inserted.
query II rowsort
SELECT * FROM add_default
----
2 42
3 10

statement ok
ALTER TABLE add_default ALTER b DROP NOT NULL

statement ok
INSERT INTO add_default (a) VALUES (5)

query II
SELECT * from add_default WHERE a=5
----
5 NULL

# Add a column with a default current_timestamp()
statement ok
ALTER TABLE add_default ADD COLUMN c TIMESTAMP DEFAULT current_timestamp()

query II rowsort
SELECT a,b FROM add_default WHERE current_timestamp > c AND current_timestamp() - c < interval '20s'
----
2 42
3 10
5 NULL

# Add a column with a default transaction_timestamp()
statement ok
ALTER TABLE add_default ADD COLUMN d TIMESTAMP DEFAULT transaction_timestamp()

query II rowsort
SELECT a,b FROM add_default WHERE d > c AND d - c < interval '20s'
----
2 42
3 10
5 NULL

# Add a column with a default statement_timestamp()
statement ok
ALTER TABLE add_default ADD COLUMN e TIMESTAMP DEFAULT statement_timestamp()

query II rowsort
SELECT a,b FROM add_default WHERE e > d AND e - d < interval '20s'
----
2 42
3 10
5 NULL

# Add a column with a null-default statement_timestamp()
statement ok
ALTER TABLE add_default ADD COLUMN f TIMESTAMP DEFAULT NULL

query IIS rowsort
SELECT a,b,f FROM add_default
----
2 42   NULL
3 10   NULL
5 NULL NULL

# Adding a unique column to an existing table with data with a default value
# is illegal
statement error pgcode 23505 violates unique constraint \"add_default_g_key\"
ALTER TABLE add_default ADD g INT UNIQUE DEFAULT 1

# various default evaluation errors

statement ok
CREATE SEQUENCE initial_seq

statement error pgcode 0A000 cannot evaluate scalar expressions containing sequence operations in this context
ALTER TABLE add_default ADD g INT DEFAULT nextval('initial_seq')

statement error pgcode 22C01 cannot evaluate scalar expressions using table lookups in this context
ALTER TABLE add_default ADD g OID DEFAULT 'foo'::regclass::oid

statement error pgcode 22C01 cannot evaluate scalar expressions using table lookups in this context
ALTER TABLE add_default ADD g INT DEFAULT 'foo'::regtype::INT

subtest 26422

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

statement ok
ALTER TABLE add_default ADD fee FLOAT NOT NULL DEFAULT 2.99

statement ok
ALTER TABLE add_default ALTER COLUMN fee DROP DEFAULT

statement error pgcode XXA00 null value in column "fee" violates not-null constraint
COMMIT

statement ok
BEGIN

statement ok
ALTER TABLE add_default ALTER COLUMN a SET DEFAULT 2

statement ok
ALTER TABLE add_default ALTER COLUMN a DROP DEFAULT

statement ok
COMMIT

query TTBTTTB colnames,rowsort
SHOW COLUMNS FROM add_default
----
column_name  data_type  is_nullable  column_default           generation_expression  indices             is_hidden
a            INT8       false        NULL                     ·                      {add_default_pkey}  false
b            INT8       true         NULL                     ·                      {add_default_pkey}  false
c            TIMESTAMP  true         current_timestamp()      ·                      {add_default_pkey}  false
d            TIMESTAMP  true         transaction_timestamp()  ·                      {add_default_pkey}  false
e            TIMESTAMP  true         statement_timestamp()    ·                      {add_default_pkey}  false
f            TIMESTAMP  true         NULL                     ·                      {add_default_pkey}  false

query T rowsort
SELECT feature_name FROM crdb_internal.feature_usage WHERE feature_name = 'sql.schema.change_in_explicit_txn'
----
sql.schema.change_in_explicit_txn

statement error pgcode 42703 column "fee" does not exist
ALTER TABLE add_default DROP fee

# Multiple columns can be added at once with heterogeneous DEFAULT usage
statement ok
CREATE TABLE d (a INT PRIMARY KEY)

statement ok
INSERT INTO d VALUES (1), (2)

statement ok
ALTER TABLE d ADD COLUMN c INT, ADD COLUMN b INT DEFAULT 7

statement ok
INSERT INTO d (a, c) VALUES (3, 4)

query III rowsort
SELECT * FROM d
----
1 NULL 7
2 NULL 7
3 4    7

# Test privileges.

statement ok
CREATE TABLE privs (a INT PRIMARY KEY, b INT)

statement ok
INSERT INTO privs VALUES (1)

user testuser

query T
SHOW DATABASE
----
test

statement error pq: must be owner of table privs or have CREATE privilege on table privs
ALTER TABLE privs ADD c INT

statement error pq: must be owner of table privs or have CREATE privilege on table privs
ALTER TABLE privs ADD CONSTRAINT foo UNIQUE (b)

user root

query TTBTTTB colnames,rowsort
SHOW COLUMNS FROM privs
----
column_name  data_type  is_nullable  column_default  generation_expression  indices       is_hidden
a            INT8       false        NULL            ·                      {privs_pkey}  false
b            INT8       true         NULL            ·                      {privs_pkey}  false

statement ok
GRANT CREATE ON privs TO testuser

user testuser

statement ok
ALTER TABLE privs ADD c INT

statement ok
ALTER TABLE privs ADD CONSTRAINT foo UNIQUE (b)

query TTBTTTB colnames,rowsort
SHOW COLUMNS FROM privs
----
column_name  data_type  is_nullable  column_default  generation_expression  indices           is_hidden
a            INT8       false        NULL            ·                      {foo,privs_pkey}  false
b            INT8       true         NULL            ·                      {foo,privs_pkey}  false
c            INT8       true         NULL            ·                      {privs_pkey}      false

statement error pgcode 42P01 relation "nonexistent" does not exist
ALTER TABLE nonexistent SPLIT AT VALUES (42)

statement error pgcode 42P01 relation "nonexistent" does not exist
ALTER INDEX nonexistent@noindex SPLIT AT VALUES (42)

statement error pgcode 42P01 relation "nonexistent" does not exist
ALTER TABLE nonexistent UNSPLIT AT VALUES (42)

statement error pgcode 42P01 relation "nonexistent" does not exist
ALTER INDEX nonexistent@noindex UNSPLIT AT VALUES (42)

statement error pgcode 42P01 relation "nonexistent" does not exist
ALTER TABLE nonexistent UNSPLIT ALL

statement error pgcode 42P01 relation "nonexistent" does not exist
ALTER INDEX nonexistent@noindex UNSPLIT ALL

user root

statement ok
CREATE VIEW privsview AS SELECT a,b,c FROM privs

statement error pgcode 42809 "privsview" is not a table
ALTER TABLE privsview ADD d INT

statement error pgcode 42809 "privsview" is not a table or materialized view
ALTER TABLE privsview SPLIT AT VALUES (42)

statement error pgcode 42809 "privsview" is not a table or materialized view
ALTER TABLE privsview UNSPLIT AT VALUES (42)

statement error pgcode 42809 "privsview" is not a table or materialized view
ALTER TABLE privsview UNSPLIT ALL

# Verify that impure defaults are evaluated separately on each row
# (#14352)
statement ok
CREATE TABLE impure (x INT); INSERT INTO impure(x) VALUES (1), (2), (3);

statement ok
ALTER TABLE impure ADD COLUMN a INT DEFAULT unique_rowid();

query I
SELECT count(distinct a) FROM impure
----
3

# No orphaned schema change jobs.
query I
SELECT count(*) FROM crdb_internal.jobs
WHERE job_type = 'SCHEMA CHANGE' AND status = 'pending' OR status = 'started'
----
0

# Verify that ALTER TABLE statements are rolled back properly when a DEFAULT expression returns
# an error.

statement ok
CREATE TABLE default_err_test (foo text)

statement ok
INSERT INTO default_err_test VALUES ('foo'), ('bar'), ('baz')

statement error pgcode foo some_msg
ALTER TABLE default_err_test ADD COLUMN id int DEFAULT crdb_internal.force_error('foo', 'some_msg')

query T
SELECT * from default_err_test ORDER BY foo
----
bar
baz
foo

# Create a table with a computed column that we'll de-compute
statement ok
CREATE TABLE decomputed_column (a INT PRIMARY KEY, b INT AS ( a + 1 ) STORED, FAMILY "primary" (a, b))

statement ok
INSERT INTO decomputed_column VALUES (1), (2)

statement error cannot write directly to computed column
INSERT INTO decomputed_column VALUES (3, NULL), (4, 99)

statement ok
ALTER TABLE decomputed_column ALTER COLUMN b DROP STORED

statement error pq: column "a" is not a computed column
ALTER TABLE decomputed_column ALTER COLUMN a DROP STORED

statement error pq: column "b" is not a computed column
ALTER TABLE decomputed_column ALTER COLUMN b DROP STORED

# Verify that the computation is dropped and that we can mutate the column
statement ok
INSERT INTO decomputed_column VALUES (3, NULL), (4, 99)

query II
select a, b from decomputed_column order by a
----
1 2
2 3
3 NULL
4 99

query TT
show create table decomputed_column
----
decomputed_column  CREATE TABLE public.decomputed_column (
                     a INT8 NOT NULL,
                     b INT8 NULL,
                     CONSTRAINT decomputed_column_pkey PRIMARY KEY (a ASC)
                   )

# Test for https://github.com/cockroachdb/cockroach/issues/26483
# We try to create a unique column on an un-indexable type.
statement ok
CREATE TABLE b26483()

# Verify that auditing can be enabled by root, and cannot be disabled by non-root.

statement ok
CREATE TABLE audit(x INT); ALTER TABLE audit EXPERIMENTAL_AUDIT SET READ WRITE;

query T
SELECT feature_name FROM crdb_internal.feature_usage WHERE feature_name = 'sql.schema.set_audit_mode.read_write'
----
sql.schema.set_audit_mode.read_write

# The user must be able to issue ALTER for this test to be meaningful.
statement ok
GRANT CREATE ON audit TO testuser

user testuser

# Check the user can indeed change the table
statement ok
ALTER TABLE audit ADD COLUMN y INT

# But not the audit settings.
statement error pq: only users with admin or MODIFYCLUSTERSETTING system privilege are allowed to change audit settings on a table
ALTER TABLE audit EXPERIMENTAL_AUDIT SET OFF

user root

statement ok
ALTER TABLE audit EXPERIMENTAL_AUDIT SET OFF

query T
SELECT feature_name FROM crdb_internal.feature_usage WHERE feature_name = 'sql.schema.set_audit_mode.off'
----
sql.schema.set_audit_mode.off

# Check column backfill in the presence of fks
subtest 27402

statement ok
CREATE TABLE users (
    id INT NOT NULL,
    city STRING NOT NULL,
    name STRING NULL,
    CONSTRAINT "primary" PRIMARY KEY (city ASC, id ASC)
)

statement ok
CREATE TABLE vehicles (
    id INT NOT NULL,
    city STRING NOT NULL,
    type STRING NULL,
    owner_id INT NULL,
    mycol STRING NULL,
    CONSTRAINT "primary" PRIMARY KEY (city ASC, id ASC),
    INDEX vehicles_auto_index_fk_city_ref_users (city ASC, owner_id ASC)
)

statement ok
CREATE TABLE rides (
    id INT NOT NULL,
    city STRING NOT NULL,
    vehicle_city STRING NULL,
    rider_id INT NULL,
    vehicle_id INT NULL,
    CONSTRAINT "primary" PRIMARY KEY (city ASC, id ASC),
    INDEX rides_auto_index_fk_city_ref_users (city ASC, rider_id ASC),
    INDEX rides_auto_index_fk_vehicle_city_ref_vehicles (vehicle_city ASC, vehicle_id ASC),
    CONSTRAINT check_vehicle_city_city CHECK (vehicle_city = city)
)

statement ok
ALTER TABLE vehicles ADD CONSTRAINT fk_city_ref_users FOREIGN KEY (city, owner_id) REFERENCES users (city, id)

statement ok
ALTER TABLE rides ADD CONSTRAINT fk_city_ref_users FOREIGN KEY (city, rider_id) REFERENCES users (city, id)

statement ok
ALTER TABLE rides ADD CONSTRAINT fk_vehicle_city_ref_vehicles FOREIGN KEY (vehicle_city, vehicle_id) REFERENCES vehicles (city, id)


statement ok
INSERT INTO users VALUES (10, 'lagos', 'chimamanda')

statement ok
INSERT INTO vehicles VALUES (100, 'lagos', 'toyota', 10, 'mycol')

statement ok
INSERT INTO rides VALUES (567, 'lagos', 'lagos', 10, 100)

statement ok
ALTER TABLE vehicles DROP COLUMN mycol;

# check that adding a reference on a column still being backfilled fails.
# fix through #32917

statement ok
CREATE TABLE t32917 (a INT PRIMARY KEY)

statement ok
INSERT INTO t32917 VALUES (1), (2), (3)

statement ok
CREATE TABLE t32917_2 (b INT PRIMARY KEY)

statement ok
INSERT INTO t32917_2 VALUES (1), (2), (3)

# Test SET NOT NULL
statement ok
CREATE TABLE t (a INT)

statement ok
INSERT INTO t VALUES (1), (NULL)

statement error (.*validation of CHECK "a IS NOT NULL" failed on row: a=NULL, rowid=\d+|pq: validation of column "a" NOT NULL failed on row: a=NULL, rowid=\d+)
ALTER TABLE t ALTER COLUMN a SET NOT NULL

statement ok
DELETE FROM t WHERE a IS NULL

statement ok
ALTER TABLE t ALTER COLUMN a SET NOT NULL

statement error null value in column "a" violates not-null constraint
INSERT INTO t VALUES (NULL)

query TTTTB
SHOW CONSTRAINTS FROM t
----
t  t_pkey  PRIMARY KEY  PRIMARY KEY (rowid ASC)  true

statement ok
ALTER TABLE t ALTER COLUMN a DROP NOT NULL

statement ok
INSERT INTO t VALUES (NULL)

statement ok
DROP TABLE t

# Test interaction of SET NOT NULL with other constraints
statement ok
CREATE TABLE t (a INT)

statement ok
INSERT INTO t VALUES (1)

# Check for name collisions with the auto-generated NOT NULL check constraint name
statement ok
ALTER TABLE t ADD CONSTRAINT a_auto_not_null CHECK (a IS NOT NULL)

statement ok
ALTER TABLE t ADD CONSTRAINT a_auto_not_null1 CHECK (a IS NOT NULL), ALTER COLUMN a SET NOT NULL

statement error null value in column "a" violates not-null constraint
INSERT INTO t VALUES (NULL)

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  a_auto_not_null   CHECK        CHECK ((a IS NOT NULL))  true
t  a_auto_not_null1  CHECK        CHECK ((a IS NOT NULL))  true
t  t_pkey            PRIMARY KEY  PRIMARY KEY (rowid ASC)  true

statement ok
DROP TABLE t

# Check for adding constraints NOT VALID
statement ok
CREATE TABLE t (a int);

statement ok
INSERT INTO t VALUES (10), (15), (17)

statement error pq: validation of CHECK "a < 16:::INT8" failed on row: a=17
ALTER TABLE t ADD CHECK (a < 16)

statement ok
ALTER TABLE t ADD CHECK (a < 100)

statement ok
ALTER TABLE t ADD CHECK (a < 16) NOT VALID

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_a   CHECK        CHECK ((a < 100))           true
t  check_a1  CHECK        CHECK ((a < 16)) NOT VALID  false
t  t_pkey    PRIMARY KEY  PRIMARY KEY (rowid ASC)     true

query error pq: failed to satisfy CHECK constraint \(a < 16:::INT8\)
INSERT INTO t VALUES (20)

statement error pq: validation of CHECK "a < 16:::INT8" failed on row: a=17
ALTER TABLE t VALIDATE CONSTRAINT check_a1

statement ok
DELETE FROM t WHERE a = 17

statement ok
ALTER TABLE t VALIDATE CONSTRAINT check_a1

query TTTTB nosort
SHOW CONSTRAINTS FROM t
----
t  check_a   CHECK        CHECK ((a < 100))        true
t  check_a1  CHECK        CHECK ((a < 16))         true
t  t_pkey    PRIMARY KEY  PRIMARY KEY (rowid ASC)  true

subtest regression_42858

statement ok
CREATE TABLE TEST2 (COL1 SERIAL PRIMARY KEY, COL2 INT8)

statement ok
CREATE TABLE TEST1 (COL1 SERIAL PRIMARY KEY, COL2 INT8, COL3 INT8)

statement ok
ALTER TABLE TEST1 ADD CONSTRAINT duplicate_name FOREIGN KEY (COL2) REFERENCES TEST2 (COL1)

statement error pq: duplicate constraint name: "duplicate_name"
ALTER TABLE TEST1 ADD CONSTRAINT duplicate_name FOREIGN KEY (COL3) REFERENCES TEST2 (COL1)

statement ok
DROP TABLE test1; DROP TABLE test2

subtest multiple_set_drop_not_null_inside_txn

statement ok
CREATE TABLE t1(x INT, y INT);

statement ok
BEGIN;
ALTER TABLE t1 ALTER COLUMN x SET NOT NULL;
ALTER TABLE t1 ALTER COLUMN y SET NOT NULL;
COMMIT

statement ok
BEGIN;
ALTER TABLE t1 ALTER COLUMN x DROP NOT NULL;
ALTER TABLE t1 ALTER COLUMN y DROP NOT NULL;
COMMIT

statement ok
DROP TABLE t1

subtest regression_43092

statement ok
CREATE TABLE t43092(x INT PRIMARY KEY)

statement error pgcode 42P16 column "x" is in a primary index
ALTER TABLE t43092 ALTER COLUMN x DROP NOT NULL

statement ok
DROP TABLE t43092

subtest regression_qualification_feature_counts

statement ok
CREATE TABLE telemetry_test (d int);
ALTER TABLE telemetry_test
  ADD COLUMN a int DEFAULT 1,
  ADD COLUMN b int UNIQUE CHECK(b > 1),
  ADD COLUMN c int AS (a + b) STORED

query T rowsort
SELECT feature_name FROM crdb_internal.feature_usage
WHERE feature_name IN (
  'sql.schema.new_column.qualification.computed',
  'sql.schema.new_column.qualification.default_expr',
  'sql.schema.new_column.qualification.unique'
)
----
sql.schema.new_column.qualification.unique
sql.schema.new_column.qualification.computed
sql.schema.new_column.qualification.default_expr

statement ok
DROP TABLE telemetry_test

# Disable stats injection in explicit transactions.
statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

statement ok
CREATE TABLE inject_stats (k CHAR PRIMARY KEY, v TIMESTAMPTZ)

statement error pq: cannot inject statistics in an explicit transaction
ALTER TABLE inject_stats INJECT STATISTICS '[]'

statement ok
ROLLBACK

subtest regression_47141

statement ok
CREATE TABLE regression_47141(a time(3), b bytea)

# Regression for #26045.
statement ok
CREATE TABLE t25045 (x INT, y INT AS (x+1) STORED)

statement error pq: column \"x\" is referenced by computed column \"y\"
ALTER TABLE t25045 DROP COLUMN x

subtest add_col_references

statement ok
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 (x INT PRIMARY KEY);
CREATE TABLE t2 (y INT)

statement ok
ALTER TABLE t2 ADD COLUMN x INT REFERENCES t1 (x)

statement ok
INSERT INTO t1 VALUES (1)

statement error pq: insert on table "t2" violates foreign key constraint "t2_x_fkey"
INSERT INTO t2 VALUES (2, 2)

statement ok
INSERT INTO t2 VALUES (1, 1)

# Check that the foreign key was indeed added.
query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL,
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x)
    )

# Test that only one index gets created when adding a column
# with references and unique.
statement ok
CREATE TABLE t3 (y INT)

statement ok
ALTER TABLE t3 ADD COLUMN x INT UNIQUE REFERENCES t1 (x)

query TT
SHOW CREATE t3
----
t3  CREATE TABLE public.t3 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL,
      CONSTRAINT t3_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t3_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x),
      UNIQUE INDEX t3_x_key (x ASC)
    )

# We allowed the foreign key validation code to look into the mutations
# list to validate what columns / indexes can be used for foreign keys.
# Ensure that we still have the correct restrictions.
statement ok
DROP TABLE t1, t2 CASCADE;

statement ok
CREATE TABLE t1 (x INT PRIMARY KEY);
CREATE TABLE t2 (x INT, y INT, INDEX i (x))

statement error pq: column \"x\" does not exist
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE t2 DROP COLUMN x;
ALTER TABLE t2 ADD FOREIGN KEY (x) REFERENCES t1(x);

statement ok
ROLLBACK

statement ok
INSERT INTO t2 VALUES (1, 2)

# Test using ADD COL REFERENCES in a self referencing constraint.
statement ok
DROP TABLE t1 CASCADE;

statement ok
CREATE TABLE t1 (x INT PRIMARY KEY);

statement ok
ALTER TABLE t1 ADD COLUMN x2 INT REFERENCES t1 (x)

query TT
SHOW CREATE t1
----
t1  CREATE TABLE public.t1 (
      x INT8 NOT NULL,
      x2 INT8 NULL,
      CONSTRAINT t1_pkey PRIMARY KEY (x ASC),
      CONSTRAINT t1_x2_fkey FOREIGN KEY (x2) REFERENCES public.t1(x)
    )

statement error pq: insert on table "t1" violates foreign key constraint "t1_x2_fkey"
INSERT INTO t1 VALUES (1, 2)

# Test ADD COL REFERENCES on a new table in the same txn.
statement ok
DROP TABLE t1, t2 CASCADE

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE t1 (x INT PRIMARY KEY);
CREATE TABLE t2 (y INT);
ALTER TABLE t2 ADD COLUMN x INT REFERENCES t1 (x);
COMMIT

query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL,
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x) NOT VALID
    )

# Test that we can also add a column and then an FK in the same txn.
statement ok
DROP TABLE t1, t2 CASCADE

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE t1 (x INT PRIMARY KEY);
CREATE TABLE t2 (y INT);
ALTER TABLE t2 ADD COLUMN x INT;
ALTER TABLE t2 ADD FOREIGN KEY (x) REFERENCES t1 (x);
COMMIT

query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL,
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x) NOT VALID
    )

# Test that we can add a column and an index to an FK in the same txn.
statement ok
DROP TABLE t1, t2 CASCADE

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE t1 (x INT PRIMARY KEY);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (y INT);
INSERT INTO t2 VALUES (2);
ALTER TABLE t2 ADD COLUMN x INT;
CREATE INDEX ON t2 (x);
ALTER TABLE t2 ADD FOREIGN KEY (x) REFERENCES t1 (x);
COMMIT

query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL,
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x) NOT VALID,
      INDEX t2_x_idx (x ASC)
    )

# Test the above on a table not created in the same txn.
statement ok
DROP TABLE t1, t2 CASCADE;

statement ok
CREATE TABLE t1 (x INT PRIMARY KEY);
CREATE TABLE t2 (y INT)

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE t2 ADD COLUMN x INT;
CREATE INDEX ON t2 (x);
ALTER TABLE t2 ADD FOREIGN KEY (x) REFERENCES t1 (x);
COMMIT

query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL,
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x),
      INDEX t2_x_idx (x ASC)
    )

# Test that an FK can use a newly created index.
statement ok
DROP TABLE t1, t2 CASCADE;

statement ok
CREATE TABLE t1 (x INT PRIMARY KEY);
CREATE TABLE t2 (x INT)

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE INDEX ON t2 (x);
ALTER TABLE t2 ADD FOREIGN KEY (x) REFERENCES t1 (x);
COMMIT

query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      x INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x),
      INDEX t2_x_idx (x ASC)
    )

# Test when default column value leads to an FK violation.
statement ok
DROP TABLE t1, t2 CASCADE

statement ok
CREATE TABLE t1 (x INT PRIMARY KEY);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (y INT);
INSERT INTO t2 VALUES (2)

statement error pq: foreign key violation
ALTER TABLE t2 ADD COLUMN x INT DEFAULT 2 UNIQUE REFERENCES t1 (x)

# Test that it works with an appropriate default.
statement ok
ALTER TABLE t2 ADD COLUMN x INT DEFAULT 1 UNIQUE REFERENCES t1 (x)

query TT
SHOW CREATE t2
----
t2  CREATE TABLE public.t2 (
      y INT8 NULL,
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      x INT8 NULL DEFAULT 1:::INT8,
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      CONSTRAINT t2_x_fkey FOREIGN KEY (x) REFERENCES public.t1(x),
      UNIQUE INDEX t2_x_key (x ASC)
    )

# Regression 50069, computed exprs must only refer to columns inside the
# current table.
statement ok
CREATE TABLE t50069_a (x INT);
CREATE TABLE t50069_b (x INT);

statement error pq: no data source matches prefix: t50069_b in this context
ALTER TABLE t50069_a ADD COLUMN y INT AS (t50069_b.x + 1) STORED

statement ok
CREATE DATABASE d;
CREATE TABLE d.public.t50069_a (x INT);

statement error pq: no data source matches prefix: d.public.t50069_a in this context
ALTER TABLE t50069_a ADD COLUMN y INT AS (d.public.t50069_a.x + 1) STORED

# Dropping a column with a foreign key should delete the column and the FK.
statement ok
DROP TABLE IF EXISTS parent, child;
CREATE TABLE parent (p INT PRIMARY KEY);
CREATE TABLE child (c INT PRIMARY KEY, p INT REFERENCES parent(p), FAMILY (c, p));
ALTER TABLE child DROP COLUMN p

query TT
SHOW CREATE child
----
child  CREATE TABLE public.child (
         c INT8 NOT NULL,
         CONSTRAINT child_pkey PRIMARY KEY (c ASC),
         FAMILY fam_0_c_p (c)
       )

# Regression test for #52816.
statement ok
CREATE TABLE t52816 (x INT, y INT);
ALTER TABLE t52816 RENAME COLUMN x TO x2, RENAME COLUMN y TO y;
SELECT x2, y FROM t52816

# Regression test for #54196.
statement ok
CREATE TABLE IF NOT EXISTS regression_54196 (
	col1 int,
	col2 int,
	col3 int,
	INDEX (col1, col2),
	INDEX (col1, col3),
	INDEX (col2, col3)
); ALTER TABLE regression_54196 DROP COLUMN col1

query TT
SELECT index_name, column_name FROM [SHOW INDEXES FROM regression_54196]
ORDER BY index_name, column_name ASC
----
regression_54196_col2_col3_idx  col2
regression_54196_col2_col3_idx  col3
regression_54196_col2_col3_idx  rowid
regression_54196_pkey           col2
regression_54196_pkey           col3
regression_54196_pkey           rowid

# Test to ensure that renaming a constraint on top of an existing index
# fails with the correct error.

statement ok
CREATE TABLE t_cannot_rename_constraint_over_index (
    k INT PRIMARY KEY,
    v INT,
    CONSTRAINT v_unique UNIQUE (v),
    INDEX idx_v (v)
);

statement error relation idx_v already exists
ALTER TABLE t_cannot_rename_constraint_over_index RENAME CONSTRAINT v_unique TO idx_v;

statement error relation idx_v already exists
ALTER TABLE t_cannot_rename_constraint_over_index RENAME CONSTRAINT "t_cannot_rename_constraint_over_index_pkey" TO idx_v;

subtest unique_without_index

statement error pq: unique constraints without an index are not yet supported
CREATE TABLE unique_without_index_error (
  a INT UNIQUE WITHOUT INDEX
)

statement ok
CREATE TABLE unique_without_index_error (
  a INT
)

statement error pq: unique constraints without an index are not yet supported
ALTER TABLE unique_without_index_error ADD CONSTRAINT a_key UNIQUE WITHOUT INDEX (a)

statement ok
SET experimental_enable_unique_without_index_constraints = true

statement ok
CREATE TABLE unique_without_index (
  a INT,
  b INT UNIQUE WITHOUT INDEX,
  c INT UNIQUE,
  d INT UNIQUE WITHOUT INDEX,
  e INT,
  UNIQUE WITHOUT INDEX (b),
  UNIQUE WITHOUT INDEX (a, b),
  UNIQUE WITHOUT INDEX (c),
  UNIQUE WITHOUT INDEX (d, e)
)

statement ok
CREATE TABLE uwi_child (
  d INT REFERENCES unique_without_index (d),
  e INT,
  CONSTRAINT fk_d_e FOREIGN KEY (d, e) REFERENCES unique_without_index (d, e),
  CONSTRAINT fk_e_d FOREIGN KEY (e, d) REFERENCES unique_without_index (e, d)
)

# We don't yet support adding a column marked as UNIQUE WITHOUT INDEX after a
# table is created. (The full error message includes a hint with a workaround.)
statement error pgcode 0A000 pq: adding a column marked as UNIQUE WITHOUT INDEX is unsupported
ALTER TABLE unique_without_index ADD COLUMN f INT UNIQUE WITHOUT INDEX

# To add a UNIQUE WITHOUT INDEX column, first add the column, then add the
# constraint.
statement ok
ALTER TABLE unique_without_index ADD COLUMN f INT;
ALTER TABLE unique_without_index ADD CONSTRAINT my_unique_f UNIQUE WITHOUT INDEX (f);
ALTER TABLE unique_without_index ADD CONSTRAINT my_partial_unique_f UNIQUE WITHOUT INDEX (f) WHERE f > 0

# The unique constraint predicate must be valid. It cannot reference
# non-existent columns.
# TODO(mgartner): If we ever decide to make UNIQUE WITHOUT INDEX available
# without the experimental setting, we should test that other types of invalid
# predicates produce errors. There are similar tests in the partial_index
# logictests that would be a good starting point.
statement error column "g" does not exist
ALTER TABLE unique_without_index ADD CONSTRAINT bad_partial_unique UNIQUE WITHOUT INDEX (f) WHERE g > 0

# The unique constraint prevents new duplicate values.
skipif config #110873 weak-iso-level-configs
statement error pgcode 23505 pq: duplicate key value violates unique constraint "my_unique_f"\nDETAIL: Key \(f\)=\(1\) already exists\.
INSERT INTO unique_without_index (f) VALUES (1), (1)

# There is no unique constraint on e, yet, so this insert succeeds.
skipif config #110873 weak-iso-level-configs
statement ok
INSERT INTO unique_without_index (e, f) VALUES (1, 1), (1, 2)

# But trying to add a unique constraint now fails.
# Note that we omit the constraint name in the expected error message because if the declarative schema changer is used,
# the constraint name, at the time of validation failure, is still a place-holder name.
skipif config #110873 weak-iso-level-configs
statement error pgcode 23505 pq: could not create unique constraint ".*"\nDETAIL: Key \(e\)=\(1\) is duplicated\.
ALTER TABLE unique_without_index ADD CONSTRAINT my_unique_e UNIQUE WITHOUT INDEX (e)

# We can create not-valid constraints, however.
statement ok
ALTER TABLE unique_without_index ADD CONSTRAINT my_unique_e UNIQUE WITHOUT INDEX (e) NOT VALID;
ALTER TABLE unique_without_index ADD CONSTRAINT my_unique_e2 UNIQUE WITHOUT INDEX (e) NOT VALID

# Trying to validate one of the constraints will fail.
skipif config #110873 weak-iso-level-configs
statement error pgcode 23505 pq: could not create unique constraint ".*"\nDETAIL: Key \(e\)=\(1\) is duplicated\.
ALTER TABLE unique_without_index VALIDATE CONSTRAINT my_unique_e

# But after we delete a row, validation should succeed.
statement ok
DELETE FROM unique_without_index WHERE e = 1 AND f = 1;

statement ok
ALTER TABLE unique_without_index VALIDATE CONSTRAINT my_unique_e

# All these constraints are already valid, so validation should succeed.
skipif config #110873 weak-iso-level-configs
statement ok
ALTER TABLE unique_without_index VALIDATE CONSTRAINT unique_b;
ALTER TABLE unique_without_index VALIDATE CONSTRAINT unique_a_b;
ALTER TABLE unique_without_index VALIDATE CONSTRAINT unique_without_index_c_key

statement ok
CREATE TABLE unique_without_index_partial (
  a INT,
  b INT,
  c INT
);
INSERT INTO unique_without_index_partial VALUES
  (1, 1, 1),
  (2, 2, 2),
  (1, 3, -3),
  (2, -2, -2),
  (NULL, 4, 4),
  (NULL, 5, 5);

let $constraint_violations_before
SELECT usage_count
  FROM crdb_internal.feature_usage
 WHERE feature_name = 'sql.schema_changer.errors.constraint_violation';

# Trying to add a partial unique constraint fails when there are duplicates.
statement error pgcode 23505 pq: could not create unique constraint ".*"\nDETAIL: Key \(a\)=\(1\) is duplicated\.
ALTER TABLE unique_without_index_partial ADD CONSTRAINT uniq_a_1 UNIQUE WITHOUT INDEX (a) WHERE b > 0 OR c > 0

# Sanity: Check the number of user errors and
# database errors in the test.
# We only do this check for the legacy schema changer because the declarative schema changer does not increment
# exactly the same counters.
onlyif config local-legacy-schema-changer
query B
SELECT usage_count > $constraint_violations_before
  FROM crdb_internal.feature_usage
 WHERE feature_name = 'sql.schema_changer.errors.constraint_violation';
----
true

query I
SELECT count(usage_count)
  FROM crdb_internal.feature_usage
 WHERE feature_name = 'sql.schema_changer.errors.uncategorized' and usage_count >= 1;
----
1

# We can create not-valid constraints, however.
statement ok
ALTER TABLE unique_without_index_partial ADD CONSTRAINT uniq_a_1 UNIQUE WITHOUT INDEX (a) WHERE b > 0 OR c > 0 NOT VALID

# Trying to validate the constraint will fail.
statement error pgcode 23505 pq: could not create unique constraint ".*"\nDETAIL: Key \(a\)=\(1\) is duplicated\.
ALTER TABLE unique_without_index_partial VALIDATE CONSTRAINT uniq_a_1

# But after we delete a row, validation should succeed.
statement ok
DELETE FROM unique_without_index_partial WHERE a = 1 AND b = 3 AND c = -3;

statement ok
ALTER TABLE unique_without_index_partial VALIDATE CONSTRAINT uniq_a_1;

# Creating a new validated constraint should also succeed.
statement ok
ALTER TABLE unique_without_index_partial ADD CONSTRAINT uniq_a_2 UNIQUE WITHOUT INDEX (a) WHERE b > 0 OR c > 0

query TTTTB colnames,nosort
SHOW CONSTRAINTS FROM unique_without_index
----
table_name            constraint_name             constraint_type  details                                 validated
unique_without_index  my_partial_unique_f         UNIQUE           UNIQUE WITHOUT INDEX (f) WHERE (f > 0)  true
unique_without_index  my_unique_e                 UNIQUE           UNIQUE WITHOUT INDEX (e)                true
unique_without_index  my_unique_e2                UNIQUE           UNIQUE WITHOUT INDEX (e) NOT VALID      false
unique_without_index  my_unique_f                 UNIQUE           UNIQUE WITHOUT INDEX (f)                true
unique_without_index  unique_a_b                  UNIQUE           UNIQUE WITHOUT INDEX (a, b)             true
unique_without_index  unique_b                    UNIQUE           UNIQUE WITHOUT INDEX (b)                true
unique_without_index  unique_b_1                  UNIQUE           UNIQUE WITHOUT INDEX (b)                true
unique_without_index  unique_c                    UNIQUE           UNIQUE WITHOUT INDEX (c)                true
unique_without_index  unique_d                    UNIQUE           UNIQUE WITHOUT INDEX (d)                true
unique_without_index  unique_d_e                  UNIQUE           UNIQUE WITHOUT INDEX (d, e)             true
unique_without_index  unique_without_index_c_key  UNIQUE           UNIQUE (c ASC)                          true
unique_without_index  unique_without_index_pkey   PRIMARY KEY      PRIMARY KEY (rowid ASC)                 true

statement ok
ALTER TABLE unique_without_index RENAME COLUMN a TO aa

statement error pgcode 42704 constraint \"unique_b_2\" of relation \"unique_without_index\" does not exist
ALTER TABLE unique_without_index RENAME CONSTRAINT unique_b_2 TO unique_b_3

statement error pgcode 42710 duplicate constraint name: \"unique_b_1\"
ALTER TABLE unique_without_index RENAME CONSTRAINT unique_b TO unique_b_1

statement ok
ALTER TABLE unique_without_index RENAME CONSTRAINT unique_b TO unique_b_2

query TTTTB nosort
SHOW CONSTRAINTS FROM unique_without_index
----
unique_without_index  my_partial_unique_f         UNIQUE       UNIQUE WITHOUT INDEX (f) WHERE (f > 0)  true
unique_without_index  my_unique_e                 UNIQUE       UNIQUE WITHOUT INDEX (e)                true
unique_without_index  my_unique_e2                UNIQUE       UNIQUE WITHOUT INDEX (e) NOT VALID      false
unique_without_index  my_unique_f                 UNIQUE       UNIQUE WITHOUT INDEX (f)                true
unique_without_index  unique_a_b                  UNIQUE       UNIQUE WITHOUT INDEX (aa, b)            true
unique_without_index  unique_b_1                  UNIQUE       UNIQUE WITHOUT INDEX (b)                true
unique_without_index  unique_b_2                  UNIQUE       UNIQUE WITHOUT INDEX (b)                true
unique_without_index  unique_c                    UNIQUE       UNIQUE WITHOUT INDEX (c)                true
unique_without_index  unique_d                    UNIQUE       UNIQUE WITHOUT INDEX (d)                true
unique_without_index  unique_d_e                  UNIQUE       UNIQUE WITHOUT INDEX (d, e)             true
unique_without_index  unique_without_index_c_key  UNIQUE       UNIQUE (c ASC)                          true
unique_without_index  unique_without_index_pkey   PRIMARY KEY  PRIMARY KEY (rowid ASC)                 true

statement error pgcode 0A000 cannot drop UNIQUE constraint \"unique_without_index_c_key\"
ALTER TABLE unique_without_index DROP CONSTRAINT unique_without_index_c_key

statement error pgcode 42704 constraint \"unique_b\" of relation \"unique_without_index\" does not exist
ALTER TABLE unique_without_index DROP CONSTRAINT unique_b

# Drop a valid constraint.
statement ok
ALTER TABLE unique_without_index DROP CONSTRAINT unique_b_2

# Drop a not-valid constraint.
statement ok
ALTER TABLE unique_without_index DROP CONSTRAINT my_unique_e2

query TTTTB nosort
SHOW CONSTRAINTS FROM unique_without_index
----
unique_without_index  my_partial_unique_f         UNIQUE       UNIQUE WITHOUT INDEX (f) WHERE (f > 0)  true
unique_without_index  my_unique_e                 UNIQUE       UNIQUE WITHOUT INDEX (e)                true
unique_without_index  my_unique_f                 UNIQUE       UNIQUE WITHOUT INDEX (f)                true
unique_without_index  unique_a_b                  UNIQUE       UNIQUE WITHOUT INDEX (aa, b)            true
unique_without_index  unique_b_1                  UNIQUE       UNIQUE WITHOUT INDEX (b)                true
unique_without_index  unique_c                    UNIQUE       UNIQUE WITHOUT INDEX (c)                true
unique_without_index  unique_d                    UNIQUE       UNIQUE WITHOUT INDEX (d)                true
unique_without_index  unique_d_e                  UNIQUE       UNIQUE WITHOUT INDEX (d, e)             true
unique_without_index  unique_without_index_c_key  UNIQUE       UNIQUE (c ASC)                          true
unique_without_index  unique_without_index_pkey   PRIMARY KEY  PRIMARY KEY (rowid ASC)                 true

# Dropping a column in a unique constraint drops the constraint.
statement ok
ALTER TABLE unique_without_index DROP COLUMN b

query TTTTB nosort
SHOW CONSTRAINTS FROM unique_without_index
----
unique_without_index  my_partial_unique_f         UNIQUE       UNIQUE WITHOUT INDEX (f) WHERE (f > 0)  true
unique_without_index  my_unique_e                 UNIQUE       UNIQUE WITHOUT INDEX (e)                true
unique_without_index  my_unique_f                 UNIQUE       UNIQUE WITHOUT INDEX (f)                true
unique_without_index  unique_c                    UNIQUE       UNIQUE WITHOUT INDEX (c)                true
unique_without_index  unique_d                    UNIQUE       UNIQUE WITHOUT INDEX (d)                true
unique_without_index  unique_d_e                  UNIQUE       UNIQUE WITHOUT INDEX (d, e)             true
unique_without_index  unique_without_index_c_key  UNIQUE       UNIQUE (c ASC)                          true
unique_without_index  unique_without_index_pkey   PRIMARY KEY  PRIMARY KEY (rowid ASC)                 true

query TTTTB nosort
SHOW CONSTRAINTS FROM uwi_child
----
uwi_child  fk_d_e            FOREIGN KEY  FOREIGN KEY (d, e) REFERENCES unique_without_index(d, e)  true
uwi_child  fk_e_d            FOREIGN KEY  FOREIGN KEY (e, d) REFERENCES unique_without_index(e, d)  true
uwi_child  uwi_child_d_fkey  FOREIGN KEY  FOREIGN KEY (d) REFERENCES unique_without_index(d)        true
uwi_child  uwi_child_pkey    PRIMARY KEY  PRIMARY KEY (rowid ASC)                                   true

# Attempting to drop a column with a foreign key reference fails.
statement error pq: "unique_d" is referenced by foreign key from table "uwi_child"
ALTER TABLE unique_without_index DROP COLUMN d

# It succeeds if we use CASCADE, and also drops the fk reference.
statement ok
ALTER TABLE unique_without_index DROP COLUMN d CASCADE

query TTTTB nosort
SHOW CONSTRAINTS FROM unique_without_index
----
unique_without_index  my_partial_unique_f         UNIQUE       UNIQUE WITHOUT INDEX (f) WHERE (f > 0)  true
unique_without_index  my_unique_e                 UNIQUE       UNIQUE WITHOUT INDEX (e)                true
unique_without_index  my_unique_f                 UNIQUE       UNIQUE WITHOUT INDEX (f)                true
unique_without_index  unique_c                    UNIQUE       UNIQUE WITHOUT INDEX (c)                true
unique_without_index  unique_without_index_c_key  UNIQUE       UNIQUE (c ASC)                          true
unique_without_index  unique_without_index_pkey   PRIMARY KEY  PRIMARY KEY (rowid ASC)                 true

query TTTTB
SHOW CONSTRAINTS FROM uwi_child
----
uwi_child  uwi_child_pkey  PRIMARY KEY  PRIMARY KEY (rowid ASC)  true

# Regression for #54629.
statement ok
CREATE TABLE t54629 (c INT NOT NULL, UNIQUE INDEX (c));
ALTER TABLE t54629 ADD CONSTRAINT pk PRIMARY KEY (c);
INSERT INTO t54629 VALUES (1);
DELETE FROM t54629 WHERE c = 1;

subtest regression_45985

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE t45985 (a INT);
ALTER TABLE t45985 ADD COLUMN b INT;
COMMIT;

query I
SELECT count(descriptor_id)
  FROM (
        SELECT json_array_elements_text(
                crdb_internal.pb_to_json('cockroach.sql.jobs.jobspb.Payload', value)->'descriptorIds'
               )::INT8 AS descriptor_id
          FROM system.job_info WHERE info_key = 'legacy_payload'
       )
 WHERE descriptor_id = ('test.public.t45985'::REGCLASS)::INT8;
----
0

# Validation for #47719 where a mutation is canceled out by a drop.
statement ok
CREATE TABLE t_col_drop (a INT);

statement error pgcode 0A000 constraint "a_auto_not_null" in the middle of being added, try again later
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE t_col_drop ALTER COLUMN a SET NOT NULL;
ALTER TABLE t_col_drop DROP COLUMN a;

statement ok
ROLLBACK

statement ok
DROP TABLE t_col_drop

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE t_col_drop (a INT);
ALTER TABLE t_col_drop ALTER COLUMN a SET NOT NULL;
ALTER TABLE t_col_drop DROP COLUMN a;
COMMIT

# Validate that the schema_change_successful metric
query T
SELECT feature_name FROM crdb_internal.feature_usage
WHERE feature_name IN ('job.schema_change.successful',
'job.schema_change.failed') AND
usage_count > 0
ORDER BY feature_name DESC
----
job.schema_change.successful
job.schema_change.failed

# Regression test for #61762. Do not allow adding OIDVECTOR or INT2VECTOR
# columns.
subtest regression_61762

statement ok
CREATE TABLE t61762 ()

statement error VECTOR column types are unsupported
ALTER TABLE t61762 ADD COLUMN v OIDVECTOR

statement error VECTOR column types are unsupported
ALTER TABLE t61762 ADD COLUMN v INT2VECTOR

statement error VECTOR column types are unsupported
ALTER TABLE t61762 ADD COLUMN v OIDVECTOR AS (ARRAY[1]) STORED

statement error VECTOR column types are unsupported
ALTER TABLE t61762 ADD COLUMN v OIDVECTOR AS (ARRAY[1]) VIRTUAL

statement error VECTOR column types are unsupported
ALTER TABLE t61762 ADD COLUMN v INT2VECTOR AS (ARRAY[1]) STORED

statement error VECTOR column types are unsupported
ALTER TABLE t61762 ADD COLUMN v INT2VECTOR AS (ARRAY[1]) VIRTUAL

# Regression test for #60786. Handle in-transaction constraint ADD+DROP correctly.
subtest regression_60786

statement ok
CREATE TABLE t60786(i INT PRIMARY KEY);

statement error pgcode 0A000 constraint "fk" in the middle of being added, try again later
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE child_60786(i INT PRIMARY KEY);
ALTER TABLE t60786 ADD CONSTRAINT fk FOREIGN KEY (i) REFERENCES child_60786(i) NOT VALID;
ALTER TABLE t60786 DROP CONSTRAINT fk CASCADE

statement ok
ROLLBACK

statement error pgcode 0A000 constraint "ck" in the middle of being added, try again later
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE t60786 ADD CONSTRAINT ck CHECK(i > 0) NOT VALID;
ALTER TABLE t60786 DROP CONSTRAINT ck CASCADE

statement ok
ROLLBACK

statement error pgcode 0A000 constraint "uq" in the middle of being added, try again later
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE t60786 ADD CONSTRAINT uq UNIQUE WITHOUT INDEX(i) NOT VALID;
ALTER TABLE t60786 DROP CONSTRAINT uq CASCADE

statement ok
ROLLBACK

# Visible values can be added and removed after table creation.
statement ok
CREATE TABLE visible_table (a int primary key)

statement ok
ALTER TABLE visible_table ALTER COLUMN a SET VISIBLE

statement error column "non_existent_column" does not exist
ALTER TABLE visible_table ALTER COLUMN non_existent_column SET VISIBLE

query TT
SHOW CREATE TABLE visible_table
----
visible_table  CREATE TABLE public.visible_table (
                 a INT8 NOT NULL,
                 CONSTRAINT visible_table_pkey PRIMARY KEY (a ASC)
               )

statement ok
ALTER TABLE visible_table ALTER COLUMN a SET NOT VISIBLE

query TT
SHOW CREATE TABLE visible_table
----
visible_table  CREATE TABLE public.visible_table (
                 a INT8 NOT VISIBLE NOT NULL,
                 CONSTRAINT visible_table_pkey PRIMARY KEY (a ASC)
               )

subtest if_table_exists_already

statement ok
CREATE TABLE new_table()

# Weak isolation levels emit extra notices, so skip them.
skipif config weak-iso-level-configs
query T noticetrace
CREATE TABLE IF NOT EXISTS new_table();
----
NOTICE: relation "new_table" already exists, skipping

subtest unique_index_duplicate_name

statement ok
CREATE TABLE duplicate_index_test (k INT PRIMARY KEY, v INT, INDEX idx (v));

statement error pgcode 42P07 .* name \"idx\" already exists
ALTER TABLE duplicate_index_test ADD CONSTRAINT idx UNIQUE (v)

# Regression test for a bug which occurred when adding a foreign key
# constraint which is marked NOT VALID and is self-referencing.
subtest self_reference_fk_not_valid

statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (i INT PRIMARY KEY, j INT);
ALTER TABLE t ADD CONSTRAINT fk FOREIGN KEY (j) REFERENCES t(i) NOT VALID;

# Demonstrate that the constraint is enforced.
statement error pgcode 23503 insert on table "t" violates foreign key constraint "fk"
INSERT INTO t VALUES (1, 0)

statement ok
DROP TABLE t;

# Ensure unique constraint partial predicates are not ignored.
subtest regression_67234

statement ok
CREATE TABLE t67234 (k INT PRIMARY KEY, a INT, b INT, FAMILY (k, a, b));

statement ok
ALTER TABLE t67234 ADD CONSTRAINT t67234_c1 UNIQUE (a) WHERE b > 0;

statement ok
ALTER TABLE t67234 ADD CONSTRAINT t67234_c2 UNIQUE WITHOUT INDEX (b) WHERE a > 0

query T
SELECT create_statement FROM [SHOW CREATE TABLE t67234]
----
CREATE TABLE public.t67234 (
  k INT8 NOT NULL,
  a INT8 NULL,
  b INT8 NULL,
  CONSTRAINT t67234_pkey PRIMARY KEY (k ASC),
  UNIQUE INDEX t67234_c1 (a ASC) WHERE b > 0:::INT8,
  FAMILY fam_0_k_a_b (k, a, b),
  CONSTRAINT t67234_c2 UNIQUE WITHOUT INDEX (b) WHERE a > 0:::INT8
)

subtest generated_as_identity
statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (a INT UNIQUE)

statement ok
ALTER TABLE t ADD COLUMN b INT GENERATED ALWAYS AS IDENTITY

statement error pq: cannot insert into column "b"\nDETAIL: Column "b" is an identity column defined as GENERATED ALWAYS
INSERT INTO t (b) VALUES (2)

statement ok
ALTER TABLE t ADD COLUMN c INT GENERATED BY DEFAULT AS IDENTITY

query TT
SHOW CREATE TABLE t
----
t  CREATE TABLE public.t (
     a INT8 NULL,
     rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
     b INT8 NOT NULL GENERATED ALWAYS AS IDENTITY,
     c INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY,
     CONSTRAINT t_pkey PRIMARY KEY (rowid ASC),
     UNIQUE INDEX t_a_key (a ASC)
   )

statement ok
INSERT INTO t (c) VALUES (2)

statement ok
DROP TABLE t

subtest generated_as_identity_with_seq_option
statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (a INT UNIQUE)

statement ok
ALTER TABLE t ADD COLUMN b INT GENERATED ALWAYS AS IDENTITY (START 1 INCREMENT 3)

statement ok
ALTER TABLE t ADD COLUMN c INT GENERATED ALWAYS AS IDENTITY (START 1 INCREMENT 3
 CACHE 10)

statement ok
ALTER TABLE t DROP COLUMN c

statement ok
INSERT INTO t (a) VALUES (7), (8), (9)

# Use this lag query because the sequence is non-transactional and we may have
# restarted.

query II
SELECT a, b - lag(b, 1) OVER (ORDER BY a) FROM t ORDER BY a;
----
7  NULL
8  3
9  3

statement error pq: cannot insert into column "b"\nDETAIL: Column "b" is an identity column defined as GENERATED ALWAYS
INSERT INTO t (a, b) VALUES (10, 2)

statement error column "b" is an identity column
ALTER TABLE t ALTER COLUMN b SET DEFAULT 10

statement error identity column type must be INT, INT2, INT4 or INT8
ALTER TABLE t ALTER COLUMN b TYPE numeric(10,2)

statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (a INT UNIQUE)

statement ok
ALTER TABLE t ADD COLUMN b INT GENERATED BY DEFAULT AS IDENTITY (START 1 INCREMENT 3)

statement ok
ALTER TABLE t ADD COLUMN c INT GENERATED BY DEFAULT AS IDENTITY (START 1 INCREMENT 3
 CACHE 10)

query TT
SHOW CREATE TABLE t
----
t  CREATE TABLE public.t (
     a INT8 NULL,
     rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
     b INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START 1 INCREMENT 3),
     c INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START 1 INCREMENT 3 CACHE 10),
     CONSTRAINT t_pkey PRIMARY KEY (rowid ASC),
     UNIQUE INDEX t_a_key (a ASC)
   )

statement ok
ALTER TABLE t DROP COLUMN c

statement ok
INSERT INTO t (a) VALUES (7), (8), (9)

query II
SELECT * FROM t ORDER BY a
----
7  1
8  4
9  7

statement ok
INSERT INTO t (a, b) VALUES (10, 2)

query II
SELECT * FROM t ORDER BY a
----
7   1
8   4
9   7
10  2

statement error column "b" is an identity column
ALTER TABLE t ALTER COLUMN b SET DEFAULT 10

statement error identity column type must be INT, INT2, INT4 or INT8
ALTER TABLE t ALTER COLUMN b TYPE numeric(10,2)

# Test we can assign a PRIMARY KEY overriding the existing rowid PRIMARY KEY.
statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (id INT NOT NULL)

statement ok
ALTER TABLE t ADD CONSTRAINT t_pkey PRIMARY KEY (id)

skipif config local-legacy-schema-changer
query TT
SHOW CREATE TABLE t
----
t  CREATE TABLE public.t (
     id INT8 NOT NULL,
     CONSTRAINT t_pkey PRIMARY KEY (id ASC)
   )

# Table has a PRIMARY KEY named index; check it errors when assinging PRIMARY KEY to id.
statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (
  id INT NOT NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t_pk PRIMARY KEY (rowid),
  CONSTRAINT t_pkey UNIQUE (id)
)

statement error constraint with name "t_pkey" already exists
ALTER TABLE t ADD CONSTRAINT t_pkey PRIMARY KEY (id)

# Tests other cases where rowid is not implicitly added.

statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE t (
  id INT NOT NULL,
  explicit_rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t_pk PRIMARY KEY (explicit_rowid)
)

statement error multiple primary keys for table "t" are not allowed
ALTER TABLE t ADD CONSTRAINT t_pkey PRIMARY KEY (id)

statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE public.t (
   id INT8 NOT NULL,
   rowid INT8 NOT VISIBLE NOT NULL,
   CONSTRAINT t_pkey PRIMARY KEY (id ASC)
)

statement error multiple primary keys for table "t" are not allowed
ALTER TABLE t ADD CONSTRAINT t_pkey PRIMARY KEY (id)

statement ok
DROP TABLE IF EXISTS t;

statement ok
CREATE TABLE public.t (
   id INT8 NOT NULL,
   rowid INT4 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
   CONSTRAINT t_pkey PRIMARY KEY (id ASC)
)

statement error multiple primary keys for table "t" are not allowed
ALTER TABLE t ADD CONSTRAINT t_pkey PRIMARY KEY (id)

# Fixes issues 74360, 73798 which occur because we were not looking up
# the column names for non-public column mutations and only using the
# mutation ID when creating the foreign key. As a result the wrong column
# could be referenced for a foreign key (or an error could occur if the types
# of the selected column doesn't match) referenced column did not match.
subtest add_column_with_constraint

statement ok
BEGIN

statement ok
CREATE TABLE colref (id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY);
CREATE TABLE colsource (id UUID NOT NULL DEFAULT gen_random_uuid() PRIMARY KEY);

statement ok
ALTER TABLE colsource ADD COLUMN description STRING NULL, ADD COLUMN customer_id UUID REFERENCES colref(id);

statement ok
ALTER TABLE colsource DROP COLUMN description, DROP COLUMN customer_id

statement ok
ALTER TABLE colsource ADD COLUMN customer_id UUID  REFERENCES colref(id), ADD COLUMN description STRING NULL;

statement ok
COMMIT

# Issue #75074 occurred when we added multiple columns inside a single transaction,
# where the backfill logic was completely skipped because the last added column
# did not require one. This test will add multiple columns and confirm that a
# backfill has occurred.
subtest add_multiple_in_txn

statement ok
CREATE TABLE IF NOT EXISTS multipleinstmt (
	key STRING PRIMARY KEY, value STRING
);

statement ok
INSERT INTO multipleinstmt (key, value) VALUES ('a', 'a');
INSERT INTO multipleinstmt (key, value) VALUES ('b', 'b');
INSERT INTO multipleinstmt (key, value) VALUES ('c', 'c');


statement ok
BEGIN;
ALTER TABLE multipleinstmt ADD COLUMN IF NOT EXISTS a BOOL DEFAULT false;
ALTER TABLE multipleinstmt ADD COLUMN IF NOT EXISTS b STRING;
COMMIT;

query TTBT
SELECT * FROM multipleinstmt ORDER BY key ASC;
----
a  a  false  NULL
b  b  false  NULL
c  c  false  NULL

statement ok
ALTER TABLE multipleinstmt ADD COLUMN IF NOT EXISTS c BOOL DEFAULT true,
                           ADD COLUMN IF NOT EXISTS d STRING;

query TTBTBT
SELECT * FROM multipleinstmt ORDER BY key ASC;
----
a  a  false  NULL  true  NULL
b  b  false  NULL  true  NULL
c  c  false  NULL  true  NULL

skip_on_retry

subtest column_backfiller_update_batching

let $use_decl_sc
SHOW use_declarative_schema_changer

statement ok
SET use_declarative_schema_changer = 'off';

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE tb AS SELECT 123::INT AS k FROM generate_series(1, 10);
SET tracing = on,kv;
ALTER TABLE tb ADD COLUMN v STRING NOT NULL DEFAULT ('abc'::STRING);
SET tracing = off;

# Check that the column backfiller batches all its Puts into one batch.
query I
SELECT count(*) FROM [SHOW KV TRACE FOR SESSION] WHERE message LIKE '%sending batch%' AND message LIKE '% Put to %';
----
1

query I
SELECT count(*) FROM tb WHERE v = 'abc';
----
10

statement ok
ROLLBACK;

# Bring the threshold way down to force column backfiller batches to have no more 1 Put each.
statement ok
SET CLUSTER SETTING bulkio.column_backfill.update_chunk_size_threshold_bytes = 1;

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
CREATE TABLE tb AS SELECT 123::INT AS k FROM generate_series(1, 10);
SET tracing = on,kv;
ALTER TABLE tb ADD COLUMN v STRING NOT NULL DEFAULT ('abc'::STRING);
SET tracing = off;

query I
SELECT count(*) FROM [SHOW KV TRACE FOR SESSION] WHERE message LIKE '%sending batch%' AND message LIKE '% Put to %';
----
10

query I
SELECT count(*) FROM tb WHERE v = 'abc';
----
10

statement ok
ROLLBACK;

# Undo subtest side effects.
statement ok
RESET CLUSTER SETTING bulkio.column_backfill.update_chunk_size_threshold_bytes;

statement ok
SET use_declarative_schema_changer = $use_decl_sc;

subtest storage_params

statement ok
CREATE TABLE storage_param_table()

statement error pgcode 22023 invalid storage parameter "foo"
ALTER TABLE storage_param_table SET (foo=100)

statement error parameter "fillfactor" requires a float value
ALTER TABLE storage_param_table SET (fillfactor=true)

statement error unimplemented: storage parameter "toast_tuple_target"
ALTER TABLE storage_param_table SET (toast_tuple_target=100)

# Weak isolation levels emit extra notices, so skip them.
skipif config weak-iso-level-configs
query T noticetrace
ALTER TABLE storage_param_table SET (fillfactor=99.9, autovacuum_enabled = off)
----
NOTICE: storage parameter "fillfactor" is ignored
NOTICE: storage parameter "autovacuum_enabled = 'off'" is ignored

statement error parameter "autovacuum_enabled" requires a Boolean value
ALTER TABLE storage_param_table SET (autovacuum_enabled='11')

statement error parameter "exclude_data_from_backup" requires a Boolean value
ALTER TABLE storage_param_table SET (exclude_data_from_backup='11')

statement error pgcode 22023 invalid storage parameter "foo"
ALTER TABLE storage_param_table RESET (foo)

statement ok
ALTER TABLE storage_param_table RESET (fillfactor, toast_tuple_target)

# Fixes issue 75154 when dropping and re-creating a constraint in a transaction
# we incorrectly detected the primary index as being used, even if its dropped
# inside the transaction. The primary index will still exist, but will be
# disabled via the drop constraint.
subtest drop-and-add-constraint-primary-index

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
create table const_tbl (a int, b int, constraint "bob" primary key (a, b));
alter table const_tbl drop constraint "bob";
alter table const_tbl add constraint "bob" primary key (a, b); -- this statement
COMMIT;

statement error relation \"const_tbl\" \(\d+\): unimplemented: primary key dropped without subsequent addition of new primary key in same transaction.*
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
alter table const_tbl drop constraint "bob";
alter table const_tbl add constraint "bob" primary key (a, b); -- this statement
alter table const_tbl drop constraint "bob";
COMMIT;

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
alter table const_tbl drop constraint "bob";
-- Note: Primary key must be restored first before any other command will
-- be allowed.
alter table const_tbl add constraint "steve" primary key (a, b); -- this statement

statement error pq: relation \"const_tbl\" \(\d+\): unimplemented: cannot perform other schema changes in the same transaction as a primary key change.*
alter table const_tbl add constraint "dave" CHECK (a > 100);

statement ok
rollback

statement ok
alter table const_tbl add constraint "steve" CHECK (a > 100);

statement error  pq: duplicate constraint name: "steve"
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
alter table const_tbl drop constraint "steve";
alter table const_tbl add constraint "steve" CHECK (a > 100);
COMMIT;

# This is needed for following tests not to run in the aborted transaction
# above.
statement ok
rollback

# Test sequence is drop when a owner table/column is dropped
subtest test_serial_ownership_add_column

statement ok
SET serial_normalization = sql_sequence;

statement ok
CREATE TABLE test_serial (
	a INT PRIMARY KEY
);

statement ok
ALTER TABLE test_serial ADD COLUMN b SERIAL;

query ITTT colnames,rowsort
SELECT l.table_id, l.name, l.state, r.refobjid
FROM (
  SELECT table_id, name, state
  FROM crdb_internal.tables WHERE name
  LIKE 'test_serial%' AND state = 'PUBLIC'
) l
LEFT JOIN pg_catalog.pg_depend r ON l.table_id = r.objid;
----
table_id  name               state   refobjid
201       test_serial_b_seq  PUBLIC  200
200       test_serial        PUBLIC  NULL

statement ok
DROP TABLE test_serial;

query ITTT colnames
SELECT l.table_id, l.name, l.state, r.refobjid
FROM (
  SELECT table_id, name, state
  FROM crdb_internal.tables WHERE name
  LIKE 'test_serial%' AND state = 'PUBLIC'
) l
LEFT JOIN pg_catalog.pg_depend r ON l.table_id = r.objid;
----
table_id  name  state  refobjid

statement ok
CREATE TABLE test_serial (
	a INT PRIMARY KEY
);

statement ok
ALTER TABLE test_serial ADD COLUMN b SERIAL;

query ITTT colnames,rowsort
SELECT l.table_id, l.name, l.state, r.refobjid
FROM (
  SELECT table_id, name, state
  FROM crdb_internal.tables WHERE name
  LIKE 'test_serial%' AND state = 'PUBLIC'
) l
LEFT JOIN pg_catalog.pg_depend r ON l.table_id = r.objid;
----
table_id  name               state   refobjid
203       test_serial_b_seq  PUBLIC  202
202       test_serial        PUBLIC  NULL

statement ok
ALTER TABLE test_serial DROP COLUMN b;

query ITTT colnames
SELECT l.table_id, l.name, l.state, r.refobjid
FROM (
  SELECT table_id, name, state
  FROM crdb_internal.tables WHERE name
  LIKE 'test_serial%' AND state = 'PUBLIC'
) l
LEFT JOIN pg_catalog.pg_depend r ON l.table_id = r.objid;
----
table_id  name         state   refobjid
202       test_serial  PUBLIC  NULL

statement ok
DROP TABLE test_serial;

# Tests for issue #71709, which happens when a primary index that is used to
# enforce the uniqueness of a foreign key reference is dropped.
subtest pk-swap-fk-ref

statement ok
CREATE TABLE pk_fk_src(id int8 primary key, legacy_id int8 not null);
CREATE TABLE pk_fk_ref(a_id int8 references pk_fk_src (id));

statement error "pk_fk_src_pkey" is referenced by foreign key from table "pk_fk_ref"
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE pk_fk_src DROP CONSTRAINT "pk_fk_src_pkey";
ALTER TABLE pk_fk_src ADD CONSTRAINT "pk_fk_src_pkey" PRIMARY KEY (legacy_id);
COMMIT;

statement ok
ROLLBACK;

statement error "pk_fk_src_pkey" is referenced by foreign key from table "pk_fk_ref"
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
ALTER TABLE pk_fk_src DROP CONSTRAINT "pk_fk_src_pkey";
ALTER TABLE pk_fk_src ADD CONSTRAINT "pk_fk_src_pkey_new" PRIMARY KEY (legacy_id);
COMMIT;

statement ok
ROLLBACK;

subtest table_settings

statement ok
CREATE TABLE t5 (a int)

# Turn on automatic stats collection
statement ok
ALTER TABLE t5 SET (sql_stats_automatic_collection_enabled = true)

# Verify automatic collection is enabled.
query T
SELECT
    crdb_internal.pb_to_json('cockroach.sql.sqlbase.Descriptor',
                              d.descriptor, false)->'table'->'autoStatsSettings'
FROM
    crdb_internal.tables AS tbl
    INNER JOIN system.descriptor AS d ON d.id = tbl.table_id
WHERE
    tbl.name = 't5'
    AND tbl.drop_time IS NULL
    AND crdb_internal.pb_to_json('cockroach.sql.sqlbase.Descriptor',
                                      d.descriptor, false)->'table'->'autoStatsSettings'
                                      ->> 'enabled' = 'true'
----
{"enabled": true}

# Strings in settings should be converted to the proper data type.
statement ok
ALTER TABLE t5 SET (sql_stats_automatic_collection_enabled = 'false')

# Verify automatic collection is disabled.
query T
SELECT
    crdb_internal.pb_to_json('cockroach.sql.sqlbase.Descriptor',
                              d.descriptor, false)->'table'->'autoStatsSettings'
FROM
    crdb_internal.tables AS tbl
    INNER JOIN system.descriptor AS d ON d.id = tbl.table_id
WHERE
    tbl.name = 't5'
    AND tbl.drop_time IS NULL
    AND crdb_internal.pb_to_json('cockroach.sql.sqlbase.Descriptor',
                                      d.descriptor, false)->'table'->'autoStatsSettings'
                                      ->> 'enabled' = 'false'
----
{"enabled": false}

# SHOW CREATE TABLE displays the value properly.
query T
SELECT create_statement FROM [SHOW CREATE TABLE t5]
----
CREATE TABLE public.t5 (
  a INT8 NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t5_pkey PRIMARY KEY (rowid ASC)
) WITH (sql_stats_automatic_collection_enabled = false)

statement error pq: parameter "sql_stats_automatic_collection_enabled" requires a Boolean value
ALTER TABLE t5 SET (sql_stats_automatic_collection_enabled = 123)

statement ok
ALTER TABLE t5 RESET (sql_stats_automatic_collection_enabled)

# Verify the automatic collection setting is removed.
query T
SELECT
    crdb_internal.pb_to_json('cockroach.sql.sqlbase.Descriptor',
                              d.descriptor, false)->'table'->>'autoStatsSettings'
FROM
    crdb_internal.tables AS tbl
    INNER JOIN system.descriptor AS d ON d.id = tbl.table_id
WHERE
    tbl.name = 't5'
    AND tbl.drop_time IS NULL
----
{}

statement error pq: invalid float value for sql_stats_automatic_collection_fraction_stale_rows: could not parse "hello" as type float: strconv.ParseFloat: parsing "hello": invalid syntax
ALTER TABLE t5 SET (sql_stats_automatic_collection_fraction_stale_rows = 'hello')

statement error pq: invalid integer value for sql_stats_automatic_collection_min_stale_rows: could not parse "world" as type int: strconv.ParseInt: parsing "world": invalid syntax
ALTER TABLE t5 SET (sql_stats_automatic_collection_min_stale_rows = 'world')

# Verify strings can be converted to proper setting values.
statement ok
ALTER TABLE t5 SET (sql_stats_automatic_collection_fraction_stale_rows = '0.15',
                    sql_stats_automatic_collection_min_stale_rows = '1234')

# Verify settings
query T
SELECT
    crdb_internal.pb_to_json('cockroach.sql.sqlbase.Descriptor',
                              d.descriptor, false)->'table'->>'autoStatsSettings'
FROM
    crdb_internal.tables AS tbl
    INNER JOIN system.descriptor AS d ON d.id = tbl.table_id
WHERE
    tbl.name = 't5'
    AND tbl.drop_time IS NULL
----
{"fractionStaleRows": 0.15, "minStaleRows": "1234"}

query T
SELECT create_statement FROM [SHOW CREATE TABLE t5]
----
CREATE TABLE public.t5 (
  a INT8 NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t5_pkey PRIMARY KEY (rowid ASC)
) WITH (sql_stats_automatic_collection_min_stale_rows = 1234, sql_stats_automatic_collection_fraction_stale_rows = 0.15)

subtest add_volatile_unique_column_81448

statement ok
create table t81448 (a int primary key);
insert into t81448 values (1), (2), (3)

statement ok
alter table t81448 add column b float8 unique default (random())

statement ok
create table t81448_b as select b from t81448@t81448_pkey;

# Make sure the rows in the index are the same as the rows in the table.

query I
select (select count(*) from t81448@t81448_b_key bk inner join t81448_b cp on (cp.b = bk.b))
----
3

statement ok
drop table t81448, t81448_b

subtest sequence_is_referenced_by_ID

statement ok
DROP TABLE IF EXISTS tbl

statement ok
CREATE TABLE tbl (i INT PRIMARY KEY)

statement ok
CREATE SEQUENCE IF NOT EXISTS s1

statement ok
CREATE SEQUENCE IF NOT EXISTS s2

statement ok
ALTER TABLE tbl ADD COLUMN j INT NOT NULL DEFAULT nextval('s1') ON UPDATE nextval('s2')

query TT
SHOW CREATE TABLE tbl
----
tbl  CREATE TABLE public.tbl (
       i INT8 NOT NULL,
       j INT8 NOT NULL DEFAULT nextval('public.s1'::REGCLASS) ON UPDATE nextval('public.s2'::REGCLASS),
       CONSTRAINT tbl_pkey PRIMARY KEY (i ASC)
     )

# Now use `ALTER COLUMN` to swap the use of sequence 's1' and 's2'

statement ok
ALTER TABLE tbl ALTER COLUMN j SET DEFAULT nextval('s2')

statement ok
ALTER TABLE tbl ALTER COLUMN j SET ON UPDATE nextval('s1')

query TT
SHOW CREATE TABLE tbl
----
tbl  CREATE TABLE public.tbl (
       i INT8 NOT NULL,
       j INT8 NOT NULL DEFAULT nextval('public.s2'::REGCLASS) ON UPDATE nextval('public.s1'::REGCLASS),
       CONSTRAINT tbl_pkey PRIMARY KEY (i ASC)
     )

# Verify that adding not-null physical column with a default or computed expression
# fails if the expression evaluates to NULL.
subtest add_column_not_null

statement ok
CREATE TABLE t_add_column_not_null (i INT PRIMARY KEY);
INSERT INTO t_add_column_not_null VALUES (1), (2), (3)

statement error pgcode 23502 null value in column "j" violates not-null constraint
ALTER TABLE t_add_column_not_null ADD COLUMN j INT NOT NULL DEFAULT (NULL:::INT)

statement error pgcode 23502 (null value in column "j" violates not-null constraint|pq: validation of column "j" NOT NULL failed on row: i=\d+, j=NULL)
ALTER TABLE t_add_column_not_null ADD COLUMN j INT GENERATED ALWAYS AS (NULL:::INT) STORED NOT NULL;

# Note that the UNIQUE here leads to a secondary index being built which will fail.
skipif config local-legacy-schema-changer
statement error pgcode 23502 validation of column "j" NOT NULL failed on row: i=1, j=NULL
ALTER TABLE t_add_column_not_null ADD COLUMN j INT GENERATED ALWAYS AS (NULL::INT) VIRTUAL NOT NULL UNIQUE;

onlyif config local-legacy-schema-changer
statement error pgcode 23502 null value in column "j" violates not-null constraint
ALTER TABLE t_add_column_not_null ADD COLUMN j INT GENERATED ALWAYS AS (NULL::INT) VIRTUAL NOT NULL UNIQUE;

statement error pgcode 23502 validation of column "j" NOT NULL failed on row: i=1, j=NULL
ALTER TABLE t_add_column_not_null ADD COLUMN j INT GENERATED ALWAYS AS (NULL::INT) VIRTUAL NOT NULL;

statement ok
DROP TABLE t_add_column_not_null

subtest regression_81448

statement ok
CREATE TABLE t81448 (a INT PRIMARY KEY)

statement error pq: multiple primary keys for table "t81448" are not allowed
ALTER TABLE t81448 ADD COLUMN b INT PRIMARY KEY

statement ok
DROP TABLE t81448

subtest add_unique_array_column

statement ok
CREATE TABLE t1_unique_array (n INT8);

statement ok
ALTER TABLE t1_unique_array ADD COLUMN x CHAR(256)[] UNIQUE;

subtest regression_89025

statement ok
CREATE TABLE t_89025 (i int primary key);

statement ok
INSERT INTO t_89025 VALUES (1)

statement error pgcode 0A000 cannot use crdb_internal\.lease_holder in this context
ALTER TABLE t_89025 ADD COLUMN j INT DEFAULT (crdb_internal.lease_holder('a'));

statement ok
DROP TABLE t_89025

# Tests for issue #90570 where we did not properly honour mutations on virtual
# computed columns, which could cause selects to fail. Specifically in a cascaded
# drop scenario, where the dependent column for a computed one is no longer
# available.
subtest drop_column_cascade_with_access

statement ok
create table t_with_dropped_index_expr (i INT PRIMARY KEY, j INT, INDEX((j+1)));

# Pause at the first PostComit phase in the plan, which is after the PreCommit
# phase of this plan added mutations in the table descriptors blocking access
# to the virtual column.
statement ok
SET CLUSTER SETTING jobs.debug.pausepoints="newschemachanger.before.exec";

skipif config local-legacy-schema-changer
statement error job \d+ was paused before it completed with reason: pause point "newschemachanger.before.exec" hit
ALTER TABLE t_with_dropped_index_expr DROP COLUMN j CASCADE;

statement ok
SET CLUSTER SETTING jobs.debug.pausepoints="";

query I
SELECT count(*) from t_with_dropped_index_expr;
----
0

statement ok
RESUME JOB (SELECT job_id FROM crdb_internal.jobs WHERE description LIKE 'ALTER TABLE %t_with_dropped_index_expr DROP COLUMN j CASCADE%' AND status='paused' FETCH FIRST 1 ROWS ONLY);


# In 23.1 we added support for default expressions which can be assignment cast
# to the column type. This work introduced a bug whereby the backfill logic
# would not apply the appropriate cast. This test ensures that such tables can
# be backfilled.
subtest add_column_with_default_expression_with_different_type

statement ok
CREATE TABLE t_93398 (c1 INT);
INSERT INTO t_93398 VALUES (0);

statement ok
ALTER TABLE t_93398 ADD COLUMN c2 DECIMAL DEFAULT pi();

query IT
SELECT * FROM t_93398;
----
0  3.141592653589793

statement error pgcode 22001 value too long for type CHAR
ALTER TABLE t_93398 ADD COLUMN c3 CHAR(1) DEFAULT 'foo'::TEXT;

statement ok
ALTER TABLE t_93398 ADD COLUMN c3 "char" DEFAULT 'foo'::TEXT;

query IT
SELECT c1, c3 FROM t_93398;
----
0  f

# The following subtest tests the case when there is a check constraint
# that references other descriptors (such as sequences and types):
# - drop referenced sequence cascade
# - drop the check itself
# - drop the referencing table
# Note that legacy schema changer won't support those cases correctly
# so we will skip them.
subtest cross_descriptor_checks_96115

statement ok
CREATE SEQUENCE seq_96115;

statement ok
CREATE TYPE typ_96115 AS ENUM ('a', 'b');

statement ok
CREATE TABLE t_96115 (i INT PRIMARY KEY, j STRING);

statement ok
ALTER TABLE t_96115 ADD CHECK (i > nextval('seq_96115') AND j::typ_96115 = 'a'::typ_96115);

skipif config local-legacy-schema-changer
query TTTB colnames
SELECT table_name, constraint_name, constraint_type, validated
FROM [SHOW CONSTRAINTS FROM t_96115]
ORDER BY constraint_type;
----
table_name  constraint_name  constraint_type  validated
t_96115     check_i_j        CHECK            true
t_96115     t_96115_pkey     PRIMARY KEY      true

statement ok
ALTER TABLE t_96115 DROP CONSTRAINT check_i_j;

skipif config local-legacy-schema-changer
query TTTB colnames
SELECT table_name, constraint_name, constraint_type, validated
FROM [SHOW CONSTRAINTS FROM t_96115]
ORDER BY constraint_type;
----
table_name  constraint_name  constraint_type  validated
t_96115     t_96115_pkey     PRIMARY KEY      true

statement ok
ALTER TABLE t_96115 ADD CHECK (i > nextval('seq_96115') AND j::typ_96115 = 'a'::typ_96115);

skipif config local-legacy-schema-changer
query TTTB colnames
SELECT table_name, constraint_name, constraint_type, validated
FROM [SHOW CONSTRAINTS FROM t_96115]
ORDER BY constraint_type;
----
table_name  constraint_name  constraint_type  validated
t_96115     check_i_j        CHECK            true
t_96115     t_96115_pkey     PRIMARY KEY      true

statement ok
DROP SEQUENCE seq_96115 CASCADE;

skipif config local-legacy-schema-changer
query TTTB colnames
SELECT table_name, constraint_name, constraint_type, validated
FROM [SHOW CONSTRAINTS FROM t_96115]
ORDER BY constraint_type;
----
table_name  constraint_name  constraint_type  validated
t_96115     t_96115_pkey     PRIMARY KEY      true

statement ok
CREATE SEQUENCE seq_96115;

statement ok
ALTER TABLE t_96115 ADD CHECK (i > nextval('seq_96115') AND j::typ_96115 = 'a'::typ_96115);

statement ok
DROP TABLE t_96115;

statement ok
DROP TYPE typ_96115;

statement ok
DROP SEQUENCE seq_96115

# This subtest ensures we can drop partial unique without index.
subtest drop_partial_unique_without_index_constraint_96115

statement ok
CREATE TABLE t_96115 (i INT PRIMARY KEY, j INT);

statement ok
set experimental_enable_unique_without_index_constraints = true;

statement ok
ALTER TABLE t_96115 ADD UNIQUE WITHOUT INDEX (j) WHERE j > 0;

query TTTB colnames
SELECT table_name, constraint_name, constraint_type, validated
FROM [SHOW CONSTRAINTS FROM t_96115]
ORDER BY constraint_type;
----
table_name  constraint_name  constraint_type  validated
t_96115     t_96115_pkey     PRIMARY KEY      true
t_96115     unique_j         UNIQUE           true

statement ok
ALTER TABLE t_96115 DROP CONSTRAINT unique_j;

query TTTB colnames
SELECT table_name, constraint_name, constraint_type, validated
FROM [SHOW CONSTRAINTS FROM t_96115]
ORDER BY constraint_type;
----
table_name  constraint_name  constraint_type  validated
t_96115     t_96115_pkey     PRIMARY KEY      true

statement ok
DROP TABLE t_96115;

# This subtest tests the behavior of adding/dropping a constraint and validating
# the constraint in one ALTER TABLE statement.

subtest 96648

statement ok
CREATE TABLE t_96648 (i INT PRIMARY KEY);

statement error pq: constraint "check_i" in the middle of being added, try again later
ALTER TABLE t_96648 ADD CONSTRAINT check_i CHECK (i > 0), VALIDATE CONSTRAINT check_i;

statement ok
ALTER TABLE t_96648 ADD CONSTRAINT check_i CHECK (i > 0);

# Ensure check "check_i" is successfully added.
statement error pq: failed to satisfy CHECK constraint \(i > 0:::INT8\)
INSERT INTO t_96648 VALUES (0);

statement ok
ALTER TABLE t_96648 ADD CONSTRAINT check_i1 CHECK (i > 10) NOT VALID, VALIDATE CONSTRAINT check_i1;

# Ensure check "check_i2" is successfully added.
statement error pq: failed to satisfy CHECK constraint \(i > 10:::INT8\)
INSERT INTO t_96648 VALUES (5)

statement error pgcode 42704 constraint "check_i" of relation "t_96648" does not exist
ALTER TABLE t_96648 DROP CONSTRAINT check_i, VALIDATE CONSTRAINT check_i;

statement error pgcode 42704 constraint "check_i1" of relation "t_96648" does not exist
ALTER TABLE t_96648 DROP CONSTRAINT check_i1, VALIDATE CONSTRAINT check_i1;

statement ok
ALTER TABLE t_96648 DROP CONSTRAINT check_i, DROP CONSTRAINT check_i1;

statement ok
DROP TABLE t_96648

# This subtests ensures that dropping unique and unique without index
# constraints with dependent FKs works properly.
subtest drop_constraint_with_dependent_FKs_97538

statement ok
CREATE TABLE t_97538_2 (i INT PRIMARY KEY, j INT);

statement ok
SET experimental_enable_unique_without_index_constraints = true

statement ok
ALTER TABLE t_97538_2 ADD UNIQUE WITHOUT INDEX (j);

statement ok
CREATE UNIQUE INDEX t_97538_2_j_key on t_97538_2(j);

statement ok
CREATE TABLE t_97538_1 (i INT PRIMARY KEY REFERENCES t_97538_2(j));

statement ok
DROP INDEX t_97538_2_j_key;

# Ensure that only the unique index is dropped but not the FK
# because we have replacement (the other unique without index constraint).
query TTTTB colnames,nosort
SHOW CONSTRAINTS FROM t_97538_1
----
table_name  constraint_name   constraint_type  details                                  validated
t_97538_1   t_97538_1_i_fkey  FOREIGN KEY      FOREIGN KEY (i) REFERENCES t_97538_2(j)  true
t_97538_1   t_97538_1_pkey    PRIMARY KEY      PRIMARY KEY (i ASC)                      true

# Add back the unique index, and drop the unique without index constraint (without CASCADE) this time.
statement ok
CREATE UNIQUE INDEX t_97538_2_j_key on t_97538_2(j);

statement ok
ALTER TABLE t_97538_2 DROP CONSTRAINT unique_j;

# Similarly, ensure that only the constraint is dropped but not the FK
# because we have replacement (the other unique index).
query TTTTB colnames,nosort
SHOW CONSTRAINTS FROM t_97538_1
----
table_name  constraint_name   constraint_type  details                                  validated
t_97538_1   t_97538_1_i_fkey  FOREIGN KEY      FOREIGN KEY (i) REFERENCES t_97538_2(j)  true
t_97538_1   t_97538_1_pkey    PRIMARY KEY      PRIMARY KEY (i ASC)                      true

statement ok
DROP INDEX t_97538_2_j_key CASCADE;

# Now ensure that the FK is dropped as a result of the cascade.
query TTTTB colnames
SHOW CONSTRAINTS FROM t_97538_1
----
table_name  constraint_name  constraint_type  details              validated
t_97538_1   t_97538_1_pkey   PRIMARY KEY      PRIMARY KEY (i ASC)  true

# This subtest ensures that dropping a column that is referenced
# by constraints works properly.
subtest drop_column_with_dependent_FKs_96727

statement ok
CREATE TABLE t_96727_2 (i INT PRIMARY KEY, j INT UNIQUE, FAMILY (i, j));

statement ok
SET experimental_enable_unique_without_index_constraints = true

statement ok
ALTER TABLE t_96727_2 ADD UNIQUE WITHOUT INDEX (j);

statement ok
CREATE TABLE t_96727_1 (i INT PRIMARY KEY REFERENCES t_96727_2(j));

# Here, either the unique index or the unique without index constraint
# is used for the output of error message is okay, so we used ".*".
statement error pq: ".*" is referenced by foreign key from table "t_96727_1"
ALTER TABLE t_96727_2 DROP COLUMN j;

statement ok
ALTER TABLE t_96727_2 DROP COLUMN j CASCADE;

# Ensure that the unique index, unique without index constraint, as well
# as the FK constraint are all dropped as a result of dropping the column.
query TT
SHOW CREATE TABLE t_96727_2
----
t_96727_2  CREATE TABLE public.t_96727_2 (
             i INT8 NOT NULL,
             CONSTRAINT t_96727_2_pkey PRIMARY KEY (i ASC),
             FAMILY fam_0_i_j (i)
           )

query TT
SHOW CREATE TABLE t_96727_1
----
t_96727_1  CREATE TABLE public.t_96727_1 (
             i INT8 NOT NULL,
             CONSTRAINT t_96727_1_pkey PRIMARY KEY (i ASC)
           )

# More testing when the column is referenced in other constraints.
statement ok
ALTER TABLE t_96727_2 ADD COLUMN j INT;

statement ok
ALTER TABLE t_96727_2 ADD CHECK (j > 0), ADD CHECK (j < 10) NOT VALID, ADD UNIQUE WITHOUT INDEX (j);

statement ok
CREATE UNIQUE INDEX idx ON t_96727_2(j);

statement ok
ALTER TABLE t_96727_2 DROP COLUMN j;

# Ensure dropping the column, even without CASCADE, will also
# drop all the constraints.
query TT
SHOW CREATE TABLE t_96727_2
----
t_96727_2  CREATE TABLE public.t_96727_2 (
             i INT8 NOT NULL,
             CONSTRAINT t_96727_2_pkey PRIMARY KEY (i ASC),
             FAMILY fam_0_i_j (i)
           )

subtest regression_97546

statement ok
CREATE TABLE t_twocol (
  id INT PRIMARY KEY,
  a INT,
  b INT,
  FAMILY fam_0 (id, a, b)
);
CREATE FUNCTION f1() RETURNS t_twocol AS 'SELECT * FROM t_twocol' LANGUAGE SQL;
CREATE FUNCTION f2() RETURNS t_twocol AS 'SELECT * FROM t_twocol' LANGUAGE SQL;
CREATE FUNCTION f3() RETURNS INT AS 'SELECT a FROM t_twocol' LANGUAGE SQL;

statement ok
ALTER TABLE t_twocol DROP COLUMN b CASCADE;

statement error pq: unknown function: f1\(\)
SELECT f1();

statement error pq: unknown function: f2\(\)
SELECT f2();

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_twocol]
----
CREATE TABLE public.t_twocol (
  id INT8 NOT NULL,
  a INT8 NULL,
  CONSTRAINT t_twocol_pkey PRIMARY KEY (id ASC),
  FAMILY fam_0 (id, a)
)

statement ok
DROP TABLE t_twocol CASCADE;

subtest regress_96368

statement ok
CREATE TABLE t_twocol (
  id INT PRIMARY KEY,
  a INT,
  b INT,
  FAMILY fam_0 (id, a, b)
);
CREATE FUNCTION f_unqualified_twocol() RETURNS t_twocol AS
$$
  SELECT t_twocol.id, t_twocol.a, t_twocol.b FROM t_twocol;
$$ LANGUAGE SQL;
CREATE FUNCTION f_allcolsel_alias() RETURNS t_twocol AS
$$
  SELECT t1.id, t1.a, t1.b FROM t_twocol AS t1, t_twocol AS t2 WHERE t1.a = t2.a;
$$ LANGUAGE SQL;
CREATE FUNCTION f_tuplestar() RETURNS t_twocol AS
$$
  SELECT t_twocol.id, t_twocol.a, t_twocol.b FROM t_twocol;
$$ LANGUAGE SQL;

# This statement should be ok but fails
statement ok
ALTER TABLE t_twocol DROP COLUMN b CASCADE;

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_twocol]
----
CREATE TABLE public.t_twocol (
  id INT8 NOT NULL,
  a INT8 NULL,
  CONSTRAINT t_twocol_pkey PRIMARY KEY (id ASC),
  FAMILY fam_0 (id, a)
)

# This subtests ensures we cannot add an unvalidated PK constraint
subtest add_unvalidated_pk_96729

statement ok
CREATE TABLE t_96729 (i INT NOT NULL)

statement error pgcode 0A000 PRIMARY KEY constraints cannot be marked NOT VALID
ALTER TABLE t_96729 ADD PRIMARY KEY (i) NOT VALID;

statement ok
ALTER TABLE t_96729 ADD PRIMARY KEY (i);

query TTTTB colnames
SHOW CONSTRAINTS FROM t_96729
----
table_name  constraint_name  constraint_type  details              validated
t_96729     t_96729_pkey     PRIMARY KEY      PRIMARY KEY (i ASC)  true

# This subtests ensures adding UNIQUE constraint works properly.
subtest alter_table_add_unique_96728

statement ok
CREATE TABLE t_96728 (i INT PRIMARY KEY, j INT, k INT);

statement error pgcode 0A000 UNIQUE constraints cannot be marked NOT VALID
ALTER TABLE t_96728 ADD UNIQUE (j) NOT VALID;

statement ok
ALTER TABLE t_96728 ADD UNIQUE (j, k) WHERE (i > 0);

query TTTTB colnames,nosort
SHOW CONSTRAINTS FROM t_96728
----
table_name  constraint_name  constraint_type  details                              validated
t_96728     t_96728_j_k_key  UNIQUE           UNIQUE (j ASC, k ASC) WHERE (i > 0)  true
t_96728     t_96728_pkey     PRIMARY KEY      PRIMARY KEY (i ASC)                  true

# This subtest tests behavior when there are multiple commands (ADD COLUMN, DROP COLUMN,
# ALTER PRIMARY KEY, ADD CONSTRAINT) in one ALTER TABLE statement.
# 1). add column + drop column
# 2). add column + alter primary key
# 3). drop column + alter primary key
# 4). add column + drop column + alter primary key
# 5). add column(s) + drop column(s) + alter primary key
# 6). add column(s) + drop column(s) + alter primary key + add check + add fk
# This is only supported in declarative schema changer starting from V23_2.
subtest alter_table_with_multiple_commands_99035

statement ok
DROP TABLE IF EXISTS t_99035;
CREATE TABLE t_99035 (i INT PRIMARY KEY, j INT NOT NULL, FAMILY "primary" (i, j));
INSERT INTO t_99035 VALUES (0,0);

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN k INT DEFAULT unique_rowid(), DROP COLUMN j;

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  i INT8 NOT NULL,
  k INT8 NULL DEFAULT unique_rowid(),
  CONSTRAINT t_99035_pkey PRIMARY KEY (i ASC)
)

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN j INT DEFAULT unique_rowid(), DROP COLUMN j; -- noop

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN j INT, DROP COLUMN j;  -- noop

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  i INT8 NOT NULL,
  k INT8 NULL DEFAULT unique_rowid(),
  CONSTRAINT t_99035_pkey PRIMARY KEY (i ASC)
)

statement ok
DROP TABLE IF EXISTS t_99035;
CREATE TABLE t_99035 (i INT PRIMARY KEY, j INT NOT NULL, FAMILY "primary" (i, j));
INSERT INTO t_99035 VALUES (0,0);

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN k INT DEFAULT unique_rowid(), ALTER PRIMARY KEY USING COLUMNS (j);

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  i INT8 NOT NULL,
  j INT8 NOT NULL,
  k INT8 NULL DEFAULT unique_rowid(),
  CONSTRAINT t_99035_pkey PRIMARY KEY (j ASC),
  UNIQUE INDEX t_99035_i_key (i ASC)
)

statement ok
DROP TABLE IF EXISTS t_99035;
CREATE TABLE t_99035 (i INT PRIMARY KEY, j INT NOT NULL, FAMILY "primary" (i, j));
INSERT INTO t_99035 VALUES (0,0);

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ALTER PRIMARY KEY USING COLUMNS (j), DROP COLUMN i;

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  j INT8 NOT NULL,
  CONSTRAINT t_99035_pkey PRIMARY KEY (j ASC)
)

statement ok
DROP TABLE IF EXISTS t_99035;
CREATE TABLE t_99035 (i INT PRIMARY KEY, j INT NOT NULL, FAMILY "primary" (i, j));
INSERT INTO t_99035 VALUES (0,0);

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN k INT DEFAULT unique_rowid(), ALTER PRIMARY KEY USING COLUMNS (j), DROP COLUMN i;

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  j INT8 NOT NULL,
  k INT8 NULL DEFAULT unique_rowid(),
  CONSTRAINT t_99035_pkey PRIMARY KEY (j ASC)
)

statement ok
DROP TABLE IF EXISTS t_99035;
CREATE TABLE t_99035 (i INT PRIMARY KEY, j INT NOT NULL, FAMILY "primary" (i, j));
INSERT INTO t_99035 VALUES (0,0);

skipif config local-legacy-schema-changer
statement error validation of CHECK "j > 0:::INT8" failed on row: i=NULL, j=0, k=[0-9]+, p=30
ALTER TABLE t_99035 ADD COLUMN k INT DEFAULT unique_rowid(), ALTER PRIMARY KEY USING COLUMNS (j), DROP COLUMN i, ADD COLUMN p INT DEFAULT 30, ADD CHECK (j>0);

query II
SELECT * FROM t_99035
----
0 0

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN k INT DEFAULT unique_rowid(), ALTER PRIMARY KEY USING COLUMNS (j), DROP COLUMN i, ADD COLUMN p INT DEFAULT 30, ADD CHECK (j>=0);

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  j INT8 NOT NULL,
  k INT8 NULL DEFAULT unique_rowid(),
  p INT8 NULL DEFAULT 30:::INT8,
  CONSTRAINT t_99035_pkey PRIMARY KEY (j ASC),
  CONSTRAINT check_j CHECK (j >= 0:::INT8)
)

statement ok
DROP TABLE IF EXISTS t_99035;
CREATE TABLE t_99035 (i INT PRIMARY KEY, j INT NOT NULL, FAMILY "primary" (i, j));
INSERT INTO t_99035 VALUES (0,0);

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99035 ADD COLUMN k INT DEFAULT unique_rowid(), ALTER PRIMARY KEY USING COLUMNS (j), DROP COLUMN i, ADD COLUMN p INT DEFAULT 0, ADD CHECK (j>=0), ADD FOREIGN KEY (p) REFERENCES t_99035(j);

skipif config local-legacy-schema-changer
query T
SELECT create_statement FROM [SHOW CREATE TABLE t_99035]
----
CREATE TABLE public.t_99035 (
  j INT8 NOT NULL,
  k INT8 NULL DEFAULT unique_rowid(),
  p INT8 NULL DEFAULT 0:::INT8,
  CONSTRAINT t_99035_pkey PRIMARY KEY (j ASC),
  CONSTRAINT t_99035_p_fkey FOREIGN KEY (p) REFERENCES public.t_99035(j),
  CONSTRAINT check_j CHECK (j >= 0:::INT8)
)

subtest end

# This subtest disallows using builtin function `cluster_logical_timestamp()`
# as the default expression when backfilling a column.
subtest 98269

statement ok
CREATE TABLE t_98269 (i INT PRIMARY KEY);
INSERT INTO t_98269 VALUES (0);

statement error pgcode 0A000 .* cluster_logical_timestamp\(\): nil txn in cluster context
ALTER TABLE t_98269 ADD COLUMN j DECIMAL NOT NULL DEFAULT cluster_logical_timestamp();

# In #99185, we saw test failures that result from adding a foreign key
# constraint to a non-existent table with IF EXISTS because we require all tables
# in the stmt should be marked as non-existent or fully resolved. We didn't do
# anything to the referenced table name, so the validation logic complained that
# referenced table name is not fully resolved nor marked as non-existent.
subtest alter_non_existent_table_with_if_exists

statement ok
ALTER TABLE IF EXISTS t_non_existent_99185 ADD FOREIGN KEY (i) REFERENCES t_other_99185 (i);

# This subtest tests behavior when we have add/drop column and add constraint in one stmt.
subtest 99281

statement ok
SET experimental_enable_unique_without_index_constraints = true;

statement ok
CREATE TABLE t_99281 (i INT PRIMARY KEY, j INT NOT NULL, k INT NOT NULL, FAMILY "primary" (i,j,k));
INSERT INTO t_99281 VALUES (0,0,0), (1,0,1);

statement error pq: could not create unique constraint ".*"
ALTER TABLE t_99281 ADD UNIQUE WITHOUT INDEX (j);

statement error pq: could not create unique constraint ".*"
ALTER TABLE t_99281 ADD COLUMN p INT DEFAULT unique_rowid(), ADD UNIQUE WITHOUT INDEX (j);

# The following statement will cause the stmt to hang using the legacy schema changer.
skipif config local-legacy-schema-changer
statement error pq: could not create unique constraint ".*"
ALTER TABLE t_99281 DROP COLUMN k, ADD UNIQUE WITHOUT INDEX (j);

statement error pq: validation of CHECK "i > 0:::INT8" failed on row: i=0, j=0, k=0, p=[0-9]+
ALTER TABLE t_99281 ADD COLUMN p INT DEFAULT unique_rowid(), ADD CHECK (i > 0);

statement error pq: validation of CHECK "j > 0:::INT8" failed on row: i=[0-1], j=0, k=[0-1], p=[0-9]+
ALTER TABLE t_99281 ADD COLUMN p INT DEFAULT unique_rowid(), ADD CHECK (i >= 0), ADD CHECK (j > 0);

statement ok
CREATE TABLE t_99281_other (i INT PRIMARY KEY);

statement error pq: foreign key violation: "t_99281" row j=0, i=[0-1] has no match in "t_99281_other"
ALTER TABLE t_99281 ADD COLUMN p INT DEFAULT unique_rowid(), ADD FOREIGN KEY (j) REFERENCES t_99281_other;

# The following statement is not supported using the legacy schema changer.
skipif config local-legacy-schema-changer
statement error pq: foreign key violation: "t_99281" row j=0, k=[0-1] has no match in "t_99281_other"
ALTER TABLE t_99281 ALTER PRIMARY KEY USING COLUMNS (k), ADD FOREIGN KEY (j) REFERENCES t_99281_other;

query TT
show create table t_99281
----
t_99281  CREATE TABLE public.t_99281 (
           i INT8 NOT NULL,
           j INT8 NOT NULL,
           k INT8 NOT NULL,
           CONSTRAINT t_99281_pkey PRIMARY KEY (i ASC)
         )

subtest 99764

statement ok
CREATE TABLE t_99764 (i INT PRIMARY KEY, j INT, UNIQUE (j, CAST(j AS STRING)), FAMILY "primary" (i, j));
set sql_safe_updates = false;

# Dropping `j` should also drop the unique index as well as the expression column.
# Legacy schema change is incapable to do this.
skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_99764 DROP COLUMN j CASCADE;

skipif config local-legacy-schema-changer
query TT
show create table t_99764
----
t_99764  CREATE TABLE public.t_99764 (
             i INT8 NOT NULL,
             CONSTRAINT t_99764_pkey PRIMARY KEY (i ASC)
         )

# Validate that DROP COLUMN CASCADE generates the proper error if we attempt
# to drop a key column
subtest alter_table_drop_cascade_with_key

statement ok
create table t_drop_cascade_with_key(n int primary key, k int);

statement ok
alter table t_drop_cascade_with_key add column j int as (n) stored null;

statement ok
set sql_safe_updates=false

statement error pgcode 42P10 column "n" is referenced by.*
alter table t_drop_cascade_with_key drop column n cascade;

subtest end

# This subtest ensures that if a schema change requires dropping an index,
# primary or secondary, and that index is referenced in a UDF body or a view
# query via index hinting, then we disallow such schema changes.
subtest 108974

statement ok
CREATE TABLE t_108974_f(i INT PRIMARY KEY, j INT NOT NULL, k INT, INDEX (i,j));
INSERT INTO t_108974_f SELECT p,p+1,p+2 FROM generate_series(1,100) AS tmp(p);
CREATE TABLE t_108974_v(i INT PRIMARY KEY, j INT NOT NULL, k INT, INDEX (i,j));
INSERT INTO t_108974_v SELECT p,p+1,p+2 FROM generate_series(1,100) AS tmp(p);
CREATE FUNCTION f_108974() RETURNS RECORD LANGUAGE SQL AS
$$
SELECT i, j FROM t_108974_f;
SELECT i, j FROM t_108974_f@t_108974_f_pkey;
SELECT i, j FROM t_108974_f@t_108974_f_i_j_idx;
SELECT i, j FROM t_108974_f@[0];
SELECT i, j FROM t_108974_f@[1];
SELECT i, j FROM t_108974_f@[2];
$$;
CREATE VIEW v_108974 AS SELECT i, j FROM t_108974_v@t_108974_v_pkey;
SET sql_safe_updates = false;

statement error pgcode 2BP01 pq: cannot drop index "t_108974_f_i_j_idx" because function "f_108974" depends on it
DROP INDEX t_108974_f@t_108974_f_i_j_idx;

statement error pgcode 0A000 pq: unimplemented: table \"t_108974_f\" has an index \(t_108974_f_i_j_idx\) that is still referenced by \"f_108974\"
ALTER TABLE t_108974_f ALTER PRIMARY KEY USING COLUMNS (j);

statement error pgcode 2BP01 pq: cannot drop index "t_108974_v_pkey" because view "v_108974" depends on it
ALTER TABLE t_108974_v ALTER PRIMARY KEY USING COLUMNS (j);

statement error pgcode 2BP01 pq: cannot drop index "t_108974_f_pkey" because function "f_108974" depends on it
ALTER TABLE t_108974_f ADD COLUMN p INT DEFAULT 30;

statement error pgcode 2BP01 pq: cannot drop index "t_108974_v_pkey" because view "v_108974" depends on it
ALTER TABLE t_108974_v ADD COLUMN p INT DEFAULT 30;

statement error pgcode 2BP01 pq: cannot drop index "t_108974_f_pkey" because function "f_108974" depends on it
ALTER TABLE t_108974_f DROP COLUMN k;

statement error pgcode 2BP01 pq: cannot drop index "t_108974_v_pkey" because view "v_108974" depends on it
ALTER TABLE t_108974_v DROP COLUMN k;

subtest end

# Regression test for https://github.com/cockroachdb/cockroach/issues/110629.
subtest 110629

# Subqueries are not allowed in storage parameters.
statement ok
CREATE TABLE t_110629 (a INT PRIMARY KEY);

statement error subqueries are not allowed in table storage parameters
ALTER TABLE t SET ( 'string' = EXISTS ( TABLE error ) );

subtest end

# Regression test for https://github.com/cockroachdb/cockroach/issues/118246
subtest 118246

statement ok
CREATE TABLE t_118246 (i INT PRIMARY KEY);
INSERT INTO t_118246 VALUES (0);

statement ok
SET experimental_enable_unique_without_index_constraints = true;

statement ok
ALTER TABLE t_118246 ADD COLUMN j INT, ADD UNIQUE WITHOUT INDEX (j);

statement ok
ALTER TABLE t_118246 ADD COLUMN k INT DEFAULT 30, ADD UNIQUE WITHOUT INDEX (k);

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_118246]
----
CREATE TABLE public.t_118246 (
  i INT8 NOT NULL,
  j INT8 NULL,
  k INT8 NULL DEFAULT 30:::INT8,
  CONSTRAINT t_118246_pkey PRIMARY KEY (i ASC),
  CONSTRAINT unique_j UNIQUE WITHOUT INDEX (j),
  CONSTRAINT unique_k UNIQUE WITHOUT INDEX (k)
)

subtest end


# When the new primary key does not have the same columns as the original primary
# key schema changes recreating secondary indexes could fail incorrectly during validation,
# if the secondary had some references to the old primary index key (for example
# partial expressions). This was because an scan of the new secondary index would
# not return the old primary key, which query execution was expecting.
subtest 118626

statement ok
CREATE TABLE public.t_118626(n int primary key, b int NOT NULL, c int NOT NULL);
INSERT INTO public.t_118626 VALUES(1, 2, 3);

statement ok
CREATE UNIQUE INDEX ON public.t_118626(c) WHERE n>= 1;

statement ok
ALTER TABLE public.t_118626 ALTER PRIMARY KEY USING COLUMNS(b);

# Regression test to make sure that we can drop and re-add a CHECK constraint
# with the same name in one statement.
subtest 120017

statement ok
CREATE TABLE t_120017 (
  a INT PRIMARY KEY,
  b TEXT,
  c INT NOT NULL,
  CHECK (b IN ('x', 'y'))
)

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE t_120017
DROP CONSTRAINT check_b,
ADD CONSTRAINT check_b CHECK (b IN ('x', 'y', 'z'))

query T
SELECT crdb_internal.pb_to_json('desc', descriptor) #> '{table,mutations}'
FROM system.descriptor
WHERE id = 't_120017'::regclass::oid
----
NULL

statement ok
ALTER TABLE t_120017
DROP CONSTRAINT "t_120017_pkey",
ADD CONSTRAINT "t_120017_pkey" PRIMARY KEY (a, c)

subtest end

subtest identity_column

statement ok
CREATE TABLE t_add_generated (
  a int NOT NULL,
  b int NOT NULL,
  c int,
  d STRING NOT NULL,
  e INT DEFAULT 1,
  FAMILY (a,b,c,d,e)
)

statement ok
ALTER TABLE t_add_generated ALTER COLUMN a ADD GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3);

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_add_generated]
----
CREATE TABLE public.t_add_generated (
  a INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3),
  b INT8 NOT NULL,
  c INT8 NULL,
  d STRING NOT NULL,
  e INT8 NULL DEFAULT 1:::INT8,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t_add_generated_pkey PRIMARY KEY (rowid ASC),
  FAMILY fam_0_a_b_c_d_e_rowid (a, b, c, d, e, rowid)
)

statement ok
ALTER TABLE t_add_generated ALTER COLUMN b ADD GENERATED ALWAYS AS IDENTITY (START WITH 2 INCREMENT 3);

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_add_generated]
----
CREATE TABLE public.t_add_generated (
  a INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3),
  b INT8 NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 2 INCREMENT 3),
  c INT8 NULL,
  d STRING NOT NULL,
  e INT8 NULL DEFAULT 1:::INT8,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t_add_generated_pkey PRIMARY KEY (rowid ASC),
  FAMILY fam_0_a_b_c_d_e_rowid (a, b, c, d, e, rowid)
)

query error pq: column "c" of relation "t_add_generated" must be declared NOT NULL before identity can be added
ALTER TABLE t_add_generated ALTER COLUMN c ADD GENERATED ALWAYS AS IDENTITY;

query error pq: column "e" of relation "t_add_generated" already has a default value
ALTER TABLE t_add_generated ALTER COLUMN e ADD GENERATED ALWAYS AS IDENTITY;

query error pq: column "a" of relation "t_add_generated" is already an identity column
ALTER TABLE t_add_generated ALTER COLUMN a ADD GENERATED ALWAYS AS IDENTITY;

query error pq: column "d" of relation "t_add_generated" type must be an integer type
ALTER TABLE t_add_generated ALTER COLUMN d ADD GENERATED ALWAYS AS IDENTITY;

statement ok
INSERT INTO t_add_generated (d) VALUES ('11'), ('12'), ('13');

statement ok
INSERT INTO t_add_generated (a,d) VALUES (21,'21'), (22,'22'), (23,'23');

statement error pq: cannot insert into column "b"\nDETAIL: Column "b" is an identity column defined as GENERATED ALWAYS
INSERT INTO t_add_generated (b,d) VALUES (31,'31'), (32,'32'), (33,'33');

query IIITI
SELECT * FROM t_add_generated ORDER BY a
----
2   2   NULL  11  1
5   5   NULL  12  1
8   8   NULL  13  1
21  11  NULL  21  1
22  14  NULL  22  1
23  17  NULL  23  1

statement ok
CREATE TABLE t_set_generated (
  a int GENERATED ALWAYS AS IDENTITY (START WITH 2 INCREMENT 3),
  b int GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3),
  c int,
  FAMILY (a,b,c)
);

statement ok
ALTER TABLE t_set_generated ALTER COLUMN a SET GENERATED BY DEFAULT;

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_set_generated]
----
CREATE TABLE public.t_set_generated (
  a INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3),
  b INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3),
  c INT8 NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t_set_generated_pkey PRIMARY KEY (rowid ASC),
  FAMILY fam_0_a_b_c_rowid (a, b, c, rowid)
)

statement ok
ALTER TABLE t_set_generated ALTER COLUMN b SET GENERATED ALWAYS;

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_set_generated]
----
CREATE TABLE public.t_set_generated (
  a INT8 NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 2 INCREMENT 3),
  b INT8 NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 2 INCREMENT 3),
  c INT8 NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  CONSTRAINT t_set_generated_pkey PRIMARY KEY (rowid ASC),
  FAMILY fam_0_a_b_c_rowid (a, b, c, rowid)
)

statement error pq: column "c" of relation "t_set_generated" is not an identity column
ALTER TABLE t_set_generated ALTER COLUMN c SET GENERATED BY DEFAULT;

statement error pq: column "c" of relation "t_set_generated" is not an identity column
ALTER TABLE t_set_generated ALTER COLUMN c SET GENERATED ALWAYS;

statement ok
INSERT INTO t_set_generated DEFAULT VALUES;

statement ok
INSERT INTO t_set_generated DEFAULT VALUES;

statement ok
INSERT INTO t_set_generated (a) VALUES (3);

statement error pq: cannot insert into column "b"\nDETAIL: Column "b" is an identity column defined as GENERATED ALWAYS
INSERT INTO t_set_generated (b) VALUES (4);

query III
SELECT * FROM t_set_generated ORDER BY a
----
2  2  NULL
3  8  NULL
5  5  NULL

subtest end


statement ok
CREATE TABLE t_alter_identity (id SERIAL PRIMARY KEY, a int GENERATED ALWAYS AS IDENTITY, b int GENERATED ALWAYS AS IDENTITY, z int);

statement error pq: INCREMENT must not be zero
ALTER TABLE t_alter_identity ALTER COLUMN b SET INCREMENT 0;

query error pq: START value \(11\) cannot be greater than MAXVALUE \(10\)
ALTER TABLE t_alter_identity ALTER COLUMN b SET MAXVALUE 10 SET START WITH 11;

query error pq: START value \(5\) cannot be less than MINVALUE \(10\)
ALTER TABLE t_alter_identity ALTER COLUMN b SET MINVALUE 10 SET START WITH 5;

query error pq: column "z" of relation "t_alter_identity" is not an identity column
ALTER TABLE t_alter_identity ALTER COLUMN z SET START WITH 5;

# Verify sequence options are implemented on the identity

statement ok
INSERT INTO t_alter_identity DEFAULT VALUES;

statement ok
ALTER TABLE t_alter_identity ALTER COLUMN b SET START WITH 5;

statement ok
ALTER TABLE t_alter_identity ALTER COLUMN b SET INCREMENT 4;

statement ok
ALTER TABLE t_alter_identity ALTER COLUMN b RESTART;

statement ok
INSERT INTO t_alter_identity DEFAULT VALUES;

statement ok
INSERT INTO t_alter_identity DEFAULT VALUES;

statement ok
ALTER TABLE t_alter_identity ALTER COLUMN b SET MAXVALUE 40 RESTART WITH 20 SET CACHE 5 SET INCREMENT BY 2

statement ok
INSERT INTO t_alter_identity DEFAULT VALUES;

statement ok
INSERT INTO t_alter_identity DEFAULT VALUES;

query I rowsort
SELECT b from t_alter_identity ORDER BY b;
----
1
5
9
18
20

statement ok
CREATE TABLE t_identity_drop (a int GENERATED ALWAYS AS IDENTITY (START WITH 10), b int GENERATED BY DEFAULT AS IDENTITY);

statement error pgcode 428C9 pq: cannot insert into column "a"\nDETAIL: Column "a" is an identity column defined as GENERATED ALWAYS
INSERT INTO t_identity_drop (a) VALUES (3);

statement ok
ALTER TABLE t_identity_drop ALTER COLUMN a DROP IDENTITY;

statement error pgcode 55000 pq: column "a" of relation "t_identity_drop" is not an identity column
ALTER TABLE t_identity_drop ALTER COLUMN a DROP IDENTITY;

statement notice NOTICE: column "a" of relation "t_identity_drop" is not an identity column, skipping
ALTER TABLE t_identity_drop ALTER COLUMN a DROP IDENTITY IF EXISTS;

statement ok
INSERT INTO t_identity_drop (a) VALUES (3);

statement ok
CREATE TABLE t_identity_drop_dependency(id INT PRIMARY KEY DEFAULT nextval('public.t_identity_drop_b_seq'));

statement error pgcode 2BP01 pq: cannot drop table t_identity_drop because other objects depend on it
ALTER TABLE t_identity_drop ALTER COLUMN b DROP IDENTITY;

subtest comma_syntax

statement ok
CREATE TABLE foo (i int);

skipif config local-legacy-schema-changer
statement ok
ALTER TABLE foo DROP COLUMN i, ADD COLUMN i bool;

skipif config local-legacy-schema-changer
statement error pgcode 42703 pq: column "i" does not exist
ALTER TABLE foo DROP COLUMN i, DROP COLUMN i;

subtest end

subtest alter_primary_key_using_dropped_column

statement ok
CREATE TABLE foo_bar (i int unique not null, j int);

skipif config local-legacy-schema-changer
statement error pgcode 55000 pq: column "i" is being dropped
ALTER TABLE foo_bar DROP COLUMN i, ALTER PRIMARY KEY USING COLUMNS (i);

subtest end

subtest alter_add_foreign_key_against_computed_column

statement ok
CREATE TABLE x (a int8 not null primary key, computed_col int8 null as (a) stored);

statement ok
CREATE TABLE y (a int8 not null primary key, computed_col int8 null as (a) stored);

statement ok
INSERT INTO x VALUES (0),(1),(2),(3),(4);

statement ok
INSERT INTO y VALUES (0),(1),(2);

query II rowsort
SELECT a,computed_col from y;
----
0 0
1 1
2 2

statement ok
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x;

statement error .*delete on table "x" violates foreign key constraint.*
DELETE FROM x WHERE A IN (0,2,4);

statement ok
ALTER TABLE y DROP CONSTRAINT y_computed_col_fkey;

statement ok
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON DELETE CASCADE;

statement ok
DELETE FROM x WHERE A IN (0,2);

query II rowsort
SELECT a,computed_col from y;
----
1 1

statement error pq: invalid ON UPDATE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON UPDATE CASCADE;

statement error pq: invalid ON UPDATE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON UPDATE CASCADE;

statement error pq: invalid ON UPDATE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON UPDATE SET DEFAULT;

statement error pq: invalid ON UPDATE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON UPDATE SET NULL;

statement error pq: invalid ON UPDATE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON UPDATE SET NULL ON DELETE SET DEFAULT;

statement error pq: invalid ON DELETE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON DELETE SET DEFAULT;

statement error pq: invalid ON DELETE action for foreign key constraint containing computed column
ALTER TABLE y ADD FOREIGN KEY (computed_col) REFERENCES x ON DELETE SET NULL;

statement ok
DROP TABLE y CASCADE;

statement ok
DROP TABLE x CASCADE;

subtest end

subtest add_default_empty_array

statement ok
CREATE TABLE t_114316 (i INT PRIMARY KEY)

statement ok
ALTER TABLE t_114316 ADD COLUMN a INT[] DEFAULT ARRAY[]::OID[]

query T
SELECT create_statement FROM [SHOW CREATE TABLE t_114316];
----
CREATE TABLE public.t_114316 (
  i INT8 NOT NULL,
  a INT8[] NULL DEFAULT ARRAY[]:::OID[],
  CONSTRAINT t_114316_pkey PRIMARY KEY (i ASC)
)

subtest end

subtest regression_test_alter_table_add_constraint_unique

statement ok
create table t_124546(a int);

# Regression Test for https://github.com/cockroachdb/cockroach/issues/124546
statement error pgcode 42601 variable sub-expressions are not allowed in EXPRESSION INDEX ELEMENT
ALTER TABLE t_124546 ADD CONSTRAINT ident UNIQUE ( ( EXISTS ( TABLE error FOR READ ONLY ) ) DESC ) STORING ( ident , ident );

subtest end

subtest alter_table_add_column_serial

statement ok
create table roach (id int);
insert into roach DEFAULT VALUES;
insert into roach DEFAULT VALUES;
SET serial_normalization = rowid

statement ok
alter table roach add column serial_id SERIAL;

query TTBTTTB colnames,rowsort
show columns from roach;
----
column_name  data_type  is_nullable  column_default  generation_expression  indices       is_hidden
id           INT8       true         NULL            ·                      {roach_pkey}  false
rowid        INT8       false        unique_rowid()  ·                      {roach_pkey}  true
serial_id    INT8       false        unique_rowid()  ·                      {roach_pkey}  false

subtest end

subtest unimplemented_for_non_rowid_in_DSC

statement ok
SET serial_normalization = sql_sequence

statement error .*nextval\(\): unimplemented: cannot evaluate scalar expressions containing sequence operations in this context.*
alter table roach add column serial_id2 SERIAL

subtest end

statement ok
set use_declarative_schema_changer = on

# Tests for #131948 where we incorrectly backfilled empty column
# families for composite datums.
subtest composite_type_131948

statement ok
CREATE TABLE t1_with_composite(i int, j STRING COLLATE de_DE NOT NULL, family(i), family(j));
INSERT INTO t1_with_composite VALUES(1, 'a');
INSERT INTO t1_with_composite VALUES(2, 'b');

statement ok
ALTER TABLE t1_with_composite DROP COLUMN j;

query I
SELECT * FROM t1_with_composite ORDER BY i ASC;
----
1
2

subtest end

subtest sanity_test_pk_with_composite_columns

# Sanity testing for single table column families with composite types.
statement ok
CREATE TABLE tbl_with_dft_column_family(f float NOT NULL, d decimal NOT NULL, j json NOT NULL, s STRING COLLATE de_DE NOT NULL, family(f), family(d), family(j), family(s))

statement ok
INSERT INTO tbl_with_dft_column_family VALUES(1.0, 1.0, '{"cat": "mouse"}', 'abc');
INSERT INTO tbl_with_dft_column_family VALUES(2.0, 2.0, '{"lion": "gazelle"}', 'def');
INSERT INTO tbl_with_dft_column_family VALUES(3.0, 3.0, '{"wolf": "sheep"}', 'ghi');

query FFTT
SELECT f, d, j, s FROM tbl_with_dft_column_family ORDER BY 1
----
1  1.0  {"cat": "mouse"}     abc
2  2.0  {"lion": "gazelle"}  def
3  3.0  {"wolf": "sheep"}    ghi

statement ok
ALTER TABLE tbl_with_dft_column_family ALTER PRIMARY KEY USING COLUMNS (f);

query FFTT
SELECT * FROM tbl_with_dft_column_family ORDER BY 1
----
1  1.0  {"cat": "mouse"}     abc
2  2.0  {"lion": "gazelle"}  def
3  3.0  {"wolf": "sheep"}    ghi

statement ok
ALTER TABLE tbl_with_dft_column_family ALTER PRIMARY KEY USING COLUMNS (d);

query FFTT
SELECT * FROM tbl_with_dft_column_family ORDER BY 1
----
1  1.0  {"cat": "mouse"}     abc
2  2.0  {"lion": "gazelle"}  def
3  3.0  {"wolf": "sheep"}    ghi

statement ok
ALTER TABLE tbl_with_dft_column_family ALTER PRIMARY KEY USING COLUMNS (j);

query FFTT
SELECT * FROM tbl_with_dft_column_family ORDER BY 1
----
1  1.0  {"cat": "mouse"}     abc
2  2.0  {"lion": "gazelle"}  def
3  3.0  {"wolf": "sheep"}    ghi

statement ok
ALTER TABLE tbl_with_dft_column_family ALTER PRIMARY KEY USING COLUMNS (s);

query FFTT
SELECT * FROM tbl_with_dft_column_family ORDER BY 1
----
1  1.0  {"cat": "mouse"}     abc
2  2.0  {"lion": "gazelle"}  def
3  3.0  {"wolf": "sheep"}    ghi

subtest alter_dropped_col

# Force DSC always so that we use it within a transaction
let $schema_changer_state
SELECT value FROM information_schema.session_variables where variable='use_declarative_schema_changer'

skipif config local-legacy-schema-changer
statement ok
set use_declarative_schema_changer = 'unsafe_always';

statement ok
create table t_droppedcol (dropme int);

statement ok
begin;

statement ok
alter table t_droppedcol drop column dropme;

skipif config local-legacy-schema-changer
statement error pq: column "dropme" does not exist
alter table t_droppedcol alter column dropme set not null;

onlyif config local-legacy-schema-changer
statement error pq: column "dropme" in the middle of being dropped
alter table t_droppedcol alter column dropme set not null;

statement ok
rollback;

statement ok
begin;

statement ok
alter table t_droppedcol drop column dropme;

skipif config local-legacy-schema-changer
statement error pq: column "dropme" does not exist
alter table t_droppedcol alter column dropme set default 99;

onlyif config local-legacy-schema-changer
statement error pq: column "dropme" in the middle of being dropped
alter table t_droppedcol alter column dropme set default 99;

statement ok
rollback;

query TT
SHOW CREATE TABLE t_droppedcol;
----
t_droppedcol CREATE TABLE public.t_droppedcol (
               dropme INT8 NULL,
               rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
               CONSTRAINT t_droppedcol_pkey PRIMARY KEY (rowid ASC)
             )

statement ok
DROP TABLE t_droppedcol;

# Restore the schema changer state back.
statement ok
SET use_declarative_schema_changer = $schema_changer_state

subtest end


subtest validate_not_null_during_sc

statement error pgcode 23514 pq: failed to satisfy CHECK constraint \(n IS NOT NULL\)
BEGIN;
create table t1_135692(n int);
alter table t1_135692 alter column n set not null;
insert into t1_135692 values (null);

statement ok
ROLLBACK;

subtest end


subtest serial_columns

statement ok
create table t1_serial_columns(n int);

statement ok
SET serial_normalization = sql_sequence;

# add multiple serial columns
statement ok
alter table t1_serial_columns add column i serial, add column j serial, add column k serial;

# test other serialization modes
skipif config local-read-committed
skipif config local-repeatable-read
statement ok
SET serial_normalization = sql_sequence_cached;
alter table t1_serial_columns add column i_cache serial;

skipif config local-read-committed
skipif config local-repeatable-read
statement ok
SET serial_normalization = virtual_sequence;
alter table t1_serial_columns add column i_virtual serial;

skipif config local-read-committed
skipif config local-repeatable-read
statement ok
SET serial_normalization = sql_sequence_cached_node;
alter table t1_serial_columns add column i_node_cache serial;

skipif config local-read-committed
skipif config local-repeatable-read
statement ok
SET serial_normalization = unordered_rowid;
alter table t1_serial_columns add column i_unordered_rowid serial;

statement ok
SET serial_normalization = sql_sequence;

skipif config local-read-committed
skipif config local-repeatable-read
statement ok
BEGIN;
CREATE SEQUENCE t1_serial_columns_z_seq;
alter table t1_serial_columns add column z serial;
alter table t1_serial_columns add column l serial;
COMMIT;

skipif config local-read-committed
skipif config local-repeatable-read
query T
SELECT create_statement FROM crdb_internal.create_statements WHERE descriptor_name like 't1_serial_columns%' ORDER BY descriptor_name;
----
CREATE TABLE public.t1_serial_columns (
  n INT8 NULL,
  rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
  i INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_i_seq'::REGCLASS),
  j INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_j_seq'::REGCLASS),
  k INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_k_seq'::REGCLASS),
  i_cache INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_i_cache_seq'::REGCLASS),
  i_virtual INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_i_virtual_seq'::REGCLASS),
  i_node_cache INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_i_node_cache_seq'::REGCLASS),
  i_unordered_rowid INT8 NOT NULL DEFAULT unordered_unique_rowid(),
  z INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_z_seq1'::REGCLASS),
  l INT8 NOT NULL DEFAULT nextval('public.t1_serial_columns_l_seq'::REGCLASS),
  CONSTRAINT t1_serial_columns_pkey PRIMARY KEY (rowid ASC)
)
CREATE SEQUENCE public.t1_serial_columns_i_cache_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 CACHE 256
CREATE SEQUENCE public.t1_serial_columns_i_node_cache_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 PER NODE CACHE 256
CREATE SEQUENCE public.t1_serial_columns_i_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1
CREATE SEQUENCE public.t1_serial_columns_i_virtual_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1 VIRTUAL
CREATE SEQUENCE public.t1_serial_columns_j_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1
CREATE SEQUENCE public.t1_serial_columns_k_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1
CREATE SEQUENCE public.t1_serial_columns_l_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1
CREATE SEQUENCE public.t1_serial_columns_z_seq MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1
CREATE SEQUENCE public.t1_serial_columns_z_seq1 MINVALUE 1 MAXVALUE 9223372036854775807 INCREMENT 1 START 1

# Regression tests for issue #137326. Add column with IF NOT EXIST.
subtest add_col_if_not_exists

statement ok
CREATE TABLE t1_add ();

statement ok
ALTER TABLE t1_add ADD COLUMN c1 BIGINT;

statement ok
INSERT INTO t1_add VALUES (100);

statement error pgcode 42601 pq: variable sub-expressions are not allowed in ON UPDATE
ALTER TABLE t1_add ADD COLUMN IF NOT EXISTS c1 TEXT ON UPDATE EXISTS ( TABLE error );

statement ok
ALTER TABLE t1_add ADD COLUMN IF NOT EXISTS c1 TEXT ON UPDATE 10;

query TT
SHOW CREATE TABLE t1_add
----
t1_add  CREATE TABLE public.t1_add (
          rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
          c1 INT8 NULL,
          CONSTRAINT t1_add_pkey PRIMARY KEY (rowid ASC)
        )

let $use_decl_sc
SHOW use_declarative_schema_changer

statement ok
set use_declarative_schema_changer = 'unsafe_always';

statement ok;
BEGIN;
ALTER TABLE t1_add DROP COLUMN c1;
ALTER TABLE t1_add ADD COLUMN IF NOT EXISTS c1 date DEFAULT '2024-08-31';
COMMIT;

query T
SELECT c1 FROM t1_add
----
2024-08-31 00:00:00 +0000 +0000

query TT
SHOW CREATE TABLE t1_add
----
t1_add  CREATE TABLE public.t1_add (
          rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
          c1 DATE NULL DEFAULT '2024-08-31':::DATE,
          CONSTRAINT t1_add_pkey PRIMARY KEY (rowid ASC)
        )

statement ok
DROP TABLE t1_add

statement ok
SET use_declarative_schema_changer = $use_decl_sc;

subtest end
