citus/src/test/regress/expected/multi_partitioning.out

2220 lines
93 KiB
Plaintext

--
-- Distributed Partitioned Table Tests
--
SET citus.next_shard_id TO 1660000;
SET citus.shard_count TO 4;
SET citus.shard_replication_factor TO 1;
SET citus.enable_repartition_joins to ON;
--
-- Distributed Partitioned Table Creation Tests
--
-- 1-) Distributing partitioned table
-- create partitioned table
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
CREATE TABLE partitioning_hash_test(id int, subid int) PARTITION BY HASH(subid);
-- create its partitions
CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
CREATE TABLE partitioning_test_2010 PARTITION OF partitioning_test FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
CREATE TABLE partitioning_hash_test_0 PARTITION OF partitioning_hash_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_test_1 PARTITION OF partitioning_hash_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
-- load some data and distribute tables
INSERT INTO partitioning_test VALUES (1, '2009-06-06');
INSERT INTO partitioning_test VALUES (2, '2010-07-07');
INSERT INTO partitioning_test_2009 VALUES (3, '2009-09-09');
INSERT INTO partitioning_test_2010 VALUES (4, '2010-03-03');
INSERT INTO partitioning_hash_test VALUES (1, 2);
INSERT INTO partitioning_hash_test VALUES (2, 13);
INSERT INTO partitioning_hash_test VALUES (3, 7);
INSERT INTO partitioning_hash_test VALUES (4, 4);
-- distribute partitioned table
SELECT create_distributed_table('partitioning_test', 'id');
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($$public.partitioning_test_2009$$)
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($$public.partitioning_test_2010$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('partitioning_hash_test', 'id');
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($$public.partitioning_hash_test_0$$)
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($$public.partitioning_hash_test_1$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- see the data is loaded to shards
SELECT * FROM partitioning_test ORDER BY 1;
id | time
---------------------------------------------------------------------
1 | 06-06-2009
2 | 07-07-2010
3 | 09-09-2009
4 | 03-03-2010
(4 rows)
SELECT * FROM partitioning_hash_test ORDER BY 1;
id | subid
---------------------------------------------------------------------
1 | 2
2 | 13
3 | 7
4 | 4
(4 rows)
-- should not return results when only querying parent
SELECT * FROM ONLY partitioning_test ORDER BY 1;
id | time
---------------------------------------------------------------------
(0 rows)
SELECT * FROM ONLY partitioning_test WHERE id = 1;
id | time
---------------------------------------------------------------------
(0 rows)
SELECT * FROM ONLY partitioning_test a JOIN partitioning_hash_test b ON (a.id = b.subid) ORDER BY 1;
id | time | id | subid
---------------------------------------------------------------------
(0 rows)
-- see partitioned table and its partitions are distributed
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010')
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_test
partitioning_test_2009
partitioning_test_2010
(3 rows)
SELECT
logicalrelid, count(*)
FROM pg_dist_shard
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010')
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
partitioning_test | 4
partitioning_test_2009 | 4
partitioning_test_2010 | 4
(3 rows)
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_hash_test', 'partitioning_hash_test_0', 'partitioning_hash_test_1')
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_hash_test
partitioning_hash_test_0
partitioning_hash_test_1
(3 rows)
SELECT
logicalrelid, count(*)
FROM pg_dist_shard
WHERE logicalrelid IN ('partitioning_hash_test', 'partitioning_hash_test_0', 'partitioning_hash_test_1')
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
partitioning_hash_test | 4
partitioning_hash_test_0 | 4
partitioning_hash_test_1 | 4
(3 rows)
-- 2-) Creating partition of a distributed table
CREATE TABLE partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
-- new partition is automatically distributed as well
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_test', 'partitioning_test_2011')
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_test
partitioning_test_2011
(2 rows)
SELECT
logicalrelid, count(*)
FROM pg_dist_shard
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2011')
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
partitioning_test | 4
partitioning_test_2011 | 4
(2 rows)
-- 3-) Attaching non distributed table to a distributed table
CREATE TABLE partitioning_test_2012(id int, time date);
-- load some data
INSERT INTO partitioning_test_2012 VALUES (5, '2012-06-06');
INSERT INTO partitioning_test_2012 VALUES (6, '2012-07-07');
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2012 FOR VALUES FROM ('2012-01-01') TO ('2013-01-01');
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($$public.partitioning_test_2012$$)
-- attached partition is distributed as well
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_test', 'partitioning_test_2012')
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_test
partitioning_test_2012
(2 rows)
SELECT
logicalrelid, count(*)
FROM pg_dist_shard
WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2012')
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
partitioning_test | 4
partitioning_test_2012 | 4
(2 rows)
-- try to insert a new data to hash partitioned table
-- no partition is defined for value 5
INSERT INTO partitioning_hash_test VALUES (8, 5);
ERROR: no partition of relation "partitioning_hash_test_1660012" found for row
DETAIL: Partition key of the failing row contains (subid) = (5).
CONTEXT: while executing command on localhost:xxxxx
INSERT INTO partitioning_hash_test VALUES (9, 12);
ERROR: no partition of relation "partitioning_hash_test_1660015" found for row
DETAIL: Partition key of the failing row contains (subid) = (12).
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE partitioning_hash_test_2 (id int, subid int);
INSERT INTO partitioning_hash_test_2 VALUES (8, 5);
ALTER TABLE partitioning_hash_test ATTACH PARTITION partitioning_hash_test_2 FOR VALUES WITH (MODULUS 3, REMAINDER 2);
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($$public.partitioning_hash_test_2$$)
INSERT INTO partitioning_hash_test VALUES (9, 12);
-- see the data is loaded to shards
SELECT * FROM partitioning_test ORDER BY 1;
id | time
---------------------------------------------------------------------
1 | 06-06-2009
2 | 07-07-2010
3 | 09-09-2009
4 | 03-03-2010
5 | 06-06-2012
6 | 07-07-2012
(6 rows)
SELECT * FROM partitioning_hash_test ORDER BY 1;
id | subid
---------------------------------------------------------------------
1 | 2
2 | 13
3 | 7
4 | 4
8 | 5
9 | 12
(6 rows)
-- 4-) Attaching distributed table to distributed table
CREATE TABLE partitioning_test_2013(id int, time date);
SELECT create_distributed_table('partitioning_test_2013', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- load some data
INSERT INTO partitioning_test_2013 VALUES (7, '2013-06-06');
INSERT INTO partitioning_test_2013 VALUES (8, '2013-07-07');
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2013 FOR VALUES FROM ('2013-01-01') TO ('2014-01-01');
-- see the data is loaded to shards
SELECT * FROM partitioning_test ORDER BY 1;
id | time
---------------------------------------------------------------------
1 | 06-06-2009
2 | 07-07-2010
3 | 09-09-2009
4 | 03-03-2010
5 | 06-06-2012
6 | 07-07-2012
7 | 06-06-2013
8 | 07-07-2013
(8 rows)
-- 5-) Failure cases while creating distributed partitioned tables
-- cannot distribute a partition if its parent is not distributed
CREATE TABLE partitioning_test_failure(id int, time date) PARTITION BY RANGE (time);
CREATE TABLE partitioning_test_failure_2009 PARTITION OF partitioning_test_failure FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
SELECT create_distributed_table('partitioning_test_failure_2009', 'id');
ERROR: cannot distribute relation "partitioning_test_failure_2009" which is partition of "partitioning_test_failure"
DETAIL: Citus does not support distributing partitions if their parent is not distributed table.
HINT: Distribute the partitioned table "partitioning_test_failure" instead.
-- only hash distributed tables can have partitions
SELECT create_distributed_table('partitioning_test_failure', 'id', 'append');
ERROR: distributing partitioned tables in only supported for hash-distributed tables
SELECT create_distributed_table('partitioning_test_failure', 'id', 'range');
ERROR: distributing partitioned tables in only supported for hash-distributed tables
SELECT create_reference_table('partitioning_test_failure');
ERROR: distributing partitioned tables in only supported for hash-distributed tables
SET citus.shard_replication_factor TO 1;
-- non-distributed tables cannot have distributed partitions;
DROP TABLE partitioning_test_failure_2009;
CREATE TABLE partitioning_test_failure_2009(id int, time date);
SELECT create_distributed_table('partitioning_test_failure_2009', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
ALTER TABLE partitioning_test_failure ATTACH PARTITION partitioning_test_failure_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
ERROR: non-distributed tables cannot have distributed partitions
HINT: Distribute the partitioned table "partitioning_test_failure" instead
-- multi-level partitioning is not allowed
DROP TABLE partitioning_test_failure_2009;
CREATE TABLE partitioning_test_failure_2009 PARTITION OF partitioning_test_failure FOR VALUES FROM ('2009-01-01') TO ('2010-01-01') PARTITION BY RANGE (time);
SELECT create_distributed_table('partitioning_test_failure', 'id');
ERROR: distributing multi-level partitioned tables is not supported
DETAIL: Relation "partitioning_test_failure_2009" is partitioned table itself and it is also partition of relation "partitioning_test_failure".
-- multi-level partitioning is not allowed in different order
DROP TABLE partitioning_test_failure_2009;
SELECT create_distributed_table('partitioning_test_failure', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE partitioning_test_failure_2009 PARTITION OF partitioning_test_failure FOR VALUES FROM ('2009-01-01') TO ('2010-01-01') PARTITION BY RANGE (time);
ERROR: distributing multi-level partitioned tables is not supported
DETAIL: Relation "partitioning_test_failure_2009" is partitioned table itself and it is also partition of relation "partitioning_test_failure".
--
-- DMLs in distributed partitioned tables
--
-- test COPY
-- COPY data to partitioned table
COPY partitioning_test FROM STDIN WITH CSV;
-- COPY data to partition directly
COPY partitioning_test_2009 FROM STDIN WITH CSV;
-- see the data is loaded to shards
SELECT * FROM partitioning_test WHERE id >= 9 ORDER BY 1;
id | time
---------------------------------------------------------------------
9 | 01-01-2009
10 | 01-01-2010
11 | 01-01-2011
12 | 01-01-2012
13 | 01-02-2009
14 | 01-03-2009
(6 rows)
-- test INSERT
-- INSERT INTO the partitioned table
INSERT INTO partitioning_test VALUES(15, '2009-02-01');
INSERT INTO partitioning_test VALUES(16, '2010-02-01');
INSERT INTO partitioning_test VALUES(17, '2011-02-01');
INSERT INTO partitioning_test VALUES(18, '2012-02-01');
-- INSERT INTO the partitions directly table
INSERT INTO partitioning_test VALUES(19, '2009-02-02');
INSERT INTO partitioning_test VALUES(20, '2010-02-02');
-- see the data is loaded to shards
SELECT * FROM partitioning_test WHERE id >= 15 ORDER BY 1;
id | time
---------------------------------------------------------------------
15 | 02-01-2009
16 | 02-01-2010
17 | 02-01-2011
18 | 02-01-2012
19 | 02-02-2009
20 | 02-02-2010
(6 rows)
-- test INSERT/SELECT
-- INSERT/SELECT from partition to partitioned table
INSERT INTO partitioning_test SELECT * FROM partitioning_test_2011;
-- INSERT/SELECT from partitioned table to partition
INSERT INTO partitioning_test_2012 SELECT * FROM partitioning_test WHERE time >= '2012-01-01' AND time < '2013-01-01';
-- see the data is loaded to shards (rows in the given range should be duplicated)
SELECT * FROM partitioning_test WHERE time >= '2011-01-01' AND time < '2013-01-01' ORDER BY 1;
id | time
---------------------------------------------------------------------
5 | 06-06-2012
5 | 06-06-2012
6 | 07-07-2012
6 | 07-07-2012
11 | 01-01-2011
11 | 01-01-2011
12 | 01-01-2012
12 | 01-01-2012
17 | 02-01-2011
17 | 02-01-2011
18 | 02-01-2012
18 | 02-01-2012
(12 rows)
-- test UPDATE
-- (1) UPDATE partitioned table
UPDATE partitioning_test SET time = '2013-07-07' WHERE id = 7;
-- (2) UPDATE partition directly
UPDATE partitioning_test_2013 SET time = '2013-08-08' WHERE id = 8;
-- (3) UPDATE only the parent (noop)
UPDATE ONLY partitioning_test SET time = '2013-09-09' WHERE id = 7;
-- (4) DELETE from only the parent (noop)
DELETE FROM ONLY partitioning_test WHERE id = 7;
-- see that only (1) and (2) had an effect
SELECT * FROM partitioning_test WHERE id = 7 OR id = 8 ORDER BY 1;
id | time
---------------------------------------------------------------------
7 | 07-07-2013
8 | 08-08-2013
(2 rows)
-- UPDATE that tries to move a row to a non-existing partition (this should fail)
UPDATE partitioning_test SET time = '2020-07-07' WHERE id = 7;
ERROR: no partition of relation "partitioning_test_1660001" found for row
DETAIL: Partition key of the failing row contains ("time") = (2020-07-07).
CONTEXT: while executing command on localhost:xxxxx
-- UPDATE with subqueries on partitioned table
UPDATE
partitioning_test
SET
time = time + INTERVAL '1 day'
WHERE
id IN (SELECT id FROM partitioning_test WHERE id = 1);
-- UPDATE with subqueries on partition
UPDATE
partitioning_test_2009
SET
time = time + INTERVAL '1 month'
WHERE
id IN (SELECT id FROM partitioning_test WHERE id = 2);
-- see the data is updated
SELECT * FROM partitioning_test WHERE id = 1 OR id = 2 ORDER BY 1;
id | time
---------------------------------------------------------------------
1 | 06-07-2009
2 | 07-07-2010
(2 rows)
-- test DELETE
-- DELETE from partitioned table
DELETE FROM partitioning_test WHERE id = 9;
-- DELETE from partition directly
DELETE FROM partitioning_test_2010 WHERE id = 10;
-- see the data is deleted
SELECT * FROM partitioning_test WHERE id = 9 OR id = 10 ORDER BY 1;
id | time
---------------------------------------------------------------------
(0 rows)
-- create default partition
CREATE TABLE partitioning_test_default PARTITION OF partitioning_test DEFAULT;
\d+ partitioning_test
Table "public.partitioning_test"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
---------------------------------------------------------------------
id | integer | | | | plain | |
time | date | | | | plain | |
Partition key: RANGE ("time")
Partitions: partitioning_test_2009 FOR VALUES FROM ('01-01-2009') TO ('01-01-2010'),
partitioning_test_2010 FOR VALUES FROM ('01-01-2010') TO ('01-01-2011'),
partitioning_test_2011 FOR VALUES FROM ('01-01-2011') TO ('01-01-2012'),
partitioning_test_2012 FOR VALUES FROM ('01-01-2012') TO ('01-01-2013'),
partitioning_test_2013 FOR VALUES FROM ('01-01-2013') TO ('01-01-2014'),
partitioning_test_default DEFAULT
INSERT INTO partitioning_test VALUES(21, '2014-02-02');
INSERT INTO partitioning_test VALUES(22, '2015-04-02');
-- see they are inserted into default partition
SELECT * FROM partitioning_test WHERE id > 20 ORDER BY 1, 2;
id | time
---------------------------------------------------------------------
21 | 02-02-2014
22 | 04-02-2015
(2 rows)
SELECT * FROM partitioning_test_default ORDER BY 1, 2;
id | time
---------------------------------------------------------------------
21 | 02-02-2014
22 | 04-02-2015
(2 rows)
-- create a new partition (will fail)
CREATE TABLE partitioning_test_2014 PARTITION OF partitioning_test FOR VALUES FROM ('2014-01-01') TO ('2015-01-01');
ERROR: updated partition constraint for default partition would be violated by some row
CONTEXT: while executing command on localhost:xxxxx
BEGIN;
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_default;
CREATE TABLE partitioning_test_2014 PARTITION OF partitioning_test FOR VALUES FROM ('2014-01-01') TO ('2015-01-01');
INSERT INTO partitioning_test SELECT * FROM partitioning_test_default WHERE time >= '2014-01-01' AND time < '2015-01-01';
DELETE FROM partitioning_test_default WHERE time >= '2014-01-01' AND time < '2015-01-01';
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_default DEFAULT;
END;
-- see data is in the table, but some moved out from default partition
SELECT * FROM partitioning_test WHERE id > 20 ORDER BY 1, 2;
id | time
---------------------------------------------------------------------
21 | 02-02-2014
22 | 04-02-2015
(2 rows)
SELECT * FROM partitioning_test_default ORDER BY 1, 2;
id | time
---------------------------------------------------------------------
22 | 04-02-2015
(1 row)
-- multi-shard UPDATE on partitioned table
UPDATE partitioning_test SET time = time + INTERVAL '1 day';
-- see rows are UPDATED
SELECT * FROM partitioning_test ORDER BY 1;
id | time
---------------------------------------------------------------------
1 | 06-08-2009
2 | 07-08-2010
3 | 09-10-2009
4 | 03-04-2010
5 | 06-07-2012
5 | 06-07-2012
6 | 07-08-2012
6 | 07-08-2012
7 | 07-08-2013
8 | 08-09-2013
11 | 01-02-2011
11 | 01-02-2011
12 | 01-02-2012
12 | 01-02-2012
13 | 01-03-2009
14 | 01-04-2009
15 | 02-02-2009
16 | 02-02-2010
17 | 02-02-2011
17 | 02-02-2011
18 | 02-02-2012
18 | 02-02-2012
19 | 02-03-2009
20 | 02-03-2010
21 | 02-03-2014
22 | 04-03-2015
(26 rows)
-- multi-shard UPDATE on partition directly
UPDATE partitioning_test_2009 SET time = time + INTERVAL '1 day';
-- see rows are UPDATED
SELECT * FROM partitioning_test_2009 ORDER BY 1;
id | time
---------------------------------------------------------------------
1 | 06-09-2009
3 | 09-11-2009
13 | 01-04-2009
14 | 01-05-2009
15 | 02-03-2009
19 | 02-04-2009
(6 rows)
-- test multi-shard UPDATE which fails in workers (updated value is outside of partition bounds)
UPDATE partitioning_test_2009 SET time = time + INTERVAL '6 month';
ERROR: new row for relation "partitioning_test_2009_1660005" violates partition constraint
DETAIL: Failing row contains (3, 2010-03-11).
CONTEXT: while executing command on localhost:xxxxx
--
-- DDL in distributed partitioned tables
--
-- test CREATE INDEX
-- CREATE INDEX on partitioned table - this will error out
-- on earlier versions of postgres earlier than 11.
CREATE INDEX partitioning_index ON partitioning_test(id);
-- CREATE INDEX on partition
CREATE INDEX partitioning_2009_index ON partitioning_test_2009(id);
-- CREATE INDEX CONCURRENTLY on partition
CREATE INDEX CONCURRENTLY partitioned_2010_index ON partitioning_test_2010(id);
-- see index is created
SELECT tablename, indexname FROM pg_indexes WHERE tablename LIKE 'partitioning_test_%' ORDER BY indexname;
tablename | indexname
---------------------------------------------------------------------
partitioning_test_2010 | partitioned_2010_index
partitioning_test_2009 | partitioning_2009_index
partitioning_test_2009 | partitioning_test_2009_id_idx
partitioning_test_2010 | partitioning_test_2010_id_idx
partitioning_test_2011 | partitioning_test_2011_id_idx
partitioning_test_2012 | partitioning_test_2012_id_idx
partitioning_test_2013 | partitioning_test_2013_id_idx
partitioning_test_2014 | partitioning_test_2014_id_idx
partitioning_test_default | partitioning_test_default_id_idx
(9 rows)
-- test drop
-- indexes created on parent table can only be dropped on parent table
-- ie using the same index name
-- following will fail
DROP INDEX partitioning_test_2009_id_idx;
ERROR: cannot drop index partitioning_test_2009_id_idx because index partitioning_index requires it
HINT: You can drop index partitioning_index instead.
-- but dropping index on parent table will succeed
DROP INDEX partitioning_index;
-- this index was already created on partition table
DROP INDEX partitioning_2009_index;
-- test drop index on non-distributed, partitioned table
CREATE TABLE non_distributed_partitioned_table(a int, b int) PARTITION BY RANGE (a);
CREATE TABLE non_distributed_partitioned_table_1 PARTITION OF non_distributed_partitioned_table
FOR VALUES FROM (0) TO (10);
CREATE INDEX non_distributed_partitioned_table_index ON non_distributed_partitioned_table(a);
-- see index is created
SELECT tablename, indexname FROM pg_indexes WHERE tablename LIKE 'non_distributed_partitioned_table_%' ORDER BY indexname;
tablename | indexname
---------------------------------------------------------------------
non_distributed_partitioned_table_1 | non_distributed_partitioned_table_1_a_idx
(1 row)
-- drop the index and see it is dropped
DROP INDEX non_distributed_partitioned_table_index;
SELECT tablename, indexname FROM pg_indexes WHERE tablename LIKE 'non_distributed%' ORDER BY indexname;
tablename | indexname
---------------------------------------------------------------------
(0 rows)
-- test add COLUMN
-- add COLUMN to partitioned table
ALTER TABLE partitioning_test ADD new_column int;
-- add COLUMN to partition - this will error out
ALTER TABLE partitioning_test_2010 ADD new_column_2 int;
ERROR: cannot add column to a partition
-- see additional column is created
SELECT name, type FROM table_attrs WHERE relid = 'partitioning_test'::regclass ORDER BY 1;
name | type
---------------------------------------------------------------------
id | integer
new_column | integer
time | date
(3 rows)
SELECT name, type FROM table_attrs WHERE relid = 'partitioning_test_2010'::regclass ORDER BY 1;
name | type
---------------------------------------------------------------------
id | integer
new_column | integer
time | date
(3 rows)
-- test add PRIMARY KEY
-- add PRIMARY KEY to partitioned table - this will error out
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_primary PRIMARY KEY (id);
ERROR: unique constraint on partitioned table must include all partitioning columns
DETAIL: PRIMARY KEY constraint on table "partitioning_test" lacks column "time" which is part of the partition key.
-- ADD PRIMARY KEY to partition
ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_2009_primary PRIMARY KEY (id);
-- see PRIMARY KEY is created
SELECT
table_name,
constraint_name,
constraint_type
FROM
information_schema.table_constraints
WHERE
table_name = 'partitioning_test_2009' AND
constraint_name = 'partitioning_2009_primary';
table_name | constraint_name | constraint_type
---------------------------------------------------------------------
partitioning_test_2009 | partitioning_2009_primary | PRIMARY KEY
(1 row)
-- however, you can add primary key if it contains both distribution and partition key
ALTER TABLE partitioning_hash_test ADD CONSTRAINT partitioning_hash_primary PRIMARY KEY (id, subid);
-- see PRIMARY KEY is created
SELECT
table_name,
constraint_name,
constraint_type
FROM
information_schema.table_constraints
WHERE
table_name LIKE 'partitioning_hash_test%' AND
constraint_type = 'PRIMARY KEY'
ORDER BY 1;
table_name | constraint_name | constraint_type
---------------------------------------------------------------------
partitioning_hash_test | partitioning_hash_primary | PRIMARY KEY
partitioning_hash_test_0 | partitioning_hash_test_0_pkey | PRIMARY KEY
partitioning_hash_test_1 | partitioning_hash_test_1_pkey | PRIMARY KEY
partitioning_hash_test_2 | partitioning_hash_test_2_pkey | PRIMARY KEY
(4 rows)
-- test ADD FOREIGN CONSTRAINT
-- add FOREIGN CONSTRAINT to partitioned table -- this will error out (it is a self reference)
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_foreign FOREIGN KEY (id) REFERENCES partitioning_test_2009 (id);
ERROR: cannot ALTER TABLE "partitioning_test_2009" because it is being used by active queries in this session
-- add FOREIGN CONSTRAINT to partition
INSERT INTO partitioning_test_2009 VALUES (5, '2009-06-06');
INSERT INTO partitioning_test_2009 VALUES (6, '2009-07-07');
INSERT INTO partitioning_test_2009 VALUES(12, '2009-02-01');
INSERT INTO partitioning_test_2009 VALUES(18, '2009-02-01');
ALTER TABLE partitioning_test_2012 ADD CONSTRAINT partitioning_2012_foreign FOREIGN KEY (id) REFERENCES partitioning_test_2009 (id) ON DELETE CASCADE;
-- see FOREIGN KEY is created
SELECT "Constraint" FROM table_fkeys WHERE relid = 'partitioning_test_2012'::regclass ORDER BY 1;
Constraint
---------------------------------------------------------------------
partitioning_2012_foreign
(1 row)
-- test ON DELETE CASCADE works
DELETE FROM partitioning_test_2009 WHERE id = 5;
-- see that element is deleted from both partitions
SELECT * FROM partitioning_test_2009 WHERE id = 5 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
SELECT * FROM partitioning_test_2012 WHERE id = 5 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- test DETACH partition
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009;
-- see DETACHed partitions content is not accessible from partitioning_test;
SELECT * FROM partitioning_test WHERE time >= '2009-01-01' AND time < '2010-01-01' ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- delete from default partition
DELETE FROM partitioning_test WHERE time >= '2015-01-01';
SELECT * FROM partitioning_test_default;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- create a reference table for foreign key test
CREATE TABLE partitioning_test_reference(id int PRIMARY KEY, subid int);
INSERT INTO partitioning_test_reference SELECT a, a FROM generate_series(1, 50) a;
SELECT create_reference_table('partitioning_test_reference');
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($$public.partitioning_test_reference$$)
create_reference_table
---------------------------------------------------------------------
(1 row)
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey FOREIGN KEY (id) REFERENCES partitioning_test_reference(id) ON DELETE CASCADE;
CREATE TABLE partitioning_test_foreign_key(id int PRIMARY KEY, value int);
SELECT create_distributed_table('partitioning_test_foreign_key', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
INSERT INTO partitioning_test_foreign_key SELECT * FROM partitioning_test_reference;
ALTER TABLE partitioning_hash_test ADD CONSTRAINT partitioning_reference_fk_test FOREIGN KEY (id) REFERENCES partitioning_test_foreign_key(id) ON DELETE CASCADE;
-- check foreign keys on partitions
SELECT
table_name, constraint_name, constraint_type FROm information_schema.table_constraints
WHERE
table_name LIKE 'partitioning_hash_test%' AND
constraint_type = 'FOREIGN KEY'
ORDER BY
1,2;
table_name | constraint_name | constraint_type
---------------------------------------------------------------------
partitioning_hash_test | partitioning_reference_fk_test | FOREIGN KEY
partitioning_hash_test_0 | partitioning_reference_fk_test | FOREIGN KEY
partitioning_hash_test_1 | partitioning_reference_fk_test | FOREIGN KEY
partitioning_hash_test_2 | partitioning_reference_fk_test | FOREIGN KEY
(4 rows)
-- check foreign keys on partition shards
-- there is some text ordering issue regarding table name
-- forcing integer sort by extracting shardid
CREATE TYPE foreign_key_details AS (table_name text, constraint_name text, constraint_type text);
SELECT right(table_name, 7)::int as shardid, * FROM (
SELECT (json_populate_record(NULL::foreign_key_details,
json_array_elements_text(result::json)::json )).*
FROM run_command_on_workers($$
SELECT
COALESCE(json_agg(row_to_json(q)), '[]'::json)
FROM (
SELECT
table_name, constraint_name, constraint_type
FROM information_schema.table_constraints
WHERE
table_name LIKE 'partitioning_hash_test%' AND
constraint_type = 'FOREIGN KEY'
ORDER BY 1, 2, 3
) q
$$) ) w
ORDER BY 1, 2, 3, 4;
shardid | table_name | constraint_name | constraint_type
---------------------------------------------------------------------
1660012 | partitioning_hash_test_1660012 | partitioning_reference_fk_test_1660012 | FOREIGN KEY
1660013 | partitioning_hash_test_1660013 | partitioning_reference_fk_test_1660013 | FOREIGN KEY
1660014 | partitioning_hash_test_1660014 | partitioning_reference_fk_test_1660014 | FOREIGN KEY
1660015 | partitioning_hash_test_1660015 | partitioning_reference_fk_test_1660015 | FOREIGN KEY
1660016 | partitioning_hash_test_0_1660016 | partitioning_reference_fk_test_1660012 | FOREIGN KEY
1660017 | partitioning_hash_test_0_1660017 | partitioning_reference_fk_test_1660013 | FOREIGN KEY
1660018 | partitioning_hash_test_0_1660018 | partitioning_reference_fk_test_1660014 | FOREIGN KEY
1660019 | partitioning_hash_test_0_1660019 | partitioning_reference_fk_test_1660015 | FOREIGN KEY
1660020 | partitioning_hash_test_1_1660020 | partitioning_reference_fk_test_1660012 | FOREIGN KEY
1660021 | partitioning_hash_test_1_1660021 | partitioning_reference_fk_test_1660013 | FOREIGN KEY
1660022 | partitioning_hash_test_1_1660022 | partitioning_reference_fk_test_1660014 | FOREIGN KEY
1660023 | partitioning_hash_test_1_1660023 | partitioning_reference_fk_test_1660015 | FOREIGN KEY
1660032 | partitioning_hash_test_2_1660032 | partitioning_reference_fk_test_1660012 | FOREIGN KEY
1660033 | partitioning_hash_test_2_1660033 | partitioning_reference_fk_test_1660013 | FOREIGN KEY
1660034 | partitioning_hash_test_2_1660034 | partitioning_reference_fk_test_1660014 | FOREIGN KEY
1660035 | partitioning_hash_test_2_1660035 | partitioning_reference_fk_test_1660015 | FOREIGN KEY
(16 rows)
DROP TYPE foreign_key_details;
-- set replication factor back to 1 since it gots reset
-- after connection re-establishment
SET citus.shard_replication_factor TO 1;
SELECT * FROM partitioning_test WHERE id = 11 or id = 12;
id | time | new_column
---------------------------------------------------------------------
11 | 01-02-2011 |
11 | 01-02-2011 |
12 | 01-02-2012 |
12 | 01-02-2012 |
(4 rows)
DELETE FROM partitioning_test_reference WHERE id = 11 or id = 12;
SELECT * FROM partitioning_hash_test ORDER BY 1, 2;
id | subid
---------------------------------------------------------------------
1 | 2
2 | 13
3 | 7
4 | 4
8 | 5
9 | 12
(6 rows)
DELETE FROM partitioning_test_foreign_key WHERE id = 2 OR id = 9;
-- see data is deleted from referencing table
SELECT * FROM partitioning_test WHERE id = 11 or id = 12;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
SELECT * FROM partitioning_hash_test ORDER BY 1, 2;
id | subid
---------------------------------------------------------------------
1 | 2
3 | 7
4 | 4
8 | 5
(4 rows)
--
-- Transaction tests
--
-- DDL in transaction
BEGIN;
ALTER TABLE partitioning_test ADD newer_column int;
-- see additional column is created
SELECT name, type FROM table_attrs WHERE relid = 'partitioning_test'::regclass ORDER BY 1;
name | type
---------------------------------------------------------------------
id | integer
new_column | integer
newer_column | integer
time | date
(4 rows)
ROLLBACK;
-- see rollback is successful
SELECT name, type FROM table_attrs WHERE relid = 'partitioning_test'::regclass ORDER BY 1;
name | type
---------------------------------------------------------------------
id | integer
new_column | integer
time | date
(3 rows)
-- COPY in transaction
BEGIN;
COPY partitioning_test FROM STDIN WITH CSV;
-- see the data is loaded to shards
SELECT * FROM partitioning_test WHERE id = 22 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
22 | 01-01-2010 | 22
(1 row)
SELECT * FROM partitioning_test WHERE id = 23 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
23 | 01-01-2011 | 23
(1 row)
SELECT * FROM partitioning_test WHERE id = 24 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
24 | 01-01-2013 | 24
(1 row)
ROLLBACK;
-- see rollback is successful
SELECT * FROM partitioning_test WHERE id >= 22 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- DML in transaction
BEGIN;
-- INSERT in transaction
INSERT INTO partitioning_test VALUES(25, '2010-02-02');
-- see the data is loaded to shards
SELECT * FROM partitioning_test WHERE id = 25 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
25 | 02-02-2010 |
(1 row)
-- INSERT/SELECT in transaction
INSERT INTO partitioning_test SELECT * FROM partitioning_test WHERE id = 25;
-- see the data is loaded to shards
SELECT * FROM partitioning_test WHERE id = 25 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
25 | 02-02-2010 |
25 | 02-02-2010 |
(2 rows)
-- UPDATE in transaction
UPDATE partitioning_test SET time = '2010-10-10' WHERE id = 25;
-- see the data is updated
SELECT * FROM partitioning_test WHERE id = 25 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
25 | 10-10-2010 |
25 | 10-10-2010 |
(2 rows)
-- perform operations on partition and partioned tables together
INSERT INTO partitioning_test VALUES(26, '2010-02-02', 26);
INSERT INTO partitioning_test_2010 VALUES(26, '2010-02-02', 26);
COPY partitioning_test FROM STDIN WITH CSV;
COPY partitioning_test_2010 FROM STDIN WITH CSV;
-- see the data is loaded to shards (we should see 4 rows with same content)
SELECT * FROM partitioning_test WHERE id = 26 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
26 | 02-02-2010 | 26
26 | 02-02-2010 | 26
26 | 02-02-2010 | 26
26 | 02-02-2010 | 26
(4 rows)
ROLLBACK;
-- see rollback is successful
SELECT * FROM partitioning_test WHERE id = 26 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- DETACH and DROP in a transaction
BEGIN;
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2011;
DROP TABLE partitioning_test_2011;
COMMIT;
-- see DROPed partitions content is not accessible
SELECT * FROM partitioning_test WHERE time >= '2011-01-01' AND time < '2012-01-01' ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
--
-- Misc tests
--
-- test TRUNCATE
-- test TRUNCATE partition
TRUNCATE partitioning_test_2012;
-- see partition is TRUNCATEd
SELECT * FROM partitioning_test_2012 ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- test TRUNCATE partitioned table
TRUNCATE partitioning_test;
-- see partitioned table is TRUNCATEd
SELECT * FROM partitioning_test ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- test DROP
-- test DROP partition
INSERT INTO partitioning_test_2010 VALUES(27, '2010-02-01');
DROP TABLE partitioning_test_2010;
-- see DROPped partitions content is not accessible from partitioning_test;
SELECT * FROM partitioning_test WHERE time >= '2010-01-01' AND time < '2011-01-01' ORDER BY 1;
id | time | new_column
---------------------------------------------------------------------
(0 rows)
-- test DROP partitioned table
DROP TABLE partitioning_test;
DROP TABLE partitioning_test_reference;
-- dropping the parent should CASCADE to the children as well
SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'partitioning_test%' ORDER BY 1;
table_name
---------------------------------------------------------------------
partitioning_test_2009
partitioning_test_failure
partitioning_test_foreign_key
(3 rows)
-- test distributing partitioned table colocated with non-partitioned table
CREATE TABLE partitioned_users_table (user_id int, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint) PARTITION BY RANGE (time);
CREATE TABLE partitioned_events_table (user_id int, time timestamp, event_type int, value_2 int, value_3 float, value_4 bigint) PARTITION BY RANGE (time);
SELECT create_distributed_table('partitioned_users_table', 'user_id', colocate_with => 'users_table');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('partitioned_events_table', 'user_id', colocate_with => 'events_table');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- INSERT/SELECT from regular table to partitioned table
CREATE TABLE partitioned_users_table_2009 PARTITION OF partitioned_users_table FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
CREATE TABLE partitioned_events_table_2009 PARTITION OF partitioned_events_table FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');
INSERT INTO partitioned_events_table SELECT * FROM events_table;
INSERT INTO partitioned_users_table_2009 SELECT * FROM users_table;
--
-- Complex JOINs, subqueries, UNIONs etc...
--
-- subquery with UNIONs on partitioned table
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
FROM
(SELECT *, random()
FROM
(SELECT
"t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types"
FROM
(SELECT
"t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events
FROM(
(SELECT
"events"."user_id", "events"."time", 0 AS event
FROM
partitioned_events_table as "events"
WHERE
event_type IN (1, 2) )
UNION
(SELECT
"events"."user_id", "events"."time", 1 AS event
FROM
partitioned_events_table as "events"
WHERE
event_type IN (3, 4) )
UNION
(SELECT
"events"."user_id", "events"."time", 2 AS event
FROM
partitioned_events_table as "events"
WHERE
event_type IN (5, 6) )
UNION
(SELECT
"events"."user_id", "events"."time", 3 AS event
FROM
partitioned_events_table as "events"
WHERE
event_type IN (1, 6))) t1
GROUP BY "t1"."user_id") AS t) "q"
) AS final_query
GROUP BY types
ORDER BY types;
types | sumofeventtype
---------------------------------------------------------------------
0 | 43
1 | 44
2 | 8
3 | 25
(4 rows)
-- subquery with UNIONs on partitioned table, but only scan (empty) parent for some
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
FROM
(SELECT *, random()
FROM
(SELECT
"t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types"
FROM
(SELECT
"t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events
FROM(
(SELECT
"events"."user_id", "events"."time", 0 AS event
FROM
partitioned_events_table as "events"
WHERE
event_type IN (1, 2) )
UNION
(SELECT
"events"."user_id", "events"."time", 1 AS event
FROM
partitioned_events_table as "events"
WHERE
event_type IN (3, 4) )
UNION
(SELECT
"events"."user_id", "events"."time", 2 AS event
FROM
ONLY partitioned_events_table as "events"
WHERE
event_type IN (5, 6) )
UNION
(SELECT
"events"."user_id", "events"."time", 3 AS event
FROM
ONLY partitioned_events_table as "events"
WHERE
event_type IN (1, 6))) t1
GROUP BY "t1"."user_id") AS t) "q"
) AS final_query
GROUP BY types
ORDER BY types;
types | sumofeventtype
---------------------------------------------------------------------
0 | 43
1 | 44
(2 rows)
-- UNION and JOIN on both partitioned and regular tables
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
FROM
(SELECT
*, random()
FROM
(SELECT
"t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types"
FROM
(SELECT
"t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events
FROM (
(SELECT
*
FROM
(SELECT
"events"."time", 0 AS event, "events"."user_id"
FROM
partitioned_events_table as "events"
WHERE
event_type IN (1, 2)) events_subquery_1)
UNION
(SELECT *
FROM
(
SELECT * FROM
(
SELECT
max("events"."time"),
0 AS event,
"events"."user_id"
FROM
events_table as "events", users_table as "users"
WHERE
events.user_id = users.user_id AND
event_type IN (1, 2)
GROUP BY "events"."user_id"
) as events_subquery_5
) events_subquery_2)
UNION
(SELECT *
FROM
(SELECT
"events"."time", 2 AS event, "events"."user_id"
FROM
partitioned_events_table as "events"
WHERE
event_type IN (3, 4)) events_subquery_3)
UNION
(SELECT *
FROM
(SELECT
"events"."time", 3 AS event, "events"."user_id"
FROM
events_table as "events"
WHERE
event_type IN (5, 6)) events_subquery_4)
) t1
GROUP BY "t1"."user_id") AS t) "q"
INNER JOIN
(SELECT
"users"."user_id"
FROM
partitioned_users_table as "users"
WHERE
value_1 > 2 and value_1 < 5) AS t
ON (t.user_id = q.user_id)) as final_query
GROUP BY
types
ORDER BY
types;
types | sumofeventtype
---------------------------------------------------------------------
0 | 367
2 | 360
3 | 57
(3 rows)
-- test LIST partitioning
CREATE TABLE list_partitioned_events_table (user_id int, time date, event_type int, value_2 int, value_3 float, value_4 bigint) PARTITION BY LIST (time);
CREATE TABLE list_partitioned_events_table_2014_01_01_05 PARTITION OF list_partitioned_events_table FOR VALUES IN ('2017-11-21', '2017-11-22', '2017-11-23', '2017-11-24', '2017-11-25');
CREATE TABLE list_partitioned_events_table_2014_01_06_10 PARTITION OF list_partitioned_events_table FOR VALUES IN ('2017-11-26', '2017-11-27', '2017-11-28', '2017-11-29', '2017-11-30');
CREATE TABLE list_partitioned_events_table_2014_01_11_15 PARTITION OF list_partitioned_events_table FOR VALUES IN ('2017-12-01', '2017-12-02', '2017-12-03', '2017-12-04', '2017-12-05');
-- test distributing partitioned table colocated with another partitioned table
SELECT create_distributed_table('list_partitioned_events_table', 'user_id', colocate_with => 'partitioned_events_table');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- INSERT/SELECT from partitioned table to partitioned table
INSERT INTO
list_partitioned_events_table
SELECT
user_id,
date_trunc('day', time) as time,
event_type,
value_2,
value_3,
value_4
FROM
events_table
WHERE
time >= '2017-11-21' AND
time <= '2017-12-01';
-- LEFT JOINs used with INNER JOINs on range partitioned table, list partitioned table and non-partitioned table
SELECT
count(*) AS cnt, "generated_group_field"
FROM
(SELECT
"eventQuery"."user_id", random(), generated_group_field
FROM
(SELECT
"multi_group_wrapper_1".*, generated_group_field, random()
FROM
(SELECT *
FROM
(SELECT
"list_partitioned_events_table"."time", "list_partitioned_events_table"."user_id" as event_user_id
FROM
list_partitioned_events_table as "list_partitioned_events_table"
WHERE
user_id > 2) "temp_data_queries"
INNER JOIN
(SELECT
"users"."user_id"
FROM
partitioned_users_table as "users"
WHERE
user_id > 2 and value_2 = 1) "user_filters_1"
ON ("temp_data_queries".event_user_id = "user_filters_1".user_id)) AS "multi_group_wrapper_1"
LEFT JOIN
(SELECT
"users"."user_id" AS "user_id", value_2 AS "generated_group_field"
FROM
partitioned_users_table as "users") "left_group_by_1"
ON ("left_group_by_1".user_id = "multi_group_wrapper_1".event_user_id)) "eventQuery") "pushedDownQuery"
GROUP BY
"generated_group_field"
ORDER BY
cnt DESC, generated_group_field ASC
LIMIT 10;
cnt | generated_group_field
---------------------------------------------------------------------
1851 | 1
1077 | 4
963 | 2
955 | 3
768 | 5
639 | 0
(6 rows)
--
-- Additional partitioning features
--
-- test multi column partitioning
CREATE TABLE multi_column_partitioning(c1 int, c2 int) PARTITION BY RANGE (c1, c2);
CREATE TABLE multi_column_partitioning_0_0_10_0 PARTITION OF multi_column_partitioning FOR VALUES FROM (0, 0) TO (10, 0);
SELECT create_distributed_table('multi_column_partitioning', 'c1');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- test INSERT to multi-column partitioned table
INSERT INTO multi_column_partitioning VALUES(1, 1);
INSERT INTO multi_column_partitioning_0_0_10_0 VALUES(5, -5);
-- test INSERT to multi-column partitioned table where no suitable partition exists
INSERT INTO multi_column_partitioning VALUES(10, 1);
ERROR: no partition of relation "multi_column_partitioning_1660101" found for row
DETAIL: Partition key of the failing row contains (c1, c2) = (10, 1).
CONTEXT: while executing command on localhost:xxxxx
-- test with MINVALUE/MAXVALUE
CREATE TABLE multi_column_partitioning_10_max_20_min PARTITION OF multi_column_partitioning FOR VALUES FROM (10, MAXVALUE) TO (20, MINVALUE);
-- test INSERT to partition with MINVALUE/MAXVALUE bounds
INSERT INTO multi_column_partitioning VALUES(11, -11);
INSERT INTO multi_column_partitioning_10_max_20_min VALUES(19, -19);
-- test INSERT to multi-column partitioned table where no suitable partition exists
INSERT INTO multi_column_partitioning VALUES(20, -20);
ERROR: no partition of relation "multi_column_partitioning_1660101" found for row
DETAIL: Partition key of the failing row contains (c1, c2) = (20, -20).
CONTEXT: while executing command on localhost:xxxxx
-- see data is loaded to multi-column partitioned table
SELECT * FROM multi_column_partitioning ORDER BY 1, 2;
c1 | c2
---------------------------------------------------------------------
1 | 1
5 | -5
11 | -11
19 | -19
(4 rows)
--
-- Tests for locks on partitioned tables
--
CREATE TABLE partitioning_locks(id int, ref_id int, time date) PARTITION BY RANGE (time);
-- create its partitions
CREATE TABLE partitioning_locks_2009 PARTITION OF partitioning_locks FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
CREATE TABLE partitioning_locks_2010 PARTITION OF partitioning_locks FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
-- distribute partitioned table
SELECT create_distributed_table('partitioning_locks', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- test locks on router SELECT
BEGIN;
SELECT * FROM partitioning_locks WHERE id = 1 ORDER BY 1, 2;
id | ref_id | time
---------------------------------------------------------------------
(0 rows)
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2010 | relation | AccessShareLock
(3 rows)
COMMIT;
-- test locks on real-time SELECT
BEGIN;
SELECT * FROM partitioning_locks ORDER BY 1, 2;
id | ref_id | time
---------------------------------------------------------------------
(0 rows)
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2010 | relation | AccessShareLock
(3 rows)
COMMIT;
BEGIN;
SELECT * FROM partitioning_locks AS pl1 JOIN partitioning_locks AS pl2 ON pl1.id = pl2.ref_id ORDER BY 1, 2;
id | ref_id | time | id | ref_id | time
---------------------------------------------------------------------
(0 rows)
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2010 | relation | AccessShareLock
(3 rows)
COMMIT;
-- test locks on INSERT
BEGIN;
INSERT INTO partitioning_locks VALUES(1, 1, '2009-01-01');
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks | relation | RowExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | RowExclusiveLock
(6 rows)
COMMIT;
-- test locks on UPDATE
BEGIN;
UPDATE partitioning_locks SET time = '2009-02-01' WHERE id = 1;
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks | relation | RowExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | RowExclusiveLock
(6 rows)
COMMIT;
-- test locks on DELETE
BEGIN;
DELETE FROM partitioning_locks WHERE id = 1;
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks | relation | RowExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | RowExclusiveLock
(6 rows)
COMMIT;
-- test locks on INSERT/SELECT
CREATE TABLE partitioning_locks_for_select(id int, ref_id int, time date);
SELECT create_distributed_table('partitioning_locks_for_select', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
BEGIN;
INSERT INTO partitioning_locks SELECT * FROM partitioning_locks_for_select;
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks | relation | RowExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | RowExclusiveLock
partitioning_locks_for_select | relation | AccessShareLock
(7 rows)
COMMIT;
-- test locks on coordinator INSERT/SELECT
BEGIN;
INSERT INTO partitioning_locks SELECT * FROM partitioning_locks_for_select LIMIT 5;
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks | relation | RowExclusiveLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | RowExclusiveLock
partitioning_locks_for_select | relation | AccessShareLock
(5 rows)
COMMIT;
-- test locks on multi-shard UPDATE
BEGIN;
UPDATE partitioning_locks SET time = '2009-03-01';
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessShareLock
partitioning_locks | relation | RowExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | RowExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | RowExclusiveLock
(6 rows)
COMMIT;
-- test locks on DDL
BEGIN;
ALTER TABLE partitioning_locks ADD COLUMN new_column int;
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessExclusiveLock
partitioning_locks | relation | AccessShareLock
partitioning_locks_2009 | relation | AccessExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2010 | relation | AccessExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
(6 rows)
COMMIT;
-- test locks on TRUNCATE
BEGIN;
TRUNCATE partitioning_locks;
SELECT relation::regclass, locktype, mode FROM pg_locks WHERE relation::regclass::text LIKE 'partitioning_locks%' AND pid = pg_backend_pid() ORDER BY 1, 2, 3;
relation | locktype | mode
---------------------------------------------------------------------
partitioning_locks | relation | AccessExclusiveLock
partitioning_locks | relation | AccessShareLock
partitioning_locks_2009 | relation | AccessExclusiveLock
partitioning_locks_2009 | relation | AccessShareLock
partitioning_locks_2009 | relation | ShareLock
partitioning_locks_2010 | relation | AccessExclusiveLock
partitioning_locks_2010 | relation | AccessShareLock
partitioning_locks_2010 | relation | ShareLock
(8 rows)
COMMIT;
CREATE VIEW lockinfo AS
SELECT
logicalrelid,
CASE
WHEN l.objsubid = 5 THEN 'shard'
WHEN l.objsubid = 4 THEN 'shard_metadata'
ELSE 'colocated_shards_metadata'
END AS locktype,
mode
FROM
pg_locks AS l JOIN (select row_number() over (partition by logicalrelid order by shardminvalue) -1 as shardintervalindex, * from pg_dist_shard) AS s
ON
(l.objsubid IN (4, 5) AND l.objid = s.shardid )
OR (l.objsubid = 8
AND l.objid IN (select colocationid from pg_dist_partition AS p where p.logicalrelid = s.logicalrelid)
AND l.classid = shardintervalindex
)
WHERE
logicalrelid IN ('partitioning_locks', 'partitioning_locks_2009', 'partitioning_locks_2010')
AND pid = pg_backend_pid()
AND l.locktype = 'advisory'
ORDER BY
1, 2, 3;
-- test shard resource locks with multi-shard UPDATE
BEGIN;
UPDATE partitioning_locks_2009 SET time = '2009-03-01';
-- see the locks on parent table
SELECT * FROM lockinfo;
logicalrelid | locktype | mode
---------------------------------------------------------------------
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
(20 rows)
COMMIT;
-- test shard resource locks with TRUNCATE
BEGIN;
TRUNCATE partitioning_locks_2009;
-- see the locks on parent table
SELECT * FROM lockinfo;
logicalrelid | locktype | mode
---------------------------------------------------------------------
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
(12 rows)
COMMIT;
-- test shard resource locks with INSERT/SELECT
BEGIN;
INSERT INTO partitioning_locks_2009 SELECT * FROM partitioning_locks WHERE time >= '2009-01-01' AND time < '2010-01-01';
-- see the locks on parent table
SELECT * FROM lockinfo;
logicalrelid | locktype | mode
---------------------------------------------------------------------
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | colocated_shards_metadata | ShareLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | colocated_shards_metadata | ShareLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2009 | shard | ShareUpdateExclusiveLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
partitioning_locks_2010 | colocated_shards_metadata | ShareLock
(20 rows)
COMMIT;
-- test partition-wise join
CREATE TABLE partitioning_hash_join_test(id int, subid int) PARTITION BY HASH(subid);
CREATE TABLE partitioning_hash_join_test_0 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_join_test_1 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
CREATE TABLE partitioning_hash_join_test_2 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 2);
SELECT create_distributed_table('partitioning_hash_join_test', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT success FROM run_command_on_workers('alter system set enable_mergejoin to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_nestloop to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexonlyscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Append
-> Seq Scan on partitioning_hash_join_test_0_1660133 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_1660137 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_1660141 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_1660016 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_1660020 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_2_1660032 partitioning_hash_test_xxx
(16 rows)
-- set partition-wise join on and parallel to off
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to on');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
SET enable_partitionwise_join TO on;
ANALYZE partitioning_hash_test, partitioning_hash_join_test;
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Append
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Seq Scan on partitioning_hash_join_test_0_1660133 partitioning_hash_join_test_xxx
-> Hash
-> Seq Scan on partitioning_hash_test_0_1660016 partitioning_hash_test_xxx
-> Hash Join
Hash Cond: ((partitioning_hash_test_xxx.id = partitioning_hash_join_test_xxx.id) AND (partitioning_hash_test_xxx.subid = partitioning_hash_join_test_xxx.subid))
-> Seq Scan on partitioning_hash_test_1_1660020 partitioning_hash_test_xxx
-> Hash
-> Seq Scan on partitioning_hash_join_test_1_1660137 partitioning_hash_join_test_xxx
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Seq Scan on partitioning_hash_join_test_2_1660141 partitioning_hash_join_test_xxx
-> Hash
-> Seq Scan on partitioning_hash_test_2_1660032 partitioning_hash_test_xxx
(21 rows)
-- note that partition-wise joins only work when partition key is in the join
-- following join does not have that, therefore join will not be pushed down to
-- partitions
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: (partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id)
-> Append
-> Seq Scan on partitioning_hash_join_test_0_1660133 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_1660137 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_1660141 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_1660016 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_1660020 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_2_1660032 partitioning_hash_test_xxx
(16 rows)
-- reset partition-wise join
SELECT success FROM run_command_on_workers('alter system reset enable_partitionwise_join');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_mergejoin');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_nestloop');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexonlyscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
RESET enable_partitionwise_join;
DROP VIEW lockinfo;
DROP TABLE
IF EXISTS
partitioning_test_2009,
partitioned_events_table,
partitioned_users_table,
list_partitioned_events_table,
multi_column_partitioning,
partitioning_locks,
partitioning_locks_for_select;
-- make sure we can create a partitioned table with streaming replication
SET citus.shard_replication_factor TO 1;
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
SELECT create_distributed_table('partitioning_test', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
DROP TABLE partitioning_test;
-- make sure we can attach partitions to a distributed table in a schema
CREATE SCHEMA partitioning_schema;
CREATE TABLE partitioning_schema."schema-test"(id int, time date) PARTITION BY RANGE (time);
SELECT create_distributed_table('partitioning_schema."schema-test"', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE partitioning_schema."schema-test_2009"(id int, time date);
ALTER TABLE partitioning_schema."schema-test" ATTACH PARTITION partitioning_schema."schema-test_2009" FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
-- attached partition is distributed as well
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_schema."schema-test"'::regclass, 'partitioning_schema."schema-test_2009"'::regclass)
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_schema."schema-test"
partitioning_schema."schema-test_2009"
(2 rows)
SELECT
logicalrelid, count(*)
FROM
pg_dist_shard
WHERE
logicalrelid IN ('partitioning_schema."schema-test"'::regclass, 'partitioning_schema."schema-test_2009"'::regclass)
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
partitioning_schema."schema-test" | 4
partitioning_schema."schema-test_2009" | 4
(2 rows)
DROP TABLE partitioning_schema."schema-test";
-- make sure we can create partition of a distributed table in a schema
CREATE TABLE partitioning_schema."schema-test"(id int, time date) PARTITION BY RANGE (time);
SELECT create_distributed_table('partitioning_schema."schema-test"', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE partitioning_schema."schema-test_2009" PARTITION OF partitioning_schema."schema-test" FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
-- newly created partition is distributed as well
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_schema."schema-test"'::regclass, 'partitioning_schema."schema-test_2009"'::regclass)
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_schema."schema-test"
partitioning_schema."schema-test_2009"
(2 rows)
SELECT
logicalrelid, count(*)
FROM
pg_dist_shard
WHERE
logicalrelid IN ('partitioning_schema."schema-test"'::regclass, 'partitioning_schema."schema-test_2009"'::regclass)
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
partitioning_schema."schema-test" | 4
partitioning_schema."schema-test_2009" | 4
(2 rows)
DROP TABLE partitioning_schema."schema-test";
-- make sure creating partitioned tables works while search_path is set
CREATE TABLE partitioning_schema."schema-test"(id int, time date) PARTITION BY RANGE (time);
SET search_path = partitioning_schema;
SELECT create_distributed_table('"schema-test"', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE partitioning_schema."schema-test_2009" PARTITION OF "schema-test" FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
-- newly created partition is distributed as well
SELECT
logicalrelid
FROM
pg_dist_partition
WHERE
logicalrelid IN ('partitioning_schema."schema-test"'::regclass, 'partitioning_schema."schema-test_2009"'::regclass)
ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
"schema-test"
"schema-test_2009"
(2 rows)
SELECT
logicalrelid, count(*)
FROM
pg_dist_shard
WHERE
logicalrelid IN ('partitioning_schema."schema-test"'::regclass, 'partitioning_schema."schema-test_2009"'::regclass)
GROUP BY
logicalrelid
ORDER BY
1,2;
logicalrelid | count
---------------------------------------------------------------------
"schema-test" | 4
"schema-test_2009" | 4
(2 rows)
-- test we don't deadlock when attaching and detaching partitions from partitioned
-- tables with foreign keys
CREATE TABLE reference_table(id int PRIMARY KEY);
SELECT create_reference_table('reference_table');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE reference_table_2(id int PRIMARY KEY);
SELECT create_reference_table('reference_table_2');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
CREATE TABLE partitioning_test_2008 PARTITION OF partitioning_test FOR VALUES FROM ('2008-01-01') TO ('2009-01-01');
CREATE TABLE partitioning_test_2009 (LIKE partitioning_test);
CREATE TABLE partitioning_test_2010 (LIKE partitioning_test);
CREATE TABLE partitioning_test_2011 (LIKE partitioning_test);
-- distributing partitioning_test will also distribute partitioning_test_2008
SELECT create_distributed_table('partitioning_test', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('partitioning_test_2009', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('partitioning_test_2010', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('partitioning_test_2011', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
ALTER TABLE partitioning_test ADD CONSTRAINT partitioning_reference_fkey
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
ALTER TABLE partitioning_test_2009 ADD CONSTRAINT partitioning_reference_fkey_2009
FOREIGN KEY (id) REFERENCES reference_table(id) ON DELETE CASCADE;
INSERT INTO partitioning_test_2010 VALUES (1, '2010-02-01');
-- This should fail because of foreign key constraint violation
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
ERROR: insert or update on table "partitioning_test_2010_1660191" violates foreign key constraint "partitioning_reference_fkey_1660179"
DETAIL: Key (id)=(X) is not present in table "reference_table_1660177".
CONTEXT: while executing command on localhost:xxxxx
-- Truncate, so attaching again won't fail
TRUNCATE partitioning_test_2010;
-- Attach a table which already has the same constraint
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009
FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
-- Attach a table which doesn't have the constraint
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010
FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
-- Attach a table which has a different constraint
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2011
FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
SELECT parent_table, partition_column, partition, from_value, to_value FROM time_partitions;
parent_table | partition_column | partition | from_value | to_value
---------------------------------------------------------------------
"schema-test" | time | "schema-test_2009" | 01-01-2009 | 01-01-2010
partitioning_test | time | partitioning_test_2008 | 01-01-2008 | 01-01-2009
partitioning_test | time | partitioning_test_2009 | 01-01-2009 | 01-01-2010
partitioning_test | time | partitioning_test_2010 | 01-01-2010 | 01-01-2011
partitioning_test | time | partitioning_test_2011 | 01-01-2011 | 01-01-2012
public.non_distributed_partitioned_table | a | public.non_distributed_partitioned_table_1 | 0 | 10
(6 rows)
-- create the same partition to verify it behaves like in plain PG
CREATE TABLE partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
ERROR: relation "partitioning_test_2011" already exists
CREATE TABLE IF NOT EXISTS partitioning_test_2011 PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
NOTICE: relation "partitioning_test_2011" already exists, skipping
-- verify we can create a partition that doesn't already exist with IF NOT EXISTS
CREATE TABLE IF NOT EXISTS partitioning_test_2013 PARTITION OF partitioning_test FOR VALUES FROM ('2013-01-01') TO ('2014-01-01');
SELECT logicalrelid FROM pg_dist_partition WHERE logicalrelid IN ('partitioning_test', 'partitioning_test_2013') ORDER BY 1;
logicalrelid
---------------------------------------------------------------------
partitioning_test
partitioning_test_2013
(2 rows)
-- create the same table but that is not a partition and verify it behaves like in plain PG
CREATE TABLE not_partition(time date);
CREATE TABLE not_partition PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
ERROR: relation "not_partition" already exists
CREATE TABLE IF NOT EXISTS not_partition PARTITION OF partitioning_test FOR VALUES FROM ('2011-01-01') TO ('2012-01-01');
NOTICE: relation "not_partition" already exists, skipping
DROP TABLE not_partition;
-- verify it skips when the partition with the same name belongs to another table
CREATE TABLE another_table(id int, time date) PARTITION BY RANGE (time);
CREATE TABLE partition_of_other_table PARTITION OF another_table FOR VALUES FROM ('2014-01-01') TO ('2015-01-01');
CREATE TABLE partition_of_other_table PARTITION OF partitioning_test FOR VALUES FROM ('2014-01-01') TO ('2015-01-01');
ERROR: relation "partition_of_other_table" already exists
CREATE TABLE IF NOT EXISTS partition_of_other_table PARTITION OF partitioning_test FOR VALUES FROM ('2014-01-01') TO ('2015-01-01');
NOTICE: relation "partition_of_other_table" already exists, skipping
ALTER TABLE another_table DETACH PARTITION partition_of_other_table;
DROP TABLE another_table, partition_of_other_table;
-- test fix_pre_citus10_partitioned_table_constraint_names udf
SELECT fix_pre_citus10_partitioned_table_constraint_names('partitioning_test');
fix_pre_citus10_partitioned_table_constraint_names
---------------------------------------------------------------------
(1 row)
SELECT fix_pre_citus10_partitioned_table_constraint_names();
fix_pre_citus10_partitioned_table_constraint_names
---------------------------------------------------------------------
partitioning_test
"schema-test"
public.partitioning_hash_join_test
public.partitioning_hash_test
public.partitioning_test_failure
(5 rows)
-- the following should fail
SELECT fix_pre_citus10_partitioned_table_constraint_names('public.non_distributed_partitioned_table');
ERROR: fix_pre_citus10_partitioned_table_constraint_names can only be called for distributed partitioned tables
SELECT fix_pre_citus10_partitioned_table_constraint_names('reference_table');
ERROR: could not fix partition constraints: relation does not exist or is not partitioned
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2008;
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2009;
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2010;
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2011;
ALTER TABLE partitioning_test DETACH PARTITION partitioning_test_2013;
DROP TABLE partitioning_test_2008, partitioning_test_2009, partitioning_test_2010,
partitioning_test_2011, partitioning_test_2013, reference_table_2;
-- verify this doesn't crash and gives a debug message for dropped table
SET client_min_messages TO DEBUG1;
DROP TABLE partitioning_test, reference_table;
DEBUG: switching to sequential query execution mode
DETAIL: Table "<dropped>" is modified, which might lead to data inconsistencies or distributed deadlocks via parallel accesses to hash distributed tables due to foreign keys. Any parallel modification to those hash distributed tables in the same transaction can only be executed in sequential query execution mode
CONTEXT: SQL statement "SELECT citus_drop_all_shards(v_obj.objid, v_obj.schema_name, v_obj.object_name)"
PL/pgSQL function citus_drop_trigger() line 16 at PERFORM
DEBUG: drop cascades to 2 other objects
DETAIL: drop cascades to constraint partitioning_reference_fkey_1660179 on table partitioning_schema.partitioning_test_1660179
drop cascades to constraint partitioning_reference_fkey_1660181 on table partitioning_schema.partitioning_test_1660181
DETAIL: from localhost:xxxxx
CONTEXT: SQL statement "SELECT citus_drop_all_shards(v_obj.objid, v_obj.schema_name, v_obj.object_name)"
PL/pgSQL function citus_drop_trigger() line 16 at PERFORM
DEBUG: drop cascades to 2 other objects
DETAIL: drop cascades to constraint partitioning_reference_fkey_1660180 on table partitioning_schema.partitioning_test_1660180
drop cascades to constraint partitioning_reference_fkey_1660182 on table partitioning_schema.partitioning_test_1660182
DETAIL: from localhost:xxxxx
CONTEXT: SQL statement "SELECT citus_drop_all_shards(v_obj.objid, v_obj.schema_name, v_obj.object_name)"
PL/pgSQL function citus_drop_trigger() line 16 at PERFORM
RESET client_min_messages;
RESET SEARCH_PATH;
-- not timestamp partitioned
CREATE TABLE not_time_partitioned (x int, y int) PARTITION BY RANGE (x);
CREATE TABLE not_time_partitioned_p0 PARTITION OF not_time_partitioned DEFAULT;
CREATE TABLE not_time_partitioned_p1 PARTITION OF not_time_partitioned FOR VALUES FROM (1) TO (2);
SELECT parent_table, partition_column, partition, from_value, to_value FROM time_partitions;
parent_table | partition_column | partition | from_value | to_value
---------------------------------------------------------------------
non_distributed_partitioned_table | a | non_distributed_partitioned_table_1 | 0 | 10
not_time_partitioned | x | not_time_partitioned_p1 | 1 | 2
not_time_partitioned | x | not_time_partitioned_p0 | |
partitioning_schema."schema-test" | time | partitioning_schema."schema-test_2009" | 01-01-2009 | 01-01-2010
(4 rows)
SELECT * FROM time_partition_range('not_time_partitioned_p1');
lower_bound | upper_bound
---------------------------------------------------------------------
1 | 2
(1 row)
DROP TABLE not_time_partitioned;
-- multi-column partitioned
CREATE TABLE multi_column_partitioned (x date, y date) PARTITION BY RANGE (x, y);
CREATE TABLE multi_column_partitioned_p1 PARTITION OF multi_column_partitioned FOR VALUES FROM ('2020-01-01', '2020-01-01') TO ('2020-12-31','2020-12-31');
SELECT parent_table, partition_column, partition, from_value, to_value FROM time_partitions;
parent_table | partition_column | partition | from_value | to_value
---------------------------------------------------------------------
non_distributed_partitioned_table | a | non_distributed_partitioned_table_1 | 0 | 10
partitioning_schema."schema-test" | time | partitioning_schema."schema-test_2009" | 01-01-2009 | 01-01-2010
(2 rows)
SELECT * FROM time_partition_range('multi_column_partitioned_p1');
ERROR: relation "multi_column_partitioned_p1" is a partition with multiple partition columns
DETAIL: time_partition_range can only be used for partitions of range-partitioned tables with a single partition column
DROP TABLE multi_column_partitioned;
-- not-range-partitioned
CREATE TABLE list_partitioned (x date, y date) PARTITION BY LIST (x);
CREATE TABLE list_partitioned_p1 PARTITION OF list_partitioned FOR VALUES IN ('2020-01-01');
SELECT parent_table, partition_column, partition, from_value, to_value FROM time_partitions;
parent_table | partition_column | partition | from_value | to_value
---------------------------------------------------------------------
non_distributed_partitioned_table | a | non_distributed_partitioned_table_1 | 0 | 10
partitioning_schema."schema-test" | time | partitioning_schema."schema-test_2009" | 01-01-2009 | 01-01-2010
(2 rows)
SELECT * FROM time_partition_range('list_partitioned_p1');
ERROR: relation "list_partitioned_p1" is not a range partition
DETAIL: time_partition_range can only be used for partitions of range-partitioned tables with a single partition column
DROP TABLE list_partitioned;
-- error out when inheriting a distributed table
CREATE TABLE test_inheritance(a int, b int);
SELECT create_distributed_table('test_inheritance','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE local_inheritance (k int) INHERITS (test_inheritance);
ERROR: non-distributed tables cannot inherit distributed tables
DROP TABLE test_inheritance;
-- test worker partitioned table size functions
CREATE TABLE "events.Energy Added" (user_id int, time timestamp with time zone, data jsonb, PRIMARY KEY (user_id, time )) PARTITION BY RANGE ("time");
SELECT create_distributed_table('"events.Energy Added"', 'user_id', colocate_with:='none');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE "Energy Added_17634" PARTITION OF "events.Energy Added" FOR VALUES FROM ('2018-04-13 00:00:00+00') TO ('2018-04-14 00:00:00+00');
-- test shard cost by disk size function
SET client_min_messages TO DEBUG1;
SELECT citus_shard_cost_by_disk_size(shardid) FROM pg_dist_shard WHERE logicalrelid = '"events.Energy Added"'::regclass ORDER BY shardid LIMIT 1;
DEBUG: skipping child tables for relation named: events.Energy Added
citus_shard_cost_by_disk_size
---------------------------------------------------------------------
16384
(1 row)
RESET client_min_messages;
CREATE INDEX idx_btree_hobbies ON "events.Energy Added" USING BTREE ((data->>'location'));
\c - - - :worker_1_port
-- should not be zero because of TOAST, vm, fms
SELECT worker_partitioned_table_size(oid) FROM pg_class WHERE relname LIKE '%events.Energy Added%' ORDER BY relname LIMIT 1;
worker_partitioned_table_size
---------------------------------------------------------------------
8192
(1 row)
-- should be zero since no data
SELECT worker_partitioned_relation_size(oid) FROM pg_class WHERE relname LIKE '%events.Energy Added%' ORDER BY relname LIMIT 1;
worker_partitioned_relation_size
---------------------------------------------------------------------
0
(1 row)
-- should not be zero because of indexes + pg_table_size()
SELECT worker_partitioned_relation_total_size(oid) FROM pg_class WHERE relname LIKE '%events.Energy Added%' ORDER BY relname LIMIT 1;
worker_partitioned_relation_total_size
---------------------------------------------------------------------
24576
(1 row)
\c - - - :master_port
DROP TABLE "events.Energy Added";
DROP SCHEMA partitioning_schema CASCADE;
NOTICE: drop cascades to table partitioning_schema."schema-test"
DROP TABLE IF EXISTS
partitioning_hash_test,
partitioning_hash_join_test,
partitioning_test_failure,
non_distributed_partitioned_table,
partitioning_test_foreign_key;