-- -- MULTI_CREATE_TABLE_CONSTRAINTS -- ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 365000; ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 365000; -- test that Citus forbids unique and EXCLUDE constraints on append-partitioned tables. CREATE TABLE uniq_cns_append_tables ( partition_col integer UNIQUE, other_col integer ); SELECT master_create_distributed_table('uniq_cns_append_tables', 'partition_col', 'append'); WARNING: table "uniq_cns_append_tables" has a UNIQUE or EXCLUDE constraint DETAIL: UNIQUE constraints, EXCLUDE constraints, and PRIMARY KEYs on append-partitioned tables cannot be enforced. HINT: Consider using hash partitioning. master_create_distributed_table --------------------------------- (1 row) CREATE TABLE excl_cns_append_tables ( partition_col integer, other_col integer, EXCLUDE (partition_col WITH =) ); SELECT master_create_distributed_table('excl_cns_append_tables', 'partition_col', 'append'); WARNING: table "excl_cns_append_tables" has a UNIQUE or EXCLUDE constraint DETAIL: UNIQUE constraints, EXCLUDE constraints, and PRIMARY KEYs on append-partitioned tables cannot be enforced. HINT: Consider using hash partitioning. master_create_distributed_table --------------------------------- (1 row) -- test that Citus cannot distribute unique constraints that do not include -- the partition column on hash-partitioned tables. CREATE TABLE pk_on_non_part_col ( partition_col integer, other_col integer PRIMARY KEY ); SELECT master_create_distributed_table('pk_on_non_part_col', 'partition_col', 'hash'); ERROR: cannot distribute relation: "pk_on_non_part_col" DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE). CREATE TABLE uq_on_non_part_col ( partition_col integer, other_col integer UNIQUE ); SELECT master_create_distributed_table('uq_on_non_part_col', 'partition_col', 'hash'); ERROR: cannot distribute relation: "uq_on_non_part_col" DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE). CREATE TABLE ex_on_non_part_col ( partition_col integer, other_col integer, EXCLUDE (other_col WITH =) ); SELECT master_create_distributed_table('ex_on_non_part_col', 'partition_col', 'hash'); ERROR: cannot distribute relation: "ex_on_non_part_col" DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE). -- now show that Citus can distribute unique and EXCLUDE constraints that -- include the partition column for hash-partitioned tables. -- However, EXCLUDE constraints must include the partition column with -- an equality operator. -- These tests are for UNNAMED constraints. CREATE TABLE pk_on_part_col ( partition_col integer PRIMARY KEY, other_col integer ); SELECT master_create_distributed_table('pk_on_part_col', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) CREATE TABLE uq_part_col ( partition_col integer UNIQUE, other_col integer ); SELECT master_create_distributed_table('uq_part_col', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) CREATE TABLE uq_two_columns ( partition_col integer, other_col integer, UNIQUE (partition_col, other_col) ); SELECT master_create_distributed_table('uq_two_columns', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('uq_two_columns', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO uq_two_columns (partition_col, other_col) VALUES (1,1); INSERT INTO uq_two_columns (partition_col, other_col) VALUES (1,1); ERROR: duplicate key value violates unique constraint "uq_two_columns_partition_col_other_col_key_365000" DETAIL: Key (partition_col, other_col)=(1, 1) already exists. CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_on_part_col ( partition_col integer, other_col integer, EXCLUDE (partition_col WITH =) ); SELECT master_create_distributed_table('ex_on_part_col', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_on_part_col', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_on_part_col (partition_col, other_col) VALUES (1,1); INSERT INTO ex_on_part_col (partition_col, other_col) VALUES (1,2); ERROR: conflicting key value violates exclusion constraint "ex_on_part_col_partition_col_excl_365004" DETAIL: Key (partition_col)=(1) conflicts with existing key (partition_col)=(1). CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_on_two_columns ( partition_col integer, other_col integer, EXCLUDE (partition_col WITH =, other_col WITH =) ); SELECT master_create_distributed_table('ex_on_two_columns', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_on_two_columns', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_on_two_columns (partition_col, other_col) VALUES (1,1); INSERT INTO ex_on_two_columns (partition_col, other_col) VALUES (1,1); ERROR: conflicting key value violates exclusion constraint "ex_on_two_columns_partition_col_other_col_excl_365008" DETAIL: Key (partition_col, other_col)=(1, 1) conflicts with existing key (partition_col, other_col)=(1, 1). CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_wrong_operator ( partition_col tsrange, other_col tsrange, EXCLUDE USING gist (other_col WITH =, partition_col WITH &&) ); SELECT master_create_distributed_table('ex_wrong_operator', 'partition_col', 'hash'); ERROR: cannot distribute relation: "ex_wrong_operator" DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE). CREATE TABLE ex_overlaps ( partition_col tsrange, other_col tsrange, EXCLUDE USING gist (other_col WITH &&, partition_col WITH =) ); SELECT master_create_distributed_table('ex_overlaps', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_overlaps', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_overlaps (partition_col, other_col) VALUES ('[2016-01-01 00:00:00, 2016-02-01 00:00:00]', '[2016-01-01 00:00:00, 2016-02-01 00:00:00]'); INSERT INTO ex_overlaps (partition_col, other_col) VALUES ('[2016-01-01 00:00:00, 2016-02-01 00:00:00]', '[2016-01-15 00:00:00, 2016-02-01 00:00:00]'); ERROR: conflicting key value violates exclusion constraint "ex_overlaps_other_col_partition_col_excl_365015" DETAIL: Key (other_col, partition_col)=(["2016-01-15 00:00:00","2016-02-01 00:00:00"], ["2016-01-01 00:00:00","2016-02-01 00:00:00"]) conflicts with existing key (other_col, partition_col)=(["2016-01-01 00:00:00","2016-02-01 00:00:00"], ["2016-01-01 00:00:00","2016-02-01 00:00:00"]). CONTEXT: while executing command on localhost:57638 -- now show that Citus can distribute unique and EXCLUDE constraints that -- include the partition column, for hash-partitioned tables. -- However, EXCLUDE constraints must include the partition column with -- an equality operator. -- These tests are for NAMED constraints. CREATE TABLE pk_on_part_col_named ( partition_col integer CONSTRAINT pk_on_part_col_named_pk PRIMARY KEY, other_col integer ); SELECT master_create_distributed_table('pk_on_part_col_named', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) CREATE TABLE uq_part_col_named ( partition_col integer CONSTRAINT uq_part_col_named_uniq UNIQUE, other_col integer ); SELECT master_create_distributed_table('uq_part_col_named', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) CREATE TABLE uq_two_columns_named ( partition_col integer, other_col integer, CONSTRAINT uq_two_columns_named_uniq UNIQUE (partition_col, other_col) ); SELECT master_create_distributed_table('uq_two_columns_named', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('uq_two_columns_named', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO uq_two_columns_named (partition_col, other_col) VALUES (1,1); INSERT INTO uq_two_columns_named (partition_col, other_col) VALUES (1,1); ERROR: duplicate key value violates unique constraint "uq_two_columns_named_uniq_365016" DETAIL: Key (partition_col, other_col)=(1, 1) already exists. CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_on_part_col_named ( partition_col integer, other_col integer, CONSTRAINT ex_on_part_col_named_exclude EXCLUDE (partition_col WITH =) ); SELECT master_create_distributed_table('ex_on_part_col_named', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_on_part_col_named', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_on_part_col_named (partition_col, other_col) VALUES (1,1); INSERT INTO ex_on_part_col_named (partition_col, other_col) VALUES (1,2); ERROR: conflicting key value violates exclusion constraint "ex_on_part_col_named_exclude_365020" DETAIL: Key (partition_col)=(1) conflicts with existing key (partition_col)=(1). CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_on_two_columns_named ( partition_col integer, other_col integer, CONSTRAINT ex_on_two_columns_named_exclude EXCLUDE (partition_col WITH =, other_col WITH =) ); SELECT master_create_distributed_table('ex_on_two_columns_named', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_on_two_columns_named', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_on_two_columns_named (partition_col, other_col) VALUES (1,1); INSERT INTO ex_on_two_columns_named (partition_col, other_col) VALUES (1,1); ERROR: conflicting key value violates exclusion constraint "ex_on_two_columns_named_exclude_365024" DETAIL: Key (partition_col, other_col)=(1, 1) conflicts with existing key (partition_col, other_col)=(1, 1). CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_multiple_excludes ( partition_col integer, other_col integer, other_other_col integer, CONSTRAINT ex_multiple_excludes_excl1 EXCLUDE (partition_col WITH =, other_col WITH =), CONSTRAINT ex_multiple_excludes_excl2 EXCLUDE (partition_col WITH =, other_other_col WITH =) ); SELECT master_create_distributed_table('ex_multiple_excludes', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_multiple_excludes', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_multiple_excludes (partition_col, other_col, other_other_col) VALUES (1,1,1); INSERT INTO ex_multiple_excludes (partition_col, other_col, other_other_col) VALUES (1,1,2); ERROR: conflicting key value violates exclusion constraint "ex_multiple_excludes_excl1_365028" DETAIL: Key (partition_col, other_col)=(1, 1) conflicts with existing key (partition_col, other_col)=(1, 1). CONTEXT: while executing command on localhost:57637 INSERT INTO ex_multiple_excludes (partition_col, other_col, other_other_col) VALUES (1,2,1); ERROR: conflicting key value violates exclusion constraint "ex_multiple_excludes_excl2_365028" DETAIL: Key (partition_col, other_other_col)=(1, 1) conflicts with existing key (partition_col, other_other_col)=(1, 1). CONTEXT: while executing command on localhost:57637 CREATE TABLE ex_wrong_operator_named ( partition_col tsrange, other_col tsrange, CONSTRAINT ex_wrong_operator_named_exclude EXCLUDE USING gist (other_col WITH =, partition_col WITH &&) ); SELECT master_create_distributed_table('ex_wrong_operator_named', 'partition_col', 'hash'); ERROR: cannot distribute relation: "ex_wrong_operator_named" DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE). CREATE TABLE ex_overlaps_named ( partition_col tsrange, other_col tsrange, CONSTRAINT ex_overlaps_operator_named_exclude EXCLUDE USING gist (other_col WITH &&, partition_col WITH =) ); SELECT master_create_distributed_table('ex_overlaps_named', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('ex_overlaps_named', '4', '2'); master_create_worker_shards ----------------------------- (1 row) INSERT INTO ex_overlaps_named (partition_col, other_col) VALUES ('[2016-01-01 00:00:00, 2016-02-01 00:00:00]', '[2016-01-01 00:00:00, 2016-02-01 00:00:00]'); INSERT INTO ex_overlaps_named (partition_col, other_col) VALUES ('[2016-01-01 00:00:00, 2016-02-01 00:00:00]', '[2016-01-15 00:00:00, 2016-02-01 00:00:00]'); ERROR: conflicting key value violates exclusion constraint "ex_overlaps_operator_named_exclude_365035" DETAIL: Key (other_col, partition_col)=(["2016-01-15 00:00:00","2016-02-01 00:00:00"], ["2016-01-01 00:00:00","2016-02-01 00:00:00"]) conflicts with existing key (other_col, partition_col)=(["2016-01-01 00:00:00","2016-02-01 00:00:00"], ["2016-01-01 00:00:00","2016-02-01 00:00:00"]). CONTEXT: while executing command on localhost:57638 -- now show that Citus allows unique constraints on range-partitioned tables. CREATE TABLE uq_range_tables ( partition_col integer UNIQUE, other_col integer ); SELECT master_create_distributed_table('uq_range_tables', 'partition_col', 'range'); master_create_distributed_table --------------------------------- (1 row) -- show that CHECK constraints are distributed. CREATE TABLE check_example ( partition_col integer UNIQUE, other_col integer CHECK (other_col >= 100), other_other_col integer CHECK (abs(other_other_col) >= 100) ); SELECT master_create_distributed_table('check_example', 'partition_col', 'hash'); master_create_distributed_table --------------------------------- (1 row) SELECT master_create_worker_shards('check_example', '2', '2'); master_create_worker_shards ----------------------------- (1 row) \c - - - :worker_1_port \d check_example* Table "public.check_example_365036" Column | Type | Modifiers -----------------+---------+----------- partition_col | integer | other_col | integer | other_other_col | integer | Indexes: "check_example_partition_col_key_365036" UNIQUE CONSTRAINT, btree (partition_col) Check constraints: "check_example_other_col_check" CHECK (other_col >= 100) "check_example_other_other_col_check" CHECK (abs(other_other_col) >= 100) Table "public.check_example_365037" Column | Type | Modifiers -----------------+---------+----------- partition_col | integer | other_col | integer | other_other_col | integer | Indexes: "check_example_partition_col_key_365037" UNIQUE CONSTRAINT, btree (partition_col) Check constraints: "check_example_other_col_check" CHECK (other_col >= 100) "check_example_other_other_col_check" CHECK (abs(other_other_col) >= 100) Index "public.check_example_partition_col_key_365036" Column | Type | Definition ---------------+---------+--------------- partition_col | integer | partition_col unique, btree, for table "public.check_example_365036" Index "public.check_example_partition_col_key_365037" Column | Type | Definition ---------------+---------+--------------- partition_col | integer | partition_col unique, btree, for table "public.check_example_365037" \c - - - :worker_2_port \d check_example* Table "public.check_example_365036" Column | Type | Modifiers -----------------+---------+----------- partition_col | integer | other_col | integer | other_other_col | integer | Indexes: "check_example_partition_col_key_365036" UNIQUE CONSTRAINT, btree (partition_col) Check constraints: "check_example_other_col_check" CHECK (other_col >= 100) "check_example_other_other_col_check" CHECK (abs(other_other_col) >= 100) Table "public.check_example_365037" Column | Type | Modifiers -----------------+---------+----------- partition_col | integer | other_col | integer | other_other_col | integer | Indexes: "check_example_partition_col_key_365037" UNIQUE CONSTRAINT, btree (partition_col) Check constraints: "check_example_other_col_check" CHECK (other_col >= 100) "check_example_other_other_col_check" CHECK (abs(other_other_col) >= 100) Index "public.check_example_partition_col_key_365036" Column | Type | Definition ---------------+---------+--------------- partition_col | integer | partition_col unique, btree, for table "public.check_example_365036" Index "public.check_example_partition_col_key_365037" Column | Type | Definition ---------------+---------+--------------- partition_col | integer | partition_col unique, btree, for table "public.check_example_365037" \c - - - :master_port -- drop unnecessary tables DROP TABLE pk_on_non_part_col, uq_on_non_part_col CASCADE; DROP TABLE pk_on_part_col, uq_part_col, uq_two_columns CASCADE; DROP TABLE ex_on_part_col, ex_on_two_columns, ex_multiple_excludes, ex_overlaps CASCADE; DROP TABLE ex_on_part_col_named, ex_on_two_columns_named, ex_overlaps_named CASCADE; DROP TABLE uq_range_tables, check_example CASCADE;