Skip to content

Commit

Permalink
Fix regression in foreign keys on distributed tables
Browse files Browse the repository at this point in the history
In commit eadc88a we changed how we skip foreign key validation. The
goal was to skip it in more cases. However, one change had the
unintended regression of introducing failures when trying to create
certain foreign keys. This reverts that part of the change.

The new way of skipping validation of foreign keys skipped the
validation during execution. The reason that this caused this regression
was because some foreign key validation queries already fail during
planning. In those cases it never gets to the execution step where it
would later be skipped.

Fixes #6543
  • Loading branch information
JelteF committed Dec 7, 2022
1 parent 1e415bb commit 2c5af71
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -623,18 +623,13 @@ ExecuteForeignKeyCreateCommand(const char *commandString, bool skip_validation)
*/
Assert(IsA(parseTree, AlterTableStmt));

bool oldSkipConstraintsValidationValue = SkipConstraintValidation;

if (skip_validation && IsA(parseTree, AlterTableStmt))
{
EnableSkippingConstraintValidation();

SkipForeignKeyValidationIfConstraintIsFkey((AlterTableStmt *) parseTree, true);
ereport(DEBUG4, (errmsg("skipping validation for foreign key create "
"command \"%s\"", commandString)));
}

ProcessUtilityParseTree(parseTree, commandString, PROCESS_UTILITY_QUERY,
NULL, None_Receiver, NULL);

SkipConstraintValidation = oldSkipConstraintsValidationValue;
}
16 changes: 11 additions & 5 deletions src/backend/distributed/commands/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -1873,7 +1873,8 @@ PreprocessAlterTableSchemaStmt(Node *node, const char *queryString,
* ALTER TABLE ... ADD FOREIGN KEY command to skip the validation step.
*/
void
SkipForeignKeyValidationIfConstraintIsFkey(AlterTableStmt *alterTableStatement)
SkipForeignKeyValidationIfConstraintIsFkey(AlterTableStmt *alterTableStatement,
bool processLocalRelation)
{
/* first check whether a distributed relation is affected */
if (alterTableStatement->relation == NULL)
Expand All @@ -1888,11 +1889,17 @@ SkipForeignKeyValidationIfConstraintIsFkey(AlterTableStmt *alterTableStatement)
return;
}

if (!IsCitusTable(leftRelationId))
if (!IsCitusTable(leftRelationId) && !processLocalRelation)
{
return;
}

/*
* We check if there is a ADD FOREIGN CONSTRAINT command in sub commands
* list. We set skip_validation to true to prevent PostgreSQL to verify
* validity of the foreign constraint. Validity will be checked on the
* shards anyway.
*/
AlterTableCmd *command = NULL;
foreach_ptr(command, alterTableStatement->cmds)
{
Expand All @@ -1904,9 +1911,8 @@ SkipForeignKeyValidationIfConstraintIsFkey(AlterTableStmt *alterTableStatement)
Constraint *constraint = (Constraint *) command->def;
if (constraint->contype == CONSTR_FOREIGN)
{
/* set the GUC skip_constraint_validation to on */
EnableSkippingConstraintValidation();
return;
/* foreign constraint validations will be done in shards. */
constraint->skip_validation = true;
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/backend/distributed/commands/utility_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,9 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
* Citus intervening. The only exception is partition column drop, in
* which case we error out. Advanced Citus users use this to implement their
* own DDL propagation. We also use it to avoid re-propagating DDL commands
* when changing MX tables on workers.
* when changing MX tables on workers. Below, we also make sure that DDL
* commands don't run queries that might get intercepted by Citus and error
* out during planning, specifically we skip validation in foreign keys.
*/

if (IsA(parsetree, AlterTableStmt))
Expand All @@ -627,7 +629,7 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
* Note validation is done on the shard level when DDL propagation
* is enabled. The following eagerly executes some tasks on workers.
*/
SkipForeignKeyValidationIfConstraintIsFkey(alterTableStmt);
SkipForeignKeyValidationIfConstraintIsFkey(alterTableStmt, false);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/include/distributed/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,8 @@ extern List * PreprocessAlterTableMoveAllStmt(Node *node, const char *queryStrin
ProcessUtilityContext processUtilityContext);
extern List * PreprocessAlterTableSchemaStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext);
extern void SkipForeignKeyValidationIfConstraintIsFkey(AlterTableStmt *alterTableStmt);
extern void SkipForeignKeyValidationIfConstraintIsFkey(AlterTableStmt *alterTableStmt,
bool processLocalRelation);
extern bool IsAlterTableRenameStmt(RenameStmt *renameStmt);
extern void ErrorIfAlterDropsPartitionColumn(AlterTableStmt *alterTableStatement);
extern void PostprocessAlterTableStmt(AlterTableStmt *pStmt);
Expand Down
30 changes: 30 additions & 0 deletions src/test/regress/expected/issue_6543.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
CREATE SCHEMA issue_6543;
SET search_path TO issue_6543;
SET citus.shard_count TO 4;
SET citus.shard_replication_factor TO 1;
SET citus.next_shard_id TO 67322500;
CREATE TABLE event (
tenant_id varchar,
id bigint,
primary key (tenant_id, id)
);
CREATE TABLE page (
tenant_id varchar,
id int,
primary key (tenant_id, id)
);
SELECT create_distributed_table('event', 'tenant_id');
create_distributed_table
---------------------------------------------------------------------

(1 row)

SELECT create_distributed_table('page', 'tenant_id', colocate_with => 'event');
create_distributed_table
---------------------------------------------------------------------

(1 row)

alter table page add constraint fk21 foreign key (tenant_id, id) references event;
SET client_min_messages TO WARNING;
DROP SCHEMA issue_6543 CASCADE;
2 changes: 1 addition & 1 deletion src/test/regress/multi_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ test: multi_dropped_column_aliases foreign_key_restriction_enforcement
test: binary_protocol
test: alter_table_set_access_method
test: alter_distributed_table
test: issue_5248 issue_5099 issue_5763
test: issue_5248 issue_5099 issue_5763 issue_6543
test: object_propagation_debug
test: undistribute_table
test: run_command_on_all_nodes
Expand Down
24 changes: 24 additions & 0 deletions src/test/regress/sql/issue_6543.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
CREATE SCHEMA issue_6543;
SET search_path TO issue_6543;
SET citus.shard_count TO 4;
SET citus.shard_replication_factor TO 1;
SET citus.next_shard_id TO 67322500;

CREATE TABLE event (
tenant_id varchar,
id bigint,
primary key (tenant_id, id)
);

CREATE TABLE page (
tenant_id varchar,
id int,
primary key (tenant_id, id)
);

SELECT create_distributed_table('event', 'tenant_id');
SELECT create_distributed_table('page', 'tenant_id', colocate_with => 'event');
alter table page add constraint fk21 foreign key (tenant_id, id) references event;

SET client_min_messages TO WARNING;
DROP SCHEMA issue_6543 CASCADE;

0 comments on commit 2c5af71

Please sign in to comment.