--------------------------------------------------------------------- --- tests around access tracking within transaction blocks --------------------------------------------------------------------- CREATE SCHEMA access_tracking; SET search_path TO 'access_tracking'; -- idempotently add node to allow this test to run without add_coordinator SET client_min_messages TO WARNING; SELECT 1 FROM citus_set_coordinator_host('localhost', :master_port); ?column? --------------------------------------------------------------------- 1 (1 row) SELECT 1 FROM master_set_node_property('localhost', :master_port, 'shouldhaveshards', true); ?column? --------------------------------------------------------------------- 1 (1 row) RESET client_min_messages; SET citus.shard_count TO 4; SET citus.shard_replication_factor TO 1; SET citus.next_shard_id TO 90930500; CREATE OR REPLACE FUNCTION relation_select_access_mode(relationId Oid) RETURNS int LANGUAGE C STABLE STRICT AS 'citus', $$relation_select_access_mode$$; CREATE OR REPLACE FUNCTION relation_dml_access_mode(relationId Oid) RETURNS int LANGUAGE C STABLE STRICT AS 'citus', $$relation_dml_access_mode$$; CREATE OR REPLACE FUNCTION relation_ddl_access_mode(relationId Oid) RETURNS int LANGUAGE C STABLE STRICT AS 'citus', $$relation_ddl_access_mode$$; CREATE OR REPLACE FUNCTION distributed_relation(relation_name text) RETURNS bool AS $$ DECLARE part_method char; BEGIN select partmethod INTO part_method from pg_dist_partition WHERE logicalrelid = relation_name::regclass; IF part_method = 'h' THEN RETURN true; ELSE RETURN false; END IF; END; $$ LANGUAGE 'plpgsql' IMMUTABLE; CREATE OR REPLACE FUNCTION relation_access_mode_to_text(relation_name text, relationShardAccess int) RETURNS text AS $$ BEGIN IF relationShardAccess = 0 and distributed_relation(relation_name) THEN RETURN 'not_parallel_accessed'; ELSIF relationShardAccess = 0 and NOT distributed_relation(relation_name) THEN RETURN 'not_accessed'; ELSIF relationShardAccess = 1 THEN RETURN 'reference_table_access'; ELSE RETURN 'parallel_access'; END IF; END; $$ LANGUAGE 'plpgsql' IMMUTABLE; CREATE VIEW relation_accesses AS SELECT table_name, relation_access_mode_to_text(table_name, relation_select_access_mode(table_name::regclass)) as select_access, relation_access_mode_to_text(table_name, relation_dml_access_mode(table_name::regclass)) as dml_access, relation_access_mode_to_text(table_name, relation_ddl_access_mode(table_name::regclass)) as ddl_access FROM ((SELECT 'table_' || i as table_name FROM generate_series(1, 7) i) UNION (SELECT 'partitioning_test') UNION (SELECT 'partitioning_test_2009') UNION (SELECT 'partitioning_test_2010')) tables; SET citus.shard_replication_factor TO 1; CREATE TABLE table_1 (key int, value int); SELECT create_distributed_table('table_1', 'key'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE table_2 (key int, value int); SELECT create_distributed_table('table_2', 'key'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE table_3 (key int, value int); SELECT create_distributed_table('table_3', 'key'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE table_4 (key int, value int); SELECT create_distributed_table('table_4', 'key'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE table_5 (key int, value int); SELECT create_distributed_table('table_5', 'key'); create_distributed_table --------------------------------------------------------------------- (1 row) CREATE TABLE table_6 (key int, value int); SELECT create_reference_Table('table_6'); create_reference_table --------------------------------------------------------------------- (1 row) INSERT INTO table_1 SELECT i, i FROM generate_series(0,100) i; INSERT INTO table_2 SELECT i, i FROM generate_series(0,100) i; INSERT INTO table_3 SELECT i, i FROM generate_series(0,100) i; INSERT INTO table_4 SELECT i, i FROM generate_series(0,100) i; INSERT INTO table_5 SELECT i, i FROM generate_series(0,100) i; INSERT INTO table_6 SELECT i, i FROM generate_series(0,100) i; -- create_distributed_table works fine BEGIN; CREATE TABLE table_7 (key int, value int); SELECT create_distributed_table('table_7', 'key'); create_distributed_table --------------------------------------------------------------------- (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_7') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_7 | not_parallel_accessed | not_parallel_accessed | parallel_access (1 row) COMMIT; -- outside the transaction blocks, the function always returns zero SELECT count(*) FROM table_1; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) -- a very simple test that first checks sequential -- and parallel SELECTs,DMLs, and DDLs BEGIN; SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) SELECT count(*) FROM table_1 WHERE key = 1; count --------------------------------------------------------------------- 1 (1 row) SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) SELECT count(*) FROM table_1 WHERE key = 1 OR key = 2; count --------------------------------------------------------------------- 2 (1 row) SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed (1 row) INSERT INTO table_1 VALUES (1,1); SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed (1 row) INSERT INTO table_1 VALUES (1,1), (2,2); SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed (1 row) ALTER TABLE table_1 ADD COLUMN test_col INT; -- now see that the other tables are not accessed at all SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | parallel_access (1 row) ROLLBACK; -- this test shows that even if two multiple single shard -- commands executed, we can treat the transaction as sequential BEGIN; SELECT count(*) FROM table_1 WHERE key = 1; count --------------------------------------------------------------------- 1 (1 row) SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) SELECT count(*) FROM table_1 WHERE key = 2; count --------------------------------------------------------------------- 1 (1 row) SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) INSERT INTO table_1 VALUES (1,1); SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) INSERT INTO table_1 VALUES (2,2); SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- a sample DDL example BEGIN; ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access (1 row) ROLLBACK; -- a simple join touches single shard per table BEGIN; SELECT count(*) FROM table_1, table_2, table_3, table_4, table_5 WHERE table_1.key = table_2.key AND table_2.key = table_3.key AND table_3.key = table_4.key AND table_4.key = table_5.key AND table_1.key = 1; count --------------------------------------------------------------------- 1 (1 row) SELECT * FROM relation_accesses WHERE table_name LIKE 'table_%' ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_3 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_4 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_5 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_6 | not_accessed | not_accessed | not_accessed table_7 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (7 rows) ROLLBACK; -- a simple real-time join touches all shard per table BEGIN; SELECT count(*) FROM table_1, table_2 WHERE table_1.key = table_2.key; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | parallel_access | not_parallel_accessed | not_parallel_accessed (2 rows) ROLLBACK; -- a simple real-time join touches all shard per table -- in sequential mode BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SELECT count(*) FROM table_1, table_2 WHERE table_1.key = table_2.key; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (2 rows) ROLLBACK; -- a simple subquery pushdown that touches all shards BEGIN; SELECT count(*) FROM ( SELECT random() FROM table_1, table_2, table_3, table_4, table_5 WHERE table_1.key = table_2.key AND table_2.key = table_3.key AND table_3.key = table_4.key AND table_4.key = table_5.key ) as foo; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name LIKE 'table_%' ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | parallel_access | not_parallel_accessed | not_parallel_accessed table_3 | parallel_access | not_parallel_accessed | not_parallel_accessed table_4 | parallel_access | not_parallel_accessed | not_parallel_accessed table_5 | parallel_access | not_parallel_accessed | not_parallel_accessed table_6 | not_accessed | not_accessed | not_accessed table_7 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (7 rows) ROLLBACK; -- simple multi shard update both sequential and parallel modes -- note that in multi shard modify mode we always add select -- access for all the shards accessed. But, sequential mode is OK BEGIN; UPDATE table_1 SET value = 15; SELECT * FROM relation_accesses WHERE table_name = 'table_1'; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | parallel_access | not_parallel_accessed (1 row) SET LOCAL citus.multi_shard_modify_mode = 'sequential'; UPDATE table_2 SET value = 15; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | parallel_access | not_parallel_accessed table_2 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (2 rows) ROLLBACK; -- now UPDATE/DELETE with subselect pushdown BEGIN; UPDATE table_1 SET value = 15 WHERE key IN (SELECT key FROM table_2 JOIN table_3 USING (key) WHERE table_2.value = 15); SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | parallel_access | not_parallel_accessed table_2 | parallel_access | not_parallel_accessed | not_parallel_accessed table_3 | parallel_access | not_parallel_accessed | not_parallel_accessed (3 rows) ROLLBACK; -- INSERT .. SELECT pushdown BEGIN; INSERT INTO table_2 SELECT * FROM table_1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | parallel_access | not_parallel_accessed (2 rows) ROLLBACK; -- INSERT .. SELECT pushdown in sequential mode should be OK BEGIN; SET LOCAL citus.multi_shard_modify_mode = 'sequential'; INSERT INTO table_2 SELECT * FROM table_1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (2 rows) ROLLBACK; -- coordinator INSERT .. SELECT BEGIN; -- We use offset 1 to make sure the result needs to be pulled to the coordinator, offset 0 would be optimized away INSERT INTO table_2 SELECT * FROM table_1 OFFSET 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | parallel_access | not_parallel_accessed (2 rows) ROLLBACK; -- recursively planned SELECT BEGIN; SELECT count(*) FROM ( SELECT random() FROM table_1, table_2 WHERE table_1.key = table_2.key OFFSET 0 ) as foo; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | parallel_access | not_parallel_accessed | not_parallel_accessed (2 rows) ROLLBACK; -- recursively planned SELECT and coordinator INSERT .. SELECT BEGIN; INSERT INTO table_3 (key) SELECT * FROM ( SELECT random() * 1000 FROM table_1, table_2 WHERE table_1.key = table_2.key OFFSET 0 ) as foo; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | parallel_access | not_parallel_accessed | not_parallel_accessed table_3 | not_parallel_accessed | parallel_access | not_parallel_accessed (3 rows) ROLLBACK; -- recursively planned SELECT and coordinator INSERT .. SELECT -- but modifies single shard, marked as sequential operation BEGIN; INSERT INTO table_3 (key) SELECT * FROM ( SELECT random() * 1000 FROM table_1, table_2 WHERE table_1.key = table_2.key AND table_1.key = 1 OFFSET 0 ) as foo; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_3 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) ROLLBACK; -- recursively planned SELECT and recursively planned multi-shard DELETE BEGIN; DELETE FROM table_3 where key IN ( SELECT * FROM ( SELECT table_1.key FROM table_1, table_2 WHERE table_1.key = table_2.key OFFSET 0 ) as foo ) AND value IN (SELECT key FROM table_4); SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3', 'table_4') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_2 | parallel_access | not_parallel_accessed | not_parallel_accessed table_3 | parallel_access | parallel_access | not_parallel_accessed table_4 | parallel_access | not_parallel_accessed | not_parallel_accessed (4 rows) ROLLBACK; -- copy out BEGIN; COPY (SELECT * FROM table_1 WHERE key IN (1,2,3) ORDER BY 1) TO stdout; 1 1 2 2 3 3 SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- copy in BEGIN; COPY table_1 FROM STDIN WITH CSV; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | parallel_access | not_parallel_accessed (1 row) ROLLBACK; -- copy in single shard BEGIN; COPY table_1 FROM STDIN WITH CSV; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- reference table accesses should always be a sequential BEGIN; SELECT count(*) FROM table_6; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_6'); table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_6 | reference_table_access | not_accessed | not_accessed (1 row) UPDATE table_6 SET value = 15; SELECT * FROM relation_accesses WHERE table_name IN ('table_6'); table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_6 | reference_table_access | reference_table_access | not_accessed (1 row) ALTER TABLE table_6 ADD COLUMN x INT; SELECT * FROM relation_accesses WHERE table_name IN ('table_6'); table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_6 | reference_table_access | reference_table_access | reference_table_access (1 row) ROLLBACK; -- reference table join with a distributed table BEGIN; SELECT count(*) FROM table_1 JOIN table_6 USING(key); count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_6', 'table_1') ORDER BY 1,2; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_6 | parallel_access | not_accessed | not_accessed (2 rows) ROLLBACK; -- TRUNCATE should be DDL BEGIN; TRUNCATE table_1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access (1 row) ROLLBACK; -- TRUNCATE can be a sequential DDL BEGIN; SET LOCAL citus.multi_shard_modify_mode = 'sequential'; TRUNCATE table_1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- TRUNCATE on a reference table should be sequential BEGIN; TRUNCATE table_6; SELECT * FROM relation_accesses WHERE table_name IN ('table_6') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_6 | not_accessed | not_accessed | reference_table_access (1 row) ROLLBACK; -- creating foreign keys should consider adding the placement accesses for the referenced table ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); BEGIN; ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access table_2 | not_parallel_accessed | not_parallel_accessed | parallel_access (2 rows) ROLLBACK; -- creating foreign keys should consider adding the placement accesses for the referenced table -- in sequential mode as well BEGIN; SET LOCAL citus.multi_shard_modify_mode = 'sequential'; ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_2 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (2 rows) ROLLBACK; CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time); SELECT create_distributed_table('partitioning_test', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) -- Adding partition tables via CREATE TABLE should have DDL access the partitioned table as well BEGIN; CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | parallel_access (2 rows) ROLLBACK; -- Adding partition tables via ATTACH PARTITION on local tables should have DDL access the partitioned table as well CREATE TABLE partitioning_test_2009 AS SELECT * FROM partitioning_test; BEGIN; ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | parallel_access (2 rows) COMMIT; -- Adding partition tables via ATTACH PARTITION on distributed tables should have DDL access the partitioned table as well CREATE TABLE partitioning_test_2010 AS SELECT * FROM partitioning_test; SELECT create_distributed_table('partitioning_test_2010', 'id'); create_distributed_table --------------------------------------------------------------------- (1 row) BEGIN; ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 FOR VALUES FROM ('2010-01-01') TO ('2011-01-01'); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | parallel_access (2 rows) COMMIT; -- reading from partitioned table marks all of its partitions BEGIN; SELECT count(*) FROM partitioning_test; count --------------------------------------------------------------------- 0 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | parallel_access | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | parallel_access | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | parallel_access | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- reading from partitioned table sequentially marks all of its partitions with sequential accesses BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SELECT count(*) FROM partitioning_test; count --------------------------------------------------------------------- 0 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- updating partitioned table marks all of its partitions BEGIN; UPDATE partitioning_test SET time = now(); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | parallel_access | parallel_access | not_parallel_accessed partitioning_test_2009 | parallel_access | parallel_access | not_parallel_accessed partitioning_test_2010 | parallel_access | parallel_access | not_parallel_accessed (3 rows) COMMIT; -- updating partitioned table sequentially marks all of its partitions with sequential accesses BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; UPDATE partitioning_test SET time = now(); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- DDLs on partitioned table marks all of its partitions BEGIN; ALTER TABLE partitioning_test ADD COLUMN X INT; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | parallel_access (3 rows) ROLLBACK; -- DDLs on partitioned table sequentially marks all of its partitions with sequential accesses BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; ALTER TABLE partitioning_test ADD COLUMN X INT; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) ROLLBACK; -- reading from partition table marks its parent BEGIN; SELECT count(*) FROM partitioning_test_2009; count --------------------------------------------------------------------- 0 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | parallel_access | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | parallel_access | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- rreading from partition table marks its parent with sequential accesses BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SELECT count(*) FROM partitioning_test_2009; count --------------------------------------------------------------------- 0 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- updating from partition table marks its parent BEGIN; UPDATE partitioning_test_2009 SET time = now(); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | parallel_access | parallel_access | not_parallel_accessed partitioning_test_2009 | parallel_access | parallel_access | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- updating from partition table marks its parent sequential accesses BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; UPDATE partitioning_test_2009 SET time = now(); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) COMMIT; -- DDLs on partition table marks its parent BEGIN; CREATE INDEX i1000000 ON partitioning_test_2009 (id); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) ROLLBACK; -- DDLs on partition table marks its parent in sequential mode BEGIN; SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; CREATE INDEX i1000000 ON partitioning_test_2009 (id); SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2009 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test_2010 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (3 rows) ROLLBACK; -- TRUNCATE CASCADE works fine ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); BEGIN; TRUNCATE table_1 CASCADE; NOTICE: truncate cascades to table "table_2" NOTICE: truncate cascades to table "table_2_xxxxx" NOTICE: truncate cascades to table "table_2_xxxxx" NOTICE: truncate cascades to table "table_2_xxxxx" NOTICE: truncate cascades to table "table_2_xxxxx" SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access table_2 | not_parallel_accessed | not_parallel_accessed | parallel_access (2 rows) ROLLBACK; -- CTEs with SELECT only should work fine BEGIN; WITH cte AS (SELECT count(*) FROM table_1) SELECT * FROM cte; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed (1 row) COMMIT; -- CTEs with SELECT only in sequential mode should work fine BEGIN; SET LOCAL citus.multi_shard_modify_mode = 'sequential'; WITH cte AS (SELECT count(*) FROM table_1) SELECT * FROM cte; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) COMMIT; -- modifying CTEs should work fine with multi-row inserts, which are by default in sequential BEGIN; WITH cte_1 AS (INSERT INTO table_1 VALUES (1000,1000), (1001, 1001), (1002, 1002) RETURNING *) SELECT * FROM cte_1 ORDER BY 1; key | value --------------------------------------------------------------------- 1000 | 1000 1001 | 1001 1002 | 1002 (3 rows) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- modifying CTEs should work fine with parallel mode BEGIN; WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *) SELECT count(*) FROM cte_1 ORDER BY 1; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | parallel_access | parallel_access | not_parallel_accessed (1 row) ROLLBACK; -- modifying CTEs should work fine with sequential mode BEGIN; SET LOCAL citus.multi_shard_modify_mode = 'sequential'; WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *) SELECT count(*) FROM cte_1 ORDER BY 1; count --------------------------------------------------------------------- 101 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- router planned modifying CTEs should work fine with parallel mode BEGIN; WITH cte_1 AS (UPDATE table_1 SET value = 15 WHERE key = 6 RETURNING *) SELECT count(*) FROM cte_1 ORDER BY 1; count --------------------------------------------------------------------- 1 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- router planned modifying CTEs should work fine with sequential mode BEGIN; SET LOCAL citus.multi_shard_modify_mode = 'sequential'; WITH cte_1 AS (UPDATE table_1 SET value = 15 WHERE key = 6 RETURNING *) SELECT count(*) FROM cte_1 ORDER BY 1; count --------------------------------------------------------------------- 1 (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed (1 row) ROLLBACK; -- create distributed table with data loading -- should mark both parallel dml and parallel ddl DROP TABLE table_3; CREATE TABLE table_3 (key int, value int); INSERT INTO table_3 SELECT i, i FROM generate_series(0,100) i; BEGIN; SELECT create_distributed_table('table_3', 'key'); 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($$access_tracking.table_3$$) create_distributed_table --------------------------------------------------------------------- (1 row) SELECT * FROM relation_accesses WHERE table_name IN ('table_3') ORDER BY 1; table_name | select_access | dml_access | ddl_access --------------------------------------------------------------------- table_3 | not_parallel_accessed | parallel_access | parallel_access (1 row) COMMIT; SET search_path TO 'public'; DROP SCHEMA access_tracking CASCADE; NOTICE: drop cascades to 43 other objects DETAIL: drop cascades to function access_tracking.relation_select_access_mode(oid) drop cascades to function access_tracking.relation_dml_access_mode(oid) drop cascades to function access_tracking.relation_ddl_access_mode(oid) drop cascades to function access_tracking.distributed_relation(text) drop cascades to function access_tracking.relation_access_mode_to_text(text,integer) drop cascades to view access_tracking.relation_accesses drop cascades to table access_tracking.table_1 drop cascades to table access_tracking.table_1_90930500 drop cascades to table access_tracking.table_1_90930501 drop cascades to table access_tracking.table_1_90930502 drop cascades to table access_tracking.table_1_90930503 drop cascades to table access_tracking.table_2 drop cascades to table access_tracking.table_2_90930504 drop cascades to table access_tracking.table_2_90930505 drop cascades to table access_tracking.table_2_90930506 drop cascades to table access_tracking.table_2_90930507 drop cascades to table access_tracking.table_4 drop cascades to table access_tracking.table_4_90930512 drop cascades to table access_tracking.table_4_90930513 drop cascades to table access_tracking.table_4_90930514 drop cascades to table access_tracking.table_4_90930515 drop cascades to table access_tracking.table_5 drop cascades to table access_tracking.table_5_90930516 drop cascades to table access_tracking.table_5_90930517 drop cascades to table access_tracking.table_5_90930518 drop cascades to table access_tracking.table_5_90930519 drop cascades to table access_tracking.table_6 drop cascades to table access_tracking.table_6_90930520 drop cascades to table access_tracking.table_7 drop cascades to table access_tracking.table_7_90930521 drop cascades to table access_tracking.table_7_90930522 drop cascades to table access_tracking.table_7_90930523 drop cascades to table access_tracking.table_7_90930524 drop cascades to table access_tracking.partitioning_test drop cascades to table access_tracking.partitioning_test_90930525 drop cascades to table access_tracking.partitioning_test_90930526 drop cascades to table access_tracking.partitioning_test_90930527 drop cascades to table access_tracking.partitioning_test_90930528 drop cascades to table access_tracking.table_3 drop cascades to table access_tracking.table_3_90930541 drop cascades to table access_tracking.table_3_90930542 drop cascades to table access_tracking.table_3_90930543 drop cascades to table access_tracking.table_3_90930544