SET client_min_messages TO WARNING;
CREATE EXTENSION IF NOT EXISTS citus_columnar;
RESET client_min_messages;
CREATE SCHEMA alter_distributed_table;
SET search_path TO alter_distributed_table;
SET citus.shard_count TO 4;
SET citus.shard_replication_factor TO 1;
CREATE TABLE dist_table (a INT, b INT);
SELECT create_distributed_table ('dist_table', 'a', colocate_with := 'none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO dist_table VALUES (1, 1), (2, 2), (3, 3);
CREATE TABLE colocation_table (a INT, b INT);
SELECT create_distributed_table ('colocation_table', 'a', colocate_with := 'none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE colocation_table_2 (a INT, b INT);
SELECT create_distributed_table ('colocation_table_2', 'a', colocate_with := 'none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2');
     table_name     | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 colocation_table   | distributed      | a                   |           4
 colocation_table_2 | distributed      | a                   |           4
 dist_table         | distributed      | a                   |           4
(3 rows)

SELECT STRING_AGG(table_name::text, ', ' ORDER BY 1) AS "Colocation Groups" FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2') GROUP BY colocation_id ORDER BY 1;
 Colocation Groups
---------------------------------------------------------------------
 colocation_table
 colocation_table_2
 dist_table
(3 rows)

-- test altering distribution column
SELECT alter_distributed_table('dist_table', distribution_column := 'b');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2');
     table_name     | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 colocation_table   | distributed      | a                   |           4
 colocation_table_2 | distributed      | a                   |           4
 dist_table         | distributed      | b                   |           4
(3 rows)

SELECT STRING_AGG(table_name::text, ', ' ORDER BY 1) AS "Colocation Groups" FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2') GROUP BY colocation_id ORDER BY 1;
 Colocation Groups
---------------------------------------------------------------------
 colocation_table
 colocation_table_2
 dist_table
(3 rows)

-- test altering shard count
SELECT alter_distributed_table('dist_table', shard_count := 6);
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2');
     table_name     | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 colocation_table   | distributed      | a                   |           4
 colocation_table_2 | distributed      | a                   |           4
 dist_table         | distributed      | b                   |           6
(3 rows)

SELECT STRING_AGG(table_name::text, ', ' ORDER BY 1) AS "Colocation Groups" FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2') GROUP BY colocation_id ORDER BY 1;
 Colocation Groups
---------------------------------------------------------------------
 colocation_table
 colocation_table_2
 dist_table
(3 rows)

-- right now dist_table has columns a, b, dist_column is b, it has 6 shards
-- column cache is: a pos 1, b pos 2
-- let's add another column
ALTER TABLE dist_table ADD COLUMN c int DEFAULT 1;
-- right now column cache is: a pos 1, b pos 2, c pos 3
-- test using alter_distributed_table to change shard count after dropping one column
ALTER TABLE dist_table DROP COLUMN a;
-- right now column cache is: a pos 1 attisdropped=true, b pos 2, c pos 3
-- let's try changing the shard count
SELECT alter_distributed_table('dist_table', shard_count := 7, cascade_to_colocated := false);
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- right now column cache is: b pos 1, c pos 2 because a new table has been created
-- check that b is still distribution column
SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name = 'dist_table'::regclass;
 table_name | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 dist_table | distributed      | b                   |           7
(1 row)

-- let's add another column
ALTER TABLE dist_table ADD COLUMN d int DEFAULT 2;
-- right now column cache is: b pos 1, c pos 2, d pos 3, dist_column is b
-- test using alter_distributed_table to change dist. column after dropping one column
ALTER TABLE dist_table DROP COLUMN c;
-- right now column cache is: b pos 1, c pos 2 attisdropped=true, d pos 3
-- let's try changing the distribution column
SELECT alter_distributed_table('dist_table', distribution_column := 'd');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- right now column cache is: b pos 1, d pos 2 because a new table has been created
-- check that d is the distribution column
SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name = 'dist_table'::regclass;
 table_name | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 dist_table | distributed      | d                   |           7
(1 row)

-- add another column and undistribute
ALTER TABLE dist_table ADD COLUMN e int DEFAULT 3;
SELECT undistribute_table('dist_table');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 undistribute_table
---------------------------------------------------------------------

(1 row)

-- right now column cache is: b pos 1, d pos 2, e pos 3, table is not Citus table
-- try dropping column and then distributing
ALTER TABLE dist_table DROP COLUMN b;
-- right now column cache is: b pos 1 attisdropped=true, d pos 2, e pos 3
-- distribute with d
SELECT create_distributed_table ('dist_table', 'd', colocate_with := 'none');
NOTICE:  Copying data from local table...
NOTICE:  copying the data has completed
DETAIL:  The local data in the table is no longer visible, but is still on disk.
HINT:  To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$alter_distributed_table.dist_table$$)
 create_distributed_table
---------------------------------------------------------------------

(1 row)

-- check that d is the distribution column
SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name = 'dist_table'::regclass;
 table_name | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 dist_table | distributed      | d                   |           4
(1 row)

-- alter distribution column to e
SELECT alter_distributed_table('dist_table', distribution_column := 'e');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- right now column cache is: d pos 1, e pos 2
-- check that e is the distribution column
SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name = 'dist_table'::regclass;
 table_name | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 dist_table | distributed      | e                   |           4
(1 row)

ALTER TABLE dist_table ADD COLUMN a int DEFAULT 4;
ALTER TABLE dist_table ADD COLUMN b int DEFAULT 5;
-- right now column cache is: d pos 1, e pos 2, a pos 3, b pos 4
-- alter distribution column to a
SELECT alter_distributed_table('dist_table', distribution_column := 'a');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- right now column cache hasn't changed
-- check that a is the distribution column
SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name = 'dist_table'::regclass;
 table_name | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 dist_table | distributed      | a                   |           4
(1 row)

ALTER TABLE dist_table DROP COLUMN d;
ALTER TABLE dist_table DROP COLUMN e;
-- right now column cache is: d pos 1 attisdropped=true, e pos 2 attisdropped=true, a pos 3, b pos 4
-- alter distribution column to b
SELECT alter_distributed_table('dist_table', distribution_column := 'b');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- column cache is: a pos 1, b pos 2 -> configuration with which we started these drop column tests
-- check that b is the distribution column
SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name = 'dist_table'::regclass;
 table_name | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 dist_table | distributed      | b                   |           4
(1 row)

-- test altering colocation, note that shard count will also change
SELECT alter_distributed_table('dist_table', colocate_with := 'alter_distributed_table.colocation_table');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2');
     table_name     | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 colocation_table   | distributed      | a                   |           4
 colocation_table_2 | distributed      | a                   |           4
 dist_table         | distributed      | b                   |           4
(3 rows)

SELECT STRING_AGG(table_name::text, ', ' ORDER BY 1) AS "Colocation Groups" FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2') GROUP BY colocation_id ORDER BY 1;
      Colocation Groups
---------------------------------------------------------------------
 colocation_table, dist_table
 colocation_table_2
(2 rows)

-- test altering shard count with cascading, note that the colocation will be kept
SELECT alter_distributed_table('dist_table', shard_count := 8, cascade_to_colocated := true);
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
NOTICE:  creating a new table for alter_distributed_table.colocation_table
NOTICE:  moving the data of alter_distributed_table.colocation_table
NOTICE:  dropping the old alter_distributed_table.colocation_table
NOTICE:  renaming the new table to alter_distributed_table.colocation_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2');
     table_name     | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 colocation_table   | distributed      | a                   |           8
 colocation_table_2 | distributed      | a                   |           4
 dist_table         | distributed      | b                   |           8
(3 rows)

SELECT STRING_AGG(table_name::text, ', ' ORDER BY 1) AS "Colocation Groups" FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2') GROUP BY colocation_id ORDER BY 1;
      Colocation Groups
---------------------------------------------------------------------
 colocation_table, dist_table
 colocation_table_2
(2 rows)

-- test altering shard count without cascading, note that the colocation will be broken
SELECT alter_distributed_table('dist_table', shard_count := 10, cascade_to_colocated := false);
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2');
     table_name     | citus_table_type | distribution_column | shard_count
---------------------------------------------------------------------
 colocation_table   | distributed      | a                   |           8
 colocation_table_2 | distributed      | a                   |           4
 dist_table         | distributed      | b                   |          10
(3 rows)

SELECT STRING_AGG(table_name::text, ', ' ORDER BY 1) AS "Colocation Groups" FROM public.citus_tables
    WHERE table_name IN ('dist_table', 'colocation_table', 'colocation_table_2') GROUP BY colocation_id ORDER BY 1;
 Colocation Groups
---------------------------------------------------------------------
 colocation_table
 colocation_table_2
 dist_table
(3 rows)

-- test partitions
CREATE TABLE partitioned_table (id INT, a INT) PARTITION BY RANGE (id);
SELECT create_distributed_table('partitioned_table', 'id', colocate_with := 'none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE partitioned_table_1_5 PARTITION OF partitioned_table FOR VALUES FROM (1) TO (5);
CREATE TABLE partitioned_table_6_10 PARTITION OF partitioned_table FOR VALUES FROM (6) TO (10);
INSERT INTO partitioned_table VALUES (2, 12), (7, 2);
SELECT logicalrelid::text FROM pg_dist_partition WHERE logicalrelid::regclass::text LIKE 'partitioned\_table%' ORDER BY 1;
      logicalrelid
---------------------------------------------------------------------
 partitioned_table
 partitioned_table_1_5
 partitioned_table_6_10
(3 rows)

SELECT run_command_on_workers($$SELECT COUNT(*) FROM pg_catalog.pg_class WHERE relname LIKE 'partitioned\_table%'$$);
 run_command_on_workers
---------------------------------------------------------------------
 (localhost,57637,t,9)
 (localhost,57638,t,9)
(2 rows)

SELECT inhrelid::regclass::text FROM pg_catalog.pg_inherits WHERE inhparent = 'partitioned_table'::regclass ORDER BY 1;
        inhrelid
---------------------------------------------------------------------
 partitioned_table_1_5
 partitioned_table_6_10
(2 rows)

SELECT table_name::text, distribution_column, shard_count FROM public.citus_tables WHERE table_name::text LIKE 'partitioned\_table%' ORDER BY 1;
       table_name       | distribution_column | shard_count
---------------------------------------------------------------------
 partitioned_table      | id                  |           4
 partitioned_table_1_5  | id                  |           4
 partitioned_table_6_10 | id                  |           4
(3 rows)

SELECT * FROM partitioned_table ORDER BY 1, 2;
 id | a
---------------------------------------------------------------------
  2 | 12
  7 |  2
(2 rows)

SELECT * FROM partitioned_table_1_5 ORDER BY 1, 2;
 id | a
---------------------------------------------------------------------
  2 | 12
(1 row)

SELECT * FROM partitioned_table_6_10 ORDER BY 1, 2;
 id | a
---------------------------------------------------------------------
  7 | 2
(1 row)

-- test altering the parent table
SELECT alter_distributed_table('partitioned_table', shard_count := 10, distribution_column := 'a');
NOTICE:  converting the partitions of alter_distributed_table.partitioned_table
NOTICE:  creating a new table for alter_distributed_table.partitioned_table_1_5
NOTICE:  moving the data of alter_distributed_table.partitioned_table_1_5
NOTICE:  dropping the old alter_distributed_table.partitioned_table_1_5
NOTICE:  renaming the new table to alter_distributed_table.partitioned_table_1_5
NOTICE:  creating a new table for alter_distributed_table.partitioned_table_6_10
NOTICE:  moving the data of alter_distributed_table.partitioned_table_6_10
NOTICE:  dropping the old alter_distributed_table.partitioned_table_6_10
NOTICE:  renaming the new table to alter_distributed_table.partitioned_table_6_10
NOTICE:  creating a new table for alter_distributed_table.partitioned_table
NOTICE:  dropping the old alter_distributed_table.partitioned_table
NOTICE:  renaming the new table to alter_distributed_table.partitioned_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- test altering the partition
SELECT alter_distributed_table('partitioned_table_1_5', shard_count := 10, distribution_column := 'a');
ERROR:  cannot complete operation because table is a partition
HINT:  the parent table is "partitioned_table"
SELECT logicalrelid::text FROM pg_dist_partition WHERE logicalrelid::regclass::text LIKE 'partitioned\_table%' ORDER BY 1;
      logicalrelid
---------------------------------------------------------------------
 partitioned_table
 partitioned_table_1_5
 partitioned_table_6_10
(3 rows)

SELECT run_command_on_workers($$SELECT COUNT(*) FROM pg_catalog.pg_class WHERE relname LIKE 'partitioned\_table%'$$);
 run_command_on_workers
---------------------------------------------------------------------
 (localhost,57637,t,18)
 (localhost,57638,t,18)
(2 rows)

SELECT inhrelid::regclass::text FROM pg_catalog.pg_inherits WHERE inhparent = 'partitioned_table'::regclass ORDER BY 1;
        inhrelid
---------------------------------------------------------------------
 partitioned_table_1_5
 partitioned_table_6_10
(2 rows)

SELECT table_name::text, distribution_column, shard_count FROM public.citus_tables WHERE table_name::text LIKE 'partitioned\_table%' ORDER BY 1;
       table_name       | distribution_column | shard_count
---------------------------------------------------------------------
 partitioned_table      | a                   |          10
 partitioned_table_1_5  | a                   |          10
 partitioned_table_6_10 | a                   |          10
(3 rows)

SELECT * FROM partitioned_table ORDER BY 1, 2;
 id | a
---------------------------------------------------------------------
  2 | 12
  7 |  2
(2 rows)

SELECT * FROM partitioned_table_1_5 ORDER BY 1, 2;
 id | a
---------------------------------------------------------------------
  2 | 12
(1 row)

SELECT * FROM partitioned_table_6_10 ORDER BY 1, 2;
 id | a
---------------------------------------------------------------------
  7 | 2
(1 row)

-- test altering partitioned table colocate_with:none
CREATE TABLE foo (x int, y int, t timestamptz default now()) PARTITION BY RANGE (t);
CREATE TABLE foo_1 PARTITION of foo for VALUES FROM ('2022-01-01') TO ('2022-12-31');
CREATE TABLE foo_2 PARTITION of foo for VALUES FROM ('2023-01-01') TO ('2023-12-31');
SELECT create_distributed_table('foo','x');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE foo_bar (x int, y int, t timestamptz default now()) PARTITION BY RANGE (t);
CREATE TABLE foo_bar_1 PARTITION of foo_bar for VALUES FROM ('2022-01-01') TO ('2022-12-31');
CREATE TABLE foo_bar_2 PARTITION of foo_bar for VALUES FROM ('2023-01-01') TO ('2023-12-31');
SELECT create_distributed_table('foo_bar','x');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT COUNT(DISTINCT colocationid) FROM pg_dist_partition WHERE logicalrelid::regclass::text in ('foo', 'foo_1', 'foo_2', 'foo_bar', 'foo_bar_1', 'foo_bar_2');
 count
---------------------------------------------------------------------
     1
(1 row)

SELECT alter_distributed_table('foo', colocate_with => 'none');
NOTICE:  converting the partitions of alter_distributed_table.foo
NOTICE:  creating a new table for alter_distributed_table.foo_1
NOTICE:  moving the data of alter_distributed_table.foo_1
NOTICE:  dropping the old alter_distributed_table.foo_1
NOTICE:  renaming the new table to alter_distributed_table.foo_1
NOTICE:  creating a new table for alter_distributed_table.foo_2
NOTICE:  moving the data of alter_distributed_table.foo_2
NOTICE:  dropping the old alter_distributed_table.foo_2
NOTICE:  renaming the new table to alter_distributed_table.foo_2
NOTICE:  creating a new table for alter_distributed_table.foo
NOTICE:  dropping the old alter_distributed_table.foo
NOTICE:  renaming the new table to alter_distributed_table.foo
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT COUNT(DISTINCT colocationid) FROM pg_dist_partition WHERE logicalrelid::regclass::text in ('foo', 'foo_1', 'foo_2', 'foo_bar', 'foo_bar_1', 'foo_bar_2');
 count
---------------------------------------------------------------------
     2
(1 row)

-- test references
CREATE TABLE referenced_dist_table (a INT UNIQUE);
CREATE TABLE referenced_ref_table (a INT UNIQUE);
CREATE TABLE table_with_references (a1 INT UNIQUE, a2 INT);
CREATE TABLE referencing_dist_table (a INT);
SELECT create_distributed_table('referenced_dist_table', 'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_reference_table('referenced_ref_table');
 create_reference_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('table_with_references', 'a1', colocate_with:='referenced_dist_table');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('referencing_dist_table', 'a', colocate_with:='referenced_dist_table');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

ALTER TABLE table_with_references ADD FOREIGN KEY (a1) REFERENCES referenced_dist_table(a);
ALTER TABLE table_with_references ADD FOREIGN KEY (a2) REFERENCES referenced_ref_table(a);
ALTER TABLE referencing_dist_table ADD FOREIGN KEY (a) REFERENCES table_with_references(a1);
SET client_min_messages TO WARNING;
SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM  pg_constraint
    WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1,2;
   Referencing Table    |                      Definition
---------------------------------------------------------------------
 referencing_dist_table | FOREIGN KEY (a) REFERENCES table_with_references(a1)
 table_with_references  | FOREIGN KEY (a1) REFERENCES referenced_dist_table(a)
 table_with_references  | FOREIGN KEY (a2) REFERENCES referenced_ref_table(a)
(3 rows)

SELECT alter_distributed_table('table_with_references', shard_count := 12, cascade_to_colocated := true);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM  pg_constraint
    WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1,2;
   Referencing Table    |                      Definition
---------------------------------------------------------------------
 referencing_dist_table | FOREIGN KEY (a) REFERENCES table_with_references(a1)
 table_with_references  | FOREIGN KEY (a1) REFERENCES referenced_dist_table(a)
 table_with_references  | FOREIGN KEY (a2) REFERENCES referenced_ref_table(a)
(3 rows)

SELECT alter_distributed_table('table_with_references', shard_count := 10, cascade_to_colocated := false);
WARNING:  foreign key table_with_references_a1_fkey will be dropped
WARNING:  foreign key referencing_dist_table_a_fkey will be dropped
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM  pg_constraint
    WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1,2;
   Referencing Table   |                     Definition
---------------------------------------------------------------------
 table_with_references | FOREIGN KEY (a2) REFERENCES referenced_ref_table(a)
(1 row)

-- check when multi shard modify mode is set to sequential
SELECT alter_distributed_table('referenced_dist_table', colocate_with:='none');
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE ref_to_dist_table(a INT REFERENCES referenced_dist_table(a));
CREATE TABLE ref_to_ref_table(a INT REFERENCES referenced_ref_table(a));
SELECT create_distributed_table('ref_to_dist_table', 'a', colocate_with:='referenced_dist_table');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('ref_to_ref_table', 'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

-- alter a table referencing a reference table
SELECT alter_distributed_table('ref_to_ref_table', shard_count:=6);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- let's create a table that is not colocated with a table that references a reference table
CREATE TABLE col_with_ref_to_dist (a INT);
SELECT create_distributed_table('col_with_ref_to_dist', 'a', colocate_with:='ref_to_dist_table');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

-- and create a table colocated with a table that references a reference table
CREATE TABLE col_with_ref_to_ref (a INT);
SELECT alter_distributed_table('ref_to_ref_table', colocate_with:='none');
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('col_with_ref_to_ref', 'a', colocate_with:='ref_to_ref_table');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

-- alter a table colocated with a table referencing a reference table with cascading
SELECT alter_distributed_table('col_with_ref_to_ref', shard_count:=8, cascade_to_colocated:=true);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- alter a table colocated with a table referencing a reference table without cascading
SELECT alter_distributed_table('col_with_ref_to_ref', shard_count:=10, cascade_to_colocated:=false);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- alter a table not colocated with a table referencing a reference table with cascading
SELECT alter_distributed_table('col_with_ref_to_dist', shard_count:=6, cascade_to_colocated:=true);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- test altering columnar table
CREATE TABLE columnar_table (a INT) USING columnar;
SELECT create_distributed_table('columnar_table', 'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name::text, shard_count, access_method FROM public.citus_tables WHERE table_name::text = 'columnar_table';
   table_name   | shard_count | access_method
---------------------------------------------------------------------
 columnar_table |           4 | columnar
(1 row)

SELECT alter_distributed_table('columnar_table', shard_count:=6);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT table_name::text, shard_count, access_method FROM public.citus_tables WHERE table_name::text = 'columnar_table';
   table_name   | shard_count | access_method
---------------------------------------------------------------------
 columnar_table |           6 | columnar
(1 row)

-- test complex cascade operations
CREATE TABLE cas_1 (a INT UNIQUE);
CREATE TABLE cas_2 (a INT UNIQUE);
CREATE TABLE cas_3 (a INT UNIQUE);
CREATE TABLE cas_4 (a INT UNIQUE);
CREATE TABLE cas_par (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE cas_par_1 PARTITION OF cas_par FOR VALUES FROM (1) TO (4);
CREATE TABLE cas_par_2 PARTITION OF cas_par FOR VALUES FROM (5) TO (8);
CREATE TABLE cas_col (a INT UNIQUE);
-- add foreign keys from and to partitions
ALTER TABLE cas_par_1 ADD CONSTRAINT fkey_from_par_1 FOREIGN KEY (a) REFERENCES cas_1(a);
ALTER TABLE cas_2 ADD CONSTRAINT fkey_to_par_1 FOREIGN KEY (a) REFERENCES cas_par_1(a);
ALTER TABLE cas_par ADD CONSTRAINT fkey_from_par FOREIGN KEY (a) REFERENCES cas_3(a);
ALTER TABLE cas_4 ADD CONSTRAINT fkey_to_par FOREIGN KEY (a) REFERENCES cas_par(a);
-- distribute all the tables
SELECT create_distributed_table('cas_1', 'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('cas_3', 'a', colocate_with:='cas_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('cas_par', 'a', colocate_with:='cas_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('cas_2', 'a', colocate_with:='cas_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('cas_4', 'a', colocate_with:='cas_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('cas_col', 'a', colocate_with:='cas_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM  pg_constraint
    WHERE (conrelid::regclass::text = 'cas_par_1' OR confrelid::regclass::text = 'cas_par_1') ORDER BY 1, 2;
 Referencing Table |               Definition
---------------------------------------------------------------------
 cas_2             | FOREIGN KEY (a) REFERENCES cas_par_1(a)
 cas_4             | FOREIGN KEY (a) REFERENCES cas_par_1(a)
 cas_par_1         | FOREIGN KEY (a) REFERENCES cas_1(a)
 cas_par_1         | FOREIGN KEY (a) REFERENCES cas_3(a)
 cas_par_1         | UNIQUE (a)
(5 rows)

SELECT inhrelid::regclass::text FROM pg_catalog.pg_inherits WHERE inhparent = 'cas_par'::regclass ORDER BY 1;
 inhrelid
---------------------------------------------------------------------
 cas_par_1
 cas_par_2
(2 rows)

-- alter the cas_col and cascade the change
SELECT alter_distributed_table('cas_col', shard_count:=6, cascade_to_colocated:=true);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM  pg_constraint
    WHERE (conrelid::regclass::text = 'cas_par_1' OR confrelid::regclass::text = 'cas_par_1') ORDER BY 1, 2;
 Referencing Table |               Definition
---------------------------------------------------------------------
 cas_2             | FOREIGN KEY (a) REFERENCES cas_par_1(a)
 cas_4             | FOREIGN KEY (a) REFERENCES cas_par_1(a)
 cas_par_1         | FOREIGN KEY (a) REFERENCES cas_1(a)
 cas_par_1         | FOREIGN KEY (a) REFERENCES cas_3(a)
 cas_par_1         | UNIQUE (a)
(5 rows)

SELECT inhrelid::regclass::text FROM pg_catalog.pg_inherits WHERE inhparent = 'cas_par'::regclass ORDER BY 1;
 inhrelid
---------------------------------------------------------------------
 cas_par_1
 cas_par_2
(2 rows)

SET client_min_messages TO DEFAULT;
-- test changing dist column and colocating partitioned table without changing shard count
CREATE TABLE col_table (a INT);
SELECT create_distributed_table('col_table', 'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE par_table (a BIGINT, b INT) PARTITION BY RANGE (a);
SELECT create_distributed_table('par_table', 'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE par_table_1 (a BIGINT, b INT);
SELECT create_distributed_table('par_table_1', 'a', colocate_with:='par_table');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

ALTER TABLE par_table ATTACH PARTITION par_table_1 FOR VALUES FROM (1) TO (5);
SELECT alter_distributed_table('par_table', distribution_column:='b', colocate_with:='col_table');
NOTICE:  converting the partitions of alter_distributed_table.par_table
NOTICE:  creating a new table for alter_distributed_table.par_table_1
NOTICE:  moving the data of alter_distributed_table.par_table_1
NOTICE:  dropping the old alter_distributed_table.par_table_1
NOTICE:  renaming the new table to alter_distributed_table.par_table_1
NOTICE:  creating a new table for alter_distributed_table.par_table
NOTICE:  dropping the old alter_distributed_table.par_table
NOTICE:  renaming the new table to alter_distributed_table.par_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- test changing shard count into a default colocation group with shard split
-- ensure there is no colocation group with 23 shards
SELECT count(*) FROM pg_dist_colocation WHERE shardcount = 23;
 count
---------------------------------------------------------------------
     0
(1 row)

SET citus.shard_count TO 23;
CREATE TABLE shard_split_table (a int, b int);
SELECT create_distributed_table ('shard_split_table', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT 1 FROM isolate_tenant_to_new_shard('shard_split_table', 5, shard_transfer_mode => 'block_writes');
 ?column?
---------------------------------------------------------------------
        1
(1 row)

-- show the difference in pg_dist_colocation and citus_tables shard counts
SELECT
	(
		SELECT shardcount FROM pg_dist_colocation WHERE colocationid IN
		(
			SELECT colocation_id FROM public.citus_tables WHERE table_name = 'shard_split_table'::regclass
		)
	) AS "pg_dist_colocation",
	(SELECT shard_count FROM public.citus_tables WHERE table_name = 'shard_split_table'::regclass) AS "citus_tables";
 pg_dist_colocation | citus_tables
---------------------------------------------------------------------
                 23 |           25
(1 row)

SET citus.shard_count TO 4;
-- distribute another table and then change shard count to 23
CREATE TABLE shard_split_table_2 (a int, b int);
SELECT create_distributed_table ('shard_split_table_2', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table ('shard_split_table_2', shard_count:=23, cascade_to_colocated:=false);
NOTICE:  creating a new table for alter_distributed_table.shard_split_table_2
NOTICE:  moving the data of alter_distributed_table.shard_split_table_2
NOTICE:  dropping the old alter_distributed_table.shard_split_table_2
NOTICE:  renaming the new table to alter_distributed_table.shard_split_table_2
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT a.colocation_id = b.colocation_id FROM public.citus_tables a, public.citus_tables b
	WHERE a.table_name = 'shard_split_table'::regclass AND b.table_name = 'shard_split_table_2'::regclass;
 ?column?
---------------------------------------------------------------------
 f
(1 row)

SELECT shard_count FROM public.citus_tables WHERE table_name = 'shard_split_table_2'::regclass;
 shard_count
---------------------------------------------------------------------
          23
(1 row)

-- test messages
-- test nothing to change
SELECT alter_distributed_table('dist_table');
ERROR:  you have to specify at least one of the distribution_column, shard_count or colocate_with parameters
SELECT alter_distributed_table('dist_table', cascade_to_colocated := false);
ERROR:  you have to specify at least one of the distribution_column, shard_count or colocate_with parameters
-- no operation UDF calls
SELECT alter_distributed_table('dist_table', distribution_column := 'b');
ERROR:  this call doesn't change any properties of the table
HINT:  check citus_tables view to see current properties of the table
SELECT alter_distributed_table('dist_table', shard_count := 10);
ERROR:  this call doesn't change any properties of the table
HINT:  check citus_tables view to see current properties of the table
-- first colocate the tables, then try to re-colococate
SELECT alter_distributed_table('dist_table', colocate_with := 'colocation_table');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', colocate_with := 'colocation_table');
ERROR:  this call doesn't change any properties of the table
HINT:  check citus_tables view to see current properties of the table
-- test some changes while keeping others same
-- shouldn't error but should have notices about no-change parameters
SELECT alter_distributed_table('dist_table', distribution_column:='b', shard_count:=4, cascade_to_colocated:=false);
NOTICE:  table is already distributed by b
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', shard_count:=4, colocate_with:='colocation_table_2');
NOTICE:  shard count of the table is already 4
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', colocate_with:='colocation_table_2', distribution_column:='a');
NOTICE:  table is already colocated with colocation_table_2
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- test cascading distribution column, should error
SELECT alter_distributed_table('dist_table', distribution_column := 'b', cascade_to_colocated := true);
ERROR:  distribution_column cannot be cascaded to colocated tables
SELECT alter_distributed_table('dist_table', distribution_column := 'b', shard_count:=12, colocate_with:='colocation_table_2', cascade_to_colocated := true);
ERROR:  distribution_column cannot be cascaded to colocated tables
-- test nothing to cascade
SELECT alter_distributed_table('dist_table', cascade_to_colocated := true);
ERROR:  shard_count or colocate_with is necessary for cascading to colocated tables
-- test cascading colocate_with := 'none'
SELECT alter_distributed_table('dist_table', colocate_with := 'none', cascade_to_colocated := true);
ERROR:  colocate_with := 'none' cannot be cascaded to colocated tables
-- test changing shard count of a colocated table without cascade_to_colocated, should error
SELECT alter_distributed_table('dist_table', shard_count := 14);
ERROR:  cascade_to_colocated parameter is necessary
DETAIL:  this table is colocated with some other tables
HINT:  cascade_to_colocated := false will break the current colocation, cascade_to_colocated := true will change the shard count of colocated tables too.
-- test changing shard count of a non-colocated table without cascade_to_colocated, shouldn't error
SELECT alter_distributed_table('dist_table', colocate_with := 'none');
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', shard_count := 14);
NOTICE:  creating a new table for alter_distributed_table.dist_table
NOTICE:  moving the data of alter_distributed_table.dist_table
NOTICE:  dropping the old alter_distributed_table.dist_table
NOTICE:  renaming the new table to alter_distributed_table.dist_table
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- test altering a table into colocating with a table but giving a different shard count
SELECT alter_distributed_table('dist_table', colocate_with := 'colocation_table', shard_count := 16);
ERROR:  shard_count cannot be different than the shard count of the table in colocate_with
HINT:  if no shard_count is specified shard count will be same with colocate_with table's
-- test colocation with distribution columns with different data types
CREATE TABLE different_type_table (a TEXT);
SELECT create_distributed_table('different_type_table', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', colocate_with := 'different_type_table');
ERROR:  cannot colocate with different_type_table because data type of its distribution column is different than dist_table
SELECT alter_distributed_table('dist_table', distribution_column := 'a', colocate_with := 'different_type_table');
ERROR:  cannot colocate with different_type_table and change distribution column to a because data type of column a is different then the distribution column of the different_type_table
-- test shard_count := 0
SELECT alter_distributed_table('dist_table', shard_count := 0);
ERROR:  shard_count cannot be 0
HINT:  if you no longer want this to be a distributed table you can try undistribute_table() function
-- test colocating with non-distributed table
CREATE TABLE reference_table (a INT);
SELECT create_reference_table('reference_table');
 create_reference_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', colocate_with:='reference_table');
ERROR:  cannot colocate with reference_table because it is not a distributed table
-- test colocating with single shard table
CREATE TABLE single_shard_table (a INT);
SELECT create_distributed_table('single_shard_table', null);
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist_table', colocate_with:='single_shard_table');
ERROR:  cannot colocate with single_shard_table because it is a single shard distributed table
-- test append table
CREATE TABLE append_table (a INT);
SELECT create_distributed_table('append_table', 'a', 'append');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('append_table', shard_count:=6);
ERROR:  relation append_table should be a hash distributed table
-- test keeping dependent materialized views
CREATE TABLE mat_view_test (a int, b int);
SELECT create_distributed_table('mat_view_test', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO mat_view_test VALUES (1,1), (2,2);
CREATE MATERIALIZED VIEW mat_view AS SELECT * FROM mat_view_test;
SELECT alter_distributed_table('mat_view_test', shard_count := 5, cascade_to_colocated := false);
NOTICE:  creating a new table for alter_distributed_table.mat_view_test
NOTICE:  moving the data of alter_distributed_table.mat_view_test
NOTICE:  dropping the old alter_distributed_table.mat_view_test
NOTICE:  drop cascades to materialized view mat_view
CONTEXT:  SQL statement "DROP TABLE alter_distributed_table.mat_view_test CASCADE"
NOTICE:  renaming the new table to alter_distributed_table.mat_view_test
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT * FROM mat_view ORDER BY a;
 a | b
---------------------------------------------------------------------
 1 | 1
 2 | 2
(2 rows)

-- test long table names
SET client_min_messages TO DEBUG1;
CREATE TABLE abcde_0123456789012345678901234567890123456789012345678901234567890123456789 (x int, y int);
NOTICE:  identifier "abcde_0123456789012345678901234567890123456789012345678901234567890123456789" will be truncated to "abcde_012345678901234567890123456789012345678901234567890123456"
SELECT create_distributed_table('abcde_0123456789012345678901234567890123456789012345678901234567890123456789', 'x');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('abcde_0123456789012345678901234567890123456789012345678901234567890123456789', distribution_column := 'y');
DEBUG:  the name of the shard (abcde_01234567890123456789012345678901234567890_f7ff6612_xxxxxx) for relation (abcde_012345678901234567890123456789012345678901234567890123456) is too long, switching to sequential and local execution mode to prevent self deadlocks
NOTICE:  creating a new table for alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456
NOTICE:  moving the data of alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456
DEBUG:  cannot perform distributed INSERT INTO ... SELECT because the partition columns in the source table and subquery do not match
DETAIL:  The target table's partition column should correspond to a partition column in the subquery.
CONTEXT:  SQL statement "INSERT INTO alter_distributed_table.abcde_0123456789012345678901234567890123456_f7ff6612_4160710162 (x,y) OVERRIDING SYSTEM VALUE SELECT x,y FROM alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456"
DEBUG:  performing repartitioned INSERT ... SELECT
CONTEXT:  SQL statement "INSERT INTO alter_distributed_table.abcde_0123456789012345678901234567890123456_f7ff6612_4160710162 (x,y) OVERRIDING SYSTEM VALUE SELECT x,y FROM alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456"
NOTICE:  dropping the old alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456
CONTEXT:  SQL statement "DROP TABLE alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456 CASCADE"
NOTICE:  renaming the new table to alter_distributed_table.abcde_012345678901234567890123456789012345678901234567890123456
DEBUG:  the name of the shard (abcde_01234567890123456789012345678901234567890_f7ff6612_xxxxxx) for relation (abcde_012345678901234567890123456789012345678901234567890123456) is too long, switching to sequential and local execution mode to prevent self deadlocks
CONTEXT:  SQL statement "ALTER TABLE alter_distributed_table.abcde_0123456789012345678901234567890123456_f7ff6612_4160710162 RENAME TO abcde_012345678901234567890123456789012345678901234567890123456"
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

RESET client_min_messages;
-- test long partitioned table names
CREATE TABLE partition_lengths
(
    tenant_id integer NOT NULL,
    timeperiod timestamp without time zone NOT NULL,
    inserted_utc timestamp without time zone NOT NULL DEFAULT now()
) PARTITION BY RANGE (timeperiod);
SELECT create_distributed_table('partition_lengths', 'tenant_id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE partition_lengths_p2020_09_28_12345678901234567890123456789012345678901234567890 PARTITION OF partition_lengths FOR VALUES FROM ('2020-09-28 00:00:00') TO ('2020-09-29 00:00:00');
NOTICE:  identifier "partition_lengths_p2020_09_28_12345678901234567890123456789012345678901234567890" will be truncated to "partition_lengths_p2020_09_28_123456789012345678901234567890123"
-- verify alter_distributed_table works with long partition names
SELECT alter_distributed_table('partition_lengths', shard_count := 29, cascade_to_colocated := false);
NOTICE:  converting the partitions of alter_distributed_table.partition_lengths
NOTICE:  creating a new table for alter_distributed_table.partition_lengths_p2020_09_28_123456789012345678901234567890123
NOTICE:  moving the data of alter_distributed_table.partition_lengths_p2020_09_28_123456789012345678901234567890123
NOTICE:  dropping the old alter_distributed_table.partition_lengths_p2020_09_28_123456789012345678901234567890123
NOTICE:  renaming the new table to alter_distributed_table.partition_lengths_p2020_09_28_123456789012345678901234567890123
NOTICE:  creating a new table for alter_distributed_table.partition_lengths
NOTICE:  dropping the old alter_distributed_table.partition_lengths
NOTICE:  renaming the new table to alter_distributed_table.partition_lengths
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- test long partition table names
ALTER TABLE partition_lengths_p2020_09_28_12345678901234567890123456789012345678901234567890 RENAME TO partition_lengths_p2020_09_28;
NOTICE:  identifier "partition_lengths_p2020_09_28_12345678901234567890123456789012345678901234567890" will be truncated to "partition_lengths_p2020_09_28_123456789012345678901234567890123"
ALTER TABLE partition_lengths RENAME TO partition_lengths_12345678901234567890123456789012345678901234567890;
NOTICE:  identifier "partition_lengths_12345678901234567890123456789012345678901234567890" will be truncated to "partition_lengths_123456789012345678901234567890123456789012345"
-- verify alter_distributed_table works with long partitioned table names
SELECT alter_distributed_table('partition_lengths_12345678901234567890123456789012345678901234567890', shard_count := 17, cascade_to_colocated := false);
NOTICE:  converting the partitions of alter_distributed_table.partition_lengths_123456789012345678901234567890123456789012345
NOTICE:  creating a new table for alter_distributed_table.partition_lengths_p2020_09_28
NOTICE:  moving the data of alter_distributed_table.partition_lengths_p2020_09_28
NOTICE:  dropping the old alter_distributed_table.partition_lengths_p2020_09_28
NOTICE:  renaming the new table to alter_distributed_table.partition_lengths_p2020_09_28
NOTICE:  creating a new table for alter_distributed_table.partition_lengths_123456789012345678901234567890123456789012345
NOTICE:  dropping the old alter_distributed_table.partition_lengths_123456789012345678901234567890123456789012345
NOTICE:  renaming the new table to alter_distributed_table.partition_lengths_123456789012345678901234567890123456789012345
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

-- verify that alter_distributed_table doesn't change the access methods for the views on the table
CREATE TABLE test_am_matview(a int);
SELECT create_distributed_table('test_am_matview' ,'a', colocate_with:='none');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE MATERIALIZED VIEW test_mat_view_am USING COLUMNAR AS SELECT count(*), a FROM test_am_matview GROUP BY a ;
SELECT alter_distributed_table('test_am_matview', shard_count:= 52);
NOTICE:  creating a new table for alter_distributed_table.test_am_matview
NOTICE:  moving the data of alter_distributed_table.test_am_matview
NOTICE:  dropping the old alter_distributed_table.test_am_matview
NOTICE:  drop cascades to materialized view test_mat_view_am
CONTEXT:  SQL statement "DROP TABLE alter_distributed_table.test_am_matview CASCADE"
NOTICE:  renaming the new table to alter_distributed_table.test_am_matview
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT amname FROM pg_am WHERE oid IN (SELECT relam FROM pg_class WHERE relname ='test_mat_view_am');
  amname
---------------------------------------------------------------------
 columnar
(1 row)

-- verify that alter_distributed_table works if it has dependent views and materialized views
-- set colocate_with explicitly to not to affect other tables
CREATE SCHEMA schema_to_test_alter_dist_table;
SET search_path to schema_to_test_alter_dist_table;
CREATE TABLE test_alt_dist_table_1(a int, b int);
SELECT create_distributed_table('test_alt_dist_table_1', 'a', colocate_with => 'None');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE test_alt_dist_table_2(a int, b int);
SELECT create_distributed_table('test_alt_dist_table_2', 'a', colocate_with => 'test_alt_dist_table_1');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE VIEW dependent_view_1 AS SELECT test_alt_dist_table_2.* FROM test_alt_dist_table_2;
CREATE VIEW dependent_view_2 AS SELECT test_alt_dist_table_2.* FROM test_alt_dist_table_2 JOIN test_alt_dist_table_1 USING(a);
CREATE MATERIALIZED VIEW dependent_mat_view_1 AS SELECT test_alt_dist_table_2.* FROM test_alt_dist_table_2;
-- Alter owner to make sure that alter_distributed_table doesn't change view's owner
SET client_min_messages TO WARNING;
CREATE USER alter_dist_table_test_user;
SELECT 1 FROM run_command_on_workers($$CREATE USER alter_dist_table_test_user$$);
 ?column?
---------------------------------------------------------------------
        1
        1
(2 rows)

ALTER VIEW dependent_view_1 OWNER TO alter_dist_table_test_user;
ALTER VIEW dependent_view_2 OWNER TO alter_dist_table_test_user;
ALTER MATERIALIZED VIEW dependent_mat_view_1 OWNER TO alter_dist_table_test_user;
SELECT alter_distributed_table('test_alt_dist_table_1', shard_count:=12, cascade_to_colocated:=true);
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT viewowner FROM pg_views WHERE viewname IN ('dependent_view_1', 'dependent_view_2');
         viewowner
---------------------------------------------------------------------
 alter_dist_table_test_user
 alter_dist_table_test_user
(2 rows)

SELECT matviewowner FROM pg_matviews WHERE matviewname = 'dependent_mat_view_1';
        matviewowner
---------------------------------------------------------------------
 alter_dist_table_test_user
(1 row)

-- Check the existence of the view on the worker node as well
SELECT run_command_on_workers($$SELECT viewowner FROM pg_views WHERE viewname = 'dependent_view_1'$$);
             run_command_on_workers
---------------------------------------------------------------------
 (localhost,57637,t,alter_dist_table_test_user)
 (localhost,57638,t,alter_dist_table_test_user)
(2 rows)

SELECT run_command_on_workers($$SELECT viewowner FROM pg_views WHERE viewname = 'dependent_view_2'$$);
             run_command_on_workers
---------------------------------------------------------------------
 (localhost,57637,t,alter_dist_table_test_user)
 (localhost,57638,t,alter_dist_table_test_user)
(2 rows)

-- It is expected to not have mat view on worker node
SELECT run_command_on_workers($$SELECT count(*) FROM pg_matviews WHERE matviewname = 'dependent_mat_view_1';$$);
 run_command_on_workers
---------------------------------------------------------------------
 (localhost,57637,t,0)
 (localhost,57638,t,0)
(2 rows)

RESET search_path;
DROP SCHEMA alter_distributed_table CASCADE;
DROP SCHEMA schema_to_test_alter_dist_table CASCADE;
DROP USER alter_dist_table_test_user;
SET client_min_messages TO WARNING;
DROP EXTENSION citus_columnar CASCADE;
