diff --git a/src/backend/distributed/commands/distribute_object_ops.c b/src/backend/distributed/commands/distribute_object_ops.c index 8f372a9e8..d9d4533f0 100644 --- a/src/backend/distributed/commands/distribute_object_ops.c +++ b/src/backend/distributed/commands/distribute_object_ops.c @@ -15,6 +15,10 @@ #include "distributed/commands.h" #include "distributed/deparser.h" +static bool MatchOnAllNestedObjectTypes(Node *node, + DistributedObjectOpsContainerNestedInfo * + nestedInfo); + static DistributeObjectOps NoDistributeOps = { .deparse = NULL, .qualify = NULL, @@ -23,17 +27,6 @@ static DistributeObjectOps NoDistributeOps = { .address = NULL, }; -/* TODO this is a 2 level nested statement which we do not currently support */ -static DistributeObjectOps Attribute_Rename = { - .deparse = DeparseRenameAttributeStmt, - .qualify = QualifyRenameAttributeStmt, - .preprocess = PreprocessRenameAttributeStmt, - .postprocess = NULL, - .address = RenameAttributeStmtObjectAddress, -}; -REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_ATTRIBUTE, - Attribute_Rename); - /* linker provided pointers */ SECTION_ARRAY(DistributedObjectOpsContainer *, opscontainer); @@ -50,20 +43,9 @@ GetDistributeObjectOps(Node *node) for (i = 0; i < sz; i++) { DistributedObjectOpsContainer *container = opscontainer_array[i]; - if (node->type == container->type) + if (node->type == container->type && + MatchOnAllNestedObjectTypes(node, container->nestedInfo)) { - if (container->nested) - { - /* nested types are not perse a match */ - ObjectType nestedType = *((ObjectType *) (((char *) node) + - container->nestedOffset)); - if (container->nestedType != nestedType) - { - /* nested types do not match, skip this entry */ - continue; - } - } - /* this DistributedObjectOps is a match for the current statement */ return container->ops; } @@ -72,3 +54,31 @@ GetDistributeObjectOps(Node *node) /* no DistributedObjectOps linked for this statement type */ return &NoDistributeOps; } + + +static bool +MatchOnAllNestedObjectTypes(Node *node, + DistributedObjectOpsContainerNestedInfo *nestedInfo) +{ + if (nestedInfo == NULL) + { + /* No nested information, matching by convention */ + return true; + } + + /* + * Iterate till you find the last entry { 0 }. For convenience it is the only one with + * offset 0 + */ + for (; nestedInfo->offset != 0; ++nestedInfo) + { + ObjectType nestedType = *((ObjectType *) (((char *) node) + nestedInfo->offset)); + if (nestedInfo->type != nestedType) + { + /* nested object type is not matching*/ + return false; + } + } + + return true; +} diff --git a/src/backend/distributed/commands/rename.c b/src/backend/distributed/commands/rename.c index 868085a3f..679d127a0 100644 --- a/src/backend/distributed/commands/rename.c +++ b/src/backend/distributed/commands/rename.c @@ -154,30 +154,3 @@ ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt) "currently unsupported"))); } } - - -/* - * PreprocessRenameAttributeStmt called for RenameStmt's that are targetting an attribute eg. - * type attributes. Based on the relation type the attribute gets renamed it dispatches to - * a specialized implementation if present, otherwise return an empty list for its DDLJobs - */ -List * -PreprocessRenameAttributeStmt(Node *node, const char *queryString) -{ - RenameStmt *stmt = castNode(RenameStmt, node); - Assert(stmt->renameType == OBJECT_ATTRIBUTE); - - switch (stmt->relationType) - { - case OBJECT_TYPE: - { - return PreprocessRenameTypeAttributeStmt(node, queryString); - } - - default: - { - /* unsupported relation for attribute rename, do nothing */ - return NIL; - } - } -} diff --git a/src/backend/distributed/commands/type.c b/src/backend/distributed/commands/type.c index d101fc149..62f9b1d8a 100644 --- a/src/backend/distributed/commands/type.c +++ b/src/backend/distributed/commands/type.c @@ -158,6 +158,18 @@ static DistributeObjectOps Type_Rename = { }; REGISTER_DISTRIBUTED_OPERATION_NESTED(RenameStmt, renameType, OBJECT_TYPE, Type_Rename); +static List * PreprocessRenameTypeAttributeStmt(Node *node, const char *queryString); +static ObjectAddress RenameTypeAttributeStmtObjectAddress(Node *node, bool missing_ok); +static DistributeObjectOps Type_Rename_Attribute = { + .deparse = DeparseRenameAttributeStmt, + .qualify = QualifyRenameAttributeStmt, + .preprocess = PreprocessRenameTypeAttributeStmt, + .postprocess = NULL, + .address = RenameTypeAttributeStmtObjectAddress, +}; +REGISTER_DISTRIBUTED_OPERATION_NESTED2(RenameStmt, renameType, OBJECT_ATTRIBUTE, + relationType, OBJECT_TYPE, Type_Rename_Attribute); + static List * PreprocessCompositeTypeStmt(Node *node, const char *queryString); static List * PostprocessCompositeTypeStmt(Node *node, const char *queryString); static ObjectAddress CompositeTypeStmtObjectAddress(Node *node, bool missing_ok); @@ -638,7 +650,7 @@ PreprocessRenameTypeStmt(Node *node, const char *queryString) * For distributed types we apply the attribute renames directly on all the workers to * keep the type in sync across the cluster. */ -List * +static List * PreprocessRenameTypeAttributeStmt(Node *node, const char *queryString) { RenameStmt *stmt = castNode(RenameStmt, node); @@ -1075,7 +1087,7 @@ AlterTypeSchemaStmtObjectAddress(Node *node, bool missing_ok) * changed as Attributes are not distributed on their own but as a side effect of the * whole type distribution. */ -ObjectAddress +static ObjectAddress RenameTypeAttributeStmtObjectAddress(Node *node, bool missing_ok) { RenameStmt *stmt = castNode(RenameStmt, node); diff --git a/src/backend/distributed/deparser/objectaddress.c b/src/backend/distributed/deparser/objectaddress.c index 3f245ca24..1f8b7e219 100644 --- a/src/backend/distributed/deparser/objectaddress.c +++ b/src/backend/distributed/deparser/objectaddress.c @@ -37,28 +37,6 @@ GetObjectAddressFromParseTree(Node *parseTree, bool missing_ok) } -ObjectAddress -RenameAttributeStmtObjectAddress(Node *node, bool missing_ok) -{ - RenameStmt *stmt = castNode(RenameStmt, node); - Assert(stmt->renameType == OBJECT_ATTRIBUTE); - - switch (stmt->relationType) - { - case OBJECT_TYPE: - { - return RenameTypeAttributeStmtObjectAddress(node, missing_ok); - } - - default: - { - ereport(ERROR, (errmsg("unsupported alter rename attribute statement to get " - "object address for"))); - } - } -} - - /* * AlterExtensionStmtObjectAddress finds the ObjectAddress for the extension described * by the AlterExtensionStmt. If missing_ok is false, then this function throws an diff --git a/src/include/distributed/commands.h b/src/include/distributed/commands.h index 36889492a..f5c882029 100644 --- a/src/include/distributed/commands.h +++ b/src/include/distributed/commands.h @@ -44,26 +44,16 @@ typedef struct DistributeObjectOps ObjectAddress (*address)(Node *, bool); } DistributeObjectOps; +typedef struct DistributedObjectOpsContainerNestedInfo +{ + size_t offset; + ObjectType type; +} DistributedObjectOpsContainerNestedInfo; + typedef struct DistributedObjectOpsContainer { NodeTag type; - - /* - * Nested information is only set for statements that can operate on multiple - * different objects like ALTER ... SET SCHEMA. The object type is encoded in a field - * in the statement. - * - * bool nested - * signals this container describes a nested tyoe - * size_t nestedOffset - * the offest of the ObjectType field within the statement - * ObjectType nestedType - * the object type the DistributedObjectOps of this container operates on - */ - bool nested; - size_t nestedOffset; - ObjectType nestedType; - + DistributedObjectOpsContainerNestedInfo *nestedInfo; DistributeObjectOps *ops; } DistributedObjectOpsContainer; @@ -97,18 +87,36 @@ typedef struct DistributedObjectOpsContainer ((size_t) ((__stop_ ## sect - __start_ ## sect))) #define REGISTER_DISTRIBUTED_OPERATION(stmt, opsvar) \ - static DistributedObjectOpsContainer PP_CAT(opscontainer, opsvar) = { \ + static DistributedObjectOpsContainer PP_CAT(opscontainer_, stmt) = { \ .type = T_ ## stmt, \ .ops = &opsvar, \ }; \ - REGISTER_SECTION_POINTER(opscontainer, PP_CAT(opscontainer, opsvar)) + REGISTER_SECTION_POINTER(opscontainer, PP_CAT(opscontainer_, stmt)) #define REGISTER_DISTRIBUTED_OPERATION_NESTED(stmt, objectVarName, objtype, opsvar) \ + static DistributedObjectOpsContainerNestedInfo \ + PP_CAT3(opscontainer_info, stmt, objtype)[] = { \ + { offsetof(stmt, objectVarName), objtype }, \ + { 0 } \ + }; \ static DistributedObjectOpsContainer PP_CAT3(opscontainer_, stmt, objtype) = { \ .type = T_ ## stmt, \ - .nested = true, \ - .nestedOffset = offsetof(stmt, objectVarName), \ - .nestedType = objtype, \ + .nestedInfo = &PP_CAT3(opscontainer_info, stmt, objtype)[0], \ + .ops = &opsvar, \ + }; \ + REGISTER_SECTION_POINTER(opscontainer, PP_CAT3(opscontainer_, stmt, objtype)) + +#define REGISTER_DISTRIBUTED_OPERATION_NESTED2(stmt, objectVarName1, objtype1, \ + objectVarName2, objtype2, opsvar) \ + static DistributedObjectOpsContainerNestedInfo \ + PP_CAT3(opscontainer_info, stmt, objtype)[] = { \ + { offsetof(stmt, objectVarName1), objtype1 }, \ + { offsetof(stmt, objectVarName2), objtype2 }, \ + { 0 } \ + }; \ + static DistributedObjectOpsContainer PP_CAT3(opscontainer_, stmt, objtype) = { \ + .type = T_ ## stmt, \ + .nestedInfo = &PP_CAT3(opscontainer_info, stmt, objtype)[0], \ .ops = &opsvar, \ }; \ REGISTER_SECTION_POINTER(opscontainer, PP_CAT3(opscontainer_, stmt, objtype)) @@ -178,7 +186,6 @@ extern void DropPolicyEventExtendNames(DropStmt *stmt, const char *schemaName, u /* rename.c - forward declarations*/ extern void ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt); -extern List * PreprocessRenameAttributeStmt(Node *stmt, const char *queryString); /* role.c - forward declarations*/ @@ -214,11 +221,8 @@ extern void ErrorIfUnsupportedConstraint(Relation relation, char distributionMet extern void PostprocessTruncateStatement(TruncateStmt *truncateStatement); /* type.c - forward declarations */ -extern List * PreprocessRenameTypeAttributeStmt(Node *stmt, const char *queryString); extern Node * CreateTypeStmtByObjectAddress(const ObjectAddress *address); -extern ObjectAddress RenameTypeAttributeStmtObjectAddress(Node *stmt, - bool missing_ok); extern List * CreateTypeDDLCommandsIdempotent(const ObjectAddress *typeAddress); extern char * GenerateBackupNameForTypeCollision(const ObjectAddress *address); diff --git a/src/include/distributed/deparser.h b/src/include/distributed/deparser.h index c016665b0..e7dc59fbb 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -76,7 +76,6 @@ extern void QualifyAlterTypeSchemaStmt(Node *stmt); extern void QualifyAlterTypeOwnerStmt(Node *stmt); extern ObjectAddress GetObjectAddressFromParseTree(Node *parseTree, bool missing_ok); -extern ObjectAddress RenameAttributeStmtObjectAddress(Node *stmt, bool missing_ok); /* forward declarations for deparse_function_stmts.c */ extern char * DeparseDropFunctionStmt(Node *stmt);