Do not rely on fk cache when truncating local data (#5018)

pull/5029/head
Hanefi Onaldi 2021-06-07 11:56:48 +03:00 committed by GitHub
parent 9770a1bf00
commit 5c6069a74a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 19 deletions

View File

@ -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

View File

@ -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)));
}
}

View File

@ -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);