Add an allow_unsafe_constraints flag for constraints without distribution column (#6237)

Co-authored-by: Marco Slot <marco.slot@gmail.com>
pull/6238/head
Marco Slot 2022-08-25 10:37:50 +02:00 committed by GitHub
parent 69d2fcf5c0
commit 9bf3c3dd5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 276 additions and 21 deletions

View File

@ -1202,6 +1202,15 @@ ErrorIfUnsupportedIndexStmt(IndexStmt *createIndexStatement)
"is currently unsupported")));
}
if (AllowUnsafeConstraints)
{
/*
* The user explicitly wants to allow the constraint without
* distribution column.
*/
return;
}
Var *partitionKey = DistPartitionKeyOrError(relationId);
List *indexParameterList = createIndexStatement->indexParams;
IndexElem *indexElement = NULL;

View File

@ -54,6 +54,12 @@
/* controlled via GUC, should be accessed via GetEnableLocalReferenceForeignKeys() */
bool EnableLocalReferenceForeignKeys = true;
/*
* GUC that controls whether to allow unique/exclude constraints without
* distribution column.
*/
bool AllowUnsafeConstraints = false;
/* Local functions forward declarations for unsupported command checks */
static void PostprocessCreateTableStmtForeignKeys(CreateStmt *createStatement);
static void PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement,
@ -2573,6 +2579,16 @@ ErrorIfUnsupportedConstraint(Relation relation, char distributionMethod,
errhint("Consider using hash partitioning.")));
}
if (AllowUnsafeConstraints)
{
/*
* The user explicitly wants to allow the constraint without
* distribution column.
*/
index_close(indexDesc, NoLock);
continue;
}
int attributeCount = indexInfo->ii_NumIndexAttrs;
AttrNumber *attributeNumberArray = indexInfo->ii_IndexAttrNumbers;

View File

@ -821,6 +821,26 @@ RegisterCitusConfigVariables(void)
GUC_NO_SHOW_ALL,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"citus.allow_unsafe_constraints",
gettext_noop("Enables unique constraints and exclusion constraints "
"that do not include a distribution column."),
gettext_noop("To enforce global uniqueness, Citus normally requires "
"that unique constraints and exclusion constraints contain "
"the distribution column. If the tuple does not include the "
"distribution column, Citus cannot ensure that the same value "
"is not present in another shard. However, in some cases the "
"index creator knows that uniqueness within the shard implies "
"global uniqueness (e.g. when indexing an expression derived "
"from the distribution column) and adding the distribution column "
"separately may not be desirable. This setting can then be used "
"to disable the check."),
&AllowUnsafeConstraints,
false,
PGC_USERSET,
GUC_NO_SHOW_ALL,
NULL, NULL, NULL);
DefineCustomBoolVariable(
"citus.allow_unsafe_locks_from_workers",
gettext_noop("Enables acquiring a distributed lock from a worker "

View File

@ -27,6 +27,12 @@ extern bool AddAllLocalTablesToMetadata;
/* controlled via GUC, should be accessed via EnableLocalReferenceForeignKeys() */
extern bool EnableLocalReferenceForeignKeys;
/*
* GUC that controls whether to allow unique/exclude constraints without
* distribution column.
*/
extern bool AllowUnsafeConstraints;
extern bool EnableUnsafeTriggers;
extern int MaxMatViewSizeToAutoRecreate;

View File

@ -279,6 +279,19 @@ SELECT create_distributed_table('products', 'product_no');
ALTER TABLE products ADD CONSTRAINT exc_name EXCLUDE USING btree (name with =);
ERROR: cannot create constraint on "products"
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE).
-- check that we can disable the constraint check for EXCLUDE
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
ALTER TABLE products ADD CONSTRAINT exc_name EXCLUDE USING btree (name with =);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',12.0);
ERROR: conflicting key value violates exclusion constraint "exc_name_1450103"
DETAIL: Key (name)=(boat) conflicts with existing key (name)=(boat).
CONTEXT: while executing command on localhost:xxxxx
ROLLBACK;
-- We can add composite exclusion
ALTER TABLE products ADD CONSTRAINT exc_pno_name EXCLUDE USING btree (product_no with =, name with =);
-- 4th command will error out since it conflicts with exc_pno_name constraint
@ -453,6 +466,46 @@ INSERT INTO products VALUES(1,'product_1', 5);
-- DDL should pick the right connections after a single INSERT
ALTER TABLE products ADD CONSTRAINT unn_pno UNIQUE(product_no);
ROLLBACK;
-- check that we can disable the constraint check for CREATE UNIQUE INDEX
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
CREATE UNIQUE INDEX ON products (name, price);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',10.0);
ERROR: duplicate key value violates unique constraint "products_name_price_idx_1450203"
DETAIL: Key (name, price)=(boat, 10.0) already exists.
CONTEXT: while executing command on localhost:xxxxx
ROLLBACK;
-- check that we can disable the constraint check for CREATE UNIQUE INDEX CONCURRENTLY
SET citus.allow_unsafe_constraints TO on;
CREATE UNIQUE INDEX CONCURRENTLY product_idx ON products (name, price);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',10.0);
ERROR: duplicate key value violates unique constraint "product_idx_1450203"
DETAIL: Key (name, price)=(boat, 10.0) already exists.
CONTEXT: while executing command on localhost:xxxxx
DROP INDEX product_idx;
TRUNCATE products;
RESET citus.allow_unsafe_constraints;
-- check that we can disable the constraint check for ADD CONSTRAINT .. PRIMARY KEY
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
ALTER TABLE products ADD CONSTRAINT products_pk PRIMARY KEY (name, price);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',10.0);
ERROR: duplicate key value violates unique constraint "products_pk_1450203"
DETAIL: Key (name, price)=(boat, 10.0) already exists.
CONTEXT: while executing command on localhost:xxxxx
ROLLBACK;
BEGIN;
-- Add constraints
ALTER TABLE products ADD CONSTRAINT unn_pno UNIQUE(product_no);

View File

@ -42,6 +42,24 @@ CREATE TABLE pk_on_non_part_col
SELECT create_distributed_table('pk_on_non_part_col', 'partition_col', 'hash');
ERROR: cannot create constraint on "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).
-- check that we can disable the constraint check
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
SELECT create_distributed_table('pk_on_non_part_col', 'partition_col', 'hash');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- not enforced across shards
INSERT INTO pk_on_non_part_col VALUES (1,1);
INSERT INTO pk_on_non_part_col VALUES (2,1);
-- enforced within shard
INSERT INTO pk_on_non_part_col VALUES (1,1);
ERROR: duplicate key value violates unique constraint "pk_on_non_part_col_pkey_365000"
DETAIL: Key (other_col)=(1) already exists.
CONTEXT: while executing command on localhost:xxxxx
END;
CREATE TABLE uq_on_non_part_col
(
partition_col integer,
@ -59,6 +77,24 @@ CREATE TABLE ex_on_non_part_col
SELECT create_distributed_table('ex_on_non_part_col', 'partition_col', 'hash');
ERROR: cannot create constraint on "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).
-- check that we can disable the constraint check
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
SELECT create_distributed_table('ex_on_non_part_col', 'partition_col', 'hash');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- not enforced across shards
INSERT INTO ex_on_non_part_col VALUES (1,1);
INSERT INTO ex_on_non_part_col VALUES (2,1);
-- enforced within shard
INSERT INTO ex_on_non_part_col VALUES (1,1);
ERROR: conflicting key value violates exclusion constraint "ex_on_non_part_col_other_col_excl_365004"
DETAIL: Key (other_col)=(1) conflicts with existing key (other_col)=(1).
CONTEXT: while executing command on localhost:xxxxx
END;
-- 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
@ -100,9 +136,37 @@ SELECT create_distributed_table('uq_two_columns', 'partition_col', 'hash');
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_365008"
ERROR: duplicate key value violates unique constraint "uq_two_columns_partition_col_other_col_key_365016"
DETAIL: Key (partition_col, other_col)=(1, 1) already exists.
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE pk_on_two_non_part_cols
(
partition_col integer,
other_col integer,
other_col_2 text,
PRIMARY KEY (other_col, other_col_2)
);
SELECT create_distributed_table('pk_on_two_non_part_cols', 'partition_col', 'hash');
ERROR: cannot create constraint on "pk_on_two_non_part_cols"
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE).
-- check that we can disable the constraint check
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
SELECT create_distributed_table('pk_on_two_non_part_cols', 'partition_col', 'hash');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- not enforced across shards
INSERT INTO pk_on_two_non_part_cols VALUES (1,1,1);
INSERT INTO pk_on_two_non_part_cols VALUES (2,1,1);
-- enforced within shard
INSERT INTO pk_on_two_non_part_cols VALUES (1,1,1);
ERROR: duplicate key value violates unique constraint "pk_on_two_non_part_cols_pkey_365020"
DETAIL: Key (other_col, other_col_2)=(1, 1) already exists.
CONTEXT: while executing command on localhost:xxxxx
END;
CREATE TABLE ex_on_part_col
(
partition_col integer,
@ -117,7 +181,7 @@ SELECT create_distributed_table('ex_on_part_col', 'partition_col', 'hash');
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_365012"
ERROR: conflicting key value violates exclusion constraint "ex_on_part_col_partition_col_excl_365024"
DETAIL: Key (partition_col)=(1) conflicts with existing key (partition_col)=(1).
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE ex_on_two_columns
@ -134,7 +198,7 @@ SELECT create_distributed_table('ex_on_two_columns', 'partition_col', 'hash');
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_365016"
ERROR: conflicting key value violates exclusion constraint "ex_on_two_columns_partition_col_other_col_excl_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:xxxxx
CREATE TABLE ex_on_two_columns_prt
@ -153,7 +217,7 @@ INSERT INTO ex_on_two_columns_prt (partition_col, other_col) VALUES (1,1);
INSERT INTO ex_on_two_columns_prt (partition_col, other_col) VALUES (1,1);
INSERT INTO ex_on_two_columns_prt (partition_col, other_col) VALUES (1,101);
INSERT INTO ex_on_two_columns_prt (partition_col, other_col) VALUES (1,101);
ERROR: conflicting key value violates exclusion constraint "ex_on_two_columns_prt_partition_col_other_col_excl_365020"
ERROR: conflicting key value violates exclusion constraint "ex_on_two_columns_prt_partition_col_other_col_excl_365032"
DETAIL: Key (partition_col, other_col)=(1, 101) conflicts with existing key (partition_col, other_col)=(1, 101).
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE ex_wrong_operator
@ -179,7 +243,7 @@ SELECT create_distributed_table('ex_overlaps', 'partition_col', 'hash');
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_365027"
ERROR: conflicting key value violates exclusion constraint "ex_overlaps_other_col_partition_col_excl_365039"
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:xxxxx
-- now show that Citus can distribute unique and EXCLUDE constraints that
@ -223,7 +287,7 @@ SELECT create_distributed_table('uq_two_columns_named', 'partition_col', 'hash')
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_365036"
ERROR: duplicate key value violates unique constraint "uq_two_columns_named_uniq_365048"
DETAIL: Key (partition_col, other_col)=(1, 1) already exists.
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE ex_on_part_col_named
@ -240,7 +304,7 @@ SELECT create_distributed_table('ex_on_part_col_named', 'partition_col', 'hash')
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_365040"
ERROR: conflicting key value violates exclusion constraint "ex_on_part_col_named_exclude_365052"
DETAIL: Key (partition_col)=(1) conflicts with existing key (partition_col)=(1).
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE ex_on_two_columns_named
@ -257,7 +321,7 @@ SELECT create_distributed_table('ex_on_two_columns_named', 'partition_col', 'has
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_365044"
ERROR: conflicting key value violates exclusion constraint "ex_on_two_columns_named_exclude_365056"
DETAIL: Key (partition_col, other_col)=(1, 1) conflicts with existing key (partition_col, other_col)=(1, 1).
CONTEXT: while executing command on localhost:xxxxx
CREATE TABLE ex_multiple_excludes
@ -276,11 +340,11 @@ SELECT create_distributed_table('ex_multiple_excludes', 'partition_col', 'hash')
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_365048"
ERROR: conflicting key value violates exclusion constraint "ex_multiple_excludes_excl1_365060"
DETAIL: Key (partition_col, other_col)=(1, 1) conflicts with existing key (partition_col, other_col)=(1, 1).
CONTEXT: while executing command on localhost:xxxxx
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_365048"
ERROR: conflicting key value violates exclusion constraint "ex_multiple_excludes_excl2_365060"
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:xxxxx
CREATE TABLE ex_wrong_operator_named
@ -306,7 +370,7 @@ SELECT create_distributed_table('ex_overlaps_named', 'partition_col', 'hash');
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_365055"
ERROR: conflicting key value violates exclusion constraint "ex_overlaps_operator_named_exclude_365067"
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:xxxxx
-- now show that Citus allows unique constraints on range-partitioned tables.
@ -336,13 +400,13 @@ SELECT create_distributed_table('check_example', 'partition_col', 'hash');
\c - - :public_worker_1_host :worker_1_port
SELECT "Column", "Type", "Definition" FROM index_attrs WHERE
relid = 'check_example_partition_col_key_365056'::regclass;
relid = 'check_example_partition_col_key_365068'::regclass;
Column | Type | Definition
---------------------------------------------------------------------
partition_col | integer | partition_col
(1 row)
SELECT "Constraint", "Definition" FROM table_checks WHERE relid='public.check_example_365056'::regclass;
SELECT "Constraint", "Definition" FROM table_checks WHERE relid='public.check_example_365068'::regclass;
Constraint | Definition
---------------------------------------------------------------------
check_example_other_col_check | CHECK (other_col >= 100)

View File

@ -521,9 +521,9 @@ SELECT tablename, indexname FROM pg_indexes WHERE schemaname = 'fix_idx_names' O
tablename | indexname
---------------------------------------------------------------------
date_partitioned_citus_local_table | date_partitioned_citus_local_table_measureid_idx
date_partitioned_citus_local_table_361377 | date_partitioned_citus_local_table_measureid_idx_361377
date_partitioned_citus_local_table_361369 | date_partitioned_citus_local_table_measureid_idx_361369
partition_local_table | partition_local_table_measureid_idx
partition_local_table_361378 | partition_local_table_measureid_idx_361378
partition_local_table_361370 | partition_local_table_measureid_idx_361370
(4 rows)
-- creating a single object should only need to trigger fixing the single object
@ -699,9 +699,9 @@ NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SET citus.enable_ddl_propagation TO 'off'
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT citus_internal_add_partition_metadata ('fix_idx_names.p2'::regclass, 'h', 'dist_col', 1370000, 's')
NOTICE: issuing SELECT citus_internal_add_partition_metadata ('fix_idx_names.p2'::regclass, 'h', 'dist_col', 1370001, 's')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing SELECT citus_internal_add_partition_metadata ('fix_idx_names.p2'::regclass, 'h', 'dist_col', 1370000, 's')
NOTICE: issuing SELECT citus_internal_add_partition_metadata ('fix_idx_names.p2'::regclass, 'h', 'dist_col', 1370001, 's')
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing WITH shard_data(relationname, shardid, storagetype, shardminvalue, shardmaxvalue) AS (VALUES ('fix_idx_names.p2'::regclass, 915002, 't'::"char", '-2147483648', '2147483647')) SELECT citus_internal_add_shard_metadata(relationname, shardid, storagetype, shardminvalue, shardmaxvalue) FROM shard_data;
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
@ -753,7 +753,7 @@ DETAIL: drop cascades to table not_partitioned
drop cascades to table not_distributed
drop cascades to table fk_table
drop cascades to table p
drop cascades to table date_partitioned_citus_local_table_361377
drop cascades to table date_partitioned_citus_local_table_361369
drop cascades to table date_partitioned_citus_local_table
drop cascades to table parent_table
SELECT citus_remove_node('localhost', :master_port);

View File

@ -62,7 +62,7 @@ test: multi_remove_node_reference_table
# ----------
test: multi_create_table
test: multi_create_table_superuser
test: multi_create_table_constraints multi_master_protocol multi_load_data multi_load_data_superuser multi_behavioral_analytics_create_table
test: multi_master_protocol multi_load_data multi_load_data_superuser multi_behavioral_analytics_create_table
test: multi_behavioral_analytics_basics multi_behavioral_analytics_single_shard_queries multi_insert_select_non_pushable_queries multi_insert_select multi_behavioral_analytics_create_table_superuser
test: multi_shard_update_delete recursive_dml_with_different_planners_executors
test: insert_select_repartition window_functions dml_recursive multi_insert_select_window

View File

@ -239,6 +239,17 @@ SELECT create_distributed_table('products', 'product_no');
-- Command below should error out since 'name' is not a distribution column
ALTER TABLE products ADD CONSTRAINT exc_name EXCLUDE USING btree (name with =);
-- check that we can disable the constraint check for EXCLUDE
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
ALTER TABLE products ADD CONSTRAINT exc_name EXCLUDE USING btree (name with =);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',12.0);
ROLLBACK;
-- We can add composite exclusion
ALTER TABLE products ADD CONSTRAINT exc_pno_name EXCLUDE USING btree (product_no with =, name with =);
@ -399,6 +410,40 @@ INSERT INTO products VALUES(1,'product_1', 5);
ALTER TABLE products ADD CONSTRAINT unn_pno UNIQUE(product_no);
ROLLBACK;
-- check that we can disable the constraint check for CREATE UNIQUE INDEX
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
CREATE UNIQUE INDEX ON products (name, price);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',10.0);
ROLLBACK;
-- check that we can disable the constraint check for CREATE UNIQUE INDEX CONCURRENTLY
SET citus.allow_unsafe_constraints TO on;
CREATE UNIQUE INDEX CONCURRENTLY product_idx ON products (name, price);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',10.0);
DROP INDEX product_idx;
TRUNCATE products;
RESET citus.allow_unsafe_constraints;
-- check that we can disable the constraint check for ADD CONSTRAINT .. PRIMARY KEY
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
ALTER TABLE products ADD CONSTRAINT products_pk PRIMARY KEY (name, price);
-- not enforced across shards
INSERT INTO products VALUES (1,'boat',10.0);
INSERT INTO products VALUES (2,'boat',11.0);
-- enforced within the shard
INSERT INTO products VALUES (1,'boat',10.0);
ROLLBACK;
BEGIN;
-- Add constraints
ALTER TABLE products ADD CONSTRAINT unn_pno UNIQUE(product_no);

View File

@ -31,6 +31,17 @@ CREATE TABLE pk_on_non_part_col
);
SELECT create_distributed_table('pk_on_non_part_col', 'partition_col', 'hash');
-- check that we can disable the constraint check
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
SELECT create_distributed_table('pk_on_non_part_col', 'partition_col', 'hash');
-- not enforced across shards
INSERT INTO pk_on_non_part_col VALUES (1,1);
INSERT INTO pk_on_non_part_col VALUES (2,1);
-- enforced within shard
INSERT INTO pk_on_non_part_col VALUES (1,1);
END;
CREATE TABLE uq_on_non_part_col
(
partition_col integer,
@ -46,6 +57,17 @@ CREATE TABLE ex_on_non_part_col
);
SELECT create_distributed_table('ex_on_non_part_col', 'partition_col', 'hash');
-- check that we can disable the constraint check
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
SELECT create_distributed_table('ex_on_non_part_col', 'partition_col', 'hash');
-- not enforced across shards
INSERT INTO ex_on_non_part_col VALUES (1,1);
INSERT INTO ex_on_non_part_col VALUES (2,1);
-- enforced within shard
INSERT INTO ex_on_non_part_col VALUES (1,1);
END;
-- 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
@ -76,6 +98,26 @@ SELECT create_distributed_table('uq_two_columns', 'partition_col', 'hash');
INSERT INTO uq_two_columns (partition_col, other_col) VALUES (1,1);
INSERT INTO uq_two_columns (partition_col, other_col) VALUES (1,1);
CREATE TABLE pk_on_two_non_part_cols
(
partition_col integer,
other_col integer,
other_col_2 text,
PRIMARY KEY (other_col, other_col_2)
);
SELECT create_distributed_table('pk_on_two_non_part_cols', 'partition_col', 'hash');
-- check that we can disable the constraint check
BEGIN;
SET LOCAL citus.allow_unsafe_constraints TO on;
SELECT create_distributed_table('pk_on_two_non_part_cols', 'partition_col', 'hash');
-- not enforced across shards
INSERT INTO pk_on_two_non_part_cols VALUES (1,1,1);
INSERT INTO pk_on_two_non_part_cols VALUES (2,1,1);
-- enforced within shard
INSERT INTO pk_on_two_non_part_cols VALUES (1,1,1);
END;
CREATE TABLE ex_on_part_col
(
partition_col integer,
@ -226,8 +268,8 @@ CREATE TABLE check_example
SELECT create_distributed_table('check_example', 'partition_col', 'hash');
\c - - :public_worker_1_host :worker_1_port
SELECT "Column", "Type", "Definition" FROM index_attrs WHERE
relid = 'check_example_partition_col_key_365056'::regclass;
SELECT "Constraint", "Definition" FROM table_checks WHERE relid='public.check_example_365056'::regclass;
relid = 'check_example_partition_col_key_365068'::regclass;
SELECT "Constraint", "Definition" FROM table_checks WHERE relid='public.check_example_365068'::regclass;
\c - - :master_host :master_port
-- Index-based constraints are created with shard-extended names, but others