Refactor foreign key functions to use table types (#4424)

* Reuses extractReferencing/Referenced variables

* Refactors GetForeignKeyOids function to check table types

* Converts flags to inclusive
pull/4445/head
Halil Ozan Akgül 2020-12-23 17:05:09 +03:00 committed by GitHub
parent d1b3eaf767
commit 9fd3f62cb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 81 deletions

View File

@ -68,10 +68,7 @@ static List * GetForeignKeyIdsForColumn(char *columnName, Oid relationId,
int searchForeignKeyColumnFlags); int searchForeignKeyColumnFlags);
static List * GetForeignConstraintCommandsInternal(Oid relationId, int flags); static List * GetForeignConstraintCommandsInternal(Oid relationId, int flags);
static Oid get_relation_constraint_oid_compat(HeapTuple heapTuple); static Oid get_relation_constraint_oid_compat(HeapTuple heapTuple);
static List * GetForeignKeyOidsToCitusLocalTables(Oid relationId); static bool IsTableTypeIncluded(Oid relationId, int flags);
static List * GetForeignKeyOidsToReferenceTables(Oid relationId);
static List * FilterFKeyOidListByReferencedTableType(List *foreignKeyOidList,
CitusTableType citusTableType);
/* /*
* ConstraintIsAForeignKeyToReferenceTable checks if the given constraint is a * ConstraintIsAForeignKeyToReferenceTable checks if the given constraint is a
@ -80,7 +77,8 @@ static List * FilterFKeyOidListByReferencedTableType(List *foreignKeyOidList,
bool bool
ConstraintIsAForeignKeyToReferenceTable(char *inputConstaintName, Oid relationId) ConstraintIsAForeignKeyToReferenceTable(char *inputConstaintName, Oid relationId)
{ {
List *foreignKeyOids = GetForeignKeyOidsToReferenceTables(relationId); int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_REFERENCE_TABLES;
List *foreignKeyOids = GetForeignKeyOids(relationId, flags);
Oid foreignKeyOid = FindForeignKeyOidWithName(foreignKeyOids, inputConstaintName); Oid foreignKeyOid = FindForeignKeyOidWithName(foreignKeyOids, inputConstaintName);
@ -122,7 +120,7 @@ ErrorIfUnsupportedForeignConstraintExists(Relation relation, char referencingDis
{ {
Oid referencingTableId = relation->rd_id; Oid referencingTableId = relation->rd_id;
int flags = INCLUDE_REFERENCING_CONSTRAINTS; int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
List *foreignKeyOids = GetForeignKeyOids(referencingTableId, flags); List *foreignKeyOids = GetForeignKeyOids(referencingTableId, flags);
Oid foreignKeyOid = InvalidOid; Oid foreignKeyOid = InvalidOid;
@ -595,7 +593,7 @@ GetForeignKeyIdsForColumn(char *columnName, Oid relationId,
List * List *
GetReferencingForeignConstaintCommands(Oid relationId) GetReferencingForeignConstaintCommands(Oid relationId)
{ {
int flags = INCLUDE_REFERENCING_CONSTRAINTS; int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
return GetForeignConstraintCommandsInternal(relationId, flags); return GetForeignConstraintCommandsInternal(relationId, flags);
} }
@ -661,23 +659,9 @@ get_relation_constraint_oid_compat(HeapTuple heapTuple)
bool bool
HasForeignKeyToCitusLocalTable(Oid relationId) HasForeignKeyToCitusLocalTable(Oid relationId)
{ {
List *foreignKeyOidList = GetForeignKeyOidsToCitusLocalTables(relationId); int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_CITUS_LOCAL_TABLES;
return list_length(foreignKeyOidList) > 0;
}
/*
* GetForeignKeyOidsToCitusLocalTables returns list of OIDs for the foreign key
* constraints on the given relationId that are referencing to citus local tables.
*/
static List *
GetForeignKeyOidsToCitusLocalTables(Oid relationId)
{
int flags = INCLUDE_REFERENCING_CONSTRAINTS;
List *foreignKeyOidList = GetForeignKeyOids(relationId, flags); List *foreignKeyOidList = GetForeignKeyOids(relationId, flags);
List *fKeyOidsToCitusLocalTables = return list_length(foreignKeyOidList) > 0;
FilterFKeyOidListByReferencedTableType(foreignKeyOidList, CITUS_LOCAL_TABLE);
return fKeyOidsToCitusLocalTables;
} }
@ -689,57 +673,13 @@ GetForeignKeyOidsToCitusLocalTables(Oid relationId)
bool bool
HasForeignKeyToReferenceTable(Oid relationId) HasForeignKeyToReferenceTable(Oid relationId)
{ {
List *foreignKeyOids = GetForeignKeyOidsToReferenceTables(relationId); int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_REFERENCE_TABLES;
List *foreignKeyOids = GetForeignKeyOids(relationId, flags);
return list_length(foreignKeyOids) > 0; return list_length(foreignKeyOids) > 0;
} }
/*
* GetForeignKeyOidsToReferenceTables returns list of OIDs for the foreign key
* constraints on the given relationId that are referencing to reference tables.
*/
static List *
GetForeignKeyOidsToReferenceTables(Oid relationId)
{
int flags = INCLUDE_REFERENCING_CONSTRAINTS;
List *foreignKeyOidList = GetForeignKeyOids(relationId, flags);
List *fKeyOidsToReferenceTables =
FilterFKeyOidListByReferencedTableType(foreignKeyOidList, REFERENCE_TABLE);
return fKeyOidsToReferenceTables;
}
/*
* FilterFKeyOidListByReferencedTableType takes a list of foreign key OIDs and
* CitusTableType to filter the foreign key OIDs that CitusTableType matches
* referenced relation's type.
*/
static List *
FilterFKeyOidListByReferencedTableType(List *foreignKeyOidList,
CitusTableType citusTableType)
{
List *filteredFKeyOidList = NIL;
Oid foreignKeyOid = InvalidOid;
foreach_oid(foreignKeyOid, foreignKeyOidList)
{
HeapTuple heapTuple = SearchSysCache1(CONSTROID, ObjectIdGetDatum(foreignKeyOid));
Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple);
Oid referencedTableOid = constraintForm->confrelid;
if (IsCitusTableType(referencedTableOid, citusTableType))
{
filteredFKeyOidList = lappend_oid(filteredFKeyOidList, foreignKeyOid);
}
ReleaseSysCache(heapTuple);
}
return filteredFKeyOidList;
}
/* /*
* TableReferenced function checks whether given table is referenced by another table * TableReferenced function checks whether given table is referenced by another table
* via foreign constraints. If it is referenced, this function returns true. * via foreign constraints. If it is referenced, this function returns true.
@ -747,7 +687,7 @@ FilterFKeyOidListByReferencedTableType(List *foreignKeyOidList,
bool bool
TableReferenced(Oid relationId) TableReferenced(Oid relationId)
{ {
int flags = INCLUDE_REFERENCED_CONSTRAINTS; int flags = INCLUDE_REFERENCED_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
List *foreignKeyOids = GetForeignKeyOids(relationId, flags); List *foreignKeyOids = GetForeignKeyOids(relationId, flags);
return list_length(foreignKeyOids) > 0; return list_length(foreignKeyOids) > 0;
@ -793,7 +733,7 @@ HeapTupleOfForeignConstraintIncludesColumn(HeapTuple heapTuple, Oid relationId,
bool bool
TableReferencing(Oid relationId) TableReferencing(Oid relationId)
{ {
int flags = INCLUDE_REFERENCING_CONSTRAINTS; int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
List *foreignKeyOids = GetForeignKeyOids(relationId, flags); List *foreignKeyOids = GetForeignKeyOids(relationId, flags);
return list_length(foreignKeyOids) > 0; return list_length(foreignKeyOids) > 0;
@ -821,7 +761,7 @@ ConstraintIsAForeignKey(char *inputConstaintName, Oid relationId)
Oid Oid
GetForeignKeyOidByName(char *inputConstaintName, Oid relationId) GetForeignKeyOidByName(char *inputConstaintName, Oid relationId)
{ {
int flags = INCLUDE_REFERENCING_CONSTRAINTS; int flags = INCLUDE_REFERENCING_CONSTRAINTS | INCLUDE_ALL_TABLE_TYPES;
List *foreignKeyOids = GetForeignKeyOids(relationId, flags); List *foreignKeyOids = GetForeignKeyOids(relationId, flags);
Oid foreignKeyId = FindForeignKeyOidWithName(foreignKeyOids, inputConstaintName); Oid foreignKeyId = FindForeignKeyOidWithName(foreignKeyOids, inputConstaintName);
@ -862,10 +802,12 @@ FindForeignKeyOidWithName(List *foreignKeyOids, const char *inputConstraintName)
void void
ErrorIfTableHasExternalForeignKeys(Oid relationId) ErrorIfTableHasExternalForeignKeys(Oid relationId)
{ {
int flags = (INCLUDE_REFERENCING_CONSTRAINTS | EXCLUDE_SELF_REFERENCES); int flags = (INCLUDE_REFERENCING_CONSTRAINTS | EXCLUDE_SELF_REFERENCES |
INCLUDE_ALL_TABLE_TYPES);
List *foreignKeyIdsTableReferencing = GetForeignKeyOids(relationId, flags); List *foreignKeyIdsTableReferencing = GetForeignKeyOids(relationId, flags);
flags = (INCLUDE_REFERENCED_CONSTRAINTS | EXCLUDE_SELF_REFERENCES); flags = (INCLUDE_REFERENCED_CONSTRAINTS | EXCLUDE_SELF_REFERENCES |
INCLUDE_ALL_TABLE_TYPES);
List *foreignKeyIdsTableReferenced = GetForeignKeyOids(relationId, flags); List *foreignKeyIdsTableReferenced = GetForeignKeyOids(relationId, flags);
List *foreignKeysWithOtherTables = list_concat(foreignKeyIdsTableReferencing, List *foreignKeysWithOtherTables = list_concat(foreignKeyIdsTableReferencing,
@ -897,10 +839,8 @@ GetForeignKeyOids(Oid relationId, int flags)
{ {
AttrNumber pgConstraintTargetAttrNumber = InvalidAttrNumber; AttrNumber pgConstraintTargetAttrNumber = InvalidAttrNumber;
bool extractReferencing PG_USED_FOR_ASSERTS_ONLY = bool extractReferencing = (flags & INCLUDE_REFERENCING_CONSTRAINTS);
(flags & INCLUDE_REFERENCING_CONSTRAINTS); bool extractReferenced = (flags & INCLUDE_REFERENCED_CONSTRAINTS);
bool extractReferenced PG_USED_FOR_ASSERTS_ONLY =
(flags & INCLUDE_REFERENCED_CONSTRAINTS);
/* /*
* Only one of them should be passed at a time since the way we scan * Only one of them should be passed at a time since the way we scan
@ -913,14 +853,14 @@ GetForeignKeyOids(Oid relationId, int flags)
bool useIndex = false; bool useIndex = false;
Oid indexOid = InvalidOid; Oid indexOid = InvalidOid;
if (flags & INCLUDE_REFERENCING_CONSTRAINTS) if (extractReferencing)
{ {
pgConstraintTargetAttrNumber = Anum_pg_constraint_conrelid; pgConstraintTargetAttrNumber = Anum_pg_constraint_conrelid;
useIndex = true; useIndex = true;
indexOid = ConstraintRelidTypidNameIndexId; indexOid = ConstraintRelidTypidNameIndexId;
} }
else if (flags & INCLUDE_REFERENCED_CONSTRAINTS) else if (extractReferenced)
{ {
pgConstraintTargetAttrNumber = Anum_pg_constraint_confrelid; pgConstraintTargetAttrNumber = Anum_pg_constraint_confrelid;
} }
@ -970,6 +910,22 @@ GetForeignKeyOids(Oid relationId, int flags)
continue; continue;
} }
Oid otherTableId = InvalidOid;
if (extractReferencing)
{
otherTableId = constraintForm->confrelid;
}
else if (extractReferenced)
{
otherTableId = constraintForm->conrelid;
}
if (!IsTableTypeIncluded(otherTableId, flags))
{
heapTuple = systable_getnext(scanDescriptor);
continue;
}
foreignKeyOids = lappend_oid(foreignKeyOids, constraintId); foreignKeyOids = lappend_oid(foreignKeyOids, constraintId);
heapTuple = systable_getnext(scanDescriptor); heapTuple = systable_getnext(scanDescriptor);
@ -1010,3 +966,30 @@ GetReferencedTableId(Oid foreignKeyId)
return referencedTableId; return referencedTableId;
} }
/*
* 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
*/
static bool
IsTableTypeIncluded(Oid relationId, int flags)
{
if (!IsCitusTable(relationId))
{
return (flags & INCLUDE_LOCAL_TABLES) != 0;
}
else if (IsCitusTableType(relationId, DISTRIBUTED_TABLE))
{
return (flags & INCLUDE_DISTRIBUTED_TABLES) != 0;
}
else if (IsCitusTableType(relationId, REFERENCE_TABLE))
{
return (flags & INCLUDE_REFERENCE_TABLES) != 0;
}
else if (IsCitusTableType(relationId, CITUS_LOCAL_TABLE))
{
return (flags & INCLUDE_CITUS_LOCAL_TABLES) != 0;
}
return false;
}

View File

@ -61,7 +61,24 @@ typedef enum ExtractForeignKeyConstraintsMode
INCLUDE_REFERENCED_CONSTRAINTS = 1 << 1, INCLUDE_REFERENCED_CONSTRAINTS = 1 << 1,
/* exclude the self-referencing foreign keys */ /* exclude the self-referencing foreign keys */
EXCLUDE_SELF_REFERENCES = 1 << 2 EXCLUDE_SELF_REFERENCES = 1 << 2,
/* any combination of the 4 flags below is supported */
/* include foreign keys when the other table is a distributed table*/
INCLUDE_DISTRIBUTED_TABLES = 1 << 3,
/* include foreign keys when the other table is a reference table*/
INCLUDE_REFERENCE_TABLES = 1 << 4,
/* include foreign keys when the other table is a citus local table*/
INCLUDE_CITUS_LOCAL_TABLES = 1 << 5,
/* include foreign keys when the other table is a Postgres local table*/
INCLUDE_LOCAL_TABLES = 1 << 6,
/* include foreign keys regardless of the other table's type */
INCLUDE_ALL_TABLE_TYPES = INCLUDE_DISTRIBUTED_TABLES | INCLUDE_REFERENCE_TABLES |
INCLUDE_CITUS_LOCAL_TABLES | INCLUDE_LOCAL_TABLES
} ExtractForeignKeyConstraintMode; } ExtractForeignKeyConstraintMode;