# Test that sequences are encoded and decoded/printed properly.
subtest show_sequences

statement ok
SET serial_normalization = 'sql_sequence'

statement ok
CREATE SEQUENCE test_seq

statement ok
CREATE DATABASE diff_db

statement ok
CREATE SEQUENCE diff_db.test_seq

let $test_seq_id
SELECT 'test_seq'::regclass::int

statement ok
CREATE TABLE foo (i SERIAL PRIMARY KEY)

statement ok
ALTER TABLE foo ADD COLUMN j INT NOT NULL DEFAULT nextval($test_seq_id)

statement ok
ALTER TABLE foo ADD COLUMN k SERIAL

statement ok
ALTER TABLE foo ADD COLUMN l INT NOT NULL

statement error pq: sequence references cannot come from other databases; \(see the 'sql\.cross_db_sequence_references\.enabled' cluster setting\)
ALTER TABLE FOO ALTER COLUMN l SET DEFAULT currval('diff_db.test_seq')

statement ok
SET CLUSTER SETTING sql.cross_db_sequence_references.enabled = TRUE

statement ok
ALTER TABLE FOO ALTER COLUMN l SET DEFAULT currval('diff_db.test_seq')

statement ok
SELECT nextval('diff_db.test_seq')

query TT
SHOW CREATE TABLE foo
----
foo  CREATE TABLE public.foo (
       i INT8 NOT NULL DEFAULT nextval('public.foo_i_seq'::REGCLASS),
       j INT8 NOT NULL DEFAULT nextval('public.test_seq'::REGCLASS),
       k INT8 NOT NULL DEFAULT nextval('public.foo_k_seq'::REGCLASS),
       l INT8 NOT NULL DEFAULT currval('diff_db.public.test_seq'::REGCLASS),
       CONSTRAINT foo_pkey PRIMARY KEY (i ASC)
     )

statement ok
INSERT INTO foo VALUES (default, default, default, default)


# Test that references are still correctly created for
# sequences referenced via their IDs.
subtest sequence_references

statement ok
SET serial_normalization = 'sql_sequence'

statement ok
CREATE SEQUENCE dep_seq

statement ok
CREATE SEQUENCE dep_seq2

let $dep_seq_id
SELECT 'dep_seq'::regclass::int

statement ok
CREATE TABLE seq_table (
  i SERIAL PRIMARY KEY,
  j INT NOT NULL DEFAULT nextval($dep_seq_id::regclass),
  k INT NOT NULL DEFAULT nextval('dep_seq2'))

query TTT
SELECT pg_get_serial_sequence('seq_table', 'i'), pg_get_serial_sequence('seq_table', 'j'), pg_get_serial_sequence('seq_table', 'k')
----
public.seq_table_i_seq  public.dep_seq  public.dep_seq2

statement error cannot drop sequence seq_table_i_seq because other objects depend on it
DROP SEQUENCE seq_table_i_seq

statement error cannot drop sequence dep_seq because other objects depend on it
DROP SEQUENCE dep_seq

statement error cannot drop sequence dep_seq2 because other objects depend on it
DROP SEQUENCE dep_seq2


# Test that all new sequences can now be renamed, even if they are
# referenced using their names (since they're converted to IDs now).
subtest sequence_renames

statement ok
SET serial_normalization = 'sql_sequence'

statement ok
CREATE SEQUENCE s1

let $s1_id
SELECT 's1'::regclass::int

statement ok
CREATE SEQUENCE s2

statement ok
CREATE TABLE bar (
  i SERIAL PRIMARY KEY,
  j INT NOT NULL DEFAULT currval($s1_id),
  k INT NOT NULL DEFAULT nextval('s2'),
  FAMILY (i, j, k))

statement ok
SELECT nextval($s1_id::regclass)

statement ok
INSERT INTO bar VALUES (default, default, default)

statement ok
ALTER SEQUENCE bar_i_seq RENAME TO new_bar_i_seq

statement ok
ALTER SEQUENCE s1 RENAME TO new_s1

statement ok
ALTER SEQUENCE s2 RENAME TO new_s2

# Verify that the sequence rename is reflected.
query TT
SHOW CREATE TABLE bar
----
bar  CREATE TABLE public.bar (
       i INT8 NOT NULL DEFAULT nextval('public.new_bar_i_seq'::REGCLASS),
       j INT8 NOT NULL DEFAULT currval('public.new_s1'::REGCLASS),
       k INT8 NOT NULL DEFAULT nextval('public.new_s2'::REGCLASS),
       CONSTRAINT bar_pkey PRIMARY KEY (i ASC),
       FAMILY fam_0_i_j_k (i, j, k)
     )

# Verify that the table hasn't been corrupted.
statement ok
INSERT INTO bar VALUES (default, default, default)

query III
SELECT i, j, k FROM bar ORDER BY i, j, k
----
1  1  1
2  1  2


# Test that databases with sequences can be renamed, even if they are
# referenced by name in a sequence (since we are now storing them as IDs).
subtest database_renames

statement ok
SET serial_normalization = 'sql_sequence'

statement ok
CREATE DATABASE other_db

statement ok
CREATE SEQUENCE other_db.s

let $s_id
SELECT 'other_db.s'::regclass::int

statement ok
CREATE SEQUENCE other_db.s2

statement ok
CREATE TABLE other_db.t (
  i INT NOT NULL DEFAULT nextval($s_id),
  j INT NOT NULL DEFAULT currval('other_db.public.s2'),
  FAMILY (i, j))

statement ok
SELECT nextval('other_db.public.s2')

statement ok
INSERT INTO other_db.t VALUES (default, default)

statement ok
ALTER DATABASE other_db RENAME TO new_other_db

# Verify that the database rename is reflected.
query TT
SHOW CREATE TABLE new_other_db.t
----
new_other_db.public.t  CREATE TABLE public.t (
                         i INT8 NOT NULL DEFAULT nextval('new_other_db.public.s'::REGCLASS),
                         j INT8 NOT NULL DEFAULT currval('new_other_db.public.s2'::REGCLASS),
                         rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
                         CONSTRAINT t_pkey PRIMARY KEY (rowid ASC),
                         FAMILY fam_0_i_j_rowid (i, j, rowid)
                       )

# Verify the table hasn't been corrupted.
statement ok
INSERT INTO new_other_db.public.t VALUES (default, default)

query II
SELECT i, j FROM new_other_db.t ORDER BY i, j
----
1  1
2  1


# Test that sequences can change schemas even if they're referenced
# by name and that name contains the schema.
subtest alter_sequence_schema

statement ok
SET serial_normalization = 'sql_sequence'

statement ok
CREATE SEQUENCE sc_s1

let $sc_s1_id
SELECT 'sc_s1'::regclass::int

statement ok
CREATE SEQUENCE sc_s2

statement ok
CREATE SCHEMA test_schema

statement ok
CREATE TABLE tb (
  i SERIAL PRIMARY KEY,
  j INT NOT NULL DEFAULT nextval($sc_s1_id),
  k INT NOT NULL DEFAULT currval('test.public.sc_s2'),
  FAMILY (i, j, k))

statement ok
SELECT nextval('test.public.sc_s2')

statement ok
INSERT INTO tb VALUES (default, default, default)

statement ok
ALTER SEQUENCE tb_i_seq SET SCHEMA test_schema

statement ok
ALTER SEQUENCE sc_s1 SET SCHEMA test_schema

statement ok
ALTER SEQUENCE sc_s2 SET SCHEMA test_schema

# Verify that the schema change is reflected.
query TT
SHOW CREATE TABLE tb
----
tb  CREATE TABLE public.tb (
      i INT8 NOT NULL DEFAULT nextval('test_schema.tb_i_seq'::REGCLASS),
      j INT8 NOT NULL DEFAULT nextval('test_schema.sc_s1'::REGCLASS),
      k INT8 NOT NULL DEFAULT currval('test_schema.sc_s2'::REGCLASS),
      CONSTRAINT tb_pkey PRIMARY KEY (i ASC),
      FAMILY fam_0_i_j_k (i, j, k)
    )

# Verify the table hasn't been corrupted.
statement ok
INSERT INTO tb VALUES (default, default, default)

query III
SELECT i, j, k FROM tb ORDER BY i, j, k
----
1  1  1
2  2  1


# Test that sequences can have their schemas renamed even if
# they're referenced by name and that name contains the schema.
subtest rename_sequence_schema

statement ok
SET SCHEMA test_schema

statement ok
CREATE SEQUENCE s3

let $s3_id
SELECT 's3'::regclass::int

statement ok
CREATE SEQUENCE s4

statement ok
CREATE TABLE foo (
  i SERIAL PRIMARY KEY,
  j INT NOT NULL DEFAULT nextval($s3_id),
  k INT NOT NULL DEFAULT currval('test.test_schema.s4'),
  FAMILY (i, j, k))

statement ok
SELECT nextval('test.test_schema.s4')

statement ok
INSERT INTO foo VALUES (default, default, default)

statement ok
ALTER SCHEMA test_schema RENAME to new_test_schema

# Verify that the schema rename is reflected.
query TT
SHOW CREATE TABLE new_test_schema.foo
----
new_test_schema.foo  CREATE TABLE new_test_schema.foo (
                       i INT8 NOT NULL DEFAULT nextval('new_test_schema.foo_i_seq'::REGCLASS),
                       j INT8 NOT NULL DEFAULT nextval('new_test_schema.s3'::REGCLASS),
                       k INT8 NOT NULL DEFAULT currval('new_test_schema.s4'::REGCLASS),
                       CONSTRAINT foo_pkey PRIMARY KEY (i ASC),
                       FAMILY fam_0_i_j_k (i, j, k)
                     )

# Verify the table hasn't been corrupted.
statement ok
INSERT INTO new_test_schema.foo VALUES (default, default, default)

query III
SELECT i, j, k FROM new_test_schema.foo ORDER BY i, j, k
----
1  1  1
2  2  1

statement ok
SET SCHEMA public


# Test that sequences can be accessed regardless of
# the user's current database.
subtest cross_database_sequence

statement ok
SET serial_normalization = 'sql_sequence'

statement ok
CREATE DATABASE other_db

statement ok
CREATE TABLE other_db.t (s SERIAL PRIMARY KEY, i INT)

statement ok
INSERT INTO other_db.t (i) VALUES (1)

statement ok
USE other_db

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

statement ok
USE test


# Test using sequences in a castexpr.
subtest sequence_castexpr

statement ok
CREATE SEQUENCE s5

statement ok
CREATE TABLE t2 (
  i INT NOT NULL DEFAULT nextval('s5'::regclass),
  j INT NOT NULL DEFAULT nextval('s5'::regclass::int::string),
  FAMILY (i, j))

statement ok
ALTER SEQUENCE s5 RENAME TO s5_new

query TT
SHOW CREATE TABLE t2
----
t2  CREATE TABLE public.t2 (
      i INT8 NOT NULL DEFAULT nextval('public.s5_new'::REGCLASS),
      j INT8 NOT NULL DEFAULT nextval('public.s5_new'::REGCLASS),
      rowid INT8 NOT VISIBLE NOT NULL DEFAULT unique_rowid(),
      CONSTRAINT t2_pkey PRIMARY KEY (rowid ASC),
      FAMILY fam_0_i_j_rowid (i, j, rowid)
    )

query TT
SELECT pg_get_serial_sequence('t2', 'i'), pg_get_serial_sequence('t2', 'j')
----
public.s5_new  public.s5_new

statement ok
INSERT INTO t2 VALUES (default, default)


# Test that sequences used in views are encoded
# properly and can be renamed.
subtest view_sequence

statement ok
CREATE TABLE t3 (i INT NOT NULL, j INT NOT NULL)

statement ok
CREATE TABLE t4 (i INT NOT NULL, j INT NOT NULL)

statement ok
CREATE SEQUENCE view_seq

let $view_seq_id
SELECT 'view_seq'::regclass::int

# Basic view.
statement ok
CREATE VIEW v AS (SELECT i, nextval('view_seq') FROM t3)

query TT
SHOW CREATE VIEW v
----
v  CREATE VIEW public.v (
     i,
     nextval
   ) AS (SELECT i, nextval('public.view_seq'::REGCLASS) FROM test.public.t3)

# Subquery in FROM clause.
statement ok
CREATE VIEW v2 AS SELECT currval FROM (SELECT currval('view_seq'::regclass) FROM t3)

query TT
SHOW CREATE VIEW v2
----
v2  CREATE VIEW public.v2 (
      currval
    ) AS SELECT
        currval
      FROM
        (SELECT currval('public.view_seq'::REGCLASS) FROM test.public.t3) AS "?subquery1?"

# Union containing sequences.
statement ok
CREATE VIEW v3 AS SELECT nextval($view_seq_id), i FROM t3 UNION SELECT nextval('view_seq'), i FROM t4

query TT
SHOW CREATE VIEW v3
----
v3  CREATE VIEW public.v3 (
      nextval,
      i
    ) AS SELECT nextval('public.view_seq'::REGCLASS), i FROM test.public.t3
      UNION SELECT nextval('public.view_seq'::REGCLASS), i FROM test.public.t4

statement ok
CREATE VIEW v4 AS SELECT t3.i, nextval('view_seq') FROM t3 INNER JOIN (SELECT j, currval($view_seq_id) FROM t4) as t5 ON t3.i = t5.j

# Join containing sequences.
query TT
SHOW CREATE VIEW v4
----
v4  CREATE VIEW public.v4 (
      i,
      nextval
    ) AS SELECT
        t3.i, nextval('public.view_seq'::REGCLASS)
      FROM
        test.public.t3
        INNER JOIN (SELECT j, currval('public.view_seq'::REGCLASS) FROM test.public.t4) AS t5 ON
            t3.i = t5.j

# Materialized view containing sequences.
statement ok
CREATE MATERIALIZED VIEW v5 AS SELECT currval('view_seq'), i FROM t3

query TT
SHOW CREATE VIEW v5
----
v5  CREATE MATERIALIZED VIEW public.v5 (
      currval,
      i,
      rowid
    ) AS SELECT currval('public.view_seq'::REGCLASS), i FROM test.public.t3

# Replacing an existing view.
statement ok
CREATE view v6 AS SELECT nextval('view_seq') AS i

statement ok
CREATE OR REPLACE VIEW v6 AS SELECT currval($view_seq_id) AS i

query TT
SHOW CREATE VIEW v6
----
v6  CREATE VIEW public.v6 (
      i
    ) AS SELECT currval('public.view_seq'::REGCLASS) AS i

# Subquery in the SELECT expr.
statement ok
CREATE VIEW v7 AS (SELECT i, (SELECT nextval('view_seq')) FROM t3)

query TT
SHOW CREATE VIEW v7
----
v7  CREATE VIEW public.v7 (
      i,
      nextval
    ) AS (SELECT i, (SELECT nextval('public.view_seq'::REGCLASS)) FROM test.public.t3)

# Sequence in the WHERE clause.
statement ok
CREATE VIEW v8 AS SELECT i FROM t3 WHERE i = nextval($view_seq_id)

query TT
SHOW CREATE VIEW v8
----
v8  CREATE VIEW public.v8 (
      i
    ) AS SELECT i FROM test.public.t3 WHERE i = nextval('public.view_seq'::REGCLASS)

# Sequence in the CTE.
statement ok
CREATE VIEW v9 AS (WITH w AS (SELECT nextval('view_seq')) SELECT nextval FROM w)

query TT
SHOW CREATE VIEW v9
----
v9  CREATE VIEW public.v9 (
      nextval
    ) AS (WITH w AS (SELECT nextval('public.view_seq'::REGCLASS)) SELECT nextval FROM w)

# Sequence in the LIMIT clause.
statement ok
CREATE VIEW v10 AS (SELECT i FROM t3 LIMIT nextval('view_seq'))

query TT
SHOW CREATE VIEW v10
----
v10  CREATE VIEW public.v10 (
       i
     ) AS (SELECT i FROM test.public.t3 LIMIT nextval('public.view_seq'::REGCLASS))

# Test renaming sequences is fine and tables are not corrupted.
statement ok
ALTER SEQUENCE view_seq RENAME TO view_seq2

query TT
SHOW CREATE VIEW v7
----
v7  CREATE VIEW public.v7 (
      i,
      nextval
    ) AS (SELECT i, (SELECT nextval('public.view_seq2'::REGCLASS)) FROM test.public.t3)

statement ok
INSERT INTO t3 VALUES (8, 2)

statement ok
INSERT INTO t4 VALUES (35, 6)

query II
SELECT * FROM v
----
8  1

query II
SELECT * FROM v3 ORDER BY nextval
----
2  8
3  35
