--
-- ALTER_TABLE_SET_ACCESS_METHOD
--
CREATE TABLE alter_am_pg_version_table (a INT);
SELECT alter_table_set_access_method('alter_am_pg_version_table', 'columnar');
NOTICE:  creating a new table for public.alter_am_pg_version_table
NOTICE:  moving the data of public.alter_am_pg_version_table
NOTICE:  dropping the old public.alter_am_pg_version_table
NOTICE:  renaming the new table to public.alter_am_pg_version_table
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

DROP TABLE alter_am_pg_version_table;
CREATE SCHEMA alter_table_set_access_method;
SET search_path TO alter_table_set_access_method;
SET citus.shard_count TO 4;
SET citus.shard_replication_factor TO 1;
SELECT public.run_command_on_coordinator_and_workers($Q$
	CREATE FUNCTION fake_am_handler(internal)
	RETURNS table_am_handler
	AS 'citus'
	LANGUAGE C;
	CREATE ACCESS METHOD fake_am TYPE TABLE HANDLER fake_am_handler;
$Q$);
 run_command_on_coordinator_and_workers
---------------------------------------------------------------------

(1 row)

CREATE TABLE dist_table (a INT, b INT);
SELECT create_distributed_table ('dist_table', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO dist_table VALUES (1, 1), (2, 2), (3, 3);
SELECT table_name, access_method FROM public.citus_tables WHERE table_name::text = 'dist_table' ORDER BY 1;
 table_name | access_method
---------------------------------------------------------------------
 dist_table | heap
(1 row)

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

(1 row)

SELECT table_name, access_method FROM public.citus_tables WHERE table_name::text = 'dist_table' ORDER BY 1;
 table_name | access_method
---------------------------------------------------------------------
 dist_table | columnar
(1 row)

-- test partitions
CREATE TABLE partitioned_table (id INT, a INT) PARTITION BY RANGE (id);
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);
SELECT create_distributed_table('partitioned_table', 'id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

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, access_method FROM public.citus_tables WHERE table_name::text LIKE 'partitioned\_table%' ORDER BY 1;
       table_name       | access_method
---------------------------------------------------------------------
 partitioned_table      |
 partitioned_table_1_5  | heap
 partitioned_table_6_10 | heap
(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)

-- altering partitioned tables' access methods is not supported
SELECT alter_table_set_access_method('partitioned_table', 'columnar');
ERROR:  you cannot alter access method of a partitioned table
-- test altering the partition's access method
SELECT alter_table_set_access_method('partitioned_table_1_5', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.partitioned_table_1_5
NOTICE:  moving the data of alter_table_set_access_method.partitioned_table_1_5
NOTICE:  dropping the old alter_table_set_access_method.partitioned_table_1_5
NOTICE:  renaming the new table to alter_table_set_access_method.partitioned_table_1_5
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

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, access_method FROM public.citus_tables WHERE table_name::text LIKE 'partitioned\_table%' ORDER BY 1;
       table_name       | access_method
---------------------------------------------------------------------
 partitioned_table      |
 partitioned_table_1_5  | columnar
 partitioned_table_6_10 | heap
(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)

-- try to compress partitions with an integer partition column
CALL alter_old_partitions_set_access_method('partitioned_table', '2021-01-01', 'columnar');
ERROR:  partition column of partitioned_table cannot be cast to a timestamptz
CONTEXT:  PL/pgSQL function alter_old_partitions_set_access_method(regclass,timestamp with time zone,name) line XX at RAISE
CREATE TABLE time_partitioned (event_time timestamp, event int) partition by range (event_time);
SELECT create_distributed_table('time_partitioned', 'event_time');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE time_partitioned_d00 PARTITION OF time_partitioned FOR VALUES FROM ('2000-01-01') TO ('2009-12-31');
CREATE TABLE time_partitioned_d10 PARTITION OF time_partitioned FOR VALUES FROM ('2010-01-01') TO ('2019-12-31');
CREATE TABLE time_partitioned_d20 PARTITION OF time_partitioned FOR VALUES FROM ('2020-01-01') TO ('2029-12-31');
INSERT INTO time_partitioned VALUES ('2005-01-01', 1);
INSERT INTO time_partitioned VALUES ('2015-01-01', 2);
INSERT INTO time_partitioned VALUES ('2025-01-01', 3);
\set VERBOSITY terse
-- compress no partitions
CALL alter_old_partitions_set_access_method('time_partitioned', '1999-01-01', 'columnar');
SELECT partition, access_method FROM time_partitions WHERE parent_table = 'time_partitioned'::regclass ORDER BY partition::text;
      partition       | access_method
---------------------------------------------------------------------
 time_partitioned_d00 | heap
 time_partitioned_d10 | heap
 time_partitioned_d20 | heap
(3 rows)

SELECT event FROM time_partitioned ORDER BY 1;
 event
---------------------------------------------------------------------
     1
     2
     3
(3 rows)

-- compress 2 old partitions
CALL alter_old_partitions_set_access_method('time_partitioned', '2021-01-01', 'columnar');
NOTICE:  converting time_partitioned_d00 with start time Sat Jan 01 00:00:00 2000 and end time Thu Dec 31 00:00:00 2009
NOTICE:  creating a new table for alter_table_set_access_method.time_partitioned_d00
NOTICE:  moving the data of alter_table_set_access_method.time_partitioned_d00
NOTICE:  dropping the old alter_table_set_access_method.time_partitioned_d00
NOTICE:  renaming the new table to alter_table_set_access_method.time_partitioned_d00
NOTICE:  converting time_partitioned_d10 with start time Fri Jan 01 00:00:00 2010 and end time Tue Dec 31 00:00:00 2019
NOTICE:  creating a new table for alter_table_set_access_method.time_partitioned_d10
NOTICE:  moving the data of alter_table_set_access_method.time_partitioned_d10
NOTICE:  dropping the old alter_table_set_access_method.time_partitioned_d10
NOTICE:  renaming the new table to alter_table_set_access_method.time_partitioned_d10
SELECT partition, access_method FROM time_partitions WHERE parent_table = 'time_partitioned'::regclass ORDER BY partition::text;
      partition       | access_method
---------------------------------------------------------------------
 time_partitioned_d00 | columnar
 time_partitioned_d10 | columnar
 time_partitioned_d20 | heap
(3 rows)

SELECT event FROM time_partitioned ORDER BY 1;
 event
---------------------------------------------------------------------
     1
     2
     3
(3 rows)

-- will not be compressed again
CALL alter_old_partitions_set_access_method('time_partitioned', '2021-01-01', 'columnar');
SELECT partition, access_method FROM time_partitions WHERE parent_table = 'time_partitioned'::regclass ORDER BY partition::text;
      partition       | access_method
---------------------------------------------------------------------
 time_partitioned_d00 | columnar
 time_partitioned_d10 | columnar
 time_partitioned_d20 | heap
(3 rows)

SELECT event FROM time_partitioned ORDER BY 1;
 event
---------------------------------------------------------------------
     1
     2
     3
(3 rows)

-- back to heap
CALL alter_old_partitions_set_access_method('time_partitioned', '2021-01-01', 'heap');
NOTICE:  converting time_partitioned_d00 with start time Sat Jan 01 00:00:00 2000 and end time Thu Dec 31 00:00:00 2009
NOTICE:  creating a new table for alter_table_set_access_method.time_partitioned_d00
NOTICE:  moving the data of alter_table_set_access_method.time_partitioned_d00
NOTICE:  dropping the old alter_table_set_access_method.time_partitioned_d00
NOTICE:  renaming the new table to alter_table_set_access_method.time_partitioned_d00
NOTICE:  converting time_partitioned_d10 with start time Fri Jan 01 00:00:00 2010 and end time Tue Dec 31 00:00:00 2019
NOTICE:  creating a new table for alter_table_set_access_method.time_partitioned_d10
NOTICE:  moving the data of alter_table_set_access_method.time_partitioned_d10
NOTICE:  dropping the old alter_table_set_access_method.time_partitioned_d10
NOTICE:  renaming the new table to alter_table_set_access_method.time_partitioned_d10
SELECT partition, access_method FROM time_partitions WHERE parent_table = 'time_partitioned'::regclass ORDER BY partition::text;
      partition       | access_method
---------------------------------------------------------------------
 time_partitioned_d00 | heap
 time_partitioned_d10 | heap
 time_partitioned_d20 | heap
(3 rows)

SELECT event FROM time_partitioned ORDER BY 1;
 event
---------------------------------------------------------------------
     1
     2
     3
(3 rows)

\set VERBOSITY default
DROP TABLE time_partitioned;
-- test altering a table with index to columnar
CREATE TABLE index_table (a INT) USING heap;
CREATE INDEX idx1 ON index_table (a);
-- also create an index with statistics
CREATE INDEX idx2 ON index_table ((a+1));
ALTER INDEX idx2 ALTER COLUMN 1 SET STATISTICS 300;
SELECT indexname FROM pg_indexes WHERE schemaname = 'alter_table_set_access_method' AND tablename = 'index_table' order by indexname;
 indexname
---------------------------------------------------------------------
 idx1
 idx2
(2 rows)

SELECT a.amname FROM pg_class c, pg_am a where c.relname = 'index_table' AND c.relnamespace = 'alter_table_set_access_method'::regnamespace AND c.relam = a.oid;
 amname
---------------------------------------------------------------------
 heap
(1 row)

SELECT alter_table_set_access_method('index_table', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.index_table
NOTICE:  moving the data of alter_table_set_access_method.index_table
NOTICE:  dropping the old alter_table_set_access_method.index_table
NOTICE:  renaming the new table to alter_table_set_access_method.index_table
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT indexname FROM pg_indexes WHERE schemaname = 'alter_table_set_access_method' AND tablename = 'index_table' order by indexname;
 indexname
---------------------------------------------------------------------
 idx1
 idx2
(2 rows)

SELECT a.amname FROM pg_class c, pg_am a where c.relname = 'index_table' AND c.relnamespace = 'alter_table_set_access_method'::regnamespace AND c.relam = a.oid;
  amname
---------------------------------------------------------------------
 columnar
(1 row)

CREATE TABLE "heap_\'tbl" (
  c1 CIRCLE,
  c2 TEXT,
  i int4[],
  p point,
  a int,
  EXCLUDE USING gist
    (c1 WITH &&, (c2::circle) WITH &&)
    WHERE (circle_center(c1) <> '(0,0)'),
  EXCLUDE USING btree
    (a WITH =)
	INCLUDE(p)
	WHERE (c2 < 'astring')
);
CREATE INDEX heap_tbl_gin ON "heap_\'tbl" USING gin (i);
CREATE INDEX "heap_tbl_\'gist" ON "heap_\'tbl" USING gist(p);
CREATE INDEX heap_tbl_brin ON "heap_\'tbl" USING brin (a) WITH (pages_per_range = 1);
CREATE INDEX heap_tbl_hash ON "heap_\'tbl" USING hash (c2);
ALTER TABLE "heap_\'tbl" ADD CONSTRAINT heap_tbl_unique UNIQUE (c2);
CREATE UNIQUE INDEX "heap_tbl_\'btree" ON "heap_\'tbl" USING btree (a);
ALTER TABLE "heap_\'tbl" ADD CONSTRAINT "heap_tbl_\'pkey" PRIMARY KEY USING INDEX "heap_tbl_\'btree";
NOTICE:  ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "heap_tbl_\'btree" to "heap_tbl_\'pkey"
SELECT indexname FROM pg_indexes
WHERE schemaname = 'alter_table_set_access_method' AND
      tablename = 'heap_\''tbl'
ORDER BY indexname;
       indexname
---------------------------------------------------------------------
 heap_\'tbl_a_p_excl
 heap_\'tbl_c1_c2_excl
 heap_tbl_\'gist
 heap_tbl_\'pkey
 heap_tbl_brin
 heap_tbl_gin
 heap_tbl_hash
 heap_tbl_unique
(8 rows)

SELECT conname FROM pg_constraint
WHERE conrelid = 'heap_\''tbl'::regclass
ORDER BY conname;
        conname
---------------------------------------------------------------------
 heap_\'tbl_a_p_excl
 heap_\'tbl_c1_c2_excl
 heap_tbl_\'pkey
 heap_tbl_unique
(4 rows)

SELECT alter_table_set_access_method('heap_\''tbl', 'columnar');
NOTICE:  unsupported access method for index heap_\'tbl_c1_c2_excl on columnar table alter_table_set_access_method."heap_\'tbl", given index and the constraint depending on the index (if any) will be dropped
NOTICE:  unsupported access method for index heap_tbl_gin on columnar table alter_table_set_access_method."heap_\'tbl", given index and the constraint depending on the index (if any) will be dropped
NOTICE:  unsupported access method for index heap_tbl_\'gist on columnar table alter_table_set_access_method."heap_\'tbl", given index and the constraint depending on the index (if any) will be dropped
NOTICE:  unsupported access method for index heap_tbl_brin on columnar table alter_table_set_access_method."heap_\'tbl", given index and the constraint depending on the index (if any) will be dropped
NOTICE:  creating a new table for alter_table_set_access_method."heap_\'tbl"
NOTICE:  moving the data of alter_table_set_access_method."heap_\'tbl"
NOTICE:  dropping the old alter_table_set_access_method."heap_\'tbl"
NOTICE:  renaming the new table to alter_table_set_access_method."heap_\'tbl"
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT indexname FROM pg_indexes
WHERE schemaname = 'alter_table_set_access_method' AND
      tablename = 'heap_\''tbl'
ORDER BY indexname;
      indexname
---------------------------------------------------------------------
 heap_\'tbl_a_p_excl
 heap_tbl_\'pkey
 heap_tbl_hash
 heap_tbl_unique
(4 rows)

SELECT conname FROM pg_constraint
WHERE conrelid = 'heap_\''tbl'::regclass
ORDER BY conname;
       conname
---------------------------------------------------------------------
 heap_\'tbl_a_p_excl
 heap_tbl_\'pkey
 heap_tbl_unique
(3 rows)

-- test different table types
SET client_min_messages to WARNING;
SELECT 1 FROM master_add_node('localhost', :master_port, groupId := 0);
 ?column?
---------------------------------------------------------------------
        1
(1 row)

SET client_min_messages to DEFAULT;
CREATE TABLE table_type_dist (a INT);
SELECT create_distributed_table('table_type_dist', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE table_type_ref (a INT);
SELECT create_reference_table('table_type_ref');
 create_reference_table
---------------------------------------------------------------------

(1 row)

CREATE TABLE table_type_citus_local(a INT);
SELECT citus_add_local_table_to_metadata('table_type_citus_local');
 citus_add_local_table_to_metadata
---------------------------------------------------------------------

(1 row)

CREATE TABLE table_type_pg_local (a INT);
SELECT table_name, citus_table_type, distribution_column, shard_count, access_method FROM public.citus_tables WHERE table_name::text LIKE 'table\_type%' ORDER BY 1;
       table_name       | citus_table_type | distribution_column | shard_count | access_method
---------------------------------------------------------------------
 table_type_dist        | distributed      | a                   |           4 | heap
 table_type_ref         | reference        | <none>              |           1 | heap
 table_type_citus_local | local            | <none>              |           1 | heap
(3 rows)

SELECT c.relname, a.amname FROM pg_class c, pg_am a where c.relname SIMILAR TO 'table_type\D*' AND c.relnamespace = 'alter_table_set_access_method'::regnamespace AND c.relam = a.oid;
        relname         | amname
---------------------------------------------------------------------
 table_type_citus_local | heap
 table_type_dist        | heap
 table_type_pg_local    | heap
 table_type_ref         | heap
(4 rows)

SELECT alter_table_set_access_method('table_type_dist', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.table_type_dist
NOTICE:  moving the data of alter_table_set_access_method.table_type_dist
NOTICE:  dropping the old alter_table_set_access_method.table_type_dist
NOTICE:  renaming the new table to alter_table_set_access_method.table_type_dist
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT alter_table_set_access_method('table_type_ref', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.table_type_ref
NOTICE:  moving the data of alter_table_set_access_method.table_type_ref
NOTICE:  dropping the old alter_table_set_access_method.table_type_ref
NOTICE:  renaming the new table to alter_table_set_access_method.table_type_ref
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT alter_table_set_access_method('table_type_pg_local', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.table_type_pg_local
NOTICE:  moving the data of alter_table_set_access_method.table_type_pg_local
NOTICE:  dropping the old alter_table_set_access_method.table_type_pg_local
NOTICE:  renaming the new table to alter_table_set_access_method.table_type_pg_local
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT alter_table_set_access_method('table_type_citus_local', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.table_type_citus_local
NOTICE:  moving the data of alter_table_set_access_method.table_type_citus_local
NOTICE:  dropping the old alter_table_set_access_method.table_type_citus_local
NOTICE:  renaming the new table to alter_table_set_access_method.table_type_citus_local
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT table_name, citus_table_type, distribution_column, shard_count, access_method FROM public.citus_tables WHERE table_name::text LIKE 'table\_type%' ORDER BY 1;
       table_name       | citus_table_type | distribution_column | shard_count | access_method
---------------------------------------------------------------------
 table_type_dist        | distributed      | a                   |           4 | columnar
 table_type_ref         | reference        | <none>              |           1 | columnar
 table_type_citus_local | local            | <none>              |           1 | columnar
(3 rows)

SELECT c.relname, a.amname FROM pg_class c, pg_am a where c.relname SIMILAR TO 'table_type\D*' AND c.relnamespace = 'alter_table_set_access_method'::regnamespace AND c.relam = a.oid;
        relname         |  amname
---------------------------------------------------------------------
 table_type_citus_local | columnar
 table_type_dist        | columnar
 table_type_pg_local    | columnar
 table_type_ref         | columnar
(4 rows)

-- test when the parent of a partition has foreign key to a reference table
create table test_pk(n int primary key);
create table test_fk_p(i int references test_pk(n)) partition by range(i);
create table test_fk_p0 partition of test_fk_p for values from (0) to (10);
create table test_fk_p1 partition of test_fk_p for values from (10) to (20);
select alter_table_set_access_method('test_fk_p1', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.test_fk_p1
NOTICE:  moving the data of alter_table_set_access_method.test_fk_p1
NOTICE:  dropping the old alter_table_set_access_method.test_fk_p1
NOTICE:  renaming the new table to alter_table_set_access_method.test_fk_p1
ERROR:  Foreign keys and AFTER ROW triggers are not supported for columnar tables
HINT:  Consider an AFTER STATEMENT trigger instead.
CONTEXT:  SQL statement "ALTER TABLE alter_table_set_access_method.test_fk_p ATTACH PARTITION alter_table_set_access_method.test_fk_p1 FOR VALUES FROM (10) TO (20);"
-- test changing into same access method
CREATE TABLE same_access_method (a INT);
SELECT alter_table_set_access_method('same_access_method', 'heap');
ERROR:  the access method of alter_table_set_access_method.same_access_method is already heap
-- test keeping dependent materialized views
CREATE TABLE mat_view_test (a int);
INSERT INTO mat_view_test VALUES (1), (2);
CREATE MATERIALIZED VIEW mat_view AS SELECT * FROM mat_view_test;
SELECT alter_table_set_access_method('mat_view_test','columnar');
NOTICE:  creating a new table for alter_table_set_access_method.mat_view_test
NOTICE:  moving the data of alter_table_set_access_method.mat_view_test
NOTICE:  dropping the old alter_table_set_access_method.mat_view_test
NOTICE:  drop cascades to materialized view mat_view
CONTEXT:  SQL statement "DROP TABLE alter_table_set_access_method.mat_view_test CASCADE"
NOTICE:  renaming the new table to alter_table_set_access_method.mat_view_test
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

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

CREATE SEQUENCE c_seq;
CREATE TABLE local(a int, b bigserial, c int default nextval('c_seq'));
INSERT INTO local VALUES (3);
create materialized view m_local as select * from local;
create view v_local as select * from local;
WARNING:  "view v_local" has dependency to "table local" that is not in Citus' metadata
DETAIL:  "view v_local" will be created only locally
HINT:  Distribute "table local" first to distribute "view v_local"
CREATE TABLE ref(a int);
SELECT create_Reference_table('ref');
 create_reference_table
---------------------------------------------------------------------

(1 row)

INSERT INTO ref VALUES (4),(5);
create materialized view m_ref as select * from ref;
create view v_ref as select * from ref;
CREATE TABLE dist(a int);
SELECT create_distributed_table('dist', 'a');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO dist VALUES (7),(9);
create materialized view m_dist as select * from dist;
create view v_dist as select * from dist;
\set VERBOSITY terse
select alter_table_set_access_method('local','columnar');
NOTICE:  creating a new table for alter_table_set_access_method.local
NOTICE:  moving the data of alter_table_set_access_method.local
NOTICE:  dropping the old alter_table_set_access_method.local
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.local
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

select alter_table_set_access_method('ref','columnar');
NOTICE:  creating a new table for alter_table_set_access_method.ref
NOTICE:  moving the data of alter_table_set_access_method.ref
NOTICE:  dropping the old alter_table_set_access_method.ref
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.ref
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

select alter_table_set_access_method('dist','columnar');
NOTICE:  creating a new table for alter_table_set_access_method.dist
NOTICE:  moving the data of alter_table_set_access_method.dist
NOTICE:  dropping the old alter_table_set_access_method.dist
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.dist
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT alter_distributed_table('dist', shard_count:=1, cascade_to_colocated:=false);
NOTICE:  creating a new table for alter_table_set_access_method.dist
NOTICE:  moving the data of alter_table_set_access_method.dist
NOTICE:  dropping the old alter_table_set_access_method.dist
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.dist
 alter_distributed_table
---------------------------------------------------------------------

(1 row)

select alter_table_set_access_method('local','heap');
NOTICE:  creating a new table for alter_table_set_access_method.local
NOTICE:  moving the data of alter_table_set_access_method.local
NOTICE:  dropping the old alter_table_set_access_method.local
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.local
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

select alter_table_set_access_method('ref','heap');
NOTICE:  creating a new table for alter_table_set_access_method.ref
NOTICE:  moving the data of alter_table_set_access_method.ref
NOTICE:  dropping the old alter_table_set_access_method.ref
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.ref
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

select alter_table_set_access_method('dist','heap');
NOTICE:  creating a new table for alter_table_set_access_method.dist
NOTICE:  moving the data of alter_table_set_access_method.dist
NOTICE:  dropping the old alter_table_set_access_method.dist
NOTICE:  drop cascades to 2 other objects
NOTICE:  renaming the new table to alter_table_set_access_method.dist
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

\set VERBOSITY default
SELECT * FROM m_local;
 a | b | c
---------------------------------------------------------------------
 3 | 1 | 1
(1 row)

SELECT * FROM m_ref;
 a
---------------------------------------------------------------------
 4
 5
(2 rows)

SELECT * FROM m_dist;
 a
---------------------------------------------------------------------
 7
 9
(2 rows)

SELECT * FROM v_local;
 a | b | c
---------------------------------------------------------------------
 3 | 1 | 1
(1 row)

SELECT * FROM v_ref;
 a
---------------------------------------------------------------------
 4
 5
(2 rows)

SELECT * FROM v_dist;
 a
---------------------------------------------------------------------
 7
 9
(2 rows)

SELECT relname, relkind
	FROM pg_class
	WHERE relname IN (
		'v_dist',
		'v_ref',
		'v_local',
		'm_dist',
		'm_ref',
		'm_local'
	)
	ORDER BY relname ASC;
 relname | relkind
---------------------------------------------------------------------
 m_dist  | m
 m_local | m
 m_ref   | m
 v_dist  | v
 v_local | v
 v_ref   | v
(6 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_table_set_access_method('abcde_0123456789012345678901234567890123456789012345678901234567890123456789', 'columnar');
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_table_set_access_method.abcde_012345678901234567890123456789012345678901234567890123456
DEBUG:  pathlist hook for columnar table am
CONTEXT:  SQL statement "SELECT TRUE FROM alter_table_set_access_method.abcde_0123456789012345678901234567890123456_f7ff6612_4160710162 LIMIT 1"
NOTICE:  moving the data of alter_table_set_access_method.abcde_012345678901234567890123456789012345678901234567890123456
NOTICE:  dropping the old alter_table_set_access_method.abcde_012345678901234567890123456789012345678901234567890123456
CONTEXT:  SQL statement "DROP TABLE alter_table_set_access_method.abcde_012345678901234567890123456789012345678901234567890123456 CASCADE"
NOTICE:  renaming the new table to alter_table_set_access_method.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_table_set_access_method.abcde_0123456789012345678901234567890123456_f7ff6612_4160710162 RENAME TO abcde_012345678901234567890123456789012345678901234567890123456"
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

SELECT * FROM abcde_0123456789012345678901234567890123456789012345678901234567890123456789;
NOTICE:  identifier "abcde_0123456789012345678901234567890123456789012345678901234567890123456789" will be truncated to "abcde_012345678901234567890123456789012345678901234567890123456"
DEBUG:  pathlist hook for columnar table am
 x | y
---------------------------------------------------------------------
(0 rows)

RESET client_min_messages;
create table events (event_id bigserial, event_time timestamptz default now(), payload text);
create index on events (event_id);
insert into events (payload) select 'hello-'||s from generate_series(1,10) s;
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int >= 16 AS server_version_ge_16
\gset
BEGIN;
  \if :server_version_ge_16
  SET LOCAL debug_parallel_query = regress;
  \else
  SET LOCAL force_parallel_mode = regress;
  \endif
  SET LOCAL min_parallel_table_scan_size = 1;
  SET LOCAL parallel_tuple_cost = 0;
  SET LOCAL max_parallel_workers = 4;
  SET LOCAL max_parallel_workers_per_gather = 4;
  select alter_table_set_access_method('events', 'columnar');
NOTICE:  creating a new table for alter_table_set_access_method.events
NOTICE:  moving the data of alter_table_set_access_method.events
NOTICE:  dropping the old alter_table_set_access_method.events
NOTICE:  renaming the new table to alter_table_set_access_method.events
 alter_table_set_access_method
---------------------------------------------------------------------

(1 row)

COMMIT;
--create the view to test alter table set access method on it
CREATE TABLE view_test_table (id int, val int, flag bool, kind int);
SELECT create_distributed_table('view_test_table','id');
 create_distributed_table
---------------------------------------------------------------------

(1 row)

INSERT INTO view_test_table VALUES (1, 1, true, 99), (2, 2, false, 99), (2, 3, true, 88);
CREATE VIEW view_test_view AS SELECT * FROM view_test_table;
-- error out when attempting to set access method of a view.
select alter_table_set_access_method('view_test_view','columnar');
ERROR:  you cannot alter access method of a view
SET client_min_messages TO WARNING;
DROP SCHEMA alter_table_set_access_method CASCADE;
