Introduce GetDistributeObjectOps to organize dispatch of logic dependent on node/object type

pull/3364/head
Philip Dubé 2020-01-03 02:40:42 +00:00
parent 22cc5b1240
commit 73c06fae3b
47 changed files with 1658 additions and 2019 deletions

View File

@ -15,10 +15,11 @@
#include "distributed/metadata_cache.h" #include "distributed/metadata_cache.h"
/* placeholder for PlanClusterStmt */ /* placeholder for PreprocessClusterStmt */
List * List *
PlanClusterStmt(ClusterStmt *clusterStmt, const char *clusterCommand) PreprocessClusterStmt(Node *node, const char *clusterCommand)
{ {
ClusterStmt *clusterStmt = castNode(ClusterStmt, node);
bool showPropagationWarning = false; bool showPropagationWarning = false;
/* CLUSTER all */ /* CLUSTER all */

View File

@ -16,6 +16,7 @@
#include "distributed/commands/utility_hook.h" #include "distributed/commands/utility_hook.h"
#include "distributed/commands.h" #include "distributed/commands.h"
#include "distributed/deparser.h" #include "distributed/deparser.h"
#include "distributed/listutils.h"
#include "distributed/master_metadata_utility.h" #include "distributed/master_metadata_utility.h"
#include "distributed/metadata/distobject.h" #include "distributed/metadata/distobject.h"
#include "distributed/metadata_sync.h" #include "distributed/metadata_sync.h"
@ -163,14 +164,15 @@ CreateCollationDDLsIdempotent(Oid collationId)
ObjectAddress ObjectAddress
AlterCollationOwnerObjectAddress(AlterOwnerStmt *stmt) AlterCollationOwnerObjectAddress(Node *node, bool missing_ok)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Relation relation; Relation relation;
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
return get_object_address(stmt->objectType, stmt->object, &relation, return get_object_address(stmt->objectType, stmt->object, &relation,
AccessExclusiveLock, false); AccessExclusiveLock, missing_ok);
} }
@ -217,13 +219,14 @@ FilterNameListForDistributedCollations(List *objects, bool missing_ok,
List * List *
PlanDropCollationStmt(DropStmt *stmt) PreprocessDropCollationStmt(Node *node, const char *queryString)
{ {
DropStmt *stmt = castNode(DropStmt, node);
/* /*
* We swap the list of objects to remove during deparse so we need a reference back to * We swap the list of objects to remove during deparse so we need a reference back to
* the old list to put back * the old list to put back
*/ */
ListCell *addressCell = NULL;
List *distributedTypeAddresses = NIL; List *distributedTypeAddresses = NIL;
if (!ShouldPropagate()) if (!ShouldPropagate())
@ -253,10 +256,10 @@ PlanDropCollationStmt(DropStmt *stmt)
/* /*
* remove the entries for the distributed objects on dropping * remove the entries for the distributed objects on dropping
*/ */
foreach(addressCell, distributedTypeAddresses) ObjectAddress *addressItem = NULL;
foreach_ptr(addressItem, distributedTypeAddresses)
{ {
ObjectAddress *address = (ObjectAddress *) lfirst(addressCell); UnmarkObjectDistributed(addressItem);
UnmarkObjectDistributed(address);
} }
/* /*
@ -279,19 +282,20 @@ PlanDropCollationStmt(DropStmt *stmt)
/* /*
* PlanAlterCollationOwnerStmt is called for change of ownership of collations * PreprocessAlterCollationOwnerStmt is called for change of ownership of collations
* before the ownership is changed on the local instance. * before the ownership is changed on the local instance.
* *
* If the type for which the owner is changed is distributed we execute the change on all * If the type for which the owner is changed is distributed we execute the change on all
* the workers to keep the type in sync across the cluster. * the workers to keep the type in sync across the cluster.
*/ */
List * List *
PlanAlterCollationOwnerStmt(AlterOwnerStmt *stmt, const char *queryString) PreprocessAlterCollationOwnerStmt(Node *node, const char *queryString)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
ObjectAddress *collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(collationAddress)) if (!ShouldPropagateObject(&collationAddress))
{ {
return NIL; return NIL;
} }
@ -311,7 +315,7 @@ PlanAlterCollationOwnerStmt(AlterOwnerStmt *stmt, const char *queryString)
/* /*
* PlanRenameCollationStmt is called when the user is renaming the collation. The invocation happens * PreprocessRenameCollationStmt is called when the user is renaming the collation. The invocation happens
* before the statement is applied locally. * before the statement is applied locally.
* *
* As the collation already exists we have access to the ObjectAddress for the collation, this is * As the collation already exists we have access to the ObjectAddress for the collation, this is
@ -319,10 +323,11 @@ PlanAlterCollationOwnerStmt(AlterOwnerStmt *stmt, const char *queryString)
* executed on all the workers to keep the collation in sync across the cluster. * executed on all the workers to keep the collation in sync across the cluster.
*/ */
List * List *
PlanRenameCollationStmt(RenameStmt *stmt, const char *queryString) PreprocessRenameCollationStmt(Node *node, const char *queryString)
{ {
ObjectAddress *collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false); RenameStmt *stmt = castNode(RenameStmt, node);
if (!ShouldPropagateObject(collationAddress)) ObjectAddress collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(&collationAddress))
{ {
return NIL; return NIL;
} }
@ -345,18 +350,19 @@ PlanRenameCollationStmt(RenameStmt *stmt, const char *queryString)
/* /*
* PlanAlterCollationSchemaStmt is executed before the statement is applied to the local * PreprocessAlterCollationSchemaStmt is executed before the statement is applied to the local
* postgres instance. * postgres instance.
* *
* In this stage we can prepare the commands that need to be run on all workers. * In this stage we can prepare the commands that need to be run on all workers.
*/ */
List * List *
PlanAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PreprocessAlterCollationSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
ObjectAddress *collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(collationAddress)) if (!ShouldPropagateObject(&collationAddress))
{ {
return NIL; return NIL;
} }
@ -377,23 +383,26 @@ PlanAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryStrin
/* /*
* ProcessAlterCollationSchemaStmt is executed after the change has been applied locally, we * PostprocessAlterCollationSchemaStmt is executed after the change has been applied locally, we
* can now use the new dependencies of the type to ensure all its dependencies exist on * can now use the new dependencies of the type to ensure all its dependencies exist on
* the workers before we apply the commands remotely. * the workers before we apply the commands remotely.
*/ */
void List *
ProcessAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PostprocessAlterCollationSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
ObjectAddress *collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress collationAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(collationAddress)) if (!ShouldPropagateObject(&collationAddress))
{ {
return; return NIL;
} }
/* dependencies have changed (schema) let's ensure they exist */ /* dependencies have changed (schema) let's ensure they exist */
EnsureDependenciesExistsOnAllNodes(collationAddress); EnsureDependenciesExistOnAllNodes(&collationAddress);
return NIL;
} }
@ -401,15 +410,16 @@ ProcessAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt, const char *querySt
* RenameCollationStmtObjectAddress returns the ObjectAddress of the type that is the object * RenameCollationStmtObjectAddress returns the ObjectAddress of the type that is the object
* of the RenameStmt. Errors if missing_ok is false. * of the RenameStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
RenameCollationStmtObjectAddress(RenameStmt *stmt, bool missing_ok) RenameCollationStmtObjectAddress(Node *node, bool missing_ok)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_COLLATION); Assert(stmt->renameType == OBJECT_COLLATION);
ObjectAddress *address = palloc0(sizeof(ObjectAddress));
Oid collationOid = get_collation_oid((List *) stmt->object, missing_ok); Oid collationOid = get_collation_oid((List *) stmt->object, missing_ok);
ObjectAddress address = { 0 };
ObjectAddressSet(address, CollationRelationId, collationOid);
ObjectAddressSet(*address, CollationRelationId, collationOid);
return address; return address;
} }
@ -423,9 +433,10 @@ RenameCollationStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
* new schema. Errors if missing_ok is false and the type cannot be found in either of the * new schema. Errors if missing_ok is false and the type cannot be found in either of the
* schemas. * schemas.
*/ */
ObjectAddress * ObjectAddress
AlterCollationSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok) AlterCollationSchemaStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
List *name = (List *) stmt->object; List *name = (List *) stmt->object;
@ -445,8 +456,8 @@ AlterCollationSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_
} }
} }
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, CollationRelationId, collationOid); ObjectAddressSet(address, CollationRelationId, collationOid);
return address; return address;
} }
@ -544,31 +555,31 @@ GenerateBackupNameForCollationCollision(const ObjectAddress *address)
} }
ObjectAddress * ObjectAddress
DefineCollationStmtObjectAddress(DefineStmt *stmt, bool missing_ok) DefineCollationStmtObjectAddress(Node *node, bool missing_ok)
{ {
DefineStmt *stmt = castNode(DefineStmt, node);
Assert(stmt->kind == OBJECT_COLLATION); Assert(stmt->kind == OBJECT_COLLATION);
Oid collOid = get_collation_oid(stmt->defnames, missing_ok); Oid collOid = get_collation_oid(stmt->defnames, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(address, CollationRelationId, collOid);
ObjectAddressSet(*address, CollationRelationId, collOid);
return address; return address;
} }
/* /*
* ProcessCollationDefineStmt executed after the extension has been * PostprocessDefineCollationStmt executed after the collation has been
* created locally and before we create it on the worker nodes. * created locally and before we create it on the worker nodes.
* As we now have access to ObjectAddress of the extension that is just * As we now have access to ObjectAddress of the collation that is just
* created, we can mark it as distributed to make sure that its * created, we can mark it as distributed to make sure that its
* dependencies exist on all nodes. * dependencies exist on all nodes.
*/ */
List * List *
ProcessCollationDefineStmt(DefineStmt *stmt, const char *queryString) PostprocessDefineCollationStmt(Node *node, const char *queryString)
{ {
Assert(stmt->kind == OBJECT_COLLATION); Assert(castNode(DefineStmt, node)->kind == OBJECT_COLLATION);
if (!ShouldPropagate()) if (!ShouldPropagate())
{ {
@ -584,18 +595,13 @@ ProcessCollationDefineStmt(DefineStmt *stmt, const char *queryString)
return NIL; return NIL;
} }
ObjectAddress *collationAddress = ObjectAddress collationAddress =
DefineCollationStmtObjectAddress(stmt, false); DefineCollationStmtObjectAddress(node, false);
if (collationAddress->objectId == InvalidOid) EnsureDependenciesExistOnAllNodes(&collationAddress);
{
return NIL;
}
EnsureDependenciesExistsOnAllNodes(collationAddress); MarkObjectDistributed(&collationAddress);
MarkObjectDistributed(collationAddress);
return NodeDDLTaskList(ALL_WORKERS, CreateCollationDDLsIdempotent( return NodeDDLTaskList(ALL_WORKERS, CreateCollationDDLsIdempotent(
collationAddress->objectId)); collationAddress.objectId));
} }

View File

@ -141,7 +141,7 @@ master_create_distributed_table(PG_FUNCTION_ARGS)
* sessions creating shards. * sessions creating shards.
*/ */
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
/* /*
* Lock target relation with an exclusive lock - there's no way to make * Lock target relation with an exclusive lock - there's no way to make
@ -207,7 +207,7 @@ create_distributed_table(PG_FUNCTION_ARGS)
* sessions creating shards. * sessions creating shards.
*/ */
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
/* /*
* Lock target relation with an exclusive lock - there's no way to make * Lock target relation with an exclusive lock - there's no way to make
@ -272,7 +272,7 @@ create_reference_table(PG_FUNCTION_ARGS)
* sessions creating shards. * sessions creating shards.
*/ */
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
/* /*
* Lock target relation with an exclusive lock - there's no way to make * Lock target relation with an exclusive lock - there's no way to make

View File

@ -24,16 +24,17 @@
#include "storage/lmgr.h" #include "storage/lmgr.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
typedef bool (*AddressPredicate)(const ObjectAddress *);
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency); static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
static List * FilterObjectAddressListByPredicate(List *objectAddressList, static List * FilterObjectAddressListByPredicate(List *objectAddressList,
bool (*predicate)(const AddressPredicate predicate);
ObjectAddress *));
bool EnableDependencyCreation = true; bool EnableDependencyCreation = true;
/* /*
* EnsureDependenciesExists finds all the dependencies that we support and makes sure * EnsureDependenciesExistOnAllNodes finds all the dependencies that we support and makes
* these are available on all workers. If not available they will be created on the * sure these are available on all workers. If not available they will be created on the
* workers via a separate session that will be committed directly so that the objects are * workers via a separate session that will be committed directly so that the objects are
* visible to potentially multiple sessions creating the shards. * visible to potentially multiple sessions creating the shards.
* *
@ -47,7 +48,7 @@ bool EnableDependencyCreation = true;
* postgres native CREATE IF NOT EXISTS, or citus helper functions. * postgres native CREATE IF NOT EXISTS, or citus helper functions.
*/ */
void void
EnsureDependenciesExistsOnAllNodes(const ObjectAddress *target) EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
{ {
/* local variables to work with dependencies */ /* local variables to work with dependencies */
List *dependenciesWithCommands = NIL; List *dependenciesWithCommands = NIL;
@ -324,8 +325,7 @@ ShouldPropagateObject(const ObjectAddress *address)
* only containing the ObjectAddress *'s for which the predicate returned true. * only containing the ObjectAddress *'s for which the predicate returned true.
*/ */
static List * static List *
FilterObjectAddressListByPredicate(List *objectAddressList, FilterObjectAddressListByPredicate(List *objectAddressList, AddressPredicate predicate)
bool (*predicate)(const ObjectAddress *))
{ {
List *result = NIL; List *result = NIL;
ListCell *objectAddressListCell = NULL; ListCell *objectAddressListCell = NULL;

View File

@ -0,0 +1,752 @@
/*-------------------------------------------------------------------------
*
* distribute_object_ops.c
*
* Contains declarations for DistributeObjectOps, along with their
* lookup function, GetDistributeObjectOps.
*
* Copyright (c) Citus Data, Inc.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "distributed/commands.h"
#include "distributed/deparser.h"
static DistributeObjectOps NoDistributeOps = {
.deparse = NULL,
.qualify = NULL,
.preprocess = NULL,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Aggregate_AlterObjectSchema = {
.deparse = DeparseAlterFunctionSchemaStmt,
.qualify = QualifyAlterFunctionSchemaStmt,
.preprocess = PreprocessAlterFunctionSchemaStmt,
.postprocess = PostprocessAlterFunctionSchemaStmt,
.address = AlterFunctionSchemaStmtObjectAddress,
};
static DistributeObjectOps Aggregate_AlterOwner = {
.deparse = DeparseAlterFunctionOwnerStmt,
.qualify = QualifyAlterFunctionOwnerStmt,
.preprocess = PreprocessAlterFunctionOwnerStmt,
.postprocess = NULL,
.address = AlterFunctionOwnerObjectAddress,
};
static DistributeObjectOps Aggregate_Define = {
.deparse = NULL,
.qualify = NULL,
.preprocess = NULL,
.postprocess = NULL,
.address = DefineAggregateStmtObjectAddress,
};
static DistributeObjectOps Aggregate_Drop = {
.deparse = DeparseDropFunctionStmt,
.qualify = NULL,
.preprocess = PreprocessDropFunctionStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Aggregate_Rename = {
.deparse = DeparseRenameFunctionStmt,
.qualify = QualifyRenameFunctionStmt,
.preprocess = PreprocessRenameFunctionStmt,
.postprocess = NULL,
.address = RenameFunctionStmtObjectAddress,
};
static DistributeObjectOps Any_AlterEnum = {
.deparse = DeparseAlterEnumStmt,
.qualify = QualifyAlterEnumStmt,
.preprocess = PreprocessAlterEnumStmt,
.postprocess = PostprocessAlterEnumStmt,
.address = AlterEnumStmtObjectAddress,
};
static DistributeObjectOps Any_AlterExtension = {
.deparse = DeparseAlterExtensionStmt,
.qualify = NULL,
.preprocess = PreprocessAlterExtensionUpdateStmt,
.postprocess = NULL,
.address = AlterExtensionUpdateStmtObjectAddress,
};
static DistributeObjectOps Any_AlterExtensionContents = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterExtensionContentsStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_AlterFunction = {
.deparse = DeparseAlterFunctionStmt,
.qualify = QualifyAlterFunctionStmt,
.preprocess = PreprocessAlterFunctionStmt,
.postprocess = NULL,
.address = AlterFunctionStmtObjectAddress,
};
static DistributeObjectOps Any_AlterObjectSchema = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterTableSchemaStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_AlterPolicy = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterPolicyStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_AlterRole = {
.deparse = DeparseAlterRoleStmt,
.qualify = NULL,
.preprocess = NULL,
.postprocess = PostprocessAlterRoleStmt,
.address = NULL,
};
static DistributeObjectOps Any_AlterTableMoveAll = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterTableMoveAllStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_Cluster = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessClusterStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_CompositeType = {
.deparse = DeparseCompositeTypeStmt,
.qualify = QualifyCompositeTypeStmt,
.preprocess = PreprocessCompositeTypeStmt,
.postprocess = PostprocessCompositeTypeStmt,
.address = CompositeTypeStmtObjectAddress,
};
static DistributeObjectOps Any_CreateEnum = {
.deparse = DeparseCreateEnumStmt,
.qualify = QualifyCreateEnumStmt,
.preprocess = PreprocessCreateEnumStmt,
.postprocess = PostprocessCreateEnumStmt,
.address = CreateEnumStmtObjectAddress,
};
static DistributeObjectOps Any_CreateExtension = {
.deparse = DeparseCreateExtensionStmt,
.qualify = NULL,
.preprocess = NULL,
.postprocess = PostprocessCreateExtensionStmt,
.address = CreateExtensionStmtObjectAddress,
};
static DistributeObjectOps Any_CreateFunction = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessCreateFunctionStmt,
.postprocess = PostprocessCreateFunctionStmt,
.address = CreateFunctionStmtObjectAddress,
};
static DistributeObjectOps Any_CreatePolicy = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessCreatePolicyStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_Grant = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessGrantStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_Index = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessIndexStmt,
.postprocess = PostprocessIndexStmt,
.address = NULL,
};
static DistributeObjectOps Any_Reindex = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessReindexStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Any_Rename = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessRenameStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Attribute_Rename = {
.deparse = DeparseRenameAttributeStmt,
.qualify = QualifyRenameAttributeStmt,
.preprocess = PreprocessRenameAttributeStmt,
.postprocess = NULL,
.address = RenameAttributeStmtObjectAddress,
};
static DistributeObjectOps Collation_AlterObjectSchema = {
.deparse = DeparseAlterCollationSchemaStmt,
.qualify = QualifyAlterCollationSchemaStmt,
.preprocess = PreprocessAlterCollationSchemaStmt,
.postprocess = PostprocessAlterCollationSchemaStmt,
.address = AlterCollationSchemaStmtObjectAddress,
};
static DistributeObjectOps Collation_AlterOwner = {
.deparse = DeparseAlterCollationOwnerStmt,
.qualify = QualifyAlterCollationOwnerStmt,
.preprocess = PreprocessAlterCollationOwnerStmt,
.postprocess = NULL,
.address = AlterCollationOwnerObjectAddress,
};
static DistributeObjectOps Collation_Define = {
.deparse = NULL,
.qualify = NULL,
.preprocess = NULL,
.postprocess = PostprocessDefineCollationStmt,
.address = DefineCollationStmtObjectAddress,
};
static DistributeObjectOps Collation_Drop = {
.deparse = DeparseDropCollationStmt,
.qualify = QualifyDropCollationStmt,
.preprocess = PreprocessDropCollationStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Collation_Rename = {
.deparse = DeparseRenameCollationStmt,
.qualify = QualifyRenameCollationStmt,
.preprocess = PreprocessRenameCollationStmt,
.postprocess = NULL,
.address = RenameCollationStmtObjectAddress,
};
static DistributeObjectOps Extension_AlterObjectSchema = {
.deparse = DeparseAlterExtensionSchemaStmt,
.qualify = NULL,
.preprocess = PreprocessAlterExtensionSchemaStmt,
.postprocess = PostprocessAlterExtensionSchemaStmt,
.address = AlterExtensionSchemaStmtObjectAddress,
};
static DistributeObjectOps Extension_Drop = {
.deparse = DeparseDropExtensionStmt,
.qualify = NULL,
.preprocess = PreprocessDropExtensionStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps ForeignTable_AlterTable = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterTableStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Function_AlterObjectDepends = {
.deparse = DeparseAlterFunctionDependsStmt,
.qualify = QualifyAlterFunctionDependsStmt,
.preprocess = PreprocessAlterFunctionDependsStmt,
.postprocess = NULL,
.address = AlterFunctionDependsStmtObjectAddress,
};
static DistributeObjectOps Function_AlterObjectSchema = {
.deparse = DeparseAlterFunctionSchemaStmt,
.qualify = QualifyAlterFunctionSchemaStmt,
.preprocess = PreprocessAlterFunctionSchemaStmt,
.postprocess = PostprocessAlterFunctionSchemaStmt,
.address = AlterFunctionSchemaStmtObjectAddress,
};
static DistributeObjectOps Function_AlterOwner = {
.deparse = DeparseAlterFunctionOwnerStmt,
.qualify = QualifyAlterFunctionOwnerStmt,
.preprocess = PreprocessAlterFunctionOwnerStmt,
.postprocess = NULL,
.address = AlterFunctionOwnerObjectAddress,
};
static DistributeObjectOps Function_Drop = {
.deparse = DeparseDropFunctionStmt,
.qualify = NULL,
.preprocess = PreprocessDropFunctionStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Function_Rename = {
.deparse = DeparseRenameFunctionStmt,
.qualify = QualifyRenameFunctionStmt,
.preprocess = PreprocessRenameFunctionStmt,
.postprocess = NULL,
.address = RenameFunctionStmtObjectAddress,
};
static DistributeObjectOps Index_AlterTable = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterTableStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Index_Drop = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessDropIndexStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Policy_Drop = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessDropPolicyStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Procedure_AlterObjectDepends = {
.deparse = DeparseAlterFunctionDependsStmt,
.qualify = QualifyAlterFunctionDependsStmt,
.preprocess = PreprocessAlterFunctionDependsStmt,
.postprocess = NULL,
.address = AlterFunctionDependsStmtObjectAddress,
};
static DistributeObjectOps Procedure_AlterObjectSchema = {
.deparse = DeparseAlterFunctionSchemaStmt,
.qualify = QualifyAlterFunctionSchemaStmt,
.preprocess = PreprocessAlterFunctionSchemaStmt,
.postprocess = PostprocessAlterFunctionSchemaStmt,
.address = AlterFunctionSchemaStmtObjectAddress,
};
static DistributeObjectOps Procedure_AlterOwner = {
.deparse = DeparseAlterFunctionOwnerStmt,
.qualify = QualifyAlterFunctionOwnerStmt,
.preprocess = PreprocessAlterFunctionOwnerStmt,
.postprocess = NULL,
.address = AlterFunctionOwnerObjectAddress,
};
static DistributeObjectOps Procedure_Drop = {
.deparse = DeparseDropFunctionStmt,
.qualify = NULL,
.preprocess = PreprocessDropFunctionStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Procedure_Rename = {
.deparse = DeparseRenameFunctionStmt,
.qualify = QualifyRenameFunctionStmt,
.preprocess = PreprocessRenameFunctionStmt,
.postprocess = NULL,
.address = RenameFunctionStmtObjectAddress,
};
static DistributeObjectOps Schema_Drop = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessDropSchemaStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Table_AlterTable = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessAlterTableStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Table_Drop = {
.deparse = NULL,
.qualify = NULL,
.preprocess = PreprocessDropTableStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Type_AlterObjectSchema = {
.deparse = DeparseAlterTypeSchemaStmt,
.qualify = QualifyAlterTypeSchemaStmt,
.preprocess = PreprocessAlterTypeSchemaStmt,
.postprocess = PostprocessAlterTypeSchemaStmt,
.address = AlterTypeSchemaStmtObjectAddress,
};
static DistributeObjectOps Type_AlterOwner = {
.deparse = DeparseAlterTypeOwnerStmt,
.qualify = QualifyAlterTypeOwnerStmt,
.preprocess = PreprocessAlterTypeOwnerStmt,
.postprocess = NULL,
.address = AlterTypeOwnerObjectAddress,
};
static DistributeObjectOps Type_AlterTable = {
.deparse = DeparseAlterTypeStmt,
.qualify = QualifyAlterTypeStmt,
.preprocess = PreprocessAlterTypeStmt,
.postprocess = NULL,
.address = AlterTypeStmtObjectAddress,
};
static DistributeObjectOps Type_Drop = {
.deparse = DeparseDropTypeStmt,
.qualify = NULL,
.preprocess = PreprocessDropTypeStmt,
.postprocess = NULL,
.address = NULL,
};
static DistributeObjectOps Type_Rename = {
.deparse = DeparseRenameTypeStmt,
.qualify = QualifyRenameTypeStmt,
.preprocess = PreprocessRenameTypeStmt,
.postprocess = NULL,
.address = RenameTypeStmtObjectAddress,
};
/*
* GetDistributeObjectOps looks up the DistributeObjectOps which handles the node.
*
* Never returns NULL.
*/
const DistributeObjectOps *
GetDistributeObjectOps(Node *node)
{
switch (nodeTag(node))
{
case T_AlterEnumStmt:
{
return &Any_AlterEnum;
}
case T_AlterExtensionStmt:
{
return &Any_AlterExtension;
}
case T_AlterExtensionContentsStmt:
{
return &Any_AlterExtensionContents;
}
case T_AlterFunctionStmt:
{
return &Any_AlterFunction;
}
case T_AlterObjectDependsStmt:
{
AlterObjectDependsStmt *stmt = castNode(AlterObjectDependsStmt, node);
switch (stmt->objectType)
{
case OBJECT_FUNCTION:
{
return &Function_AlterObjectDepends;
}
case OBJECT_PROCEDURE:
{
return &Procedure_AlterObjectDepends;
}
default:
{
return &NoDistributeOps;
}
}
}
case T_AlterObjectSchemaStmt:
{
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
switch (stmt->objectType)
{
case OBJECT_AGGREGATE:
{
return &Aggregate_AlterObjectSchema;
}
case OBJECT_COLLATION:
{
return &Collation_AlterObjectSchema;
}
case OBJECT_EXTENSION:
{
return &Extension_AlterObjectSchema;
}
case OBJECT_FUNCTION:
{
return &Function_AlterObjectSchema;
}
case OBJECT_PROCEDURE:
{
return &Procedure_AlterObjectSchema;
}
case OBJECT_TYPE:
{
return &Type_AlterObjectSchema;
}
default:
{
return &Any_AlterObjectSchema;
}
}
}
case T_AlterOwnerStmt:
{
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
switch (stmt->objectType)
{
case OBJECT_AGGREGATE:
{
return &Aggregate_AlterOwner;
}
case OBJECT_COLLATION:
{
return &Collation_AlterOwner;
}
case OBJECT_FUNCTION:
{
return &Function_AlterOwner;
}
case OBJECT_PROCEDURE:
{
return &Procedure_AlterOwner;
}
case OBJECT_TYPE:
{
return &Type_AlterOwner;
}
default:
{
return &NoDistributeOps;
}
}
}
case T_AlterPolicyStmt:
{
return &Any_AlterPolicy;
}
case T_AlterRoleStmt:
{
return &Any_AlterRole;
}
case T_AlterTableStmt:
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
switch (stmt->relkind)
{
case OBJECT_TYPE:
{
return &Type_AlterTable;
}
case OBJECT_TABLE:
{
return &Table_AlterTable;
}
case OBJECT_FOREIGN_TABLE:
{
return &ForeignTable_AlterTable;
}
case OBJECT_INDEX:
{
return &Index_AlterTable;
}
default:
{
return &NoDistributeOps;
}
}
}
case T_AlterTableMoveAllStmt:
{
return &Any_AlterTableMoveAll;
}
case T_ClusterStmt:
{
return &Any_Cluster;
}
case T_CompositeTypeStmt:
{
return &Any_CompositeType;
}
case T_CreateEnumStmt:
{
return &Any_CreateEnum;
}
case T_CreateExtensionStmt:
{
return &Any_CreateExtension;
}
case T_CreateFunctionStmt:
{
return &Any_CreateFunction;
}
case T_CreatePolicyStmt:
{
return &Any_CreatePolicy;
}
case T_DefineStmt:
{
DefineStmt *stmt = castNode(DefineStmt, node);
switch (stmt->kind)
{
case OBJECT_AGGREGATE:
{
return &Aggregate_Define;
}
case OBJECT_COLLATION:
{
return &Collation_Define;
}
default:
{
return &NoDistributeOps;
}
}
}
case T_DropStmt:
{
DropStmt *stmt = castNode(DropStmt, node);
switch (stmt->removeType)
{
case OBJECT_AGGREGATE:
{
return &Aggregate_Drop;
}
case OBJECT_COLLATION:
{
return &Collation_Drop;
}
case OBJECT_EXTENSION:
{
return &Extension_Drop;
}
case OBJECT_FUNCTION:
{
return &Function_Drop;
}
case OBJECT_INDEX:
{
return &Index_Drop;
}
case OBJECT_POLICY:
{
return &Policy_Drop;
}
case OBJECT_PROCEDURE:
{
return &Procedure_Drop;
}
case OBJECT_SCHEMA:
{
return &Schema_Drop;
}
case OBJECT_TABLE:
{
return &Table_Drop;
}
case OBJECT_TYPE:
{
return &Type_Drop;
}
default:
{
return &NoDistributeOps;
}
}
}
case T_GrantStmt:
{
return &Any_Grant;
}
case T_IndexStmt:
{
return &Any_Index;
}
case T_ReindexStmt:
{
return &Any_Reindex;
}
case T_RenameStmt:
{
RenameStmt *stmt = castNode(RenameStmt, node);
switch (stmt->renameType)
{
case OBJECT_AGGREGATE:
{
return &Aggregate_Rename;
}
case OBJECT_ATTRIBUTE:
{
return &Attribute_Rename;
}
case OBJECT_COLLATION:
{
return &Collation_Rename;
}
case OBJECT_FUNCTION:
{
return &Function_Rename;
}
case OBJECT_PROCEDURE:
{
return &Procedure_Rename;
}
case OBJECT_TYPE:
{
return &Type_Rename;
}
default:
{
return &Any_Rename;
}
}
}
default:
{
return &NoDistributeOps;
}
}
}

View File

@ -115,16 +115,21 @@ ExtractNewExtensionVersion(Node *parseTree)
/* /*
* PlanCreateExtensionStmt is called during the creation of an extension. * PostprocessCreateExtensionStmt is called after the creation of an extension.
* It is executed before the statement is applied locally.
* We decide if the extension needs to be replicated to the worker, and * We decide if the extension needs to be replicated to the worker, and
* if that is the case return a list of DDLJob's that describe how and * if that is the case return a list of DDLJob's that describe how and
* where the extension needs to be created. * where the extension needs to be created.
*
* As we now have access to ObjectAddress of the extension that is just
* created, we can mark it as distributed to make sure that its
* dependencies exist on all nodes.
*/ */
List * List *
PlanCreateExtensionStmt(CreateExtensionStmt *createExtensionStmt, const char *queryString) PostprocessCreateExtensionStmt(Node *node, const char *queryString)
{ {
if (!ShouldPropagateExtensionCommand((Node *) createExtensionStmt)) CreateExtensionStmt *stmt = castNode(CreateExtensionStmt, node);
if (!ShouldPropagateExtensionCommand(node))
{ {
return NIL; return NIL;
} }
@ -161,9 +166,9 @@ PlanCreateExtensionStmt(CreateExtensionStmt *createExtensionStmt, const char *qu
* Here we append "schema" field to the "options" list (if not specified) * Here we append "schema" field to the "options" list (if not specified)
* to satisfy the schema consistency between worker nodes and the coordinator. * to satisfy the schema consistency between worker nodes and the coordinator.
*/ */
AddSchemaFieldIfMissing(createExtensionStmt); AddSchemaFieldIfMissing(stmt);
const char *createExtensionStmtSql = DeparseTreeNode((Node *) createExtensionStmt); const char *createExtensionStmtSql = DeparseTreeNode(node);
/* /*
* To prevent recursive propagation in mx architecture, we disable ddl * To prevent recursive propagation in mx architecture, we disable ddl
@ -173,6 +178,12 @@ PlanCreateExtensionStmt(CreateExtensionStmt *createExtensionStmt, const char *qu
(void *) createExtensionStmtSql, (void *) createExtensionStmtSql,
ENABLE_DDL_PROPAGATION); ENABLE_DDL_PROPAGATION);
ObjectAddress extensionAddress = GetObjectAddressFromParseTree(node, false);
EnsureDependenciesExistOnAllNodes(&extensionAddress);
MarkObjectDistributed(&extensionAddress);
return NodeDDLTaskList(ALL_WORKERS, commands); return NodeDDLTaskList(ALL_WORKERS, commands);
} }
@ -214,42 +225,7 @@ AddSchemaFieldIfMissing(CreateExtensionStmt *createExtensionStmt)
/* /*
* ProcessCreateExtensionStmt is executed after the extension has been * PreprocessDropExtensionStmt is called to drop extension(s) in coordinator and
* created locally and before we create it on the worker nodes.
* As we now have access to ObjectAddress of the extension that is just
* created, we can mark it as distributed to make sure that its
* dependencies exist on all nodes.
*/
void
ProcessCreateExtensionStmt(CreateExtensionStmt *createExtensionStmt, const
char *queryString)
{
if (!ShouldPropagateExtensionCommand((Node *) createExtensionStmt))
{
return;
}
/*
* If the extension command is a part of a bigger multi-statement transaction,
* do not propagate it
*/
if (IsMultiStatementTransaction())
{
return;
}
const ObjectAddress *extensionAddress = GetObjectAddressFromParseTree(
(Node *) createExtensionStmt, false);
EnsureDependenciesExistsOnAllNodes(extensionAddress);
MarkObjectDistributed(extensionAddress);
}
/*
* PlanDropExtensionStmt is called to drop extension(s) in coordinator and
* in worker nodes if distributed before. * in worker nodes if distributed before.
* We first ensure that we keep only the distributed ones before propagating * We first ensure that we keep only the distributed ones before propagating
* the statement to worker nodes. * the statement to worker nodes.
@ -257,19 +233,18 @@ ProcessCreateExtensionStmt(CreateExtensionStmt *createExtensionStmt, const
* be made to the workers. * be made to the workers.
*/ */
List * List *
PlanDropExtensionStmt(DropStmt *dropStmt, const char *queryString) PreprocessDropExtensionStmt(Node *node, const char *queryString)
{ {
List *allDroppedExtensions = dropStmt->objects; DropStmt *stmt = castNode(DropStmt, node);
ListCell *addressCell = NULL; ListCell *addressCell = NULL;
if (!ShouldPropagateExtensionCommand((Node *) dropStmt)) if (!ShouldPropagateExtensionCommand(node))
{ {
return NIL; return NIL;
} }
/* get distributed extensions to be dropped in worker nodes as well */ /* get distributed extensions to be dropped in worker nodes as well */
List *allDroppedExtensions = stmt->objects;
List *distributedExtensions = FilterDistributedExtensions(allDroppedExtensions); List *distributedExtensions = FilterDistributedExtensions(allDroppedExtensions);
if (list_length(distributedExtensions) <= 0) if (list_length(distributedExtensions) <= 0)
@ -311,13 +286,13 @@ PlanDropExtensionStmt(DropStmt *dropStmt, const char *queryString)
* Temporary swap the lists of objects to delete with the distributed * Temporary swap the lists of objects to delete with the distributed
* objects and deparse to an sql statement for the workers. * objects and deparse to an sql statement for the workers.
* Then switch back to allDroppedExtensions to drop all specified * Then switch back to allDroppedExtensions to drop all specified
* extensions in coordinator after PlanDropExtensionStmt completes * extensions in coordinator after PreprocessDropExtensionStmt completes
* its execution. * its execution.
*/ */
dropStmt->objects = distributedExtensions; stmt->objects = distributedExtensions;
const char *deparsedStmt = DeparseTreeNode((Node *) dropStmt); const char *deparsedStmt = DeparseTreeNode((Node *) stmt);
dropStmt->objects = allDroppedExtensions; stmt->objects = allDroppedExtensions;
/* /*
* To prevent recursive propagation in mx architecture, we disable ddl * To prevent recursive propagation in mx architecture, we disable ddl
@ -348,8 +323,6 @@ FilterDistributedExtensions(List *extensionObjectList)
{ {
char *extensionName = strVal(lfirst(objectCell)); char *extensionName = strVal(lfirst(objectCell));
ObjectAddress *address = palloc0(sizeof(ObjectAddress));
Oid extensionOid = get_extension_oid(extensionName, missingOk); Oid extensionOid = get_extension_oid(extensionName, missingOk);
if (!OidIsValid(extensionOid)) if (!OidIsValid(extensionOid))
@ -357,9 +330,10 @@ FilterDistributedExtensions(List *extensionObjectList)
continue; continue;
} }
ObjectAddressSet(*address, ExtensionRelationId, extensionOid); ObjectAddress address = { 0 };
ObjectAddressSet(address, ExtensionRelationId, extensionOid);
if (!IsObjectDistributed(address)) if (!IsObjectDistributed(&address))
{ {
continue; continue;
} }
@ -408,13 +382,12 @@ ExtensionNameListToObjectAddressList(List *extensionObjectList)
/* /*
* PlanAlterExtensionSchemaStmt is invoked for alter extension set schema statements. * PreprocessAlterExtensionSchemaStmt is invoked for alter extension set schema statements.
*/ */
List * List *
PlanAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionStmt, const PreprocessAlterExtensionSchemaStmt(Node *node, const char *queryString)
char *queryString)
{ {
if (!ShouldPropagateExtensionCommand((Node *) alterExtensionStmt)) if (!ShouldPropagateExtensionCommand(node))
{ {
return NIL; return NIL;
} }
@ -437,7 +410,7 @@ PlanAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionStmt, const
*/ */
EnsureSequentialModeForExtensionDDL(); EnsureSequentialModeForExtensionDDL();
const char *alterExtensionStmtSql = DeparseTreeNode((Node *) alterExtensionStmt); const char *alterExtensionStmtSql = DeparseTreeNode(node);
/* /*
* To prevent recursive propagation in mx architecture, we disable ddl * To prevent recursive propagation in mx architecture, we disable ddl
@ -452,34 +425,34 @@ PlanAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionStmt, const
/* /*
* ProcessAlterExtensionSchemaStmt is executed after the change has been applied * PostprocessAlterExtensionSchemaStmt is executed after the change has been applied
* locally, we can now use the new dependencies (schema) of the extension to ensure * locally, we can now use the new dependencies (schema) of the extension to ensure
* all its dependencies exist on the workers before we apply the commands remotely. * all its dependencies exist on the workers before we apply the commands remotely.
*/ */
void List *
ProcessAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionStmt, const PostprocessAlterExtensionSchemaStmt(Node *node, const char *queryString)
char *queryString)
{ {
const ObjectAddress *extensionAddress = GetObjectAddressFromParseTree( ObjectAddress extensionAddress = GetObjectAddressFromParseTree(node, false);
(Node *) alterExtensionStmt, false);
if (!ShouldPropagateExtensionCommand((Node *) alterExtensionStmt)) if (!ShouldPropagateExtensionCommand(node))
{ {
return; return NIL;
} }
/* dependencies (schema) have changed let's ensure they exist */ /* dependencies (schema) have changed let's ensure they exist */
EnsureDependenciesExistsOnAllNodes(extensionAddress); EnsureDependenciesExistOnAllNodes(&extensionAddress);
return NIL;
} }
/* /*
* PlanAlterExtensionUpdateStmt is invoked for alter extension update statements. * PreprocessAlterExtensionUpdateStmt is invoked for alter extension update statements.
*/ */
List * List *
PlanAlterExtensionUpdateStmt(AlterExtensionStmt *alterExtensionStmt, const PreprocessAlterExtensionUpdateStmt(Node *node, const char *queryString)
char *queryString)
{ {
AlterExtensionStmt *alterExtensionStmt = castNode(AlterExtensionStmt, node);
if (!ShouldPropagateExtensionCommand((Node *) alterExtensionStmt)) if (!ShouldPropagateExtensionCommand((Node *) alterExtensionStmt))
{ {
return NIL; return NIL;
@ -518,6 +491,21 @@ PlanAlterExtensionUpdateStmt(AlterExtensionStmt *alterExtensionStmt, const
} }
/*
* PreprocessAlterExtensionContentsStmt issues a notice. It does not propagate.
*/
List *
PreprocessAlterExtensionContentsStmt(Node *node, const char *queryString)
{
ereport(NOTICE, (errmsg(
"Citus does not propagate adding/dropping member objects"),
errhint(
"You can add/drop the member objects on the workers as well.")));
return NIL;
}
/* /*
* EnsureSequentialModeForExtensionDDL makes sure that the current transaction is already in * EnsureSequentialModeForExtensionDDL makes sure that the current transaction is already in
* sequential mode, or can still safely be put in sequential mode, it errors if that is * sequential mode, or can still safely be put in sequential mode, it errors if that is
@ -753,13 +741,13 @@ RecreateExtensionStmt(Oid extensionOid)
* AlterExtensionSchemaStmtObjectAddress returns the ObjectAddress of the extension that is * AlterExtensionSchemaStmtObjectAddress returns the ObjectAddress of the extension that is
* the subject of the AlterObjectSchemaStmt. Errors if missing_ok is false. * the subject of the AlterObjectSchemaStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
AlterExtensionSchemaStmtObjectAddress(AlterObjectSchemaStmt *alterExtensionSchemaStmt, AlterExtensionSchemaStmtObjectAddress(Node *node, bool missing_ok)
bool missing_ok)
{ {
Assert(alterExtensionSchemaStmt->objectType == OBJECT_EXTENSION); AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_EXTENSION);
const char *extensionName = strVal(alterExtensionSchemaStmt->object); const char *extensionName = strVal(stmt->object);
Oid extensionOid = get_extension_oid(extensionName, missing_ok); Oid extensionOid = get_extension_oid(extensionName, missing_ok);
@ -770,10 +758,10 @@ AlterExtensionSchemaStmtObjectAddress(AlterObjectSchemaStmt *alterExtensionSchem
extensionName))); extensionName)));
} }
ObjectAddress *extensionAddress = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*extensionAddress, ExtensionRelationId, extensionOid); ObjectAddressSet(address, ExtensionRelationId, extensionOid);
return extensionAddress; return address;
} }
@ -781,11 +769,11 @@ AlterExtensionSchemaStmtObjectAddress(AlterObjectSchemaStmt *alterExtensionSchem
* AlterExtensionUpdateStmtObjectAddress returns the ObjectAddress of the extension that is * AlterExtensionUpdateStmtObjectAddress returns the ObjectAddress of the extension that is
* the subject of the AlterExtensionStmt. Errors if missing_ok is false. * the subject of the AlterExtensionStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
AlterExtensionUpdateStmtObjectAddress(AlterExtensionStmt *alterExtensionStmt, AlterExtensionUpdateStmtObjectAddress(Node *node, bool missing_ok)
bool missing_ok)
{ {
const char *extensionName = alterExtensionStmt->extname; AlterExtensionStmt *stmt = castNode(AlterExtensionStmt, node);
const char *extensionName = stmt->extname;
Oid extensionOid = get_extension_oid(extensionName, missing_ok); Oid extensionOid = get_extension_oid(extensionName, missing_ok);
@ -796,8 +784,8 @@ AlterExtensionUpdateStmtObjectAddress(AlterExtensionStmt *alterExtensionStmt,
extensionName))); extensionName)));
} }
ObjectAddress *extensionAddress = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*extensionAddress, ExtensionRelationId, extensionOid); ObjectAddressSet(address, ExtensionRelationId, extensionOid);
return extensionAddress; return address;
} }

View File

@ -75,9 +75,9 @@ static void EnsureSequentialModeForFunctionDDL(void);
static void TriggerSyncMetadataToPrimaryNodes(void); static void TriggerSyncMetadataToPrimaryNodes(void);
static bool ShouldPropagateCreateFunction(CreateFunctionStmt *stmt); static bool ShouldPropagateCreateFunction(CreateFunctionStmt *stmt);
static bool ShouldPropagateAlterFunction(const ObjectAddress *address); static bool ShouldPropagateAlterFunction(const ObjectAddress *address);
static ObjectAddress * FunctionToObjectAddress(ObjectType objectType, static ObjectAddress FunctionToObjectAddress(ObjectType objectType,
ObjectWithArgs *objectWithArgs, ObjectWithArgs *objectWithArgs,
bool missing_ok); bool missing_ok);
static void ErrorIfUnsupportedAlterFunctionStmt(AlterFunctionStmt *stmt); static void ErrorIfUnsupportedAlterFunctionStmt(AlterFunctionStmt *stmt);
static void ErrorIfFunctionDependsOnExtension(const ObjectAddress *functionAddress); static void ErrorIfFunctionDependsOnExtension(const ObjectAddress *functionAddress);
static char * quote_qualified_func_name(Oid funcOid); static char * quote_qualified_func_name(Oid funcOid);
@ -155,7 +155,7 @@ create_distributed_function(PG_FUNCTION_ARGS)
*/ */
EnsureSequentialModeForFunctionDDL(); EnsureSequentialModeForFunctionDDL();
EnsureDependenciesExistsOnAllNodes(&functionAddress); EnsureDependenciesExistOnAllNodes(&functionAddress);
const char *createFunctionSQL = GetFunctionDDLCommand(funcOid, true); const char *createFunctionSQL = GetFunctionDDLCommand(funcOid, true);
const char *alterFunctionOwnerSQL = GetFunctionAlterOwnerCommand(funcOid); const char *alterFunctionOwnerSQL = GetFunctionAlterOwnerCommand(funcOid);
@ -1098,8 +1098,8 @@ ShouldPropagateCreateFunction(CreateFunctionStmt *stmt)
* Even though its a replace we should accept an non-existing function, it will just * Even though its a replace we should accept an non-existing function, it will just
* not be distributed * not be distributed
*/ */
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, true); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, true);
if (!IsObjectDistributed(address)) if (!IsObjectDistributed(&address))
{ {
/* do not propagate alter function for non-distributed functions */ /* do not propagate alter function for non-distributed functions */
return false; return false;
@ -1144,7 +1144,7 @@ ShouldPropagateAlterFunction(const ObjectAddress *address)
/* /*
* PlanCreateFunctionStmt is called during the planning phase for CREATE [OR REPLACE] * PreprocessCreateFunctionStmt is called during the planning phase for CREATE [OR REPLACE]
* FUNCTION. We primarily care for the replace variant of this statement to keep * FUNCTION. We primarily care for the replace variant of this statement to keep
* distributed functions in sync. We bail via a check on ShouldPropagateCreateFunction * distributed functions in sync. We bail via a check on ShouldPropagateCreateFunction
* which checks for the OR REPLACE modifier. * which checks for the OR REPLACE modifier.
@ -1156,8 +1156,10 @@ ShouldPropagateAlterFunction(const ObjectAddress *address)
* can propagate the function in sequential mode. * can propagate the function in sequential mode.
*/ */
List * List *
PlanCreateFunctionStmt(CreateFunctionStmt *stmt, const char *queryString) PreprocessCreateFunctionStmt(Node *node, const char *queryString)
{ {
CreateFunctionStmt *stmt = castNode(CreateFunctionStmt, node);
if (!ShouldPropagateCreateFunction(stmt)) if (!ShouldPropagateCreateFunction(stmt))
{ {
return NIL; return NIL;
@ -1176,26 +1178,28 @@ PlanCreateFunctionStmt(CreateFunctionStmt *stmt, const char *queryString)
/* /*
* ProcessCreateFunctionStmt actually creates the plan we need to execute for function * PostprocessCreateFunctionStmt actually creates the plan we need to execute for function
* propagation. This is the downside of using pg_get_functiondef to get the sql statement. * propagation. This is the downside of using pg_get_functiondef to get the sql statement.
* *
* Besides creating the plan we also make sure all (new) dependencies of the function are * Besides creating the plan we also make sure all (new) dependencies of the function are
* created on all nodes. * created on all nodes.
*/ */
List * List *
ProcessCreateFunctionStmt(CreateFunctionStmt *stmt, const char *queryString) PostprocessCreateFunctionStmt(Node *node, const char *queryString)
{ {
CreateFunctionStmt *stmt = castNode(CreateFunctionStmt, node);
if (!ShouldPropagateCreateFunction(stmt)) if (!ShouldPropagateCreateFunction(stmt))
{ {
return NIL; return NIL;
} }
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
EnsureDependenciesExistsOnAllNodes(address); EnsureDependenciesExistOnAllNodes(&address);
List *commands = list_make4(DISABLE_DDL_PROPAGATION, List *commands = list_make4(DISABLE_DDL_PROPAGATION,
GetFunctionDDLCommand(address->objectId, true), GetFunctionDDLCommand(address.objectId, true),
GetFunctionAlterOwnerCommand(address->objectId), GetFunctionAlterOwnerCommand(address.objectId),
ENABLE_DDL_PROPAGATION); ENABLE_DDL_PROPAGATION);
return NodeDDLTaskList(ALL_WORKERS, commands); return NodeDDLTaskList(ALL_WORKERS, commands);
@ -1207,9 +1211,10 @@ ProcessCreateFunctionStmt(CreateFunctionStmt *stmt, const char *queryString)
* CREATE [OR REPLACE] FUNCTION statement. If missing_ok is false it will error with the * CREATE [OR REPLACE] FUNCTION statement. If missing_ok is false it will error with the
* normal postgres error for unfound functions. * normal postgres error for unfound functions.
*/ */
ObjectAddress * ObjectAddress
CreateFunctionStmtObjectAddress(CreateFunctionStmt *stmt, bool missing_ok) CreateFunctionStmtObjectAddress(Node *node, bool missing_ok)
{ {
CreateFunctionStmt *stmt = castNode(CreateFunctionStmt, node);
ObjectType objectType = OBJECT_FUNCTION; ObjectType objectType = OBJECT_FUNCTION;
ListCell *parameterCell = NULL; ListCell *parameterCell = NULL;
@ -1236,12 +1241,12 @@ CreateFunctionStmtObjectAddress(CreateFunctionStmt *stmt, bool missing_ok)
* by the DefineStmtObjectAddress. If missing_ok is false this function throws an error if the * by the DefineStmtObjectAddress. If missing_ok is false this function throws an error if the
* aggregate does not exist. * aggregate does not exist.
* *
* Never returns NULL, but the objid in the address could be invalid if missing_ok was set * objectId in the address can be invalid if missing_ok was set to true.
* to true.
*/ */
ObjectAddress * ObjectAddress
DefineAggregateStmtObjectAddress(DefineStmt *stmt, bool missing_ok) DefineAggregateStmtObjectAddress(Node *node, bool missing_ok)
{ {
DefineStmt *stmt = castNode(DefineStmt, node);
ListCell *parameterCell = NULL; ListCell *parameterCell = NULL;
Assert(stmt->kind == OBJECT_AGGREGATE); Assert(stmt->kind == OBJECT_AGGREGATE);
@ -1260,17 +1265,18 @@ DefineAggregateStmtObjectAddress(DefineStmt *stmt, bool missing_ok)
/* /*
* PlanAlterFunctionStmt is invoked for alter function statements with actions. Here we * PreprocessAlterFunctionStmt is invoked for alter function statements with actions. Here we
* plan the jobs to be executed on the workers for functions that have been distributed in * plan the jobs to be executed on the workers for functions that have been distributed in
* the cluster. * the cluster.
*/ */
List * List *
PlanAlterFunctionStmt(AlterFunctionStmt *stmt, const char *queryString) PreprocessAlterFunctionStmt(Node *node, const char *queryString)
{ {
AlterFunctionStmt *stmt = castNode(AlterFunctionStmt, node);
AssertObjectTypeIsFunctional(stmt->objtype); AssertObjectTypeIsFunctional(stmt->objtype);
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateAlterFunction(address)) if (!ShouldPropagateAlterFunction(&address))
{ {
return NIL; return NIL;
} }
@ -1290,7 +1296,7 @@ PlanAlterFunctionStmt(AlterFunctionStmt *stmt, const char *queryString)
/* /*
* PlanRenameFunctionStmt is called when the user is renaming a function. The invocation * PreprocessRenameFunctionStmt is called when the user is renaming a function. The invocation
* happens before the statement is applied locally. * happens before the statement is applied locally.
* *
* As the function already exists we have access to the ObjectAddress, this is used to * As the function already exists we have access to the ObjectAddress, this is used to
@ -1298,12 +1304,13 @@ PlanAlterFunctionStmt(AlterFunctionStmt *stmt, const char *queryString)
* types in sync across the cluster. * types in sync across the cluster.
*/ */
List * List *
PlanRenameFunctionStmt(RenameStmt *stmt, const char *queryString) PreprocessRenameFunctionStmt(Node *node, const char *queryString)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
AssertObjectTypeIsFunctional(stmt->renameType); AssertObjectTypeIsFunctional(stmt->renameType);
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateAlterFunction(address)) if (!ShouldPropagateAlterFunction(&address))
{ {
return NIL; return NIL;
} }
@ -1322,18 +1329,19 @@ PlanRenameFunctionStmt(RenameStmt *stmt, const char *queryString)
/* /*
* PlanAlterFunctionSchemaStmt is executed before the statement is applied to the local * PreprocessAlterFunctionSchemaStmt is executed before the statement is applied to the local
* postgres instance. * postgres instance.
* *
* In this stage we can prepare the commands that need to be run on all workers. * In this stage we can prepare the commands that need to be run on all workers.
*/ */
List * List *
PlanAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PreprocessAlterFunctionSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateAlterFunction(address)) if (!ShouldPropagateAlterFunction(&address))
{ {
return NIL; return NIL;
} }
@ -1352,19 +1360,20 @@ PlanAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString
/* /*
* PlanAlterTypeOwnerStmt is called for change of owner ship of functions before the owner * PreprocessAlterTypeOwnerStmt is called for change of owner ship of functions before the owner
* ship is changed on the local instance. * ship is changed on the local instance.
* *
* If the function for which the owner is changed is distributed we execute the change on * If the function for which the owner is changed is distributed we execute the change on
* all the workers to keep the type in sync across the cluster. * all the workers to keep the type in sync across the cluster.
*/ */
List * List *
PlanAlterFunctionOwnerStmt(AlterOwnerStmt *stmt, const char *queryString) PreprocessAlterFunctionOwnerStmt(Node *node, const char *queryString)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateAlterFunction(address)) if (!ShouldPropagateAlterFunction(&address))
{ {
return NIL; return NIL;
} }
@ -1383,7 +1392,7 @@ PlanAlterFunctionOwnerStmt(AlterOwnerStmt *stmt, const char *queryString)
/* /*
* PlanDropFunctionStmt gets called during the planning phase of a DROP FUNCTION statement * PreprocessDropFunctionStmt gets called during the planning phase of a DROP FUNCTION statement
* and returns a list of DDLJob's that will drop any distributed functions from the * and returns a list of DDLJob's that will drop any distributed functions from the
* workers. * workers.
* *
@ -1392,8 +1401,9 @@ PlanAlterFunctionOwnerStmt(AlterOwnerStmt *stmt, const char *queryString)
* functions will still be dropped locally but not on the workers. * functions will still be dropped locally but not on the workers.
*/ */
List * List *
PlanDropFunctionStmt(DropStmt *stmt, const char *queryString) PreprocessDropFunctionStmt(Node *node, const char *queryString)
{ {
DropStmt *stmt = castNode(DropStmt, node);
List *deletingObjectWithArgsList = stmt->objects; List *deletingObjectWithArgsList = stmt->objects;
List *distributedObjectWithArgsList = NIL; List *distributedObjectWithArgsList = NIL;
List *distributedFunctionAddresses = NIL; List *distributedFunctionAddresses = NIL;
@ -1433,16 +1443,18 @@ PlanDropFunctionStmt(DropStmt *stmt, const char *queryString)
foreach(objectWithArgsListCell, deletingObjectWithArgsList) foreach(objectWithArgsListCell, deletingObjectWithArgsList)
{ {
ObjectWithArgs *func = castNode(ObjectWithArgs, lfirst(objectWithArgsListCell)); ObjectWithArgs *func = castNode(ObjectWithArgs, lfirst(objectWithArgsListCell));
ObjectAddress *address = FunctionToObjectAddress(stmt->removeType, func, ObjectAddress address = FunctionToObjectAddress(stmt->removeType, func,
stmt->missing_ok); stmt->missing_ok);
if (!IsObjectDistributed(address)) if (!IsObjectDistributed(&address))
{ {
continue; continue;
} }
/* collect information for all distributed functions */ /* collect information for all distributed functions */
distributedFunctionAddresses = lappend(distributedFunctionAddresses, address); ObjectAddress *addressp = palloc(sizeof(ObjectAddress));
*addressp = address;
distributedFunctionAddresses = lappend(distributedFunctionAddresses, addressp);
distributedObjectWithArgsList = lappend(distributedObjectWithArgsList, func); distributedObjectWithArgsList = lappend(distributedObjectWithArgsList, func);
} }
@ -1484,7 +1496,7 @@ PlanDropFunctionStmt(DropStmt *stmt, const char *queryString)
/* /*
* PlanAlterFunctionDependsStmt is called during the planning phase of an * PreprocessAlterFunctionDependsStmt is called during the planning phase of an
* ALTER FUNCION ... DEPENDS ON EXTENSION ... statement. Since functions depending on * ALTER FUNCION ... DEPENDS ON EXTENSION ... statement. Since functions depending on
* extensions are assumed to be Owned by an extension we assume the extension to keep the * extensions are assumed to be Owned by an extension we assume the extension to keep the
* function in sync. * function in sync.
@ -1495,8 +1507,9 @@ PlanDropFunctionStmt(DropStmt *stmt, const char *queryString)
* don't allow this dependency to be created. * don't allow this dependency to be created.
*/ */
List * List *
PlanAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt, const char *queryString) PreprocessAlterFunctionDependsStmt(Node *node, const char *queryString)
{ {
AlterObjectDependsStmt *stmt = castNode(AlterObjectDependsStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
if (creating_extension) if (creating_extension)
@ -1516,8 +1529,8 @@ PlanAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt, const char *queryStri
return NIL; return NIL;
} }
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, true); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, true);
if (!IsObjectDistributed(address)) if (!IsObjectDistributed(&address))
{ {
return NIL; return NIL;
} }
@ -1528,7 +1541,7 @@ PlanAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt, const char *queryStri
* workers * workers
*/ */
const char *functionName = getObjectIdentity(address); const char *functionName = getObjectIdentity(&address);
ereport(ERROR, (errmsg("distrtibuted functions are not allowed to depend on an " ereport(ERROR, (errmsg("distrtibuted functions are not allowed to depend on an "
"extension"), "extension"),
errdetail("Function \"%s\" is already distributed. Functions from " errdetail("Function \"%s\" is already distributed. Functions from "
@ -1542,9 +1555,10 @@ PlanAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt, const char *queryStri
* is the subject of an ALTER FUNCTION ... DEPENS ON EXTENSION ... statement. If * is the subject of an ALTER FUNCTION ... DEPENS ON EXTENSION ... statement. If
* missing_ok is set to false the lookup will raise an error. * missing_ok is set to false the lookup will raise an error.
*/ */
ObjectAddress * ObjectAddress
AlterFunctionDependsStmtObjectAddress(AlterObjectDependsStmt *stmt, bool missing_ok) AlterFunctionDependsStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterObjectDependsStmt *stmt = castNode(AlterObjectDependsStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
return FunctionToObjectAddress(stmt->objectType, return FunctionToObjectAddress(stmt->objectType,
@ -1553,23 +1567,26 @@ AlterFunctionDependsStmtObjectAddress(AlterObjectDependsStmt *stmt, bool missing
/* /*
* ProcessAlterFunctionSchemaStmt is executed after the change has been applied locally, * PostprocessAlterFunctionSchemaStmt is executed after the change has been applied locally,
* we can now use the new dependencies of the function to ensure all its dependencies * we can now use the new dependencies of the function to ensure all its dependencies
* exist on the workers before we apply the commands remotely. * exist on the workers before we apply the commands remotely.
*/ */
void List *
ProcessAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PostprocessAlterFunctionSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
const ObjectAddress *address = GetObjectAddressFromParseTree((Node *) stmt, false); ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateAlterFunction(address)) if (!ShouldPropagateAlterFunction(&address))
{ {
return; return NIL;
} }
/* dependencies have changed (schema) let's ensure they exist */ /* dependencies have changed (schema) let's ensure they exist */
EnsureDependenciesExistsOnAllNodes(address); EnsureDependenciesExistOnAllNodes(&address);
return NIL;
} }
@ -1578,9 +1595,10 @@ ProcessAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryStr
* AlterFunctionStmt. If missing_ok is set to false an error will be raised if postgres * AlterFunctionStmt. If missing_ok is set to false an error will be raised if postgres
* was unable to find the function/procedure that was the target of the statement. * was unable to find the function/procedure that was the target of the statement.
*/ */
ObjectAddress * ObjectAddress
AlterFunctionStmtObjectAddress(AlterFunctionStmt *stmt, bool missing_ok) AlterFunctionStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterFunctionStmt *stmt = castNode(AlterFunctionStmt, node);
return FunctionToObjectAddress(stmt->objtype, stmt->func, missing_ok); return FunctionToObjectAddress(stmt->objtype, stmt->func, missing_ok);
} }
@ -1589,9 +1607,10 @@ AlterFunctionStmtObjectAddress(AlterFunctionStmt *stmt, bool missing_ok)
* RenameFunctionStmtObjectAddress returns the ObjectAddress of the function that is the * RenameFunctionStmtObjectAddress returns the ObjectAddress of the function that is the
* subject of the RenameStmt. Errors if missing_ok is false. * subject of the RenameStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
RenameFunctionStmtObjectAddress(RenameStmt *stmt, bool missing_ok) RenameFunctionStmtObjectAddress(Node *node, bool missing_ok)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
return FunctionToObjectAddress(stmt->renameType, return FunctionToObjectAddress(stmt->renameType,
castNode(ObjectWithArgs, stmt->object), missing_ok); castNode(ObjectWithArgs, stmt->object), missing_ok);
} }
@ -1601,9 +1620,10 @@ RenameFunctionStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
* AlterFunctionOwnerObjectAddress returns the ObjectAddress of the function that is the * AlterFunctionOwnerObjectAddress returns the ObjectAddress of the function that is the
* subject of the AlterOwnerStmt. Errors if missing_ok is false. * subject of the AlterOwnerStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
AlterFunctionOwnerObjectAddress(AlterOwnerStmt *stmt, bool missing_ok) AlterFunctionOwnerObjectAddress(Node *node, bool missing_ok)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
return FunctionToObjectAddress(stmt->objectType, return FunctionToObjectAddress(stmt->objectType,
castNode(ObjectWithArgs, stmt->object), missing_ok); castNode(ObjectWithArgs, stmt->object), missing_ok);
} }
@ -1618,9 +1638,10 @@ AlterFunctionOwnerObjectAddress(AlterOwnerStmt *stmt, bool missing_ok)
* the new schema. Errors if missing_ok is false and the type cannot be found in either of * the new schema. Errors if missing_ok is false and the type cannot be found in either of
* the schemas. * the schemas.
*/ */
ObjectAddress * ObjectAddress
AlterFunctionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok) AlterFunctionSchemaStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
ObjectWithArgs *objectWithArgs = castNode(ObjectWithArgs, stmt->object); ObjectWithArgs *objectWithArgs = castNode(ObjectWithArgs, stmt->object);
@ -1662,8 +1683,8 @@ AlterFunctionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_o
} }
} }
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, ProcedureRelationId, funcOid); ObjectAddressSet(address, ProcedureRelationId, funcOid);
return address; return address;
} }
@ -1780,15 +1801,15 @@ ObjectWithArgsFromOid(Oid funcOid)
* false an error will be raised by postgres explaining the Function/Procedure could not * false an error will be raised by postgres explaining the Function/Procedure could not
* be found. * be found.
*/ */
static ObjectAddress * static ObjectAddress
FunctionToObjectAddress(ObjectType objectType, ObjectWithArgs *objectWithArgs, FunctionToObjectAddress(ObjectType objectType, ObjectWithArgs *objectWithArgs,
bool missing_ok) bool missing_ok)
{ {
AssertObjectTypeIsFunctional(objectType); AssertObjectTypeIsFunctional(objectType);
Oid funcOid = LookupFuncWithArgs(objectType, objectWithArgs, missing_ok); Oid funcOid = LookupFuncWithArgs(objectType, objectWithArgs, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, ProcedureRelationId, funcOid); ObjectAddressSet(address, ProcedureRelationId, funcOid);
return address; return address;
} }

View File

@ -11,9 +11,9 @@
#include "distributed/commands.h" #include "distributed/commands.h"
/* placeholder for PlanGrantStmt */ /* placeholder for PreprocessGrantStmt */
List * List *
PlanGrantStmt(GrantStmt *grantStmt) PreprocessGrantStmt(Node *node, const char *queryString)
{ {
return NIL; return NIL;
} }

View File

@ -96,7 +96,7 @@ IsIndexRenameStmt(RenameStmt *renameStmt)
/* /*
* PlanIndexStmt determines whether a given CREATE INDEX statement involves * PreprocessIndexStmt determines whether a given CREATE INDEX statement involves
* a distributed table. If so (and if the statement does not use unsupported * a distributed table. If so (and if the statement does not use unsupported
* options), it modifies the input statement to ensure proper execution against * options), it modifies the input statement to ensure proper execution against
* the master node table and creates a DDLJob to encapsulate information needed * the master node table and creates a DDLJob to encapsulate information needed
@ -104,8 +104,9 @@ IsIndexRenameStmt(RenameStmt *renameStmt)
* in a List. If no distributed table is involved, this function returns NIL. * in a List. If no distributed table is involved, this function returns NIL.
*/ */
List * List *
PlanIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand) PreprocessIndexStmt(Node *node, const char *createIndexCommand)
{ {
IndexStmt *createIndexStatement = castNode(IndexStmt, node);
List *ddlJobs = NIL; List *ddlJobs = NIL;
/* /*
@ -187,7 +188,7 @@ PlanIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand)
/* /*
* PlanReindexStmt determines whether a given REINDEX statement involves * PreprocessReindexStmt determines whether a given REINDEX statement involves
* a distributed table. If so (and if the statement does not use unsupported * a distributed table. If so (and if the statement does not use unsupported
* options), it modifies the input statement to ensure proper execution against * options), it modifies the input statement to ensure proper execution against
* the master node table and creates a DDLJob to encapsulate information needed * the master node table and creates a DDLJob to encapsulate information needed
@ -195,8 +196,9 @@ PlanIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand)
* in a List. If no distributed table is involved, this function returns NIL. * in a List. If no distributed table is involved, this function returns NIL.
*/ */
List * List *
PlanReindexStmt(ReindexStmt *reindexStatement, const char *reindexCommand) PreprocessReindexStmt(Node *node, const char *reindexCommand)
{ {
ReindexStmt *reindexStatement = castNode(ReindexStmt, node);
List *ddlJobs = NIL; List *ddlJobs = NIL;
/* /*
@ -294,7 +296,7 @@ PlanReindexStmt(ReindexStmt *reindexStatement, const char *reindexCommand)
/* /*
* PlanDropIndexStmt determines whether a given DROP INDEX statement involves * PreprocessDropIndexStmt determines whether a given DROP INDEX statement involves
* a distributed table. If so (and if the statement does not use unsupported * a distributed table. If so (and if the statement does not use unsupported
* options), it modifies the input statement to ensure proper execution against * options), it modifies the input statement to ensure proper execution against
* the master node table and creates a DDLJob to encapsulate information needed * the master node table and creates a DDLJob to encapsulate information needed
@ -302,8 +304,9 @@ PlanReindexStmt(ReindexStmt *reindexStatement, const char *reindexCommand)
* in a List. If no distributed table is involved, this function returns NIL. * in a List. If no distributed table is involved, this function returns NIL.
*/ */
List * List *
PlanDropIndexStmt(DropStmt *dropIndexStatement, const char *dropIndexCommand) PreprocessDropIndexStmt(Node *node, const char *dropIndexCommand)
{ {
DropStmt *dropIndexStatement = castNode(DropStmt, node);
List *ddlJobs = NIL; List *ddlJobs = NIL;
ListCell *dropObjectCell = NULL; ListCell *dropObjectCell = NULL;
Oid distributedIndexId = InvalidOid; Oid distributedIndexId = InvalidOid;
@ -384,24 +387,26 @@ PlanDropIndexStmt(DropStmt *dropIndexStatement, const char *dropIndexCommand)
/* /*
* PostProcessIndexStmt marks new indexes invalid if they were created using the * PostprocessIndexStmt marks new indexes invalid if they were created using the
* CONCURRENTLY flag. This (non-transactional) change provides the fallback * CONCURRENTLY flag. This (non-transactional) change provides the fallback
* state if an error is raised, otherwise a sub-sequent change to valid will be * state if an error is raised, otherwise a sub-sequent change to valid will be
* committed. * committed.
*/ */
void List *
PostProcessIndexStmt(IndexStmt *indexStmt) PostprocessIndexStmt(Node *node, const char *queryString)
{ {
IndexStmt *indexStmt = castNode(IndexStmt, node);
/* we are only processing CONCURRENT index statements */ /* we are only processing CONCURRENT index statements */
if (!indexStmt->concurrent) if (!indexStmt->concurrent)
{ {
return; return NIL;
} }
/* this logic only applies to the coordinator */ /* this logic only applies to the coordinator */
if (!IsCoordinator()) if (!IsCoordinator())
{ {
return; return NIL;
} }
/* commit the current transaction and start anew */ /* commit the current transaction and start anew */
@ -441,6 +446,8 @@ PostProcessIndexStmt(IndexStmt *indexStmt)
/* clean up; index now marked valid, but ROLLBACK will mark invalid */ /* clean up; index now marked valid, but ROLLBACK will mark invalid */
heap_freetuple(indexTuple); heap_freetuple(indexTuple);
heap_close(pg_index, RowExclusiveLock); heap_close(pg_index, RowExclusiveLock);
return NIL;
} }

View File

@ -26,10 +26,11 @@ CreatePolicyCommands(Oid relationId)
} }
/* placeholder for PlanCreatePolicyStmt */ /* placeholder for PreprocessCreatePolicyStmt */
List * List *
PlanCreatePolicyStmt(CreatePolicyStmt *stmt) PreprocessCreatePolicyStmt(Node *node, const char *queryString)
{ {
CreatePolicyStmt *stmt = castNode(CreatePolicyStmt, node);
Oid relationId = RangeVarGetRelid(stmt->table, Oid relationId = RangeVarGetRelid(stmt->table,
AccessExclusiveLock, AccessExclusiveLock,
false); false);
@ -45,9 +46,9 @@ PlanCreatePolicyStmt(CreatePolicyStmt *stmt)
} }
/* placeholder for PlanAlterPolicyStmt */ /* placeholder for PreprocessAlterPolicyStmt */
List * List *
PlanAlterPolicyStmt(AlterPolicyStmt *stmt) PreprocessAlterPolicyStmt(Node *node, const char *queryString)
{ {
/* placeholder for future implementation */ /* placeholder for future implementation */
return NIL; return NIL;
@ -76,9 +77,9 @@ ErrorIfUnsupportedPolicyExpr(Node *expr)
} }
/* placeholder for PlanDropPolicyStmt */ /* placeholder for PreprocessDropPolicyStmt */
List * List *
PlanDropPolicyStmt(DropStmt *stmt, const char *queryString) PreprocessDropPolicyStmt(Node *node, const char *queryString)
{ {
/* placeholder for future implementation */ /* placeholder for future implementation */
return NIL; return NIL;

View File

@ -19,15 +19,16 @@
/* /*
* PlanRenameStmt first determines whether a given rename statement involves * PreprocessRenameStmt first determines whether a given rename statement involves
* a distributed table. If so (and if it is supported, i.e. renames a column), * a distributed table. If so (and if it is supported, i.e. renames a column),
* it creates a DDLJob to encapsulate information needed during the worker node * it creates a DDLJob to encapsulate information needed during the worker node
* portion of DDL execution before returning that DDLJob in a List. If no dis- * portion of DDL execution before returning that DDLJob in a List. If no dis-
* tributed table is involved, this function returns NIL. * tributed table is involved, this function returns NIL.
*/ */
List * List *
PlanRenameStmt(RenameStmt *renameStmt, const char *renameCommand) PreprocessRenameStmt(Node *node, const char *renameCommand)
{ {
RenameStmt *renameStmt = castNode(RenameStmt, node);
Oid objectRelationId = InvalidOid; /* SQL Object OID */ Oid objectRelationId = InvalidOid; /* SQL Object OID */
Oid tableRelationId = InvalidOid; /* Relation OID, maybe not the same. */ Oid tableRelationId = InvalidOid; /* Relation OID, maybe not the same. */
@ -136,3 +137,30 @@ ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt)
"currently unsupported"))); "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;
}
}
}

View File

@ -38,13 +38,14 @@ static DefElem * makeDefElemInt(char *name, int value);
bool EnableAlterRolePropagation = false; bool EnableAlterRolePropagation = false;
/* /*
* ProcessAlterRoleStmt actually creates the plan we need to execute for alter * PostprocessAlterRoleStmt actually creates the plan we need to execute for alter
* role statement. We need to do it this way because we need to use the encrypted * role statement. We need to do it this way because we need to use the encrypted
* password, which is, in some cases, created at standardProcessUtility. * password, which is, in some cases, created at standardProcessUtility.
*/ */
List * List *
ProcessAlterRoleStmt(AlterRoleStmt *stmt, const char *queryString) PostprocessAlterRoleStmt(Node *node, const char *queryString)
{ {
AlterRoleStmt *stmt = castNode(AlterRoleStmt, node);
ListCell *optionCell = NULL; ListCell *optionCell = NULL;
if (!EnableAlterRolePropagation || !IsCoordinator()) if (!EnableAlterRolePropagation || !IsCoordinator())

View File

@ -31,12 +31,13 @@
/* /*
* ProcessDropSchemaStmt invalidates the foreign key cache if any table created * PreprocessDropSchemaStmt invalidates the foreign key cache if any table created
* under dropped schema involved in any foreign key relationship. * under dropped schema involved in any foreign key relationship.
*/ */
void List *
ProcessDropSchemaStmt(DropStmt *dropStatement) PreprocessDropSchemaStmt(Node *node, const char *queryString)
{ {
DropStmt *dropStatement = castNode(DropStmt, node);
Relation pgClass = NULL; Relation pgClass = NULL;
HeapTuple heapTuple = NULL; HeapTuple heapTuple = NULL;
SysScanDesc scanDescriptor = NULL; SysScanDesc scanDescriptor = NULL;
@ -48,7 +49,7 @@ ProcessDropSchemaStmt(DropStmt *dropStatement)
if (dropStatement->behavior != DROP_CASCADE) if (dropStatement->behavior != DROP_CASCADE)
{ {
return; return NIL;
} }
foreach(dropSchemaCell, dropStatement->objects) foreach(dropSchemaCell, dropStatement->objects)
@ -91,7 +92,7 @@ ProcessDropSchemaStmt(DropStmt *dropStatement)
systable_endscan(scanDescriptor); systable_endscan(scanDescriptor);
heap_close(pgClass, NoLock); heap_close(pgClass, NoLock);
return; return NIL;
} }
heapTuple = systable_getnext(scanDescriptor); heapTuple = systable_getnext(scanDescriptor);
@ -100,69 +101,21 @@ ProcessDropSchemaStmt(DropStmt *dropStatement)
systable_endscan(scanDescriptor); systable_endscan(scanDescriptor);
heap_close(pgClass, NoLock); heap_close(pgClass, NoLock);
} }
return NIL;
} }
/* /*
* PlanAlterObjectSchemaStmt is called by citus' utility hook for AlterObjectSchemaStmt * PreprocessAlterTableSchemaStmt determines whether a given ALTER ... SET SCHEMA
* parsetrees. It dispatches the statement based on the object type for which the schema
* is being altered.
*
* A (potentially empty) list of DDLJobs is being returned with the jobs on how to
* distribute the change into the cluster.
*/
List *
PlanAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
return PlanAlterTypeSchemaStmt(stmt, queryString);
}
case OBJECT_COLLATION:
{
return PlanAlterCollationSchemaStmt(stmt, queryString);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return PlanAlterFunctionSchemaStmt(stmt, queryString);
}
case OBJECT_EXTENSION:
{
return PlanAlterExtensionSchemaStmt(stmt, queryString);
}
default:
{
/* do nothing for unsupported objects */
break;
}
}
/*
* old behaviour, needs to be reconciled to the above switch statement for all
* objectType's relating to tables. Maybe it is as easy to support
* ALTER TABLE ... SET SCHEMA
*/
return PlanAlterTableSchemaStmt(stmt, queryString);
}
/*
* PlanAlterTableSchemaStmt determines whether a given ALTER ... SET SCHEMA
* statement involves a distributed table and issues a warning if so. Because * statement involves a distributed table and issues a warning if so. Because
* we do not support distributed ALTER ... SET SCHEMA, this function always * we do not support distributed ALTER ... SET SCHEMA, this function always
* returns NIL. * returns NIL.
*/ */
List * List *
PlanAlterTableSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PreprocessAlterTableSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
if (stmt->relation == NULL) if (stmt->relation == NULL)
{ {
return NIL; return NIL;
@ -186,49 +139,3 @@ PlanAlterTableSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString)
return NIL; return NIL;
} }
/*
* ProcessAlterObjectSchemaStmt is called by multi_ProcessUtility _after_ the command has
* been applied to the local postgres. It is useful to create potentially new dependencies
* of this object (the new schema) on the workers before the command gets applied to the
* remote objects.
*/
void
ProcessAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
ProcessAlterTypeSchemaStmt(stmt, queryString);
return;
}
case OBJECT_COLLATION:
{
ProcessAlterCollationSchemaStmt(stmt, queryString);
return;
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
ProcessAlterFunctionSchemaStmt(stmt, queryString);
return;
}
case OBJECT_EXTENSION:
{
ProcessAlterExtensionSchemaStmt(stmt, queryString);
return;
}
default:
{
/* do nothing for unsupported objects */
return;
}
}
}

View File

@ -52,7 +52,7 @@ static void ErrorIfUnsupportedAlterAddConstraintStmt(AlterTableStmt *alterTableS
static bool SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command); static bool SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command);
/* /*
* ProcessDropTableStmt processes DROP TABLE commands for partitioned tables. * PreprocessDropTableStmt processes DROP TABLE commands for partitioned tables.
* If we are trying to DROP partitioned tables, we first need to go to MX nodes * If we are trying to DROP partitioned tables, we first need to go to MX nodes
* and DETACH partitions from their parents. Otherwise, we process DROP command * and DETACH partitions from their parents. Otherwise, we process DROP command
* multiple times in MX workers. For shards, we send DROP commands with IF EXISTS * multiple times in MX workers. For shards, we send DROP commands with IF EXISTS
@ -61,9 +61,10 @@ static bool SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *comma
* Postgres catalogs via performDeletion function, thus we need to be cautious * Postgres catalogs via performDeletion function, thus we need to be cautious
* about not processing same DROP command twice. * about not processing same DROP command twice.
*/ */
void List *
ProcessDropTableStmt(DropStmt *dropTableStatement) PreprocessDropTableStmt(Node *node, const char *queryString)
{ {
DropStmt *dropTableStatement = castNode(DropStmt, node);
ListCell *dropTableCell = NULL; ListCell *dropTableCell = NULL;
Assert(dropTableStatement->removeType == OBJECT_TABLE); Assert(dropTableStatement->removeType == OBJECT_TABLE);
@ -114,11 +115,13 @@ ProcessDropTableStmt(DropStmt *dropTableStatement)
SendCommandToWorkersWithMetadata(detachPartitionCommand); SendCommandToWorkersWithMetadata(detachPartitionCommand);
} }
} }
return NIL;
} }
/* /*
* ProcessCreateTableStmtPartitionOf takes CreateStmt object as a parameter but * PostprocessCreateTableStmtPartitionOf takes CreateStmt object as a parameter but
* it only processes CREATE TABLE ... PARTITION OF statements and it checks if * it only processes CREATE TABLE ... PARTITION OF statements and it checks if
* user creates the table as a partition of a distributed table. In that case, * user creates the table as a partition of a distributed table. In that case,
* it distributes partition as well. Since the table itself is a partition, * it distributes partition as well. Since the table itself is a partition,
@ -128,8 +131,9 @@ ProcessDropTableStmt(DropStmt *dropTableStatement)
* This function does nothing if the provided CreateStmt is not a CREATE TABLE ... * This function does nothing if the provided CreateStmt is not a CREATE TABLE ...
* PARTITION OF command. * PARTITION OF command.
*/ */
void List *
ProcessCreateTableStmtPartitionOf(CreateStmt *createStatement) PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement, const
char *queryString)
{ {
if (createStatement->inhRelations != NIL && createStatement->partbound != NULL) if (createStatement->inhRelations != NIL && createStatement->partbound != NULL)
{ {
@ -162,11 +166,13 @@ ProcessCreateTableStmtPartitionOf(CreateStmt *createStatement)
viaDeprecatedAPI); viaDeprecatedAPI);
} }
} }
return NIL;
} }
/* /*
* ProcessAlterTableStmtAttachPartition takes AlterTableStmt object as parameter * PostprocessAlterTableStmtAttachPartition takes AlterTableStmt object as parameter
* but it only processes into ALTER TABLE ... ATTACH PARTITION commands and * but it only processes into ALTER TABLE ... ATTACH PARTITION commands and
* distributes the partition if necessary. There are four cases to consider; * distributes the partition if necessary. There are four cases to consider;
* *
@ -191,8 +197,9 @@ ProcessCreateTableStmtPartitionOf(CreateStmt *createStatement)
* This function does nothing if the provided CreateStmt is not an ALTER TABLE ... * This function does nothing if the provided CreateStmt is not an ALTER TABLE ...
* ATTACH PARTITION OF command. * ATTACH PARTITION OF command.
*/ */
void List *
ProcessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement) PostprocessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement,
const char *queryString)
{ {
List *commandList = alterTableStatement->cmds; List *commandList = alterTableStatement->cmds;
ListCell *commandCell = NULL; ListCell *commandCell = NULL;
@ -239,11 +246,13 @@ ProcessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement)
} }
} }
} }
return NIL;
} }
/* /*
* PlanAlterTableStmt determines whether a given ALTER TABLE statement involves * PreprocessAlterTableStmt determines whether a given ALTER TABLE statement involves
* a distributed table. If so (and if the statement does not use unsupported * a distributed table. If so (and if the statement does not use unsupported
* options), it modifies the input statement to ensure proper execution against * options), it modifies the input statement to ensure proper execution against
* the master node table and creates a DDLJob to encapsulate information needed * the master node table and creates a DDLJob to encapsulate information needed
@ -251,8 +260,9 @@ ProcessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement)
* in a List. If no distributed table is involved, this function returns NIL. * in a List. If no distributed table is involved, this function returns NIL.
*/ */
List * List *
PlanAlterTableStmt(AlterTableStmt *alterTableStatement, const char *alterTableCommand) PreprocessAlterTableStmt(Node *node, const char *alterTableCommand)
{ {
AlterTableStmt *alterTableStatement = castNode(AlterTableStmt, node);
Oid rightRelationId = InvalidOid; Oid rightRelationId = InvalidOid;
ListCell *commandCell = NULL; ListCell *commandCell = NULL;
bool executeSequentially = false; bool executeSequentially = false;
@ -448,6 +458,24 @@ PlanAlterTableStmt(AlterTableStmt *alterTableStatement, const char *alterTableCo
} }
/*
* PreprocessAlterTableStmt issues a warning.
* ALTER TABLE ALL IN TABLESPACE statements have their node type as
* AlterTableMoveAllStmt. At the moment we do not support this functionality in
* the distributed environment. We warn out here.
*/
List *
PreprocessAlterTableMoveAllStmt(Node *node, const char *queryString)
{
ereport(WARNING, (errmsg("not propagating ALTER TABLE ALL IN TABLESPACE "
"commands to worker nodes"),
errhint("Connect to worker nodes directly to manually "
"move all tables.")));
return NIL;
}
/* /*
* WorkerProcessAlterTableStmt checks and processes the alter table statement to be * WorkerProcessAlterTableStmt checks and processes the alter table statement to be
* worked on the distributed table of the worker node. Currently, it only processes * worked on the distributed table of the worker node. Currently, it only processes
@ -587,14 +615,14 @@ ErrorIfAlterDropsPartitionColumn(AlterTableStmt *alterTableStatement)
/* /*
* PostProcessAlterTableStmt runs after the ALTER TABLE command has already run on the * PostprocessAlterTableStmt runs after the ALTER TABLE command has already run on the
* master, so we are checking constraints over the table with constraints already defined * master, so we are checking constraints over the table with constraints already defined
* (to make the constraint check process same for ALTER TABLE and CREATE TABLE). If * (to make the constraint check process same for ALTER TABLE and CREATE TABLE). If
* constraints do not fulfill the rules we defined, they will be removed and the table * constraints do not fulfill the rules we defined, they will be removed and the table
* will return back to the state before the ALTER TABLE command. * will return back to the state before the ALTER TABLE command.
*/ */
void void
PostProcessAlterTableStmt(AlterTableStmt *alterTableStatement) PostprocessAlterTableStmt(AlterTableStmt *alterTableStatement)
{ {
List *commandList = alterTableStatement->cmds; List *commandList = alterTableStatement->cmds;
ListCell *commandCell = NULL; ListCell *commandCell = NULL;
@ -607,7 +635,7 @@ 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);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
} }
foreach(commandCell, commandList) foreach(commandCell, commandList)

View File

@ -42,12 +42,12 @@ static void AcquireDistributedLockOnRelations(List *relationIdList, LOCKMODE loc
/* /*
* ProcessTruncateStatement handles few things that should be * PostprocessTruncateStatement handles few things that should be
* done before standard process utility is called for truncate * done before standard process utility is called for truncate
* command. * command.
*/ */
void void
ProcessTruncateStatement(TruncateStmt *truncateStatement) PostprocessTruncateStatement(TruncateStmt *truncateStatement)
{ {
ErrorIfUnsupportedTruncateStmt(truncateStatement); ErrorIfUnsupportedTruncateStmt(truncateStatement);
EnsurePartitionTableNotReplicatedForTruncate(truncateStatement); EnsurePartitionTableNotReplicatedForTruncate(truncateStatement);

View File

@ -101,7 +101,7 @@ static bool ShouldPropagateTypeCreate(void);
/* /*
* PlanCompositeTypeStmt is called during the creation of a composite type. It is executed * PreprocessCompositeTypeStmt is called during the creation of a composite type. It is executed
* before the statement is applied locally. * before the statement is applied locally.
* *
* We decide if the compisite type needs to be replicated to the worker, and if that is * We decide if the compisite type needs to be replicated to the worker, and if that is
@ -112,7 +112,7 @@ static bool ShouldPropagateTypeCreate(void);
* access to the ObjectAddress of the new type. * access to the ObjectAddress of the new type.
*/ */
List * List *
PlanCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString) PreprocessCompositeTypeStmt(Node *node, const char *queryString)
{ {
if (!ShouldPropagateTypeCreate()) if (!ShouldPropagateTypeCreate())
{ {
@ -136,7 +136,7 @@ PlanCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString)
LockRelationOid(DistNodeRelationId(), RowShareLock); LockRelationOid(DistNodeRelationId(), RowShareLock);
/* fully qualify before lookup and later deparsing */ /* fully qualify before lookup and later deparsing */
QualifyTreeNode((Node *) stmt); QualifyTreeNode(node);
/* /*
* reconstruct creation statement in a portable fashion. The create_or_replace helper * reconstruct creation statement in a portable fashion. The create_or_replace helper
@ -146,7 +146,7 @@ PlanCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString)
* type previously has been attempted to be created in a transaction which did not * type previously has been attempted to be created in a transaction which did not
* commit on the coordinator. * commit on the coordinator.
*/ */
const char *compositeTypeStmtSql = DeparseCompositeTypeStmt(stmt); const char *compositeTypeStmtSql = DeparseCompositeTypeStmt(node);
compositeTypeStmtSql = WrapCreateOrReplace(compositeTypeStmtSql); compositeTypeStmtSql = WrapCreateOrReplace(compositeTypeStmtSql);
/* /*
@ -164,45 +164,46 @@ PlanCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString)
/* /*
* ProcessCompositeTypeStmt is executed after the type has been created locally and before * PostprocessCompositeTypeStmt is executed after the type has been created locally and before
* we create it on the remote servers. Here we have access to the ObjectAddress of the new * we create it on the remote servers. Here we have access to the ObjectAddress of the new
* type which we use to make sure the type's dependencies are on all nodes. * type which we use to make sure the type's dependencies are on all nodes.
*/ */
void List *
ProcessCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString) PostprocessCompositeTypeStmt(Node *node, const char *queryString)
{ {
/* same check we perform during planning of the statement */ /* same check we perform during planning of the statement */
if (!ShouldPropagateTypeCreate()) if (!ShouldPropagateTypeCreate())
{ {
return; return NIL;
} }
/* /*
* find object address of the just created object, because the type has been created * find object address of the just created object, because the type has been created
* locally it can't be missing * locally it can't be missing
*/ */
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree(node, false);
false); EnsureDependenciesExistOnAllNodes(&typeAddress);
EnsureDependenciesExistsOnAllNodes(typeAddress);
MarkObjectDistributed(typeAddress); MarkObjectDistributed(&typeAddress);
return NIL;
} }
/* /*
* PlanAlterTypeStmt is invoked for alter type statements for composite types. * PreprocessAlterTypeStmt is invoked for alter type statements for composite types.
* *
* Normally we would have a process step as well to re-ensure dependencies exists, however * Normally we would have a process step as well to re-ensure dependencies exists, however
* this is already implemented by the post processing for adding columns to tables. * this is already implemented by the post processing for adding columns to tables.
*/ */
List * List *
PlanAlterTypeStmt(AlterTableStmt *stmt, const char *queryString) PreprocessAlterTypeStmt(Node *node, const char *queryString)
{ {
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_TYPE); Assert(stmt->relkind == OBJECT_TYPE);
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return NIL; return NIL;
} }
@ -229,7 +230,7 @@ PlanAlterTypeStmt(AlterTableStmt *stmt, const char *queryString)
/* /*
* PlanCreateEnumStmt is called before the statement gets applied locally. * PreprocessCreateEnumStmt is called before the statement gets applied locally.
* *
* It decides if the create statement will be applied to the workers and if that is the * It decides if the create statement will be applied to the workers and if that is the
* case returns a list of DDLJobs that will be executed _after_ the statement has been * case returns a list of DDLJobs that will be executed _after_ the statement has been
@ -239,24 +240,21 @@ PlanAlterTypeStmt(AlterTableStmt *stmt, const char *queryString)
* ObjectAddress for the new type just yet. * ObjectAddress for the new type just yet.
*/ */
List * List *
PlanCreateEnumStmt(CreateEnumStmt *stmt, const char *queryString) PreprocessCreateEnumStmt(Node *node, const char *queryString)
{ {
if (!ShouldPropagateTypeCreate()) if (!ShouldPropagateTypeCreate())
{ {
return NIL; return NIL;
} }
/* /* managing types can only be done on the coordinator */
* managing types can only be done on the coordinator if ddl propagation is on. when
* it is off we will never get here
*/
EnsureCoordinator(); EnsureCoordinator();
/* enforce fully qualified typeName for correct deparsing and lookup */ /* enforce fully qualified typeName for correct deparsing and lookup */
QualifyTreeNode((Node *) stmt); QualifyTreeNode(node);
/* reconstruct creation statement in a portable fashion */ /* reconstruct creation statement in a portable fashion */
const char *createEnumStmtSql = DeparseCreateEnumStmt(stmt); const char *createEnumStmtSql = DeparseCreateEnumStmt(node);
createEnumStmtSql = WrapCreateOrReplace(createEnumStmtSql); createEnumStmtSql = WrapCreateOrReplace(createEnumStmtSql);
/* /*
@ -275,37 +273,38 @@ PlanCreateEnumStmt(CreateEnumStmt *stmt, const char *queryString)
/* /*
* ProcessCreateEnumStmt is called after the statement has been applied locally, but * PostprocessCreateEnumStmt is called after the statement has been applied locally, but
* before the plan on how to create the types on the workers has been executed. * before the plan on how to create the types on the workers has been executed.
* *
* We apply the same checks to verify if the type should be distributed, if that is the * We apply the same checks to verify if the type should be distributed, if that is the
* case we resolve the ObjectAddress for the just created object, distribute its * case we resolve the ObjectAddress for the just created object, distribute its
* dependencies to all the nodes, and mark the object as distributed. * dependencies to all the nodes, and mark the object as distributed.
*/ */
void List *
ProcessCreateEnumStmt(CreateEnumStmt *stmt, const char *queryString) PostprocessCreateEnumStmt(Node *node, const char *queryString)
{ {
if (!ShouldPropagateTypeCreate()) if (!ShouldPropagateTypeCreate())
{ {
return; return NIL;
} }
/* lookup type address of just created type */ /* lookup type address of just created type */
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree(node, false);
false); EnsureDependenciesExistOnAllNodes(&typeAddress);
EnsureDependenciesExistsOnAllNodes(typeAddress);
/* /*
* now that the object has been created and distributed to the workers we mark them as * now that the object has been created and distributed to the workers we mark them as
* distributed so we know to keep them up to date and recreate on a new node in the * distributed so we know to keep them up to date and recreate on a new node in the
* future * future
*/ */
MarkObjectDistributed(typeAddress); MarkObjectDistributed(&typeAddress);
return NIL;
} }
/* /*
* PlanAlterEnumStmt handles ALTER TYPE ... ADD VALUE for enum based types. Planning * PreprocessAlterEnumStmt handles ALTER TYPE ... ADD VALUE for enum based types. Planning
* happens before the statement has been applied locally. * happens before the statement has been applied locally.
* *
* Since it is an alter of an existing type we actually have the ObjectAddress. This is * Since it is an alter of an existing type we actually have the ObjectAddress. This is
@ -313,13 +312,12 @@ ProcessCreateEnumStmt(CreateEnumStmt *stmt, const char *queryString)
* workers directly to keep the types in sync accross the cluster. * workers directly to keep the types in sync accross the cluster.
*/ */
List * List *
PlanAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString) PreprocessAlterEnumStmt(Node *node, const char *queryString)
{ {
List *commands = NIL; List *commands = NIL;
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree(node, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return NIL; return NIL;
} }
@ -338,8 +336,8 @@ PlanAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString)
*/ */
EnsureCoordinator(); EnsureCoordinator();
QualifyTreeNode((Node *) stmt); QualifyTreeNode(node);
const char *alterEnumStmtSql = DeparseTreeNode((Node *) stmt); const char *alterEnumStmtSql = DeparseTreeNode(node);
/* /*
* Before pg12 ALTER ENUM ... ADD VALUE could not be within a xact block. Instead of * Before pg12 ALTER ENUM ... ADD VALUE could not be within a xact block. Instead of
@ -347,7 +345,7 @@ PlanAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString)
* we directly connect to workers and execute the commands remotely. * we directly connect to workers and execute the commands remotely.
*/ */
#if PG_VERSION_NUM < 120000 #if PG_VERSION_NUM < 120000
if (AlterEnumIsAddValue(stmt)) if (AlterEnumIsAddValue(castNode(AlterEnumStmt, node)))
{ {
/* /*
* a plan cannot be made as it will be committed via 2PC when ran through the * a plan cannot be made as it will be committed via 2PC when ran through the
@ -366,7 +364,7 @@ PlanAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString)
/* /*
* ProcessAlterEnumStmt is called after the AlterEnumStmt has been applied locally. * PostprocessAlterEnumStmt is called after the AlterEnumStmt has been applied locally.
* *
* This function is used for ALTER ENUM ... ADD VALUE for postgres versions lower than 12 * This function is used for ALTER ENUM ... ADD VALUE for postgres versions lower than 12
* to distribute the call. Before pg12 these statements could not be called in a * to distribute the call. Before pg12 these statements could not be called in a
@ -381,16 +379,9 @@ PlanAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString)
* For pg12 the statements can be called in a transaction but will only become visible * For pg12 the statements can be called in a transaction but will only become visible
* when the transaction commits. This is behaviour that is ok to perform in a 2PC. * when the transaction commits. This is behaviour that is ok to perform in a 2PC.
*/ */
void List *
ProcessAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString) PostprocessAlterEnumStmt(Node *node, const char *queryString)
{ {
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt,
false);
if (!ShouldPropagateObject(typeAddress))
{
return;
}
/* /*
* Before pg12 ALTER ENUM ... ADD VALUE could not be within a xact block. Normally we * Before pg12 ALTER ENUM ... ADD VALUE could not be within a xact block. Normally we
* would propagate the statements in a xact block to perform 2pc on changes via ddl. * would propagate the statements in a xact block to perform 2pc on changes via ddl.
@ -400,6 +391,13 @@ ProcessAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString)
* planning. * planning.
*/ */
#if PG_VERSION_NUM < 120000 #if PG_VERSION_NUM < 120000
AlterEnumStmt *stmt = castNode(AlterEnumStmt, node);
ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(&typeAddress))
{
return NIL;
}
if (AlterEnumIsAddValue(stmt)) if (AlterEnumIsAddValue(stmt))
{ {
/* /*
@ -433,17 +431,21 @@ ProcessAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString)
} }
} }
#endif #endif
return NIL;
} }
/* /*
* PlanDropTypeStmt is called for all DROP TYPE statements. For all types in the list that * PreprocessDropTypeStmt is called for all DROP TYPE statements. For all types in the list that
* citus has distributed to the workers it will drop the type on the workers as well. If * citus has distributed to the workers it will drop the type on the workers as well. If
* no types in the drop list are distributed no calls will be made to the workers. * no types in the drop list are distributed no calls will be made to the workers.
*/ */
List * List *
PlanDropTypeStmt(DropStmt *stmt, const char *queryString) PreprocessDropTypeStmt(Node *node, const char *queryString)
{ {
DropStmt *stmt = castNode(DropStmt, node);
/* /*
* We swap the list of objects to remove during deparse so we need a reference back to * We swap the list of objects to remove during deparse so we need a reference back to
* the old list to put back * the old list to put back
@ -501,7 +503,7 @@ PlanDropTypeStmt(DropStmt *stmt, const char *queryString)
/* /*
* PlanRenameTypeStmt is called when the user is renaming the type. The invocation happens * PreprocessRenameTypeStmt is called when the user is renaming the type. The invocation happens
* before the statement is applied locally. * before the statement is applied locally.
* *
* As the type already exists we have access to the ObjectAddress for the type, this is * As the type already exists we have access to the ObjectAddress for the type, this is
@ -509,20 +511,19 @@ PlanDropTypeStmt(DropStmt *stmt, const char *queryString)
* executed on all the workers to keep the types in sync across the cluster. * executed on all the workers to keep the types in sync across the cluster.
*/ */
List * List *
PlanRenameTypeStmt(RenameStmt *stmt, const char *queryString) PreprocessRenameTypeStmt(Node *node, const char *queryString)
{ {
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree(node, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return NIL; return NIL;
} }
/* fully qualify */ /* fully qualify */
QualifyTreeNode((Node *) stmt); QualifyTreeNode(node);
/* deparse sql*/ /* deparse sql*/
const char *renameStmtSql = DeparseTreeNode((Node *) stmt); const char *renameStmtSql = DeparseTreeNode(node);
EnsureSequentialModeForTypeDDL(); EnsureSequentialModeForTypeDDL();
@ -536,21 +537,21 @@ PlanRenameTypeStmt(RenameStmt *stmt, const char *queryString)
/* /*
* PlanRenameTypeAttributeStmt is called for changes of attribute names for composite * PreprocessRenameTypeAttributeStmt is called for changes of attribute names for composite
* types. Planning is called before the statement is applied locally. * types. Planning is called before the statement is applied locally.
* *
* For distributed types we apply the attribute renames directly on all the workers to * For distributed types we apply the attribute renames directly on all the workers to
* keep the type in sync across the cluster. * keep the type in sync across the cluster.
*/ */
List * List *
PlanRenameTypeAttributeStmt(RenameStmt *stmt, const char *queryString) PreprocessRenameTypeAttributeStmt(Node *node, const char *queryString)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_ATTRIBUTE); Assert(stmt->renameType == OBJECT_ATTRIBUTE);
Assert(stmt->relationType == OBJECT_TYPE); Assert(stmt->relationType == OBJECT_TYPE);
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return NIL; return NIL;
} }
@ -569,19 +570,19 @@ PlanRenameTypeAttributeStmt(RenameStmt *stmt, const char *queryString)
/* /*
* PlanAlterTypeSchemaStmt is executed before the statement is applied to the local * PreprocessAlterTypeSchemaStmt is executed before the statement is applied to the local
* postgres instance. * postgres instance.
* *
* In this stage we can prepare the commands that need to be run on all workers. * In this stage we can prepare the commands that need to be run on all workers.
*/ */
List * List *
PlanAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PreprocessAlterTypeSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return NIL; return NIL;
} }
@ -602,42 +603,44 @@ PlanAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString)
/* /*
* ProcessAlterTypeSchemaStmt is executed after the change has been applied locally, we * PostprocessAlterTypeSchemaStmt is executed after the change has been applied locally, we
* can now use the new dependencies of the type to ensure all its dependencies exist on * can now use the new dependencies of the type to ensure all its dependencies exist on
* the workers before we apply the commands remotely. * the workers before we apply the commands remotely.
*/ */
void List *
ProcessAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt, const char *queryString) PostprocessAlterTypeSchemaStmt(Node *node, const char *queryString)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return; return NIL;
} }
/* dependencies have changed (schema) let's ensure they exist */ /* dependencies have changed (schema) let's ensure they exist */
EnsureDependenciesExistsOnAllNodes(typeAddress); EnsureDependenciesExistOnAllNodes(&typeAddress);
return NIL;
} }
/* /*
* PlanAlterTypeOwnerStmt is called for change of ownership of types before the * PreprocessAlterTypeOwnerStmt is called for change of ownership of types before the
* ownership is changed on the local instance. * ownership is changed on the local instance.
* *
* If the type for which the owner is changed is distributed we execute the change on all * If the type for which the owner is changed is distributed we execute the change on all
* the workers to keep the type in sync across the cluster. * the workers to keep the type in sync across the cluster.
*/ */
List * List *
PlanAlterTypeOwnerStmt(AlterOwnerStmt *stmt, const char *queryString) PreprocessAlterTypeOwnerStmt(Node *node, const char *queryString)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
const ObjectAddress *typeAddress = GetObjectAddressFromParseTree((Node *) stmt, ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
false); if (!ShouldPropagateObject(&typeAddress))
if (!ShouldPropagateObject(typeAddress))
{ {
return NIL; return NIL;
} }
@ -815,13 +818,14 @@ EnumValsList(Oid typeOid)
* Never returns NULL, but the objid in the address could be invalid if missing_ok was set * Never returns NULL, but the objid in the address could be invalid if missing_ok was set
* to true. * to true.
*/ */
ObjectAddress * ObjectAddress
CompositeTypeStmtObjectAddress(CompositeTypeStmt *stmt, bool missing_ok) CompositeTypeStmtObjectAddress(Node *node, bool missing_ok)
{ {
CompositeTypeStmt *stmt = castNode(CompositeTypeStmt, node);
TypeName *typeName = MakeTypeNameFromRangeVar(stmt->typevar); TypeName *typeName = MakeTypeNameFromRangeVar(stmt->typevar);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -835,13 +839,14 @@ CompositeTypeStmtObjectAddress(CompositeTypeStmt *stmt, bool missing_ok)
* Never returns NULL, but the objid in the address could be invalid if missing_ok was set * Never returns NULL, but the objid in the address could be invalid if missing_ok was set
* to true. * to true.
*/ */
ObjectAddress * ObjectAddress
CreateEnumStmtObjectAddress(CreateEnumStmt *stmt, bool missing_ok) CreateEnumStmtObjectAddress(Node *node, bool missing_ok)
{ {
CreateEnumStmt *stmt = castNode(CreateEnumStmt, node);
TypeName *typeName = makeTypeNameFromNameList(stmt->typeName); TypeName *typeName = makeTypeNameFromNameList(stmt->typeName);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -855,15 +860,16 @@ CreateEnumStmtObjectAddress(CreateEnumStmt *stmt, bool missing_ok)
* Never returns NULL, but the objid in the address could be invalid if missing_ok was set * Never returns NULL, but the objid in the address could be invalid if missing_ok was set
* to true. * to true.
*/ */
ObjectAddress * ObjectAddress
AlterTypeStmtObjectAddress(AlterTableStmt *stmt, bool missing_ok) AlterTypeStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_TYPE); Assert(stmt->relkind == OBJECT_TYPE);
TypeName *typeName = MakeTypeNameFromRangeVar(stmt->relation); TypeName *typeName = MakeTypeNameFromRangeVar(stmt->relation);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -873,13 +879,14 @@ AlterTypeStmtObjectAddress(AlterTableStmt *stmt, bool missing_ok)
* AlterEnumStmtObjectAddress return the ObjectAddress of the enum type that is the * AlterEnumStmtObjectAddress return the ObjectAddress of the enum type that is the
* object of the AlterEnumStmt. Errors is missing_ok is false. * object of the AlterEnumStmt. Errors is missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
AlterEnumStmtObjectAddress(AlterEnumStmt *stmt, bool missing_ok) AlterEnumStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterEnumStmt *stmt = castNode(AlterEnumStmt, node);
TypeName *typeName = makeTypeNameFromNameList(stmt->typeName); TypeName *typeName = makeTypeNameFromNameList(stmt->typeName);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -889,15 +896,16 @@ AlterEnumStmtObjectAddress(AlterEnumStmt *stmt, bool missing_ok)
* RenameTypeStmtObjectAddress returns the ObjectAddress of the type that is the object * RenameTypeStmtObjectAddress returns the ObjectAddress of the type that is the object
* of the RenameStmt. Errors if missing_ok is false. * of the RenameStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
RenameTypeStmtObjectAddress(RenameStmt *stmt, bool missing_ok) RenameTypeStmtObjectAddress(Node *node, bool missing_ok)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_TYPE); Assert(stmt->renameType == OBJECT_TYPE);
TypeName *typeName = makeTypeNameFromNameList((List *) stmt->object); TypeName *typeName = makeTypeNameFromNameList((List *) stmt->object);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -912,9 +920,10 @@ RenameTypeStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
* new schema. Errors if missing_ok is false and the type cannot be found in either of the * new schema. Errors if missing_ok is false and the type cannot be found in either of the
* schemas. * schemas.
*/ */
ObjectAddress * ObjectAddress
AlterTypeSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok) AlterTypeSchemaStmtObjectAddress(Node *node, bool missing_ok)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
List *names = (List *) stmt->object; List *names = (List *) stmt->object;
@ -956,8 +965,8 @@ AlterTypeSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok)
} }
} }
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -971,16 +980,17 @@ AlterTypeSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok)
* changed as Attributes are not distributed on their own but as a side effect of the * changed as Attributes are not distributed on their own but as a side effect of the
* whole type distribution. * whole type distribution.
*/ */
ObjectAddress * ObjectAddress
RenameTypeAttributeStmtObjectAddress(RenameStmt *stmt, bool missing_ok) RenameTypeAttributeStmtObjectAddress(Node *node, bool missing_ok)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_ATTRIBUTE); Assert(stmt->renameType == OBJECT_ATTRIBUTE);
Assert(stmt->relationType == OBJECT_TYPE); Assert(stmt->relationType == OBJECT_TYPE);
TypeName *typeName = MakeTypeNameFromRangeVar(stmt->relation); TypeName *typeName = MakeTypeNameFromRangeVar(stmt->relation);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }
@ -990,15 +1000,16 @@ RenameTypeAttributeStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
* AlterTypeOwnerObjectAddress returns the ObjectAddress of the type that is the object * AlterTypeOwnerObjectAddress returns the ObjectAddress of the type that is the object
* of the AlterOwnerStmt. Errors if missing_ok is false. * of the AlterOwnerStmt. Errors if missing_ok is false.
*/ */
ObjectAddress * ObjectAddress
AlterTypeOwnerObjectAddress(AlterOwnerStmt *stmt, bool missing_ok) AlterTypeOwnerObjectAddress(Node *node, bool missing_ok)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
TypeName *typeName = makeTypeNameFromNameList((List *) stmt->object); TypeName *typeName = makeTypeNameFromNameList((List *) stmt->object);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok); Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); ObjectAddress address = { 0 };
ObjectAddressSet(*address, TypeRelationId, typeOid); ObjectAddressSet(address, TypeRelationId, typeOid);
return address; return address;
} }

View File

@ -4,7 +4,7 @@
* *
* The utility hook is called by PostgreSQL when processing any command * The utility hook is called by PostgreSQL when processing any command
* that is not SELECT, UPDATE, DELETE, INSERT, in place of the regular * that is not SELECT, UPDATE, DELETE, INSERT, in place of the regular
* ProcessUtility function. We use this primarily to implement (or in * PostprocessUtility function. We use this primarily to implement (or in
* some cases prevent) DDL commands and COPY on distributed tables. * some cases prevent) DDL commands and COPY on distributed tables.
* *
* For DDL commands that affect distributed tables, we check whether * For DDL commands that affect distributed tables, we check whether
@ -18,7 +18,7 @@
* on their distribution column value instead of writing it to the local * on their distribution column value instead of writing it to the local
* table on the coordinator. For COPY from a distributed table, we * table on the coordinator. For COPY from a distributed table, we
* replace the table with a SELECT * FROM table and pass it back to * replace the table with a SELECT * FROM table and pass it back to
* ProcessUtility, which will plan the query via the distributed planner * PostprocessUtility, which will plan the query via the distributed planner
* hook. * hook.
* *
* Copyright (c) Citus Data, Inc. * Copyright (c) Citus Data, Inc.
@ -41,6 +41,7 @@
#include "distributed/commands.h" #include "distributed/commands.h"
#include "distributed/commands/multi_copy.h" #include "distributed/commands/multi_copy.h"
#include "distributed/commands/utility_hook.h" /* IWYU pragma: keep */ #include "distributed/commands/utility_hook.h" /* IWYU pragma: keep */
#include "distributed/deparser.h"
#include "distributed/listutils.h" #include "distributed/listutils.h"
#include "distributed/local_executor.h" #include "distributed/local_executor.h"
#include "distributed/maintenanced.h" #include "distributed/maintenanced.h"
@ -72,11 +73,6 @@ static int activeDropSchemaOrDBs = 0;
static void ExecuteDistributedDDLJob(DDLJob *ddlJob); static void ExecuteDistributedDDLJob(DDLJob *ddlJob);
static char * SetSearchPathToCurrentSearchPathCommand(void); static char * SetSearchPathToCurrentSearchPathCommand(void);
static char * CurrentSearchPath(void); static char * CurrentSearchPath(void);
static void PostProcessUtility(Node *parsetree);
static List * PlanRenameAttributeStmt(RenameStmt *stmt, const char *queryString);
static List * PlanAlterOwnerStmt(AlterOwnerStmt *stmt, const char *queryString);
static List * PlanAlterObjectDependsStmt(AlterObjectDependsStmt *stmt,
const char *queryString);
static bool IsDropSchemaOrDB(Node *parsetree); static bool IsDropSchemaOrDB(Node *parsetree);
@ -289,7 +285,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
if (IsMultiStatementTransaction() && ShouldPropagateSetCommand(setStmt)) if (IsMultiStatementTransaction() && ShouldPropagateSetCommand(setStmt))
{ {
ProcessVariableSetStmt(setStmt, queryString); PostprocessVariableSetStmt(setStmt, queryString);
} }
} }
@ -368,245 +364,21 @@ multi_ProcessUtility(PlannedStmt *pstmt,
if (IsA(parsetree, TruncateStmt)) if (IsA(parsetree, TruncateStmt))
{ {
ProcessTruncateStatement((TruncateStmt *) parsetree); PostprocessTruncateStatement((TruncateStmt *) parsetree);
} }
/* only generate worker DDLJobs if propagation is enabled */ /* only generate worker DDLJobs if propagation is enabled */
const DistributeObjectOps *ops = NULL;
if (EnableDDLPropagation) if (EnableDDLPropagation)
{ {
/* copy planned statement since we might scribble on it or its utilityStmt */ /* copy planned statement since we might scribble on it or its utilityStmt */
pstmt = copyObject(pstmt); pstmt = copyObject(pstmt);
parsetree = pstmt->utilityStmt; parsetree = pstmt->utilityStmt;
ops = GetDistributeObjectOps(parsetree);
if (IsA(parsetree, IndexStmt)) if (ops && ops->preprocess)
{ {
ddlJobs = PlanIndexStmt((IndexStmt *) parsetree, queryString); ddlJobs = ops->preprocess(parsetree, queryString);
}
if (IsA(parsetree, ReindexStmt))
{
ddlJobs = PlanReindexStmt((ReindexStmt *) parsetree, queryString);
}
if (IsA(parsetree, DropStmt))
{
DropStmt *dropStatement = (DropStmt *) parsetree;
switch (dropStatement->removeType)
{
case OBJECT_COLLATION:
{
ddlJobs = PlanDropCollationStmt(dropStatement);
break;
}
case OBJECT_INDEX:
{
ddlJobs = PlanDropIndexStmt(dropStatement, queryString);
break;
}
case OBJECT_TABLE:
{
ProcessDropTableStmt(dropStatement);
break;
}
case OBJECT_SCHEMA:
{
ProcessDropSchemaStmt(dropStatement);
break;
}
case OBJECT_POLICY:
{
ddlJobs = PlanDropPolicyStmt(dropStatement, queryString);
break;
}
case OBJECT_TYPE:
{
ddlJobs = PlanDropTypeStmt(dropStatement, queryString);
break;
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
ddlJobs = PlanDropFunctionStmt(dropStatement, queryString);
break;
}
case OBJECT_EXTENSION:
{
ddlJobs = PlanDropExtensionStmt(dropStatement, queryString);
break;
}
default:
{
/* unsupported type, skipping*/
}
}
}
if (IsA(parsetree, AlterEnumStmt))
{
ddlJobs = PlanAlterEnumStmt(castNode(AlterEnumStmt, parsetree), queryString);
}
if (IsA(parsetree, AlterTableStmt))
{
AlterTableStmt *alterTableStmt = (AlterTableStmt *) parsetree;
if (alterTableStmt->relkind == OBJECT_TABLE ||
alterTableStmt->relkind == OBJECT_FOREIGN_TABLE ||
alterTableStmt->relkind == OBJECT_INDEX)
{
ddlJobs = PlanAlterTableStmt(alterTableStmt, queryString);
}
if (alterTableStmt->relkind == OBJECT_TYPE)
{
ddlJobs = PlanAlterTypeStmt(alterTableStmt, queryString);
}
}
/*
* ALTER ... RENAME statements have their node type as RenameStmt.
* So intercept RenameStmt to tackle these commands.
*/
if (IsA(parsetree, RenameStmt))
{
RenameStmt *renameStmt = (RenameStmt *) parsetree;
switch (renameStmt->renameType)
{
case OBJECT_COLLATION:
{
ddlJobs = PlanRenameCollationStmt(renameStmt, queryString);
break;
}
case OBJECT_TYPE:
{
ddlJobs = PlanRenameTypeStmt(renameStmt, queryString);
break;
}
case OBJECT_ATTRIBUTE:
{
ddlJobs = PlanRenameAttributeStmt(renameStmt, queryString);
break;
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
ddlJobs = PlanRenameFunctionStmt(renameStmt, queryString);
break;
}
default:
{
ddlJobs = PlanRenameStmt(renameStmt, queryString);
break;
}
}
}
/* handle distributed CLUSTER statements */
if (IsA(parsetree, ClusterStmt))
{
ddlJobs = PlanClusterStmt((ClusterStmt *) parsetree, queryString);
}
/*
* ALTER ... SET SCHEMA statements have their node type as AlterObjectSchemaStmt.
* So, we intercept AlterObjectSchemaStmt to tackle these commands.
*/
if (IsA(parsetree, AlterObjectSchemaStmt))
{
ddlJobs = PlanAlterObjectSchemaStmt(
castNode(AlterObjectSchemaStmt, parsetree), queryString);
}
if (IsA(parsetree, GrantStmt))
{
ddlJobs = PlanGrantStmt((GrantStmt *) parsetree);
}
if (IsA(parsetree, AlterOwnerStmt))
{
ddlJobs = PlanAlterOwnerStmt(castNode(AlterOwnerStmt, parsetree),
queryString);
}
if (IsA(parsetree, CreatePolicyStmt))
{
ddlJobs = PlanCreatePolicyStmt((CreatePolicyStmt *) parsetree);
}
if (IsA(parsetree, AlterPolicyStmt))
{
ddlJobs = PlanAlterPolicyStmt((AlterPolicyStmt *) parsetree);
}
if (IsA(parsetree, CompositeTypeStmt))
{
ddlJobs = PlanCompositeTypeStmt(castNode(CompositeTypeStmt, parsetree),
queryString);
}
if (IsA(parsetree, CreateEnumStmt))
{
ddlJobs = PlanCreateEnumStmt(castNode(CreateEnumStmt, parsetree),
queryString);
}
if (IsA(parsetree, AlterFunctionStmt))
{
ddlJobs = PlanAlterFunctionStmt(castNode(AlterFunctionStmt, parsetree),
queryString);
}
if (IsA(parsetree, CreateFunctionStmt))
{
ddlJobs = PlanCreateFunctionStmt(castNode(CreateFunctionStmt, parsetree),
queryString);
}
if (IsA(parsetree, AlterObjectDependsStmt))
{
ddlJobs = PlanAlterObjectDependsStmt(
castNode(AlterObjectDependsStmt, parsetree), queryString);
}
if (IsA(parsetree, AlterExtensionStmt))
{
ddlJobs = PlanAlterExtensionUpdateStmt(castNode(AlterExtensionStmt,
parsetree), queryString);
}
if (IsA(parsetree, AlterExtensionContentsStmt))
{
ereport(NOTICE, (errmsg(
"Citus does not propagate adding/dropping member objects"),
errhint(
"You can add/drop the member objects on the workers as well.")));
}
/*
* ALTER TABLE ALL IN TABLESPACE statements have their node type as
* AlterTableMoveAllStmt. At the moment we do not support this functionality in
* the distributed environment. We warn out here.
*/
if (IsA(parsetree, AlterTableMoveAllStmt))
{
ereport(WARNING, (errmsg("not propagating ALTER TABLE ALL IN TABLESPACE "
"commands to worker nodes"),
errhint("Connect to worker nodes directly to manually "
"move all tables.")));
} }
} }
else else
@ -635,9 +407,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
* the validation step should be skipped on the distributed table. * the validation step should be skipped on the distributed table.
* Therefore, we check whether the given ALTER TABLE statement is a * Therefore, we check whether the given ALTER TABLE statement is a
* FOREIGN KEY constraint and if so disable the validation step. * FOREIGN KEY constraint and if so disable the validation step.
* Note that validation is done on the shard level when DDL * Note validation is done on the shard level when DDL propagation
* propagation is enabled. Unlike the preceeding Plan* calls, the * is enabled. The following eagerly executes some tasks on workers.
* following eagerly executes some tasks on workers.
*/ */
parsetree = WorkerProcessAlterTableStmt(alterTableStmt, queryString); parsetree = WorkerProcessAlterTableStmt(alterTableStmt, queryString);
} }
@ -743,51 +514,17 @@ multi_ProcessUtility(PlannedStmt *pstmt,
*/ */
if (EnableDDLPropagation) if (EnableDDLPropagation)
{ {
if (IsA(parsetree, CompositeTypeStmt)) if (ops && ops->postprocess)
{ {
ProcessCompositeTypeStmt(castNode(CompositeTypeStmt, parsetree), queryString); List *processJobs = ops->postprocess(parsetree, queryString);
}
if (IsA(parsetree, CreateEnumStmt)) if (processJobs)
{
ProcessCreateEnumStmt(castNode(CreateEnumStmt, parsetree), queryString);
}
if (IsA(parsetree, DefineStmt))
{
DefineStmt *defineStmt = castNode(DefineStmt, parsetree);
if (defineStmt->kind == OBJECT_COLLATION)
{ {
ddlJobs = ProcessCollationDefineStmt(defineStmt, queryString); Assert(ddlJobs == NIL); /* jobs should not have been set before */
ddlJobs = processJobs;
} }
} }
if (IsA(parsetree, AlterObjectSchemaStmt))
{
ProcessAlterObjectSchemaStmt(castNode(AlterObjectSchemaStmt, parsetree),
queryString);
}
if (IsA(parsetree, AlterEnumStmt))
{
ProcessAlterEnumStmt(castNode(AlterEnumStmt, parsetree), queryString);
}
if (IsA(parsetree, CreateFunctionStmt))
{
Assert(ddlJobs == NIL); /* jobs should not have been set before */
ddlJobs = ProcessCreateFunctionStmt(castNode(CreateFunctionStmt, parsetree),
queryString);
}
if (IsA(parsetree, AlterRoleStmt))
{
Assert(ddlJobs == NIL); /* jobs should not have been set before */
ddlJobs = ProcessAlterRoleStmt(castNode(AlterRoleStmt, parsetree),
queryString);
}
if (IsA(parsetree, AlterRoleSetStmt) && EnableAlterRolePropagation) if (IsA(parsetree, AlterRoleSetStmt) && EnableAlterRolePropagation)
{ {
ereport(NOTICE, (errmsg("Citus partially supports ALTER ROLE for " ereport(NOTICE, (errmsg("Citus partially supports ALTER ROLE for "
@ -822,7 +559,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
{ {
CreateStmt *createStatement = (CreateStmt *) parsetree; CreateStmt *createStatement = (CreateStmt *) parsetree;
ProcessCreateTableStmtPartitionOf(createStatement); PostprocessCreateTableStmtPartitionOf(createStatement, queryString);
} }
/* /*
@ -833,27 +570,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
{ {
AlterTableStmt *alterTableStatement = (AlterTableStmt *) parsetree; AlterTableStmt *alterTableStatement = (AlterTableStmt *) parsetree;
ProcessAlterTableStmtAttachPartition(alterTableStatement); PostprocessAlterTableStmtAttachPartition(alterTableStatement, queryString);
}
/*
* We call PlanCreateExtensionStmt and ProcessCreateExtensionStmt after standard_ProcessUtility
* does its work to learn the schema that the extension belongs to (if statement does not include
* WITH SCHEMA clause)
*/
if (EnableDDLPropagation && IsA(parsetree, CreateExtensionStmt))
{
CreateExtensionStmt *createExtensionStmt = castNode(CreateExtensionStmt,
parsetree);
ddlJobs = PlanCreateExtensionStmt(createExtensionStmt, queryString);
ProcessCreateExtensionStmt(createExtensionStmt, queryString);
}
/* don't run post-process code for local commands */
if (ddlJobs != NIL)
{
PostProcessUtility(parsetree);
} }
/* /*
@ -869,17 +586,14 @@ multi_ProcessUtility(PlannedStmt *pstmt,
/* after local command has completed, finish by executing worker DDLJobs, if any */ /* after local command has completed, finish by executing worker DDLJobs, if any */
if (ddlJobs != NIL) if (ddlJobs != NIL)
{ {
ListCell *ddlJobCell = NULL;
if (IsA(parsetree, AlterTableStmt)) if (IsA(parsetree, AlterTableStmt))
{ {
PostProcessAlterTableStmt(castNode(AlterTableStmt, parsetree)); PostprocessAlterTableStmt(castNode(AlterTableStmt, parsetree));
} }
foreach(ddlJobCell, ddlJobs) DDLJob *ddlJob = NULL;
foreach_ptr(ddlJob, ddlJobs)
{ {
DDLJob *ddlJob = (DDLJob *) lfirst(ddlJobCell);
ExecuteDistributedDDLJob(ddlJob); ExecuteDistributedDDLJob(ddlJob);
} }
} }
@ -889,7 +603,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
{ {
VacuumStmt *vacuumStmt = (VacuumStmt *) parsetree; VacuumStmt *vacuumStmt = (VacuumStmt *) parsetree;
ProcessVacuumStmt(vacuumStmt, queryString); PostprocessVacuumStmt(vacuumStmt, queryString);
} }
/* /*
@ -918,94 +632,6 @@ IsDropSchemaOrDB(Node *parsetree)
} }
/*
* PlanRenameAttributeStmt 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
*/
static List *
PlanRenameAttributeStmt(RenameStmt *stmt, const char *queryString)
{
Assert(stmt->renameType == OBJECT_ATTRIBUTE);
switch (stmt->relationType)
{
case OBJECT_TYPE:
{
return PlanRenameTypeAttributeStmt(stmt, queryString);
}
default:
{
/* unsupported relation for attribute rename, do nothing */
return NIL;
}
}
}
/*
* PlanAlterOwnerStmt gets called for statements that change the ownership of an object.
* Based on the type of object the ownership gets changed for it dispatches to a
* specialized implementation or returns an empty list of DDLJobs for objects that do not
* have an implementation provided.
*/
static List *
PlanAlterOwnerStmt(AlterOwnerStmt *stmt, const char *queryString)
{
switch (stmt->objectType)
{
case OBJECT_COLLATION:
{
return PlanAlterCollationOwnerStmt(stmt, queryString);
}
case OBJECT_TYPE:
{
return PlanAlterTypeOwnerStmt(stmt, queryString);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return PlanAlterFunctionOwnerStmt(stmt, queryString);
}
default:
{
/* do nothing for unsupported alter owner statements */
return NIL;
}
}
}
/*
* PlanAlterObjectDependsStmt gets called during the planning phase for
* ALTER ... DEPENDS ON EXTENSION ... statements. Based on the object type we call out to
* a specialized implementation. If no implementation is available we do nothing, eg. we
* allow the local node to execute.
*/
static List *
PlanAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, const char *queryString)
{
switch (stmt->objectType)
{
case OBJECT_PROCEDURE:
case OBJECT_FUNCTION:
{
return PlanAlterFunctionDependsStmt(stmt, queryString);
}
default:
{
return NIL;
}
}
}
/* /*
* ExecuteDistributedDDLJob simply executes a provided DDLJob in a distributed trans- * ExecuteDistributedDDLJob simply executes a provided DDLJob in a distributed trans-
* action, including metadata sync if needed. If the multi shard commit protocol is * action, including metadata sync if needed. If the multi shard commit protocol is
@ -1174,20 +800,6 @@ CurrentSearchPath(void)
} }
/*
* PostProcessUtility performs additional tasks after a utility's local portion
* has been completed.
*/
static void
PostProcessUtility(Node *parsetree)
{
if (IsA(parsetree, IndexStmt))
{
PostProcessIndexStmt(castNode(IndexStmt, parsetree));
}
}
/* /*
* MarkInvalidateForeignKeyGraph marks whether the foreign key graph should be * MarkInvalidateForeignKeyGraph marks whether the foreign key graph should be
* invalidated due to a DDL. * invalidated due to a DDL.

View File

@ -49,7 +49,7 @@ static List * ExtractVacuumTargetRels(VacuumStmt *vacuumStmt);
static CitusVacuumParams VacuumStmtParams(VacuumStmt *vacstmt); static CitusVacuumParams VacuumStmtParams(VacuumStmt *vacstmt);
/* /*
* ProcessVacuumStmt processes vacuum statements that may need propagation to * PostprocessVacuumStmt processes vacuum statements that may need propagation to
* distributed tables. If a VACUUM or ANALYZE command references a distributed * distributed tables. If a VACUUM or ANALYZE command references a distributed
* table, it is propagated to all involved nodes; otherwise, this function will * table, it is propagated to all involved nodes; otherwise, this function will
* immediately exit after some error checking. * immediately exit after some error checking.
@ -59,7 +59,7 @@ static CitusVacuumParams VacuumStmtParams(VacuumStmt *vacstmt);
* ANALYZE has already been processed. * ANALYZE has already been processed.
*/ */
void void
ProcessVacuumStmt(VacuumStmt *vacuumStmt, const char *vacuumCommand) PostprocessVacuumStmt(VacuumStmt *vacuumStmt, const char *vacuumCommand)
{ {
int relationIndex = 0; int relationIndex = 0;
List *vacuumRelationList = ExtractVacuumTargetRels(vacuumStmt); List *vacuumRelationList = ExtractVacuumTargetRels(vacuumStmt);

View File

@ -110,12 +110,12 @@ IsSettingSafeToPropagate(char *name)
/* /*
* ProcessVariableSetStmt actually does the work of propagating a provided SET stmt * PostprocessVariableSetStmt actually does the work of propagating a provided SET stmt
* to currently-participating worker nodes and adding the SET command test to a string * to currently-participating worker nodes and adding the SET command test to a string
* keeping track of all propagated SET commands since (sub-)xact start. * keeping track of all propagated SET commands since (sub-)xact start.
*/ */
void void
ProcessVariableSetStmt(VariableSetStmt *setStmt, const char *setStmtString) PostprocessVariableSetStmt(VariableSetStmt *setStmt, const char *setStmtString)
{ {
dlist_iter iter; dlist_iter iter;
const bool raiseInterrupts = true; const bool raiseInterrupts = true;

View File

@ -197,8 +197,8 @@ StartNodeConnection(uint32 flags, const char *hostname, int32 port)
* See StartNodeUserDatabaseConnection for details. * See StartNodeUserDatabaseConnection for details.
*/ */
MultiConnection * MultiConnection *
GetNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port, const GetNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
char *user, const char *database) const char *user, const char *database)
{ {
MultiConnection *connection = StartNodeUserDatabaseConnection(flags, hostname, port, MultiConnection *connection = StartNodeUserDatabaseConnection(flags, hostname, port,
user, database); user, database);
@ -250,8 +250,8 @@ StartWorkerListConnections(List *workerNodeList, uint32 flags, const char *user,
* that's not desired use the Get* variant. * that's not desired use the Get* variant.
*/ */
MultiConnection * MultiConnection *
StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port, const StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
char *user, const char *database) const char *user, const char *database)
{ {
ConnectionHashKey key; ConnectionHashKey key;
MultiConnection *connection; MultiConnection *connection;

View File

@ -15,344 +15,23 @@
#include "postgres.h" #include "postgres.h"
#include "distributed/commands.h"
#include "distributed/deparser.h" #include "distributed/deparser.h"
static char * DeparseDropStmt(DropStmt *stmt);
static char * DeparseAlterTableStmt(AlterTableStmt *stmt);
static char * DeparseRenameStmt(RenameStmt *stmt);
static char * DeparseRenameAttributeStmt(RenameStmt *stmt);
static char * DeparseAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
static char * DeparseAlterOwnerStmt(AlterOwnerStmt *stmt);
static char * DeparseAlterObjectDependsStmt(AlterObjectDependsStmt *stmt);
/* /*
* DeparseTreeNode aims to be the inverse of postgres' ParseTreeNode. Currently with * DeparseTreeNode aims to be the inverse of postgres' ParseTreeNode. Currently with
* limited support. Check support before using, and add support for new statements as * limited support. Check support before using, and add support for new statements as
* required. * required.
*
* Currently supported:
* - CREATE TYPE, ALTER TYPE, DROP TYPE
* - ALTER FUNCTION, ALTER PROCEDURE, ALTER AGGREGATE
* - DROP FUNCTION, DROP PROCEDURE, DROP AGGREGATE
* - CREATE EXTENSION, ALTER EXTENSION, DROP EXTENSION
* - ALTER COLLATION, DROP COLLATION
*/ */
char * char *
DeparseTreeNode(Node *stmt) DeparseTreeNode(Node *stmt)
{ {
switch (nodeTag(stmt)) const DistributeObjectOps *ops = GetDistributeObjectOps(stmt);
if (!ops->deparse)
{ {
case T_DropStmt: ereport(ERROR, (errmsg("unsupported statement for deparsing")));
{
return DeparseDropStmt(castNode(DropStmt, stmt));
}
case T_CompositeTypeStmt:
{
return DeparseCompositeTypeStmt(castNode(CompositeTypeStmt, stmt));
}
case T_CreateEnumStmt:
{
return DeparseCreateEnumStmt(castNode(CreateEnumStmt, stmt));
}
case T_AlterTableStmt:
{
return DeparseAlterTableStmt(castNode(AlterTableStmt, stmt));
}
case T_AlterEnumStmt:
{
return DeparseAlterEnumStmt(castNode(AlterEnumStmt, stmt));
}
case T_AlterFunctionStmt:
{
return DeparseAlterFunctionStmt(castNode(AlterFunctionStmt, stmt));
}
case T_RenameStmt:
{
return DeparseRenameStmt(castNode(RenameStmt, stmt));
}
case T_AlterObjectSchemaStmt:
{
return DeparseAlterObjectSchemaStmt(castNode(AlterObjectSchemaStmt, stmt));
}
case T_AlterOwnerStmt:
{
return DeparseAlterOwnerStmt(castNode(AlterOwnerStmt, stmt));
}
case T_AlterObjectDependsStmt:
{
return DeparseAlterObjectDependsStmt(castNode(AlterObjectDependsStmt, stmt));
}
case T_AlterRoleStmt:
{
return DeparseAlterRoleStmt(castNode(AlterRoleStmt, stmt));
}
case T_CreateExtensionStmt:
{
return DeparseCreateExtensionStmt(castNode(CreateExtensionStmt, stmt));
}
case T_AlterExtensionStmt:
{
return DeparseAlterExtensionStmt(castNode(AlterExtensionStmt, stmt));
}
default:
{
ereport(ERROR, (errmsg("unsupported statement for deparsing")));
}
}
}
/*
* DeparseDropStmt aims to deparse DROP statements.
*
* Currently with limited support. Check support before using, and add support for new
* statements as required.
*/
static char *
DeparseDropStmt(DropStmt *stmt)
{
switch (stmt->removeType)
{
case OBJECT_TYPE:
{
return DeparseDropTypeStmt(stmt);
}
case OBJECT_COLLATION:
{
return DeparseDropCollationStmt(stmt);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return DeparseDropFunctionStmt(stmt);
}
case OBJECT_EXTENSION:
{
return DeparseDropExtensionStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported drop statement for deparsing")));
}
}
}
/*
* DeparseAlterTableStmt deparses an AlterTableStmt to its SQL command.
* Contrary to its name these statements are covering not only ALTER TABLE ...
* statements but are used for almost all relation-esque objects in postgres,
* including but not limited to, Tables, Types, ...
*
* Currently with limited support. Check support before using, and add support for new
* statements as required.
*/
static char *
DeparseAlterTableStmt(AlterTableStmt *stmt)
{
switch (stmt->relkind)
{
case OBJECT_TYPE:
{
return DeparseAlterTypeStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter statement for deparsing")));
}
}
}
/*
* DeparseRenameStmt deparses an RenameStmt to its SQL command.
* Contrary to its name these statements are not covering all ALTER .. RENAME
* statements.
*
* e.g. ALTER TYPE name RENAME VALUE old TO new is an AlterEnumStmt
*
* Currently with limited support. Check support before using, and add support for new
* statements as required.
*/
static char *
DeparseRenameStmt(RenameStmt *stmt)
{
switch (stmt->renameType)
{
case OBJECT_TYPE:
{
return DeparseRenameTypeStmt(stmt);
}
case OBJECT_ATTRIBUTE:
{
return DeparseRenameAttributeStmt(stmt);
}
case OBJECT_COLLATION:
{
return DeparseRenameCollationStmt(stmt);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return DeparseRenameFunctionStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported rename statement for deparsing")));
}
}
}
static char *
DeparseRenameAttributeStmt(RenameStmt *stmt)
{
Assert(stmt->renameType == OBJECT_ATTRIBUTE);
switch (stmt->relationType)
{
case OBJECT_TYPE:
{
return DeparseRenameTypeAttributeStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported rename attribute statement for"
" deparsing")));
}
}
}
/*
* DeparseAlterObjectSchemaStmt aims to deparse
* ALTER .. SET SCHEMA ..
* statements.
*
* Currently with limited support. Check support before using, and add support for new
* statements as required.
*/
static char *
DeparseAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
return DeparseAlterTypeSchemaStmt(stmt);
}
case OBJECT_COLLATION:
{
return DeparseAlterCollationSchemaStmt(stmt);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return DeparseAlterFunctionSchemaStmt(stmt);
}
case OBJECT_EXTENSION:
{
return DeparseAlterExtensionSchemaStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported rename statement for deparsing")));
}
}
}
/*
* DeparseAlterOwnerStmt aims to deparse
* ALTER .. OWNER TO ..
* statements.
*
* Currently with limited support. Check support before using, and add support for new
* statements as required.
*/
static char *
DeparseAlterOwnerStmt(AlterOwnerStmt *stmt)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
return DeparseAlterTypeOwnerStmt(stmt);
}
case OBJECT_COLLATION:
{
return DeparseAlterCollationOwnerStmt(stmt);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return DeparseAlterFunctionOwnerStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter owner statement for deparsing")));
}
}
}
/*
* DeparseAlterObjectDependsStmt aims to deparse
* ALTER .. DEPENDS ON EXTENSION ..
* statements.
*
* Currently with limited support. Check support before using, and add support for new
* statements as required.
*/
static char *
DeparseAlterObjectDependsStmt(AlterObjectDependsStmt *stmt)
{
switch (stmt->objectType)
{
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return DeparseAlterFunctionDependsStmt(stmt);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter depends statement for deparsing")));
}
} }
return ops->deparse(stmt);
} }

View File

@ -0,0 +1,33 @@
/*-------------------------------------------------------------------------
*
* deparse_attribute_stmts.c
* All routines to deparse attribute statements.
*
* Copyright (c) Citus Data, Inc.
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "distributed/deparser.h"
char *
DeparseRenameAttributeStmt(Node *node)
{
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_ATTRIBUTE);
switch (stmt->relationType)
{
case OBJECT_TYPE:
{
return DeparseRenameTypeAttributeStmt(node);
}
default:
{
ereport(ERROR, (errmsg("unsupported rename attribute statement for"
" deparsing")));
}
}
}

View File

@ -31,8 +31,9 @@ static void AppendNameList(StringInfo buf, List *objects);
* DeparseDropCollationStmt builds and returns a string representing the DropStmt * DeparseDropCollationStmt builds and returns a string representing the DropStmt
*/ */
char * char *
DeparseDropCollationStmt(DropStmt *stmt) DeparseDropCollationStmt(Node *node)
{ {
DropStmt *stmt = castNode(DropStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -67,8 +68,9 @@ AppendDropCollationStmt(StringInfo buf, DropStmt *stmt)
* DeparseRenameCollationStmt builds and returns a string representing the RenameStmt * DeparseRenameCollationStmt builds and returns a string representing the RenameStmt
*/ */
char * char *
DeparseRenameCollationStmt(RenameStmt *stmt) DeparseRenameCollationStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -88,8 +90,8 @@ AppendRenameCollationStmt(StringInfo buf, RenameStmt *stmt)
{ {
List *names = (List *) stmt->object; List *names = (List *) stmt->object;
appendStringInfo(buf, "ALTER COLLATION %s RENAME TO %s;", NameListToQuotedString( appendStringInfo(buf, "ALTER COLLATION %s RENAME TO %s;",
names), NameListToQuotedString(names),
quote_identifier(stmt->newname)); quote_identifier(stmt->newname));
} }
@ -98,8 +100,9 @@ AppendRenameCollationStmt(StringInfo buf, RenameStmt *stmt)
* DeparseAlterCollationSchemaStmt builds and returns a string representing the AlterObjectSchemaStmt * DeparseAlterCollationSchemaStmt builds and returns a string representing the AlterObjectSchemaStmt
*/ */
char * char *
DeparseAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt) DeparseAlterCollationSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -130,8 +133,9 @@ AppendAlterCollationSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
* DeparseAlterCollationOwnerStmt builds and returns a string representing the AlterOwnerStmt * DeparseAlterCollationOwnerStmt builds and returns a string representing the AlterOwnerStmt
*/ */
char * char *
DeparseAlterCollationOwnerStmt(AlterOwnerStmt *stmt) DeparseAlterCollationOwnerStmt(Node *node)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);

View File

@ -68,12 +68,13 @@ GetExtensionOption(List *extensionOptions, const char *defname)
* CreateExtensionStmt to be sent to worker nodes. * CreateExtensionStmt to be sent to worker nodes.
*/ */
char * char *
DeparseCreateExtensionStmt(CreateExtensionStmt *createExtensionStmt) DeparseCreateExtensionStmt(Node *node)
{ {
CreateExtensionStmt *stmt = castNode(CreateExtensionStmt, node);
StringInfoData sql = { 0 }; StringInfoData sql = { 0 };
initStringInfo(&sql); initStringInfo(&sql);
AppendCreateExtensionStmt(&sql, createExtensionStmt); AppendCreateExtensionStmt(&sql, stmt);
return sql.data; return sql.data;
} }
@ -141,12 +142,13 @@ AppendCreateExtensionStmt(StringInfo buf, CreateExtensionStmt *createExtensionSt
* AlterExtensionStmt to be sent to worker nodes. * AlterExtensionStmt to be sent to worker nodes.
*/ */
char * char *
DeparseAlterExtensionStmt(AlterExtensionStmt *alterExtensionStmt) DeparseAlterExtensionStmt(Node *node)
{ {
AlterExtensionStmt *stmt = castNode(AlterExtensionStmt, node);
StringInfoData sql = { 0 }; StringInfoData sql = { 0 };
initStringInfo(&sql); initStringInfo(&sql);
AppendAlterExtensionStmt(&sql, alterExtensionStmt); AppendAlterExtensionStmt(&sql, stmt);
return sql.data; return sql.data;
} }
@ -184,12 +186,13 @@ AppendAlterExtensionStmt(StringInfo buf, AlterExtensionStmt *alterExtensionStmt)
* DeparseDropExtensionStmt builds and returns a string representing the DropStmt * DeparseDropExtensionStmt builds and returns a string representing the DropStmt
*/ */
char * char *
DeparseDropExtensionStmt(DropStmt *dropStmt) DeparseDropExtensionStmt(Node *node)
{ {
DropStmt *stmt = castNode(DropStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
AppendDropExtensionStmt(&str, dropStmt); AppendDropExtensionStmt(&str, stmt);
return str.data; return str.data;
} }
@ -252,14 +255,15 @@ AppendExtensionNameList(StringInfo str, List *objects)
* AlterObjectSchemaStmt (ALTER EXTENSION SET SCHEMA). * AlterObjectSchemaStmt (ALTER EXTENSION SET SCHEMA).
*/ */
char * char *
DeparseAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionSchemaStmt) DeparseAlterExtensionSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
Assert(alterExtensionSchemaStmt->objectType == OBJECT_EXTENSION); Assert(stmt->objectType == OBJECT_EXTENSION);
AppendAlterExtensionSchemaStmt(&str, alterExtensionSchemaStmt); AppendAlterExtensionSchemaStmt(&str, stmt);
return str.data; return str.data;
} }

View File

@ -71,8 +71,9 @@ static char * CopyAndConvertToUpperCase(const char *str);
* DeparseAlterFunctionStmt builds and returns a string representing the AlterFunctionStmt * DeparseAlterFunctionStmt builds and returns a string representing the AlterFunctionStmt
*/ */
char * char *
DeparseAlterFunctionStmt(AlterFunctionStmt *stmt) DeparseAlterFunctionStmt(Node *node)
{ {
AlterFunctionStmt *stmt = castNode(AlterFunctionStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -427,8 +428,9 @@ AppendVarSetValue(StringInfo buf, VariableSetStmt *setStmt)
* DeparseRenameFunctionStmt builds and returns a string representing the RenameStmt * DeparseRenameFunctionStmt builds and returns a string representing the RenameStmt
*/ */
char * char *
DeparseRenameFunctionStmt(RenameStmt *stmt) DeparseRenameFunctionStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -458,8 +460,9 @@ AppendRenameFunctionStmt(StringInfo buf, RenameStmt *stmt)
* DeparseAlterFunctionSchemaStmt builds and returns a string representing the AlterObjectSchemaStmt * DeparseAlterFunctionSchemaStmt builds and returns a string representing the AlterObjectSchemaStmt
*/ */
char * char *
DeparseAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt) DeparseAlterFunctionSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -489,8 +492,9 @@ AppendAlterFunctionSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
* DeparseAlterFunctionOwnerStmt builds and returns a string representing the AlterOwnerStmt * DeparseAlterFunctionOwnerStmt builds and returns a string representing the AlterOwnerStmt
*/ */
char * char *
DeparseAlterFunctionOwnerStmt(AlterOwnerStmt *stmt) DeparseAlterFunctionOwnerStmt(Node *node)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -520,8 +524,9 @@ AppendAlterFunctionOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt)
* DeparseAlterFunctionDependsStmt builds and returns a string representing the AlterObjectDependsStmt * DeparseAlterFunctionDependsStmt builds and returns a string representing the AlterObjectDependsStmt
*/ */
char * char *
DeparseAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt) DeparseAlterFunctionDependsStmt(Node *node)
{ {
AlterObjectDependsStmt *stmt = castNode(AlterObjectDependsStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -551,8 +556,9 @@ AppendAlterFunctionDependsStmt(StringInfo buf, AlterObjectDependsStmt *stmt)
* DeparseDropFunctionStmt builds and returns a string representing the DropStmt * DeparseDropFunctionStmt builds and returns a string representing the DropStmt
*/ */
char * char *
DeparseDropFunctionStmt(DropStmt *stmt) DeparseDropFunctionStmt(Node *node)
{ {
DropStmt *stmt = castNode(DropStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);

View File

@ -27,8 +27,9 @@ static void AppendAlterRoleStmt(StringInfo buf, AlterRoleStmt *stmt);
* AlterRoleStmt for application on a remote server. * AlterRoleStmt for application on a remote server.
*/ */
char * char *
DeparseAlterRoleStmt(AlterRoleStmt *stmt) DeparseAlterRoleStmt(Node *node)
{ {
AlterRoleStmt *stmt = castNode(AlterRoleStmt, node);
StringInfoData buf = { 0 }; StringInfoData buf = { 0 };
initStringInfo(&buf); initStringInfo(&buf);

View File

@ -62,8 +62,9 @@ static void AppendAlterTypeOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt);
* CompositeTypeStmt for application on a remote server. * CompositeTypeStmt for application on a remote server.
*/ */
char * char *
DeparseCompositeTypeStmt(CompositeTypeStmt *stmt) DeparseCompositeTypeStmt(Node *node)
{ {
CompositeTypeStmt *stmt = castNode(CompositeTypeStmt, node);
StringInfoData sql = { 0 }; StringInfoData sql = { 0 };
initStringInfo(&sql); initStringInfo(&sql);
@ -74,8 +75,9 @@ DeparseCompositeTypeStmt(CompositeTypeStmt *stmt)
char * char *
DeparseCreateEnumStmt(CreateEnumStmt *stmt) DeparseCreateEnumStmt(Node *node)
{ {
CreateEnumStmt *stmt = castNode(CreateEnumStmt, node);
StringInfoData sql = { 0 }; StringInfoData sql = { 0 };
initStringInfo(&sql); initStringInfo(&sql);
@ -86,8 +88,9 @@ DeparseCreateEnumStmt(CreateEnumStmt *stmt)
char * char *
DeparseAlterEnumStmt(AlterEnumStmt *stmt) DeparseAlterEnumStmt(Node *node)
{ {
AlterEnumStmt *stmt = castNode(AlterEnumStmt, node);
StringInfoData sql = { 0 }; StringInfoData sql = { 0 };
initStringInfo(&sql); initStringInfo(&sql);
@ -98,8 +101,9 @@ DeparseAlterEnumStmt(AlterEnumStmt *stmt)
char * char *
DeparseDropTypeStmt(DropStmt *stmt) DeparseDropTypeStmt(Node *node)
{ {
DropStmt *stmt = castNode(DropStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -112,8 +116,9 @@ DeparseDropTypeStmt(DropStmt *stmt)
char * char *
DeparseAlterTypeStmt(AlterTableStmt *stmt) DeparseAlterTypeStmt(Node *node)
{ {
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -395,8 +400,9 @@ AppendColumnDef(StringInfo str, ColumnDef *columnDef)
char * char *
DeparseRenameTypeStmt(RenameStmt *stmt) DeparseRenameTypeStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -419,8 +425,9 @@ AppendRenameTypeStmt(StringInfo buf, RenameStmt *stmt)
char * char *
DeparseRenameTypeAttributeStmt(RenameStmt *stmt) DeparseRenameTypeAttributeStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -452,8 +459,9 @@ AppendRenameTypeAttributeStmt(StringInfo buf, RenameStmt *stmt)
char * char *
DeparseAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt) DeparseAlterTypeSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);
@ -477,8 +485,9 @@ AppendAlterTypeSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
char * char *
DeparseAlterTypeOwnerStmt(AlterOwnerStmt *stmt) DeparseAlterTypeOwnerStmt(Node *node)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
StringInfoData str = { 0 }; StringInfoData str = { 0 };
initStringInfo(&str); initStringInfo(&str);

View File

@ -18,241 +18,36 @@
#include "catalog/objectaddress.h" #include "catalog/objectaddress.h"
#include "catalog/pg_extension_d.h" #include "catalog/pg_extension_d.h"
static ObjectAddress * AlterTableStmtObjectAddress(AlterTableStmt *stmt, bool missing_ok);
static ObjectAddress * RenameStmtObjectAddress(RenameStmt *stmt, bool missing_ok);
static ObjectAddress * AlterObjectSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt,
bool missing_ok);
static ObjectAddress * RenameAttributeStmtObjectAddress(RenameStmt *stmt, bool
missing_ok);
static ObjectAddress * AlterOwnerStmtObjectAddress(AlterOwnerStmt *stmt, bool missing_ok);
static ObjectAddress * AlterObjectDependsStmtObjectAddress(AlterObjectDependsStmt *stmt,
bool missing_ok);
static ObjectAddress * CreateExtensionStmtObjectAddress(CreateExtensionStmt *stmt, bool
missing_ok);
static ObjectAddress * AlterExtensionStmtObjectAddress(
AlterExtensionStmt *alterExtensionStmt, bool missing_ok);
/* /*
* GetObjectAddressFromParseTree returns the ObjectAddress of the main target of the parse * GetObjectAddressFromParseTree returns the ObjectAddress of the main target of the parse
* tree. * tree.
*/ */
ObjectAddress * ObjectAddress
GetObjectAddressFromParseTree(Node *parseTree, bool missing_ok) GetObjectAddressFromParseTree(Node *parseTree, bool missing_ok)
{ {
switch (parseTree->type) const DistributeObjectOps *ops = GetDistributeObjectOps(parseTree);
if (!ops->address)
{ {
case T_CompositeTypeStmt: ereport(ERROR, (errmsg("unsupported statement to get object address for")));
{
return CompositeTypeStmtObjectAddress(castNode(CompositeTypeStmt, parseTree),
missing_ok);
}
case T_AlterTableStmt:
{
return AlterTableStmtObjectAddress(castNode(AlterTableStmt, parseTree),
missing_ok);
}
case T_CreateEnumStmt:
{
return CreateEnumStmtObjectAddress(castNode(CreateEnumStmt, parseTree),
missing_ok);
}
case T_AlterEnumStmt:
{
return AlterEnumStmtObjectAddress(castNode(AlterEnumStmt, parseTree),
missing_ok);
}
case T_RenameStmt:
{
return RenameStmtObjectAddress(castNode(RenameStmt, parseTree), missing_ok);
}
case T_AlterObjectSchemaStmt:
{
return AlterObjectSchemaStmtObjectAddress(castNode(AlterObjectSchemaStmt,
parseTree), missing_ok);
}
case T_AlterOwnerStmt:
{
return AlterOwnerStmtObjectAddress(castNode(AlterOwnerStmt, parseTree),
missing_ok);
}
case T_AlterFunctionStmt:
{
return AlterFunctionStmtObjectAddress(castNode(AlterFunctionStmt, parseTree),
missing_ok);
}
case T_CreateFunctionStmt:
{
return CreateFunctionStmtObjectAddress(
castNode(CreateFunctionStmt, parseTree), missing_ok);
}
case T_AlterObjectDependsStmt:
{
return AlterObjectDependsStmtObjectAddress(
castNode(AlterObjectDependsStmt, parseTree), missing_ok);
}
case T_DefineStmt:
{
DefineStmt *stmt = castNode(DefineStmt, parseTree);
switch (stmt->kind)
{
case OBJECT_AGGREGATE:
{
return DefineAggregateStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_COLLATION:
{
return DefineCollationStmtObjectAddress(stmt, missing_ok);
}
default:
{
break;
}
}
ereport(ERROR, (errmsg(
"unsupported object type to get object address for DefineStmt")));
return NULL;
}
case T_CreateExtensionStmt:
{
return CreateExtensionStmtObjectAddress(castNode(CreateExtensionStmt,
parseTree), missing_ok);
}
case T_AlterExtensionStmt:
{
return AlterExtensionStmtObjectAddress(castNode(AlterExtensionStmt,
parseTree), missing_ok);
}
default:
{
/*
* should not be reached, indicates the coordinator is sending unsupported
* statements
*/
ereport(ERROR, (errmsg("unsupported statement to get object address for")));
return NULL;
}
} }
return ops->address(parseTree, missing_ok);
} }
static ObjectAddress * ObjectAddress
AlterTableStmtObjectAddress(AlterTableStmt *stmt, bool missing_ok) RenameAttributeStmtObjectAddress(Node *node, bool missing_ok)
{
switch (stmt->relkind)
{
case OBJECT_TYPE:
{
return AlterTypeStmtObjectAddress(stmt, missing_ok);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter statement to get object address for"
)));
}
}
}
static ObjectAddress *
RenameStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
{
switch (stmt->renameType)
{
case OBJECT_TYPE:
{
return RenameTypeStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_ATTRIBUTE:
{
return RenameAttributeStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_COLLATION:
{
return RenameCollationStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return RenameFunctionStmtObjectAddress(stmt, missing_ok);
}
default:
{
ereport(ERROR, (errmsg("unsupported rename statement to get object address "
"for")));
}
}
}
static ObjectAddress *
AlterObjectSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
return AlterTypeSchemaStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_COLLATION:
{
return AlterCollationSchemaStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return AlterFunctionSchemaStmtObjectAddress(stmt, missing_ok);
}
case OBJECT_EXTENSION:
{
return AlterExtensionSchemaStmtObjectAddress(stmt, missing_ok);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter schema statement to get object "
"address for")));
}
}
}
static ObjectAddress *
RenameAttributeStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_ATTRIBUTE); Assert(stmt->renameType == OBJECT_ATTRIBUTE);
switch (stmt->relationType) switch (stmt->relationType)
{ {
case OBJECT_TYPE: case OBJECT_TYPE:
{ {
return RenameTypeAttributeStmtObjectAddress(stmt, missing_ok); return RenameTypeAttributeStmtObjectAddress(node, missing_ok);
} }
default: default:
@ -264,69 +59,6 @@ RenameAttributeStmtObjectAddress(RenameStmt *stmt, bool missing_ok)
} }
static ObjectAddress *
AlterOwnerStmtObjectAddress(AlterOwnerStmt *stmt, bool missing_ok)
{
switch (stmt->objectType)
{
case OBJECT_COLLATION:
{
ObjectAddress *address = palloc(sizeof(ObjectAddress));
*address = AlterCollationOwnerObjectAddress(stmt);
return address;
}
case OBJECT_TYPE:
{
return AlterTypeOwnerObjectAddress(stmt, missing_ok);
}
case OBJECT_PROCEDURE:
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
{
return AlterFunctionOwnerObjectAddress(stmt, missing_ok);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter owner statement to get object "
"address for")));
}
}
}
/*
* AlterObjectDependsStmtObjectAddress resolves the ObjectAddress for the object targeted
* by the AlterObjectDependStmt. This is done by dispatching the call to the object
* specific implementation based on the ObjectType captured in the original statement. If
* a specific implementation is not present an error will be raised. This is a developer
* error since this function should only be reachable by calls of supported types.
*
* If missing_ok is set to fails the object specific implementation is supposed to raise
* an error explaining the user the object is not existing.
*/
static ObjectAddress *
AlterObjectDependsStmtObjectAddress(AlterObjectDependsStmt *stmt, bool missing_ok)
{
switch (stmt->objectType)
{
case OBJECT_PROCEDURE:
case OBJECT_FUNCTION:
{
return AlterFunctionDependsStmtObjectAddress(stmt, missing_ok);
}
default:
{
ereport(ERROR, (errmsg("unsupported alter depends on extension statement to "
"get object address for")));
}
}
}
/* /*
* CreateExtensionStmtObjectAddress finds the ObjectAddress for the extension described * CreateExtensionStmtObjectAddress finds the ObjectAddress for the extension described
* by the CreateExtensionStmt. If missing_ok is false, then this function throws an * by the CreateExtensionStmt. If missing_ok is false, then this function throws an
@ -335,13 +67,13 @@ AlterObjectDependsStmtObjectAddress(AlterObjectDependsStmt *stmt, bool missing_o
* Never returns NULL, but the objid in the address could be invalid if missing_ok was set * Never returns NULL, but the objid in the address could be invalid if missing_ok was set
* to true. * to true.
*/ */
static ObjectAddress * ObjectAddress
CreateExtensionStmtObjectAddress(CreateExtensionStmt *createExtensionStmt, bool CreateExtensionStmtObjectAddress(Node *node, bool missing_ok)
missing_ok)
{ {
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); CreateExtensionStmt *stmt = castNode(CreateExtensionStmt, node);
ObjectAddress address = { 0 };
const char *extensionName = createExtensionStmt->extname; const char *extensionName = stmt->extname;
Oid extensionoid = get_extension_oid(extensionName, missing_ok); Oid extensionoid = get_extension_oid(extensionName, missing_ok);
@ -353,7 +85,7 @@ CreateExtensionStmtObjectAddress(CreateExtensionStmt *createExtensionStmt, bool
extensionName))); extensionName)));
} }
ObjectAddressSet(*address, ExtensionRelationId, extensionoid); ObjectAddressSet(address, ExtensionRelationId, extensionoid);
return address; return address;
} }
@ -367,13 +99,13 @@ CreateExtensionStmtObjectAddress(CreateExtensionStmt *createExtensionStmt, bool
* Never returns NULL, but the objid in the address could be invalid if missing_ok was set * Never returns NULL, but the objid in the address could be invalid if missing_ok was set
* to true. * to true.
*/ */
static ObjectAddress * ObjectAddress
AlterExtensionStmtObjectAddress(AlterExtensionStmt *alterExtensionStmt, bool AlterExtensionStmtObjectAddress(Node *node, bool missing_ok)
missing_ok)
{ {
ObjectAddress *address = palloc0(sizeof(ObjectAddress)); AlterExtensionStmt *stmt = castNode(AlterExtensionStmt, node);
ObjectAddress address = { 0 };
const char *extensionName = alterExtensionStmt->extname; const char *extensionName = stmt->extname;
Oid extensionoid = get_extension_oid(extensionName, missing_ok); Oid extensionoid = get_extension_oid(extensionName, missing_ok);
@ -385,7 +117,7 @@ AlterExtensionStmtObjectAddress(AlterExtensionStmt *alterExtensionStmt, bool
extensionName))); extensionName)));
} }
ObjectAddressSet(*address, ExtensionRelationId, extensionoid); ObjectAddressSet(address, ExtensionRelationId, extensionoid);
return address; return address;
} }

View File

@ -21,17 +21,10 @@
#include "postgres.h" #include "postgres.h"
#include "distributed/commands.h"
#include "distributed/deparser.h" #include "distributed/deparser.h"
static void QualifyRenameStmt(RenameStmt *stmt);
static void QualifyRenameAttributeStmt(RenameStmt *stmt);
static void QualifyAlterTableStmt(AlterTableStmt *stmt);
static void QualifyAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
static void QualifyAlterOwnerStmt(AlterOwnerStmt *stmt);
static void QualifyAlterObjectDependsStmt(AlterObjectDependsStmt *stmt);
static void QualifyDropObjectStmt(DropStmt *stmt);
/* /*
* QualifyTreeNode transforms the statement in place and makes all (supported) statements * QualifyTreeNode transforms the statement in place and makes all (supported) statements
* fully qualified. Fully qualified statements allow for application on a remote postgres * fully qualified. Fully qualified statements allow for application on a remote postgres
@ -40,117 +33,11 @@ static void QualifyDropObjectStmt(DropStmt *stmt);
void void
QualifyTreeNode(Node *stmt) QualifyTreeNode(Node *stmt)
{ {
switch (nodeTag(stmt)) const DistributeObjectOps *ops = GetDistributeObjectOps(stmt);
if (ops && ops->qualify)
{ {
case T_RenameStmt: ops->qualify(stmt);
{
QualifyRenameStmt(castNode(RenameStmt, stmt));
return;
}
case T_AlterEnumStmt:
{
QualifyAlterEnumStmt(castNode(AlterEnumStmt, stmt));
return;
}
case T_AlterTableStmt:
{
QualifyAlterTableStmt(castNode(AlterTableStmt, stmt));
return;
}
case T_CompositeTypeStmt:
{
QualifyCompositeTypeStmt(castNode(CompositeTypeStmt, stmt));
return;
}
case T_CreateEnumStmt:
{
QualifyCreateEnumStmt(castNode(CreateEnumStmt, stmt));
return;
}
case T_AlterObjectSchemaStmt:
{
QualifyAlterObjectSchemaStmt(castNode(AlterObjectSchemaStmt, stmt));
return;
}
case T_AlterOwnerStmt:
{
QualifyAlterOwnerStmt(castNode(AlterOwnerStmt, stmt));
return;
}
case T_AlterFunctionStmt:
{
QualifyAlterFunctionStmt(castNode(AlterFunctionStmt, stmt));
return;
}
case T_AlterObjectDependsStmt:
{
QualifyAlterObjectDependsStmt(castNode(AlterObjectDependsStmt, stmt));
return;
}
case T_DropStmt:
{
QualifyDropObjectStmt(castNode(DropStmt, stmt));
break;
}
default:
{
/* skip unsupported statements */
break;
}
}
}
/*
* QualifyRenameStmt transforms a RENAME statement in place and makes all (supported)
* statements fully qualified.
*/
static void
QualifyRenameStmt(RenameStmt *stmt)
{
switch (stmt->renameType)
{
case OBJECT_TYPE:
{
QualifyRenameTypeStmt(stmt);
return;
}
case OBJECT_ATTRIBUTE:
{
QualifyRenameAttributeStmt(stmt);
return;
}
case OBJECT_COLLATION:
{
QualifyRenameCollationStmt(stmt);
return;
}
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
{
QualifyRenameFunctionStmt(stmt);
return;
}
default:
{
/* skip unsupported statements */
break;
}
} }
} }
@ -159,142 +46,17 @@ QualifyRenameStmt(RenameStmt *stmt)
* QualifyRenameAttributeStmt transforms a RENAME ATTRIBUTE statement in place and makes all (supported) * QualifyRenameAttributeStmt transforms a RENAME ATTRIBUTE statement in place and makes all (supported)
* statements fully qualified. * statements fully qualified.
*/ */
static void void
QualifyRenameAttributeStmt(RenameStmt *stmt) QualifyRenameAttributeStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_ATTRIBUTE); Assert(stmt->renameType == OBJECT_ATTRIBUTE);
switch (stmt->relationType) switch (stmt->relationType)
{ {
case OBJECT_TYPE: case OBJECT_TYPE:
{ {
QualifyRenameTypeAttributeStmt(stmt); QualifyRenameTypeAttributeStmt(node);
return;
}
default:
{
return;
}
}
}
static void
QualifyAlterTableStmt(AlterTableStmt *stmt)
{
switch (stmt->relkind)
{
case OBJECT_TYPE:
{
QualifyAlterTypeStmt(stmt);
return;
}
default:
{
/* skip unsupported statements */
break;
}
}
}
static void
QualifyAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
QualifyAlterTypeSchemaStmt(stmt);
return;
}
case OBJECT_COLLATION:
{
QualifyAlterCollationSchemaStmt(stmt);
return;
}
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
{
QualifyAlterFunctionSchemaStmt(stmt);
return;
}
default:
{
/* skip unsupported statements */
break;
}
}
}
static void
QualifyAlterOwnerStmt(AlterOwnerStmt *stmt)
{
switch (stmt->objectType)
{
case OBJECT_TYPE:
{
QualifyAlterTypeOwnerStmt(stmt);
return;
}
case OBJECT_COLLATION:
{
QualifyAlterCollationOwnerStmt(stmt);
return;
}
case OBJECT_AGGREGATE:
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
{
QualifyAlterFunctionOwnerStmt(stmt);
return;
}
default:
{
return;
}
}
}
static void
QualifyAlterObjectDependsStmt(AlterObjectDependsStmt *stmt)
{
switch (stmt->objectType)
{
case OBJECT_FUNCTION:
case OBJECT_PROCEDURE:
{
QualifyAlterFunctionDependsStmt(stmt);
return;
}
default:
{
return;
}
}
}
static void
QualifyDropObjectStmt(DropStmt *stmt)
{
switch (stmt->removeType)
{
case OBJECT_COLLATION:
{
QualifyDropCollationStmt(stmt);
return; return;
} }

View File

@ -32,8 +32,9 @@ static Node * QualifyCollationName(List *func);
* statement in place and makes the collation name fully qualified. * statement in place and makes the collation name fully qualified.
*/ */
void void
QualifyRenameCollationStmt(RenameStmt *stmt) QualifyRenameCollationStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_COLLATION); Assert(stmt->renameType == OBJECT_COLLATION);
stmt->object = QualifyCollationName(castNode(List, stmt->object)); stmt->object = QualifyCollationName(castNode(List, stmt->object));
@ -46,8 +47,9 @@ QualifyRenameCollationStmt(RenameStmt *stmt)
* statement in place and makes the collation name fully qualified. * statement in place and makes the collation name fully qualified.
*/ */
void void
QualifyAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt) QualifyAlterCollationSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
stmt->object = QualifyCollationName(castNode(List, stmt->object)); stmt->object = QualifyCollationName(castNode(List, stmt->object));
@ -60,8 +62,9 @@ QualifyAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt)
* statement in place and makes the collation name fully qualified. * statement in place and makes the collation name fully qualified.
*/ */
void void
QualifyAlterCollationOwnerStmt(AlterOwnerStmt *stmt) QualifyAlterCollationOwnerStmt(Node *node)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_COLLATION); Assert(stmt->objectType == OBJECT_COLLATION);
stmt->object = QualifyCollationName(castNode(List, stmt->object)); stmt->object = QualifyCollationName(castNode(List, stmt->object));
@ -74,8 +77,9 @@ QualifyAlterCollationOwnerStmt(AlterOwnerStmt *stmt)
* statement in place and makes the collation name fully qualified. * statement in place and makes the collation name fully qualified.
*/ */
void void
QualifyDropCollationStmt(DropStmt *stmt) QualifyDropCollationStmt(Node *node)
{ {
DropStmt *stmt = castNode(DropStmt, node);
List *names = NIL; List *names = NIL;
List *name = NIL; List *name = NIL;

View File

@ -51,8 +51,9 @@ AssertObjectTypeIsFunctional(ObjectType type)
* (e.g. ALTER FUNCTION .. RENAME .. queries are RenameStmt ) * (e.g. ALTER FUNCTION .. RENAME .. queries are RenameStmt )
*/ */
void void
QualifyAlterFunctionStmt(AlterFunctionStmt *stmt) QualifyAlterFunctionStmt(Node *node)
{ {
AlterFunctionStmt *stmt = castNode(AlterFunctionStmt, node);
AssertObjectTypeIsFunctional(stmt->objtype); AssertObjectTypeIsFunctional(stmt->objtype);
QualifyFunction(stmt->func, stmt->objtype); QualifyFunction(stmt->func, stmt->objtype);
@ -65,8 +66,9 @@ QualifyAlterFunctionStmt(AlterFunctionStmt *stmt)
* statement in place and makes the function name fully qualified. * statement in place and makes the function name fully qualified.
*/ */
void void
QualifyRenameFunctionStmt(RenameStmt *stmt) QualifyRenameFunctionStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
AssertObjectTypeIsFunctional(stmt->renameType); AssertObjectTypeIsFunctional(stmt->renameType);
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->renameType); QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->renameType);
@ -79,8 +81,9 @@ QualifyRenameFunctionStmt(RenameStmt *stmt)
* statement in place and makes the function name fully qualified. * statement in place and makes the function name fully qualified.
*/ */
void void
QualifyAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt) QualifyAlterFunctionSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType); QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
@ -93,8 +96,9 @@ QualifyAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt)
* statement in place and makes the function name fully qualified. * statement in place and makes the function name fully qualified.
*/ */
void void
QualifyAlterFunctionOwnerStmt(AlterOwnerStmt *stmt) QualifyAlterFunctionOwnerStmt(Node *node)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType); QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);
@ -107,8 +111,9 @@ QualifyAlterFunctionOwnerStmt(AlterOwnerStmt *stmt)
* statement in place and makes the function name fully qualified. * statement in place and makes the function name fully qualified.
*/ */
void void
QualifyAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt) QualifyAlterFunctionDependsStmt(Node *node)
{ {
AlterObjectDependsStmt *stmt = castNode(AlterObjectDependsStmt, node);
AssertObjectTypeIsFunctional(stmt->objectType); AssertObjectTypeIsFunctional(stmt->objectType);
QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType); QualifyFunction(castNode(ObjectWithArgs, stmt->object), stmt->objectType);

View File

@ -70,8 +70,9 @@ TypeOidGetNamespaceOid(Oid typeOid)
void void
QualifyRenameTypeStmt(RenameStmt *stmt) QualifyRenameTypeStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
List *names = (List *) stmt->object; List *names = (List *) stmt->object;
Assert(stmt->renameType == OBJECT_TYPE); Assert(stmt->renameType == OBJECT_TYPE);
@ -88,8 +89,9 @@ QualifyRenameTypeStmt(RenameStmt *stmt)
void void
QualifyRenameTypeAttributeStmt(RenameStmt *stmt) QualifyRenameTypeAttributeStmt(Node *node)
{ {
RenameStmt *stmt = castNode(RenameStmt, node);
Assert(stmt->renameType == OBJECT_ATTRIBUTE); Assert(stmt->renameType == OBJECT_ATTRIBUTE);
Assert(stmt->relationType == OBJECT_TYPE); Assert(stmt->relationType == OBJECT_TYPE);
@ -103,8 +105,9 @@ QualifyRenameTypeAttributeStmt(RenameStmt *stmt)
void void
QualifyAlterEnumStmt(AlterEnumStmt *stmt) QualifyAlterEnumStmt(Node *node)
{ {
AlterEnumStmt *stmt = castNode(AlterEnumStmt, node);
List *names = stmt->typeName; List *names = stmt->typeName;
if (list_length(names) == 1) if (list_length(names) == 1)
@ -119,8 +122,9 @@ QualifyAlterEnumStmt(AlterEnumStmt *stmt)
void void
QualifyAlterTypeStmt(AlterTableStmt *stmt) QualifyAlterTypeStmt(Node *node)
{ {
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_TYPE); Assert(stmt->relkind == OBJECT_TYPE);
if (stmt->relation->schemaname == NULL) if (stmt->relation->schemaname == NULL)
@ -133,8 +137,10 @@ QualifyAlterTypeStmt(AlterTableStmt *stmt)
void void
QualifyCompositeTypeStmt(CompositeTypeStmt *stmt) QualifyCompositeTypeStmt(Node *node)
{ {
CompositeTypeStmt *stmt = castNode(CompositeTypeStmt, node);
if (stmt->typevar->schemaname == NULL) if (stmt->typevar->schemaname == NULL)
{ {
Oid creationSchema = RangeVarGetCreationNamespace(stmt->typevar); Oid creationSchema = RangeVarGetCreationNamespace(stmt->typevar);
@ -144,8 +150,10 @@ QualifyCompositeTypeStmt(CompositeTypeStmt *stmt)
void void
QualifyCreateEnumStmt(CreateEnumStmt *stmt) QualifyCreateEnumStmt(Node *node)
{ {
CreateEnumStmt *stmt = castNode(CreateEnumStmt, node);
if (list_length(stmt->typeName) == 1) if (list_length(stmt->typeName) == 1)
{ {
char *objname = NULL; char *objname = NULL;
@ -157,8 +165,9 @@ QualifyCreateEnumStmt(CreateEnumStmt *stmt)
void void
QualifyAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt) QualifyAlterTypeSchemaStmt(Node *node)
{ {
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
List *names = (List *) stmt->object; List *names = (List *) stmt->object;
@ -173,8 +182,9 @@ QualifyAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt)
void void
QualifyAlterTypeOwnerStmt(AlterOwnerStmt *stmt) QualifyAlterTypeOwnerStmt(Node *node)
{ {
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_TYPE); Assert(stmt->objectType == OBJECT_TYPE);
List *names = (List *) stmt->object; List *names = (List *) stmt->object;

View File

@ -84,7 +84,7 @@ master_create_worker_shards(PG_FUNCTION_ARGS)
* sessions creating shards. * sessions creating shards.
*/ */
ObjectAddressSet(tableAddress, RelationRelationId, distributedTableId); ObjectAddressSet(tableAddress, RelationRelationId, distributedTableId);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
CreateShardsWithRoundRobinPolicy(distributedTableId, shardCount, replicationFactor, CreateShardsWithRoundRobinPolicy(distributedTableId, shardCount, replicationFactor,
useExclusiveConnections); useExclusiveConnections);

View File

@ -105,7 +105,7 @@ master_create_empty_shard(PG_FUNCTION_ARGS)
* sessions creating shards. * sessions creating shards.
*/ */
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
/* don't allow the table to be dropped */ /* don't allow the table to be dropped */
LockRelationOid(relationId, AccessShareLock); LockRelationOid(relationId, AccessShareLock);

View File

@ -46,8 +46,8 @@ typedef struct ObjectAddressCollector
/* forward declarations for functions to interact with the ObjectAddressCollector */ /* forward declarations for functions to interact with the ObjectAddressCollector */
static void InitObjectAddressCollector(ObjectAddressCollector *collector); static void InitObjectAddressCollector(ObjectAddressCollector *collector);
static void CollectObjectAddress(ObjectAddressCollector *collector, const static void CollectObjectAddress(ObjectAddressCollector *collector,
ObjectAddress *address); const ObjectAddress *address);
static bool IsObjectAddressCollected(const ObjectAddress *findAddress, static bool IsObjectAddressCollected(const ObjectAddress *findAddress,
ObjectAddressCollector *collector); ObjectAddressCollector *collector);
static void MarkObjectVisited(ObjectAddressCollector *collector, static void MarkObjectVisited(ObjectAddressCollector *collector,

View File

@ -394,7 +394,7 @@ MetadataCreateCommands(void)
* visible to all sessions creating shards. * visible to all sessions creating shards.
*/ */
ObjectAddressSet(tableAddress, RelationRelationId, relationId); ObjectAddressSet(tableAddress, RelationRelationId, relationId);
EnsureDependenciesExistsOnAllNodes(&tableAddress); EnsureDependenciesExistOnAllNodes(&tableAddress);
metadataSnapshotCommandList = list_concat(metadataSnapshotCommandList, metadataSnapshotCommandList = list_concat(metadataSnapshotCommandList,
workerSequenceDDLCommands); workerSequenceDDLCommands);

View File

@ -35,12 +35,12 @@
static void SendCommandToMetadataWorkersParams(const char *command, static void SendCommandToMetadataWorkersParams(const char *command,
const char *user, int parameterCount, const char *user, int parameterCount,
const Oid *parameterTypes, const const Oid *parameterTypes,
char *const *parameterValues); const char *const *parameterValues);
static void SendCommandToWorkersParamsInternal(TargetWorkerSet targetWorkerSet, static void SendCommandToWorkersParamsInternal(TargetWorkerSet targetWorkerSet,
const char *command, const char *user, const char *command, const char *user,
int parameterCount, const int parameterCount,
Oid *parameterTypes, const Oid *parameterTypes,
const char *const *parameterValues); const char *const *parameterValues);
static void ErrorIfAnyMetadataNodeOutOfSync(List *metadataNodeList); static void ErrorIfAnyMetadataNodeOutOfSync(List *metadataNodeList);
static void SendCommandListToAllWorkersInternal(List *commandList, bool failOnError, static void SendCommandListToAllWorkersInternal(List *commandList, bool failOnError,
@ -316,8 +316,8 @@ SendBareOptionalCommandListToAllWorkersAsUser(List *commandList, const char *use
static void static void
SendCommandToMetadataWorkersParams(const char *command, SendCommandToMetadataWorkersParams(const char *command,
const char *user, int parameterCount, const char *user, int parameterCount,
const Oid *parameterTypes, const const Oid *parameterTypes,
char *const *parameterValues) const char *const *parameterValues)
{ {
List *workerNodeList = TargetWorkerSetNodeList(WORKERS_WITH_METADATA, ShareLock); List *workerNodeList = TargetWorkerSetNodeList(WORKERS_WITH_METADATA, ShareLock);
@ -340,8 +340,8 @@ SendCommandToMetadataWorkersParams(const char *command,
static void static void
SendCommandToWorkersParamsInternal(TargetWorkerSet targetWorkerSet, const char *command, SendCommandToWorkersParamsInternal(TargetWorkerSet targetWorkerSet, const char *command,
const char *user, int parameterCount, const char *user, int parameterCount,
const Oid *parameterTypes, const const Oid *parameterTypes,
char *const *parameterValues) const char *const *parameterValues)
{ {
List *connectionList = NIL; List *connectionList = NIL;
ListCell *connectionCell = NULL; ListCell *connectionCell = NULL;

View File

@ -75,8 +75,8 @@ static ForeignConstraintRelationshipGraph *fConstraintRelationshipGraph = NULL;
static void CreateForeignConstraintRelationshipGraph(void); static void CreateForeignConstraintRelationshipGraph(void);
static void PopulateAdjacencyLists(void); static void PopulateAdjacencyLists(void);
static int CompareForeignConstraintRelationshipEdges(const void *leftElement, const static int CompareForeignConstraintRelationshipEdges(const void *leftElement,
void *rightElement); const void *rightElement);
static void AddForeignConstraintRelationshipEdge(Oid referencingOid, Oid referencedOid); static void AddForeignConstraintRelationshipEdge(Oid referencingOid, Oid referencedOid);
static ForeignConstraintRelationshipNode * CreateOrFindNode(HTAB *adjacencyLists, Oid static ForeignConstraintRelationshipNode * CreateOrFindNode(HTAB *adjacencyLists, Oid
relid); relid);
@ -360,15 +360,13 @@ PopulateAdjacencyLists(void)
* ForeignConstraintRelationshipEdge using referencing and referenced ids respectively. * ForeignConstraintRelationshipEdge using referencing and referenced ids respectively.
*/ */
static int static int
CompareForeignConstraintRelationshipEdges(const void *leftElement, const CompareForeignConstraintRelationshipEdges(const void *leftElement,
void *rightElement) const void *rightElement)
{ {
const ForeignConstraintRelationshipEdge *leftEdge = *((const const ForeignConstraintRelationshipEdge *leftEdge =
ForeignConstraintRelationshipEdge *((const ForeignConstraintRelationshipEdge **) leftElement);
**) leftElement); const ForeignConstraintRelationshipEdge *rightEdge =
const ForeignConstraintRelationshipEdge *rightEdge = *((const *((const ForeignConstraintRelationshipEdge **) rightElement);
ForeignConstraintRelationshipEdge
**) rightElement);
int referencingDiff = leftEdge->referencingRelationOID - int referencingDiff = leftEdge->referencingRelationOID -
rightEdge->referencingRelationOID; rightEdge->referencingRelationOID;

View File

@ -83,10 +83,10 @@ worker_create_or_replace_object(PG_FUNCTION_ARGS)
* if the type actually exists instead of adding the IF EXISTS keyword to the * if the type actually exists instead of adding the IF EXISTS keyword to the
* statement. * statement.
*/ */
const ObjectAddress *address = GetObjectAddressFromParseTree(parseTree, true); ObjectAddress address = GetObjectAddressFromParseTree(parseTree, true);
if (ObjectExists(address)) if (ObjectExists(&address))
{ {
const char *localSqlStatement = CreateStmtByObjectAddress(address); const char *localSqlStatement = CreateStmtByObjectAddress(&address);
if (strcmp(sqlStatement, localSqlStatement) == 0) if (strcmp(sqlStatement, localSqlStatement) == 0)
{ {
@ -106,9 +106,9 @@ worker_create_or_replace_object(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
} }
char *newName = GenerateBackupNameForCollision(address); char *newName = GenerateBackupNameForCollision(&address);
RenameStmt *renameStmt = CreateRenameStatement(address, newName); RenameStmt *renameStmt = CreateRenameStatement(&address, newName);
const char *sqlRenameStmt = DeparseTreeNode((Node *) renameStmt); const char *sqlRenameStmt = DeparseTreeNode((Node *) renameStmt);
CitusProcessUtility((Node *) renameStmt, sqlRenameStmt, CitusProcessUtility((Node *) renameStmt, sqlRenameStmt,
PROCESS_UTILITY_TOPLEVEL, PROCESS_UTILITY_TOPLEVEL,

View File

@ -57,6 +57,8 @@ static uint32 FileBufferSizeInBytes = 0; /* file buffer size to init later */
/* Local functions forward declarations */ /* Local functions forward declarations */
typedef uint32 (*PartitionIdFunction)(Datum, Oid, const void *);
static ShardInterval ** SyntheticShardIntervalArrayForShardMinValues( static ShardInterval ** SyntheticShardIntervalArrayForShardMinValues(
Datum *shardMinValues, Datum *shardMinValues,
int shardCount); int shardCount);
@ -69,8 +71,7 @@ static void FileOutputStreamWrite(FileOutputStream *file, StringInfo dataToWrite
static void FileOutputStreamFlush(FileOutputStream *file); static void FileOutputStreamFlush(FileOutputStream *file);
static void FilterAndPartitionTable(const char *filterQuery, static void FilterAndPartitionTable(const char *filterQuery,
const char *columnName, Oid columnType, const char *columnName, Oid columnType,
uint32 (*PartitionIdFunction)(Datum, Oid, const PartitionIdFunction partitionIdFunction,
void *),
const void *partitionIdContext, const void *partitionIdContext,
FileOutputStream *partitionFileArray, FileOutputStream *partitionFileArray,
uint32 fileCount); uint32 fileCount);
@ -79,10 +80,10 @@ static CopyOutState InitRowOutputState(void);
static void ClearRowOutputState(CopyOutState copyState); static void ClearRowOutputState(CopyOutState copyState);
static void OutputBinaryHeaders(FileOutputStream *partitionFileArray, uint32 fileCount); static void OutputBinaryHeaders(FileOutputStream *partitionFileArray, uint32 fileCount);
static void OutputBinaryFooters(FileOutputStream *partitionFileArray, uint32 fileCount); static void OutputBinaryFooters(FileOutputStream *partitionFileArray, uint32 fileCount);
static uint32 RangePartitionId(Datum partitionValue, Oid partitionCollation, const static uint32 RangePartitionId(Datum partitionValue, Oid partitionCollation,
void *context); const void *context);
static uint32 HashPartitionId(Datum partitionValue, Oid partitionCollation, const static uint32 HashPartitionId(Datum partitionValue, Oid partitionCollation,
void *context); const void *context);
static StringInfo UserPartitionFilename(StringInfo directoryName, uint32 partitionId); static StringInfo UserPartitionFilename(StringInfo directoryName, uint32 partitionId);
static bool FileIsLink(char *filename, struct stat filestat); static bool FileIsLink(char *filename, struct stat filestat);
@ -854,7 +855,7 @@ FileOutputStreamFlush(FileOutputStream *file)
static void static void
FilterAndPartitionTable(const char *filterQuery, FilterAndPartitionTable(const char *filterQuery,
const char *partitionColumnName, Oid partitionColumnType, const char *partitionColumnName, Oid partitionColumnType,
uint32 (*PartitionIdFunction)(Datum, Oid, const void *), PartitionIdFunction partitionIdFunction,
const void *partitionIdContext, const void *partitionIdContext,
FileOutputStream *partitionFileArray, FileOutputStream *partitionFileArray,
uint32 fileCount) uint32 fileCount)
@ -941,7 +942,7 @@ FilterAndPartitionTable(const char *filterQuery,
*/ */
if (!partitionKeyNull) if (!partitionKeyNull)
{ {
partitionId = (*PartitionIdFunction)(partitionKey, partitionId = (*partitionIdFunction)(partitionKey,
partitionColumnCollation, partitionColumnCollation,
partitionIdContext); partitionIdContext);
if (partitionId == INVALID_SHARD_INDEX) if (partitionId == INVALID_SHARD_INDEX)

View File

@ -19,62 +19,84 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "tcop/dest.h" #include "tcop/dest.h"
/*
* DistributeObjectOps specifies handlers for node/object type pairs.
* Instances of this type should all be declared in deparse.c.
* Handlers expect to receive the same Node passed to GetDistributeObjectOps.
* Handlers may be NULL.
*
* Handlers:
* deparse: return a string representation of the node.
* qualify: replace names in tree with qualified names.
* preprocess: executed before standard_ProcessUtility.
* postprocess: executed after standard_ProcessUtility.
* address: return an ObjectAddress for the subject of the statement.
* 2nd parameter is missing_ok.
*
* preprocess/postprocess return a List of DDLJobs.
*/
typedef struct DistributeObjectOps
{
char * (*deparse)(Node *);
void (*qualify)(Node *);
List * (*preprocess)(Node *, const char *);
List * (*postprocess)(Node *, const char *);
ObjectAddress (*address)(Node *, bool);
} DistributeObjectOps;
const DistributeObjectOps * GetDistributeObjectOps(Node *node);
/* cluster.c - forward declarations */ /* cluster.c - forward declarations */
extern List * PlanClusterStmt(ClusterStmt *clusterStmt, const char *clusterCommand); extern List * PreprocessClusterStmt(Node *node, const char *clusterCommand);
/* call.c */ /* call.c */
extern bool CallDistributedProcedureRemotely(CallStmt *callStmt, DestReceiver *dest); extern bool CallDistributedProcedureRemotely(CallStmt *callStmt, DestReceiver *dest);
/* collation.c - forward declarations */ /* collation.c - forward declarations */
extern char * CreateCollationDDL(Oid collationId); extern char * CreateCollationDDL(Oid collationId);
extern List * CreateCollationDDLsIdempotent(Oid collationId); extern List * CreateCollationDDLsIdempotent(Oid collationId);
extern ObjectAddress AlterCollationOwnerObjectAddress(AlterOwnerStmt *stmt); extern ObjectAddress AlterCollationOwnerObjectAddress(Node *stmt, bool missing_ok);
extern List * PlanDropCollationStmt(DropStmt *stmt); extern List * PreprocessDropCollationStmt(Node *stmt, const char *queryString);
extern List * PlanAlterCollationOwnerStmt(AlterOwnerStmt *stmt, const char *queryString); extern List * PreprocessAlterCollationOwnerStmt(Node *stmt, const char *queryString);
extern List * PlanAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt, extern List * PreprocessAlterCollationSchemaStmt(Node *stmt, const char *queryString);
const char *queryString); extern List * PreprocessRenameCollationStmt(Node *stmt, const char *queryString);
extern List * PlanRenameCollationStmt(RenameStmt *stmt, const char *queryString); extern ObjectAddress RenameCollationStmtObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress * RenameCollationStmtObjectAddress(RenameStmt *stmt, extern ObjectAddress AlterCollationSchemaStmtObjectAddress(Node *stmt,
bool missing_ok); bool missing_ok);
extern ObjectAddress * AlterCollationSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, extern List * PostprocessAlterCollationSchemaStmt(Node *stmt, const char *queryString);
bool missing_ok);
extern void ProcessAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt,
const char *queryString);
extern char * GenerateBackupNameForCollationCollision(const ObjectAddress *address); extern char * GenerateBackupNameForCollationCollision(const ObjectAddress *address);
extern ObjectAddress * DefineCollationStmtObjectAddress(DefineStmt *stmt, bool extern ObjectAddress DefineCollationStmtObjectAddress(Node *stmt, bool missing_ok);
missing_ok); extern List * PostprocessDefineCollationStmt(Node *stmt, const char *queryString);
extern List * ProcessCollationDefineStmt(DefineStmt *stmt, const char *queryString);
/* extension.c - forward declarations */ /* extension.c - forward declarations */
extern bool IsCreateAlterExtensionUpdateCitusStmt(Node *parsetree); extern bool IsCreateAlterExtensionUpdateCitusStmt(Node *parsetree);
extern void ErrorIfUnstableCreateOrAlterExtensionStmt(Node *parsetree); extern void ErrorIfUnstableCreateOrAlterExtensionStmt(Node *parsetree);
extern List * PlanCreateExtensionStmt(CreateExtensionStmt *stmt, const char *queryString); extern List * PostprocessCreateExtensionStmt(Node *stmt, const char *queryString);
extern void ProcessCreateExtensionStmt(CreateExtensionStmt *stmt, const extern List * PreprocessDropExtensionStmt(Node *stmt, const char *queryString);
char *queryString); extern List * PreprocessAlterExtensionSchemaStmt(Node *stmt,
extern List * PlanDropExtensionStmt(DropStmt *stmt, const char *queryString); const char *queryString);
extern List * PlanAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionStmt, extern List * PostprocessAlterExtensionSchemaStmt(Node *stmt,
const char *queryString); const char *queryString);
extern void ProcessAlterExtensionSchemaStmt(AlterObjectSchemaStmt *alterExtensionStmt, extern List * PreprocessAlterExtensionUpdateStmt(Node *stmt,
const char *queryString); const char *queryString);
extern List * PlanAlterExtensionUpdateStmt(AlterExtensionStmt *alterExtensionStmt, const extern List * PreprocessAlterExtensionContentsStmt(Node *node,
char *queryString); const char *queryString);
extern List * CreateExtensionDDLCommand(const ObjectAddress *extensionAddress); extern List * CreateExtensionDDLCommand(const ObjectAddress *extensionAddress);
extern ObjectAddress * AlterExtensionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, extern ObjectAddress AlterExtensionSchemaStmtObjectAddress(Node *stmt,
bool missing_ok); bool missing_ok);
extern ObjectAddress * AlterExtensionUpdateStmtObjectAddress( extern ObjectAddress AlterExtensionUpdateStmtObjectAddress(Node *stmt,
AlterExtensionStmt *alterExtensionStmt, bool missing_ok);
bool missing_ok);
/* foreign_constraint.c - forward declarations */ /* foreign_constraint.c - forward declarations */
extern bool ConstraintIsAForeignKeyToReferenceTable(char *constraintName, extern bool ConstraintIsAForeignKeyToReferenceTable(char *constraintName,
Oid leftRelationId); Oid leftRelationId);
extern void ErrorIfUnsupportedForeignConstraintExists(Relation relation, char extern void ErrorIfUnsupportedForeignConstraintExists(Relation relation,
distributionMethod, char distributionMethod,
Var *distributionColumn, uint32 Var *distributionColumn,
colocationId); uint32 colocationId);
extern bool ColumnAppearsInForeignKeyToReferenceTable(char *columnName, Oid extern bool ColumnAppearsInForeignKeyToReferenceTable(char *columnName, Oid
relationId); relationId);
extern List * GetTableForeignConstraintCommands(Oid relationId); extern List * GetTableForeignConstraintCommands(Oid relationId);
@ -85,58 +107,62 @@ extern bool ConstraintIsAForeignKey(char *constraintName, Oid relationId);
/* function.c - forward declarations */ /* function.c - forward declarations */
extern List * PlanCreateFunctionStmt(CreateFunctionStmt *stmt, const char *queryString); extern List * PreprocessCreateFunctionStmt(Node *stmt, const char *queryString);
extern List * ProcessCreateFunctionStmt(CreateFunctionStmt *stmt, const extern List * PostprocessCreateFunctionStmt(Node *stmt,
char *queryString); const char *queryString);
extern ObjectAddress * CreateFunctionStmtObjectAddress(CreateFunctionStmt *stmt, extern ObjectAddress CreateFunctionStmtObjectAddress(Node *stmt,
bool missing_ok); bool missing_ok);
extern ObjectAddress * DefineAggregateStmtObjectAddress(DefineStmt *stmt, bool extern ObjectAddress DefineAggregateStmtObjectAddress(Node *stmt,
missing_ok);
extern List * PlanAlterFunctionStmt(AlterFunctionStmt *stmt, const char *queryString);
extern ObjectAddress * AlterFunctionStmtObjectAddress(AlterFunctionStmt *stmt,
bool missing_ok); bool missing_ok);
extern List * PlanRenameFunctionStmt(RenameStmt *stmt, const char *queryString); extern List * PreprocessAlterFunctionStmt(Node *stmt, const char *queryString);
extern ObjectAddress * RenameFunctionStmtObjectAddress(RenameStmt *stmt, extern ObjectAddress AlterFunctionStmtObjectAddress(Node *stmt,
bool missing_ok); bool missing_ok);
extern List * PlanAlterFunctionOwnerStmt(AlterOwnerStmt *stmt, const char *queryString); extern List * PreprocessRenameFunctionStmt(Node *stmt, const char *queryString);
extern ObjectAddress * AlterFunctionOwnerObjectAddress(AlterOwnerStmt *stmt, extern ObjectAddress RenameFunctionStmtObjectAddress(Node *stmt,
bool missing_ok); bool missing_ok);
extern List * PlanAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, extern List * PreprocessAlterFunctionOwnerStmt(Node *stmt, const char *queryString);
const char *queryString); extern ObjectAddress AlterFunctionOwnerObjectAddress(Node *stmt,
extern ObjectAddress * AlterFunctionSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok);
bool missing_ok); extern List * PreprocessAlterFunctionSchemaStmt(Node *stmt, const char *queryString);
extern void ProcessAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt, extern ObjectAddress AlterFunctionSchemaStmtObjectAddress(Node *stmt,
const char *queryString); bool missing_ok);
extern List * PlanDropFunctionStmt(DropStmt *stmt, const char *queryString); extern List * PostprocessAlterFunctionSchemaStmt(Node *stmt,
extern List * PlanAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt, const char *queryString);
const char *queryString); extern List * PreprocessDropFunctionStmt(Node *stmt, const char *queryString);
extern ObjectAddress * AlterFunctionDependsStmtObjectAddress(AlterObjectDependsStmt *stmt, extern List * PreprocessAlterFunctionDependsStmt(Node *stmt,
bool missing_ok); const char *queryString);
extern ObjectAddress AlterFunctionDependsStmtObjectAddress(Node *stmt,
bool missing_ok);
/* grant.c - forward declarations */ /* grant.c - forward declarations */
extern List * PlanGrantStmt(GrantStmt *grantStmt); extern List * PreprocessGrantStmt(Node *node, const char *queryString);
/* index.c - forward declarations */ /* index.c - forward declarations */
extern bool IsIndexRenameStmt(RenameStmt *renameStmt); extern bool IsIndexRenameStmt(RenameStmt *renameStmt);
extern List * PlanIndexStmt(IndexStmt *createIndexStatement, extern List * PreprocessIndexStmt(Node *createIndexStatement,
const char *createIndexCommand); const char *createIndexCommand);
extern List * PlanReindexStmt(ReindexStmt *ReindexStatement, extern List * PreprocessReindexStmt(Node *ReindexStatement,
const char *ReindexCommand); const char *ReindexCommand);
extern List * PlanDropIndexStmt(DropStmt *dropIndexStatement, extern List * PreprocessDropIndexStmt(Node *dropIndexStatement,
const char *dropIndexCommand); const char *dropIndexCommand);
extern void PostProcessIndexStmt(IndexStmt *indexStmt); extern List * PostprocessIndexStmt(Node *node,
const char *queryString);
extern void ErrorIfUnsupportedAlterIndexStmt(AlterTableStmt *alterTableStatement); extern void ErrorIfUnsupportedAlterIndexStmt(AlterTableStmt *alterTableStatement);
/* objectaddress.c - forward declarations */
extern ObjectAddress CreateExtensionStmtObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress AlterExtensionStmtObjectAddress(Node *stmt, bool missing_ok);
/* policy.c - forward declarations */ /* policy.c - forward declarations */
extern List * CreatePolicyCommands(Oid relationId); extern List * CreatePolicyCommands(Oid relationId);
extern void ErrorIfUnsupportedPolicy(Relation relation); extern void ErrorIfUnsupportedPolicy(Relation relation);
extern void ErrorIfUnsupportedPolicyExpr(Node *expr); extern void ErrorIfUnsupportedPolicyExpr(Node *expr);
extern List * PlanCreatePolicyStmt(CreatePolicyStmt *stmt); extern List * PreprocessCreatePolicyStmt(Node *node, const char *queryString);
extern List * PlanAlterPolicyStmt(AlterPolicyStmt *stmt); extern List * PreprocessAlterPolicyStmt(Node *node, const char *queryString);
extern List * PlanDropPolicyStmt(DropStmt *stmt, const char *queryString); extern List * PreprocessDropPolicyStmt(Node *stmt, const char *queryString);
extern bool IsPolicyRenameStmt(RenameStmt *stmt); extern bool IsPolicyRenameStmt(RenameStmt *stmt);
extern void CreatePolicyEventExtendNames(CreatePolicyStmt *stmt, const char *schemaName, extern void CreatePolicyEventExtendNames(CreatePolicyStmt *stmt, const char *schemaName,
uint64 shardId); uint64 shardId);
@ -149,24 +175,23 @@ extern void DropPolicyEventExtendNames(DropStmt *stmt, const char *schemaName, u
/* rename.c - forward declarations*/ /* rename.c - forward declarations*/
extern List * PlanRenameStmt(RenameStmt *renameStmt, const char *renameCommand); extern List * PreprocessRenameStmt(Node *renameStmt, const char *renameCommand);
extern void ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt); extern void ErrorIfUnsupportedRenameStmt(RenameStmt *renameStmt);
extern List * PreprocessRenameAttributeStmt(Node *stmt, const char *queryString);
/* role.c - forward declarations*/ /* role.c - forward declarations*/
extern List * ProcessAlterRoleStmt(AlterRoleStmt *stmt, const char *queryString); extern List * PostprocessAlterRoleStmt(Node *stmt, const char *queryString);
extern List * GenerateAlterRoleIfExistsCommandAllRoles(void); extern List * GenerateAlterRoleIfExistsCommandAllRoles(void);
/* schema.c - forward declarations */ /* schema.c - forward declarations */
extern void ProcessDropSchemaStmt(DropStmt *dropSchemaStatement); extern List * PreprocessDropSchemaStmt(Node *dropSchemaStatement,
extern List * PlanAlterTableSchemaStmt(AlterObjectSchemaStmt *stmt,
const char *queryString); const char *queryString);
extern List * PlanAlterObjectSchemaStmt(AlterObjectSchemaStmt *alterObjectSchemaStmt, extern List * PreprocessAlterTableSchemaStmt(Node *stmt,
const char *alterObjectSchemaCommand); const char *queryString);
extern List * PreprocessAlterObjectSchemaStmt(Node *alterObjectSchemaStmt,
extern void ProcessAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, const char *alterObjectSchemaCommand);
const char *queryString);
/* sequence.c - forward declarations */ /* sequence.c - forward declarations */
@ -179,16 +204,19 @@ extern Node * ProcessCreateSubscriptionStmt(CreateSubscriptionStmt *createSubStm
/* table.c - forward declarations */ /* table.c - forward declarations */
extern void ProcessDropTableStmt(DropStmt *dropTableStatement); extern List * PreprocessDropTableStmt(Node *stmt, const char *queryString);
extern void ProcessCreateTableStmtPartitionOf(CreateStmt *createStatement); extern List * PostprocessCreateTableStmtPartitionOf(CreateStmt *createStatement,
extern void ProcessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement); const char *queryString);
extern List * PlanAlterTableStmt(AlterTableStmt *alterTableStatement, extern List * PostprocessAlterTableStmtAttachPartition(
const char *alterTableCommand); AlterTableStmt *alterTableStatement,
const char *queryString);
extern List * PreprocessAlterTableStmt(Node *node, const char *alterTableCommand);
extern List * PreprocessAlterTableMoveAllStmt(Node *node, const char *queryString);
extern Node * WorkerProcessAlterTableStmt(AlterTableStmt *alterTableStatement, extern Node * WorkerProcessAlterTableStmt(AlterTableStmt *alterTableStatement,
const char *alterTableCommand); const char *alterTableCommand);
extern bool IsAlterTableRenameStmt(RenameStmt *renameStmt); extern bool IsAlterTableRenameStmt(RenameStmt *renameStmt);
extern void ErrorIfAlterDropsPartitionColumn(AlterTableStmt *alterTableStatement); extern void ErrorIfAlterDropsPartitionColumn(AlterTableStmt *alterTableStatement);
extern void PostProcessAlterTableStmt(AlterTableStmt *pStmt); extern void PostprocessAlterTableStmt(AlterTableStmt *pStmt);
extern void ErrorUnsupportedAlterTableAddColumn(Oid relationId, AlterTableCmd *command, extern void ErrorUnsupportedAlterTableAddColumn(Oid relationId, AlterTableCmd *command,
Constraint *constraint); Constraint *constraint);
extern void ErrorIfUnsupportedConstraint(Relation relation, char distributionMethod, extern void ErrorIfUnsupportedConstraint(Relation relation, char distributionMethod,
@ -196,36 +224,33 @@ extern void ErrorIfUnsupportedConstraint(Relation relation, char distributionMet
/* truncate.c - forward declarations */ /* truncate.c - forward declarations */
extern void ProcessTruncateStatement(TruncateStmt *truncateStatement); extern void PostprocessTruncateStatement(TruncateStmt *truncateStatement);
/* type.c - forward declarations */ /* type.c - forward declarations */
extern List * PlanCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString); extern List * PreprocessCompositeTypeStmt(Node *stmt, const char *queryString);
extern void ProcessCompositeTypeStmt(CompositeTypeStmt *stmt, const char *queryString); extern List * PostprocessCompositeTypeStmt(Node *stmt, const char *queryString);
extern List * PlanAlterTypeStmt(AlterTableStmt *stmt, const char *queryString); extern List * PreprocessAlterTypeStmt(Node *stmt, const char *queryString);
extern List * PlanCreateEnumStmt(CreateEnumStmt *createEnumStmt, const char *queryString); extern List * PreprocessCreateEnumStmt(Node *stmt, const char *queryString);
extern void ProcessCreateEnumStmt(CreateEnumStmt *stmt, const char *queryString); extern List * PostprocessCreateEnumStmt(Node *stmt, const char *queryString);
extern List * PlanAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString); extern List * PreprocessAlterEnumStmt(Node *stmt, const char *queryString);
extern void ProcessAlterEnumStmt(AlterEnumStmt *stmt, const char *queryString); extern List * PostprocessAlterEnumStmt(Node *stmt, const char *queryString);
extern List * PlanDropTypeStmt(DropStmt *stmt, const char *queryString); extern List * PreprocessDropTypeStmt(Node *stmt, const char *queryString);
extern List * PlanRenameTypeStmt(RenameStmt *stmt, const char *queryString); extern List * PreprocessRenameTypeStmt(Node *stmt, const char *queryString);
extern List * PlanRenameTypeAttributeStmt(RenameStmt *stmt, const char *queryString); extern List * PreprocessRenameTypeAttributeStmt(Node *stmt, const char *queryString);
extern List * PlanAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt, extern List * PreprocessAlterTypeSchemaStmt(Node *stmt, const char *queryString);
const char *queryString); extern List * PreprocessAlterTypeOwnerStmt(Node *stmt, const char *queryString);
extern List * PlanAlterTypeOwnerStmt(AlterOwnerStmt *stmt, const char *queryString); extern List * PostprocessAlterTypeSchemaStmt(Node *stmt, const char *queryString);
extern void ProcessAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt,
const char *queryString);
extern Node * CreateTypeStmtByObjectAddress(const ObjectAddress *address); extern Node * CreateTypeStmtByObjectAddress(const ObjectAddress *address);
extern ObjectAddress * CompositeTypeStmtObjectAddress(CompositeTypeStmt *stmt, bool extern ObjectAddress CompositeTypeStmtObjectAddress(Node *stmt, bool missing_ok);
missing_ok); extern ObjectAddress CreateEnumStmtObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress * CreateEnumStmtObjectAddress(CreateEnumStmt *stmt, bool missing_ok); extern ObjectAddress AlterTypeStmtObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress * AlterTypeStmtObjectAddress(AlterTableStmt *stmt, bool missing_ok); extern ObjectAddress AlterEnumStmtObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress * AlterEnumStmtObjectAddress(AlterEnumStmt *stmt, bool missing_ok); extern ObjectAddress RenameTypeStmtObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress * RenameTypeStmtObjectAddress(RenameStmt *stmt, bool missing_ok); extern ObjectAddress AlterTypeSchemaStmtObjectAddress(Node *stmt,
extern ObjectAddress * AlterTypeSchemaStmtObjectAddress(AlterObjectSchemaStmt *stmt, bool missing_ok);
bool missing_ok); extern ObjectAddress RenameTypeAttributeStmtObjectAddress(Node *stmt,
extern ObjectAddress * RenameTypeAttributeStmtObjectAddress(RenameStmt *stmt, bool bool missing_ok);
missing_ok); extern ObjectAddress AlterTypeOwnerObjectAddress(Node *stmt, bool missing_ok);
extern ObjectAddress * AlterTypeOwnerObjectAddress(AlterOwnerStmt *stmt, bool missing_ok);
extern List * CreateTypeDDLCommandsIdempotent(const ObjectAddress *typeAddress); extern List * CreateTypeDDLCommandsIdempotent(const ObjectAddress *typeAddress);
extern char * GenerateBackupNameForTypeCollision(const ObjectAddress *address); extern char * GenerateBackupNameForTypeCollision(const ObjectAddress *address);
@ -236,9 +261,9 @@ extern char * GenerateBackupNameForProcCollision(const ObjectAddress *address);
extern ObjectWithArgs * ObjectWithArgsFromOid(Oid funcOid); extern ObjectWithArgs * ObjectWithArgsFromOid(Oid funcOid);
/* vacuum.c - froward declarations */ /* vacuum.c - froward declarations */
extern void ProcessVacuumStmt(VacuumStmt *vacuumStmt, const char *vacuumCommand); extern void PostprocessVacuumStmt(VacuumStmt *vacuumStmt, const char *vacuumCommand);
extern bool ShouldPropagateSetCommand(VariableSetStmt *setStmt); extern bool ShouldPropagateSetCommand(VariableSetStmt *setStmt);
extern void ProcessVariableSetStmt(VariableSetStmt *setStmt, const char *setCommand); extern void PostprocessVariableSetStmt(VariableSetStmt *setStmt, const char *setCommand);
#endif /*CITUS_COMMANDS_H */ #endif /*CITUS_COMMANDS_H */

View File

@ -209,8 +209,8 @@ extern MultiConnection * GetNodeConnection(uint32 flags, const char *hostname,
extern MultiConnection * StartNodeConnection(uint32 flags, const char *hostname, extern MultiConnection * StartNodeConnection(uint32 flags, const char *hostname,
int32 port); int32 port);
extern MultiConnection * GetNodeUserDatabaseConnection(uint32 flags, const char *hostname, extern MultiConnection * GetNodeUserDatabaseConnection(uint32 flags, const char *hostname,
int32 port, const char *user, const int32 port, const char *user,
char *database); const char *database);
extern List * StartWorkerListConnections(List *workerList, uint32 flags, const char *user, extern List * StartWorkerListConnections(List *workerList, uint32 flags, const char *user,
const char *database); const char *database);
extern MultiConnection * StartNodeUserDatabaseConnection(uint32 flags, extern MultiConnection * StartNodeUserDatabaseConnection(uint32 flags,

View File

@ -32,64 +32,68 @@ extern void AssertObjectTypeIsFunctional(ObjectType type);
extern void QualifyTreeNode(Node *stmt); extern void QualifyTreeNode(Node *stmt);
extern char * DeparseTreeNode(Node *stmt); extern char * DeparseTreeNode(Node *stmt);
/* forward declarations for deparse_collation_stmts.c */ /* forward declarations for deparse_attribute_stmts.c */
extern char * DeparseDropCollationStmt(DropStmt *stmt); extern char * DeparseRenameAttributeStmt(Node *);
extern char * DeparseRenameCollationStmt(RenameStmt *stmt);
extern char * DeparseAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt);
extern char * DeparseAlterCollationOwnerStmt(AlterOwnerStmt *stmt);
extern void QualifyDropCollationStmt(DropStmt *stmt); /* forward declarations for deparse_collation_stmts.c */
extern void QualifyRenameCollationStmt(RenameStmt *stmt); extern char * DeparseDropCollationStmt(Node *stmt);
extern void QualifyAlterCollationSchemaStmt(AlterObjectSchemaStmt *stmt); extern char * DeparseRenameCollationStmt(Node *stmt);
extern void QualifyAlterCollationOwnerStmt(AlterOwnerStmt *stmt); extern char * DeparseAlterCollationSchemaStmt(Node *stmt);
extern char * DeparseAlterCollationOwnerStmt(Node *stmt);
extern void QualifyDropCollationStmt(Node *stmt);
extern void QualifyRenameCollationStmt(Node *stmt);
extern void QualifyAlterCollationSchemaStmt(Node *stmt);
extern void QualifyAlterCollationOwnerStmt(Node *stmt);
/* forward declarations for deparse_type_stmts.c */ /* forward declarations for deparse_type_stmts.c */
extern char * DeparseCompositeTypeStmt(CompositeTypeStmt *stmt); extern char * DeparseCompositeTypeStmt(Node *stmt);
extern char * DeparseCreateEnumStmt(CreateEnumStmt *stmt); extern char * DeparseCreateEnumStmt(Node *stmt);
extern char * DeparseDropTypeStmt(DropStmt *stmt); extern char * DeparseDropTypeStmt(Node *stmt);
extern char * DeparseAlterEnumStmt(AlterEnumStmt *stmt); extern char * DeparseAlterEnumStmt(Node *stmt);
extern char * DeparseAlterTypeStmt(AlterTableStmt *stmt); extern char * DeparseAlterTypeStmt(Node *stmt);
extern char * DeparseRenameTypeStmt(RenameStmt *stmt); extern char * DeparseRenameTypeStmt(Node *stmt);
extern char * DeparseRenameTypeAttributeStmt(RenameStmt *stmt); extern char * DeparseRenameTypeAttributeStmt(Node *stmt);
extern char * DeparseAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt); extern char * DeparseAlterTypeSchemaStmt(Node *stmt);
extern char * DeparseAlterTypeOwnerStmt(AlterOwnerStmt *stmt); extern char * DeparseAlterTypeOwnerStmt(Node *stmt);
extern void QualifyRenameTypeStmt(RenameStmt *stmt); extern void QualifyRenameAttributeStmt(Node *stmt);
extern void QualifyRenameTypeAttributeStmt(RenameStmt *stmt); extern void QualifyRenameTypeStmt(Node *stmt);
extern void QualifyAlterEnumStmt(AlterEnumStmt *stmt); extern void QualifyRenameTypeAttributeStmt(Node *stmt);
extern void QualifyAlterTypeStmt(AlterTableStmt *stmt); extern void QualifyAlterEnumStmt(Node *stmt);
extern void QualifyCompositeTypeStmt(CompositeTypeStmt *stmt); extern void QualifyAlterTypeStmt(Node *stmt);
extern void QualifyCreateEnumStmt(CreateEnumStmt *stmt); extern void QualifyCompositeTypeStmt(Node *stmt);
extern void QualifyAlterTypeSchemaStmt(AlterObjectSchemaStmt *stmt); extern void QualifyCreateEnumStmt(Node *stmt);
extern void QualifyAlterTypeOwnerStmt(AlterOwnerStmt *stmt); extern void QualifyAlterTypeSchemaStmt(Node *stmt);
extern void QualifyAlterTypeOwnerStmt(Node *stmt);
extern ObjectAddress * GetObjectAddressFromParseTree(Node *parseTree, bool missing_ok); extern ObjectAddress GetObjectAddressFromParseTree(Node *parseTree, bool missing_ok);
extern ObjectAddress RenameAttributeStmtObjectAddress(Node *stmt, bool missing_ok);
/* forward declarations for deparse_function_stmts.c */ /* forward declarations for deparse_function_stmts.c */
extern char * DeparseDropFunctionStmt(DropStmt *stmt); extern char * DeparseDropFunctionStmt(Node *stmt);
extern char * DeparseAlterFunctionStmt(AlterFunctionStmt *stmt); extern char * DeparseAlterFunctionStmt(Node *stmt);
extern char * DeparseRenameFunctionStmt(RenameStmt *stmt); extern char * DeparseRenameFunctionStmt(Node *stmt);
extern char * DeparseAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt); extern char * DeparseAlterFunctionSchemaStmt(Node *stmt);
extern char * DeparseAlterFunctionOwnerStmt(AlterOwnerStmt *stmt); extern char * DeparseAlterFunctionOwnerStmt(Node *stmt);
extern char * DeparseAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt); extern char * DeparseAlterFunctionDependsStmt(Node *stmt);
extern void QualifyAlterFunctionStmt(AlterFunctionStmt *stmt); extern void QualifyAlterFunctionStmt(Node *stmt);
extern void QualifyRenameFunctionStmt(RenameStmt *stmt); extern void QualifyRenameFunctionStmt(Node *stmt);
extern void QualifyAlterFunctionSchemaStmt(AlterObjectSchemaStmt *stmt); extern void QualifyAlterFunctionSchemaStmt(Node *stmt);
extern void QualifyAlterFunctionOwnerStmt(AlterOwnerStmt *stmt); extern void QualifyAlterFunctionOwnerStmt(Node *stmt);
extern void QualifyAlterFunctionDependsStmt(AlterObjectDependsStmt *stmt); extern void QualifyAlterFunctionDependsStmt(Node *stmt);
/* forward declarations for deparse_role_stmts.c */ /* forward declarations for deparse_role_stmts.c */
extern char * DeparseAlterRoleStmt(AlterRoleStmt *stmt); extern char * DeparseAlterRoleStmt(Node *stmt);
/* forward declarations for deparse_extension_stmts.c */ /* forward declarations for deparse_extension_stmts.c */
extern Value * GetExtensionOption(List *extensionOptions, const extern Value * GetExtensionOption(List *extensionOptions,
char *defname); const char *defname);
extern char * DeparseCreateExtensionStmt(CreateExtensionStmt *stmt); extern char * DeparseCreateExtensionStmt(Node *stmt);
extern char * DeparseDropExtensionStmt(DropStmt *stmt); extern char * DeparseDropExtensionStmt(Node *stmt);
extern char * DeparseAlterExtensionSchemaStmt( extern char * DeparseAlterExtensionSchemaStmt(Node *stmt);
AlterObjectSchemaStmt *alterExtensionSchemaStmt); extern char * DeparseAlterExtensionStmt(Node *stmt);
extern char * DeparseAlterExtensionStmt(AlterExtensionStmt *alterExtensionStmt);
#endif /* CITUS_DEPARSER_H */ #endif /* CITUS_DEPARSER_H */

View File

@ -38,8 +38,8 @@ typedef struct DeferredErrorMessage
DeferredErrorInternal(code, message, detail, hint, __FILE__, __LINE__, \ DeferredErrorInternal(code, message, detail, hint, __FILE__, __LINE__, \
PG_FUNCNAME_MACRO) PG_FUNCNAME_MACRO)
DeferredErrorMessage * DeferredErrorInternal(int code, const char *message, const DeferredErrorMessage * DeferredErrorInternal(int code, const char *message,
char *detail, const char *hint, const char *detail, const char *hint,
const char *filename, int linenumber, const const char *filename, int linenumber, const
char *functionname); char *functionname);

View File

@ -137,7 +137,7 @@ extern void CreateDistributedTable(Oid relationId, Var *distributionColumn,
bool viaDeprecatedAPI); bool viaDeprecatedAPI);
extern void CreateTruncateTrigger(Oid relationId); extern void CreateTruncateTrigger(Oid relationId);
extern void EnsureDependenciesExistsOnAllNodes(const ObjectAddress *target); extern void EnsureDependenciesExistOnAllNodes(const ObjectAddress *target);
extern bool ShouldPropagate(void); extern bool ShouldPropagate(void);
extern bool ShouldPropagateObject(const ObjectAddress *address); extern bool ShouldPropagateObject(const ObjectAddress *address);
extern void ReplicateAllDependenciesToNode(const char *nodeName, int nodePort); extern void ReplicateAllDependenciesToNode(const char *nodeName, int nodePort);

View File

@ -42,8 +42,8 @@ extern ShardInterval * LowestShardIntervalById(List *shardIntervalList);
extern int CompareShardIntervals(const void *leftElement, const void *rightElement, extern int CompareShardIntervals(const void *leftElement, const void *rightElement,
SortShardIntervalContext *sortContext); SortShardIntervalContext *sortContext);
extern int CompareShardIntervalsById(const void *leftElement, const void *rightElement); extern int CompareShardIntervalsById(const void *leftElement, const void *rightElement);
extern int CompareShardPlacementsByShardId(const void *leftElement, const extern int CompareShardPlacementsByShardId(const void *leftElement,
void *rightElement); const void *rightElement);
extern int CompareRelationShards(const void *leftElement, extern int CompareRelationShards(const void *leftElement,
const void *rightElement); const void *rightElement);
extern int ShardIndex(ShardInterval *shardInterval); extern int ShardIndex(ShardInterval *shardInterval);

View File

@ -32,9 +32,8 @@ typedef enum TargetWorkerSet
extern List * GetWorkerTransactions(void); extern List * GetWorkerTransactions(void);
extern List * TargetWorkerSetNodeList(TargetWorkerSet targetWorkerSet, LOCKMODE lockMode); extern List * TargetWorkerSetNodeList(TargetWorkerSet targetWorkerSet, LOCKMODE lockMode);
extern void SendCommandToWorker(char *nodeName, int32 nodePort, const char *command); extern void SendCommandToWorker(char *nodeName, int32 nodePort, const char *command);
extern void SendCommandToWorkersAsUser(TargetWorkerSet targetWorkerSet, const extern void SendCommandToWorkersAsUser(TargetWorkerSet targetWorkerSet,
char *nodeUser, const char *nodeUser, const char *command);
const char *command);
extern void SendCommandToWorkerAsUser(char *nodeName, int32 nodePort, extern void SendCommandToWorkerAsUser(char *nodeName, int32 nodePort,
const char *nodeUser, const char *command); const char *nodeUser, const char *command);
extern void SendCommandToWorkersWithMetadata(const char *command); extern void SendCommandToWorkersWithMetadata(const char *command);