mirror of https://github.com/citusdata/citus.git
Merge remote-tracking branch 'origin' into users/saawasek/non_blocking_split_integrated
commit
15014f405f
|
@ -6,7 +6,7 @@ orbs:
|
|||
parameters:
|
||||
image_suffix:
|
||||
type: string
|
||||
default: '-vabaecad'
|
||||
default: '-v5579d00'
|
||||
pg13_version:
|
||||
type: string
|
||||
default: '13.4'
|
||||
|
|
|
@ -26,9 +26,6 @@ configure -whitespace
|
|||
|
||||
# except these exceptions...
|
||||
src/backend/distributed/utils/citus_outfuncs.c -citus-style
|
||||
src/backend/distributed/utils/pg11_snprintf.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_11.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_12.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_13.c -citus-style
|
||||
src/backend/distributed/deparser/ruleutils_14.c -citus-style
|
||||
src/backend/distributed/commands/index_pg_source.c -citus-style
|
||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,3 +1,28 @@
|
|||
### citus v11.0.5 (August 1, 2022) ###
|
||||
|
||||
* Avoids possible information leakage about existing users
|
||||
|
||||
* Allows using `WITH HOLD` cursors with parameters
|
||||
|
||||
* Fixes a bug that could cause failures in `INSERT INTO .. SELECT`
|
||||
|
||||
* Fixes a bug that prevents pushing down `IN` expressions when using columnar
|
||||
custom scan
|
||||
|
||||
* Fixes a concurrency bug between creating a co-located distributed table and
|
||||
shard moves
|
||||
|
||||
* Fixes a crash that can happen due to catalog read in `shmem_exit`
|
||||
|
||||
* Fixes an unexpected error caused by constraints when moving shards
|
||||
|
||||
* Fixes an unexpected error for foreign tables when upgrading Postgres
|
||||
|
||||
* Prevents adding local table into metadata if there is a view with circular
|
||||
dependencies on it
|
||||
|
||||
* Reduces memory consumption of index name fix for partitioned tables
|
||||
|
||||
### citus v11.0.4 (July 13, 2022) ###
|
||||
|
||||
* Fixes a bug that prevents promoting read-replicas as primaries
|
||||
|
|
|
@ -17,13 +17,7 @@ DATA = $(columnar_sql_files) \
|
|||
|
||||
PG_CPPFLAGS += -I$(libpq_srcdir) -I$(safestringlib_srcdir)/include
|
||||
|
||||
ifdef USE_PGXS
|
||||
PG_CONFIG = pg_config
|
||||
PGXS := $(shell $(PG_CONFIG) --pgxs)
|
||||
include $(PGXS)
|
||||
else
|
||||
include $(citus_top_builddir)/Makefile.global
|
||||
|
||||
.PHONY: install-all
|
||||
install-all: install
|
||||
endif
|
||||
|
|
|
@ -824,6 +824,18 @@ ExtractPushdownClause(PlannerInfo *root, RelOptInfo *rel, Node *node)
|
|||
}
|
||||
}
|
||||
|
||||
if (IsA(node, ScalarArrayOpExpr))
|
||||
{
|
||||
if (!contain_volatile_functions(node))
|
||||
{
|
||||
return (Expr *) node;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsA(node, OpExpr) || list_length(((OpExpr *) node)->args) != 2)
|
||||
{
|
||||
ereport(ColumnarPlannerDebugLevel,
|
||||
|
|
|
@ -122,7 +122,7 @@ static void ColumnarProcessUtility(PlannedStmt *pstmt,
|
|||
ParamListInfo params,
|
||||
struct QueryEnvironment *queryEnv,
|
||||
DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag);
|
||||
QueryCompletion *completionTag);
|
||||
static bool ConditionalLockRelationWithTimeout(Relation rel, LOCKMODE lockMode,
|
||||
int timeout, int retryInterval);
|
||||
static List * NeededColumnsList(TupleDesc tupdesc, Bitmapset *attr_needed);
|
||||
|
@ -2239,7 +2239,7 @@ ColumnarProcessUtility(PlannedStmt *pstmt,
|
|||
ParamListInfo params,
|
||||
struct QueryEnvironment *queryEnv,
|
||||
DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag)
|
||||
QueryCompletion *completionTag)
|
||||
{
|
||||
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||
if (readOnlyTree)
|
||||
|
@ -2956,7 +2956,7 @@ AvailableExtensionVersionColumnar(void)
|
|||
/* pg_available_extensions returns result set containing all available extensions */
|
||||
(*pg_available_extensions)(fcinfo);
|
||||
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlotCompat(
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlot(
|
||||
extensionsResultSet->setDesc,
|
||||
&TTSOpsMinimalTuple);
|
||||
bool hasTuple = tuplestore_gettupleslot(extensionsResultSet->setResult, goForward,
|
||||
|
|
|
@ -168,8 +168,8 @@ CallDistributedProcedureRemotely(CallStmt *callStmt, DestReceiver *dest)
|
|||
{
|
||||
Tuplestorestate *tupleStore = tuplestore_begin_heap(true, false, work_mem);
|
||||
TupleDesc tupleDesc = CallStmtResultDesc(callStmt);
|
||||
TupleTableSlot *slot = MakeSingleTupleTableSlotCompat(tupleDesc,
|
||||
&TTSOpsMinimalTuple);
|
||||
TupleTableSlot *slot = MakeSingleTupleTableSlot(tupleDesc,
|
||||
&TTSOpsMinimalTuple);
|
||||
bool expectResults = true;
|
||||
Task *task = CitusMakeNode(Task);
|
||||
|
||||
|
|
|
@ -39,9 +39,12 @@ PreprocessClusterStmt(Node *node, const char *clusterCommand,
|
|||
|
||||
if (clusterStmt->relation == NULL)
|
||||
{
|
||||
ereport(WARNING, (errmsg("not propagating CLUSTER command to worker nodes"),
|
||||
errhint("Provide a specific table in order to CLUSTER "
|
||||
"distributed tables.")));
|
||||
if (EnableUnsupportedFeatureMessages)
|
||||
{
|
||||
ereport(WARNING, (errmsg("not propagating CLUSTER command to worker nodes"),
|
||||
errhint("Provide a specific table in order to CLUSTER "
|
||||
"distributed tables.")));
|
||||
}
|
||||
|
||||
return NIL;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ CreateCollationDDLInternal(Oid collationId, Oid *collowner, char **quotedCollati
|
|||
"CREATE COLLATION %s (provider = '%s'",
|
||||
*quotedCollationName, providerString);
|
||||
|
||||
if (strcmp(collcollate, collctype))
|
||||
if (strcmp(collcollate, collctype) == 0)
|
||||
{
|
||||
appendStringInfo(&collationNameDef,
|
||||
", locale = %s",
|
||||
|
@ -170,7 +170,7 @@ CreateCollationDDLsIdempotent(Oid collationId)
|
|||
|
||||
|
||||
List *
|
||||
AlterCollationOwnerObjectAddress(Node *node, bool missing_ok)
|
||||
AlterCollationOwnerObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
Relation relation;
|
||||
|
@ -192,7 +192,7 @@ AlterCollationOwnerObjectAddress(Node *node, bool missing_ok)
|
|||
* of the RenameStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
RenameCollationStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameCollationStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_COLLATION);
|
||||
|
@ -215,7 +215,7 @@ RenameCollationStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* schemas.
|
||||
*/
|
||||
List *
|
||||
AlterCollationSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterCollationSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_COLLATION);
|
||||
|
@ -297,7 +297,7 @@ GenerateBackupNameForCollationCollision(const ObjectAddress *address)
|
|||
|
||||
|
||||
List *
|
||||
DefineCollationStmtObjectAddress(Node *node, bool missing_ok)
|
||||
DefineCollationStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DefineStmt *stmt = castNode(DefineStmt, node);
|
||||
Assert(stmt->kind == OBJECT_COLLATION);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "postgres.h"
|
||||
|
||||
#include "catalog/objectaddress.h"
|
||||
#include "catalog/pg_ts_config.h"
|
||||
#include "catalog/pg_ts_dict.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "tcop/utility.h"
|
||||
|
||||
|
@ -61,7 +63,7 @@ PostprocessCreateDistributedObjectFromCatalogStmt(Node *stmt, const char *queryS
|
|||
return NIL;
|
||||
}
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree(stmt, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree(stmt, false, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -74,7 +76,11 @@ PostprocessCreateDistributedObjectFromCatalogStmt(Node *stmt, const char *queryS
|
|||
addresses);
|
||||
if (depError != NULL)
|
||||
{
|
||||
RaiseDeferredError(depError, WARNING);
|
||||
if (EnableUnsupportedFeatureMessages)
|
||||
{
|
||||
RaiseDeferredError(depError, WARNING);
|
||||
}
|
||||
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
@ -115,7 +121,7 @@ PreprocessAlterDistributedObjectStmt(Node *stmt, const char *queryString,
|
|||
const DistributeObjectOps *ops = GetDistributeObjectOps(stmt);
|
||||
Assert(ops != NULL);
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree(stmt, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree(stmt, false, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -164,7 +170,7 @@ PostprocessAlterDistributedObjectStmt(Node *stmt, const char *queryString)
|
|||
const DistributeObjectOps *ops = GetDistributeObjectOps(stmt);
|
||||
Assert(ops != NULL);
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree(stmt, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree(stmt, false, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -283,3 +289,53 @@ PreprocessDropDistributedObjectStmt(Node *node, const char *queryString,
|
|||
|
||||
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DropTextSearchDictObjectAddress returns list of object addresses in
|
||||
* the drop tsdict statement.
|
||||
*/
|
||||
List *
|
||||
DropTextSearchDictObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DropStmt *stmt = castNode(DropStmt, node);
|
||||
|
||||
List *objectAddresses = NIL;
|
||||
|
||||
List *objNameList = NIL;
|
||||
foreach_ptr(objNameList, stmt->objects)
|
||||
{
|
||||
Oid tsdictOid = get_ts_dict_oid(objNameList, missing_ok);
|
||||
|
||||
ObjectAddress *objectAddress = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*objectAddress, TSDictionaryRelationId, tsdictOid);
|
||||
objectAddresses = lappend(objectAddresses, objectAddress);
|
||||
}
|
||||
|
||||
return objectAddresses;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DropTextSearchConfigObjectAddress returns list of object addresses in
|
||||
* the drop tsconfig statement.
|
||||
*/
|
||||
List *
|
||||
DropTextSearchConfigObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DropStmt *stmt = castNode(DropStmt, node);
|
||||
|
||||
List *objectAddresses = NIL;
|
||||
|
||||
List *objNameList = NIL;
|
||||
foreach_ptr(objNameList, stmt->objects)
|
||||
{
|
||||
Oid tsconfigOid = get_ts_config_oid(objNameList, missing_ok);
|
||||
|
||||
ObjectAddress *objectAddress = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*objectAddress, TSConfigRelationId, tsconfigOid);
|
||||
objectAddresses = lappend(objectAddresses, objectAddress);
|
||||
}
|
||||
|
||||
return objectAddresses;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "distributed/relation_access_tracking.h"
|
||||
#include "distributed/remote_commands.h"
|
||||
#include "distributed/shared_library_init.h"
|
||||
#include "distributed/shard_rebalancer.h"
|
||||
#include "distributed/worker_protocol.h"
|
||||
#include "distributed/worker_shard_visibility.h"
|
||||
#include "distributed/worker_transaction.h"
|
||||
|
@ -850,6 +851,17 @@ CreateHashDistributedTableShards(Oid relationId, int shardCount,
|
|||
|
||||
if (colocatedTableId != InvalidOid)
|
||||
{
|
||||
/*
|
||||
* We currently allow concurrent distribution of colocated tables (which
|
||||
* we probably should not be allowing because of foreign keys /
|
||||
* partitioning etc).
|
||||
*
|
||||
* We also prevent concurrent shard moves / copy / splits) while creating
|
||||
* a colocated table.
|
||||
*/
|
||||
AcquirePlacementColocationLock(colocatedTableId, ShareLock,
|
||||
"colocate distributed table");
|
||||
|
||||
CreateColocatedShards(relationId, colocatedTableId, useExclusiveConnection);
|
||||
}
|
||||
else
|
||||
|
@ -1642,7 +1654,7 @@ CopyLocalDataIntoShards(Oid distributedRelationId)
|
|||
|
||||
/* get the table columns */
|
||||
TupleDesc tupleDescriptor = RelationGetDescr(distributedRelation);
|
||||
TupleTableSlot *slot = CreateTableSlotForRel(distributedRelation);
|
||||
TupleTableSlot *slot = table_slot_create(distributedRelation, NULL);
|
||||
List *columnNameList = TupleDescColumnNameList(tupleDescriptor);
|
||||
|
||||
int partitionColumnIndex = INVALID_PARTITION_COLUMN_INDEX;
|
||||
|
|
|
@ -41,7 +41,7 @@ bool EnableAlterDatabaseOwner = true;
|
|||
* object of the AlterOwnerStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterDatabaseOwnerObjectAddress(Node *node, bool missing_ok)
|
||||
AlterDatabaseOwnerObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_DATABASE);
|
||||
|
|
|
@ -202,12 +202,12 @@ ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
|
|||
|
||||
/*
|
||||
* DeferErrorIfCircularDependencyExists checks whether given object has
|
||||
* circular dependency with itself via existing objects of pg_dist_object.
|
||||
* circular dependency with itself. If so, returns a deferred error.
|
||||
*/
|
||||
DeferredErrorMessage *
|
||||
DeferErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
|
||||
{
|
||||
List *dependencies = GetAllSupportedDependenciesForObject(objectAddress);
|
||||
List *dependencies = GetAllDependenciesForObject(objectAddress);
|
||||
|
||||
ObjectAddress *dependency = NULL;
|
||||
foreach_ptr(dependency, dependencies)
|
||||
|
|
|
@ -23,6 +23,7 @@ static DistributeObjectOps NoDistributeOps = {
|
|||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_NONE,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -32,6 +33,7 @@ static DistributeObjectOps Aggregate_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -41,6 +43,7 @@ static DistributeObjectOps Aggregate_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -50,6 +53,7 @@ static DistributeObjectOps Aggregate_Define = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_AGGREGATE,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = DefineAggregateStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -58,6 +62,7 @@ static DistributeObjectOps Aggregate_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -67,6 +72,7 @@ static DistributeObjectOps Aggregate_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameFunctionStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -76,6 +82,7 @@ static DistributeObjectOps Any_AlterEnum = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterEnumStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -84,6 +91,7 @@ static DistributeObjectOps Any_AlterExtension = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterExtensionUpdateStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterExtensionUpdateStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -92,6 +100,7 @@ static DistributeObjectOps Any_AlterExtensionContents = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterExtensionContentsStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -101,6 +110,7 @@ static DistributeObjectOps Any_AlterForeignServer = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_FOREIGN_SERVER,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterForeignServerStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -109,6 +119,7 @@ static DistributeObjectOps Any_AlterFunction = {
|
|||
.qualify = QualifyAlterFunctionStmt,
|
||||
.preprocess = PreprocessAlterFunctionStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -117,6 +128,7 @@ static DistributeObjectOps Any_AlterPolicy = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterPolicyStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -125,6 +137,7 @@ static DistributeObjectOps Any_AlterRole = {
|
|||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.postprocess = PostprocessAlterRoleStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterRoleStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -133,6 +146,7 @@ static DistributeObjectOps Any_AlterRoleSet = {
|
|||
.qualify = QualifyAlterRoleSetStmt,
|
||||
.preprocess = PreprocessAlterRoleSetStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterRoleSetStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -141,6 +155,7 @@ static DistributeObjectOps Any_AlterTableMoveAll = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterTableMoveAllStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -149,6 +164,7 @@ static DistributeObjectOps Any_Cluster = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessClusterStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_NONE,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -158,6 +174,7 @@ static DistributeObjectOps Any_CompositeType = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.featureFlag = &EnableCreateTypePropagation,
|
||||
.address = CompositeTypeStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
|
@ -168,6 +185,7 @@ static DistributeObjectOps Any_CreateDomain = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_DOMAIN,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateDomainStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -177,6 +195,7 @@ static DistributeObjectOps Any_CreateEnum = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.featureFlag = &EnableCreateTypePropagation,
|
||||
.address = CreateEnumStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
|
@ -186,6 +205,7 @@ static DistributeObjectOps Any_CreateExtension = {
|
|||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateExtensionStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateExtensionStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -194,6 +214,7 @@ static DistributeObjectOps Any_CreateFunction = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessCreateFunctionStmt,
|
||||
.postprocess = PostprocessCreateFunctionStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateFunctionStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -202,6 +223,7 @@ static DistributeObjectOps Any_View = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessViewStmt,
|
||||
.postprocess = PostprocessViewStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = ViewStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -210,6 +232,7 @@ static DistributeObjectOps Any_CreatePolicy = {
|
|||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreatePolicyStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -218,6 +241,7 @@ static DistributeObjectOps Any_CreateRole = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessCreateRoleStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateRoleStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -226,6 +250,7 @@ static DistributeObjectOps Any_DropRole = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropRoleStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -235,6 +260,7 @@ static DistributeObjectOps Any_CreateForeignServer = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_FOREIGN_SERVER,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateForeignServerStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -243,6 +269,7 @@ static DistributeObjectOps Any_CreateSchema = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessCreateSchemaStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateSchemaStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -251,6 +278,7 @@ static DistributeObjectOps Any_CreateStatistics = {
|
|||
.qualify = QualifyCreateStatisticsStmt,
|
||||
.preprocess = PreprocessCreateStatisticsStmt,
|
||||
.postprocess = PostprocessCreateStatisticsStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateStatisticsStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -259,6 +287,7 @@ static DistributeObjectOps Any_CreateTrigger = {
|
|||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateTriggerStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateTriggerStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -267,6 +296,7 @@ static DistributeObjectOps Any_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -275,6 +305,7 @@ static DistributeObjectOps Any_GrantRole = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantRoleStmt,
|
||||
.postprocess = PostprocessGrantRoleStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -283,6 +314,7 @@ static DistributeObjectOps Any_Index = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessIndexStmt,
|
||||
.postprocess = PostprocessIndexStmt,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -291,7 +323,8 @@ static DistributeObjectOps Any_Reindex = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessReindexStmt,
|
||||
.postprocess = NULL,
|
||||
.address = NULL,
|
||||
.operationType = DIST_OPS_NONE,
|
||||
.address = ReindexStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
static DistributeObjectOps Any_Rename = {
|
||||
|
@ -299,6 +332,7 @@ static DistributeObjectOps Any_Rename = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessRenameStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -307,6 +341,7 @@ static DistributeObjectOps Attribute_Rename = {
|
|||
.qualify = QualifyRenameAttributeStmt,
|
||||
.preprocess = PreprocessRenameAttributeStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameAttributeStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -316,6 +351,7 @@ static DistributeObjectOps Collation_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_COLLATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterCollationSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -325,6 +361,7 @@ static DistributeObjectOps Collation_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_COLLATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterCollationOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -334,6 +371,7 @@ static DistributeObjectOps Collation_Define = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_COLLATION,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = DefineCollationStmtObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -342,6 +380,7 @@ static DistributeObjectOps Collation_Drop = {
|
|||
.qualify = QualifyDropCollationStmt,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -351,6 +390,7 @@ static DistributeObjectOps Collation_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_COLLATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameCollationStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -360,6 +400,7 @@ static DistributeObjectOps Database_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_DATABASE,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.featureFlag = &EnableAlterDatabaseOwner,
|
||||
.address = AlterDatabaseOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
|
@ -370,6 +411,7 @@ static DistributeObjectOps Domain_Alter = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_DOMAIN,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterDomainStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -379,6 +421,7 @@ static DistributeObjectOps Domain_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_DOMAIN,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTypeSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -388,6 +431,7 @@ static DistributeObjectOps Domain_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_DOMAIN,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterDomainOwnerStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -396,6 +440,7 @@ static DistributeObjectOps Domain_Drop = {
|
|||
.qualify = QualifyDropDomainStmt,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -405,6 +450,7 @@ static DistributeObjectOps Domain_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_DOMAIN,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameDomainStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -415,6 +461,7 @@ static DistributeObjectOps Domain_RenameConstraint = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_DOMAIN,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = DomainRenameConstraintStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -423,6 +470,7 @@ static DistributeObjectOps Extension_AlterObjectSchema = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterExtensionSchemaStmt,
|
||||
.postprocess = PostprocessAlterExtensionSchemaStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterExtensionSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -431,6 +479,7 @@ static DistributeObjectOps Extension_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropExtensionStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -439,6 +488,7 @@ static DistributeObjectOps FDW_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantOnFDWStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -447,6 +497,7 @@ static DistributeObjectOps ForeignServer_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -455,6 +506,7 @@ static DistributeObjectOps ForeignServer_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantOnForeignServerStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -464,6 +516,7 @@ static DistributeObjectOps ForeignServer_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_FOREIGN_SERVER,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameForeignServerStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -473,6 +526,7 @@ static DistributeObjectOps ForeignServer_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FOREIGN_SERVER,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterForeignServerOwnerStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -481,6 +535,7 @@ static DistributeObjectOps ForeignTable_AlterTable = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterTableStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -489,6 +544,7 @@ static DistributeObjectOps Function_AlterObjectDepends = {
|
|||
.qualify = QualifyAlterFunctionDependsStmt,
|
||||
.preprocess = PreprocessAlterFunctionDependsStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionDependsStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -498,6 +554,7 @@ static DistributeObjectOps Function_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -507,6 +564,7 @@ static DistributeObjectOps Function_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -515,6 +573,7 @@ static DistributeObjectOps Function_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -523,6 +582,7 @@ static DistributeObjectOps Function_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantOnFunctionStmt,
|
||||
.postprocess = PostprocessGrantOnFunctionStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -531,7 +591,8 @@ static DistributeObjectOps View_Drop = {
|
|||
.qualify = QualifyDropViewStmt,
|
||||
.preprocess = PreprocessDropViewStmt,
|
||||
.postprocess = NULL,
|
||||
.address = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = DropViewStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
static DistributeObjectOps Function_Rename = {
|
||||
|
@ -540,6 +601,7 @@ static DistributeObjectOps Function_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameFunctionStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -548,6 +610,7 @@ static DistributeObjectOps Index_AlterTable = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterTableStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -556,6 +619,7 @@ static DistributeObjectOps Index_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropIndexStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -564,6 +628,7 @@ static DistributeObjectOps Policy_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropPolicyStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -572,6 +637,7 @@ static DistributeObjectOps Procedure_AlterObjectDepends = {
|
|||
.qualify = QualifyAlterFunctionDependsStmt,
|
||||
.preprocess = PreprocessAlterFunctionDependsStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionDependsStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -581,6 +647,7 @@ static DistributeObjectOps Procedure_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -590,6 +657,7 @@ static DistributeObjectOps Procedure_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -598,6 +666,7 @@ static DistributeObjectOps Procedure_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -606,6 +675,7 @@ static DistributeObjectOps Procedure_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantOnFunctionStmt,
|
||||
.postprocess = PostprocessGrantOnFunctionStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -615,6 +685,7 @@ static DistributeObjectOps Procedure_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameFunctionStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -623,6 +694,7 @@ static DistributeObjectOps Routine_AlterObjectDepends = {
|
|||
.qualify = QualifyAlterFunctionDependsStmt,
|
||||
.preprocess = PreprocessAlterFunctionDependsStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionDependsStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -631,6 +703,7 @@ static DistributeObjectOps Sequence_Alter = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterSequenceStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterSequenceStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -639,6 +712,7 @@ static DistributeObjectOps Sequence_AlterObjectSchema = {
|
|||
.qualify = QualifyAlterSequenceSchemaStmt,
|
||||
.preprocess = PreprocessAlterSequenceSchemaStmt,
|
||||
.postprocess = PostprocessAlterSequenceSchemaStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterSequenceSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -647,6 +721,7 @@ static DistributeObjectOps Sequence_AlterOwner = {
|
|||
.qualify = QualifyAlterSequenceOwnerStmt,
|
||||
.preprocess = PreprocessAlterSequenceOwnerStmt,
|
||||
.postprocess = PostprocessAlterSequenceOwnerStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterSequenceOwnerStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -655,7 +730,8 @@ static DistributeObjectOps Sequence_Drop = {
|
|||
.qualify = QualifyDropSequenceStmt,
|
||||
.preprocess = PreprocessDropSequenceStmt,
|
||||
.postprocess = NULL,
|
||||
.address = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = SequenceDropStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
static DistributeObjectOps Sequence_Grant = {
|
||||
|
@ -663,6 +739,7 @@ static DistributeObjectOps Sequence_Grant = {
|
|||
.qualify = QualifyGrantOnSequenceStmt,
|
||||
.preprocess = PreprocessGrantOnSequenceStmt,
|
||||
.postprocess = PostprocessGrantOnSequenceStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -671,6 +748,7 @@ static DistributeObjectOps Sequence_Rename = {
|
|||
.qualify = QualifyRenameSequenceStmt,
|
||||
.preprocess = PreprocessRenameSequenceStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameSequenceStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -680,6 +758,7 @@ static DistributeObjectOps TextSearchConfig_Alter = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TSCONFIGURATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTextSearchConfigurationStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -689,6 +768,7 @@ static DistributeObjectOps TextSearchConfig_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_TSCONFIGURATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTextSearchConfigurationSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -698,6 +778,7 @@ static DistributeObjectOps TextSearchConfig_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_TSCONFIGURATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTextSearchConfigurationOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -707,6 +788,7 @@ static DistributeObjectOps TextSearchConfig_Comment = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TSCONFIGURATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = TextSearchConfigurationCommentObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -716,6 +798,7 @@ static DistributeObjectOps TextSearchConfig_Define = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_TSCONFIGURATION,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateTextSearchConfigurationObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -724,7 +807,8 @@ static DistributeObjectOps TextSearchConfig_Drop = {
|
|||
.qualify = QualifyDropTextSearchConfigurationStmt,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.address = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = DropTextSearchConfigObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
static DistributeObjectOps TextSearchConfig_Rename = {
|
||||
|
@ -733,6 +817,7 @@ static DistributeObjectOps TextSearchConfig_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TSCONFIGURATION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameTextSearchConfigurationStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -742,6 +827,7 @@ static DistributeObjectOps TextSearchDict_Alter = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TSDICTIONARY,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTextSearchDictionaryStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -751,6 +837,7 @@ static DistributeObjectOps TextSearchDict_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_TSDICTIONARY,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTextSearchDictionarySchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -760,6 +847,7 @@ static DistributeObjectOps TextSearchDict_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_TSDICTIONARY,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTextSearchDictOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -769,6 +857,7 @@ static DistributeObjectOps TextSearchDict_Comment = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TSDICTIONARY,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = TextSearchDictCommentObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -778,6 +867,7 @@ static DistributeObjectOps TextSearchDict_Define = {
|
|||
.preprocess = NULL,
|
||||
.postprocess = PostprocessCreateDistributedObjectFromCatalogStmt,
|
||||
.objectType = OBJECT_TSDICTIONARY,
|
||||
.operationType = DIST_OPS_CREATE,
|
||||
.address = CreateTextSearchDictObjectAddress,
|
||||
.markDistributed = true,
|
||||
};
|
||||
|
@ -786,7 +876,8 @@ static DistributeObjectOps TextSearchDict_Drop = {
|
|||
.qualify = QualifyDropTextSearchDictionaryStmt,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.address = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = DropTextSearchDictObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
static DistributeObjectOps TextSearchDict_Rename = {
|
||||
|
@ -795,6 +886,7 @@ static DistributeObjectOps TextSearchDict_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TSDICTIONARY,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameTextSearchDictionaryStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -803,6 +895,7 @@ static DistributeObjectOps Trigger_AlterObjectDepends = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterTriggerDependsStmt,
|
||||
.postprocess = PostprocessAlterTriggerDependsStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -812,6 +905,7 @@ static DistributeObjectOps Routine_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -821,6 +915,7 @@ static DistributeObjectOps Routine_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterFunctionOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -829,6 +924,7 @@ static DistributeObjectOps Routine_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -837,6 +933,7 @@ static DistributeObjectOps Routine_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantOnFunctionStmt,
|
||||
.postprocess = PostprocessGrantOnFunctionStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -846,6 +943,7 @@ static DistributeObjectOps Routine_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_FUNCTION,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameFunctionStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -854,6 +952,7 @@ static DistributeObjectOps Schema_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropSchemaStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -862,6 +961,7 @@ static DistributeObjectOps Schema_Grant = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessGrantOnSchemaStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -871,6 +971,7 @@ static DistributeObjectOps Schema_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_SCHEMA,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterSchemaRenameStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -879,6 +980,7 @@ static DistributeObjectOps Statistics_Alter = {
|
|||
.qualify = QualifyAlterStatisticsStmt,
|
||||
.preprocess = PreprocessAlterStatisticsStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -887,6 +989,7 @@ static DistributeObjectOps Statistics_AlterObjectSchema = {
|
|||
.qualify = QualifyAlterStatisticsSchemaStmt,
|
||||
.preprocess = PreprocessAlterStatisticsSchemaStmt,
|
||||
.postprocess = PostprocessAlterStatisticsSchemaStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterStatisticsSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -894,6 +997,7 @@ static DistributeObjectOps Statistics_AlterOwner = {
|
|||
.deparse = DeparseAlterStatisticsOwnerStmt,
|
||||
.qualify = QualifyAlterStatisticsOwnerStmt,
|
||||
.preprocess = PreprocessAlterStatisticsOwnerStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.postprocess = PostprocessAlterStatisticsOwnerStmt,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
|
@ -903,7 +1007,8 @@ static DistributeObjectOps Statistics_Drop = {
|
|||
.qualify = QualifyDropStatisticsStmt,
|
||||
.preprocess = PreprocessDropStatisticsStmt,
|
||||
.postprocess = NULL,
|
||||
.address = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = DropStatisticsObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
static DistributeObjectOps Statistics_Rename = {
|
||||
|
@ -911,6 +1016,7 @@ static DistributeObjectOps Statistics_Rename = {
|
|||
.qualify = QualifyAlterStatisticsRenameStmt,
|
||||
.preprocess = PreprocessAlterStatisticsRenameStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -919,6 +1025,7 @@ static DistributeObjectOps Table_AlterTable = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessAlterTableStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -927,6 +1034,7 @@ static DistributeObjectOps Table_AlterObjectSchema = {
|
|||
.qualify = QualifyAlterTableSchemaStmt,
|
||||
.preprocess = PreprocessAlterTableSchemaStmt,
|
||||
.postprocess = PostprocessAlterTableSchemaStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTableSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -935,6 +1043,7 @@ static DistributeObjectOps Table_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropTableStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -944,6 +1053,7 @@ static DistributeObjectOps Type_AlterObjectSchema = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTypeSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -960,6 +1070,7 @@ static DistributeObjectOps View_AlterObjectSchema = {
|
|||
.qualify = QualifyAlterViewSchemaStmt,
|
||||
.preprocess = PreprocessAlterViewSchemaStmt,
|
||||
.postprocess = PostprocessAlterViewSchemaStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterViewSchemaStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -969,6 +1080,7 @@ static DistributeObjectOps Type_AlterOwner = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = PostprocessAlterDistributedObjectStmt,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTypeOwnerObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -978,6 +1090,7 @@ static DistributeObjectOps Type_AlterTable = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterTypeStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -994,6 +1107,7 @@ static DistributeObjectOps View_AlterView = {
|
|||
.qualify = QualifyAlterViewStmt,
|
||||
.preprocess = PreprocessAlterViewStmt,
|
||||
.postprocess = PostprocessAlterViewStmt,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = AlterViewStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -1002,6 +1116,7 @@ static DistributeObjectOps Type_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -1010,6 +1125,7 @@ static DistributeObjectOps Trigger_Drop = {
|
|||
.qualify = NULL,
|
||||
.preprocess = PreprocessDropTriggerStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_DROP,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -1019,6 +1135,7 @@ static DistributeObjectOps Type_Rename = {
|
|||
.preprocess = PreprocessAlterDistributedObjectStmt,
|
||||
.postprocess = NULL,
|
||||
.objectType = OBJECT_TYPE,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameTypeStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -1027,6 +1144,7 @@ static DistributeObjectOps Vacuum_Analyze = {
|
|||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.postprocess = PostprocessVacuumStmt,
|
||||
.operationType = DIST_OPS_NONE,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -1042,6 +1160,7 @@ static DistributeObjectOps View_Rename = {
|
|||
.qualify = QualifyRenameViewStmt,
|
||||
.preprocess = PreprocessRenameViewStmt,
|
||||
.postprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.address = RenameViewStmtObjectAddress,
|
||||
.markDistributed = false,
|
||||
};
|
||||
|
@ -1049,6 +1168,7 @@ static DistributeObjectOps Trigger_Rename = {
|
|||
.deparse = NULL,
|
||||
.qualify = NULL,
|
||||
.preprocess = NULL,
|
||||
.operationType = DIST_OPS_ALTER,
|
||||
.postprocess = PostprocessAlterTriggerRenameStmt,
|
||||
.address = NULL,
|
||||
.markDistributed = false,
|
||||
|
|
|
@ -230,7 +230,7 @@ MakeCollateClauseFromOid(Oid collationOid)
|
|||
* the domain cannot be found in the local catalog.
|
||||
*/
|
||||
List *
|
||||
CreateDomainStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateDomainStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateDomainStmt *stmt = castNode(CreateDomainStmt, node);
|
||||
|
||||
|
@ -249,7 +249,7 @@ CreateDomainStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* found.
|
||||
*/
|
||||
List *
|
||||
AlterDomainStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterDomainStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterDomainStmt *stmt = castNode(AlterDomainStmt, node);
|
||||
|
||||
|
@ -264,7 +264,7 @@ AlterDomainStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* error if the domain cannot be found.
|
||||
*/
|
||||
List *
|
||||
DomainRenameConstraintStmtObjectAddress(Node *node, bool missing_ok)
|
||||
DomainRenameConstraintStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
|
||||
|
@ -279,7 +279,7 @@ DomainRenameConstraintStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* cannot be found.
|
||||
*/
|
||||
List *
|
||||
AlterDomainOwnerStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterDomainOwnerStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_DOMAIN);
|
||||
|
@ -295,7 +295,7 @@ AlterDomainOwnerStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* found.
|
||||
*/
|
||||
List *
|
||||
RenameDomainStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameDomainStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_DOMAIN);
|
||||
|
|
|
@ -181,7 +181,7 @@ PostprocessCreateExtensionStmt(Node *node, const char *queryString)
|
|||
(void *) createExtensionStmtSql,
|
||||
ENABLE_DDL_PROPAGATION);
|
||||
|
||||
List *extensionAddresses = GetObjectAddressListFromParseTree(node, false);
|
||||
List *extensionAddresses = GetObjectAddressListFromParseTree(node, false, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(extensionAddresses) == 1);
|
||||
|
@ -413,7 +413,7 @@ PreprocessAlterExtensionSchemaStmt(Node *node, const char *queryString,
|
|||
List *
|
||||
PostprocessAlterExtensionSchemaStmt(Node *node, const char *queryString)
|
||||
{
|
||||
List *extensionAddresses = GetObjectAddressListFromParseTree(node, false);
|
||||
List *extensionAddresses = GetObjectAddressListFromParseTree(node, false, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(extensionAddresses) == 1);
|
||||
|
@ -1134,7 +1134,7 @@ GetDependentFDWsToExtension(Oid extensionId)
|
|||
* the subject of the AlterObjectSchemaStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterExtensionSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterExtensionSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_EXTENSION);
|
||||
|
@ -1162,7 +1162,7 @@ AlterExtensionSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* the subject of the AlterExtensionStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterExtensionUpdateStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterExtensionUpdateStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterExtensionStmt *stmt = castNode(AlterExtensionStmt, node);
|
||||
const char *extensionName = stmt->extname;
|
||||
|
|
|
@ -42,7 +42,7 @@ static List * GetObjectAddressByServerName(char *serverName, bool missing_ok);
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
CreateForeignServerStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateForeignServerStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateForeignServerStmt *stmt = castNode(CreateForeignServerStmt, node);
|
||||
|
||||
|
@ -59,7 +59,7 @@ CreateForeignServerStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
AlterForeignServerStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterForeignServerStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterForeignServerStmt *stmt = castNode(AlterForeignServerStmt, node);
|
||||
|
||||
|
@ -124,7 +124,7 @@ PreprocessGrantOnForeignServerStmt(Node *node, const char *queryString,
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
RenameForeignServerStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameForeignServerStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_FOREIGN_SERVER);
|
||||
|
@ -142,7 +142,7 @@ RenameForeignServerStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
AlterForeignServerOwnerStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterForeignServerOwnerStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
char *serverName = strVal(stmt->object);
|
||||
|
@ -269,7 +269,7 @@ static List *
|
|||
GetObjectAddressByServerName(char *serverName, bool missing_ok)
|
||||
{
|
||||
ForeignServer *server = GetForeignServerByName(serverName, missing_ok);
|
||||
Oid serverOid = server->serverid;
|
||||
Oid serverOid = (server) ? server->serverid : InvalidOid;
|
||||
ObjectAddress *address = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*address, ForeignServerRelationId, serverOid);
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/extension.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/citus_ruleutils.h"
|
||||
#include "distributed/citus_safe_lib.h"
|
||||
#include "distributed/colocation_utils.h"
|
||||
|
@ -1371,7 +1372,8 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString)
|
|||
return NIL;
|
||||
}
|
||||
|
||||
List *functionAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false);
|
||||
List *functionAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false,
|
||||
true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(functionAddresses) == 1);
|
||||
|
@ -1387,7 +1389,11 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString)
|
|||
|
||||
if (errMsg != NULL)
|
||||
{
|
||||
RaiseDeferredError(errMsg, WARNING);
|
||||
if (EnableUnsupportedFeatureMessages)
|
||||
{
|
||||
RaiseDeferredError(errMsg, WARNING);
|
||||
}
|
||||
|
||||
return NIL;
|
||||
}
|
||||
|
||||
|
@ -1411,7 +1417,7 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString)
|
|||
* normal postgres error for unfound functions.
|
||||
*/
|
||||
List *
|
||||
CreateFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateFunctionStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateFunctionStmt *stmt = castNode(CreateFunctionStmt, node);
|
||||
ObjectType objectType = OBJECT_FUNCTION;
|
||||
|
@ -1434,7 +1440,17 @@ CreateFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
|||
}
|
||||
}
|
||||
|
||||
return FunctionToObjectAddress(objectType, objectWithArgs, missing_ok);
|
||||
int OldClientMinMessage = client_min_messages;
|
||||
|
||||
/* suppress NOTICE if running under pg vanilla tests */
|
||||
SetLocalClientMinMessagesIfRunningPGTests(WARNING);
|
||||
|
||||
List *funcAddresses = FunctionToObjectAddress(objectType, objectWithArgs, missing_ok);
|
||||
|
||||
/* set it back */
|
||||
SetLocalClientMinMessagesIfRunningPGTests(OldClientMinMessage);
|
||||
|
||||
return funcAddresses;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1446,7 +1462,7 @@ CreateFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* objectId in the address can be invalid if missing_ok was set to true.
|
||||
*/
|
||||
List *
|
||||
DefineAggregateStmtObjectAddress(Node *node, bool missing_ok)
|
||||
DefineAggregateStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DefineStmt *stmt = castNode(DefineStmt, node);
|
||||
|
||||
|
@ -1499,7 +1515,7 @@ PreprocessAlterFunctionStmt(Node *node, const char *queryString,
|
|||
AlterFunctionStmt *stmt = castNode(AlterFunctionStmt, node);
|
||||
AssertObjectTypeIsFunctional(stmt->objtype);
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt, false, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -1561,7 +1577,7 @@ PreprocessAlterFunctionDependsStmt(Node *node, const char *queryString,
|
|||
return NIL;
|
||||
}
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt, true);
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt, true, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -1595,7 +1611,7 @@ PreprocessAlterFunctionDependsStmt(Node *node, const char *queryString,
|
|||
* missing_ok is set to false the lookup will raise an error.
|
||||
*/
|
||||
List *
|
||||
AlterFunctionDependsStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterFunctionDependsStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectDependsStmt *stmt = castNode(AlterObjectDependsStmt, node);
|
||||
AssertObjectTypeIsFunctional(stmt->objectType);
|
||||
|
@ -1611,7 +1627,7 @@ AlterFunctionDependsStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* was unable to find the function/procedure that was the target of the statement.
|
||||
*/
|
||||
List *
|
||||
AlterFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterFunctionStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterFunctionStmt *stmt = castNode(AlterFunctionStmt, node);
|
||||
return FunctionToObjectAddress(stmt->objtype, stmt->func, missing_ok);
|
||||
|
@ -1623,7 +1639,7 @@ AlterFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* subject of the RenameStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
RenameFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameFunctionStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
return FunctionToObjectAddress(stmt->renameType,
|
||||
|
@ -1636,7 +1652,7 @@ RenameFunctionStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* subject of the AlterOwnerStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterFunctionOwnerObjectAddress(Node *node, bool missing_ok)
|
||||
AlterFunctionOwnerObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
return FunctionToObjectAddress(stmt->objectType,
|
||||
|
@ -1654,7 +1670,7 @@ AlterFunctionOwnerObjectAddress(Node *node, bool missing_ok)
|
|||
* the schemas.
|
||||
*/
|
||||
List *
|
||||
AlterFunctionSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterFunctionSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
AssertObjectTypeIsFunctional(stmt->objectType);
|
||||
|
|
|
@ -75,7 +75,7 @@ static void RangeVarCallbackForReindexIndex(const RangeVar *rel, Oid relOid, Oid
|
|||
static void ErrorIfUnsupportedIndexStmt(IndexStmt *createIndexStatement);
|
||||
static void ErrorIfUnsupportedDropIndexStmt(DropStmt *dropIndexStatement);
|
||||
static List * DropIndexTaskList(Oid relationId, Oid indexId, DropStmt *dropStmt);
|
||||
|
||||
static Oid ReindexStmtFindRelationOid(ReindexStmt *reindexStmt, bool missingOk);
|
||||
|
||||
/*
|
||||
* This struct defines the state for the callback for drop statements.
|
||||
|
@ -522,6 +522,49 @@ GetCreateIndexRelationLockMode(IndexStmt *createIndexStatement)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* ReindexStmtFindRelationOid returns the oid of the relation on which the index exist
|
||||
* if the object is an index in the reindex stmt. It returns the oid of the relation
|
||||
* if the object is a table in the reindex stmt. It also acquires the relevant lock
|
||||
* for the statement.
|
||||
*/
|
||||
static Oid
|
||||
ReindexStmtFindRelationOid(ReindexStmt *reindexStmt, bool missingOk)
|
||||
{
|
||||
Assert(reindexStmt->relation != NULL);
|
||||
|
||||
Assert(reindexStmt->kind == REINDEX_OBJECT_INDEX ||
|
||||
reindexStmt->kind == REINDEX_OBJECT_TABLE);
|
||||
|
||||
Oid relationId = InvalidOid;
|
||||
|
||||
LOCKMODE lockmode = IsReindexWithParam_compat(reindexStmt, "concurrently") ?
|
||||
ShareUpdateExclusiveLock : AccessExclusiveLock;
|
||||
|
||||
if (reindexStmt->kind == REINDEX_OBJECT_INDEX)
|
||||
{
|
||||
struct ReindexIndexCallbackState state;
|
||||
state.concurrent = IsReindexWithParam_compat(reindexStmt,
|
||||
"concurrently");
|
||||
state.locked_table_oid = InvalidOid;
|
||||
|
||||
Oid indOid = RangeVarGetRelidExtended(reindexStmt->relation, lockmode,
|
||||
(missingOk) ? RVR_MISSING_OK : 0,
|
||||
RangeVarCallbackForReindexIndex,
|
||||
&state);
|
||||
relationId = IndexGetRelation(indOid, missingOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
relationId = RangeVarGetRelidExtended(reindexStmt->relation, lockmode,
|
||||
(missingOk) ? RVR_MISSING_OK : 0,
|
||||
RangeVarCallbackOwnsTable, NULL);
|
||||
}
|
||||
|
||||
return relationId;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PreprocessReindexStmt determines whether a given REINDEX statement involves
|
||||
* a distributed table. If so (and if the statement does not use unsupported
|
||||
|
@ -544,36 +587,17 @@ PreprocessReindexStmt(Node *node, const char *reindexCommand,
|
|||
*/
|
||||
if (reindexStatement->relation != NULL)
|
||||
{
|
||||
Relation relation = NULL;
|
||||
Oid relationId = InvalidOid;
|
||||
LOCKMODE lockmode = IsReindexWithParam_compat(reindexStatement, "concurrently") ?
|
||||
ShareUpdateExclusiveLock : AccessExclusiveLock;
|
||||
Oid relationId = ReindexStmtFindRelationOid(reindexStatement, false);
|
||||
MemoryContext relationContext = NULL;
|
||||
|
||||
Assert(reindexStatement->kind == REINDEX_OBJECT_INDEX ||
|
||||
reindexStatement->kind == REINDEX_OBJECT_TABLE);
|
||||
|
||||
Relation relation = NULL;
|
||||
if (reindexStatement->kind == REINDEX_OBJECT_INDEX)
|
||||
{
|
||||
struct ReindexIndexCallbackState state;
|
||||
state.concurrent = IsReindexWithParam_compat(reindexStatement,
|
||||
"concurrently");
|
||||
state.locked_table_oid = InvalidOid;
|
||||
|
||||
Oid indOid = RangeVarGetRelidExtended(reindexStatement->relation,
|
||||
lockmode, 0,
|
||||
RangeVarCallbackForReindexIndex,
|
||||
&state);
|
||||
Oid indOid = RangeVarGetRelid(reindexStatement->relation, NoLock, 0);
|
||||
relation = index_open(indOid, NoLock);
|
||||
relationId = IndexGetRelation(indOid, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
RangeVarGetRelidExtended(reindexStatement->relation, lockmode, 0,
|
||||
RangeVarCallbackOwnsTable, NULL);
|
||||
|
||||
relation = table_openrv(reindexStatement->relation, NoLock);
|
||||
relationId = RelationGetRelid(relation);
|
||||
}
|
||||
|
||||
bool isCitusRelation = IsCitusTable(relationId);
|
||||
|
@ -628,6 +652,30 @@ PreprocessReindexStmt(Node *node, const char *reindexCommand,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* ReindexStmtObjectAddress returns list of object addresses in the reindex
|
||||
* statement. We add the address if the object is either index or table;
|
||||
* else, we add invalid address.
|
||||
*/
|
||||
List *
|
||||
ReindexStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
ReindexStmt *reindexStatement = castNode(ReindexStmt, stmt);
|
||||
|
||||
Oid relationId = InvalidOid;
|
||||
if (reindexStatement->relation != NULL)
|
||||
{
|
||||
/* we currently only support reindex commands on tables */
|
||||
relationId = ReindexStmtFindRelationOid(reindexStatement, missing_ok);
|
||||
}
|
||||
|
||||
ObjectAddress *objectAddress = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*objectAddress, RelationRelationId, relationId);
|
||||
|
||||
return list_make1(objectAddress);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PreprocessDropIndexStmt determines whether a given DROP INDEX statement involves
|
||||
* a distributed table. If so (and if the statement does not use unsupported
|
||||
|
|
|
@ -30,11 +30,7 @@
|
|||
* By default, COPY uses normal transactions on the workers. In the case of
|
||||
* hash or range-partitioned tables, this can cause a problem when some of the
|
||||
* transactions fail to commit while others have succeeded. To ensure no data
|
||||
* is lost, COPY can use two-phase commit, by increasing max_prepared_transactions
|
||||
* on the worker and setting citus.multi_shard_commit_protocol to '2pc'. The default
|
||||
* is '1pc'. This is not a problem for append-partitioned tables because new
|
||||
* shards are created and in the case of failure, metadata changes are rolled
|
||||
* back on the master node.
|
||||
* is lost, COPY uses two-phase commit.
|
||||
*
|
||||
* Parsing options are processed and enforced on the node where copy command
|
||||
* is run, while constraints are enforced on the worker. In either case,
|
||||
|
@ -245,7 +241,7 @@ typedef enum LocalCopyStatus
|
|||
|
||||
/* Local functions forward declarations */
|
||||
static void CopyToExistingShards(CopyStmt *copyStatement,
|
||||
QueryCompletionCompat *completionTag);
|
||||
QueryCompletion *completionTag);
|
||||
static bool IsCopyInBinaryFormat(CopyStmt *copyStatement);
|
||||
static List * FindJsonbInputColumns(TupleDesc tupleDescriptor,
|
||||
List *inputColumnNameList);
|
||||
|
@ -274,7 +270,7 @@ static FmgrInfo * TypeOutputFunctions(uint32 columnCount, Oid *typeIdArray,
|
|||
static List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist);
|
||||
#endif
|
||||
static bool CopyStatementHasFormat(CopyStmt *copyStatement, char *formatName);
|
||||
static void CitusCopyFrom(CopyStmt *copyStatement, QueryCompletionCompat *completionTag);
|
||||
static void CitusCopyFrom(CopyStmt *copyStatement, QueryCompletion *completionTag);
|
||||
static void EnsureCopyCanRunOnRelation(Oid relationId);
|
||||
static HTAB * CreateConnectionStateHash(MemoryContext memoryContext);
|
||||
static HTAB * CreateShardStateHash(MemoryContext memoryContext);
|
||||
|
@ -308,7 +304,7 @@ static void UnclaimCopyConnections(List *connectionStateList);
|
|||
static void ShutdownCopyConnectionState(CopyConnectionState *connectionState,
|
||||
CitusCopyDestReceiver *copyDest);
|
||||
static SelectStmt * CitusCopySelect(CopyStmt *copyStatement);
|
||||
static void CitusCopyTo(CopyStmt *copyStatement, QueryCompletionCompat *completionTag);
|
||||
static void CitusCopyTo(CopyStmt *copyStatement, QueryCompletion *completionTag);
|
||||
static int64 ForwardCopyDataFromConnection(CopyOutState copyOutState,
|
||||
MultiConnection *connection);
|
||||
|
||||
|
@ -345,7 +341,7 @@ static bool CitusCopyDestReceiverReceive(TupleTableSlot *slot,
|
|||
static void CitusCopyDestReceiverShutdown(DestReceiver *destReceiver);
|
||||
static void CitusCopyDestReceiverDestroy(DestReceiver *destReceiver);
|
||||
static bool ContainsLocalPlacement(int64 shardId);
|
||||
static void CompleteCopyQueryTagCompat(QueryCompletionCompat *completionTag, uint64
|
||||
static void CompleteCopyQueryTagCompat(QueryCompletion *completionTag, uint64
|
||||
processedRowCount);
|
||||
static void FinishLocalCopy(CitusCopyDestReceiver *copyDest);
|
||||
static void CreateLocalColocatedIntermediateFile(CitusCopyDestReceiver *copyDest,
|
||||
|
@ -368,7 +364,7 @@ PG_FUNCTION_INFO_V1(citus_text_send_as_jsonb);
|
|||
* and the partition method of the distributed table.
|
||||
*/
|
||||
static void
|
||||
CitusCopyFrom(CopyStmt *copyStatement, QueryCompletionCompat *completionTag)
|
||||
CitusCopyFrom(CopyStmt *copyStatement, QueryCompletion *completionTag)
|
||||
{
|
||||
UseCoordinatedTransaction();
|
||||
|
||||
|
@ -450,7 +446,7 @@ EnsureCopyCanRunOnRelation(Oid relationId)
|
|||
* rows.
|
||||
*/
|
||||
static void
|
||||
CopyToExistingShards(CopyStmt *copyStatement, QueryCompletionCompat *completionTag)
|
||||
CopyToExistingShards(CopyStmt *copyStatement, QueryCompletion *completionTag)
|
||||
{
|
||||
Oid tableId = RangeVarGetRelid(copyStatement->relation, NoLock, false);
|
||||
|
||||
|
@ -471,8 +467,8 @@ CopyToExistingShards(CopyStmt *copyStatement, QueryCompletionCompat *completionT
|
|||
bool *columnNulls = palloc0(columnCount * sizeof(bool));
|
||||
|
||||
/* set up a virtual tuple table slot */
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlotCompat(tupleDescriptor,
|
||||
&TTSOpsVirtual);
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlot(tupleDescriptor,
|
||||
&TTSOpsVirtual);
|
||||
tupleTableSlot->tts_nvalid = columnCount;
|
||||
tupleTableSlot->tts_values = columnValues;
|
||||
tupleTableSlot->tts_isnull = columnNulls;
|
||||
|
@ -639,8 +635,8 @@ CopyToExistingShards(CopyStmt *copyStatement, QueryCompletionCompat *completionT
|
|||
MemoryContext oldContext = MemoryContextSwitchTo(executorTupleContext);
|
||||
|
||||
/* parse a row from the input */
|
||||
bool nextRowFound = NextCopyFromCompat(copyState, executorExpressionContext,
|
||||
columnValues, columnNulls);
|
||||
bool nextRowFound = NextCopyFrom(copyState, executorExpressionContext,
|
||||
columnValues, columnNulls);
|
||||
|
||||
if (!nextRowFound)
|
||||
{
|
||||
|
@ -760,7 +756,7 @@ FindJsonbInputColumns(TupleDesc tupleDescriptor, List *inputColumnNameList)
|
|||
|
||||
|
||||
static void
|
||||
CompleteCopyQueryTagCompat(QueryCompletionCompat *completionTag, uint64 processedRowCount)
|
||||
CompleteCopyQueryTagCompat(QueryCompletion *completionTag, uint64 processedRowCount)
|
||||
{
|
||||
SetQueryCompletion(completionTag, CMDTAG_COPY, processedRowCount);
|
||||
}
|
||||
|
@ -780,7 +776,7 @@ RemoveOptionFromList(List *optionList, char *optionName)
|
|||
|
||||
if (strncmp(option->defname, optionName, NAMEDATALEN) == 0)
|
||||
{
|
||||
return list_delete_cell_compat(optionList, optionCell, previousCell);
|
||||
return list_delete_cell(optionList, optionCell);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1387,7 +1383,7 @@ ColumnCoercionPaths(TupleDesc destTupleDescriptor, TupleDesc inputTupleDescripto
|
|||
ConversionPathForTypes(inputTupleType, destTupleType,
|
||||
&coercePaths[columnIndex]);
|
||||
|
||||
currentColumnName = lnext_compat(columnNameList, currentColumnName);
|
||||
currentColumnName = lnext(columnNameList, currentColumnName);
|
||||
|
||||
if (currentColumnName == NULL)
|
||||
{
|
||||
|
@ -2864,7 +2860,7 @@ CopyStatementHasFormat(CopyStmt *copyStatement, char *formatName)
|
|||
* further processing is needed.
|
||||
*/
|
||||
Node *
|
||||
ProcessCopyStmt(CopyStmt *copyStatement, QueryCompletionCompat *completionTag, const
|
||||
ProcessCopyStmt(CopyStmt *copyStatement, QueryCompletion *completionTag, const
|
||||
char *queryString)
|
||||
{
|
||||
/*
|
||||
|
@ -3016,7 +3012,7 @@ CitusCopySelect(CopyStmt *copyStatement)
|
|||
* table dump.
|
||||
*/
|
||||
static void
|
||||
CitusCopyTo(CopyStmt *copyStatement, QueryCompletionCompat *completionTag)
|
||||
CitusCopyTo(CopyStmt *copyStatement, QueryCompletion *completionTag)
|
||||
{
|
||||
ListCell *shardIntervalCell = NULL;
|
||||
int64 tuplesSent = 0;
|
||||
|
@ -3481,7 +3477,7 @@ InitializeCopyShardState(CopyShardState *shardState,
|
|||
bool hasRemoteCopy = false;
|
||||
|
||||
MemoryContext localContext =
|
||||
AllocSetContextCreateExtended(CurrentMemoryContext,
|
||||
AllocSetContextCreateInternal(CurrentMemoryContext,
|
||||
"InitializeCopyShardState",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
|
|
|
@ -362,7 +362,7 @@ PreprocessAlterPolicyStmt(Node *node, const char *queryString,
|
|||
|
||||
appendStringInfoString(&ddlString, RoleSpecString(roleSpec, true));
|
||||
|
||||
if (lnext_compat(stmt->roles, roleCell) != NULL)
|
||||
if (lnext(stmt->roles, roleCell) != NULL)
|
||||
{
|
||||
appendStringInfoString(&ddlString, ", ");
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ bool EnableAlterRoleSetPropagation = true;
|
|||
* was unable to find the role that was the target of the statement.
|
||||
*/
|
||||
List *
|
||||
AlterRoleStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterRoleStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterRoleStmt *stmt = castNode(AlterRoleStmt, node);
|
||||
return RoleSpecToObjectAddress(stmt->role, missing_ok);
|
||||
|
@ -101,7 +101,7 @@ AlterRoleStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* was unable to find the role that was the target of the statement.
|
||||
*/
|
||||
List *
|
||||
AlterRoleSetStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterRoleSetStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterRoleSetStmt *stmt = castNode(AlterRoleSetStmt, node);
|
||||
return RoleSpecToObjectAddress(stmt->role, missing_ok);
|
||||
|
@ -137,7 +137,7 @@ RoleSpecToObjectAddress(RoleSpec *role, bool missing_ok)
|
|||
List *
|
||||
PostprocessAlterRoleStmt(Node *node, const char *queryString)
|
||||
{
|
||||
List *addresses = GetObjectAddressListFromParseTree(node, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree(node, false, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -212,7 +212,7 @@ PreprocessAlterRoleSetStmt(Node *node, const char *queryString,
|
|||
return NIL;
|
||||
}
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree(node, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree(node, false, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -1188,7 +1188,7 @@ ConfigGenericNameCompare(const void *a, const void *b)
|
|||
* to true.
|
||||
*/
|
||||
List *
|
||||
CreateRoleStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateRoleStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateRoleStmt *stmt = castNode(CreateRoleStmt, node);
|
||||
Oid roleOid = get_role_oid(stmt->role, missing_ok);
|
||||
|
|
|
@ -184,7 +184,7 @@ PreprocessGrantOnSchemaStmt(Node *node, const char *queryString,
|
|||
* the object of the CreateSchemaStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
CreateSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateSchemaStmt *stmt = castNode(CreateSchemaStmt, node);
|
||||
|
||||
|
@ -214,7 +214,7 @@ CreateSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* the object of the RenameStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterSchemaRenameStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterSchemaRenameStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_SCHEMA);
|
||||
|
|
|
@ -191,7 +191,7 @@ ExtractDefaultColumnsAndOwnedSequences(Oid relationId, List **columnNameList,
|
|||
*columnNameList = lappend(*columnNameList, columnName);
|
||||
|
||||
List *columnOwnedSequences =
|
||||
GetSequencesOwnedByColumn(relationId, attributeIndex + 1);
|
||||
getOwnedSequences_internal(relationId, attributeIndex + 1, 0);
|
||||
|
||||
Oid ownedSequenceId = InvalidOid;
|
||||
if (list_length(columnOwnedSequences) != 0)
|
||||
|
@ -313,6 +313,34 @@ PreprocessDropSequenceStmt(Node *node, const char *queryString,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* SequenceDropStmtObjectAddress returns list of object addresses in the drop sequence
|
||||
* statement.
|
||||
*/
|
||||
List *
|
||||
SequenceDropStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DropStmt *dropSeqStmt = castNode(DropStmt, stmt);
|
||||
|
||||
List *objectAddresses = NIL;
|
||||
|
||||
List *droppingSequencesList = dropSeqStmt->objects;
|
||||
List *objectNameList = NULL;
|
||||
foreach_ptr(objectNameList, droppingSequencesList)
|
||||
{
|
||||
RangeVar *seq = makeRangeVarFromNameList(objectNameList);
|
||||
|
||||
Oid seqOid = RangeVarGetRelid(seq, AccessShareLock, missing_ok);
|
||||
|
||||
ObjectAddress *objectAddress = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*objectAddress, SequenceRelationId, seqOid);
|
||||
objectAddresses = lappend(objectAddresses, objectAddress);
|
||||
}
|
||||
|
||||
return objectAddresses;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PreprocessRenameSequenceStmt is called when the user is renaming a sequence. The invocation
|
||||
* happens before the statement is applied locally.
|
||||
|
@ -329,7 +357,7 @@ PreprocessRenameSequenceStmt(Node *node, const char *queryString, ProcessUtility
|
|||
Assert(stmt->renameType == OBJECT_SEQUENCE);
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt,
|
||||
stmt->missing_ok);
|
||||
stmt->missing_ok, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -356,7 +384,7 @@ PreprocessRenameSequenceStmt(Node *node, const char *queryString, ProcessUtility
|
|||
* subject of the RenameStmt.
|
||||
*/
|
||||
List *
|
||||
RenameSequenceStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameSequenceStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_SEQUENCE);
|
||||
|
@ -393,7 +421,7 @@ PreprocessAlterSequenceStmt(Node *node, const char *queryString,
|
|||
AlterSeqStmt *stmt = castNode(AlterSeqStmt, node);
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt,
|
||||
stmt->missing_ok);
|
||||
stmt->missing_ok, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -476,7 +504,7 @@ SequenceUsedInDistributedTable(const ObjectAddress *sequenceAddress)
|
|||
* subject of the AlterSeqStmt.
|
||||
*/
|
||||
List *
|
||||
AlterSequenceStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterSequenceStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterSeqStmt *stmt = castNode(AlterSeqStmt, node);
|
||||
|
||||
|
@ -503,7 +531,7 @@ PreprocessAlterSequenceSchemaStmt(Node *node, const char *queryString,
|
|||
Assert(stmt->objectType == OBJECT_SEQUENCE);
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt,
|
||||
stmt->missing_ok);
|
||||
stmt->missing_ok, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -530,7 +558,7 @@ PreprocessAlterSequenceSchemaStmt(Node *node, const char *queryString,
|
|||
* the subject of the AlterObjectSchemaStmt.
|
||||
*/
|
||||
List *
|
||||
AlterSequenceSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterSequenceSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_SEQUENCE);
|
||||
|
@ -581,7 +609,7 @@ PostprocessAlterSequenceSchemaStmt(Node *node, const char *queryString)
|
|||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_SEQUENCE);
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt,
|
||||
stmt->missing_ok);
|
||||
stmt->missing_ok, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -612,7 +640,8 @@ PreprocessAlterSequenceOwnerStmt(Node *node, const char *queryString,
|
|||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
|
||||
|
||||
List *sequenceAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false);
|
||||
List *sequenceAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false,
|
||||
false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(sequenceAddresses) == 1);
|
||||
|
@ -639,7 +668,7 @@ PreprocessAlterSequenceOwnerStmt(Node *node, const char *queryString,
|
|||
* subject of the AlterOwnerStmt.
|
||||
*/
|
||||
List *
|
||||
AlterSequenceOwnerStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterSequenceOwnerStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
|
||||
|
@ -664,7 +693,8 @@ PostprocessAlterSequenceOwnerStmt(Node *node, const char *queryString)
|
|||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
|
||||
|
||||
List *sequenceAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false);
|
||||
List *sequenceAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false,
|
||||
true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(sequenceAddresses) == 1);
|
||||
|
|
|
@ -120,7 +120,8 @@ PostprocessCreateStatisticsStmt(Node *node, const char *queryString)
|
|||
}
|
||||
|
||||
bool missingOk = false;
|
||||
List *objectAddresses = GetObjectAddressListFromParseTree((Node *) stmt, missingOk);
|
||||
List *objectAddresses = GetObjectAddressListFromParseTree((Node *) stmt, missingOk,
|
||||
true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(objectAddresses) == 1);
|
||||
|
@ -140,7 +141,7 @@ PostprocessCreateStatisticsStmt(Node *node, const char *queryString)
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
CreateStatisticsStmtObjectAddress(Node *node, bool missingOk)
|
||||
CreateStatisticsStmtObjectAddress(Node *node, bool missingOk, bool isPostprocess)
|
||||
{
|
||||
CreateStatsStmt *stmt = castNode(CreateStatsStmt, node);
|
||||
|
||||
|
@ -210,6 +211,33 @@ PreprocessDropStatisticsStmt(Node *node, const char *queryString,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* DropStatisticsObjectAddress returns list of object addresses in the drop statistics
|
||||
* statement.
|
||||
*/
|
||||
List *
|
||||
DropStatisticsObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DropStmt *dropStatisticsStmt = castNode(DropStmt, node);
|
||||
Assert(dropStatisticsStmt->removeType == OBJECT_STATISTIC_EXT);
|
||||
|
||||
List *objectAddresses = NIL;
|
||||
|
||||
List *objectNameList = NULL;
|
||||
foreach_ptr(objectNameList, dropStatisticsStmt->objects)
|
||||
{
|
||||
Oid statsOid = get_statistics_object_oid(objectNameList,
|
||||
dropStatisticsStmt->missing_ok);
|
||||
|
||||
ObjectAddress *objectAddress = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*objectAddress, StatisticExtRelationId, statsOid);
|
||||
objectAddresses = lappend(objectAddresses, objectAddress);
|
||||
}
|
||||
|
||||
return objectAddresses;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PreprocessAlterStatisticsRenameStmt is called during the planning phase for
|
||||
* ALTER STATISTICS RENAME.
|
||||
|
@ -307,7 +335,8 @@ PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString)
|
|||
}
|
||||
|
||||
bool missingOk = false;
|
||||
List *objectAddresses = GetObjectAddressListFromParseTree((Node *) stmt, missingOk);
|
||||
List *objectAddresses = GetObjectAddressListFromParseTree((Node *) stmt, missingOk,
|
||||
true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(objectAddresses) == 1);
|
||||
|
@ -327,14 +356,30 @@ PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString)
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk)
|
||||
AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
|
||||
ObjectAddress *address = palloc0(sizeof(ObjectAddress));
|
||||
String *statName = llast((List *) stmt->object);
|
||||
Oid statsOid = get_statistics_object_oid(list_make2(makeString(stmt->newschema),
|
||||
statName), missingOk);
|
||||
Oid statsOid = InvalidOid;
|
||||
|
||||
List *statName = (List *) stmt->object;
|
||||
|
||||
if (isPostprocess)
|
||||
{
|
||||
/*
|
||||
* we should search the object in the new schema because the method is
|
||||
* called during postprocess, standard_utility should have already moved
|
||||
* the stat into new schema.
|
||||
*/
|
||||
List *newStatName = list_make2(makeString(stmt->newschema), llast(statName));
|
||||
statsOid = get_statistics_object_oid(newStatName, missingOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
statsOid = get_statistics_object_oid(statName, missingOk);
|
||||
}
|
||||
|
||||
ObjectAddressSet(*address, StatisticExtRelationId, statsOid);
|
||||
|
||||
return list_make1(address);
|
||||
|
|
|
@ -45,9 +45,8 @@ ProcessCreateSubscriptionStmt(CreateSubscriptionStmt *createSubStmt)
|
|||
{
|
||||
useAuthinfo = defGetBoolean(defElem);
|
||||
|
||||
createSubStmt->options = list_delete_cell_compat(createSubStmt->options,
|
||||
currCell,
|
||||
prevCell);
|
||||
createSubStmt->options = list_delete_cell(createSubStmt->options,
|
||||
currCell);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -649,7 +649,7 @@ PostprocessAlterTableSchemaStmt(Node *node, const char *queryString)
|
|||
/*
|
||||
* We will let Postgres deal with missing_ok
|
||||
*/
|
||||
List *tableAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true);
|
||||
List *tableAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(tableAddresses) == 1);
|
||||
|
@ -1754,10 +1754,13 @@ List *
|
|||
PreprocessAlterTableMoveAllStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext)
|
||||
{
|
||||
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.")));
|
||||
if (EnableUnsupportedFeatureMessages)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -1783,7 +1786,7 @@ PreprocessAlterTableSchemaStmt(Node *node, const char *queryString,
|
|||
}
|
||||
|
||||
List *addresses = GetObjectAddressListFromParseTree((Node *) stmt,
|
||||
stmt->missing_ok);
|
||||
stmt->missing_ok, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
@ -3366,7 +3369,7 @@ ErrorIfUnsupportedAlterAddConstraintStmt(AlterTableStmt *alterTableStatement)
|
|||
* be found in either of the schemas.
|
||||
*/
|
||||
List *
|
||||
AlterTableSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTableSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_TABLE || stmt->objectType == OBJECT_FOREIGN_TABLE);
|
||||
|
|
|
@ -570,7 +570,8 @@ get_ts_parser_namelist(Oid tsparserOid)
|
|||
* the text search configuration described in the statement doesn't exist.
|
||||
*/
|
||||
List *
|
||||
CreateTextSearchConfigurationObjectAddress(Node *node, bool missing_ok)
|
||||
CreateTextSearchConfigurationObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
DefineStmt *stmt = castNode(DefineStmt, node);
|
||||
Assert(stmt->kind == OBJECT_TSCONFIGURATION);
|
||||
|
@ -589,7 +590,7 @@ CreateTextSearchConfigurationObjectAddress(Node *node, bool missing_ok)
|
|||
* the text search dictionary described in the statement doesn't exist.
|
||||
*/
|
||||
List *
|
||||
CreateTextSearchDictObjectAddress(Node *node, bool missing_ok)
|
||||
CreateTextSearchDictObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DefineStmt *stmt = castNode(DefineStmt, node);
|
||||
Assert(stmt->kind == OBJECT_TSDICTIONARY);
|
||||
|
@ -608,7 +609,8 @@ CreateTextSearchDictObjectAddress(Node *node, bool missing_ok)
|
|||
* exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
RenameTextSearchConfigurationStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameTextSearchConfigurationStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_TSCONFIGURATION);
|
||||
|
@ -627,7 +629,8 @@ RenameTextSearchConfigurationStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
RenameTextSearchDictionaryStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameTextSearchDictionaryStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_TSDICTIONARY);
|
||||
|
@ -646,7 +649,8 @@ RenameTextSearchDictionaryStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
AlterTextSearchConfigurationStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTextSearchConfigurationStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
AlterTSConfigurationStmt *stmt = castNode(AlterTSConfigurationStmt, node);
|
||||
|
||||
|
@ -664,7 +668,8 @@ AlterTextSearchConfigurationStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
AlterTextSearchDictionaryStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTextSearchDictionaryStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
AlterTSDictionaryStmt *stmt = castNode(AlterTSDictionaryStmt, node);
|
||||
|
||||
|
@ -686,7 +691,8 @@ AlterTextSearchDictionaryStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* in edgecases will be raised by postgres while executing the move.
|
||||
*/
|
||||
List *
|
||||
AlterTextSearchConfigurationSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTextSearchConfigurationSchemaStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_TSCONFIGURATION);
|
||||
|
@ -739,7 +745,8 @@ AlterTextSearchConfigurationSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* in edgecases will be raised by postgres while executing the move.
|
||||
*/
|
||||
List *
|
||||
AlterTextSearchDictionarySchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTextSearchDictionarySchemaStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_TSDICTIONARY);
|
||||
|
@ -788,7 +795,8 @@ AlterTextSearchDictionarySchemaStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* configuration does not exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
TextSearchConfigurationCommentObjectAddress(Node *node, bool missing_ok)
|
||||
TextSearchConfigurationCommentObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
CommentStmt *stmt = castNode(CommentStmt, node);
|
||||
Assert(stmt->objtype == OBJECT_TSCONFIGURATION);
|
||||
|
@ -807,7 +815,7 @@ TextSearchConfigurationCommentObjectAddress(Node *node, bool missing_ok)
|
|||
* exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
TextSearchDictCommentObjectAddress(Node *node, bool missing_ok)
|
||||
TextSearchDictCommentObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CommentStmt *stmt = castNode(CommentStmt, node);
|
||||
Assert(stmt->objtype == OBJECT_TSDICTIONARY);
|
||||
|
@ -826,7 +834,8 @@ TextSearchDictCommentObjectAddress(Node *node, bool missing_ok)
|
|||
* configuration does not exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
AlterTextSearchConfigurationOwnerObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTextSearchConfigurationOwnerObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
Relation relation = NULL;
|
||||
|
@ -850,7 +859,7 @@ AlterTextSearchConfigurationOwnerObjectAddress(Node *node, bool missing_ok)
|
|||
* configuration does not exist based on the missing_ok flag passed in by the caller.
|
||||
*/
|
||||
List *
|
||||
AlterTextSearchDictOwnerObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTextSearchDictOwnerObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
Relation relation = NULL;
|
||||
|
|
|
@ -224,7 +224,7 @@ PostprocessCreateTriggerStmt(Node *node, const char *queryString)
|
|||
EnsureCoordinator();
|
||||
ErrorOutForTriggerIfNotSupported(relationId);
|
||||
|
||||
List *objectAddresses = GetObjectAddressListFromParseTree(node, missingOk);
|
||||
List *objectAddresses = GetObjectAddressListFromParseTree(node, missingOk, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(objectAddresses) == 1);
|
||||
|
@ -246,7 +246,7 @@ PostprocessCreateTriggerStmt(Node *node, const char *queryString)
|
|||
* was set to true.
|
||||
*/
|
||||
List *
|
||||
CreateTriggerStmtObjectAddress(Node *node, bool missingOk)
|
||||
CreateTriggerStmtObjectAddress(Node *node, bool missingOk, bool isPostprocess)
|
||||
{
|
||||
CreateTrigStmt *createTriggerStmt = castNode(CreateTrigStmt, node);
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ PreprocessRenameTypeAttributeStmt(Node *node, const char *queryString,
|
|||
Assert(stmt->renameType == OBJECT_ATTRIBUTE);
|
||||
Assert(stmt->relationType == OBJECT_TYPE);
|
||||
|
||||
List *typeAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false);
|
||||
List *typeAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(typeAddresses) == 1);
|
||||
|
@ -305,7 +305,7 @@ EnumValsList(Oid typeOid)
|
|||
* to true.
|
||||
*/
|
||||
List *
|
||||
CompositeTypeStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CompositeTypeStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CompositeTypeStmt *stmt = castNode(CompositeTypeStmt, node);
|
||||
TypeName *typeName = MakeTypeNameFromRangeVar(stmt->typevar);
|
||||
|
@ -326,7 +326,7 @@ CompositeTypeStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* to true.
|
||||
*/
|
||||
List *
|
||||
CreateEnumStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateEnumStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateEnumStmt *stmt = castNode(CreateEnumStmt, node);
|
||||
TypeName *typeName = makeTypeNameFromNameList(stmt->typeName);
|
||||
|
@ -347,7 +347,7 @@ CreateEnumStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* to true.
|
||||
*/
|
||||
List *
|
||||
AlterTypeStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTypeStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TYPE);
|
||||
|
@ -366,7 +366,7 @@ AlterTypeStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* object of the AlterEnumStmt. Errors is missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterEnumStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterEnumStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterEnumStmt *stmt = castNode(AlterEnumStmt, node);
|
||||
TypeName *typeName = makeTypeNameFromNameList(stmt->typeName);
|
||||
|
@ -383,7 +383,7 @@ AlterEnumStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* of the RenameStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
RenameTypeStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameTypeStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_TYPE);
|
||||
|
@ -407,7 +407,7 @@ RenameTypeStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* schemas.
|
||||
*/
|
||||
List *
|
||||
AlterTypeSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTypeSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_TYPE || stmt->objectType == OBJECT_DOMAIN);
|
||||
|
@ -487,7 +487,7 @@ RenameTypeAttributeStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* of the AlterOwnerStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
AlterTypeOwnerObjectAddress(Node *node, bool missing_ok)
|
||||
AlterTypeOwnerObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||
Assert(stmt->objectType == OBJECT_TYPE);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "commands/tablecmds.h"
|
||||
#include "distributed/adaptive_executor.h"
|
||||
#include "distributed/backend_data.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/colocation_utils.h"
|
||||
#include "distributed/commands.h"
|
||||
#include "distributed/commands/multi_copy.h"
|
||||
|
@ -104,7 +105,7 @@ static void ProcessUtilityInternal(PlannedStmt *pstmt,
|
|||
ParamListInfo params,
|
||||
struct QueryEnvironment *queryEnv,
|
||||
DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag);
|
||||
QueryCompletion *completionTag);
|
||||
#if PG_VERSION_NUM >= 140000
|
||||
static void set_indexsafe_procflags(void);
|
||||
#endif
|
||||
|
@ -128,7 +129,7 @@ void
|
|||
ProcessUtilityParseTree(Node *node, const char *queryString, ProcessUtilityContext
|
||||
context,
|
||||
ParamListInfo params, DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag)
|
||||
QueryCompletion *completionTag)
|
||||
{
|
||||
PlannedStmt *plannedStmt = makeNode(PlannedStmt);
|
||||
plannedStmt->commandType = CMD_UTILITY;
|
||||
|
@ -158,7 +159,7 @@ multi_ProcessUtility(PlannedStmt *pstmt,
|
|||
ParamListInfo params,
|
||||
struct QueryEnvironment *queryEnv,
|
||||
DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag)
|
||||
QueryCompletion *completionTag)
|
||||
{
|
||||
Node *parsetree;
|
||||
|
||||
|
@ -372,10 +373,11 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
|
|||
ParamListInfo params,
|
||||
struct QueryEnvironment *queryEnv,
|
||||
DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag)
|
||||
QueryCompletion *completionTag)
|
||||
{
|
||||
Node *parsetree = pstmt->utilityStmt;
|
||||
List *ddlJobs = NIL;
|
||||
bool distOpsHasInvalidObject = false;
|
||||
|
||||
if (IsA(parsetree, ExplainStmt) &&
|
||||
IsA(((ExplainStmt *) parsetree)->query, Query))
|
||||
|
@ -542,6 +544,19 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
|
|||
parsetree = pstmt->utilityStmt;
|
||||
ops = GetDistributeObjectOps(parsetree);
|
||||
|
||||
/*
|
||||
* Preprocess and qualify steps can cause pg tests to fail because of the
|
||||
* unwanted citus related warnings or early error logs related to invalid address.
|
||||
* Therefore, we first check if all addresses in the given statement are valid.
|
||||
* Then, we do not execute qualify and preprocess if any address is invalid to
|
||||
* prevent before-mentioned citus related messages. PG will complain about the
|
||||
* invalid address, so we are safe to not execute qualify and preprocess. Also
|
||||
* note that we should not guard any step after standardProcess_Utility with
|
||||
* the flag distOpsHasInvalidObject because PG would have already failed the
|
||||
* transaction.
|
||||
*/
|
||||
distOpsHasInvalidObject = DistOpsHasInvalidObject(parsetree, ops);
|
||||
|
||||
/*
|
||||
* For some statements Citus defines a Qualify function. The goal of this function
|
||||
* is to take any ambiguity from the statement that is contextual on either the
|
||||
|
@ -551,12 +566,12 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
|
|||
* deserialize calls for the statement portable to other postgres servers, the
|
||||
* workers in our case.
|
||||
*/
|
||||
if (ops && ops->qualify)
|
||||
if (ops && ops->qualify && !distOpsHasInvalidObject)
|
||||
{
|
||||
ops->qualify(parsetree);
|
||||
}
|
||||
|
||||
if (ops && ops->preprocess)
|
||||
if (ops && ops->preprocess && !distOpsHasInvalidObject)
|
||||
{
|
||||
ddlJobs = ops->preprocess(parsetree, queryString, context);
|
||||
}
|
||||
|
@ -734,10 +749,14 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
|
|||
if (IsA(parsetree, RenameStmt) && ((RenameStmt *) parsetree)->renameType ==
|
||||
OBJECT_ROLE && EnableAlterRolePropagation)
|
||||
{
|
||||
ereport(NOTICE, (errmsg("not propagating ALTER ROLE ... RENAME TO commands "
|
||||
"to worker nodes"),
|
||||
errhint("Connect to worker nodes directly to manually "
|
||||
"rename the role")));
|
||||
if (EnableUnsupportedFeatureMessages)
|
||||
{
|
||||
ereport(NOTICE, (errmsg(
|
||||
"not propagating ALTER ROLE ... RENAME TO commands "
|
||||
"to worker nodes"),
|
||||
errhint("Connect to worker nodes directly to manually "
|
||||
"rename the role")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -853,7 +872,7 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
|
|||
*/
|
||||
if (ops && ops->markDistributed)
|
||||
{
|
||||
List *addresses = GetObjectAddressListFromParseTree(parsetree, false);
|
||||
List *addresses = GetObjectAddressListFromParseTree(parsetree, false, true);
|
||||
ObjectAddress *address = NULL;
|
||||
foreach_ptr(address, addresses)
|
||||
{
|
||||
|
|
|
@ -94,7 +94,7 @@ PostprocessViewStmt(Node *node, const char *queryString)
|
|||
return NIL;
|
||||
}
|
||||
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false);
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, false, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(viewAddresses) == 1);
|
||||
|
@ -158,7 +158,7 @@ PostprocessViewStmt(Node *node, const char *queryString)
|
|||
* CREATE [OR REPLACE] VIEW statement.
|
||||
*/
|
||||
List *
|
||||
ViewStmtObjectAddress(Node *node, bool missing_ok)
|
||||
ViewStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
ViewStmt *stmt = castNode(ViewStmt, node);
|
||||
|
||||
|
@ -221,6 +221,33 @@ PreprocessDropViewStmt(Node *node, const char *queryString, ProcessUtilityContex
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* DropViewStmtObjectAddress returns list of object addresses in the drop view
|
||||
* statement.
|
||||
*/
|
||||
List *
|
||||
DropViewStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
DropStmt *dropStmt = castNode(DropStmt, stmt);
|
||||
|
||||
List *objectAddresses = NIL;
|
||||
|
||||
List *possiblyQualifiedViewName = NULL;
|
||||
foreach_ptr(possiblyQualifiedViewName, dropStmt->objects)
|
||||
{
|
||||
RangeVar *viewRangeVar = makeRangeVarFromNameList(possiblyQualifiedViewName);
|
||||
Oid viewOid = RangeVarGetRelid(viewRangeVar, AccessShareLock,
|
||||
missing_ok);
|
||||
|
||||
ObjectAddress *objectAddress = palloc0(sizeof(ObjectAddress));
|
||||
ObjectAddressSet(*objectAddress, RelationRelationId, viewOid);
|
||||
objectAddresses = lappend(objectAddresses, objectAddress);
|
||||
}
|
||||
|
||||
return objectAddresses;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FilterNameListForDistributedViews takes a list of view names and filters against the
|
||||
* views that are distributed.
|
||||
|
@ -462,7 +489,7 @@ PreprocessAlterViewStmt(Node *node, const char *queryString, ProcessUtilityConte
|
|||
{
|
||||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true);
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(viewAddresses) == 1);
|
||||
|
@ -504,7 +531,7 @@ PostprocessAlterViewStmt(Node *node, const char *queryString)
|
|||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_VIEW);
|
||||
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true);
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(viewAddresses) == 1);
|
||||
|
@ -536,7 +563,7 @@ PostprocessAlterViewStmt(Node *node, const char *queryString)
|
|||
* ALTER VIEW statement.
|
||||
*/
|
||||
List *
|
||||
AlterViewStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterViewStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||
Oid viewOid = RangeVarGetRelid(stmt->relation, NoLock, missing_ok);
|
||||
|
@ -556,7 +583,7 @@ List *
|
|||
PreprocessRenameViewStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext)
|
||||
{
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree(node, true);
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree(node, true, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(viewAddresses) == 1);
|
||||
|
@ -595,7 +622,7 @@ PreprocessRenameViewStmt(Node *node, const char *queryString,
|
|||
* of the RenameStmt. Errors if missing_ok is false.
|
||||
*/
|
||||
List *
|
||||
RenameViewStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameViewStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
|
||||
|
@ -618,7 +645,7 @@ PreprocessAlterViewSchemaStmt(Node *node, const char *queryString,
|
|||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true);
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true, false);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(viewAddresses) == 1);
|
||||
|
@ -660,7 +687,7 @@ PostprocessAlterViewSchemaStmt(Node *node, const char *queryString)
|
|||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true);
|
||||
List *viewAddresses = GetObjectAddressListFromParseTree((Node *) stmt, true, true);
|
||||
|
||||
/* the code-path only supports a single object */
|
||||
Assert(list_length(viewAddresses) == 1);
|
||||
|
@ -682,7 +709,7 @@ PostprocessAlterViewSchemaStmt(Node *node, const char *queryString)
|
|||
* of the alter schema statement.
|
||||
*/
|
||||
List *
|
||||
AlterViewSchemaStmtObjectAddress(Node *node, bool missing_ok)
|
||||
AlterViewSchemaStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ InitializeConnectionManagement(void)
|
|||
* management. Doing so, instead of allocating in TopMemoryContext, makes
|
||||
* it easier to associate used memory.
|
||||
*/
|
||||
ConnectionContext = AllocSetContextCreateExtended(TopMemoryContext,
|
||||
ConnectionContext = AllocSetContextCreateInternal(TopMemoryContext,
|
||||
"Connection Context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
|
|
|
@ -969,7 +969,6 @@ ResetPlacementConnectionManagement(void)
|
|||
hash_delete_all(ConnectionPlacementHash);
|
||||
hash_delete_all(ConnectionShardHash);
|
||||
hash_delete_all(ColocatedPlacementsHash);
|
||||
ResetRelationAccessHash();
|
||||
|
||||
/*
|
||||
* NB: memory for ConnectionReference structs and subordinate data is
|
||||
|
@ -1089,9 +1088,6 @@ InitPlacementConnectionManagement(void)
|
|||
|
||||
ConnectionShardHash = hash_create("citus connection cache (shardid)",
|
||||
64, &info, hashFlags);
|
||||
|
||||
/* (relationId) = [relationAccessMode] hash */
|
||||
AllocateRelationAccessHash();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ IncrementSharedConnectionCounter(const char *hostname, int port)
|
|||
{
|
||||
SharedConnStatsHashKey connKey;
|
||||
|
||||
if (GetMaxSharedPoolSize() == DISABLE_CONNECTION_THROTTLING)
|
||||
if (MaxSharedPoolSize == DISABLE_CONNECTION_THROTTLING)
|
||||
{
|
||||
/* connection throttling disabled */
|
||||
return;
|
||||
|
@ -484,7 +484,11 @@ DecrementSharedConnectionCounter(const char *hostname, int port)
|
|||
{
|
||||
SharedConnStatsHashKey connKey;
|
||||
|
||||
if (GetMaxSharedPoolSize() == DISABLE_CONNECTION_THROTTLING)
|
||||
/*
|
||||
* Do not call GetMaxSharedPoolSize() here, since it may read from
|
||||
* the catalog and we may be in the process exit handler.
|
||||
*/
|
||||
if (MaxSharedPoolSize == DISABLE_CONNECTION_THROTTLING)
|
||||
{
|
||||
/* connection throttling disabled */
|
||||
return;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* tree.
|
||||
*/
|
||||
List *
|
||||
GetObjectAddressListFromParseTree(Node *parseTree, bool missing_ok)
|
||||
GetObjectAddressListFromParseTree(Node *parseTree, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
const DistributeObjectOps *ops = GetDistributeObjectOps(parseTree);
|
||||
|
||||
|
@ -33,12 +33,12 @@ GetObjectAddressListFromParseTree(Node *parseTree, bool missing_ok)
|
|||
ereport(ERROR, (errmsg("unsupported statement to get object address for")));
|
||||
}
|
||||
|
||||
return ops->address(parseTree, missing_ok);
|
||||
return ops->address(parseTree, missing_ok, isPostprocess);
|
||||
}
|
||||
|
||||
|
||||
List *
|
||||
RenameAttributeStmtObjectAddress(Node *node, bool missing_ok)
|
||||
RenameAttributeStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||
Assert(stmt->renameType == OBJECT_ATTRIBUTE);
|
||||
|
@ -68,7 +68,7 @@ RenameAttributeStmtObjectAddress(Node *node, bool missing_ok)
|
|||
* to true.
|
||||
*/
|
||||
List *
|
||||
CreateExtensionStmtObjectAddress(Node *node, bool missing_ok)
|
||||
CreateExtensionStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess)
|
||||
{
|
||||
CreateExtensionStmt *stmt = castNode(CreateExtensionStmt, node);
|
||||
ObjectAddress *address = palloc0(sizeof(ObjectAddress));
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
|
||||
#include "pg_config.h"
|
||||
|
||||
#if (PG_VERSION_NUM >= PG_VERSION_14) && (PG_VERSION_NUM < PG_VERSION_15)
|
||||
/* We should drop PG 15 support from this file, this is only for testing purposes until #6085 is merged. */
|
||||
#if (PG_VERSION_NUM >= PG_VERSION_14) && (PG_VERSION_NUM <= PG_VERSION_15)
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
bool EnableRepartitionedInsertSelect = true;
|
||||
|
||||
|
||||
static Query * WrapSubquery(Query *subquery);
|
||||
static List * TwoPhaseInsertSelectTaskList(Oid targetRelationId, Query *insertSelectQuery,
|
||||
char *resultIdPrefix);
|
||||
static void ExecutePlanIntoRelation(Oid targetRelationId, List *insertTargetList,
|
||||
|
@ -299,100 +298,6 @@ NonPushableInsertSelectExecScan(CustomScanState *node)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* BuildSelectForInsertSelect extracts the SELECT part from an INSERT...SELECT query.
|
||||
* If the INSERT...SELECT has CTEs then these are added to the resulting SELECT instead.
|
||||
*/
|
||||
Query *
|
||||
BuildSelectForInsertSelect(Query *insertSelectQuery)
|
||||
{
|
||||
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
|
||||
Query *selectQuery = selectRte->subquery;
|
||||
|
||||
/*
|
||||
* Wrap the SELECT as a subquery if the INSERT...SELECT has CTEs or the SELECT
|
||||
* has top-level set operations.
|
||||
*
|
||||
* We could simply wrap all queries, but that might create a subquery that is
|
||||
* not supported by the logical planner. Since the logical planner also does
|
||||
* not support CTEs and top-level set operations, we can wrap queries containing
|
||||
* those without breaking anything.
|
||||
*/
|
||||
if (list_length(insertSelectQuery->cteList) > 0)
|
||||
{
|
||||
selectQuery = WrapSubquery(selectRte->subquery);
|
||||
|
||||
/* copy CTEs from the INSERT ... SELECT statement into outer SELECT */
|
||||
selectQuery->cteList = copyObject(insertSelectQuery->cteList);
|
||||
selectQuery->hasModifyingCTE = insertSelectQuery->hasModifyingCTE;
|
||||
}
|
||||
else if (selectQuery->setOperations != NULL)
|
||||
{
|
||||
/* top-level set operations confuse the ReorderInsertSelectTargetLists logic */
|
||||
selectQuery = WrapSubquery(selectRte->subquery);
|
||||
}
|
||||
|
||||
return selectQuery;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* WrapSubquery wraps the given query as a subquery in a newly constructed
|
||||
* "SELECT * FROM (...subquery...) citus_insert_select_subquery" query.
|
||||
*/
|
||||
static Query *
|
||||
WrapSubquery(Query *subquery)
|
||||
{
|
||||
ParseState *pstate = make_parsestate(NULL);
|
||||
List *newTargetList = NIL;
|
||||
|
||||
Query *outerQuery = makeNode(Query);
|
||||
outerQuery->commandType = CMD_SELECT;
|
||||
|
||||
/* create range table entries */
|
||||
Alias *selectAlias = makeAlias("citus_insert_select_subquery", NIL);
|
||||
RangeTblEntry *newRangeTableEntry = RangeTableEntryFromNSItem(
|
||||
addRangeTableEntryForSubquery(
|
||||
pstate, subquery,
|
||||
selectAlias, false, true));
|
||||
outerQuery->rtable = list_make1(newRangeTableEntry);
|
||||
|
||||
/* set the FROM expression to the subquery */
|
||||
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
||||
newRangeTableRef->rtindex = 1;
|
||||
outerQuery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
|
||||
|
||||
/* create a target list that matches the SELECT */
|
||||
TargetEntry *selectTargetEntry = NULL;
|
||||
foreach_ptr(selectTargetEntry, subquery->targetList)
|
||||
{
|
||||
/* exactly 1 entry in FROM */
|
||||
int indexInRangeTable = 1;
|
||||
|
||||
if (selectTargetEntry->resjunk)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Var *newSelectVar = makeVar(indexInRangeTable, selectTargetEntry->resno,
|
||||
exprType((Node *) selectTargetEntry->expr),
|
||||
exprTypmod((Node *) selectTargetEntry->expr),
|
||||
exprCollation((Node *) selectTargetEntry->expr), 0);
|
||||
|
||||
TargetEntry *newSelectTargetEntry = makeTargetEntry((Expr *) newSelectVar,
|
||||
selectTargetEntry->resno,
|
||||
selectTargetEntry->resname,
|
||||
selectTargetEntry->resjunk);
|
||||
|
||||
newTargetList = lappend(newTargetList, newSelectTargetEntry);
|
||||
}
|
||||
|
||||
outerQuery->targetList = newTargetList;
|
||||
|
||||
return outerQuery;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* TwoPhaseInsertSelectTaskList generates a list of tasks for a query that
|
||||
* inserts into a target relation and selects from a set of co-located
|
||||
|
|
|
@ -339,7 +339,7 @@ ExecuteLocalTaskListExtended(List *taskList,
|
|||
* implemented. So, let planner to call distributed_planner() which
|
||||
* eventually calls standard_planner().
|
||||
*/
|
||||
localPlan = planner_compat(shardQuery, cursorOptions, paramListInfo);
|
||||
localPlan = planner(shardQuery, NULL, cursorOptions, paramListInfo);
|
||||
}
|
||||
|
||||
char *shardQueryString = NULL;
|
||||
|
@ -382,8 +382,8 @@ LocallyPlanAndExecuteMultipleQueries(List *queryStrings, TupleDestination *tuple
|
|||
0);
|
||||
int cursorOptions = 0;
|
||||
ParamListInfo paramListInfo = NULL;
|
||||
PlannedStmt *localPlan = planner_compat(shardQuery, cursorOptions,
|
||||
paramListInfo);
|
||||
PlannedStmt *localPlan = planner(shardQuery, NULL, cursorOptions,
|
||||
paramListInfo);
|
||||
totalProcessedRows += LocallyExecuteTaskPlan(localPlan, queryString,
|
||||
tupleDest, task,
|
||||
paramListInfo);
|
||||
|
@ -413,6 +413,9 @@ ExtractParametersForLocalExecution(ParamListInfo paramListInfo, Oid **parameterT
|
|||
static void
|
||||
LocallyExecuteUtilityTask(Task *task)
|
||||
{
|
||||
/* keep the parity with multi-node clusters */
|
||||
RecordNonDistTableAccessesForTask(task);
|
||||
|
||||
/*
|
||||
* If we roll back to a savepoint, we may no longer be in a query on
|
||||
* a shard. Reset the value as we go back up the stack.
|
||||
|
|
|
@ -459,8 +459,8 @@ ReadFileIntoTupleStore(char *fileName, char *copyFormat, TupleDesc tupleDescript
|
|||
ResetPerTupleExprContext(executorState);
|
||||
MemoryContext oldContext = MemoryContextSwitchTo(executorTupleContext);
|
||||
|
||||
bool nextRowFound = NextCopyFromCompat(copyState, executorExpressionContext,
|
||||
columnValues, columnNulls);
|
||||
bool nextRowFound = NextCopyFrom(copyState, executorExpressionContext,
|
||||
columnValues, columnNulls);
|
||||
if (!nextRowFound)
|
||||
{
|
||||
MemoryContextSwitchTo(oldContext);
|
||||
|
@ -554,8 +554,8 @@ SortTupleStore(CitusScanState *scanState)
|
|||
/* iterate over all the sorted tuples, add them to original tuplestore */
|
||||
while (true)
|
||||
{
|
||||
TupleTableSlot *newSlot = MakeSingleTupleTableSlotCompat(tupleDescriptor,
|
||||
&TTSOpsMinimalTuple);
|
||||
TupleTableSlot *newSlot = MakeSingleTupleTableSlot(tupleDescriptor,
|
||||
&TTSOpsMinimalTuple);
|
||||
bool found = tuplesort_gettupleslot(tuplesortstate, true, false, newSlot, NULL);
|
||||
|
||||
if (!found)
|
||||
|
@ -660,7 +660,7 @@ ExecuteQueryIntoDestReceiver(Query *query, ParamListInfo params, DestReceiver *d
|
|||
}
|
||||
|
||||
/* plan the subquery, this may be another distributed query */
|
||||
PlannedStmt *queryPlan = pg_plan_query_compat(query, NULL, cursorOptions, params);
|
||||
PlannedStmt *queryPlan = pg_plan_query(query, NULL, cursorOptions, params);
|
||||
|
||||
ExecutePlanIntoDestReceiver(queryPlan, params, dest);
|
||||
}
|
||||
|
@ -686,7 +686,7 @@ ExecutePlanIntoDestReceiver(PlannedStmt *queryPlan, ParamListInfo params,
|
|||
PortalDefineQuery(portal,
|
||||
NULL,
|
||||
"",
|
||||
CMDTAG_SELECT_COMPAT,
|
||||
CMDTAG_SELECT,
|
||||
list_make1(queryPlan),
|
||||
NULL);
|
||||
|
||||
|
|
|
@ -286,14 +286,14 @@ StartPortalForQueryExecution(const char *queryString)
|
|||
Query *query = ParseQueryString(queryString, NULL, 0);
|
||||
|
||||
int cursorOptions = CURSOR_OPT_PARALLEL_OK;
|
||||
PlannedStmt *queryPlan = pg_plan_query_compat(query, NULL, cursorOptions, NULL);
|
||||
PlannedStmt *queryPlan = pg_plan_query(query, NULL, cursorOptions, NULL);
|
||||
|
||||
Portal portal = CreateNewPortal();
|
||||
|
||||
/* don't display the portal in pg_cursors, it is for internal use only */
|
||||
portal->visible = false;
|
||||
|
||||
PortalDefineQuery(portal, NULL, queryString, CMDTAG_SELECT_COMPAT,
|
||||
PortalDefineQuery(portal, NULL, queryString, CMDTAG_SELECT,
|
||||
list_make1(queryPlan), NULL);
|
||||
int eflags = 0;
|
||||
PortalStart(portal, NULL, eflags, GetActiveSnapshot());
|
||||
|
|
|
@ -868,7 +868,7 @@ BuildExistingQueryIdHash(void)
|
|||
fmgrPGStatStatements->fn_addr,
|
||||
pgStatStatementsOid,
|
||||
commandTypeDatum);
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlotCompat(
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlot(
|
||||
statStatementsReturnSet->setDesc,
|
||||
&TTSOpsMinimalTuple);
|
||||
|
||||
|
|
|
@ -34,7 +34,9 @@
|
|||
#include "catalog/pg_rewrite_d.h"
|
||||
#include "catalog/pg_shdepend.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/extension.h"
|
||||
#include "common/hashfn.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/commands.h"
|
||||
#include "distributed/commands/utility_hook.h"
|
||||
#include "distributed/listutils.h"
|
||||
|
@ -168,11 +170,18 @@ static bool FollowNewSupportedDependencies(ObjectAddressCollector *collector,
|
|||
DependencyDefinition *definition);
|
||||
static bool FollowAllDependencies(ObjectAddressCollector *collector,
|
||||
DependencyDefinition *definition);
|
||||
static bool FollowExtAndInternalDependencies(ObjectAddressCollector *collector,
|
||||
DependencyDefinition *definition);
|
||||
static void ApplyAddToDependencyList(ObjectAddressCollector *collector,
|
||||
DependencyDefinition *definition);
|
||||
static void ApplyAddCitusDependedObjectsToDependencyList(
|
||||
ObjectAddressCollector *collector,
|
||||
DependencyDefinition *definition);
|
||||
static List * GetViewRuleReferenceDependencyList(Oid relationId);
|
||||
static List * ExpandCitusSupportedTypes(ObjectAddressCollector *collector,
|
||||
ObjectAddress target);
|
||||
static List * ExpandForPgVanilla(ObjectAddressCollector *collector,
|
||||
ObjectAddress target);
|
||||
static List * GetDependentRoleIdsFDW(Oid FDWOid);
|
||||
static List * ExpandRolesToGroups(Oid roleid);
|
||||
static ViewDependencyNode * BuildViewDependencyGraph(Oid relationId, HTAB *nodeMap);
|
||||
|
@ -280,6 +289,26 @@ GetAllDependenciesForObject(const ObjectAddress *target)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetAllCitusDependedDependenciesForObject returns all the dependencies
|
||||
* which are owned by citus extension for the target.
|
||||
*/
|
||||
List *
|
||||
GetAllCitusDependedDependenciesForObject(const ObjectAddress *target)
|
||||
{
|
||||
ObjectAddressCollector collector = { 0 };
|
||||
InitObjectAddressCollector(&collector);
|
||||
|
||||
RecurseObjectDependencies(*target,
|
||||
&ExpandForPgVanilla,
|
||||
&FollowExtAndInternalDependencies,
|
||||
&ApplyAddCitusDependedObjectsToDependencyList,
|
||||
&collector);
|
||||
|
||||
return collector.dependencyList;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* OrderObjectAddressListInDependencyOrder given a list of ObjectAddresses return a new
|
||||
* list of the same ObjectAddresses ordered on dependency order where dependencies
|
||||
|
@ -1121,6 +1150,37 @@ IsAnyObjectAddressOwnedByExtension(const List *targets,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* IsObjectAddressOwnedByCitus returns true if the given object address
|
||||
* is owned by the citus or citus_columnar extensions.
|
||||
*/
|
||||
bool
|
||||
IsObjectAddressOwnedByCitus(const ObjectAddress *objectAddress)
|
||||
{
|
||||
Oid citusId = get_extension_oid("citus", true);
|
||||
Oid citusColumnarId = get_extension_oid("citus_columnar", true);
|
||||
|
||||
/* return false because we could not find any citus extension */
|
||||
if (!OidIsValid(citusId) && !OidIsValid(citusColumnarId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectAddress extObjectAddress = InvalidObjectAddress;
|
||||
bool ownedByExt = IsObjectAddressOwnedByExtension(objectAddress,
|
||||
&extObjectAddress);
|
||||
if (!ownedByExt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ownedByCitus = extObjectAddress.objectId == citusId;
|
||||
bool ownedByCitusColumnar = extObjectAddress.objectId == citusColumnarId;
|
||||
|
||||
return ownedByCitus || ownedByCitusColumnar;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FollowNewSupportedDependencies applies filters on pg_depend entries to follow all
|
||||
* objects which should be distributed before the root object can safely be created.
|
||||
|
@ -1302,6 +1362,39 @@ FollowAllDependencies(ObjectAddressCollector *collector,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* FollowExtAndInternalDependencies applies filters on pg_depend entries to follow
|
||||
* the dependency tree of objects in depth first order. We will visit all objects
|
||||
* irrespective of it is supported by Citus or not and it is internal or not.
|
||||
*/
|
||||
static bool
|
||||
FollowExtAndInternalDependencies(ObjectAddressCollector *collector,
|
||||
DependencyDefinition *definition)
|
||||
{
|
||||
ObjectAddress address = DependencyDefinitionObjectAddress(definition);
|
||||
|
||||
/*
|
||||
* If the object is already in our dependency list we do not have to follow any
|
||||
* further
|
||||
*/
|
||||
if (IsObjectAddressCollected(address, collector))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CitusExtensionObject(&address))
|
||||
{
|
||||
/*
|
||||
* We do not need to follow citus extension because the purpose
|
||||
* of our walk is to find if an object is owned by citus.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ApplyAddToDependencyList is an apply function for RecurseObjectDependencies that will
|
||||
* collect all the ObjectAddresses for pg_depend entries to the context, except it is
|
||||
|
@ -1332,6 +1425,30 @@ ApplyAddToDependencyList(ObjectAddressCollector *collector,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* ApplyAddCitusDependedObjectsToDependencyList is an apply function for
|
||||
* RecurseObjectDependencies that will collect all the ObjectAddresses for
|
||||
* pg_depend entries to the context if it is citus extension owned one.
|
||||
*
|
||||
* The context here is assumed to be a (ObjectAddressCollector *) to the location where
|
||||
* all ObjectAddresses will be collected.
|
||||
*/
|
||||
static void
|
||||
ApplyAddCitusDependedObjectsToDependencyList(ObjectAddressCollector *collector,
|
||||
DependencyDefinition *definition)
|
||||
{
|
||||
ObjectAddress address = DependencyDefinitionObjectAddress(definition);
|
||||
|
||||
/*
|
||||
* We only collect the object if it is owned by citus extension.
|
||||
*/
|
||||
if (IsObjectAddressOwnedByCitus(&address))
|
||||
{
|
||||
CollectObjectAddress(collector, &address);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ExpandCitusSupportedTypes base on supported types by citus we might want to expand
|
||||
* the list of objects to visit in pg_depend.
|
||||
|
@ -1498,7 +1615,7 @@ ExpandCitusSupportedTypes(ObjectAddressCollector *collector, ObjectAddress targe
|
|||
* rule and that rule has dependencies to other objects.
|
||||
*/
|
||||
char relKind = get_rel_relkind(relationId);
|
||||
if (relKind == RELKIND_VIEW)
|
||||
if (relKind == RELKIND_VIEW || relKind == RELKIND_MATVIEW)
|
||||
{
|
||||
List *ruleRefDepList = GetViewRuleReferenceDependencyList(relationId);
|
||||
result = list_concat(result, ruleRefDepList);
|
||||
|
@ -1515,6 +1632,39 @@ ExpandCitusSupportedTypes(ObjectAddressCollector *collector, ObjectAddress targe
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* ExpandForPgVanilla only expands only comosite types because other types
|
||||
* will find their dependencies in pg_depend. The method should only be called by
|
||||
* is_citus_depended_object udf.
|
||||
*/
|
||||
static List *
|
||||
ExpandForPgVanilla(ObjectAddressCollector *collector,
|
||||
ObjectAddress target)
|
||||
{
|
||||
/* should only be called if GUC is enabled */
|
||||
Assert(HideCitusDependentObjects == true);
|
||||
|
||||
List *result = NIL;
|
||||
|
||||
if (target.classId == TypeRelationId && get_typtype(target.objectId) ==
|
||||
TYPTYPE_COMPOSITE)
|
||||
{
|
||||
/*
|
||||
* types depending on other types are not captured in pg_depend, instead
|
||||
* they are described with their dependencies by the relation that
|
||||
* describes the composite type.
|
||||
*/
|
||||
Oid typeRelationId = get_typ_typrelid(target.objectId);
|
||||
DependencyDefinition *dependency =
|
||||
CreateObjectAddressDependencyDef(RelationRelationId,
|
||||
typeRelationId);
|
||||
result = lappend(result, dependency);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetDependentRoleIdsFDW returns a list of role oids that has privileges on the
|
||||
* FDW with the given object id.
|
||||
|
@ -1959,6 +2109,23 @@ GetDependingViews(Oid relationId)
|
|||
ViewDependencyNode *dependingNode = NULL;
|
||||
foreach_ptr(dependingNode, node->dependingNodes)
|
||||
{
|
||||
ObjectAddress relationAddress = { 0 };
|
||||
ObjectAddressSet(relationAddress, RelationRelationId, dependingNode->id);
|
||||
|
||||
/*
|
||||
* This function does not catch views with circular dependencies,
|
||||
* because of the remaining dependency count check below.
|
||||
* Here we check if the view has a circular dependency or not.
|
||||
* If yes, we error out with a message that tells the user that
|
||||
* Citus does not handle circular dependencies.
|
||||
*/
|
||||
DeferredErrorMessage *depError =
|
||||
DeferErrorIfCircularDependencyExists(&relationAddress);
|
||||
if (depError != NULL)
|
||||
{
|
||||
RaiseDeferredError(depError, ERROR);
|
||||
}
|
||||
|
||||
dependingNode->remainingDependencyCount--;
|
||||
if (dependingNode->remainingDependencyCount == 0)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "commands/extension.h"
|
||||
#include "commands/trigger.h"
|
||||
#include "distributed/backend_data.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/colocation_utils.h"
|
||||
#include "distributed/connection_management.h"
|
||||
#include "distributed/citus_ruleutils.h"
|
||||
|
@ -182,6 +183,7 @@ typedef struct MetadataCacheData
|
|||
Oid relationIsAKnownShardFuncId;
|
||||
Oid jsonbExtractPathFuncId;
|
||||
Oid jsonbExtractPathTextFuncId;
|
||||
Oid CitusDependentObjectFuncId;
|
||||
bool databaseNameValid;
|
||||
char databaseName[NAMEDATALEN];
|
||||
} MetadataCacheData;
|
||||
|
@ -2206,7 +2208,7 @@ AvailableExtensionVersion(void)
|
|||
/* pg_available_extensions returns result set containing all available extensions */
|
||||
(*pg_available_extensions)(fcinfo);
|
||||
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlotCompat(
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlot(
|
||||
extensionsResultSet->setDesc,
|
||||
&TTSOpsMinimalTuple);
|
||||
bool hasTuple = tuplestore_gettupleslot(extensionsResultSet->setResult, goForward,
|
||||
|
@ -2697,10 +2699,10 @@ CitusCopyFormatTypeId(void)
|
|||
if (MetadataCache.copyFormatTypeId == InvalidOid)
|
||||
{
|
||||
char *typeName = "citus_copy_format";
|
||||
MetadataCache.copyFormatTypeId = GetSysCacheOid2Compat(TYPENAMENSP,
|
||||
Anum_pg_enum_oid,
|
||||
PointerGetDatum(typeName),
|
||||
PG_CATALOG_NAMESPACE);
|
||||
MetadataCache.copyFormatTypeId = GetSysCacheOid2(TYPENAMENSP,
|
||||
Anum_pg_enum_oid,
|
||||
PointerGetDatum(typeName),
|
||||
PG_CATALOG_NAMESPACE);
|
||||
}
|
||||
|
||||
return MetadataCache.copyFormatTypeId;
|
||||
|
@ -2895,6 +2897,30 @@ JsonbExtractPathTextFuncId(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* CitusDependentObjectFuncId returns oid of the is_citus_depended_object function.
|
||||
*/
|
||||
Oid
|
||||
CitusDependentObjectFuncId(void)
|
||||
{
|
||||
if (!HideCitusDependentObjects)
|
||||
{
|
||||
ereport(ERROR, (errmsg(
|
||||
"is_citus_depended_object can only be used while running the regression tests")));
|
||||
}
|
||||
|
||||
if (MetadataCache.CitusDependentObjectFuncId == InvalidOid)
|
||||
{
|
||||
const int argCount = 2;
|
||||
|
||||
MetadataCache.CitusDependentObjectFuncId =
|
||||
FunctionOid("pg_catalog", "is_citus_depended_object", argCount);
|
||||
}
|
||||
|
||||
return MetadataCache.CitusDependentObjectFuncId;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CurrentDatabaseName gets the name of the current database and caches
|
||||
* the result.
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
*
|
||||
* This file contains master_modify_multiple_shards function, which takes a update
|
||||
* or delete query and runs it worker shards of the distributed table. The distributed
|
||||
* modify operation can be done within a distributed transaction and committed in
|
||||
* one-phase or two-phase fashion, depending on the citus.multi_shard_commit_protocol
|
||||
* setting.
|
||||
* modify operation can be done within a distributed transaction.
|
||||
*
|
||||
* Copyright (c) Citus Data, Inc.
|
||||
*
|
||||
|
|
|
@ -170,7 +170,7 @@ master_get_table_ddl_events(PG_FUNCTION_ARGS)
|
|||
Assert(CitusIsA(ddlStatement, TableDDLCommand));
|
||||
text *ddlStatementText = cstring_to_text(GetTableDDLCommand(ddlStatement));
|
||||
|
||||
wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell);
|
||||
wrapper->listCell = lnext(wrapper->list, wrapper->listCell);
|
||||
|
||||
SRF_RETURN_NEXT(functionContext, PointerGetDatum(ddlStatementText));
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "access/htup_details.h"
|
||||
#include "catalog/pg_class.h"
|
||||
#include "catalog/pg_enum.h"
|
||||
#include "distributed/adaptive_executor.h"
|
||||
#include "distributed/citus_ruleutils.h"
|
||||
#include "distributed/colocation_utils.h"
|
||||
#include "distributed/commands.h"
|
||||
|
@ -37,6 +38,8 @@
|
|||
#include "distributed/reference_table_utils.h"
|
||||
#include "distributed/remote_commands.h"
|
||||
#include "distributed/resource_lock.h"
|
||||
#include "distributed/shard_rebalancer.h"
|
||||
#include "distributed/shard_split.h"
|
||||
#include "distributed/worker_manager.h"
|
||||
#include "distributed/worker_protocol.h"
|
||||
#include "distributed/worker_transaction.h"
|
||||
|
@ -128,6 +131,7 @@ static List * PostLoadShardCreationCommandList(ShardInterval *shardInterval,
|
|||
int32 sourceNodePort);
|
||||
static ShardCommandList * CreateShardCommandList(ShardInterval *shardInterval,
|
||||
List *ddlCommandList);
|
||||
static char * CreateShardCopyCommand(ShardInterval *shard, WorkerNode *targetNode);
|
||||
|
||||
|
||||
/* declarations for dynamic loading */
|
||||
|
@ -179,6 +183,9 @@ citus_copy_shard_placement(PG_FUNCTION_ARGS)
|
|||
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
||||
ErrorIfTableCannotBeReplicated(shardInterval->relationId);
|
||||
|
||||
AcquirePlacementColocationLock(shardInterval->relationId, ExclusiveLock,
|
||||
doRepair ? "repair" : "copy");
|
||||
|
||||
if (doRepair)
|
||||
{
|
||||
RepairShardPlacement(shardId, sourceNodeName, sourceNodePort, targetNodeName,
|
||||
|
@ -332,6 +339,8 @@ citus_move_shard_placement(PG_FUNCTION_ARGS)
|
|||
ErrorIfMoveUnsupportedTableType(relationId);
|
||||
ErrorIfTargetNodeIsNotSafeToMove(targetNodeName, targetNodePort);
|
||||
|
||||
AcquirePlacementColocationLock(relationId, ExclusiveLock, "move");
|
||||
|
||||
ShardInterval *shardInterval = LoadShardInterval(shardId);
|
||||
Oid distributedTableId = shardInterval->relationId;
|
||||
|
||||
|
@ -1174,6 +1183,9 @@ CopyShardTablesViaBlockWrites(List *shardIntervalList, char *sourceNodeName,
|
|||
ALLOCSET_DEFAULT_SIZES);
|
||||
MemoryContext oldContext = MemoryContextSwitchTo(localContext);
|
||||
|
||||
WorkerNode *sourceNode = FindWorkerNode(sourceNodeName, sourceNodePort);
|
||||
WorkerNode *targetNode = FindWorkerNode(targetNodeName, targetNodePort);
|
||||
|
||||
/* iterate through the colocated shards and copy each */
|
||||
ShardInterval *shardInterval = NULL;
|
||||
foreach_ptr(shardInterval, shardIntervalList)
|
||||
|
@ -1193,9 +1205,12 @@ CopyShardTablesViaBlockWrites(List *shardIntervalList, char *sourceNodeName,
|
|||
char *tableOwner = TableOwner(shardInterval->relationId);
|
||||
SendCommandListToWorkerOutsideTransaction(targetNodeName, targetNodePort,
|
||||
tableOwner, ddlCommandList);
|
||||
}
|
||||
|
||||
ddlCommandList = NIL;
|
||||
|
||||
int taskId = 0;
|
||||
List *copyTaskList = NIL;
|
||||
foreach_ptr(shardInterval, shardIntervalList)
|
||||
{
|
||||
/*
|
||||
* Skip copying data for partitioned tables, because they contain no
|
||||
* data themselves. Their partitions do contain data, but those are
|
||||
|
@ -1203,13 +1218,35 @@ CopyShardTablesViaBlockWrites(List *shardIntervalList, char *sourceNodeName,
|
|||
*/
|
||||
if (!PartitionedTable(shardInterval->relationId))
|
||||
{
|
||||
ddlCommandList = CopyShardContentsCommandList(shardInterval, sourceNodeName,
|
||||
sourceNodePort);
|
||||
char *copyCommand = CreateShardCopyCommand(
|
||||
shardInterval, targetNode);
|
||||
|
||||
Task *copyTask = CreateBasicTask(
|
||||
INVALID_JOB_ID,
|
||||
taskId,
|
||||
READ_TASK,
|
||||
copyCommand);
|
||||
|
||||
ShardPlacement *taskPlacement = CitusMakeNode(ShardPlacement);
|
||||
SetPlacementNodeMetadata(taskPlacement, sourceNode);
|
||||
|
||||
copyTask->taskPlacementList = list_make1(taskPlacement);
|
||||
|
||||
copyTaskList = lappend(copyTaskList, copyTask);
|
||||
taskId++;
|
||||
}
|
||||
ddlCommandList = list_concat(
|
||||
ddlCommandList,
|
||||
}
|
||||
|
||||
ExecuteTaskListOutsideTransaction(ROW_MODIFY_NONE, copyTaskList,
|
||||
MaxAdaptiveExecutorPoolSize,
|
||||
NULL /* jobIdList (ignored by API implementation) */);
|
||||
|
||||
foreach_ptr(shardInterval, shardIntervalList)
|
||||
{
|
||||
List *ddlCommandList =
|
||||
PostLoadShardCreationCommandList(shardInterval, sourceNodeName,
|
||||
sourceNodePort));
|
||||
sourceNodePort);
|
||||
char *tableOwner = TableOwner(shardInterval->relationId);
|
||||
SendCommandListToWorkerOutsideTransaction(targetNodeName, targetNodePort,
|
||||
tableOwner, ddlCommandList);
|
||||
|
||||
|
@ -1272,6 +1309,25 @@ CopyShardTablesViaBlockWrites(List *shardIntervalList, char *sourceNodeName,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* CreateShardCopyCommand constructs the command to copy a shard to another
|
||||
* worker node. This command needs to be run on the node wher you want to copy
|
||||
* the shard from.
|
||||
*/
|
||||
static char *
|
||||
CreateShardCopyCommand(ShardInterval *shard,
|
||||
WorkerNode *targetNode)
|
||||
{
|
||||
char *shardName = ConstructQualifiedShardName(shard);
|
||||
StringInfo query = makeStringInfo();
|
||||
appendStringInfo(query,
|
||||
"SELECT pg_catalog.worker_copy_table_to_node(%s::regclass, %u);",
|
||||
quote_literal_cstr(shardName),
|
||||
targetNode->nodeId);
|
||||
return query->data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CopyPartitionShardsCommandList gets a shardInterval which is a shard that
|
||||
* belongs to partitioned table (this is asserted).
|
||||
|
|
|
@ -227,7 +227,7 @@ static float4 NodeCapacity(WorkerNode *workerNode, void *context);
|
|||
static ShardCost GetShardCost(uint64 shardId, void *context);
|
||||
static List * NonColocatedDistRelationIdList(void);
|
||||
static void RebalanceTableShards(RebalanceOptions *options, Oid shardReplicationModeOid);
|
||||
static void AcquireColocationLock(Oid relationId, const char *operationName);
|
||||
static void AcquireRebalanceColocationLock(Oid relationId, const char *operationName);
|
||||
static void ExecutePlacementUpdates(List *placementUpdateList, Oid
|
||||
shardReplicationModeOid, char *noticeOperation);
|
||||
static float4 CalculateUtilization(float4 totalCost, float4 capacity);
|
||||
|
@ -616,13 +616,13 @@ GetColocatedRebalanceSteps(List *placementUpdateList)
|
|||
|
||||
|
||||
/*
|
||||
* AcquireColocationLock tries to acquire a lock for rebalance/replication. If
|
||||
* this is it not possible it fails instantly because this means another
|
||||
* rebalance/replication is currently happening. This would really mess up
|
||||
* planning.
|
||||
* AcquireRelationColocationLock tries to acquire a lock for
|
||||
* rebalance/replication. If this is it not possible it fails
|
||||
* instantly because this means another rebalance/replication
|
||||
* is currently happening. This would really mess up planning.
|
||||
*/
|
||||
static void
|
||||
AcquireColocationLock(Oid relationId, const char *operationName)
|
||||
AcquireRebalanceColocationLock(Oid relationId, const char *operationName)
|
||||
{
|
||||
uint32 lockId = relationId;
|
||||
LOCKTAG tag;
|
||||
|
@ -639,8 +639,48 @@ AcquireColocationLock(Oid relationId, const char *operationName)
|
|||
if (!lockAcquired)
|
||||
{
|
||||
ereport(ERROR, (errmsg("could not acquire the lock required to %s %s",
|
||||
operationName, generate_qualified_relation_name(
|
||||
relationId))));
|
||||
operationName,
|
||||
generate_qualified_relation_name(relationId)),
|
||||
errdetail("It means that either a concurrent shard move "
|
||||
"or shard copy is happening."),
|
||||
errhint("Make sure that the concurrent operation has "
|
||||
"finished and re-run the command")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AcquirePlacementColocationLock tries to acquire a lock for
|
||||
* rebalance/replication while moving/copying the placement. If this
|
||||
* is it not possible it fails instantly because this means
|
||||
* another move/copy is currently happening. This would really mess up planning.
|
||||
*/
|
||||
void
|
||||
AcquirePlacementColocationLock(Oid relationId, int lockMode,
|
||||
const char *operationName)
|
||||
{
|
||||
uint32 lockId = relationId;
|
||||
LOCKTAG tag;
|
||||
|
||||
CitusTableCacheEntry *citusTableCacheEntry = GetCitusTableCacheEntry(relationId);
|
||||
if (citusTableCacheEntry->colocationId != INVALID_COLOCATION_ID)
|
||||
{
|
||||
lockId = citusTableCacheEntry->colocationId;
|
||||
}
|
||||
|
||||
SET_LOCKTAG_REBALANCE_PLACEMENT_COLOCATION(tag, (int64) lockId);
|
||||
|
||||
LockAcquireResult lockAcquired = LockAcquire(&tag, lockMode, false, true);
|
||||
if (!lockAcquired)
|
||||
{
|
||||
ereport(ERROR, (errmsg("could not acquire the lock required to %s %s",
|
||||
operationName,
|
||||
generate_qualified_relation_name(relationId)),
|
||||
errdetail("It means that either a concurrent shard move "
|
||||
"or colocated distributed table creation is "
|
||||
"happening."),
|
||||
errhint("Make sure that the concurrent operation has "
|
||||
"finished and re-run the command")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -942,7 +982,7 @@ replicate_table_shards(PG_FUNCTION_ARGS)
|
|||
char transferMode = LookupShardTransferMode(shardReplicationModeOid);
|
||||
EnsureReferenceTablesExistOnAllNodesExtended(transferMode);
|
||||
|
||||
AcquireColocationLock(relationId, "replicate");
|
||||
AcquireRebalanceColocationLock(relationId, "replicate");
|
||||
|
||||
List *activeWorkerList = SortedActiveWorkers();
|
||||
List *shardPlacementList = FullShardPlacementList(relationId, excludedShardArray);
|
||||
|
@ -1555,7 +1595,7 @@ RebalanceTableShards(RebalanceOptions *options, Oid shardReplicationModeOid)
|
|||
|
||||
foreach_oid(relationId, options->relationIdList)
|
||||
{
|
||||
AcquireColocationLock(relationId, operationName);
|
||||
AcquireRebalanceColocationLock(relationId, operationName);
|
||||
}
|
||||
|
||||
List *placementUpdateList = GetRebalanceSteps(options);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "commands/dbcommands.h"
|
||||
#include "distributed/shardsplit_logical_replication.h"
|
||||
#include "distributed/deparse_shard_query.h"
|
||||
#include "distributed/shard_rebalancer.h"
|
||||
|
||||
/*
|
||||
* Entry for map that tracks ShardInterval -> Placement Node
|
||||
|
@ -376,6 +377,9 @@ SplitShard(SplitMode splitMode,
|
|||
ShardInterval *shardIntervalToSplit = LoadShardInterval(shardIdToSplit);
|
||||
List *colocatedTableList = ColocatedTableList(shardIntervalToSplit->relationId);
|
||||
|
||||
Oid relationId = RelationIdForShard(shardIdToSplit);
|
||||
AcquirePlacementColocationLock(relationId, ExclusiveLock, "split");
|
||||
|
||||
/* sort the tables to avoid deadlocks */
|
||||
colocatedTableList = SortList(colocatedTableList, CompareOids);
|
||||
Oid colocatedTableId = InvalidOid;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* worker_copy_table_to_node_udf.c
|
||||
*
|
||||
* This file implements the worker_copy_table_to_node UDF. This UDF can be
|
||||
* used to copy the data in a shard (or other table) from one worker node to
|
||||
* another.
|
||||
*
|
||||
* Copyright (c) Citus Data, Inc.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "distributed/citus_ruleutils.h"
|
||||
#include "distributed/metadata_cache.h"
|
||||
#include "distributed/multi_executor.h"
|
||||
#include "distributed/worker_shard_copy.h"
|
||||
|
||||
PG_FUNCTION_INFO_V1(worker_copy_table_to_node);
|
||||
|
||||
/*
|
||||
* worker_copy_table_to_node copies a shard from this worker to another worker
|
||||
*
|
||||
* SQL signature:
|
||||
*
|
||||
* worker_copy_table_to_node(
|
||||
* source_table regclass,
|
||||
* target_node_id integer
|
||||
* ) RETURNS VOID
|
||||
*/
|
||||
Datum
|
||||
worker_copy_table_to_node(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid relationId = PG_GETARG_OID(0);
|
||||
uint32_t targetNodeId = PG_GETARG_INT32(1);
|
||||
|
||||
Oid schemaOid = get_rel_namespace(relationId);
|
||||
char *relationSchemaName = get_namespace_name(schemaOid);
|
||||
char *relationName = get_rel_name(relationId);
|
||||
char *relationQualifiedName = quote_qualified_identifier(
|
||||
relationSchemaName,
|
||||
relationName);
|
||||
|
||||
EState *executor = CreateExecutorState();
|
||||
DestReceiver *destReceiver = CreateShardCopyDestReceiver(
|
||||
executor,
|
||||
list_make2(relationSchemaName, relationName),
|
||||
targetNodeId);
|
||||
|
||||
StringInfo selectShardQueryForCopy = makeStringInfo();
|
||||
appendStringInfo(selectShardQueryForCopy,
|
||||
"SELECT * FROM %s;", relationQualifiedName);
|
||||
|
||||
ParamListInfo params = NULL;
|
||||
ExecuteQueryStringIntoDestReceiver(selectShardQueryForCopy->data, params,
|
||||
destReceiver);
|
||||
|
||||
FreeExecutorState(executor);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
|
@ -295,7 +295,7 @@ BuildSelectStatementViaStdPlanner(Query *combineQuery, List *remoteScanTargetLis
|
|||
ReplaceCitusExtraDataContainer = true;
|
||||
ReplaceCitusExtraDataContainerWithCustomScan = remoteScan;
|
||||
|
||||
standardStmt = standard_planner_compat(combineQuery, 0, NULL);
|
||||
standardStmt = standard_planner(combineQuery, NULL, 0, NULL);
|
||||
|
||||
ReplaceCitusExtraDataContainer = false;
|
||||
ReplaceCitusExtraDataContainerWithCustomScan = NULL;
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
#include <limits.h>
|
||||
|
||||
#include "access/htup_details.h"
|
||||
#include "access/xact.h"
|
||||
#include "catalog/pg_class.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/citus_nodefuncs.h"
|
||||
#include "distributed/citus_nodes.h"
|
||||
#include "distributed/citus_ruleutils.h"
|
||||
|
@ -204,6 +206,13 @@ distributed_planner(Query *parse,
|
|||
*/
|
||||
HideShardsFromSomeApplications(parse);
|
||||
|
||||
/*
|
||||
* If GUC is set, we prevent queries, which contain pg meta relations, from
|
||||
* showing any citus dependent object. The flag is expected to be set only before
|
||||
* postgres vanilla tests.
|
||||
*/
|
||||
HideCitusDependentObjectsOnQueriesOfPgMetaTables((Node *) parse, NULL);
|
||||
|
||||
/* create a restriction context and put it at the end if context list */
|
||||
planContext.plannerRestrictionContext = CreateAndPushPlannerRestrictionContext();
|
||||
|
||||
|
@ -230,9 +239,9 @@ distributed_planner(Query *parse,
|
|||
* restriction information per table and parse tree transformations made by
|
||||
* postgres' planner.
|
||||
*/
|
||||
planContext.plan = standard_planner_compat(planContext.query,
|
||||
planContext.cursorOptions,
|
||||
planContext.boundParams);
|
||||
planContext.plan = standard_planner(planContext.query, NULL,
|
||||
planContext.cursorOptions,
|
||||
planContext.boundParams);
|
||||
if (needsDistributedPlanning)
|
||||
{
|
||||
result = PlanDistributedStmt(&planContext, rteIdCounter);
|
||||
|
@ -345,6 +354,17 @@ ListContainsDistributedTableRTE(List *rangeTableList,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (HideCitusDependentObjects && IsolationIsSerializable() && IsPgLocksTable(
|
||||
rangeTableEntry))
|
||||
{
|
||||
/*
|
||||
* Postgres tidscan.sql test fails if we do not filter pg_locks table because
|
||||
* test results, which show taken locks in serializable isolation mode,
|
||||
* fails by showing extra lock taken by IsCitusTable below.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsCitusTable(rangeTableEntry->relid))
|
||||
{
|
||||
if (maybeHasForeignDistributedTable != NULL &&
|
||||
|
@ -1004,7 +1024,7 @@ CreateDistributedPlan(uint64 planId, Query *originalQuery, Query *query, ParamLi
|
|||
* being contiguous.
|
||||
*/
|
||||
|
||||
standard_planner_compat(newQuery, 0, boundParams);
|
||||
standard_planner(newQuery, NULL, 0, boundParams);
|
||||
|
||||
/* overwrite the old transformed query with the new transformed query */
|
||||
*query = *newQuery;
|
||||
|
|
|
@ -48,8 +48,10 @@
|
|||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/rel.h"
|
||||
#include <nodes/print.h>
|
||||
|
||||
|
||||
static void PrepareInsertSelectForCitusPlanner(Query *insertSelectQuery);
|
||||
static DistributedPlan * CreateInsertSelectPlanInternal(uint64 planId,
|
||||
Query *originalQuery,
|
||||
PlannerRestrictionContext *
|
||||
|
@ -83,6 +85,7 @@ static DeferredErrorMessage * InsertPartitionColumnMatchesSelect(Query *query,
|
|||
static DistributedPlan * CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse,
|
||||
ParamListInfo boundParams);
|
||||
static DeferredErrorMessage * NonPushableInsertSelectSupported(Query *insertSelectQuery);
|
||||
static Query * WrapSubquery(Query *subquery);
|
||||
static void RelabelTargetEntryList(List *selectTargetList, List *insertTargetList);
|
||||
static List * AddInsertSelectCasts(List *insertTargetList, List *selectTargetList,
|
||||
Oid targetRelationId);
|
||||
|
@ -370,14 +373,17 @@ CreateDistributedInsertSelectPlan(Query *originalQuery,
|
|||
* combineQuery, this function also creates a dummy combineQuery for that.
|
||||
*/
|
||||
DistributedPlan *
|
||||
CreateInsertSelectIntoLocalTablePlan(uint64 planId, Query *originalQuery, ParamListInfo
|
||||
boundParams, bool hasUnresolvedParams,
|
||||
CreateInsertSelectIntoLocalTablePlan(uint64 planId, Query *insertSelectQuery,
|
||||
ParamListInfo boundParams, bool hasUnresolvedParams,
|
||||
PlannerRestrictionContext *plannerRestrictionContext)
|
||||
{
|
||||
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(originalQuery);
|
||||
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
|
||||
|
||||
PrepareInsertSelectForCitusPlanner(insertSelectQuery);
|
||||
|
||||
/* get the SELECT query (may have changed after PrepareInsertSelectForCitusPlanner) */
|
||||
Query *selectQuery = selectRte->subquery;
|
||||
|
||||
Query *selectQuery = BuildSelectForInsertSelect(originalQuery);
|
||||
originalQuery->cteList = NIL;
|
||||
DistributedPlan *distPlan = CreateDistributedPlan(planId, selectQuery,
|
||||
copyObject(selectQuery),
|
||||
boundParams, hasUnresolvedParams,
|
||||
|
@ -417,12 +423,84 @@ CreateInsertSelectIntoLocalTablePlan(uint64 planId, Query *originalQuery, ParamL
|
|||
* distributed select instead of returning it.
|
||||
*/
|
||||
selectRte->subquery = distPlan->combineQuery;
|
||||
distPlan->combineQuery = originalQuery;
|
||||
distPlan->combineQuery = insertSelectQuery;
|
||||
|
||||
return distPlan;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PrepareInsertSelectForCitusPlanner prepares an INSERT..SELECT query tree
|
||||
* that was passed to the planner for use by Citus.
|
||||
*
|
||||
* First, it rebuilds the target lists of the INSERT and the SELECT
|
||||
* to be in the same order, which is not guaranteed in the parse tree.
|
||||
*
|
||||
* Second, some of the constants in the target list will have type
|
||||
* "unknown", which would confuse the Citus planner. To address that,
|
||||
* we add casts to SELECT target list entries whose type does not correspond
|
||||
* to the destination. This also helps us feed the output directly into
|
||||
* a COPY stream for INSERT..SELECT via coordinator.
|
||||
*
|
||||
* In case of UNION or other set operations, the SELECT does not have a
|
||||
* clearly defined target list, so we first wrap the UNION in a subquery.
|
||||
* UNION queries do not have the "unknown" type problem.
|
||||
*
|
||||
* Finally, if the INSERT has CTEs, we move those CTEs into the SELECT,
|
||||
* such that we can plan the SELECT as an independent query. To ensure
|
||||
* the ctelevelsup for CTE RTE's remain the same, we wrap the SELECT into
|
||||
* a subquery, unless we already did so in case of a UNION.
|
||||
*/
|
||||
static void
|
||||
PrepareInsertSelectForCitusPlanner(Query *insertSelectQuery)
|
||||
{
|
||||
RangeTblEntry *insertRte = ExtractResultRelationRTEOrError(insertSelectQuery);
|
||||
RangeTblEntry *selectRte = ExtractSelectRangeTableEntry(insertSelectQuery);
|
||||
Oid targetRelationId = insertRte->relid;
|
||||
|
||||
bool isWrapped = false;
|
||||
|
||||
if (selectRte->subquery->setOperations != NULL)
|
||||
{
|
||||
/*
|
||||
* Prepare UNION query for reordering and adding casts by
|
||||
* wrapping it in a subquery to have a single target list.
|
||||
*/
|
||||
selectRte->subquery = WrapSubquery(selectRte->subquery);
|
||||
isWrapped = true;
|
||||
}
|
||||
|
||||
/* this is required for correct deparsing of the query */
|
||||
ReorderInsertSelectTargetLists(insertSelectQuery, insertRte, selectRte);
|
||||
|
||||
/*
|
||||
* Cast types of insert target list and select projection list to
|
||||
* match the column types of the target relation.
|
||||
*/
|
||||
selectRte->subquery->targetList =
|
||||
AddInsertSelectCasts(insertSelectQuery->targetList,
|
||||
copyObject(selectRte->subquery->targetList),
|
||||
targetRelationId);
|
||||
|
||||
if (list_length(insertSelectQuery->cteList) > 0)
|
||||
{
|
||||
if (!isWrapped)
|
||||
{
|
||||
/*
|
||||
* By wrapping the SELECT in a subquery, we can avoid adjusting
|
||||
* ctelevelsup in RTE's that point to the CTEs.
|
||||
*/
|
||||
selectRte->subquery = WrapSubquery(selectRte->subquery);
|
||||
}
|
||||
|
||||
/* copy CTEs from the INSERT ... SELECT statement into outer SELECT */
|
||||
selectRte->subquery->cteList = copyObject(insertSelectQuery->cteList);
|
||||
selectRte->subquery->hasModifyingCTE = insertSelectQuery->hasModifyingCTE;
|
||||
insertSelectQuery->cteList = NIL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CreateCombineQueryForRouterPlan is used for creating a dummy combineQuery
|
||||
* for a router plan, since router plans normally don't have one.
|
||||
|
@ -881,12 +959,11 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
|
|||
ListCell *insertTargetEntryCell;
|
||||
List *newSubqueryTargetlist = NIL;
|
||||
List *newInsertTargetlist = NIL;
|
||||
List *columnNameList = NIL;
|
||||
int resno = 1;
|
||||
Index insertTableId = 1;
|
||||
Index selectTableId = 2;
|
||||
int targetEntryIndex = 0;
|
||||
|
||||
AssertArg(InsertSelectIntoCitusTable(originalQuery));
|
||||
|
||||
Query *subquery = subqueryRte->subquery;
|
||||
|
||||
Oid insertRelationId = insertRte->relid;
|
||||
|
@ -910,7 +987,7 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
|
|||
oldInsertTargetEntry->resname);
|
||||
|
||||
/* see transformInsertRow() for the details */
|
||||
if (IsA(oldInsertTargetEntry->expr, ArrayRef) ||
|
||||
if (IsA(oldInsertTargetEntry->expr, SubscriptingRef) ||
|
||||
IsA(oldInsertTargetEntry->expr, FieldStore))
|
||||
{
|
||||
ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
|
@ -954,6 +1031,9 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
|
|||
newSubqueryTargetEntry);
|
||||
}
|
||||
|
||||
String *columnName = makeString(newSubqueryTargetEntry->resname);
|
||||
columnNameList = lappend(columnNameList, columnName);
|
||||
|
||||
/*
|
||||
* The newly created select target entry cannot be a junk entry since junk
|
||||
* entries are not in the final target list and we're processing the
|
||||
|
@ -961,7 +1041,7 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
|
|||
*/
|
||||
Assert(!newSubqueryTargetEntry->resjunk);
|
||||
|
||||
Var *newInsertVar = makeVar(insertTableId, originalAttrNo,
|
||||
Var *newInsertVar = makeVar(selectTableId, resno,
|
||||
exprType((Node *) newSubqueryTargetEntry->expr),
|
||||
exprTypmod((Node *) newSubqueryTargetEntry->expr),
|
||||
exprCollation((Node *) newSubqueryTargetEntry->expr),
|
||||
|
@ -1005,6 +1085,7 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
|
|||
|
||||
originalQuery->targetList = newInsertTargetlist;
|
||||
subquery->targetList = newSubqueryTargetlist;
|
||||
subqueryRte->eref->colnames = columnNameList;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1412,19 +1493,10 @@ CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse, ParamListInfo bou
|
|||
return distributedPlan;
|
||||
}
|
||||
|
||||
Query *selectQuery = BuildSelectForInsertSelect(insertSelectQuery);
|
||||
PrepareInsertSelectForCitusPlanner(insertSelectQuery);
|
||||
|
||||
selectRte->subquery = selectQuery;
|
||||
ReorderInsertSelectTargetLists(insertSelectQuery, insertRte, selectRte);
|
||||
|
||||
/*
|
||||
* Cast types of insert target list and select projection list to
|
||||
* match the column types of the target relation.
|
||||
*/
|
||||
selectQuery->targetList =
|
||||
AddInsertSelectCasts(insertSelectQuery->targetList,
|
||||
selectQuery->targetList,
|
||||
targetRelationId);
|
||||
/* get the SELECT query (may have changed after PrepareInsertSelectForCitusPlanner) */
|
||||
Query *selectQuery = selectRte->subquery;
|
||||
|
||||
/*
|
||||
* Later we might need to call WrapTaskListForProjection(), which requires
|
||||
|
@ -1443,8 +1515,8 @@ CreateNonPushableInsertSelectPlan(uint64 planId, Query *parse, ParamListInfo bou
|
|||
|
||||
/* plan the subquery, this may be another distributed query */
|
||||
int cursorOptions = CURSOR_OPT_PARALLEL_OK;
|
||||
PlannedStmt *selectPlan = pg_plan_query_compat(selectQueryCopy, NULL, cursorOptions,
|
||||
boundParams);
|
||||
PlannedStmt *selectPlan = pg_plan_query(selectQueryCopy, NULL, cursorOptions,
|
||||
boundParams);
|
||||
|
||||
bool repartitioned = IsRedistributablePlan(selectPlan->planTree) &&
|
||||
IsSupportedRedistributionTarget(targetRelationId);
|
||||
|
@ -1506,6 +1578,63 @@ InsertSelectResultIdPrefix(uint64 planId)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* WrapSubquery wraps the given query as a subquery in a newly constructed
|
||||
* "SELECT * FROM (...subquery...) citus_insert_select_subquery" query.
|
||||
*/
|
||||
static Query *
|
||||
WrapSubquery(Query *subquery)
|
||||
{
|
||||
ParseState *pstate = make_parsestate(NULL);
|
||||
List *newTargetList = NIL;
|
||||
|
||||
Query *outerQuery = makeNode(Query);
|
||||
outerQuery->commandType = CMD_SELECT;
|
||||
|
||||
/* create range table entries */
|
||||
Alias *selectAlias = makeAlias("citus_insert_select_subquery", NIL);
|
||||
RangeTblEntry *newRangeTableEntry = RangeTableEntryFromNSItem(
|
||||
addRangeTableEntryForSubquery(
|
||||
pstate, subquery,
|
||||
selectAlias, false, true));
|
||||
outerQuery->rtable = list_make1(newRangeTableEntry);
|
||||
|
||||
/* set the FROM expression to the subquery */
|
||||
RangeTblRef *newRangeTableRef = makeNode(RangeTblRef);
|
||||
newRangeTableRef->rtindex = 1;
|
||||
outerQuery->jointree = makeFromExpr(list_make1(newRangeTableRef), NULL);
|
||||
|
||||
/* create a target list that matches the SELECT */
|
||||
TargetEntry *selectTargetEntry = NULL;
|
||||
foreach_ptr(selectTargetEntry, subquery->targetList)
|
||||
{
|
||||
/* exactly 1 entry in FROM */
|
||||
int indexInRangeTable = 1;
|
||||
|
||||
if (selectTargetEntry->resjunk)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Var *newSelectVar = makeVar(indexInRangeTable, selectTargetEntry->resno,
|
||||
exprType((Node *) selectTargetEntry->expr),
|
||||
exprTypmod((Node *) selectTargetEntry->expr),
|
||||
exprCollation((Node *) selectTargetEntry->expr), 0);
|
||||
|
||||
TargetEntry *newSelectTargetEntry = makeTargetEntry((Expr *) newSelectVar,
|
||||
selectTargetEntry->resno,
|
||||
selectTargetEntry->resname,
|
||||
selectTargetEntry->resjunk);
|
||||
|
||||
newTargetList = lappend(newTargetList, newSelectTargetEntry);
|
||||
}
|
||||
|
||||
outerQuery->targetList = newTargetList;
|
||||
|
||||
return outerQuery;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RelabelTargetEntryList relabels select target list to have matching names with
|
||||
* insert target list.
|
||||
|
@ -1549,18 +1678,24 @@ AddInsertSelectCasts(List *insertTargetList, List *selectTargetList,
|
|||
int targetEntryIndex = 0;
|
||||
TargetEntry *insertEntry = NULL;
|
||||
TargetEntry *selectEntry = NULL;
|
||||
|
||||
forboth_ptr(insertEntry, insertTargetList, selectEntry, selectTargetList)
|
||||
{
|
||||
Var *insertColumn = (Var *) insertEntry->expr;
|
||||
Form_pg_attribute attr = TupleDescAttr(destTupleDescriptor,
|
||||
insertEntry->resno - 1);
|
||||
|
||||
Oid sourceType = insertColumn->vartype;
|
||||
Oid sourceType = exprType((Node *) selectEntry->expr);
|
||||
Oid targetType = attr->atttypid;
|
||||
if (sourceType != targetType)
|
||||
{
|
||||
insertEntry->expr = CastExpr((Expr *) insertColumn, sourceType, targetType,
|
||||
attr->attcollation, attr->atttypmod);
|
||||
/* ReorderInsertSelectTargetLists ensures we only have Vars */
|
||||
Assert(IsA(insertEntry->expr, Var));
|
||||
|
||||
/* we will cast the SELECT expression, so the type changes */
|
||||
Var *insertVar = (Var *) insertEntry->expr;
|
||||
insertVar->vartype = targetType;
|
||||
insertVar->vartypmod = attr->atttypmod;
|
||||
insertVar->varcollid = attr->attcollation;
|
||||
|
||||
/*
|
||||
* We cannot modify the selectEntry in-place, because ORDER BY or
|
||||
|
|
|
@ -376,7 +376,7 @@ RemoveLocalNodeFromWorkerList(List *workerNodeList)
|
|||
WorkerNode *workerNode = (WorkerNode *) lfirst(workerNodeCell);
|
||||
if (workerNode->groupId == localGroupId)
|
||||
{
|
||||
return list_delete_cell_compat(workerNodeList, workerNodeCell, prev);
|
||||
return list_delete_cell(workerNodeList, workerNodeCell);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ CacheLocalPlanForShardQuery(Task *task, DistributedPlan *originalDistributedPlan
|
|||
LockRelationOid(rangeTableEntry->relid, lockMode);
|
||||
|
||||
LocalPlannedStatement *localPlannedStatement = CitusMakeNode(LocalPlannedStatement);
|
||||
localPlan = planner_compat(localShardQuery, 0, NULL);
|
||||
localPlan = planner(localShardQuery, NULL, 0, NULL);
|
||||
localPlannedStatement->localPlan = localPlan;
|
||||
localPlannedStatement->shardId = task->anchorShardId;
|
||||
localPlannedStatement->localGroupId = GetLocalGroupId();
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "commands/explain.h"
|
||||
#include "commands/tablecmds.h"
|
||||
#include "optimizer/cost.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/citus_nodefuncs.h"
|
||||
#include "distributed/connection_management.h"
|
||||
#include "distributed/deparse_shard_query.h"
|
||||
|
@ -357,8 +358,8 @@ ExplainSubPlans(DistributedPlan *distributedPlan, ExplainState *es)
|
|||
|
||||
ExplainOpenGroup("PlannedStmt", "PlannedStmt", false, es);
|
||||
|
||||
ExplainOnePlanCompat(plan, into, es, queryString, params, NULL, &planduration,
|
||||
(es->buffers ? &bufusage : NULL));
|
||||
ExplainOnePlan(plan, into, es, queryString, params, NULL, &planduration,
|
||||
(es->buffers ? &bufusage : NULL));
|
||||
|
||||
ExplainCloseGroup("PlannedStmt", "PlannedStmt", false, es);
|
||||
ExplainCloseGroup("Subplan", NULL, true, es);
|
||||
|
@ -1078,7 +1079,7 @@ worker_save_query_explain_analyze(PG_FUNCTION_ARGS)
|
|||
|
||||
INSTR_TIME_SET_CURRENT(planStart);
|
||||
|
||||
PlannedStmt *plan = pg_plan_query_compat(query, NULL, CURSOR_OPT_PARALLEL_OK, NULL);
|
||||
PlannedStmt *plan = pg_plan_query(query, NULL, CURSOR_OPT_PARALLEL_OK, NULL);
|
||||
|
||||
INSTR_TIME_SET_CURRENT(planDuration);
|
||||
INSTR_TIME_SUBTRACT(planDuration, planStart);
|
||||
|
@ -1185,8 +1186,22 @@ CitusExplainOneQuery(Query *query, int cursorOptions, IntoClause *into,
|
|||
|
||||
INSTR_TIME_SET_CURRENT(planstart);
|
||||
|
||||
/*
|
||||
* We should not hide any objects while explaining some query to not break
|
||||
* postgres vanilla tests.
|
||||
*
|
||||
* The filter 'is_citus_depended_object' is added to explain result
|
||||
* and causes some tests to fail if HideCitusDependentObjects is true.
|
||||
* Therefore, we disable HideCitusDependentObjects until the current transaction
|
||||
* ends.
|
||||
*
|
||||
* We do not use security quals because a postgres vanilla test fails
|
||||
* with a change of order for its result.
|
||||
*/
|
||||
SetLocalHideCitusDependentObjectsDisabledWhenAlreadyEnabled();
|
||||
|
||||
/* plan the query */
|
||||
PlannedStmt *plan = pg_plan_query_compat(query, NULL, cursorOptions, params);
|
||||
PlannedStmt *plan = pg_plan_query(query, NULL, cursorOptions, params);
|
||||
INSTR_TIME_SET_CURRENT(planduration);
|
||||
INSTR_TIME_SUBTRACT(planduration, planstart);
|
||||
|
||||
|
@ -1198,8 +1213,8 @@ CitusExplainOneQuery(Query *query, int cursorOptions, IntoClause *into,
|
|||
}
|
||||
|
||||
/* run it (if needed) and produce output */
|
||||
ExplainOnePlanCompat(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL));
|
||||
ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1617,7 +1632,7 @@ ExplainOneQuery(Query *query, int cursorOptions,
|
|||
INSTR_TIME_SET_CURRENT(planstart);
|
||||
|
||||
/* plan the query */
|
||||
PlannedStmt *plan = pg_plan_query_compat(query, NULL, cursorOptions, params);
|
||||
PlannedStmt *plan = pg_plan_query(query, NULL, cursorOptions, params);
|
||||
|
||||
INSTR_TIME_SET_CURRENT(planduration);
|
||||
INSTR_TIME_SUBTRACT(planduration, planstart);
|
||||
|
@ -1630,7 +1645,7 @@ ExplainOneQuery(Query *query, int cursorOptions,
|
|||
}
|
||||
|
||||
/* run it (if needed) and produce output */
|
||||
ExplainOnePlanCompat(plan, into, es, queryString, params, queryEnv,
|
||||
ExplainOnePlan(plan, into, es, queryString, params, queryEnv,
|
||||
&planduration, (es->buffers ? &bufusage : NULL));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -543,7 +543,7 @@ OrSelectClauseList(List *selectClauseList)
|
|||
Node *selectClause = NULL;
|
||||
foreach_ptr(selectClause, selectClauseList)
|
||||
{
|
||||
bool orClause = or_clause(selectClause);
|
||||
bool orClause = is_orclause(selectClause);
|
||||
if (orClause)
|
||||
{
|
||||
orSelectClauseList = lappend(orSelectClauseList, selectClause);
|
||||
|
@ -3674,9 +3674,9 @@ CoordCombineAggOid()
|
|||
static Oid
|
||||
TypeOid(Oid schemaId, const char *typeName)
|
||||
{
|
||||
Oid typeOid = GetSysCacheOid2Compat(TYPENAMENSP, Anum_pg_type_oid,
|
||||
PointerGetDatum(typeName),
|
||||
ObjectIdGetDatum(schemaId));
|
||||
Oid typeOid = GetSysCacheOid2(TYPENAMENSP, Anum_pg_type_oid,
|
||||
PointerGetDatum(typeName),
|
||||
ObjectIdGetDatum(schemaId));
|
||||
|
||||
return typeOid;
|
||||
}
|
||||
|
|
|
@ -1236,7 +1236,7 @@ DeferErrorIfUnsupportedClause(List *clauseList)
|
|||
{
|
||||
Node *clause = (Node *) lfirst(clauseCell);
|
||||
|
||||
if (!(IsSelectClause(clause) || IsJoinClause(clause) || or_clause(clause)))
|
||||
if (!(IsSelectClause(clause) || IsJoinClause(clause) || is_orclause(clause)))
|
||||
{
|
||||
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||
"unsupported clause type", NULL, NULL);
|
||||
|
|
|
@ -3558,19 +3558,9 @@ DeferErrorIfUnsupportedRouterPlannableSelectQuery(Query *query)
|
|||
NULL, NULL);
|
||||
}
|
||||
|
||||
if (contain_nextval_expression_walker((Node *) query->targetList, NULL))
|
||||
{
|
||||
/*
|
||||
* We let queries with nextval in the target list fall through to
|
||||
* the logical planner, which knows how to handle those queries.
|
||||
*/
|
||||
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||
"Sequences cannot be used in router queries",
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
bool hasPostgresOrCitusLocalTable = false;
|
||||
bool hasDistributedTable = false;
|
||||
bool hasReferenceTable = false;
|
||||
|
||||
ExtractRangeTableRelationWalker((Node *) query, &rangeTableRelationList);
|
||||
foreach(rangeTableRelationCell, rangeTableRelationList)
|
||||
|
@ -3586,6 +3576,11 @@ DeferErrorIfUnsupportedRouterPlannableSelectQuery(Query *query)
|
|||
hasPostgresOrCitusLocalTable = true;
|
||||
continue;
|
||||
}
|
||||
else if (IsCitusTableType(distributedTableId, REFERENCE_TABLE))
|
||||
{
|
||||
hasReferenceTable = true;
|
||||
continue;
|
||||
}
|
||||
else if (IsCitusTableType(distributedTableId, CITUS_LOCAL_TABLE))
|
||||
{
|
||||
hasPostgresOrCitusLocalTable = true;
|
||||
|
@ -3628,6 +3623,28 @@ DeferErrorIfUnsupportedRouterPlannableSelectQuery(Query *query)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to make sure nextval happens on the coordinator / the current
|
||||
* node, since the user may have certain expectations around the values
|
||||
* produced by the sequence. We therefore cannot push down the nextval
|
||||
* call as part of a router query.
|
||||
*
|
||||
* We let queries with nextval in the target list fall through to
|
||||
* the logical planner, which will ensure that the nextval is called
|
||||
* in the combine query on the coordinator.
|
||||
*
|
||||
* If there are no distributed or reference tables in the query,
|
||||
* then the query will anyway happen on the coordinator, so we can
|
||||
* allow nextval.
|
||||
*/
|
||||
if (contain_nextval_expression_walker((Node *) query->targetList, NULL) &&
|
||||
(hasDistributedTable || hasReferenceTable))
|
||||
{
|
||||
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||
"Sequences cannot be used in router queries",
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* local tables are not allowed if there are distributed tables */
|
||||
if (hasPostgresOrCitusLocalTable && hasDistributedTable)
|
||||
{
|
||||
|
|
|
@ -1214,7 +1214,7 @@ CreateDistributedSubPlan(uint32 subPlanId, Query *subPlanQuery)
|
|||
}
|
||||
|
||||
DistributedSubPlan *subPlan = CitusMakeNode(DistributedSubPlan);
|
||||
subPlan->plan = planner_compat(subPlanQuery, cursorOptions, NULL);
|
||||
subPlan->plan = planner(subPlanQuery, NULL, cursorOptions, NULL);
|
||||
subPlan->subPlanId = subPlanId;
|
||||
|
||||
return subPlan;
|
||||
|
|
|
@ -165,7 +165,7 @@ ProgressMonitorList(uint64 commandTypeMagicNumber, List **attachedDSMSegments)
|
|||
getProgressInfoFunctionOid,
|
||||
commandTypeDatum);
|
||||
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlotCompat(
|
||||
TupleTableSlot *tupleTableSlot = MakeSingleTupleTableSlot(
|
||||
progressResultSet->setDesc,
|
||||
&TTSOpsMinimalTuple);
|
||||
|
||||
|
|
|
@ -1649,7 +1649,7 @@ WaitForRelationSubscriptionsBecomeReady(MultiConnection *targetConnection,
|
|||
* and reset it on every iteration to make sure we don't slowly build up
|
||||
* a lot of memory.
|
||||
*/
|
||||
MemoryContext loopContext = AllocSetContextCreateExtended(CurrentMemoryContext,
|
||||
MemoryContext loopContext = AllocSetContextCreateInternal(CurrentMemoryContext,
|
||||
"WaitForRelationSubscriptionsBecomeReady",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
|
@ -1936,7 +1936,7 @@ WaitForShardSubscriptionToCatchUp(MultiConnection *targetConnection, XLogRecPtr
|
|||
* and reset it on every iteration to make sure we don't slowly build up
|
||||
* a lot of memory.
|
||||
*/
|
||||
MemoryContext loopContext = AllocSetContextCreateExtended(CurrentMemoryContext,
|
||||
MemoryContext loopContext = AllocSetContextCreateInternal(CurrentMemoryContext,
|
||||
"WaitForShardSubscriptionToCatchUp",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "common/string.h"
|
||||
#include "executor/executor.h"
|
||||
#include "distributed/backend_data.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/citus_nodefuncs.h"
|
||||
#include "distributed/citus_safe_lib.h"
|
||||
#include "distributed/commands.h"
|
||||
|
@ -47,6 +48,7 @@
|
|||
#include "distributed/local_executor.h"
|
||||
#include "distributed/local_distributed_join_planner.h"
|
||||
#include "distributed/locally_reserved_shared_connections.h"
|
||||
#include "distributed/log_utils.h"
|
||||
#include "distributed/maintenanced.h"
|
||||
#include "distributed/shard_cleaner.h"
|
||||
#include "distributed/metadata_utility.h"
|
||||
|
@ -389,6 +391,7 @@ _PG_init(void)
|
|||
InitializeBackendManagement();
|
||||
InitializeConnectionManagement();
|
||||
InitPlacementConnectionManagement();
|
||||
InitRelationAccessHash();
|
||||
InitializeCitusQueryStats();
|
||||
InitializeSharedConnectionStats();
|
||||
InitializeLocallyReservedSharedConnections();
|
||||
|
@ -596,6 +599,21 @@ StartupCitusBackend(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetCurrentClientMinMessageLevelName returns the name of the
|
||||
* the GUC client_min_messages for its specified value.
|
||||
*/
|
||||
const char *
|
||||
GetClientMinMessageLevelNameForValue(int minMessageLevel)
|
||||
{
|
||||
struct config_enum record = { 0 };
|
||||
record.options = log_level_options;
|
||||
const char *clientMinMessageLevelName = config_enum_lookup_by_value(&record,
|
||||
minMessageLevel);
|
||||
return clientMinMessageLevelName;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RegisterConnectionCleanup cleans up any resources left at the end of the
|
||||
* session. We prefer to cleanup before shared memory exit to make sure that
|
||||
|
@ -650,6 +668,7 @@ CitusCleanupConnectionsAtExit(int code, Datum arg)
|
|||
|
||||
/* we don't want any monitoring view/udf to show already exited backends */
|
||||
UnSetGlobalPID();
|
||||
SetActiveMyBackend(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1155,6 +1174,17 @@ RegisterCitusConfigVariables(void)
|
|||
GUC_STANDARD,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
DefineCustomBoolVariable(
|
||||
"citus.enable_unsupported_feature_messages",
|
||||
gettext_noop("Controls showing of some citus related messages. It is intended to "
|
||||
"be used before vanilla tests to stop unwanted citus messages."),
|
||||
NULL,
|
||||
&EnableUnsupportedFeatureMessages,
|
||||
true,
|
||||
PGC_SUSET,
|
||||
GUC_SUPERUSER_ONLY | GUC_NO_SHOW_ALL,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
DefineCustomBoolVariable(
|
||||
"citus.enable_version_checks",
|
||||
gettext_noop("Enables version checks during CREATE/ALTER EXTENSION commands"),
|
||||
|
@ -1276,6 +1306,18 @@ RegisterCitusConfigVariables(void)
|
|||
GUC_NO_SHOW_ALL,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
DefineCustomBoolVariable(
|
||||
"citus.hide_citus_dependent_objects",
|
||||
gettext_noop(
|
||||
"Hides some objects, which depends on citus extension, from pg meta class queries."
|
||||
"It is intended to be used only before postgres vanilla tests to not break them."),
|
||||
NULL,
|
||||
&HideCitusDependentObjects,
|
||||
false,
|
||||
PGC_USERSET,
|
||||
GUC_SUPERUSER_ONLY | GUC_NO_SHOW_ALL,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/*
|
||||
* This was a GUC we added on Citus 11.0.1, and
|
||||
* replaced with another name on 11.0.2 via #5920.
|
||||
|
@ -2476,7 +2518,11 @@ CitusAuthHook(Port *port, int status)
|
|||
|
||||
|
||||
/*
|
||||
* IsSuperuser returns whether the role with the given name is superuser.
|
||||
* IsSuperuser returns whether the role with the given name is superuser. If
|
||||
* the user doesn't exist, this simply returns false instead of throwing an
|
||||
* error. This is done to not leak information about users existing or not, in
|
||||
* some cases postgres is vague about this on purpose. So, by returning false
|
||||
* we let postgres return this possibly vague error message.
|
||||
*/
|
||||
static bool
|
||||
IsSuperuser(char *roleName)
|
||||
|
@ -2489,9 +2535,7 @@ IsSuperuser(char *roleName)
|
|||
HeapTuple roleTuple = SearchSysCache1(AUTHNAME, CStringGetDatum(roleName));
|
||||
if (!HeapTupleIsValid(roleTuple))
|
||||
{
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
|
||||
errmsg("role \"%s\" does not exist", roleName)));
|
||||
return false;
|
||||
}
|
||||
|
||||
Form_pg_authid rform = (Form_pg_authid) GETSTRUCT(roleTuple);
|
||||
|
|
|
@ -69,4 +69,5 @@ DROP FUNCTION pg_catalog.get_all_active_transactions(OUT datid oid, OUT process_
|
|||
#include "udfs/get_all_active_transactions/11.1-1.sql"
|
||||
#include "udfs/citus_split_shard_by_split_points/11.1-1.sql"
|
||||
#include "udfs/worker_split_copy/11.1-1.sql"
|
||||
#include "udfs/worker_copy_table_to_node/11.1-1.sql"
|
||||
#include "udfs/worker_split_shard_replication_setup/11.1-1.sql"
|
||||
|
|
|
@ -77,6 +77,9 @@ DROP FUNCTION pg_catalog.worker_split_shard_replication_setup(
|
|||
splitShardInfo pg_catalog.split_shard_info[]);
|
||||
DROP TYPE pg_catalog.split_shard_info;
|
||||
DROP TYPE pg_catalog.replication_slot_info;
|
||||
DROP FUNCTION pg_catalog.worker_copy_table_to_node(
|
||||
source_table regclass,
|
||||
target_node_id integer);
|
||||
|
||||
DROP FUNCTION pg_catalog.get_all_active_transactions(OUT datid oid, OUT process_id int, OUT initiator_node_identifier int4,
|
||||
OUT worker_query BOOL, OUT transaction_number int8, OUT transaction_stamp timestamptz,
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
CREATE OR REPLACE FUNCTION pg_catalog.worker_copy_table_to_node(
|
||||
source_table regclass,
|
||||
target_node_id integer)
|
||||
RETURNS void
|
||||
LANGUAGE C STRICT
|
||||
AS 'MODULE_PATHNAME', $$worker_copy_table_to_node$$;
|
||||
COMMENT ON FUNCTION pg_catalog.worker_copy_table_to_node(regclass, integer)
|
||||
IS 'Perform copy of a shard';
|
|
@ -0,0 +1,8 @@
|
|||
CREATE OR REPLACE FUNCTION pg_catalog.worker_copy_table_to_node(
|
||||
source_table regclass,
|
||||
target_node_id integer)
|
||||
RETURNS void
|
||||
LANGUAGE C STRICT
|
||||
AS 'MODULE_PATHNAME', $$worker_copy_table_to_node$$;
|
||||
COMMENT ON FUNCTION pg_catalog.worker_copy_table_to_node(regclass, integer)
|
||||
IS 'Perform copy of a shard';
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* citus_depended_object.c
|
||||
*
|
||||
* Implements udf function related to hiding citus depended objects while executing
|
||||
* postgres vanilla tests.
|
||||
*
|
||||
* Copyright (c) Citus Data, Inc.
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "catalog/pg_aggregate.h"
|
||||
#include "catalog/pg_am.h"
|
||||
#include "catalog/pg_attribute.h"
|
||||
#include "catalog/pg_attrdef.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_class.h"
|
||||
#include "catalog/pg_depend.h"
|
||||
#include "catalog/pg_enum.h"
|
||||
#include "catalog/pg_event_trigger.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_rewrite.h"
|
||||
#include "catalog/pg_sequence.h"
|
||||
#include "catalog/pg_statistic.h"
|
||||
#include "catalog/pg_trigger.h"
|
||||
#include "catalog/pg_ts_config.h"
|
||||
#include "catalog/pg_ts_dict.h"
|
||||
#include "catalog/pg_ts_template.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/listutils.h"
|
||||
#include "distributed/metadata_cache.h"
|
||||
#include "distributed/metadata/dependency.h"
|
||||
#include "distributed/metadata/distobject.h"
|
||||
|
||||
static bool IsCitusDependentObject(ObjectAddress objectAddress);
|
||||
|
||||
PG_FUNCTION_INFO_V1(is_citus_depended_object);
|
||||
|
||||
/*
|
||||
* is_citus_depended_object a wrapper around IsCitusDependentObject, so
|
||||
* see the details there.
|
||||
*
|
||||
* The first parameter expects an oid for
|
||||
* a pg meta class, and the second parameter expects an oid for
|
||||
* the object which is found in the pg meta class.
|
||||
*/
|
||||
Datum
|
||||
is_citus_depended_object(PG_FUNCTION_ARGS)
|
||||
{
|
||||
CheckCitusVersion(ERROR);
|
||||
|
||||
if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
|
||||
{
|
||||
/* Because we want to return false for null arguments, we donot use strict keyword while creating that function. */
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
Oid metaTableId = PG_GETARG_OID(0);
|
||||
Oid objectId = PG_GETARG_OID(1);
|
||||
|
||||
if (!OidIsValid(metaTableId) || !OidIsValid(objectId))
|
||||
{
|
||||
/* we cannot continue without valid meta table or object oid */
|
||||
PG_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
bool dependsOnCitus = false;
|
||||
|
||||
ObjectAddress objectAdress = { metaTableId, objectId, 0 };
|
||||
|
||||
switch (metaTableId)
|
||||
{
|
||||
case ProcedureRelationId:
|
||||
case AccessMethodRelationId:
|
||||
case EventTriggerRelationId:
|
||||
case TriggerRelationId:
|
||||
case TSConfigRelationId:
|
||||
case TSTemplateRelationId:
|
||||
case TSDictionaryRelationId:
|
||||
case LanguageRelationId:
|
||||
case RewriteRelationId:
|
||||
case AttrDefaultRelationId:
|
||||
case NamespaceRelationId:
|
||||
case ConstraintRelationId:
|
||||
case TypeRelationId:
|
||||
case RelationRelationId:
|
||||
{
|
||||
/* meta classes that access their own oid */
|
||||
dependsOnCitus = IsCitusDependentObject(objectAdress);
|
||||
break;
|
||||
}
|
||||
|
||||
case EnumRelationId:
|
||||
{
|
||||
/*
|
||||
* we do not directly access the oid in pg_enum,
|
||||
* because it does not exist in pg_depend, but its type does
|
||||
*/
|
||||
objectAdress.classId = TypeRelationId;
|
||||
dependsOnCitus = IsCitusDependentObject(objectAdress);
|
||||
break;
|
||||
}
|
||||
|
||||
case IndexRelationId:
|
||||
case AttributeRelationId:
|
||||
case SequenceRelationId:
|
||||
case StatisticRelationId:
|
||||
{
|
||||
/* meta classes that access their relation's oid */
|
||||
objectAdress.classId = RelationRelationId;
|
||||
dependsOnCitus = IsCitusDependentObject(objectAdress);
|
||||
break;
|
||||
}
|
||||
|
||||
case AggregateRelationId:
|
||||
{
|
||||
/* We access procedure oid for aggregates. */
|
||||
objectAdress.classId = ProcedureRelationId;
|
||||
dependsOnCitus = IsCitusDependentObject(objectAdress);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PG_RETURN_BOOL(dependsOnCitus);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IsCitusDependentObject returns true if the given object depends on the citus extension.
|
||||
*/
|
||||
static bool
|
||||
IsCitusDependentObject(ObjectAddress objectAddress)
|
||||
{
|
||||
if (IsObjectAddressOwnedByCitus(&objectAddress))
|
||||
{
|
||||
/* object itself is owned by citus */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* check if object's any dependency is owned by citus. */
|
||||
List *citusDependencies = GetAllCitusDependedDependenciesForObject(&objectAddress);
|
||||
return list_length(citusDependencies) > 0;
|
||||
}
|
|
@ -51,10 +51,10 @@ partition_task_list_results(PG_FUNCTION_ARGS)
|
|||
bool binaryFormat = PG_GETARG_BOOL(3);
|
||||
|
||||
Query *parsedQuery = ParseQueryString(queryString, NULL, 0);
|
||||
PlannedStmt *queryPlan = pg_plan_query_compat(parsedQuery,
|
||||
queryString,
|
||||
CURSOR_OPT_PARALLEL_OK,
|
||||
NULL);
|
||||
PlannedStmt *queryPlan = pg_plan_query(parsedQuery,
|
||||
queryString,
|
||||
CURSOR_OPT_PARALLEL_OK,
|
||||
NULL);
|
||||
if (!IsCitusCustomScan(queryPlan->planTree))
|
||||
{
|
||||
ereport(ERROR, (errmsg("query must be distributed and shouldn't require "
|
||||
|
@ -122,10 +122,10 @@ redistribute_task_list_results(PG_FUNCTION_ARGS)
|
|||
bool binaryFormat = PG_GETARG_BOOL(3);
|
||||
|
||||
Query *parsedQuery = ParseQueryString(queryString, NULL, 0);
|
||||
PlannedStmt *queryPlan = pg_plan_query_compat(parsedQuery,
|
||||
queryString,
|
||||
CURSOR_OPT_PARALLEL_OK,
|
||||
NULL);
|
||||
PlannedStmt *queryPlan = pg_plan_query(parsedQuery,
|
||||
queryString,
|
||||
CURSOR_OPT_PARALLEL_OK,
|
||||
NULL);
|
||||
if (!IsCitusCustomScan(queryPlan->planTree))
|
||||
{
|
||||
ereport(ERROR, (errmsg("query must be distributed and shouldn't require "
|
||||
|
|
|
@ -117,7 +117,7 @@ get_referencing_relation_id_list(PG_FUNCTION_ARGS)
|
|||
{
|
||||
Oid refId = lfirst_oid(wrapper->listCell);
|
||||
|
||||
wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell);
|
||||
wrapper->listCell = lnext(wrapper->list, wrapper->listCell);
|
||||
|
||||
SRF_RETURN_NEXT(functionContext, PointerGetDatum(refId));
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ get_referenced_relation_id_list(PG_FUNCTION_ARGS)
|
|||
{
|
||||
Oid refId = lfirst_oid(wrapper->listCell);
|
||||
|
||||
wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell);
|
||||
wrapper->listCell = lnext(wrapper->list, wrapper->listCell);
|
||||
|
||||
SRF_RETURN_NEXT(functionContext, PointerGetDatum(refId));
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ get_foreign_key_to_reference_table_commands(PG_FUNCTION_ARGS)
|
|||
char *command = (char *) lfirst(wrapper->listCell);
|
||||
text *commandText = cstring_to_text(command);
|
||||
|
||||
wrapper->listCell = lnext_compat(wrapper->list, wrapper->listCell);
|
||||
wrapper->listCell = lnext(wrapper->list, wrapper->listCell);
|
||||
|
||||
SRF_RETURN_NEXT(functionContext, PointerGetDatum(commandText));
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "storage/ipc.h"
|
||||
#include "storage/lmgr.h"
|
||||
#include "storage/lwlock.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "storage/proc.h"
|
||||
#include "storage/spin.h"
|
||||
#include "storage/s_lock.h"
|
||||
|
@ -392,9 +393,9 @@ StoreAllActiveTransactions(Tuplestorestate *tupleStore, TupleDesc tupleDescripto
|
|||
|
||||
SpinLockAcquire(¤tBackend->mutex);
|
||||
|
||||
if (currentProc->pid == 0)
|
||||
if (currentProc->pid == 0 || !currentBackend->activeBackend)
|
||||
{
|
||||
/* unused PGPROC slot */
|
||||
/* unused PGPROC slot or the backend already exited */
|
||||
SpinLockRelease(¤tBackend->mutex);
|
||||
continue;
|
||||
}
|
||||
|
@ -698,6 +699,12 @@ InitializeBackendData(void)
|
|||
UnSetDistributedTransactionId();
|
||||
UnSetGlobalPID();
|
||||
|
||||
/*
|
||||
* Signal that this backend is active and should show up
|
||||
* on activity monitors.
|
||||
*/
|
||||
SetActiveMyBackend(true);
|
||||
|
||||
UnlockBackendSharedMemory();
|
||||
}
|
||||
|
||||
|
@ -746,6 +753,24 @@ UnSetGlobalPID(void)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* SetActiveMyBackend is a wrapper around MyBackendData->activeBackend.
|
||||
*/
|
||||
void
|
||||
SetActiveMyBackend(bool value)
|
||||
{
|
||||
/* backend does not exist if the extension is not created */
|
||||
if (MyBackendData)
|
||||
{
|
||||
SpinLockAcquire(&MyBackendData->mutex);
|
||||
|
||||
MyBackendData->activeBackend = value;
|
||||
|
||||
SpinLockRelease(&MyBackendData->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* LockBackendSharedMemory is a simple wrapper around LWLockAcquire on the
|
||||
* shared memory lock.
|
||||
|
@ -1224,6 +1249,16 @@ ActiveDistributedTransactionNumbers(void)
|
|||
}
|
||||
|
||||
GetBackendDataForProc(currentProc, ¤tBackendData);
|
||||
if (!currentBackendData.activeBackend)
|
||||
{
|
||||
/*
|
||||
* Skip if the PGPROC slot is unused. We should normally use
|
||||
* IsBackendPid() to be able to skip reliably all the exited
|
||||
* processes. However, that is a costly operation. Instead, we
|
||||
* keep track of activeBackend in Citus code.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsInDistributedTransaction(¤tBackendData))
|
||||
{
|
||||
|
|
|
@ -561,13 +561,23 @@ BuildLocalWaitGraph(bool onlyDistributedTx)
|
|||
PGPROC *currentProc = &ProcGlobal->allProcs[curBackend];
|
||||
BackendData currentBackendData;
|
||||
|
||||
/* skip if the PGPROC slot is unused */
|
||||
if (currentProc->pid == 0)
|
||||
{
|
||||
/* skip if the PGPROC slot is unused */
|
||||
continue;
|
||||
}
|
||||
|
||||
GetBackendDataForProc(currentProc, ¤tBackendData);
|
||||
if (!currentBackendData.activeBackend)
|
||||
{
|
||||
/*
|
||||
* Skip if the PGPROC slot is unused. We should normally use
|
||||
* IsBackendPid() to be able to skip reliably all the exited
|
||||
* processes. However, that is a costly operation. Instead, we
|
||||
* keep track of activeBackend in Citus code.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only start searching from distributed transactions, since we only
|
||||
|
|
|
@ -47,6 +47,8 @@ bool EnforceForeignKeyRestrictions = true;
|
|||
(1 << (PLACEMENT_ACCESS_DDL + \
|
||||
PARALLEL_MODE_FLAG_OFFSET)))
|
||||
|
||||
MemoryContext RelationAcessContext = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Hash table mapping relations to the
|
||||
|
@ -84,8 +86,8 @@ typedef struct RelationAccessHashEntry
|
|||
|
||||
static HTAB *RelationAccessHash;
|
||||
|
||||
|
||||
/* functions related to access recording */
|
||||
static void AllocateRelationAccessHash(void);
|
||||
static void RecordRelationAccessBase(Oid relationId, ShardPlacementAccessType accessType);
|
||||
static void RecordPlacementAccessToCache(Oid relationId,
|
||||
ShardPlacementAccessType accessType);
|
||||
|
@ -120,6 +122,18 @@ static bool HoldsConflictingLockWithReferencedRelations(Oid relationId,
|
|||
conflictingAccessMode);
|
||||
|
||||
|
||||
/*
|
||||
* InitRelationAccessHash performs initialization of the
|
||||
* infrastructure in this file at backend start.
|
||||
*/
|
||||
void
|
||||
InitRelationAccessHash(void)
|
||||
{
|
||||
/* allocate (relationId) = [relationAccessMode] hash */
|
||||
AllocateRelationAccessHash();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Empty RelationAccessHash, without destroying the hash table itself.
|
||||
*/
|
||||
|
@ -133,19 +147,29 @@ ResetRelationAccessHash()
|
|||
/*
|
||||
* Allocate RelationAccessHash.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
AllocateRelationAccessHash(void)
|
||||
{
|
||||
HASHCTL info;
|
||||
/*
|
||||
* Create a single context for relation access related memory
|
||||
* management. Doing so, instead of allocating in TopMemoryContext, makes
|
||||
* it easier to associate used memory.
|
||||
*/
|
||||
RelationAcessContext = AllocSetContextCreateInternal(TopMemoryContext,
|
||||
"Relation Access Context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
HASHCTL info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.keysize = sizeof(RelationAccessHashKey);
|
||||
info.entrysize = sizeof(RelationAccessHashEntry);
|
||||
info.hash = tag_hash;
|
||||
info.hcxt = ConnectionContext;
|
||||
info.hcxt = RelationAcessContext;
|
||||
uint32 hashFlags = (HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
|
||||
|
||||
RelationAccessHash = hash_create("citus connection cache (relationid)",
|
||||
RelationAccessHash = hash_create("citus relation access cache (relationid)",
|
||||
8, &info, hashFlags);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "distributed/repartition_join_execution.h"
|
||||
#include "distributed/transaction_management.h"
|
||||
#include "distributed/placement_connection.h"
|
||||
#include "distributed/relation_access_tracking.h"
|
||||
#include "distributed/shared_connection_stats.h"
|
||||
#include "distributed/subplan_execution.h"
|
||||
#include "distributed/version_compat.h"
|
||||
|
@ -243,7 +244,7 @@ InitializeTransactionManagement(void)
|
|||
AdjustMaxPreparedTransactions();
|
||||
|
||||
/* set aside 8kb of memory for use in CoordinatedTransactionCallback */
|
||||
CommitContext = AllocSetContextCreateExtended(TopMemoryContext,
|
||||
CommitContext = AllocSetContextCreateInternal(TopMemoryContext,
|
||||
"CommitContext",
|
||||
8 * 1024,
|
||||
8 * 1024,
|
||||
|
@ -307,6 +308,7 @@ CoordinatedTransactionCallback(XactEvent event, void *arg)
|
|||
}
|
||||
|
||||
ResetGlobalVariables();
|
||||
ResetRelationAccessHash();
|
||||
|
||||
/*
|
||||
* Make sure that we give the shared connections back to the shared
|
||||
|
@ -376,6 +378,7 @@ CoordinatedTransactionCallback(XactEvent event, void *arg)
|
|||
AfterXactConnectionHandling(false);
|
||||
|
||||
ResetGlobalVariables();
|
||||
ResetRelationAccessHash();
|
||||
|
||||
/*
|
||||
* Clear MetadataCache table if we're aborting from a CREATE EXTENSION Citus
|
||||
|
|
|
@ -165,7 +165,7 @@ RecoverWorkerTransactions(WorkerNode *workerNode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
MemoryContext localContext = AllocSetContextCreateExtended(CurrentMemoryContext,
|
||||
MemoryContext localContext = AllocSetContextCreateInternal(CurrentMemoryContext,
|
||||
"RecoverWorkerTransactions",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
|
|
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
* citus_depended_object.c
|
||||
*
|
||||
* Implements exposed functions related to hiding citus depended objects.
|
||||
*
|
||||
* Copyright (c) Citus Data, Inc.
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
#include "miscadmin.h"
|
||||
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
#include "catalog/pg_am.h"
|
||||
#include "catalog/pg_attribute.h"
|
||||
#include "catalog/pg_attrdef.h"
|
||||
#include "catalog/pg_constraint.h"
|
||||
#include "catalog/pg_class.h"
|
||||
#include "catalog/pg_depend.h"
|
||||
#include "catalog/pg_enum.h"
|
||||
#include "catalog/pg_event_trigger.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_rewrite.h"
|
||||
#include "catalog/pg_sequence.h"
|
||||
#include "catalog/pg_statistic.h"
|
||||
#include "catalog/pg_trigger.h"
|
||||
#include "catalog/pg_ts_config.h"
|
||||
#include "catalog/pg_ts_dict.h"
|
||||
#include "catalog/pg_ts_template.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "distributed/citus_depended_object.h"
|
||||
#include "distributed/metadata_cache.h"
|
||||
#include "distributed/commands.h"
|
||||
#include "distributed/listutils.h"
|
||||
#include "distributed/log_utils.h"
|
||||
#include "distributed/shared_library_init.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
/*
|
||||
* GUC hides any objects, which depends on citus extension, from pg meta class queries,
|
||||
* it is intended to be used in vanilla tests to not break postgres test logs
|
||||
*/
|
||||
bool HideCitusDependentObjects = false;
|
||||
|
||||
static Node * CreateCitusDependentObjectExpr(int pgMetaTableVarno, int pgMetaTableOid);
|
||||
static List * GetCitusDependedObjectArgs(int pgMetaTableVarno, int pgMetaTableOid);
|
||||
static bool StatementContainsIfExist(Node *node);
|
||||
static bool AlterRoleSetStatementContainsAll(Node *node);
|
||||
|
||||
/*
|
||||
* IsPgLocksTable returns true if RTE is pg_locks table.
|
||||
*/
|
||||
bool
|
||||
IsPgLocksTable(RangeTblEntry *rte)
|
||||
{
|
||||
Oid pgLocksId = get_relname_relid("pg_locks", get_namespace_oid("pg_catalog", false));
|
||||
return rte->relid == pgLocksId;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SetLocalHideCitusDependentObjectsDisabledWhenAlreadyEnabled disables the GUC HideCitusDependentObjects
|
||||
* if only it is enabled for local transaction.
|
||||
*/
|
||||
void
|
||||
SetLocalHideCitusDependentObjectsDisabledWhenAlreadyEnabled(void)
|
||||
{
|
||||
if (!HideCitusDependentObjects)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
set_config_option("citus.hide_citus_dependent_objects", "false",
|
||||
(superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION,
|
||||
GUC_ACTION_LOCAL, true, 0, false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SetLocalClientMinMessagesIfRunningPGTests sets client_min_message locally to the given value
|
||||
* if EnableUnsupportedFeatureMessages is set to false.
|
||||
*/
|
||||
void
|
||||
SetLocalClientMinMessagesIfRunningPGTests(int clientMinMessageLevel)
|
||||
{
|
||||
if (EnableUnsupportedFeatureMessages)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const char *clientMinMessageLevelName = GetClientMinMessageLevelNameForValue(
|
||||
clientMinMessageLevel);
|
||||
|
||||
set_config_option("client_min_messages", clientMinMessageLevelName,
|
||||
(superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION,
|
||||
GUC_ACTION_LOCAL, true, 0, false);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* HideCitusDependentObjectsOnQueriesOfPgMetaTables adds a NOT is_citus_depended_object(oid, oid) expr
|
||||
* to the quals of meta class RTEs that we are interested in.
|
||||
*/
|
||||
bool
|
||||
HideCitusDependentObjectsOnQueriesOfPgMetaTables(Node *node, void *context)
|
||||
{
|
||||
if (!CitusHasBeenLoaded() || !HideCitusDependentObjects || node == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsA(node, Query))
|
||||
{
|
||||
Query *query = (Query *) node;
|
||||
MemoryContext queryContext = GetMemoryChunkContext(query);
|
||||
|
||||
/*
|
||||
* We process the whole rtable rather than visiting individual RangeTblEntry's
|
||||
* in the walker, since we need to know the varno to generate the right
|
||||
* filter.
|
||||
*/
|
||||
int varno = 0;
|
||||
RangeTblEntry *rangeTableEntry = NULL;
|
||||
|
||||
foreach_ptr(rangeTableEntry, query->rtable)
|
||||
{
|
||||
varno++;
|
||||
|
||||
if (rangeTableEntry->rtekind == RTE_RELATION)
|
||||
{
|
||||
/* make sure the expression is in the right memory context */
|
||||
MemoryContext originalContext = MemoryContextSwitchTo(queryContext);
|
||||
|
||||
Oid metaTableOid = InvalidOid;
|
||||
|
||||
/*
|
||||
* add NOT is_citus_depended_object(oid, oid) to the quals
|
||||
* of the RTE if it is a pg meta table that we are interested in.
|
||||
*/
|
||||
switch (rangeTableEntry->relid)
|
||||
{
|
||||
/* pg_class */
|
||||
case RelationRelationId:
|
||||
|
||||
/* pg_proc */
|
||||
case ProcedureRelationId:
|
||||
|
||||
/* pg_am */
|
||||
case AccessMethodRelationId:
|
||||
|
||||
/* pg_type */
|
||||
case TypeRelationId:
|
||||
|
||||
/* pg_enum */
|
||||
case EnumRelationId:
|
||||
|
||||
/* pg_event_trigger */
|
||||
case EventTriggerRelationId:
|
||||
|
||||
/* pg_trigger */
|
||||
case TriggerRelationId:
|
||||
|
||||
/* pg_rewrite */
|
||||
case RewriteRelationId:
|
||||
|
||||
/* pg_attrdef */
|
||||
case AttrDefaultRelationId:
|
||||
|
||||
/* pg_constraint */
|
||||
case ConstraintRelationId:
|
||||
|
||||
/* pg_ts_config */
|
||||
case TSConfigRelationId:
|
||||
|
||||
/* pg_ts_template */
|
||||
case TSTemplateRelationId:
|
||||
|
||||
/* pg_ts_dict */
|
||||
case TSDictionaryRelationId:
|
||||
|
||||
/* pg_language */
|
||||
case LanguageRelationId:
|
||||
|
||||
/* pg_namespace */
|
||||
case NamespaceRelationId:
|
||||
|
||||
/* pg_sequence */
|
||||
case SequenceRelationId:
|
||||
|
||||
/* pg_statistic */
|
||||
case StatisticRelationId:
|
||||
|
||||
/* pg_attribute */
|
||||
case AttributeRelationId:
|
||||
|
||||
/* pg_index */
|
||||
case IndexRelationId:
|
||||
|
||||
/* pg_aggregate */
|
||||
case AggregateRelationId:
|
||||
{
|
||||
metaTableOid = rangeTableEntry->relid;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
metaTableOid = InvalidOid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (OidIsValid(metaTableOid))
|
||||
{
|
||||
/*
|
||||
* We found a valid pg meta class in query,
|
||||
* so we assert below conditions.
|
||||
*/
|
||||
Assert(query->jointree != NULL);
|
||||
Assert(query->jointree->fromlist != NULL);
|
||||
|
||||
Node *citusDependentObjExpr =
|
||||
CreateCitusDependentObjectExpr(varno, metaTableOid);
|
||||
|
||||
/*
|
||||
* We do not use security quals because a postgres vanilla test fails
|
||||
* with a change of order for its result.
|
||||
*/
|
||||
query->jointree->quals = make_and_qual(
|
||||
query->jointree->quals, citusDependentObjExpr);
|
||||
}
|
||||
|
||||
MemoryContextSwitchTo(originalContext);
|
||||
}
|
||||
}
|
||||
|
||||
return query_tree_walker((Query *) node,
|
||||
HideCitusDependentObjectsOnQueriesOfPgMetaTables,
|
||||
context, 0);
|
||||
}
|
||||
|
||||
return expression_tree_walker(node, HideCitusDependentObjectsOnQueriesOfPgMetaTables,
|
||||
context);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CreateCitusDependentObjectExpr constructs an expression of the form:
|
||||
* NOT pg_catalog.is_citus_depended_object(oid, oid)
|
||||
*/
|
||||
static Node *
|
||||
CreateCitusDependentObjectExpr(int pgMetaTableVarno, int pgMetaTableOid)
|
||||
{
|
||||
/* build the call to read_intermediate_result */
|
||||
FuncExpr *funcExpr = makeNode(FuncExpr);
|
||||
funcExpr->funcid = CitusDependentObjectFuncId();
|
||||
funcExpr->funcretset = false;
|
||||
funcExpr->funcvariadic = false;
|
||||
funcExpr->funcformat = 0;
|
||||
funcExpr->funccollid = 0;
|
||||
funcExpr->inputcollid = 0;
|
||||
funcExpr->location = -1;
|
||||
funcExpr->args = GetCitusDependedObjectArgs(pgMetaTableVarno, pgMetaTableOid);
|
||||
|
||||
BoolExpr *notExpr = makeNode(BoolExpr);
|
||||
notExpr->boolop = NOT_EXPR;
|
||||
notExpr->args = list_make1(funcExpr);
|
||||
notExpr->location = -1;
|
||||
|
||||
return (Node *) notExpr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetCitusDependedObjectArgs returns func arguments for pg_catalog.is_citus_depended_object
|
||||
*/
|
||||
static List *
|
||||
GetCitusDependedObjectArgs(int pgMetaTableVarno, int pgMetaTableOid)
|
||||
{
|
||||
/*
|
||||
* set attribute number for the oid, which we are insterest in, inside pg meta tables.
|
||||
* We are accessing the 1. col(their own oid or their relation's oid) to get the related
|
||||
* object's oid for all of the pg meta tables except pg_enum and pg_index. For pg_enum,
|
||||
* class, we access its 2. col(its type's oid) to see if its type depends on citus,
|
||||
* so it does. For pg_index, we access its 2. col (its relation's oid) to see if its relation
|
||||
* depends on citus, so it does.
|
||||
*/
|
||||
AttrNumber oidAttNum = 1;
|
||||
if (pgMetaTableOid == EnumRelationId || pgMetaTableOid == IndexRelationId)
|
||||
{
|
||||
oidAttNum = 2;
|
||||
}
|
||||
|
||||
/* create const for meta table oid */
|
||||
Const *metaTableOidConst = makeConst(OIDOID, -1, InvalidOid, sizeof(Oid),
|
||||
ObjectIdGetDatum(pgMetaTableOid),
|
||||
false, true);
|
||||
|
||||
/*
|
||||
* create a var for the oid that we are interested in,
|
||||
* col type should be regproc for pg_aggregate table; else oid
|
||||
*/
|
||||
Oid varType = (pgMetaTableOid == AggregateRelationId) ? REGPROCOID : OIDOID;
|
||||
Var *oidVar = makeVar(pgMetaTableVarno, oidAttNum,
|
||||
varType, -1, InvalidOid, 0);
|
||||
|
||||
return list_make2((Node *) metaTableOidConst, (Node *) oidVar);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DistOpsHasInvalidObject returns true if any address in the given node
|
||||
* is invalid; otherwise, returns false. If ops is null or it has no
|
||||
* implemented address method, we return false. We also have some dist ops
|
||||
* for which we should not validate and return false.
|
||||
*/
|
||||
bool
|
||||
DistOpsHasInvalidObject(Node *node, const DistributeObjectOps *ops)
|
||||
{
|
||||
if (ops && ops->operationType == DIST_OPS_CREATE)
|
||||
{
|
||||
/*
|
||||
* We should not validate CREATE statements because no address exists
|
||||
* here yet.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
else if (StatementContainsIfExist(node))
|
||||
{
|
||||
/*
|
||||
* We should not validate '[DROP|ALTER] IF EXISTS' statements because it is ok
|
||||
* by the semantics even if any object is invalid.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
else if (AlterRoleSetStatementContainsAll(node))
|
||||
{
|
||||
/*
|
||||
* We should not validate 'ALTER ROLE ALL [SET|UNSET] because for the role ALL
|
||||
* AlterRoleSetStmtObjectAddress returns an invalid address even though it should not.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ops && ops->address)
|
||||
{
|
||||
bool missingOk = true;
|
||||
bool isPostprocess = false;
|
||||
List *objectAddresses = ops->address(node, missingOk, isPostprocess);
|
||||
|
||||
ObjectAddress *objectAddress = NULL;
|
||||
foreach_ptr(objectAddress, objectAddresses)
|
||||
{
|
||||
if (!OidIsValid(objectAddress->objectId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* StatementContainsIfExist returns true if the statement contains
|
||||
* IF EXIST syntax.
|
||||
*/
|
||||
static bool
|
||||
StatementContainsIfExist(Node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_DropStmt:
|
||||
{
|
||||
DropStmt *dropStmt = castNode(DropStmt, node);
|
||||
return dropStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_DropRoleStmt:
|
||||
{
|
||||
DropRoleStmt *dropRoleStmt = castNode(DropRoleStmt, node);
|
||||
return dropRoleStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_DropdbStmt:
|
||||
{
|
||||
DropdbStmt *dropdbStmt = castNode(DropdbStmt, node);
|
||||
return dropdbStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_DropTableSpaceStmt:
|
||||
{
|
||||
DropTableSpaceStmt *dropTableSpaceStmt = castNode(DropTableSpaceStmt, node);
|
||||
return dropTableSpaceStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_DropUserMappingStmt:
|
||||
{
|
||||
DropUserMappingStmt *dropUserMappingStmt = castNode(DropUserMappingStmt,
|
||||
node);
|
||||
return dropUserMappingStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_DropSubscriptionStmt:
|
||||
{
|
||||
DropSubscriptionStmt *dropSubscriptionStmt = castNode(DropSubscriptionStmt,
|
||||
node);
|
||||
return dropSubscriptionStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_AlterTableStmt:
|
||||
{
|
||||
AlterTableStmt *alterTableStmt = castNode(AlterTableStmt, node);
|
||||
return alterTableStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_AlterDomainStmt:
|
||||
{
|
||||
AlterDomainStmt *alterDomainStmt = castNode(AlterDomainStmt, node);
|
||||
return alterDomainStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_AlterSeqStmt:
|
||||
{
|
||||
AlterSeqStmt *alterSeqStmt = castNode(AlterSeqStmt, node);
|
||||
return alterSeqStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_AlterStatsStmt:
|
||||
{
|
||||
AlterStatsStmt *alterStatsStmt = castNode(AlterStatsStmt, node);
|
||||
return alterStatsStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_RenameStmt:
|
||||
{
|
||||
RenameStmt *renameStmt = castNode(RenameStmt, node);
|
||||
return renameStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_AlterObjectSchemaStmt:
|
||||
{
|
||||
AlterObjectSchemaStmt *alterObjectSchemaStmt = castNode(AlterObjectSchemaStmt,
|
||||
node);
|
||||
return alterObjectSchemaStmt->missing_ok;
|
||||
}
|
||||
|
||||
case T_AlterTSConfigurationStmt:
|
||||
{
|
||||
AlterTSConfigurationStmt *alterTSConfigurationStmt = castNode(
|
||||
AlterTSConfigurationStmt, node);
|
||||
return alterTSConfigurationStmt->missing_ok;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AlterRoleSetStatementContainsAll returns true if the statement is a
|
||||
* ALTER ROLE ALL (SET / RESET).
|
||||
*/
|
||||
static bool
|
||||
AlterRoleSetStatementContainsAll(Node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nodeTag(node) == T_AlterRoleSetStmt)
|
||||
{
|
||||
/* rolespec is null for the role 'ALL' */
|
||||
AlterRoleSetStmt *alterRoleSetStmt = castNode(AlterRoleSetStmt, node);
|
||||
|
||||
return alterRoleSetStmt->role == NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -324,7 +324,7 @@ CreateForeignConstraintRelationshipGraph()
|
|||
|
||||
ClearForeignConstraintRelationshipGraphContext();
|
||||
|
||||
MemoryContext fConstraintRelationshipMemoryContext = AllocSetContextCreateExtended(
|
||||
MemoryContext fConstraintRelationshipMemoryContext = AllocSetContextCreateInternal(
|
||||
CacheMemoryContext,
|
||||
"Forign Constraint Relationship Graph Context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
|
|
|
@ -161,13 +161,31 @@ GeneratePositiveIntSequenceList(int upTo)
|
|||
/*
|
||||
* StringJoin gets a list of char * and then simply
|
||||
* returns a newly allocated char * joined with the
|
||||
* given delimiter.
|
||||
* given delimiter. It uses ';' as the delimiter by
|
||||
* default.
|
||||
*/
|
||||
char *
|
||||
StringJoin(List *stringList, char delimiter)
|
||||
{
|
||||
return StringJoinParams(stringList, delimiter, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* StringJoin gets a list of char * and then simply
|
||||
* returns a newly allocated char * joined with the
|
||||
* given delimiter, prefix and postfix.
|
||||
*/
|
||||
char *
|
||||
StringJoinParams(List *stringList, char delimiter, char *prefix, char *postfix)
|
||||
{
|
||||
StringInfo joinedString = makeStringInfo();
|
||||
|
||||
if (prefix != NULL)
|
||||
{
|
||||
appendStringInfoString(joinedString, prefix);
|
||||
}
|
||||
|
||||
const char *command = NULL;
|
||||
int curIndex = 0;
|
||||
foreach_ptr(command, stringList)
|
||||
|
@ -180,6 +198,11 @@ StringJoin(List *stringList, char delimiter)
|
|||
curIndex++;
|
||||
}
|
||||
|
||||
if (postfix != NULL)
|
||||
{
|
||||
appendStringInfoString(joinedString, postfix);
|
||||
}
|
||||
|
||||
return joinedString->data;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,12 @@
|
|||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* GUC controls showing of some of the unwanted citus messages, it is intended to be set false
|
||||
* before vanilla tests to not break postgres test logs.
|
||||
*/
|
||||
bool EnableUnsupportedFeatureMessages = true;
|
||||
|
||||
/*
|
||||
* IsLoggableLevel returns true if either of client or server log guc is configured to
|
||||
* log the given log level.
|
||||
|
|
|
@ -53,9 +53,9 @@ static Relation try_relation_open_nolock(Oid relationId);
|
|||
static List * CreateFixPartitionConstraintsTaskList(Oid relationId);
|
||||
static List * WorkerFixPartitionConstraintCommandList(Oid relationId, uint64 shardId,
|
||||
List *checkConstraintList);
|
||||
static List * CreateFixPartitionShardIndexNamesTaskList(Oid parentRelationId,
|
||||
Oid partitionRelationId,
|
||||
Oid parentIndexOid);
|
||||
static void CreateFixPartitionShardIndexNames(Oid parentRelationId,
|
||||
Oid partitionRelationId,
|
||||
Oid parentIndexOid);
|
||||
static List * WorkerFixPartitionShardIndexNamesCommandList(uint64 parentShardId,
|
||||
List *indexIdList,
|
||||
Oid partitionRelationId);
|
||||
|
@ -205,6 +205,13 @@ fix_partition_shard_index_names(PG_FUNCTION_ARGS)
|
|||
|
||||
FixPartitionShardIndexNames(relationId, parentIndexOid);
|
||||
|
||||
/*
|
||||
* This UDF is called from fix_all_partition_shard_index_names() which iterates
|
||||
* over all the partitioned tables. There is no need to hold all the distributed
|
||||
* table metadata until the end of the transaction for the input table.
|
||||
*/
|
||||
CitusTableCacheFlushInvalidatedEntries();
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
|
@ -329,17 +336,9 @@ FixPartitionShardIndexNames(Oid relationId, Oid parentIndexOid)
|
|||
RelationGetRelationName(relation))));
|
||||
}
|
||||
|
||||
List *taskList =
|
||||
CreateFixPartitionShardIndexNamesTaskList(parentRelationId,
|
||||
partitionRelationId,
|
||||
parentIndexOid);
|
||||
|
||||
/* do not do anything if there are no index names to fix */
|
||||
if (taskList != NIL)
|
||||
{
|
||||
bool localExecutionSupported = true;
|
||||
ExecuteUtilityTaskList(taskList, localExecutionSupported);
|
||||
}
|
||||
CreateFixPartitionShardIndexNames(parentRelationId,
|
||||
partitionRelationId,
|
||||
parentIndexOid);
|
||||
|
||||
relation_close(relation, NoLock);
|
||||
}
|
||||
|
@ -494,15 +493,15 @@ WorkerFixPartitionConstraintCommandList(Oid relationId, uint64 shardId,
|
|||
* partition each task will have parent_indexes_count query strings. When we need
|
||||
* to fix a single index, parent_indexes_count becomes 1.
|
||||
*/
|
||||
static List *
|
||||
CreateFixPartitionShardIndexNamesTaskList(Oid parentRelationId, Oid partitionRelationId,
|
||||
Oid parentIndexOid)
|
||||
static void
|
||||
CreateFixPartitionShardIndexNames(Oid parentRelationId, Oid partitionRelationId,
|
||||
Oid parentIndexOid)
|
||||
{
|
||||
List *partitionList = PartitionList(parentRelationId);
|
||||
if (partitionList == NIL)
|
||||
{
|
||||
/* early exit if the parent relation does not have any partitions */
|
||||
return NIL;
|
||||
return;
|
||||
}
|
||||
|
||||
Relation parentRelation = RelationIdGetRelation(parentRelationId);
|
||||
|
@ -526,7 +525,7 @@ CreateFixPartitionShardIndexNamesTaskList(Oid parentRelationId, Oid partitionRel
|
|||
{
|
||||
/* early exit if the parent relation does not have any indexes */
|
||||
RelationClose(parentRelation);
|
||||
return NIL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -554,8 +553,12 @@ CreateFixPartitionShardIndexNamesTaskList(Oid parentRelationId, Oid partitionRel
|
|||
/* lock metadata before getting placement lists */
|
||||
LockShardListMetadata(parentShardIntervalList, ShareLock);
|
||||
|
||||
MemoryContext localContext = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"CreateFixPartitionShardIndexNames",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
MemoryContext oldContext = MemoryContextSwitchTo(localContext);
|
||||
|
||||
int taskId = 1;
|
||||
List *taskList = NIL;
|
||||
|
||||
ShardInterval *parentShardInterval = NULL;
|
||||
foreach_ptr(parentShardInterval, parentShardIntervalList)
|
||||
|
@ -566,43 +569,36 @@ CreateFixPartitionShardIndexNamesTaskList(Oid parentRelationId, Oid partitionRel
|
|||
WorkerFixPartitionShardIndexNamesCommandList(parentShardId,
|
||||
parentIndexIdList,
|
||||
partitionRelationId);
|
||||
|
||||
if (queryStringList != NIL)
|
||||
{
|
||||
Task *task = CitusMakeNode(Task);
|
||||
task->jobId = INVALID_JOB_ID;
|
||||
task->taskId = taskId++;
|
||||
|
||||
task->taskType = DDL_TASK;
|
||||
|
||||
/*
|
||||
* There could be O(#partitions * #indexes) queries in
|
||||
* the queryStringList.
|
||||
*
|
||||
* In order to avoid round-trips per query in queryStringList,
|
||||
* we join the string and send as a single command via the UDF.
|
||||
* Otherwise, the executor sends each command with one
|
||||
* round-trip.
|
||||
*/
|
||||
char *string = StringJoin(queryStringList, ';');
|
||||
StringInfo commandToRun = makeStringInfo();
|
||||
char *prefix = "SELECT pg_catalog.citus_run_local_command($$";
|
||||
char *postfix = "$$)";
|
||||
char *string = StringJoinParams(queryStringList, ';', prefix, postfix);
|
||||
|
||||
SetTaskQueryString(task, string);
|
||||
|
||||
appendStringInfo(commandToRun,
|
||||
"SELECT pg_catalog.citus_run_local_command($$%s$$)", string);
|
||||
SetTaskQueryString(task, commandToRun->data);
|
||||
|
||||
task->dependentTaskList = NULL;
|
||||
task->replicationModel = REPLICATION_MODEL_INVALID;
|
||||
task->anchorShardId = parentShardId;
|
||||
task->taskPlacementList = ActiveShardPlacementList(parentShardId);
|
||||
|
||||
taskList = lappend(taskList, task);
|
||||
bool localExecutionSupported = true;
|
||||
ExecuteUtilityTaskList(list_make1(task), localExecutionSupported);
|
||||
}
|
||||
|
||||
/* after every iteration, clean-up all the memory associated with it */
|
||||
MemoryContextReset(localContext);
|
||||
}
|
||||
|
||||
RelationClose(parentRelation);
|
||||
MemoryContextSwitchTo(oldContext);
|
||||
|
||||
return taskList;
|
||||
RelationClose(parentRelation);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -207,6 +207,15 @@ EnsureReferenceTablesExistOnAllNodesExtended(char transferMode)
|
|||
CopyShardPlacementToWorkerNodeQuery(sourceShardPlacement,
|
||||
newWorkerNode,
|
||||
transferMode);
|
||||
|
||||
/*
|
||||
* The placement copy command uses distributed execution to copy
|
||||
* the shard. This is allowed when indicating that the backend is a
|
||||
* rebalancer backend.
|
||||
*/
|
||||
ExecuteCriticalRemoteCommand(connection,
|
||||
"SET LOCAL application_name TO "
|
||||
CITUS_REBALANCER_NAME);
|
||||
ExecuteCriticalRemoteCommand(connection, placementCopyCommand->data);
|
||||
RemoteTransactionCommit(connection);
|
||||
}
|
||||
|
|
|
@ -181,7 +181,7 @@ WorkerCreateOrReplaceObject(List *sqlStatements)
|
|||
* same subject.
|
||||
*/
|
||||
Node *parseTree = ParseTreeNode(linitial(sqlStatements));
|
||||
List *addresses = GetObjectAddressListFromParseTree(parseTree, true);
|
||||
List *addresses = GetObjectAddressListFromParseTree(parseTree, true, false);
|
||||
Assert(list_length(addresses) == 1);
|
||||
|
||||
/* We have already asserted that we have exactly 1 address in the addresses. */
|
||||
|
|
|
@ -42,6 +42,7 @@ typedef struct BackendData
|
|||
uint64 globalPID;
|
||||
bool distributedCommandOriginator;
|
||||
DistributedTransactionId transactionId;
|
||||
bool activeBackend; /* set to false when backend exists */
|
||||
} BackendData;
|
||||
|
||||
|
||||
|
@ -54,6 +55,7 @@ extern void LockBackendSharedMemory(LWLockMode lockMode);
|
|||
extern void UnlockBackendSharedMemory(void);
|
||||
extern void UnSetDistributedTransactionId(void);
|
||||
extern void UnSetGlobalPID(void);
|
||||
extern void SetActiveMyBackend(bool value);
|
||||
extern void AssignDistributedTransactionId(void);
|
||||
extern void AssignGlobalPID(void);
|
||||
extern uint64 GetGlobalPID(void);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* citus_depended_object.h
|
||||
* Exposes functions related to hiding citus depended objects while executing
|
||||
* postgres vanilla tests.
|
||||
*
|
||||
* Copyright (c) CitusDependent Data, Inc.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef CITUS_DEPENDED_OBJECT_H
|
||||
#define CITUS_DEPENDED_OBJECT_H
|
||||
|
||||
#include "distributed/commands.h"
|
||||
#include "nodes/nodes.h"
|
||||
#include "nodes/parsenodes.h"
|
||||
|
||||
extern bool HideCitusDependentObjects;
|
||||
|
||||
extern void SetLocalClientMinMessagesIfRunningPGTests(int
|
||||
clientMinMessageLevel);
|
||||
extern void SetLocalHideCitusDependentObjectsDisabledWhenAlreadyEnabled(void);
|
||||
extern bool HideCitusDependentObjectsOnQueriesOfPgMetaTables(Node *node, void *context);
|
||||
extern bool IsPgLocksTable(RangeTblEntry *rte);
|
||||
extern bool DistOpsHasInvalidObject(Node *node, const DistributeObjectOps *ops);
|
||||
|
||||
#endif /* CITUS_DEPENDED_OBJECT_H */
|
|
@ -39,6 +39,15 @@ extern void SwitchToSequentialAndLocalExecutionIfPartitionNameTooLong(Oid
|
|||
Oid
|
||||
partitionRelationId);
|
||||
|
||||
/* DistOpsOperationType to be used in DistributeObjectOps */
|
||||
typedef enum DistOpsOperationType
|
||||
{
|
||||
DIST_OPS_NONE,
|
||||
DIST_OPS_CREATE,
|
||||
DIST_OPS_ALTER,
|
||||
DIST_OPS_DROP,
|
||||
} DistOpsOperationType;
|
||||
|
||||
|
||||
/*
|
||||
* DistributeObjectOps specifies handlers for node/object type pairs.
|
||||
|
@ -52,7 +61,8 @@ extern void SwitchToSequentialAndLocalExecutionIfPartitionNameTooLong(Oid
|
|||
* 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.
|
||||
* 2nd parameter is missing_ok, and
|
||||
* 3rd parameter is isPostProcess.
|
||||
* markDistribued: true if the object will be distributed.
|
||||
*
|
||||
* preprocess/postprocess return a List of DDLJobs.
|
||||
|
@ -63,7 +73,7 @@ typedef struct DistributeObjectOps
|
|||
void (*qualify)(Node *);
|
||||
List * (*preprocess)(Node *, const char *, ProcessUtilityContext);
|
||||
List * (*postprocess)(Node *, const char *);
|
||||
List * (*address)(Node *, bool);
|
||||
List * (*address)(Node *, bool, bool);
|
||||
bool markDistributed;
|
||||
|
||||
/* fields used by common implementations, omitted for specialized implementations */
|
||||
|
@ -74,6 +84,9 @@ typedef struct DistributeObjectOps
|
|||
* common propagation functions will not propagate the creation of the object.
|
||||
*/
|
||||
bool *featureFlag;
|
||||
|
||||
/* specifies the type of the operation */
|
||||
DistOpsOperationType operationType;
|
||||
} DistributeObjectOps;
|
||||
|
||||
#define CITUS_TRUNCATE_TRIGGER_NAME "citus_truncate_trigger"
|
||||
|
@ -147,6 +160,10 @@ extern List * PostprocessAlterDistributedObjectStmt(Node *stmt, const char *quer
|
|||
extern List * PreprocessDropDistributedObjectStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext
|
||||
processUtilityContext);
|
||||
extern List * DropTextSearchConfigObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * DropTextSearchDictObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
|
||||
/* index.c */
|
||||
typedef void (*PGIndexProcessor)(Form_pg_index, List **, int);
|
||||
|
@ -159,24 +176,33 @@ extern bool CallDistributedProcedureRemotely(CallStmt *callStmt, DestReceiver *d
|
|||
/* collation.c - forward declarations */
|
||||
extern char * CreateCollationDDL(Oid collationId);
|
||||
extern List * CreateCollationDDLsIdempotent(Oid collationId);
|
||||
extern List * AlterCollationOwnerObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * RenameCollationStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * AlterCollationOwnerObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * RenameCollationStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterCollationSchemaStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern char * GenerateBackupNameForCollationCollision(const ObjectAddress *address);
|
||||
extern List * DefineCollationStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * DefineCollationStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
|
||||
/* database.c - forward declarations */
|
||||
extern List * AlterDatabaseOwnerObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterDatabaseOwnerObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * DatabaseOwnerDDLCommands(const ObjectAddress *address);
|
||||
|
||||
/* domain.c - forward declarations */
|
||||
extern List * CreateDomainStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterDomainStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * CreateDomainStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterDomainStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * DomainRenameConstraintStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
extern List * AlterDomainOwnerStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * RenameDomainStmtObjectAddress(Node *node, bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterDomainOwnerStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * RenameDomainStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern CreateDomainStmt * RecreateDomainStmt(Oid domainOid);
|
||||
extern Oid get_constraint_typid(Oid conoid);
|
||||
|
||||
|
@ -209,9 +235,9 @@ extern List * PreprocessAlterExtensionContentsStmt(Node *node,
|
|||
processUtilityContext);
|
||||
extern List * CreateExtensionDDLCommand(const ObjectAddress *extensionAddress);
|
||||
extern List * AlterExtensionSchemaStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterExtensionUpdateStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern void CreateExtensionWithVersion(char *extname, char *extVersion);
|
||||
extern void AlterExtensionUpdateStmt(char *extname, char *extVersion);
|
||||
extern int GetExtensionVersionNumber(char *extVersion);
|
||||
|
@ -263,11 +289,14 @@ extern Acl * GetPrivilegesForFDW(Oid FDWOid);
|
|||
extern List * PreprocessGrantOnForeignServerStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext
|
||||
processUtilityContext);
|
||||
extern List * CreateForeignServerStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterForeignServerStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * RenameForeignServerStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * CreateForeignServerStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterForeignServerStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * RenameForeignServerStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterForeignServerOwnerStmtObjectAddress(Node *node, bool
|
||||
missing_ok);
|
||||
missing_ok, bool isPostprocess);
|
||||
extern List * GetForeignServerCreateDDLCommand(Oid serverId);
|
||||
|
||||
|
||||
|
@ -283,25 +312,25 @@ extern List * PreprocessCreateFunctionStmt(Node *stmt, const char *queryString,
|
|||
extern List * PostprocessCreateFunctionStmt(Node *stmt,
|
||||
const char *queryString);
|
||||
extern List * CreateFunctionStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * DefineAggregateStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * PreprocessAlterFunctionStmt(Node *stmt, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * AlterFunctionStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * RenameFunctionStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterFunctionOwnerObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterFunctionSchemaStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * PreprocessAlterFunctionDependsStmt(Node *stmt,
|
||||
const char *queryString,
|
||||
ProcessUtilityContext
|
||||
processUtilityContext);
|
||||
extern List * AlterFunctionDependsStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * PreprocessGrantOnFunctionStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PostprocessGrantOnFunctionStmt(Node *node, const char *queryString);
|
||||
|
@ -328,6 +357,7 @@ extern LOCKMODE GetCreateIndexRelationLockMode(IndexStmt *createIndexStatement);
|
|||
extern List * PreprocessReindexStmt(Node *ReindexStatement,
|
||||
const char *ReindexCommand,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * ReindexStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess);
|
||||
extern List * PreprocessDropIndexStmt(Node *dropIndexStatement,
|
||||
const char *dropIndexCommand,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
|
@ -340,7 +370,8 @@ extern List * ExecuteFunctionOnEachTableIndex(Oid relationId, PGIndexProcessor
|
|||
extern bool IsReindexWithParam_compat(ReindexStmt *stmt, char *paramName);
|
||||
|
||||
/* objectaddress.c - forward declarations */
|
||||
extern List * CreateExtensionStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * CreateExtensionStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
|
||||
|
||||
/* policy.c - forward declarations */
|
||||
|
@ -377,9 +408,9 @@ extern List * PreprocessAlterRoleSetStmt(Node *stmt, const char *queryString,
|
|||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * GenerateAlterRoleSetCommandForRole(Oid roleid);
|
||||
extern List * AlterRoleStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterRoleSetStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * PreprocessCreateRoleStmt(Node *stmt, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PreprocessDropRoleStmt(Node *stmt, const char *queryString,
|
||||
|
@ -388,7 +419,8 @@ extern List * PreprocessGrantRoleStmt(Node *stmt, const char *queryString,
|
|||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PostprocessGrantRoleStmt(Node *stmt, const char *queryString);
|
||||
extern List * GenerateCreateOrAlterRoleCommand(Oid roleOid);
|
||||
extern List * CreateRoleStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * CreateRoleStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern void UnmarkRolesDistributed(List *roles);
|
||||
extern List * FilterDistributedRoles(List *roles);
|
||||
|
||||
|
@ -402,8 +434,10 @@ extern List * PreprocessAlterObjectSchemaStmt(Node *alterObjectSchemaStmt,
|
|||
const char *alterObjectSchemaCommand);
|
||||
extern List * PreprocessGrantOnSchemaStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * CreateSchemaStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterSchemaRenameStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * CreateSchemaStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterSchemaRenameStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
|
||||
/* sequence.c - forward declarations */
|
||||
extern List * PreprocessAlterSequenceStmt(Node *node, const char *queryString,
|
||||
|
@ -417,15 +451,21 @@ extern List * PreprocessAlterSequenceOwnerStmt(Node *node, const char *queryStri
|
|||
extern List * PostprocessAlterSequenceOwnerStmt(Node *node, const char *queryString);
|
||||
extern List * PreprocessDropSequenceStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * SequenceDropStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * PreprocessRenameSequenceStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PreprocessGrantOnSequenceStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PostprocessGrantOnSequenceStmt(Node *node, const char *queryString);
|
||||
extern List * AlterSequenceStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterSequenceSchemaStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterSequenceOwnerStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * RenameSequenceStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterSequenceStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterSequenceSchemaStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterSequenceOwnerStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * RenameSequenceStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern void ErrorIfUnsupportedSeqStmt(CreateSeqStmt *createSeqStmt);
|
||||
extern void ErrorIfDistributedAlterSeqOwnedBy(AlterSeqStmt *alterSeqStmt);
|
||||
extern char * GenerateBackupNameForSequenceCollision(const ObjectAddress *address);
|
||||
|
@ -436,9 +476,12 @@ extern void RenameExistingSequenceWithDifferentTypeIfExists(RangeVar *sequence,
|
|||
extern List * PreprocessCreateStatisticsStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PostprocessCreateStatisticsStmt(Node *node, const char *queryString);
|
||||
extern List * CreateStatisticsStmtObjectAddress(Node *node, bool missingOk);
|
||||
extern List * CreateStatisticsStmtObjectAddress(Node *node, bool missingOk, bool
|
||||
isPostprocess);
|
||||
extern List * PreprocessDropStatisticsStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * DropStatisticsObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext
|
||||
processUtilityContext);
|
||||
|
@ -446,7 +489,8 @@ extern List * PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryS
|
|||
ProcessUtilityContext
|
||||
processUtilityContext);
|
||||
extern List * PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString);
|
||||
extern List * AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk);
|
||||
extern List * AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk, bool
|
||||
isPostprocess);
|
||||
extern List * PreprocessAlterStatisticsStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PreprocessAlterStatisticsOwnerStmt(Node *node, const char *queryString,
|
||||
|
@ -488,7 +532,7 @@ extern void ErrorIfUnsupportedConstraint(Relation relation, char distributionMet
|
|||
char referencingReplicationModel,
|
||||
Var *distributionColumn, uint32 colocationId);
|
||||
extern List * AlterTableSchemaStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * MakeNameListFromRangeVar(const RangeVar *rel);
|
||||
extern Oid GetSequenceOid(Oid relationId, AttrNumber attnum);
|
||||
extern bool ConstrTypeUsesIndex(ConstrType constrType);
|
||||
|
@ -500,29 +544,38 @@ extern List * GetCreateTextSearchDictionaryStatements(const ObjectAddress *addre
|
|||
extern List * CreateTextSearchConfigDDLCommandsIdempotent(const ObjectAddress *address);
|
||||
extern List * CreateTextSearchDictDDLCommandsIdempotent(const ObjectAddress *address);
|
||||
extern List * CreateTextSearchConfigurationObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * CreateTextSearchDictObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * RenameTextSearchConfigurationStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * RenameTextSearchDictionaryStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTextSearchConfigurationStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTextSearchDictionaryStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTextSearchConfigurationSchemaStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTextSearchDictionarySchemaStmtObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * TextSearchConfigurationCommentObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * TextSearchDictCommentObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterTextSearchConfigurationOwnerObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTextSearchDictOwnerObjectAddress(Node *node,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern char * GenerateBackupNameForTextSearchConfiguration(const ObjectAddress *address);
|
||||
extern char * GenerateBackupNameForTextSearchDict(const ObjectAddress *address);
|
||||
extern List * get_ts_config_namelist(Oid tsconfigOid);
|
||||
|
@ -535,16 +588,20 @@ extern List * PreprocessRenameTypeAttributeStmt(Node *stmt, const char *queryStr
|
|||
ProcessUtilityContext
|
||||
processUtilityContext);
|
||||
extern Node * CreateTypeStmtByObjectAddress(const ObjectAddress *address);
|
||||
extern List * CompositeTypeStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * CreateEnumStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * AlterTypeStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * AlterEnumStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * RenameTypeStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * CompositeTypeStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * CreateEnumStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTypeStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterEnumStmtObjectAddress(Node *stmt, bool missing_ok, bool isPostprocess);
|
||||
extern List * RenameTypeStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * AlterTypeSchemaStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
bool missing_ok, bool isPostprocess);
|
||||
extern List * RenameTypeAttributeStmtObjectAddress(Node *stmt,
|
||||
bool missing_ok);
|
||||
extern List * AlterTypeOwnerObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * AlterTypeOwnerObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * CreateTypeDDLCommandsIdempotent(const ObjectAddress *typeAddress);
|
||||
extern char * GenerateBackupNameForTypeCollision(const ObjectAddress *address);
|
||||
|
||||
|
@ -565,10 +622,11 @@ extern List * PostprocessVacuumStmt(Node *node, const char *vacuumCommand);
|
|||
extern List * PreprocessViewStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PostprocessViewStmt(Node *node, const char *queryString);
|
||||
extern List * ViewStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterViewStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * ViewStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess);
|
||||
extern List * AlterViewStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess);
|
||||
extern List * PreprocessDropViewStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * DropViewStmtObjectAddress(Node *node, bool missing_ok, bool isPostprocess);
|
||||
extern char * CreateViewDDLCommand(Oid viewOid);
|
||||
extern List * GetViewCreationCommandsOfTable(Oid relationId);
|
||||
extern List * GetViewCreationTableDDLCommandsOfTable(Oid relationId);
|
||||
|
@ -582,11 +640,13 @@ extern List * PreprocessAlterViewStmt(Node *node, const char *queryString,
|
|||
extern List * PostprocessAlterViewStmt(Node *node, const char *queryString);
|
||||
extern List * PreprocessRenameViewStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * RenameViewStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * RenameViewStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * PreprocessAlterViewSchemaStmt(Node *node, const char *queryString,
|
||||
ProcessUtilityContext processUtilityContext);
|
||||
extern List * PostprocessAlterViewSchemaStmt(Node *node, const char *queryString);
|
||||
extern List * AlterViewSchemaStmtObjectAddress(Node *node, bool missing_ok);
|
||||
extern List * AlterViewSchemaStmtObjectAddress(Node *node, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern bool IsViewRenameStmt(RenameStmt *renameStmt);
|
||||
|
||||
/* trigger.c - forward declarations */
|
||||
|
@ -594,7 +654,8 @@ extern List * GetExplicitTriggerCommandList(Oid relationId);
|
|||
extern HeapTuple GetTriggerTupleById(Oid triggerId, bool missingOk);
|
||||
extern List * GetExplicitTriggerIdList(Oid relationId);
|
||||
extern List * PostprocessCreateTriggerStmt(Node *node, const char *queryString);
|
||||
extern List * CreateTriggerStmtObjectAddress(Node *node, bool missingOk);
|
||||
extern List * CreateTriggerStmtObjectAddress(Node *node, bool missingOk, bool
|
||||
isPostprocess);
|
||||
extern void CreateTriggerEventExtendNames(CreateTrigStmt *createTriggerStmt,
|
||||
char *schemaName, uint64 shardId);
|
||||
extern List * PostprocessAlterTriggerRenameStmt(Node *node, const char *queryString);
|
||||
|
|
|
@ -176,7 +176,7 @@ extern void AppendCopyBinaryFooters(CopyOutState footerOutputState);
|
|||
extern void EndRemoteCopy(int64 shardId, List *connectionList);
|
||||
extern List * CreateRangeTable(Relation rel, AclMode requiredAccess);
|
||||
extern Node * ProcessCopyStmt(CopyStmt *copyStatement,
|
||||
QueryCompletionCompat *completionTag,
|
||||
QueryCompletion *completionTag,
|
||||
const char *queryString);
|
||||
extern void CheckCopyPermissions(CopyStmt *copyStatement);
|
||||
extern bool IsCopyResultStmt(CopyStmt *copyStatement);
|
||||
|
|
|
@ -84,13 +84,13 @@ extern void multi_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||
#endif
|
||||
ProcessUtilityContext context, ParamListInfo params,
|
||||
struct QueryEnvironment *queryEnv, DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag
|
||||
QueryCompletion *completionTag
|
||||
);
|
||||
extern void ProcessUtilityParseTree(Node *node, const char *queryString,
|
||||
ProcessUtilityContext context, ParamListInfo
|
||||
params,
|
||||
DestReceiver *dest,
|
||||
QueryCompletionCompat *completionTag
|
||||
QueryCompletion *completionTag
|
||||
);
|
||||
extern void MarkInvalidateForeignKeyGraph(void);
|
||||
extern void InvalidateForeignKeyGraphForDDL(void);
|
||||
|
|
|
@ -148,8 +148,10 @@ extern void QualifyAlterTypeOwnerStmt(Node *stmt);
|
|||
extern char * GetTypeNamespaceNameByNameList(List *names);
|
||||
extern Oid TypeOidGetNamespaceOid(Oid typeOid);
|
||||
|
||||
extern List * GetObjectAddressListFromParseTree(Node *parseTree, bool missing_ok);
|
||||
extern List * RenameAttributeStmtObjectAddress(Node *stmt, bool missing_ok);
|
||||
extern List * GetObjectAddressListFromParseTree(Node *parseTree, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
extern List * RenameAttributeStmtObjectAddress(Node *stmt, bool missing_ok, bool
|
||||
isPostprocess);
|
||||
|
||||
/* forward declarations for deparse_view_stmts.c */
|
||||
extern void QualifyDropViewStmt(Node *node);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
extern bool EnableRepartitionedInsertSelect;
|
||||
|
||||
extern TupleTableSlot * NonPushableInsertSelectExecScan(CustomScanState *node);
|
||||
extern Query * BuildSelectForInsertSelect(Query *insertSelectQuery);
|
||||
extern bool IsSupportedRedistributionTarget(Oid targetRelationId);
|
||||
extern bool IsRedistributablePlan(Plan *selectPlan);
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ typedef struct ListCellAndListWrapper
|
|||
for (ListCell *(var ## CellDoNotUse) = list_head(l); \
|
||||
(var ## CellDoNotUse) != NULL && \
|
||||
(((var) = lfirst(var ## CellDoNotUse)) || true); \
|
||||
var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse))
|
||||
var ## CellDoNotUse = lnext(l, var ## CellDoNotUse))
|
||||
|
||||
|
||||
/*
|
||||
|
@ -65,7 +65,7 @@ typedef struct ListCellAndListWrapper
|
|||
for (ListCell *(var ## CellDoNotUse) = list_head(l); \
|
||||
(var ## CellDoNotUse) != NULL && \
|
||||
(((var) = lfirst_int(var ## CellDoNotUse)) || true); \
|
||||
var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse))
|
||||
var ## CellDoNotUse = lnext(l, var ## CellDoNotUse))
|
||||
|
||||
|
||||
/*
|
||||
|
@ -78,7 +78,7 @@ typedef struct ListCellAndListWrapper
|
|||
for (ListCell *(var ## CellDoNotUse) = list_head(l); \
|
||||
(var ## CellDoNotUse) != NULL && \
|
||||
(((var) = lfirst_oid(var ## CellDoNotUse)) || true); \
|
||||
var ## CellDoNotUse = lnext_compat(l, var ## CellDoNotUse))
|
||||
var ## CellDoNotUse = lnext(l, var ## CellDoNotUse))
|
||||
|
||||
/*
|
||||
* forboth_ptr -
|
||||
|
@ -93,8 +93,8 @@ typedef struct ListCellAndListWrapper
|
|||
(var2 ## CellDoNotUse) != NULL && \
|
||||
(((var1) = lfirst(var1 ## CellDoNotUse)) || true) && \
|
||||
(((var2) = lfirst(var2 ## CellDoNotUse)) || true); \
|
||||
var1 ## CellDoNotUse = lnext_compat(l1, var1 ## CellDoNotUse), \
|
||||
var2 ## CellDoNotUse = lnext_compat(l2, var2 ## CellDoNotUse) \
|
||||
var1 ## CellDoNotUse = lnext(l1, var1 ## CellDoNotUse), \
|
||||
var2 ## CellDoNotUse = lnext(l2, var2 ## CellDoNotUse) \
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -111,8 +111,8 @@ typedef struct ListCellAndListWrapper
|
|||
(var2 ## CellDoNotUse) != NULL && \
|
||||
(((var1) = lfirst(var1 ## CellDoNotUse)) || true) && \
|
||||
(((var2) = lfirst_oid(var2 ## CellDoNotUse)) || true); \
|
||||
var1 ## CellDoNotUse = lnext_compat(l1, var1 ## CellDoNotUse), \
|
||||
var2 ## CellDoNotUse = lnext_compat(l2, var2 ## CellDoNotUse) \
|
||||
var1 ## CellDoNotUse = lnext(l1, var1 ## CellDoNotUse), \
|
||||
var2 ## CellDoNotUse = lnext(l2, var2 ## CellDoNotUse) \
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -129,8 +129,8 @@ typedef struct ListCellAndListWrapper
|
|||
(var2 ## CellDoNotUse) != NULL && \
|
||||
(((var1) = lfirst_int(var1 ## CellDoNotUse)) || true) && \
|
||||
(((var2) = lfirst_oid(var2 ## CellDoNotUse)) || true); \
|
||||
var1 ## CellDoNotUse = lnext_compat(l1, var1 ## CellDoNotUse), \
|
||||
var2 ## CellDoNotUse = lnext_compat(l2, var2 ## CellDoNotUse) \
|
||||
var1 ## CellDoNotUse = lnext(l1, var1 ## CellDoNotUse), \
|
||||
var2 ## CellDoNotUse = lnext(l2, var2 ## CellDoNotUse) \
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -166,6 +166,8 @@ extern List * SortList(List *pointerList,
|
|||
extern void ** PointerArrayFromList(List *pointerList);
|
||||
extern HTAB * ListToHashSet(List *pointerList, Size keySize, bool isStringList);
|
||||
extern char * StringJoin(List *stringList, char delimiter);
|
||||
extern char * StringJoinParams(List *stringList, char delimiter,
|
||||
char *prefix, char *postfix);
|
||||
extern List * ListTake(List *pointerList, int size);
|
||||
extern void * safe_list_nth(const List *list, int index);
|
||||
extern List * GeneratePositiveIntSequenceList(int upTo);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define CITUS_LOG_LEVEL_OFF 0
|
||||
|
||||
|
||||
extern bool EnableUnsupportedFeatureMessages;
|
||||
|
||||
extern bool IsLoggableLevel(int logLevel);
|
||||
extern char * HashLogMessage(const char *text);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ extern List * GetAllDependenciesForObject(const ObjectAddress *target);
|
|||
extern bool ErrorOrWarnIfAnyObjectHasUnsupportedDependency(List *objectAddresses);
|
||||
extern DeferredErrorMessage * DeferErrorIfAnyObjectHasUnsupportedDependency(const List *
|
||||
objectAddresses);
|
||||
extern List * GetAllCitusDependedDependenciesForObject(const ObjectAddress *target);
|
||||
extern List * OrderObjectAddressListInDependencyOrder(List *objectAddressList);
|
||||
extern bool SupportedDependencyByCitus(const ObjectAddress *address);
|
||||
extern List * GetPgDependTuplesForDependingObjects(Oid targetObjectClassId,
|
||||
|
|
|
@ -29,6 +29,7 @@ extern void UnmarkObjectDistributed(const ObjectAddress *address);
|
|||
extern bool IsTableOwnedByExtension(Oid relationId);
|
||||
extern bool IsAnyObjectAddressOwnedByExtension(const List *targets,
|
||||
ObjectAddress *extensionAddress);
|
||||
extern bool IsObjectAddressOwnedByCitus(const ObjectAddress *objectAddress);
|
||||
extern ObjectAddress PgGetObjectAddress(char *ttype, ArrayType *namearr,
|
||||
ArrayType *argsarr);
|
||||
extern List * GetDistributedObjectAddressList(void);
|
||||
|
|
|
@ -263,6 +263,7 @@ extern Oid CitusTableVisibleFuncId(void);
|
|||
extern Oid RelationIsAKnownShardFuncId(void);
|
||||
extern Oid JsonbExtractPathFuncId(void);
|
||||
extern Oid JsonbExtractPathTextFuncId(void);
|
||||
extern Oid CitusDependentObjectFuncId(void);
|
||||
|
||||
/* enum oids */
|
||||
extern Oid PrimaryNodeRoleId(void);
|
||||
|
|
|
@ -34,7 +34,7 @@ typedef enum RelationAccessMode
|
|||
RELATION_PARALLEL_ACCESSED
|
||||
} RelationAccessMode;
|
||||
|
||||
extern void AllocateRelationAccessHash(void);
|
||||
extern void InitRelationAccessHash(void);
|
||||
extern void ResetRelationAccessHash(void);
|
||||
extern void RecordRelationAccessIfNonDistTable(Oid relationId,
|
||||
ShardPlacementAccessType accessType);
|
||||
|
|
|
@ -41,7 +41,8 @@ typedef enum AdvisoryLocktagClass
|
|||
ADV_LOCKTAG_CLASS_CITUS_COLOCATED_SHARDS_METADATA = 8,
|
||||
ADV_LOCKTAG_CLASS_CITUS_OPERATIONS = 9,
|
||||
ADV_LOCKTAG_CLASS_CITUS_PLACEMENT_CLEANUP = 10,
|
||||
ADV_LOCKTAG_CLASS_CITUS_LOGICAL_REPLICATION = 12
|
||||
ADV_LOCKTAG_CLASS_CITUS_LOGICAL_REPLICATION = 12,
|
||||
ADV_LOCKTAG_CLASS_CITUS_REBALANCE_PLACEMENT_COLOCATION = 13
|
||||
} AdvisoryLocktagClass;
|
||||
|
||||
/* CitusOperations has constants for citus operations */
|
||||
|
@ -84,6 +85,17 @@ typedef enum CitusOperations
|
|||
(uint32) (colocationOrTableId), \
|
||||
ADV_LOCKTAG_CLASS_CITUS_REBALANCE_COLOCATION)
|
||||
|
||||
/* reuse advisory lock, but with different, unused field 4 (13)
|
||||
* Also it has the database hardcoded to MyDatabaseId, to ensure the locks
|
||||
* are local to each database */
|
||||
#define SET_LOCKTAG_REBALANCE_PLACEMENT_COLOCATION(tag, colocationOrTableId) \
|
||||
SET_LOCKTAG_ADVISORY(tag, \
|
||||
MyDatabaseId, \
|
||||
(uint32) ((colocationOrTableId) >> 32), \
|
||||
(uint32) (colocationOrTableId), \
|
||||
ADV_LOCKTAG_CLASS_CITUS_REBALANCE_PLACEMENT_COLOCATION)
|
||||
|
||||
|
||||
/* advisory lock for citus operations, also it has the database hardcoded to MyDatabaseId,
|
||||
* to ensure the locks are local to each database */
|
||||
#define SET_LOCKTAG_CITUS_OPERATION(tag, operationId) \
|
||||
|
|
|
@ -194,6 +194,7 @@ extern List * RebalancePlacementUpdates(List *workerNodeList,
|
|||
extern List * ReplicationPlacementUpdates(List *workerNodeList, List *shardPlacementList,
|
||||
int shardReplicationFactor);
|
||||
extern void ExecuteRebalancerCommandInSeparateTransaction(char *command);
|
||||
|
||||
extern void AcquirePlacementColocationLock(Oid relationId, int lockMode,
|
||||
const char *operationName);
|
||||
|
||||
#endif /* SHARD_REBALANCER_H */
|
||||
|
|
|
@ -23,5 +23,6 @@ extern IsColumnarTableAmTable_type extern_IsColumnarTableAmTable;
|
|||
extern ReadColumnarOptions_type extern_ReadColumnarOptions;
|
||||
|
||||
extern void StartupCitusBackend(void);
|
||||
extern const char * GetClientMinMessageLevelNameForValue(int minMessageLevel);
|
||||
|
||||
#endif /* SHARED_LIBRARY_INIT_H */
|
||||
|
|
|
@ -123,37 +123,12 @@ RelationGetSmgr(Relation rel)
|
|||
#define ROLE_PG_READ_ALL_STATS DEFAULT_ROLE_READ_ALL_STATS
|
||||
#endif
|
||||
|
||||
#define lnext_compat(l, r) lnext(l, r)
|
||||
#define list_delete_cell_compat(l, c, p) list_delete_cell(l, c)
|
||||
#define pg_plan_query_compat(p, q, c, b) pg_plan_query(p, q, c, b)
|
||||
#define planner_compat(p, c, b) planner(p, NULL, c, b)
|
||||
#define standard_planner_compat(a, c, d) standard_planner(a, NULL, c, d)
|
||||
#define GetSequencesOwnedByRelation(a) getOwnedSequences(a)
|
||||
#define GetSequencesOwnedByColumn(a, b) getOwnedSequences_internal(a, b, 0)
|
||||
#define CMDTAG_SELECT_COMPAT CMDTAG_SELECT
|
||||
#define ExplainOnePlanCompat(a, b, c, d, e, f, g, h) \
|
||||
ExplainOnePlan(a, b, c, d, e, f, g, h)
|
||||
#define SetListCellPtr(a, b) ((a)->ptr_value = (b))
|
||||
#define RangeTableEntryFromNSItem(a) ((a)->p_rte)
|
||||
#define QueryCompletionCompat QueryCompletion
|
||||
|
||||
#define CreateTableSlotForRel(rel) table_slot_create(rel, NULL)
|
||||
#define MakeSingleTupleTableSlotCompat MakeSingleTupleTableSlot
|
||||
#define AllocSetContextCreateExtended AllocSetContextCreateInternal
|
||||
#define NextCopyFromCompat NextCopyFrom
|
||||
#define ArrayRef SubscriptingRef
|
||||
#define T_ArrayRef T_SubscriptingRef
|
||||
#define or_clause is_orclause
|
||||
#define GetSysCacheOid1Compat GetSysCacheOid1
|
||||
#define GetSysCacheOid2Compat GetSysCacheOid2
|
||||
#define GetSysCacheOid3Compat GetSysCacheOid3
|
||||
#define GetSysCacheOid4Compat GetSysCacheOid4
|
||||
|
||||
#define fcGetArgValue(fc, n) ((fc)->args[n].value)
|
||||
#define fcGetArgNull(fc, n) ((fc)->args[n].isnull)
|
||||
#define fcSetArgExt(fc, n, val, is_null) \
|
||||
(((fc)->args[n].isnull = (is_null)), ((fc)->args[n].value = (val)))
|
||||
|
||||
#define fcSetArg(fc, n, value) fcSetArgExt(fc, n, value, false)
|
||||
#define fcSetArgNull(fc, n) fcSetArgExt(fc, n, (Datum) 0, true)
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue