diff --git a/src/backend/distributed/commands/table.c b/src/backend/distributed/commands/table.c index ddb4e5ace..fe256feeb 100644 --- a/src/backend/distributed/commands/table.c +++ b/src/backend/distributed/commands/table.c @@ -1060,11 +1060,13 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement) case AT_EnableTrigAll: case AT_DisableTrigAll: case AT_ReplicaIdentity: + case AT_ValidateConstraint: { /* * We will not perform any special check for ALTER TABLE DROP CONSTRAINT * , ALTER TABLE .. ALTER COLUMN .. SET NOT NULL and ALTER TABLE ENABLE/ - * DISABLE TRIGGER ALL, ALTER TABLE .. REPLICA IDENTITY .. + * DISABLE TRIGGER ALL, ALTER TABLE .. REPLICA IDENTITY .., ALTER TABLE + * .. VALIDATE CONSTRAINT .. */ break; } @@ -1083,7 +1085,7 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("alter table command is currently unsupported"), errdetail("Only ADD|DROP COLUMN, SET|DROP NOT NULL, " - "SET|DROP DEFAULT, ADD|DROP CONSTRAINT, " + "SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, " "SET (), RESET (), " "ATTACH|DETACH PARTITION and TYPE subcommands " "are supported."))); diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c index 9d5cbd390..2d4dea85b 100644 --- a/src/backend/distributed/relay/relay_event_utility.c +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -113,7 +113,11 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId) AppendShardIdToConstraintName(command, shardId); } - if (command->subtype == AT_DropConstraint) + else if (command->subtype == AT_DropConstraint) + { + AppendShardIdToConstraintName(command, shardId); + } + else if (command->subtype == AT_ValidateConstraint) { AppendShardIdToConstraintName(command, shardId); } @@ -598,7 +602,8 @@ AppendShardIdToConstraintName(AlterTableCmd *command, uint64 shardId) char **constraintName = &(constraint->conname); AppendShardIdToName(constraintName, shardId); } - else if (command->subtype == AT_DropConstraint) + else if (command->subtype == AT_DropConstraint || + command->subtype == AT_ValidateConstraint) { char **constraintName = &(command->name); AppendShardIdToName(constraintName, shardId); diff --git a/src/test/regress/expected/foreign_key_to_reference_table.out b/src/test/regress/expected/foreign_key_to_reference_table.out index a3e42af88..8b73fa63d 100644 --- a/src/test/regress/expected/foreign_key_to_reference_table.out +++ b/src/test/regress/expected/foreign_key_to_reference_table.out @@ -1,6 +1,13 @@ -- -- FOREIGN_KEY_TO_REFERENCE_TABLE -- +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine; + version_above_nine +-------------------- + t +(1 row) + CREATE SCHEMA fkey_reference_table; SET search_path TO 'fkey_reference_table'; SET citus.shard_replication_factor TO 1; @@ -28,7 +35,9 @@ SELECT relid::regclass::text, refd_relid::regclass::text FROM - table_fkey_cols + table_fkey_cols + WHERE + "schema" = 'fkey_reference_table' ) d $$ )).RESULT::json )::json )).* ; CREATE TABLE referenced_table(id int UNIQUE, test_column int); @@ -722,38 +731,6 @@ INSERT INTO referencing_table SELECT x,(random()*1000)::int FROM generate_series DROP TABLE referenced_table CASCADE; NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; --- In the following test, we show that Citus currently does not support --- VALIDATE command. -CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); -CREATE TABLE referencing_table(id int, ref_id int DEFAULT -1); -SELECT create_reference_table('referenced_table'); - create_reference_table ------------------------- - -(1 row) - -SELECT create_distributed_table('referencing_table', 'id'); - create_distributed_table --------------------------- - -(1 row) - -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column) ON DELETE SET DEFAULT NOT VALID; --- Even if the foreign constraint is added with "NOT VALID", --- we make sure that it is still applied to the upcoming inserts. -INSERT INTO referenced_table SELECT x, x FROM generate_series(0,1000) AS f(x); -INSERT INTO referencing_table SELECT x, x FROM generate_series(0,1000) AS f(x); --- we expect this to fail because of the foreign constraint. -INSERT INTO referencing_table SELECT x, x FROM generate_series(1000,1001) AS f(x); -ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220" -DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000214". --- currently not supported -ALTER TABLE referencing_table VALIDATE CONSTRAINT fkey_ref; -ERROR: alter table command is currently unsupported -DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. -DROP TABLE referenced_table CASCADE; -NOTICE: drop cascades to constraint fkey_ref on table referencing_table -DROP TABLE referencing_table CASCADE; -- In the following tests, we create a foreign constraint with -- ON UPDATE CASCADE and see if it works properly with cascading upsert CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); @@ -845,38 +822,38 @@ ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (id) REFE SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------+------------------------------------------------+------------------------------------------------ - fkey_ref_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000233 - foreign_key_2_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000234 + fkey_ref_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000227 | fkey_reference_table.referencing_table_7000227 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000228 | fkey_reference_table.referencing_table_7000228 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000229 | fkey_reference_table.referencing_table_7000229 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000230 | fkey_reference_table.referencing_table_7000230 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000231 | fkey_reference_table.referencing_table_7000231 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000232 | fkey_reference_table.referencing_table_7000232 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000233 | fkey_reference_table.referencing_table_7000233 | fkey_reference_table.referenced_table_7000224 + foreign_key_2_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000227 | fkey_reference_table.referencing_table_7000227 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000228 | fkey_reference_table.referencing_table_7000228 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000229 | fkey_reference_table.referencing_table_7000229 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000230 | fkey_reference_table.referencing_table_7000230 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000231 | fkey_reference_table.referencing_table_7000231 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000232 | fkey_reference_table.referencing_table_7000232 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000233 | fkey_reference_table.referencing_table_7000233 | fkey_reference_table.referenced_table2_7000225 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x); -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x); -ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242" -DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234". +ERROR: insert or update on table "referencing_table_7000227" violates foreign key constraint "foreign_key_2_7000227" +DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000225". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242" -DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234". +ERROR: insert or update on table "referencing_table_7000227" violates foreign key constraint "foreign_key_2_7000227" +DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000225". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x); -ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "fkey_ref_7000242" -DETAIL: Key (id)=(1023) is not present in table "referenced_table_7000233". +ERROR: insert or update on table "referencing_table_7000227" violates foreign key constraint "fkey_ref_7000227" +DETAIL: Key (id)=(1005) is not present in table "referenced_table_7000224". -- should success INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x); SELECT count(*) FROM referencing_table; @@ -972,38 +949,38 @@ COMMIT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------+------------------------------------------------+------------------------------------------------ - fkey_ref_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000253 - foreign_key_2_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table2_7000254 + fkey_ref_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000247 | fkey_reference_table.referencing_table_7000247 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000248 | fkey_reference_table.referencing_table_7000248 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000249 | fkey_reference_table.referencing_table_7000249 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000250 | fkey_reference_table.referencing_table_7000250 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000251 | fkey_reference_table.referencing_table_7000251 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000252 | fkey_reference_table.referencing_table_7000252 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000253 | fkey_reference_table.referencing_table_7000253 | fkey_reference_table.referenced_table_7000244 + foreign_key_2_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000247 | fkey_reference_table.referencing_table_7000247 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000248 | fkey_reference_table.referencing_table_7000248 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000249 | fkey_reference_table.referencing_table_7000249 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000250 | fkey_reference_table.referencing_table_7000250 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000251 | fkey_reference_table.referencing_table_7000251 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000252 | fkey_reference_table.referencing_table_7000252 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000253 | fkey_reference_table.referencing_table_7000253 | fkey_reference_table.referenced_table2_7000245 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x); -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x); -ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260" -DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254". +ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "foreign_key_2_7000251" +DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000245". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260" -DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254". +ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "foreign_key_2_7000251" +DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000245". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x); -ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "fkey_ref_7000260" -DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000253". +ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "fkey_ref_7000251" +DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000244". -- should success INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x); SELECT count(*) FROM referencing_table; @@ -1105,43 +1082,43 @@ COMMIT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid --------------------------+-------------------------------------------------+------------------------------------------------ - fkey_ref_7000274 | fkey_reference_table.referencing_table_7000274 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000275 | fkey_reference_table.referencing_table_7000275 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000276 | fkey_reference_table.referencing_table_7000276 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000277 | fkey_reference_table.referencing_table_7000277 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000278 | fkey_reference_table.referencing_table_7000278 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000279 | fkey_reference_table.referencing_table_7000279 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000280 | fkey_reference_table.referencing_table_7000280 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000281 | fkey_reference_table.referencing_table_7000281 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referenced_table_7000273 - fkey_ref_to_dist_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referencing_table_7000274 - fkey_ref_to_dist_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referencing_table_7000275 - fkey_ref_to_dist_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referencing_table_7000276 - fkey_ref_to_dist_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referencing_table_7000277 - fkey_ref_to_dist_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referencing_table_7000278 - fkey_ref_to_dist_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referencing_table_7000279 - fkey_ref_to_dist_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referencing_table_7000280 - fkey_ref_to_dist_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referencing_table_7000281 + fkey_ref_7000265 | fkey_reference_table.referencing_table_7000265 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000266 | fkey_reference_table.referencing_table_7000266 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000267 | fkey_reference_table.referencing_table_7000267 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000268 | fkey_reference_table.referencing_table_7000268 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000269 | fkey_reference_table.referencing_table_7000269 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000270 | fkey_reference_table.referencing_table_7000270 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000271 | fkey_reference_table.referencing_table_7000271 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000272 | fkey_reference_table.referencing_table_7000272 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000274 | fkey_reference_table.referencing_table2_7000274 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000275 | fkey_reference_table.referencing_table2_7000275 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000276 | fkey_reference_table.referencing_table2_7000276 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000277 | fkey_reference_table.referencing_table2_7000277 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000278 | fkey_reference_table.referencing_table2_7000278 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000279 | fkey_reference_table.referencing_table2_7000279 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000280 | fkey_reference_table.referencing_table2_7000280 | fkey_reference_table.referenced_table_7000264 + fkey_ref_to_dist_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referencing_table_7000265 + fkey_ref_to_dist_7000274 | fkey_reference_table.referencing_table2_7000274 | fkey_reference_table.referencing_table_7000266 + fkey_ref_to_dist_7000275 | fkey_reference_table.referencing_table2_7000275 | fkey_reference_table.referencing_table_7000267 + fkey_ref_to_dist_7000276 | fkey_reference_table.referencing_table2_7000276 | fkey_reference_table.referencing_table_7000268 + fkey_ref_to_dist_7000277 | fkey_reference_table.referencing_table2_7000277 | fkey_reference_table.referencing_table_7000269 + fkey_ref_to_dist_7000278 | fkey_reference_table.referencing_table2_7000278 | fkey_reference_table.referencing_table_7000270 + fkey_ref_to_dist_7000279 | fkey_reference_table.referencing_table2_7000279 | fkey_reference_table.referencing_table_7000271 + fkey_ref_to_dist_7000280 | fkey_reference_table.referencing_table2_7000280 | fkey_reference_table.referencing_table_7000272 (24 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); -- should fail INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x); -ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284" -DETAIL: Key (id)=(4) is not present in table "referencing_table_7000276". +ERROR: insert or update on table "referencing_table2_7000274" violates foreign key constraint "fkey_ref_to_dist_7000274" +DETAIL: Key (id)=(5) is not present in table "referencing_table_7000266". -- should success INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -- should fail INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x); -ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284" -DETAIL: Key (id)=(408) is not present in table "referencing_table_7000276". +ERROR: insert or update on table "referencing_table2_7000274" violates foreign key constraint "fkey_ref_to_dist_7000274" +DETAIL: Key (id)=(403) is not present in table "referencing_table_7000266". -- should success INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x); DELETE FROM referenced_table WHERE test_column < 200; @@ -1239,22 +1216,22 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id, ref_i SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.referencing%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------------------------------+------------------------------------------------------------+------------------------------------------------ - fkey_ref_7000308 | fkey_reference_table.referencing_table_7000308 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000309 | fkey_reference_table.referencing_table_7000309 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000310 | fkey_reference_table.referencing_table_7000310 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000311 | fkey_reference_table.referencing_table_7000311 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000312 | fkey_reference_table.referencing_table_7000312 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000313 | fkey_reference_table.referencing_table_7000313 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000314 | fkey_reference_table.referencing_table_7000314 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000315 | fkey_reference_table.referencing_table_7000315 | fkey_reference_table.referenced_table_7000307 - referencing_referencing_table_id_fkey_7000316 | fkey_reference_table.referencing_referencing_table_7000316 | fkey_reference_table.referencing_table_7000308 - referencing_referencing_table_id_fkey_7000317 | fkey_reference_table.referencing_referencing_table_7000317 | fkey_reference_table.referencing_table_7000309 - referencing_referencing_table_id_fkey_7000318 | fkey_reference_table.referencing_referencing_table_7000318 | fkey_reference_table.referencing_table_7000310 - referencing_referencing_table_id_fkey_7000319 | fkey_reference_table.referencing_referencing_table_7000319 | fkey_reference_table.referencing_table_7000311 - referencing_referencing_table_id_fkey_7000320 | fkey_reference_table.referencing_referencing_table_7000320 | fkey_reference_table.referencing_table_7000312 - referencing_referencing_table_id_fkey_7000321 | fkey_reference_table.referencing_referencing_table_7000321 | fkey_reference_table.referencing_table_7000313 - referencing_referencing_table_id_fkey_7000322 | fkey_reference_table.referencing_referencing_table_7000322 | fkey_reference_table.referencing_table_7000314 - referencing_referencing_table_id_fkey_7000323 | fkey_reference_table.referencing_referencing_table_7000323 | fkey_reference_table.referencing_table_7000315 + fkey_ref_7000299 | fkey_reference_table.referencing_table_7000299 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000300 | fkey_reference_table.referencing_table_7000300 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000301 | fkey_reference_table.referencing_table_7000301 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000302 | fkey_reference_table.referencing_table_7000302 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000303 | fkey_reference_table.referencing_table_7000303 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000304 | fkey_reference_table.referencing_table_7000304 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000305 | fkey_reference_table.referencing_table_7000305 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000306 | fkey_reference_table.referencing_table_7000306 | fkey_reference_table.referenced_table_7000298 + referencing_referencing_table_id_fkey_7000307 | fkey_reference_table.referencing_referencing_table_7000307 | fkey_reference_table.referencing_table_7000299 + referencing_referencing_table_id_fkey_7000308 | fkey_reference_table.referencing_referencing_table_7000308 | fkey_reference_table.referencing_table_7000300 + referencing_referencing_table_id_fkey_7000309 | fkey_reference_table.referencing_referencing_table_7000309 | fkey_reference_table.referencing_table_7000301 + referencing_referencing_table_id_fkey_7000310 | fkey_reference_table.referencing_referencing_table_7000310 | fkey_reference_table.referencing_table_7000302 + referencing_referencing_table_id_fkey_7000311 | fkey_reference_table.referencing_referencing_table_7000311 | fkey_reference_table.referencing_table_7000303 + referencing_referencing_table_id_fkey_7000312 | fkey_reference_table.referencing_referencing_table_7000312 | fkey_reference_table.referencing_table_7000304 + referencing_referencing_table_id_fkey_7000313 | fkey_reference_table.referencing_referencing_table_7000313 | fkey_reference_table.referencing_table_7000305 + referencing_referencing_table_id_fkey_7000314 | fkey_reference_table.referencing_referencing_table_7000314 | fkey_reference_table.referencing_table_7000306 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(1,1000) AS f(x); @@ -1866,8 +1843,8 @@ ALTER TABLE referencing_table_4 ADD CONSTRAINT fkey FOREIGN KEY (id) REFERENCES ALTER TABLE referencing_table_4 ADD CONSTRAINT fkey_to_ref FOREIGN KEY (value_1) REFERENCES referenced_table; -- should fail since the data will flow to partitioning_test_4 and it has a foreign constraint to partitioning_test_0 on id column INSERT INTO referencing_table VALUES (0, 5); -ERROR: insert or update on table "referencing_table_4_7000549" violates foreign key constraint "fkey_7000549" -DETAIL: Key (id)=(0) is not present in table "referencing_table_0_7000533". +ERROR: insert or update on table "referencing_table_4_7000540" violates foreign key constraint "fkey_7000540" +DETAIL: Key (id)=(0) is not present in table "referencing_table_0_7000524". CONTEXT: while executing command on localhost:57638 -- should succeed on partitioning_test_0 INSERT INTO referencing_table VALUES (0, 1); @@ -1879,8 +1856,8 @@ SELECT * FROM referencing_table; -- should fail since partitioning_test_4 has foreign constraint to referenced_table on value_1 column INSERT INTO referencing_table VALUES (0, 5); -ERROR: insert or update on table "referencing_table_4_7000549" violates foreign key constraint "fkey_to_ref_7000549" -DETAIL: Key (value_1)=(5) is not present in table "referenced_table_7000521". +ERROR: insert or update on table "referencing_table_4_7000540" violates foreign key constraint "fkey_to_ref_7000540" +DETAIL: Key (value_1)=(5) is not present in table "referenced_table_7000512". CONTEXT: while executing command on localhost:57638 INSERT INTO referenced_table VALUES(5,5); -- should succeed since both of the foreign constraints are positive diff --git a/src/test/regress/expected/foreign_key_to_reference_table_0.out b/src/test/regress/expected/foreign_key_to_reference_table_0.out index 7e639e391..a5e6e4e66 100644 --- a/src/test/regress/expected/foreign_key_to_reference_table_0.out +++ b/src/test/regress/expected/foreign_key_to_reference_table_0.out @@ -1,6 +1,13 @@ -- -- FOREIGN_KEY_TO_REFERENCE_TABLE -- +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine; + version_above_nine +-------------------- + f +(1 row) + CREATE SCHEMA fkey_reference_table; SET search_path TO 'fkey_reference_table'; SET citus.shard_replication_factor TO 1; @@ -28,7 +35,9 @@ SELECT relid::regclass::text, refd_relid::regclass::text FROM - table_fkey_cols + table_fkey_cols + WHERE + "schema" = 'fkey_reference_table' ) d $$ )).RESULT::json )::json )).* ; CREATE TABLE referenced_table(id int UNIQUE, test_column int); @@ -722,38 +731,6 @@ INSERT INTO referencing_table SELECT x,(random()*1000)::int FROM generate_series DROP TABLE referenced_table CASCADE; NOTICE: drop cascades to constraint fkey_ref on table referencing_table DROP TABLE referencing_table CASCADE; --- In the following test, we show that Citus currently does not support --- VALIDATE command. -CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); -CREATE TABLE referencing_table(id int, ref_id int DEFAULT -1); -SELECT create_reference_table('referenced_table'); - create_reference_table ------------------------- - -(1 row) - -SELECT create_distributed_table('referencing_table', 'id'); - create_distributed_table --------------------------- - -(1 row) - -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column) ON DELETE SET DEFAULT NOT VALID; --- Even if the foreign constraint is added with "NOT VALID", --- we make sure that it is still applied to the upcoming inserts. -INSERT INTO referenced_table SELECT x, x FROM generate_series(0,1000) AS f(x); -INSERT INTO referencing_table SELECT x, x FROM generate_series(0,1000) AS f(x); --- we expect this to fail because of the foreign constraint. -INSERT INTO referencing_table SELECT x, x FROM generate_series(1000,1001) AS f(x); -ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220" -DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000214". --- currently not supported -ALTER TABLE referencing_table VALIDATE CONSTRAINT fkey_ref; -ERROR: alter table command is currently unsupported -DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. -DROP TABLE referenced_table CASCADE; -NOTICE: drop cascades to constraint fkey_ref on table referencing_table -DROP TABLE referencing_table CASCADE; -- In the following tests, we create a foreign constraint with -- ON UPDATE CASCADE and see if it works properly with cascading upsert CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); @@ -845,38 +822,38 @@ ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (id) REFE SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------+------------------------------------------------+------------------------------------------------ - fkey_ref_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000233 - fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000233 - foreign_key_2_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000234 - foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000234 + fkey_ref_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000227 | fkey_reference_table.referencing_table_7000227 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000228 | fkey_reference_table.referencing_table_7000228 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000229 | fkey_reference_table.referencing_table_7000229 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000230 | fkey_reference_table.referencing_table_7000230 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000231 | fkey_reference_table.referencing_table_7000231 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000232 | fkey_reference_table.referencing_table_7000232 | fkey_reference_table.referenced_table_7000224 + fkey_ref_7000233 | fkey_reference_table.referencing_table_7000233 | fkey_reference_table.referenced_table_7000224 + foreign_key_2_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000227 | fkey_reference_table.referencing_table_7000227 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000228 | fkey_reference_table.referencing_table_7000228 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000229 | fkey_reference_table.referencing_table_7000229 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000230 | fkey_reference_table.referencing_table_7000230 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000231 | fkey_reference_table.referencing_table_7000231 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000232 | fkey_reference_table.referencing_table_7000232 | fkey_reference_table.referenced_table2_7000225 + foreign_key_2_7000233 | fkey_reference_table.referencing_table_7000233 | fkey_reference_table.referenced_table2_7000225 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x); -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x); -ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242" -DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234". +ERROR: insert or update on table "referencing_table_7000227" violates foreign key constraint "foreign_key_2_7000227" +DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000225". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242" -DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234". +ERROR: insert or update on table "referencing_table_7000227" violates foreign key constraint "foreign_key_2_7000227" +DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000225". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x); -ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "fkey_ref_7000242" -DETAIL: Key (id)=(1023) is not present in table "referenced_table_7000233". +ERROR: insert or update on table "referencing_table_7000227" violates foreign key constraint "fkey_ref_7000227" +DETAIL: Key (id)=(1005) is not present in table "referenced_table_7000224". -- should success INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x); SELECT count(*) FROM referencing_table; @@ -972,38 +949,38 @@ COMMIT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------+------------------------------------------------+------------------------------------------------ - fkey_ref_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000253 - fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000253 - foreign_key_2_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table2_7000254 - foreign_key_2_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table2_7000254 + fkey_ref_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000247 | fkey_reference_table.referencing_table_7000247 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000248 | fkey_reference_table.referencing_table_7000248 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000249 | fkey_reference_table.referencing_table_7000249 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000250 | fkey_reference_table.referencing_table_7000250 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000251 | fkey_reference_table.referencing_table_7000251 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000252 | fkey_reference_table.referencing_table_7000252 | fkey_reference_table.referenced_table_7000244 + fkey_ref_7000253 | fkey_reference_table.referencing_table_7000253 | fkey_reference_table.referenced_table_7000244 + foreign_key_2_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000247 | fkey_reference_table.referencing_table_7000247 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000248 | fkey_reference_table.referencing_table_7000248 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000249 | fkey_reference_table.referencing_table_7000249 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000250 | fkey_reference_table.referencing_table_7000250 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000251 | fkey_reference_table.referencing_table_7000251 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000252 | fkey_reference_table.referencing_table_7000252 | fkey_reference_table.referenced_table2_7000245 + foreign_key_2_7000253 | fkey_reference_table.referencing_table_7000253 | fkey_reference_table.referenced_table2_7000245 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x); -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x); -ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260" -DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254". +ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "foreign_key_2_7000251" +DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000245". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260" -DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254". +ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "foreign_key_2_7000251" +DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000245". -- should fail INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x); -ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "fkey_ref_7000260" -DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000253". +ERROR: insert or update on table "referencing_table_7000251" violates foreign key constraint "fkey_ref_7000251" +DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000244". -- should success INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x); SELECT count(*) FROM referencing_table; @@ -1105,43 +1082,43 @@ COMMIT; SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3; name | relid | refd_relid --------------------------+-------------------------------------------------+------------------------------------------------ - fkey_ref_7000274 | fkey_reference_table.referencing_table_7000274 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000275 | fkey_reference_table.referencing_table_7000275 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000276 | fkey_reference_table.referencing_table_7000276 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000277 | fkey_reference_table.referencing_table_7000277 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000278 | fkey_reference_table.referencing_table_7000278 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000279 | fkey_reference_table.referencing_table_7000279 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000280 | fkey_reference_table.referencing_table_7000280 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000281 | fkey_reference_table.referencing_table_7000281 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referenced_table_7000273 - fkey_ref_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referenced_table_7000273 - fkey_ref_to_dist_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referencing_table_7000274 - fkey_ref_to_dist_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referencing_table_7000275 - fkey_ref_to_dist_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referencing_table_7000276 - fkey_ref_to_dist_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referencing_table_7000277 - fkey_ref_to_dist_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referencing_table_7000278 - fkey_ref_to_dist_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referencing_table_7000279 - fkey_ref_to_dist_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referencing_table_7000280 - fkey_ref_to_dist_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referencing_table_7000281 + fkey_ref_7000265 | fkey_reference_table.referencing_table_7000265 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000266 | fkey_reference_table.referencing_table_7000266 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000267 | fkey_reference_table.referencing_table_7000267 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000268 | fkey_reference_table.referencing_table_7000268 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000269 | fkey_reference_table.referencing_table_7000269 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000270 | fkey_reference_table.referencing_table_7000270 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000271 | fkey_reference_table.referencing_table_7000271 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000272 | fkey_reference_table.referencing_table_7000272 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000274 | fkey_reference_table.referencing_table2_7000274 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000275 | fkey_reference_table.referencing_table2_7000275 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000276 | fkey_reference_table.referencing_table2_7000276 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000277 | fkey_reference_table.referencing_table2_7000277 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000278 | fkey_reference_table.referencing_table2_7000278 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000279 | fkey_reference_table.referencing_table2_7000279 | fkey_reference_table.referenced_table_7000264 + fkey_ref_7000280 | fkey_reference_table.referencing_table2_7000280 | fkey_reference_table.referenced_table_7000264 + fkey_ref_to_dist_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referencing_table_7000265 + fkey_ref_to_dist_7000274 | fkey_reference_table.referencing_table2_7000274 | fkey_reference_table.referencing_table_7000266 + fkey_ref_to_dist_7000275 | fkey_reference_table.referencing_table2_7000275 | fkey_reference_table.referencing_table_7000267 + fkey_ref_to_dist_7000276 | fkey_reference_table.referencing_table2_7000276 | fkey_reference_table.referencing_table_7000268 + fkey_ref_to_dist_7000277 | fkey_reference_table.referencing_table2_7000277 | fkey_reference_table.referencing_table_7000269 + fkey_ref_to_dist_7000278 | fkey_reference_table.referencing_table2_7000278 | fkey_reference_table.referencing_table_7000270 + fkey_ref_to_dist_7000279 | fkey_reference_table.referencing_table2_7000279 | fkey_reference_table.referencing_table_7000271 + fkey_ref_to_dist_7000280 | fkey_reference_table.referencing_table2_7000280 | fkey_reference_table.referencing_table_7000272 (24 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x); -- should fail INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x); -ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284" -DETAIL: Key (id)=(4) is not present in table "referencing_table_7000276". +ERROR: insert or update on table "referencing_table2_7000274" violates foreign key constraint "fkey_ref_to_dist_7000274" +DETAIL: Key (id)=(5) is not present in table "referencing_table_7000266". -- should success INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x); -- should fail INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x); -ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284" -DETAIL: Key (id)=(408) is not present in table "referencing_table_7000276". +ERROR: insert or update on table "referencing_table2_7000274" violates foreign key constraint "fkey_ref_to_dist_7000274" +DETAIL: Key (id)=(403) is not present in table "referencing_table_7000266". -- should success INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x); DELETE FROM referenced_table WHERE test_column < 200; @@ -1239,22 +1216,22 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id, ref_i SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.referencing%' ORDER BY 1,2,3; name | relid | refd_relid -----------------------------------------------+------------------------------------------------------------+------------------------------------------------ - fkey_ref_7000308 | fkey_reference_table.referencing_table_7000308 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000309 | fkey_reference_table.referencing_table_7000309 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000310 | fkey_reference_table.referencing_table_7000310 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000311 | fkey_reference_table.referencing_table_7000311 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000312 | fkey_reference_table.referencing_table_7000312 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000313 | fkey_reference_table.referencing_table_7000313 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000314 | fkey_reference_table.referencing_table_7000314 | fkey_reference_table.referenced_table_7000307 - fkey_ref_7000315 | fkey_reference_table.referencing_table_7000315 | fkey_reference_table.referenced_table_7000307 - referencing_referencing_table_id_fkey_7000316 | fkey_reference_table.referencing_referencing_table_7000316 | fkey_reference_table.referencing_table_7000308 - referencing_referencing_table_id_fkey_7000317 | fkey_reference_table.referencing_referencing_table_7000317 | fkey_reference_table.referencing_table_7000309 - referencing_referencing_table_id_fkey_7000318 | fkey_reference_table.referencing_referencing_table_7000318 | fkey_reference_table.referencing_table_7000310 - referencing_referencing_table_id_fkey_7000319 | fkey_reference_table.referencing_referencing_table_7000319 | fkey_reference_table.referencing_table_7000311 - referencing_referencing_table_id_fkey_7000320 | fkey_reference_table.referencing_referencing_table_7000320 | fkey_reference_table.referencing_table_7000312 - referencing_referencing_table_id_fkey_7000321 | fkey_reference_table.referencing_referencing_table_7000321 | fkey_reference_table.referencing_table_7000313 - referencing_referencing_table_id_fkey_7000322 | fkey_reference_table.referencing_referencing_table_7000322 | fkey_reference_table.referencing_table_7000314 - referencing_referencing_table_id_fkey_7000323 | fkey_reference_table.referencing_referencing_table_7000323 | fkey_reference_table.referencing_table_7000315 + fkey_ref_7000299 | fkey_reference_table.referencing_table_7000299 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000300 | fkey_reference_table.referencing_table_7000300 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000301 | fkey_reference_table.referencing_table_7000301 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000302 | fkey_reference_table.referencing_table_7000302 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000303 | fkey_reference_table.referencing_table_7000303 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000304 | fkey_reference_table.referencing_table_7000304 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000305 | fkey_reference_table.referencing_table_7000305 | fkey_reference_table.referenced_table_7000298 + fkey_ref_7000306 | fkey_reference_table.referencing_table_7000306 | fkey_reference_table.referenced_table_7000298 + referencing_referencing_table_id_fkey_7000307 | fkey_reference_table.referencing_referencing_table_7000307 | fkey_reference_table.referencing_table_7000299 + referencing_referencing_table_id_fkey_7000308 | fkey_reference_table.referencing_referencing_table_7000308 | fkey_reference_table.referencing_table_7000300 + referencing_referencing_table_id_fkey_7000309 | fkey_reference_table.referencing_referencing_table_7000309 | fkey_reference_table.referencing_table_7000301 + referencing_referencing_table_id_fkey_7000310 | fkey_reference_table.referencing_referencing_table_7000310 | fkey_reference_table.referencing_table_7000302 + referencing_referencing_table_id_fkey_7000311 | fkey_reference_table.referencing_referencing_table_7000311 | fkey_reference_table.referencing_table_7000303 + referencing_referencing_table_id_fkey_7000312 | fkey_reference_table.referencing_referencing_table_7000312 | fkey_reference_table.referencing_table_7000304 + referencing_referencing_table_id_fkey_7000313 | fkey_reference_table.referencing_referencing_table_7000313 | fkey_reference_table.referencing_table_7000305 + referencing_referencing_table_id_fkey_7000314 | fkey_reference_table.referencing_referencing_table_7000314 | fkey_reference_table.referencing_table_7000306 (16 rows) INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(1,1000) AS f(x); diff --git a/src/test/regress/expected/isolation_validate_vs_insert.out b/src/test/regress/expected/isolation_validate_vs_insert.out new file mode 100644 index 000000000..212edbedf --- /dev/null +++ b/src/test/regress/expected/isolation_validate_vs_insert.out @@ -0,0 +1,59 @@ +Parsed test spec with 2 sessions + +starting permutation: s1-initialize s1-add-constraint s1-begin s2-begin s1-validate s2-insert s1-commit s2-commit +create_distributed_table + + +step s1-initialize: INSERT INTO constrained_table VALUES (0, 0), (1, 1), (2, 2), (3, 4); +step s1-add-constraint: ALTER TABLE constrained_table ADD CONSTRAINT check_constraint CHECK(int_data<30) NOT VALID; +step s1-begin: BEGIN; +step s2-begin: BEGIN; +step s1-validate: ALTER TABLE constrained_table VALIDATE CONSTRAINT check_constraint; +step s2-insert: INSERT INTO constrained_table VALUES(10, 10); +step s1-commit: COMMIT; +step s2-commit: COMMIT; + +starting permutation: s1-initialize s1-add-constraint s1-begin s2-begin s1-validate s2-select s1-commit s2-commit +create_distributed_table + + +step s1-initialize: INSERT INTO constrained_table VALUES (0, 0), (1, 1), (2, 2), (3, 4); +step s1-add-constraint: ALTER TABLE constrained_table ADD CONSTRAINT check_constraint CHECK(int_data<30) NOT VALID; +step s1-begin: BEGIN; +step s2-begin: BEGIN; +step s1-validate: ALTER TABLE constrained_table VALIDATE CONSTRAINT check_constraint; +step s2-select: SELECT sum(int_data) FROM constrained_table; +sum + +7 +step s1-commit: COMMIT; +step s2-commit: COMMIT; + +starting permutation: s1-initialize s1-add-constraint s1-begin s2-begin s2-insert s1-validate s1-commit s2-commit +create_distributed_table + + +step s1-initialize: INSERT INTO constrained_table VALUES (0, 0), (1, 1), (2, 2), (3, 4); +step s1-add-constraint: ALTER TABLE constrained_table ADD CONSTRAINT check_constraint CHECK(int_data<30) NOT VALID; +step s1-begin: BEGIN; +step s2-begin: BEGIN; +step s2-insert: INSERT INTO constrained_table VALUES(10, 10); +step s1-validate: ALTER TABLE constrained_table VALIDATE CONSTRAINT check_constraint; +step s1-commit: COMMIT; +step s2-commit: COMMIT; + +starting permutation: s1-initialize s1-add-constraint s1-begin s2-begin s2-select s1-validate s1-commit s2-commit +create_distributed_table + + +step s1-initialize: INSERT INTO constrained_table VALUES (0, 0), (1, 1), (2, 2), (3, 4); +step s1-add-constraint: ALTER TABLE constrained_table ADD CONSTRAINT check_constraint CHECK(int_data<30) NOT VALID; +step s1-begin: BEGIN; +step s2-begin: BEGIN; +step s2-select: SELECT sum(int_data) FROM constrained_table; +sum + +7 +step s1-validate: ALTER TABLE constrained_table VALIDATE CONSTRAINT check_constraint; +step s1-commit: COMMIT; +step s2-commit: COMMIT; diff --git a/src/test/regress/expected/multi_reference_table.out b/src/test/regress/expected/multi_reference_table.out index d13c5bab3..920a8a9c2 100644 --- a/src/test/regress/expected/multi_reference_table.out +++ b/src/test/regress/expected/multi_reference_table.out @@ -1385,7 +1385,7 @@ SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='reference_sche -- as we expect, setting WITH OIDS does not work for reference tables ALTER TABLE reference_schema.reference_table_ddl SET WITH OIDS; ERROR: alter table command is currently unsupported -DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. -- now test the renaming of the table, and back to the expected name ALTER TABLE reference_schema.reference_table_ddl RENAME TO reference_table_ddl_test; ALTER TABLE reference_schema.reference_table_ddl_test RENAME TO reference_table_ddl; diff --git a/src/test/regress/expected/multi_test_helpers.out b/src/test/regress/expected/multi_test_helpers.out index 40073f61e..c72a4487b 100644 --- a/src/test/regress/expected/multi_test_helpers.out +++ b/src/test/regress/expected/multi_test_helpers.out @@ -17,7 +17,8 @@ SELECT rc.constraint_name AS "name", kcu.column_name AS "column_name", uc_kcu.column_name AS "refd_column_name", format('%I.%I', kcu.table_schema, kcu.table_name)::regclass::oid AS relid, - format('%I.%I', uc_kcu.table_schema, uc_kcu.table_name)::regclass::oid AS refd_relid + format('%I.%I', uc_kcu.table_schema, uc_kcu.table_name)::regclass::oid AS refd_relid, + rc.constraint_schema AS "schema" FROM information_schema.referential_constraints rc, information_schema.key_column_usage kcu, information_schema.key_column_usage uc_kcu diff --git a/src/test/regress/expected/validate_constraint.out b/src/test/regress/expected/validate_constraint.out new file mode 100644 index 000000000..ad180b13b --- /dev/null +++ b/src/test/regress/expected/validate_constraint.out @@ -0,0 +1,150 @@ +-- +-- VALIDATE_CONSTRAINT +-- +-- PostgreSQL 11 Docs Excerpt: +-- The queries that can have 'NOT VALID' option are of the form: +-- ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] ADD table_constraint NOT VALID [, ...] +-- +-- where table_constraint is: +-- [ CONSTRAINT constraint_name ] +-- { CHECK ( expression ) [ NO INHERIT ] | +-- UNIQUE ( column_name [, ... ] ) index_parameters | +-- PRIMARY KEY ( column_name [, ... ] ) index_parameters | +-- EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | +-- FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] +-- [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } +-- [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] +-- This form adds a new constraint to a table using the same syntax as CREATE TABLE, plus the option NOT VALID, which is +-- currently only allowed for foreign key and CHECK constraints. If the constraint is marked NOT VALID, the +-- potentially-lengthy initial check to verify that all rows in the table satisfy the constraint is skipped. +-- The constraint will still be enforced against subsequent inserts or updates (that is, they'll fail unless there is a +-- matching row in the referenced table, in the case of foreign keys; and they'll fail unless the new row matches the +-- specified check constraints). But the database will not assume that the constraint holds for all rows in the table, +-- until it is validated by using the VALIDATE CONSTRAINT option. +CREATE SCHEMA validate_constraint; +SET search_path TO 'validate_constraint'; +SET citus.shard_replication_factor TO 1; +SET citus.shard_count TO 8; +SET citus.next_shard_id TO 8000000; +SET citus.next_placement_id TO 8000000; +CREATE TYPE constraint_validity AS (name text, validated bool); +SELECT run_command_on_workers( + $$CREATE TYPE constraint_validity AS (name text, validated bool)$$); + run_command_on_workers +----------------------------------- + (localhost,57637,t,"CREATE TYPE") + (localhost,57638,t,"CREATE TYPE") +(2 rows) + +CREATE VIEW constraint_validations_in_workers AS + SELECT (json_populate_record(NULL :: constraint_validity, + json_array_elements_text((run_command_on_workers($$ + SELECT + COALESCE(json_agg(row_to_json(d)), '[]'::json) + FROM + ( + SELECT conname as name, + convalidated as validated + FROM pg_catalog.pg_constraint AS con + JOIN pg_catalog.pg_namespace AS ns + ON ns.oid = con.connamespace + WHERE nspname = 'validate_constraint' + AND contype = 'c' + ORDER BY 1,2 + ) + d $$)).RESULT :: json) :: json)).* + ORDER BY 1,2; +CREATE VIEW constraint_validations AS + SELECT conname as "Constraint", + convalidated as "Validated?" + FROM pg_catalog.pg_constraint AS con + JOIN pg_catalog.pg_namespace AS ns ON ns.oid = con.connamespace + WHERE nspname = 'validate_constraint' + AND contype = 'c'; +CREATE TABLE referenced_table (id int UNIQUE, test_column int); +SELECT create_reference_table('referenced_table'); + create_reference_table +------------------------ + +(1 row) + +CREATE TABLE referencing_table (id int, ref_id int); +SELECT create_distributed_table('referencing_table', 'ref_id'); + create_distributed_table +-------------------------- + +(1 row) + +CREATE TABLE constrained_table (id int, constrained_column int); +SELECT create_distributed_table('constrained_table', 'constrained_column'); + create_distributed_table +-------------------------- + +(1 row) + +-- The two constraint types that are allowed to be NOT VALID +BEGIN; +ALTER TABLE constrained_table + ADD CONSTRAINT check_constraint CHECK (constrained_column > 100) NOT VALID; +ALTER TABLE constrained_table + VALIDATE CONSTRAINT check_constraint; +ROLLBACK; +BEGIN; +ALTER TABLE referencing_table + ADD CONSTRAINT fk_constraint FOREIGN KEY (ref_id) REFERENCES referenced_table (id) NOT VALID; +ALTER TABLE referencing_table + VALIDATE CONSTRAINT fk_constraint; +ROLLBACK; +-- It is possible that some other table_constraint commands will support NOT VALID option in the future +-- These should fail as Postgres does not yet allow these constraints to be NOT VALID +-- If one of these queries are not failing on a future Postgres version, we will need to test corresponding VALIDATE CONSTRAINT queries +ALTER TABLE constrained_table + ADD CONSTRAINT unique_constraint UNIQUE (constrained_column) NOT VALID; +ERROR: UNIQUE constraints cannot be marked NOT VALID +ALTER TABLE constrained_table + ADD CONSTRAINT pk_constraint PRIMARY KEY (id) NOT VALID; +ERROR: PRIMARY KEY constraints cannot be marked NOT VALID +ALTER TABLE constrained_table + ADD CONSTRAINT exclude_constraint EXCLUDE USING gist (id WITH =, constrained_column WITH <>) NOT VALID; +ERROR: EXCLUDE constraints cannot be marked NOT VALID +INSERT INTO constrained_table +SELECT x, x +from generate_series(1, 1000) as f (x); +-- a constraint that can be validated +ALTER TABLE constrained_table + ADD CONSTRAINT validatable_constraint CHECK (constrained_column < 10000) NOT VALID; +ALTER TABLE constrained_table + VALIDATE CONSTRAINT validatable_constraint; +-- Check which constraints are validated +SELECT * +FROM constraint_validations +ORDER BY 1, 2; + Constraint | Validated? +------------------------+------------ + validatable_constraint | t +(1 row) + +SELECT * +FROM constraint_validations_in_workers +ORDER BY 1, 2; + name | validated +--------------------------------+----------- + validatable_constraint_8000009 | t + validatable_constraint_8000010 | t + validatable_constraint_8000011 | t + validatable_constraint_8000012 | t + validatable_constraint_8000013 | t + validatable_constraint_8000014 | t + validatable_constraint_8000015 | t + validatable_constraint_8000016 | t +(8 rows) + +DROP TABLE constrained_table; +DROP TABLE referenced_table CASCADE; +DROP TABLE referencing_table; +DROP SCHEMA validate_constraint CASCADE; +NOTICE: drop cascades to 3 other objects +DETAIL: drop cascades to type constraint_validity +drop cascades to view constraint_validations_in_workers +drop cascades to view constraint_validations +SET search_path TO DEFAULT; diff --git a/src/test/regress/isolation_schedule b/src/test/regress/isolation_schedule index d8d677beb..86cb914b2 100644 --- a/src/test/regress/isolation_schedule +++ b/src/test/regress/isolation_schedule @@ -43,6 +43,7 @@ test: isolation_truncate_vs_all test: isolation_drop_vs_all test: isolation_ddl_vs_all test: isolation_citus_dist_activity +test: isolation_validate_vs_insert # MX tests test: isolation_reference_on_mx diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule index f438ec6dd..0bc772b5d 100644 --- a/src/test/regress/multi_schedule +++ b/src/test/regress/multi_schedule @@ -173,7 +173,7 @@ test: multi_modifications test: multi_distribution_metadata test: multi_generate_ddl_commands multi_create_shards multi_prune_shard_list multi_repair_shards test: multi_upsert multi_simple_queries multi_create_insert_proxy multi_data_types -test: multi_utilities foreign_key_to_reference_table +test: multi_utilities foreign_key_to_reference_table validate_constraint test: multi_modifying_xacts test: multi_repartition_udt multi_repartitioned_subquery_udf multi_subtransactions test: multi_transaction_recovery diff --git a/src/test/regress/output/multi_alter_table_statements.source b/src/test/regress/output/multi_alter_table_statements.source index 1975ddf87..4a3954028 100644 --- a/src/test/regress/output/multi_alter_table_statements.source +++ b/src/test/regress/output/multi_alter_table_statements.source @@ -344,7 +344,7 @@ SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineite ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER, ALTER COLUMN int_column1 SET STATISTICS 10; ERROR: alter table command is currently unsupported -DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2; SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass; Column | Type | Modifiers @@ -376,12 +376,12 @@ ERROR: cannot execute ALTER TABLE command involving partition column -- Verify that we error out on unsupported statement types ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey SET STATISTICS 100; ERROR: alter table command is currently unsupported -DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. ALTER TABLE lineitem_alter DROP CONSTRAINT IF EXISTS non_existent_contraint; NOTICE: constraint "non_existent_contraint" of relation "lineitem_alter" does not exist, skipping ALTER TABLE lineitem_alter SET WITHOUT OIDS; ERROR: alter table command is currently unsupported -DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ATTACH|DETACH PARTITION and TYPE subcommands are supported. -- Verify that we error out in case of postgres errors on supported statement -- types ALTER TABLE lineitem_alter ADD COLUMN new_column non_existent_type; diff --git a/src/test/regress/specs/isolation_validate_vs_insert.spec b/src/test/regress/specs/isolation_validate_vs_insert.spec new file mode 100644 index 000000000..81d2d1c77 --- /dev/null +++ b/src/test/regress/specs/isolation_validate_vs_insert.spec @@ -0,0 +1,39 @@ +# +# How we organize this isolation test spec, is explained at README.md file in this directory. +# + +# create distributed table to test behavior of VALIDATE in concurrent operations +setup +{ + SET citus.shard_replication_factor TO 1; + CREATE TABLE constrained_table(id integer, int_data int); + SELECT create_distributed_table('constrained_table', 'id'); +} + +# drop distributed table +teardown +{ + DROP TABLE IF EXISTS constrained_table CASCADE; +} + +# session 1 +session "s1" +step "s1-initialize" { INSERT INTO constrained_table VALUES (0, 0), (1, 1), (2, 2), (3, 4); } +step "s1-begin" { BEGIN; } +step "s1-add-constraint" { ALTER TABLE constrained_table ADD CONSTRAINT check_constraint CHECK(int_data<30) NOT VALID; } +step "s1-validate" { ALTER TABLE constrained_table VALIDATE CONSTRAINT check_constraint; } +step "s1-commit" { COMMIT; } + +# session 2 +session "s2" +step "s2-begin" { BEGIN; } +step "s2-insert" { INSERT INTO constrained_table VALUES(10, 10); } +step "s2-insert-invalid" { INSERT INTO constrained_table VALUES(100, 100); } +step "s2-select" { SELECT sum(int_data) FROM constrained_table; } +step "s2-commit" { COMMIT; } + +# permutations - check read and write are not blocked during validate queries +permutation "s1-initialize" "s1-add-constraint" "s1-begin" "s2-begin" "s1-validate" "s2-insert" "s1-commit" "s2-commit" +permutation "s1-initialize" "s1-add-constraint" "s1-begin" "s2-begin" "s1-validate" "s2-select" "s1-commit" "s2-commit" +permutation "s1-initialize" "s1-add-constraint" "s1-begin" "s2-begin" "s2-insert" "s1-validate" "s1-commit" "s2-commit" +permutation "s1-initialize" "s1-add-constraint" "s1-begin" "s2-begin" "s2-select" "s1-validate" "s1-commit" "s2-commit" diff --git a/src/test/regress/sql/foreign_key_to_reference_table.sql b/src/test/regress/sql/foreign_key_to_reference_table.sql index 88948cfe7..07924bdb5 100644 --- a/src/test/regress/sql/foreign_key_to_reference_table.sql +++ b/src/test/regress/sql/foreign_key_to_reference_table.sql @@ -1,6 +1,8 @@ -- -- FOREIGN_KEY_TO_REFERENCE_TABLE -- +SHOW server_version \gset +SELECT substring(:'server_version', '\d+')::int > 9 AS version_above_nine; CREATE SCHEMA fkey_reference_table; SET search_path TO 'fkey_reference_table'; @@ -25,7 +27,9 @@ SELECT relid::regclass::text, refd_relid::regclass::text FROM - table_fkey_cols + table_fkey_cols + WHERE + "schema" = 'fkey_reference_table' ) d $$ )).RESULT::json )::json )).* ; @@ -362,27 +366,6 @@ INSERT INTO referencing_table SELECT x,(random()*1000)::int FROM generate_series DROP TABLE referenced_table CASCADE; DROP TABLE referencing_table CASCADE; --- In the following test, we show that Citus currently does not support --- VALIDATE command. -CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); -CREATE TABLE referencing_table(id int, ref_id int DEFAULT -1); -SELECT create_reference_table('referenced_table'); -SELECT create_distributed_table('referencing_table', 'id'); -ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFERENCES referenced_table(test_column) ON DELETE SET DEFAULT NOT VALID; - --- Even if the foreign constraint is added with "NOT VALID", --- we make sure that it is still applied to the upcoming inserts. -INSERT INTO referenced_table SELECT x, x FROM generate_series(0,1000) AS f(x); -INSERT INTO referencing_table SELECT x, x FROM generate_series(0,1000) AS f(x); --- we expect this to fail because of the foreign constraint. -INSERT INTO referencing_table SELECT x, x FROM generate_series(1000,1001) AS f(x); - --- currently not supported -ALTER TABLE referencing_table VALIDATE CONSTRAINT fkey_ref; - -DROP TABLE referenced_table CASCADE; -DROP TABLE referencing_table CASCADE; - -- In the following tests, we create a foreign constraint with -- ON UPDATE CASCADE and see if it works properly with cascading upsert CREATE TABLE referenced_table(test_column int, test_column2 int, PRIMARY KEY(test_column)); diff --git a/src/test/regress/sql/multi_test_helpers.sql b/src/test/regress/sql/multi_test_helpers.sql index 26bb17882..8577ec74b 100644 --- a/src/test/regress/sql/multi_test_helpers.sql +++ b/src/test/regress/sql/multi_test_helpers.sql @@ -19,7 +19,8 @@ SELECT rc.constraint_name AS "name", kcu.column_name AS "column_name", uc_kcu.column_name AS "refd_column_name", format('%I.%I', kcu.table_schema, kcu.table_name)::regclass::oid AS relid, - format('%I.%I', uc_kcu.table_schema, uc_kcu.table_name)::regclass::oid AS refd_relid + format('%I.%I', uc_kcu.table_schema, uc_kcu.table_name)::regclass::oid AS refd_relid, + rc.constraint_schema AS "schema" FROM information_schema.referential_constraints rc, information_schema.key_column_usage kcu, information_schema.key_column_usage uc_kcu diff --git a/src/test/regress/sql/validate_constraint.sql b/src/test/regress/sql/validate_constraint.sql new file mode 100644 index 000000000..f2447285b --- /dev/null +++ b/src/test/regress/sql/validate_constraint.sql @@ -0,0 +1,126 @@ +-- +-- VALIDATE_CONSTRAINT +-- + +-- PostgreSQL 11 Docs Excerpt: + +-- The queries that can have 'NOT VALID' option are of the form: +-- ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ] ADD table_constraint NOT VALID [, ...] +-- +-- where table_constraint is: +-- [ CONSTRAINT constraint_name ] +-- { CHECK ( expression ) [ NO INHERIT ] | +-- UNIQUE ( column_name [, ... ] ) index_parameters | +-- PRIMARY KEY ( column_name [, ... ] ) index_parameters | +-- EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | +-- FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] +-- [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] } +-- [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] + +-- This form adds a new constraint to a table using the same syntax as CREATE TABLE, plus the option NOT VALID, which is +-- currently only allowed for foreign key and CHECK constraints. If the constraint is marked NOT VALID, the +-- potentially-lengthy initial check to verify that all rows in the table satisfy the constraint is skipped. + +-- The constraint will still be enforced against subsequent inserts or updates (that is, they'll fail unless there is a +-- matching row in the referenced table, in the case of foreign keys; and they'll fail unless the new row matches the +-- specified check constraints). But the database will not assume that the constraint holds for all rows in the table, +-- until it is validated by using the VALIDATE CONSTRAINT option. + +CREATE SCHEMA validate_constraint; +SET search_path TO 'validate_constraint'; +SET citus.shard_replication_factor TO 1; +SET citus.shard_count TO 8; +SET citus.next_shard_id TO 8000000; +SET citus.next_placement_id TO 8000000; + +CREATE TYPE constraint_validity AS (name text, validated bool); +SELECT run_command_on_workers( + $$CREATE TYPE constraint_validity AS (name text, validated bool)$$); + +CREATE VIEW constraint_validations_in_workers AS + SELECT (json_populate_record(NULL :: constraint_validity, + json_array_elements_text((run_command_on_workers($$ + SELECT + COALESCE(json_agg(row_to_json(d)), '[]'::json) + FROM + ( + SELECT conname as name, + convalidated as validated + FROM pg_catalog.pg_constraint AS con + JOIN pg_catalog.pg_namespace AS ns + ON ns.oid = con.connamespace + WHERE nspname = 'validate_constraint' + AND contype = 'c' + ORDER BY 1,2 + ) + d $$)).RESULT :: json) :: json)).* + ORDER BY 1,2; + +CREATE VIEW constraint_validations AS + SELECT conname as "Constraint", + convalidated as "Validated?" + FROM pg_catalog.pg_constraint AS con + JOIN pg_catalog.pg_namespace AS ns ON ns.oid = con.connamespace + WHERE nspname = 'validate_constraint' + AND contype = 'c'; + +CREATE TABLE referenced_table (id int UNIQUE, test_column int); +SELECT create_reference_table('referenced_table'); + +CREATE TABLE referencing_table (id int, ref_id int); +SELECT create_distributed_table('referencing_table', 'ref_id'); + +CREATE TABLE constrained_table (id int, constrained_column int); +SELECT create_distributed_table('constrained_table', 'constrained_column'); + +-- The two constraint types that are allowed to be NOT VALID +BEGIN; +ALTER TABLE constrained_table + ADD CONSTRAINT check_constraint CHECK (constrained_column > 100) NOT VALID; +ALTER TABLE constrained_table + VALIDATE CONSTRAINT check_constraint; +ROLLBACK; +BEGIN; +ALTER TABLE referencing_table + ADD CONSTRAINT fk_constraint FOREIGN KEY (ref_id) REFERENCES referenced_table (id) NOT VALID; +ALTER TABLE referencing_table + VALIDATE CONSTRAINT fk_constraint; +ROLLBACK; + +-- It is possible that some other table_constraint commands will support NOT VALID option in the future +-- These should fail as Postgres does not yet allow these constraints to be NOT VALID +-- If one of these queries are not failing on a future Postgres version, we will need to test corresponding VALIDATE CONSTRAINT queries +ALTER TABLE constrained_table + ADD CONSTRAINT unique_constraint UNIQUE (constrained_column) NOT VALID; + +ALTER TABLE constrained_table + ADD CONSTRAINT pk_constraint PRIMARY KEY (id) NOT VALID; + +ALTER TABLE constrained_table + ADD CONSTRAINT exclude_constraint EXCLUDE USING gist (id WITH =, constrained_column WITH <>) NOT VALID; + +INSERT INTO constrained_table +SELECT x, x +from generate_series(1, 1000) as f (x); + +-- a constraint that can be validated +ALTER TABLE constrained_table + ADD CONSTRAINT validatable_constraint CHECK (constrained_column < 10000) NOT VALID; +ALTER TABLE constrained_table + VALIDATE CONSTRAINT validatable_constraint; + +-- Check which constraints are validated +SELECT * +FROM constraint_validations +ORDER BY 1, 2; + +SELECT * +FROM constraint_validations_in_workers +ORDER BY 1, 2; + +DROP TABLE constrained_table; +DROP TABLE referenced_table CASCADE; +DROP TABLE referencing_table; + +DROP SCHEMA validate_constraint CASCADE; +SET search_path TO DEFAULT;