diff --git a/src/backend/distributed/commands/foreign_constraint.c b/src/backend/distributed/commands/foreign_constraint.c index 8fdc932ee..fe146c268 100644 --- a/src/backend/distributed/commands/foreign_constraint.c +++ b/src/backend/distributed/commands/foreign_constraint.c @@ -734,8 +734,8 @@ HasForeignKeyWithLocalTable(Oid relationId) /* - * GetForeignKeysWithLocalTables returns a list foreign keys for foreign key - * relationaships that relation has with local tables. + * GetForeignKeysWithLocalTables returns a list of foreign keys for foreign key + * relationships that relation has with local tables. */ static List * GetForeignKeysWithLocalTables(Oid relationId) @@ -753,6 +753,21 @@ GetForeignKeysWithLocalTables(Oid relationId) } +/* + * GetForeignKeysFromLocalTables returns a list of foreign keys where the referencing + * relation is a local table. + */ +List * +GetForeignKeysFromLocalTables(Oid relationId) +{ + int referencedFKeysFlag = INCLUDE_REFERENCED_CONSTRAINTS | + INCLUDE_LOCAL_TABLES; + List *referencingFKeyList = GetForeignKeyOids(relationId, referencedFKeysFlag); + + return referencingFKeyList; +} + + /* * HasForeignKeyToCitusLocalTable returns true if any of the foreign key constraints * on the relation with relationId references to a citus local table. @@ -1102,6 +1117,30 @@ GetReferencedTableId(Oid foreignKeyId) } +/* + * GetReferencingTableId returns OID of the referencing relation for the foreign + * key with foreignKeyId. If there is no such foreign key, then this function + * returns InvalidOid. + */ +Oid +GetReferencingTableId(Oid foreignKeyId) +{ + HeapTuple heapTuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(foreignKeyId)); + if (!HeapTupleIsValid(heapTuple)) + { + /* no such foreign key */ + return InvalidOid; + } + + Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple); + Oid referencingTableId = constraintForm->conrelid; + + ReleaseSysCache(heapTuple); + + return referencingTableId; +} + + /* * IsTableTypeIncluded returns true if type of the table with relationId (distributed, * reference, Citus local or Postgres local) is included in the flags, false if not diff --git a/src/backend/distributed/commands/truncate.c b/src/backend/distributed/commands/truncate.c index e4d833672..30b9f3765 100644 --- a/src/backend/distributed/commands/truncate.c +++ b/src/backend/distributed/commands/truncate.c @@ -217,25 +217,20 @@ EnsureLocalTableCanBeTruncated(Oid relationId) "tables."))); } - /* make sure there are no foreign key references from a local table */ - SetForeignConstraintRelationshipGraphInvalid(); - List *referencingRelationList = ReferencingRelationIdList(relationId); - - Oid referencingRelation = InvalidOid; - foreach_oid(referencingRelation, referencingRelationList) + List *referencingForeignConstaintsFromLocalTables = + GetForeignKeysFromLocalTables(relationId); + if (list_length(referencingForeignConstaintsFromLocalTables) > 0) { - /* we do not truncate a table if there is a local table referencing it */ - if (!IsCitusTable(referencingRelation)) - { - char *referencedRelationName = get_rel_name(relationId); - char *referencingRelationName = get_rel_name(referencingRelation); + Oid foreignKeyId = linitial_oid(referencingForeignConstaintsFromLocalTables); + Oid referencingRelation = GetReferencingTableId(foreignKeyId); + char *referencedRelationName = get_rel_name(relationId); + char *referencingRelationName = get_rel_name(referencingRelation); - ereport(ERROR, (errmsg("cannot truncate a table referenced in a " - "foreign key constraint by a local table"), - errdetail("Table \"%s\" references \"%s\"", - referencingRelationName, - referencedRelationName))); - } + ereport(ERROR, (errmsg("cannot truncate a table referenced in a " + "foreign key constraint by a local table"), + errdetail("Table \"%s\" references \"%s\"", + referencingRelationName, + referencedRelationName))); } } diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 4fc9eef64..8556f9836 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -207,6 +207,7 @@ extern bool AnyForeignKeyDependsOnIndex(Oid indexId); extern bool HasForeignKeyWithLocalTable(Oid relationId); extern bool HasForeignKeyToCitusLocalTable(Oid relationId); extern bool HasForeignKeyToReferenceTable(Oid relationOid); +extern List * GetForeignKeysFromLocalTables(Oid relationId); extern bool TableReferenced(Oid relationOid); extern bool TableReferencing(Oid relationOid); extern bool ConstraintIsAUniquenessConstraint(char *inputConstaintName, Oid relationId); @@ -217,6 +218,7 @@ extern bool ConstraintWithIdIsOfType(Oid constraintId, char targetConstraintType extern bool TableHasExternalForeignKeys(Oid relationId); extern List * GetForeignKeyOids(Oid relationId, int flags); extern Oid GetReferencedTableId(Oid foreignKeyId); +extern Oid GetReferencingTableId(Oid foreignKeyId); extern bool RelationInvolvedInAnyNonInheritedForeignKeys(Oid relationId);