Error out if adding a new object causes a circular dependency

velioglu/cyclic_dep_with_tho
Burak Velioglu 2022-03-04 12:33:15 +03:00
parent 341c3ee90a
commit 3668492e14
No known key found for this signature in database
GPG Key ID: F6827E620F6549C6
1 changed files with 42 additions and 0 deletions

View File

@ -31,6 +31,7 @@
typedef bool (*AddressPredicate)(const ObjectAddress *);
static void ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress);
static int ObjectAddressComparator(const void *a, const void *b);
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
static List * FilterObjectAddressListByPredicate(List *objectAddressList,
@ -56,6 +57,13 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
List *dependenciesWithCommands = NIL;
List *ddlCommands = NULL;
/*
* Having circular dependency between distributed objects prevents Citus from
* adding a new node. So, error out if circular dependency exists for the given
* target object.
*/
ErrorIfCircularDependencyExists(target);
/* collect all dependencies in creation order and get their ddl commands */
List *dependencies = GetDependenciesForObject(target);
ObjectAddress *dependency = NULL;
@ -135,6 +143,40 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
}
/*
* ErrorIfCircularDependencyExists checks whether given object has circular dependency
* with itself via existing objects of pg_dist_object.
*/
static void
ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
{
List *dependencies = GetAllSupportedDependenciesForObject(objectAddress);
ObjectAddress *dependency = NULL;
foreach_ptr(dependency, dependencies)
{
if (dependency->classId == objectAddress->classId &&
dependency->objectId == objectAddress->objectId &&
dependency->objectSubId == objectAddress->objectSubId)
{
char *objectDescription = NULL;
#if PG_VERSION_NUM >= PG_VERSION_14
objectDescription = getObjectDescription(objectAddress, false);
#else
objectDescription = getObjectDescription(objectAddress);
#endif
ereport(ERROR, (errmsg("Citus can not handle circular dependencies "
"between distributed objects"),
errdetail("\"%s\" circularly depends itself, resolve "
"circular dependency first",
objectDescription)));
}
}
}
/*
* Copied from PG object_address_comparator function to compare ObjectAddresses.
*/