Move check dependencies functions

velioglu/cyclic_dep_2
Burak Velioglu 2022-03-08 13:24:38 +03:00
parent 0bc5df9d7b
commit 0d396c67b3
No known key found for this signature in database
GPG Key ID: F6827E620F6549C6
7 changed files with 61 additions and 60 deletions

View File

@ -318,7 +318,6 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys, bool autoConve
* Ensure dependencies exist as we will create shell table on the other nodes * Ensure dependencies exist as we will create shell table on the other nodes
* in the MX case. * in the MX case.
*/ */
EnsureRelationDependenciesCanBeDistributed(&tableAddress);
EnsureDependenciesExistOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
/* /*

View File

@ -444,7 +444,6 @@ CreateDistributedTable(Oid relationId, char *distributionColumnName,
ObjectAddress tableAddress = { 0 }; ObjectAddress tableAddress = { 0 };
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureRelationDependenciesCanBeDistributed(&tableAddress);
EnsureDependenciesExistOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
char replicationModel = DecideReplicationModel(distributionMethod, char replicationModel = DecideReplicationModel(distributionMethod,

View File

@ -31,6 +31,7 @@
typedef bool (*AddressPredicate)(const ObjectAddress *); typedef bool (*AddressPredicate)(const ObjectAddress *);
static void EnsureDependenciesCanBeDistributed(const ObjectAddress *relationAddress);
static void ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress); static void ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress);
static int ObjectAddressComparator(const void *a, const void *b); static int ObjectAddressComparator(const void *a, const void *b);
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency); static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
@ -58,11 +59,10 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
List *ddlCommands = NULL; List *ddlCommands = NULL;
/* /*
* Having circular dependency between distributed objects prevents Citus from * If there is any unsupported dependency or circular dependency exists, Citus can
* adding a new node. So, error out if circular dependency exists for the given * not ensure dependencies will exist on all nodes.
* target object.
*/ */
ErrorIfCircularDependencyExists(target); EnsureDependenciesCanBeDistributed(target);
/* collect all dependencies in creation order and get their ddl commands */ /* collect all dependencies in creation order and get their ddl commands */
List *dependencies = GetDependenciesForObject(target); List *dependencies = GetDependenciesForObject(target);
@ -143,6 +143,61 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
} }
/*
* EnsureDependenciesCanBeDistributed ensures all dependencies of the given object
* can be distributed.
*/
static void
EnsureDependenciesCanBeDistributed(const ObjectAddress *objectAddress)
{
/* If an object circularcly depends to itself, Citus can not handle it */
ErrorIfCircularDependencyExists(objectAddress);
/* If any of the dependency of the object can not be distributed, error out */
ObjectAddress *undistributableDependency = GetUndistributableDependency(
objectAddress);
if (undistributableDependency != NULL)
{
if (SupportedDependencyByCitus(undistributableDependency))
{
/*
* Citus can't distribute some relations as dependency, although those
* types as supported by Citus. So we can use get_rel_name directly
*
* For now the relations are the only type that is supported by Citus
* but can not be distributed as dependency, though we've added an
* explicit check below as well to not to break the logic here in case
* GetUndistributableDependency changes.
*/
if (getObjectClass(undistributableDependency) == OCLASS_CLASS)
{
char *tableName = get_rel_name(objectAddress->objectId);
char *dependentRelationName = get_rel_name(
undistributableDependency->objectId);
ereport(ERROR, (errmsg("Relation \"%s\" has dependency to a table"
" \"%s\" that is not in Citus' metadata",
tableName, dependentRelationName),
errhint("Distribute dependent relation first.")));
}
}
char *dependencyDescription = NULL;
char *objectDescription = NULL;
#if PG_VERSION_NUM >= PG_VERSION_14
dependencyDescription = getObjectDescription(undistributableDependency, false);
objectDescription = getObjectDescription(objectAddress, false);
#else
dependencyDescription = getObjectDescription(undistributableDependency);
objectDescription = getObjectDescription(objectAddress);
#endif
ereport(ERROR, (errmsg("Object \"%s\" has dependency on unsupported "
"object \"%s\"", objectDescription,
dependencyDescription)));
}
}
/* /*
* ErrorIfCircularDependencyExists checks whether given object has circular dependency * ErrorIfCircularDependencyExists checks whether given object has circular dependency
* with itself via existing objects of pg_dist_object. * with itself via existing objects of pg_dist_object.

View File

@ -1955,7 +1955,6 @@ PostprocessAlterTableStmt(AlterTableStmt *alterTableStatement)
/* changing a relation could introduce new dependencies */ /* changing a relation could introduce new dependencies */
ObjectAddress tableAddress = { 0 }; ObjectAddress tableAddress = { 0 };
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureRelationDependenciesCanBeDistributed(&tableAddress);
EnsureDependenciesExistOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
} }

View File

@ -741,61 +741,12 @@ SupportedDependencyByCitus(const ObjectAddress *address)
} }
/*
* EnsureRelationDependenciesCanBeDistributed ensures all dependencies of the relation
* can be distributed.
*/
void
EnsureRelationDependenciesCanBeDistributed(ObjectAddress *relationAddress)
{
ObjectAddress *undistributableDependency =
GetUndistributableDependency(relationAddress);
if (undistributableDependency != NULL)
{
char *tableName = get_rel_name(relationAddress->objectId);
if (SupportedDependencyByCitus(undistributableDependency))
{
/*
* Citus can't distribute some relations as dependency, although those
* types as supported by Citus. So we can use get_rel_name directly
*
* For now the relations are the only type that is supported by Citus
* but can not be distributed as dependency, though we've added an
* explicit check below as well to not to break the logic here in case
* GetUndistributableDependency changes.
*/
if (getObjectClass(undistributableDependency) == OCLASS_CLASS)
{
char *dependentRelationName = get_rel_name(
undistributableDependency->objectId);
ereport(ERROR, (errmsg("Relation \"%s\" has dependency to a table"
" \"%s\" that is not in Citus' metadata",
tableName, dependentRelationName),
errhint("Distribute dependent relation first.")));
}
}
char *objectType = NULL;
#if PG_VERSION_NUM >= PG_VERSION_14
objectType = getObjectDescription(undistributableDependency, false);
#else
objectType = getObjectDescription(undistributableDependency);
#endif
ereport(ERROR, (errmsg("Relation \"%s\" has dependency on unsupported "
"object \"%s\"", tableName, objectType)));
}
}
/* /*
* GetUndistributableDependency checks whether object has any non-distributable * GetUndistributableDependency checks whether object has any non-distributable
* dependency. If any one found, it will be returned. * dependency. If any one found, it will be returned.
*/ */
ObjectAddress * ObjectAddress *
GetUndistributableDependency(ObjectAddress *objectAddress) GetUndistributableDependency(const ObjectAddress *objectAddress)
{ {
List *dependencies = GetAllDependenciesForObject(objectAddress); List *dependencies = GetAllDependenciesForObject(objectAddress);
ObjectAddress *dependency = NULL; ObjectAddress *dependency = NULL;

View File

@ -267,7 +267,6 @@ extern List * PreprocessCreateFunctionStmt(Node *stmt, const char *queryString,
ProcessUtilityContext processUtilityContext); ProcessUtilityContext processUtilityContext);
extern List * PostprocessCreateFunctionStmt(Node *stmt, extern List * PostprocessCreateFunctionStmt(Node *stmt,
const char *queryString); const char *queryString);
extern ObjectAddress * GetUndistributableDependency(ObjectAddress *functionAddress);
extern ObjectAddress CreateFunctionStmtObjectAddress(Node *stmt, extern ObjectAddress CreateFunctionStmtObjectAddress(Node *stmt,
bool missing_ok); bool missing_ok);
extern ObjectAddress DefineAggregateStmtObjectAddress(Node *stmt, extern ObjectAddress DefineAggregateStmtObjectAddress(Node *stmt,

View File

@ -21,8 +21,7 @@ extern List * GetUniqueDependenciesList(List *objectAddressesList);
extern List * GetDependenciesForObject(const ObjectAddress *target); extern List * GetDependenciesForObject(const ObjectAddress *target);
extern List * GetAllSupportedDependenciesForObject(const ObjectAddress *target); extern List * GetAllSupportedDependenciesForObject(const ObjectAddress *target);
extern List * GetAllDependenciesForObject(const ObjectAddress *target); extern List * GetAllDependenciesForObject(const ObjectAddress *target);
extern void EnsureRelationDependenciesCanBeDistributed(ObjectAddress *relationAddress); extern ObjectAddress * GetUndistributableDependency(const ObjectAddress *target);
extern ObjectAddress * GetUndistributableDependency(ObjectAddress *target);
extern List * OrderObjectAddressListInDependencyOrder(List *objectAddressList); extern List * OrderObjectAddressListInDependencyOrder(List *objectAddressList);
extern bool SupportedDependencyByCitus(const ObjectAddress *address); extern bool SupportedDependencyByCitus(const ObjectAddress *address);
extern List * GetPgDependTuplesForDependingObjects(Oid targetObjectClassId, extern List * GetPgDependTuplesForDependingObjects(Oid targetObjectClassId,