Merge pull request #3654 from citusdata/2776_modifying_ctes

Modifying ctes in router planner
pull/3903/head
Philip Dubé 2020-06-11 15:26:00 +00:00 committed by GitHub
commit f344c1a4bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 2192 additions and 587 deletions

View File

@ -1467,11 +1467,6 @@ ReadOnlyTask(TaskType taskType)
case MAP_TASK: case MAP_TASK:
case MERGE_TASK: case MERGE_TASK:
{ {
/*
* TODO: We currently do not execute modifying CTEs via ROUTER_TASK/SQL_TASK.
* When we implement it, we should either not use the mentioned task types for
* modifying CTEs detect them here.
*/
return true; return true;
} }

View File

@ -54,7 +54,7 @@ static Node * DelayedErrorCreateScan(CustomScan *scan);
/* functions that are common to different scans */ /* functions that are common to different scans */
static void CitusBeginScan(CustomScanState *node, EState *estate, int eflags); static void CitusBeginScan(CustomScanState *node, EState *estate, int eflags);
static void CitusBeginSelectScan(CustomScanState *node, EState *estate, int eflags); static void CitusBeginReadOnlyScan(CustomScanState *node, EState *estate, int eflags);
static void CitusBeginModifyScan(CustomScanState *node, EState *estate, int eflags); static void CitusBeginModifyScan(CustomScanState *node, EState *estate, int eflags);
static void CitusPreExecScan(CitusScanState *scanState); static void CitusPreExecScan(CitusScanState *scanState);
static bool ModifyJobNeedsEvaluation(Job *workerJob); static bool ModifyJobNeedsEvaluation(Job *workerJob);
@ -206,7 +206,7 @@ CitusBeginScan(CustomScanState *node, EState *estate, int eflags)
} }
else if (distributedPlan->modLevel == ROW_MODIFY_READONLY) else if (distributedPlan->modLevel == ROW_MODIFY_READONLY)
{ {
CitusBeginSelectScan(node, estate, eflags); CitusBeginReadOnlyScan(node, estate, eflags);
} }
else else
{ {
@ -248,14 +248,16 @@ CitusExecScan(CustomScanState *node)
/* /*
* CitusBeginSelectScan handles deferred pruning and plan caching for SELECTs. * CitusBeginReadOnlyScan handles deferred pruning and plan caching for SELECTs.
*/ */
static void static void
CitusBeginSelectScan(CustomScanState *node, EState *estate, int eflags) CitusBeginReadOnlyScan(CustomScanState *node, EState *estate, int eflags)
{ {
CitusScanState *scanState = (CitusScanState *) node; CitusScanState *scanState = (CitusScanState *) node;
DistributedPlan *originalDistributedPlan = scanState->distributedPlan; DistributedPlan *originalDistributedPlan = scanState->distributedPlan;
Assert(originalDistributedPlan->workerJob->jobQuery->commandType == CMD_SELECT);
if (!originalDistributedPlan->workerJob->deferredPruning) if (!originalDistributedPlan->workerJob->deferredPruning)
{ {
/* /*
@ -295,7 +297,7 @@ CitusBeginSelectScan(CustomScanState *node, EState *estate, int eflags)
* *
* TODO: evaluate stable functions * TODO: evaluate stable functions
*/ */
ExecuteMasterEvaluableParameters(jobQuery, planState); ExecuteMasterEvaluableExpressions(jobQuery, planState);
/* job query no longer has parameters, so we should not send any */ /* job query no longer has parameters, so we should not send any */
workerJob->parametersInJobQueryResolved = true; workerJob->parametersInJobQueryResolved = true;
@ -345,8 +347,7 @@ CitusBeginModifyScan(CustomScanState *node, EState *estate, int eflags)
if (ModifyJobNeedsEvaluation(workerJob)) if (ModifyJobNeedsEvaluation(workerJob))
{ {
/* evaluate both functions and parameters */ ExecuteMasterEvaluableExpressions(jobQuery, planState);
ExecuteMasterEvaluableFunctionsAndParameters(jobQuery, planState);
/* job query no longer has parameters, so we should not send any */ /* job query no longer has parameters, so we should not send any */
workerJob->parametersInJobQueryResolved = true; workerJob->parametersInJobQueryResolved = true;

View File

@ -190,7 +190,7 @@ IsLocalPlanCachingSupported(Job *currentJob, DistributedPlan *originalDistribute
* We do not cache plans with volatile functions in the query. * We do not cache plans with volatile functions in the query.
* *
* The reason we care about volatile functions is primarily that we * The reason we care about volatile functions is primarily that we
* already executed them in ExecuteMasterEvaluableFunctionsAndParameters * already executed them in ExecuteMasterEvaluableExpressions
* and since we're falling back to the original query tree here we would * and since we're falling back to the original query tree here we would
* execute them again if we execute the plan. * execute them again if we execute the plan.
*/ */

View File

@ -457,6 +457,19 @@ IsDistributedTableRTE(Node *node)
} }
/*
* IsReferenceTableRTE gets a node and returns true if the node
* is a range table relation entry that points to a reference table.
*/
bool
IsReferenceTableRTE(Node *node)
{
Oid relationId = NodeTryGetRteRelid(node);
return relationId != InvalidOid && IsCitusTable(relationId) &&
PartitionMethod(relationId) == DISTRIBUTE_BY_NONE;
}
/* /*
* FullCompositeFieldList gets a composite field list, and checks if all fields * FullCompositeFieldList gets a composite field list, and checks if all fields
* of composite type are used in the list. * of composite type are used in the list.

View File

@ -4636,6 +4636,22 @@ RowModifyLevelForQuery(Query *query)
if (commandType == CMD_SELECT) if (commandType == CMD_SELECT)
{ {
if (query->hasModifyingCTE)
{
/* skip checking for INSERT as those CTEs are recursively planned */
CommonTableExpr *cte = NULL;
foreach_ptr(cte, query->cteList)
{
Query *cteQuery = (Query *) cte->ctequery;
if (cteQuery->commandType == CMD_UPDATE ||
cteQuery->commandType == CMD_DELETE)
{
return ROW_MODIFY_NONCOMMUTATIVE;
}
}
}
return ROW_MODIFY_READONLY; return ROW_MODIFY_READONLY;
} }

View File

@ -125,6 +125,9 @@ static void CreateSingleTaskRouterSelectPlan(DistributedPlan *distributedPlan,
plannerRestrictionContext); plannerRestrictionContext);
static Oid ResultRelationOidForQuery(Query *query); static Oid ResultRelationOidForQuery(Query *query);
static bool IsTidColumn(Node *node); static bool IsTidColumn(Node *node);
static DeferredErrorMessage * ModifyPartialQuerySupported(Query *queryTree, bool
multiShardQuery,
Oid *distributedTableId);
static DeferredErrorMessage * MultiShardModifyQuerySupported(Query *originalQuery, static DeferredErrorMessage * MultiShardModifyQuerySupported(Query *originalQuery,
PlannerRestrictionContext * PlannerRestrictionContext *
plannerRestrictionContext); plannerRestrictionContext);
@ -149,19 +152,16 @@ static List * BuildRoutesForInsert(Query *query, DeferredErrorMessage **planning
static List * GroupInsertValuesByShardId(List *insertValuesList); static List * GroupInsertValuesByShardId(List *insertValuesList);
static List * ExtractInsertValuesList(Query *query, Var *partitionColumn); static List * ExtractInsertValuesList(Query *query, Var *partitionColumn);
static DeferredErrorMessage * MultiRouterPlannableQuery(Query *query); static DeferredErrorMessage * MultiRouterPlannableQuery(Query *query);
static DeferredErrorMessage * ErrorIfQueryHasModifyingCTE(Query *queryTree); static DeferredErrorMessage * ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree);
static bool SelectsFromDistributedTable(List *rangeTableList, Query *query); static bool SelectsFromDistributedTable(List *rangeTableList, Query *query);
static ShardPlacement * CreateDummyPlacement(void); static ShardPlacement * CreateDummyPlacement(void);
static List * get_all_actual_clauses(List *restrictinfo_list); static List * get_all_actual_clauses(List *restrictinfo_list);
static int CompareInsertValuesByShardId(const void *leftElement, static int CompareInsertValuesByShardId(const void *leftElement,
const void *rightElement); const void *rightElement);
static List * SingleShardSelectTaskList(Query *query, uint64 jobId, static List * SingleShardTaskList(Query *query, uint64 jobId,
List *relationShardList, List *placementList, List *relationShardList, List *placementList,
uint64 shardId, bool parametersInQueryResolved); uint64 shardId, bool parametersInQueryResolved);
static bool RowLocksOnRelations(Node *node, List **rtiLockList); static bool RowLocksOnRelations(Node *node, List **rtiLockList);
static List * SingleShardModifyTaskList(Query *query, uint64 jobId,
List *relationShardList, List *placementList,
uint64 shardId, bool parametersInQueryResolved);
static List * RemoveCoordinatorPlacement(List *placementList); static List * RemoveCoordinatorPlacement(List *placementList);
static void ReorderTaskPlacementsByTaskAssignmentPolicy(Job *job, static void ReorderTaskPlacementsByTaskAssignmentPolicy(Job *job,
TaskAssignmentPolicyType TaskAssignmentPolicyType
@ -510,10 +510,15 @@ ResultRelationOidForQuery(Query *query)
*/ */
RangeTblEntry * RangeTblEntry *
ExtractResultRelationRTE(Query *query) ExtractResultRelationRTE(Query *query)
{
if (query->resultRelation > 0)
{ {
return rt_fetch(query->resultRelation, query->rtable); return rt_fetch(query->resultRelation, query->rtable);
} }
return NULL;
}
/* /*
* IsTidColumn gets a node and returns true if the node is a Var type of TID. * IsTidColumn gets a node and returns true if the node is a Var type of TID.
@ -535,28 +540,18 @@ IsTidColumn(Node *node)
/* /*
* ModifyQuerySupported returns NULL if the query only contains supported * ModifyPartialQuerySupported implements a subset of what ModifyQuerySupported checks,
* features, otherwise it returns an error description. * that subset being what's necessary to check modifying CTEs for.
* Note that we need both the original query and the modified one because
* different checks need different versions. In particular, we cannot
* perform the ContainsReadIntermediateResultFunction check on the
* rewritten query because it may have been replaced by a subplan,
* while some of the checks for setting the partition column value rely
* on the rewritten query.
*/ */
DeferredErrorMessage * static DeferredErrorMessage *
ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuery, ModifyPartialQuerySupported(Query *queryTree, bool multiShardQuery,
PlannerRestrictionContext *plannerRestrictionContext) Oid *distributedTableIdOutput)
{ {
uint32 rangeTableId = 1; uint32 rangeTableId = 1;
List *rangeTableList = NIL;
ListCell *rangeTableCell = NULL;
uint32 queryTableCount = 0;
CmdType commandType = queryTree->commandType; CmdType commandType = queryTree->commandType;
bool fastPathRouterQuery =
plannerRestrictionContext->fastPathRestrictionContext->fastPathRouterQuery;
Oid distributedTableId = ModifyQueryResultRelationId(queryTree); Oid distributedTableId = ModifyQueryResultRelationId(queryTree);
*distributedTableIdOutput = distributedTableId;
if (!IsCitusTable(distributedTableId)) if (!IsCitusTable(distributedTableId))
{ {
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
@ -573,30 +568,6 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
return deferredError; return deferredError;
} }
/*
* Here, we check if a recursively planned query tries to modify
* rows based on the ctid column. This is a bad idea because ctid of
* the rows could be changed before the modification part of
* the query is executed.
*
* We can exclude fast path queries since they cannot have intermediate
* results by definition.
*/
if (!fastPathRouterQuery &&
ContainsReadIntermediateResultFunction((Node *) originalQuery))
{
bool hasTidColumn = FindNodeCheck((Node *) originalQuery->jointree, IsTidColumn);
if (hasTidColumn)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"cannot perform distributed planning for the given "
"modification",
"Recursively planned distributed modifications "
"with ctid on where clause are not supported.",
NULL);
}
}
/* /*
* Reject subqueries which are in SELECT or WHERE clause. * Reject subqueries which are in SELECT or WHERE clause.
* Queries which include subqueries in FROM clauses are rejected below. * Queries which include subqueries in FROM clauses are rejected below.
@ -626,17 +597,38 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
Query *cteQuery = (Query *) cte->ctequery; Query *cteQuery = (Query *) cte->ctequery;
if (cteQuery->commandType != CMD_SELECT) if (cteQuery->commandType != CMD_SELECT)
{
/* Modifying CTEs still not supported for INSERTs & multi shard queries. */
if (queryTree->commandType == CMD_INSERT)
{ {
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"Router planner doesn't support non-select common table expressions.", "Router planner doesn't support non-select common table expressions with non-select queries.",
NULL, NULL); NULL, NULL);
} }
if (cteQuery->hasForUpdate) if (multiShardQuery)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"Router planner doesn't support non-select common table expressions with multi shard queries.",
NULL, NULL);
}
}
/* Modifying CTEs exclude both INSERT CTEs & INSERT queries. */
if (cteQuery->commandType == CMD_INSERT)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"Router planner doesn't support INSERT common table expressions.",
NULL, NULL);
}
if (cteQuery->hasForUpdate &&
FindNodeCheckInRangeTableList(cteQuery->rtable, IsReferenceTableRTE))
{ {
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"Router planner doesn't support SELECT FOR UPDATE" "Router planner doesn't support SELECT FOR UPDATE"
" in common table expressions.", " in common table expressions involving reference tables.",
NULL, NULL); NULL, NULL);
} }
@ -648,6 +640,8 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
NULL, NULL); NULL, NULL);
} }
if (cteQuery->commandType == CMD_SELECT)
{
DeferredErrorMessage *cteError = MultiRouterPlannableQuery(cteQuery); DeferredErrorMessage *cteError = MultiRouterPlannableQuery(cteQuery);
if (cteError) if (cteError)
{ {
@ -655,6 +649,174 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
} }
} }
} }
}
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
commandType == CMD_DELETE)
{
bool hasVarArgument = false; /* A STABLE function is passed a Var argument */
bool hasBadCoalesce = false; /* CASE/COALESCE passed a mutable function */
FromExpr *joinTree = queryTree->jointree;
ListCell *targetEntryCell = NULL;
foreach(targetEntryCell, queryTree->targetList)
{
TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell);
bool targetEntryPartitionColumn = false;
/* reference tables do not have partition column */
if (partitionColumn == NULL)
{
targetEntryPartitionColumn = false;
}
else if (targetEntry->resno == partitionColumn->varattno)
{
targetEntryPartitionColumn = true;
}
/* skip resjunk entries: UPDATE adds some for ctid, etc. */
if (targetEntry->resjunk)
{
continue;
}
if (commandType == CMD_UPDATE &&
FindNodeCheck((Node *) targetEntry->expr, CitusIsVolatileFunction))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"functions used in UPDATE queries on distributed "
"tables must not be VOLATILE",
NULL, NULL);
}
if (commandType == CMD_UPDATE && targetEntryPartitionColumn &&
TargetEntryChangesValue(targetEntry, partitionColumn,
queryTree->jointree))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"modifying the partition value of rows is not "
"allowed",
NULL, NULL);
}
if (commandType == CMD_UPDATE &&
MasterIrreducibleExpression((Node *) targetEntry->expr,
&hasVarArgument, &hasBadCoalesce))
{
Assert(hasVarArgument || hasBadCoalesce);
}
}
if (joinTree != NULL)
{
if (FindNodeCheck((Node *) joinTree->quals, CitusIsVolatileFunction))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"functions used in the WHERE clause of modification "
"queries on distributed tables must not be VOLATILE",
NULL, NULL);
}
else if (MasterIrreducibleExpression(joinTree->quals, &hasVarArgument,
&hasBadCoalesce))
{
Assert(hasVarArgument || hasBadCoalesce);
}
}
if (hasVarArgument)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"STABLE functions used in UPDATE queries "
"cannot be called with column references",
NULL, NULL);
}
if (hasBadCoalesce)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"non-IMMUTABLE functions are not allowed in CASE or "
"COALESCE statements",
NULL, NULL);
}
if (contain_mutable_functions((Node *) queryTree->returningList))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"non-IMMUTABLE functions are not allowed in the "
"RETURNING clause",
NULL, NULL);
}
if (queryTree->jointree->quals != NULL &&
nodeTag(queryTree->jointree->quals) == T_CurrentOfExpr)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"cannot run DML queries with cursors", NULL,
NULL);
}
}
deferredError = ErrorIfOnConflictNotSupported(queryTree);
if (deferredError != NULL)
{
return deferredError;
}
return NULL;
}
/*
* ModifyQuerySupported returns NULL if the query only contains supported
* features, otherwise it returns an error description.
* Note that we need both the original query and the modified one because
* different checks need different versions. In particular, we cannot
* perform the ContainsReadIntermediateResultFunction check on the
* rewritten query because it may have been replaced by a subplan,
* while some of the checks for setting the partition column value rely
* on the rewritten query.
*/
DeferredErrorMessage *
ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuery,
PlannerRestrictionContext *plannerRestrictionContext)
{
Oid distributedTableId = InvalidOid;
DeferredErrorMessage *error = ModifyPartialQuerySupported(queryTree, multiShardQuery,
&distributedTableId);
if (error)
{
return error;
}
List *rangeTableList = NIL;
uint32 queryTableCount = 0;
CmdType commandType = queryTree->commandType;
bool fastPathRouterQuery =
plannerRestrictionContext->fastPathRestrictionContext->fastPathRouterQuery;
/*
* Here, we check if a recursively planned query tries to modify
* rows based on the ctid column. This is a bad idea because ctid of
* the rows could be changed before the modification part of
* the query is executed.
*
* We can exclude fast path queries since they cannot have intermediate
* results by definition.
*/
if (!fastPathRouterQuery &&
ContainsReadIntermediateResultFunction((Node *) originalQuery))
{
bool hasTidColumn = FindNodeCheck((Node *) originalQuery->jointree, IsTidColumn);
if (hasTidColumn)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"cannot perform distributed planning for the given "
"modification",
"Recursively planned distributed modifications "
"with ctid on where clause are not supported.",
NULL);
}
}
/* /*
* Extract range table entries for queries that are not fast path. We can skip fast * Extract range table entries for queries that are not fast path. We can skip fast
@ -666,10 +828,9 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList); ExtractRangeTableEntryWalker((Node *) originalQuery, &rangeTableList);
} }
foreach(rangeTableCell, rangeTableList) RangeTblEntry *rangeTableEntry = NULL;
foreach_ptr(rangeTableEntry, rangeTableList)
{ {
RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell);
if (rangeTableEntry->rtekind == RTE_RELATION) if (rangeTableEntry->rtekind == RTE_RELATION)
{ {
/* we do not expect to see a view in modify query */ /* we do not expect to see a view in modify query */
@ -789,117 +950,6 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
} }
} }
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
commandType == CMD_DELETE)
{
bool hasVarArgument = false; /* A STABLE function is passed a Var argument */
bool hasBadCoalesce = false; /* CASE/COALESCE passed a mutable function */
FromExpr *joinTree = queryTree->jointree;
ListCell *targetEntryCell = NULL;
foreach(targetEntryCell, queryTree->targetList)
{
TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell);
bool targetEntryPartitionColumn = false;
/* reference tables do not have partition column */
if (partitionColumn == NULL)
{
targetEntryPartitionColumn = false;
}
else if (targetEntry->resno == partitionColumn->varattno)
{
targetEntryPartitionColumn = true;
}
/* skip resjunk entries: UPDATE adds some for ctid, etc. */
if (targetEntry->resjunk)
{
continue;
}
if (commandType == CMD_UPDATE &&
FindNodeCheck((Node *) targetEntry->expr, CitusIsVolatileFunction))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"functions used in UPDATE queries on distributed "
"tables must not be VOLATILE",
NULL, NULL);
}
if (commandType == CMD_UPDATE && targetEntryPartitionColumn &&
TargetEntryChangesValue(targetEntry, partitionColumn,
queryTree->jointree))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"modifying the partition value of rows is not "
"allowed",
NULL, NULL);
}
if (commandType == CMD_UPDATE &&
MasterIrreducibleExpression((Node *) targetEntry->expr,
&hasVarArgument, &hasBadCoalesce))
{
Assert(hasVarArgument || hasBadCoalesce);
}
}
if (joinTree != NULL)
{
if (FindNodeCheck((Node *) joinTree->quals, CitusIsVolatileFunction))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"functions used in the WHERE clause of modification "
"queries on distributed tables must not be VOLATILE",
NULL, NULL);
}
else if (MasterIrreducibleExpression(joinTree->quals, &hasVarArgument,
&hasBadCoalesce))
{
Assert(hasVarArgument || hasBadCoalesce);
}
}
if (hasVarArgument)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"STABLE functions used in UPDATE queries "
"cannot be called with column references",
NULL, NULL);
}
if (hasBadCoalesce)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"non-IMMUTABLE functions are not allowed in CASE or "
"COALESCE statements",
NULL, NULL);
}
if (contain_mutable_functions((Node *) queryTree->returningList))
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"non-IMMUTABLE functions are not allowed in the "
"RETURNING clause",
NULL, NULL);
}
if (queryTree->jointree->quals != NULL &&
nodeTag(queryTree->jointree->quals) == T_CurrentOfExpr)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"cannot run DML queries with cursors", NULL,
NULL);
}
}
deferredError = ErrorIfOnConflictNotSupported(queryTree);
if (deferredError != NULL)
{
return deferredError;
}
return NULL; return NULL;
} }
@ -1053,8 +1103,7 @@ MultiShardModifyQuerySupported(Query *originalQuery,
PlannerRestrictionContext *plannerRestrictionContext) PlannerRestrictionContext *plannerRestrictionContext)
{ {
DeferredErrorMessage *errorMessage = NULL; DeferredErrorMessage *errorMessage = NULL;
RangeTblEntry *resultRangeTable = rt_fetch(originalQuery->resultRelation, RangeTblEntry *resultRangeTable = ExtractResultRelationRTE(originalQuery);
originalQuery->rtable);
Oid resultRelationOid = resultRangeTable->relid; Oid resultRelationOid = resultRangeTable->relid;
char resultPartitionMethod = PartitionMethod(resultRelationOid); char resultPartitionMethod = PartitionMethod(resultRelationOid);
@ -1666,7 +1715,7 @@ GenerateSingleShardRouterTaskList(Job *job, List *relationShardList,
if (originalQuery->commandType == CMD_SELECT) if (originalQuery->commandType == CMD_SELECT)
{ {
job->taskList = SingleShardSelectTaskList(originalQuery, job->jobId, job->taskList = SingleShardTaskList(originalQuery, job->jobId,
relationShardList, placementList, relationShardList, placementList,
shardId, shardId,
job->parametersInJobQueryResolved); job->parametersInJobQueryResolved);
@ -1693,7 +1742,7 @@ GenerateSingleShardRouterTaskList(Job *job, List *relationShardList,
} }
else else
{ {
job->taskList = SingleShardModifyTaskList(originalQuery, job->jobId, job->taskList = SingleShardTaskList(originalQuery, job->jobId,
relationShardList, placementList, relationShardList, placementList,
shardId, shardId,
job->parametersInJobQueryResolved); job->parametersInJobQueryResolved);
@ -1783,15 +1832,65 @@ RemoveCoordinatorPlacement(List *placementList)
/* /*
* SingleShardSelectTaskList generates a task for single shard select query * SingleShardTaskList generates a task for single shard query
* and returns it as a list. * and returns it as a list.
*/ */
static List * static List *
SingleShardSelectTaskList(Query *query, uint64 jobId, List *relationShardList, SingleShardTaskList(Query *query, uint64 jobId, List *relationShardList,
List *placementList, uint64 shardId, List *placementList, uint64 shardId,
bool parametersInQueryResolved) bool parametersInQueryResolved)
{ {
Task *task = CreateTask(READ_TASK); TaskType taskType = READ_TASK;
char replicationModel = 0;
if (query->commandType != CMD_SELECT)
{
List *rangeTableList = NIL;
ExtractRangeTableEntryWalker((Node *) query, &rangeTableList);
RangeTblEntry *updateOrDeleteRTE = ExtractResultRelationRTE(query);
Assert(updateOrDeleteRTE != NULL);
CitusTableCacheEntry *modificationTableCacheEntry = GetCitusTableCacheEntry(
updateOrDeleteRTE->relid);
char modificationPartitionMethod = modificationTableCacheEntry->partitionMethod;
if (modificationPartitionMethod == DISTRIBUTE_BY_NONE &&
SelectsFromDistributedTable(rangeTableList, query))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot perform select on a distributed table "
"and modify a reference table")));
}
taskType = MODIFY_TASK;
replicationModel = modificationTableCacheEntry->replicationModel;
}
if (taskType == READ_TASK && query->hasModifyingCTE)
{
/* assume ErrorIfQueryHasUnroutableModifyingCTE checked query already */
CommonTableExpr *cte = NULL;
foreach_ptr(cte, query->cteList)
{
Query *cteQuery = (Query *) cte->ctequery;
if (cteQuery->commandType != CMD_SELECT)
{
RangeTblEntry *updateOrDeleteRTE = ExtractResultRelationRTE(cteQuery);
CitusTableCacheEntry *modificationTableCacheEntry =
GetCitusTableCacheEntry(
updateOrDeleteRTE->relid);
taskType = MODIFY_TASK;
replicationModel = modificationTableCacheEntry->replicationModel;
break;
}
}
}
Task *task = CreateTask(taskType);
List *relationRowLockList = NIL; List *relationRowLockList = NIL;
RowLocksOnRelations((Node *) query, &relationRowLockList); RowLocksOnRelations((Node *) query, &relationRowLockList);
@ -1807,6 +1906,7 @@ SingleShardSelectTaskList(Query *query, uint64 jobId, List *relationShardList,
task->jobId = jobId; task->jobId = jobId;
task->relationShardList = relationShardList; task->relationShardList = relationShardList;
task->relationRowLockList = relationRowLockList; task->relationRowLockList = relationRowLockList;
task->replicationModel = replicationModel;
task->parametersInQueryStringResolved = parametersInQueryResolved; task->parametersInQueryStringResolved = parametersInQueryResolved;
return list_make1(task); return list_make1(task);
@ -1854,45 +1954,6 @@ RowLocksOnRelations(Node *node, List **relationRowLockList)
} }
/*
* SingleShardModifyTaskList generates a task for single shard update/delete query
* and returns it as a list.
*/
static List *
SingleShardModifyTaskList(Query *query, uint64 jobId, List *relationShardList,
List *placementList, uint64 shardId,
bool parametersInQueryResolved)
{
Task *task = CreateTask(MODIFY_TASK);
List *rangeTableList = NIL;
ExtractRangeTableEntryWalker((Node *) query, &rangeTableList);
RangeTblEntry *updateOrDeleteRTE = ExtractResultRelationRTE(query);
CitusTableCacheEntry *modificationTableCacheEntry = GetCitusTableCacheEntry(
updateOrDeleteRTE->relid);
char modificationPartitionMethod = modificationTableCacheEntry->partitionMethod;
if (modificationPartitionMethod == DISTRIBUTE_BY_NONE &&
SelectsFromDistributedTable(rangeTableList, query))
{
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot perform select on a distributed table "
"and modify a reference table")));
}
task->taskPlacementList = placementList;
SetTaskQueryIfShouldLazyDeparse(task, query);
task->anchorShardId = shardId;
task->jobId = jobId;
task->relationShardList = relationShardList;
task->replicationModel = modificationTableCacheEntry->replicationModel;
task->parametersInQueryStringResolved = parametersInQueryResolved;
return list_make1(task);
}
/* /*
* SelectsFromDistributedTable checks if there is a select on a distributed * SelectsFromDistributedTable checks if there is a select on a distributed
* table by looking into range table entries. * table by looking into range table entries.
@ -1901,12 +1962,11 @@ static bool
SelectsFromDistributedTable(List *rangeTableList, Query *query) SelectsFromDistributedTable(List *rangeTableList, Query *query)
{ {
ListCell *rangeTableCell = NULL; ListCell *rangeTableCell = NULL;
int resultRelation = query->resultRelation;
RangeTblEntry *resultRangeTableEntry = NULL; RangeTblEntry *resultRangeTableEntry = NULL;
if (resultRelation > 0) if (query->resultRelation > 0)
{ {
resultRangeTableEntry = rt_fetch(resultRelation, query->rtable); resultRangeTableEntry = ExtractResultRelationRTE(query);
} }
foreach(rangeTableCell, rangeTableList) foreach(rangeTableCell, rangeTableList)
@ -3186,7 +3246,7 @@ MultiRouterPlannableQuery(Query *query)
} }
} }
return ErrorIfQueryHasModifyingCTE(query); return ErrorIfQueryHasUnroutableModifyingCTE(query);
} }
@ -3247,19 +3307,25 @@ CopyRelationRestrictionContext(RelationRestrictionContext *oldContext)
/* /*
* ErrorIfQueryHasModifyingCTE checks if the query contains modifying common table * ErrorIfQueryHasUnroutableModifyingCTE checks if the query contains modifying common table
* expressions and errors out if it does. * expressions and errors out if it does.
*/ */
static DeferredErrorMessage * static DeferredErrorMessage *
ErrorIfQueryHasModifyingCTE(Query *queryTree) ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree)
{ {
ListCell *cteCell = NULL;
Assert(queryTree->commandType == CMD_SELECT); Assert(queryTree->commandType == CMD_SELECT);
foreach(cteCell, queryTree->cteList) if (!queryTree->hasModifyingCTE)
{
return NULL;
}
/* we can't route conflicting replication models */
char replicationModel = 0;
CommonTableExpr *cte = NULL;
foreach_ptr(cte, queryTree->cteList)
{ {
CommonTableExpr *cte = (CommonTableExpr *) lfirst(cteCell);
Query *cteQuery = (Query *) cte->ctequery; Query *cteQuery = (Query *) cte->ctequery;
/* /*
@ -3268,13 +3334,48 @@ ErrorIfQueryHasModifyingCTE(Query *queryTree)
* be at top level of CTE. Therefore it is OK to just check for top level. * be at top level of CTE. Therefore it is OK to just check for top level.
* Similarly, we do not need to check for subqueries. * Similarly, we do not need to check for subqueries.
*/ */
if (cteQuery->commandType != CMD_SELECT) if (cteQuery->commandType != CMD_SELECT &&
cteQuery->commandType != CMD_UPDATE &&
cteQuery->commandType != CMD_DELETE)
{ {
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED, return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"data-modifying statements are not supported in " "only SELECT, UPDATE, or DELETE common table expressions "
"the WITH clauses of distributed queries", "may be router planned",
NULL, NULL); NULL, NULL);
} }
if (cteQuery->commandType != CMD_SELECT)
{
Oid distributedTableId = InvalidOid;
DeferredErrorMessage *cteError =
ModifyPartialQuerySupported(cteQuery, false, &distributedTableId);
if (cteError)
{
return cteError;
}
CitusTableCacheEntry *modificationTableCacheEntry =
GetCitusTableCacheEntry(distributedTableId);
char modificationPartitionMethod =
modificationTableCacheEntry->partitionMethod;
if (modificationPartitionMethod == DISTRIBUTE_BY_NONE)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"cannot router plan modification of a reference table",
NULL, NULL);
}
if (replicationModel &&
modificationTableCacheEntry->replicationModel != replicationModel)
{
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"cannot route mixed replication models",
NULL, NULL);
}
replicationModel = modificationTableCacheEntry->replicationModel;
}
} }
/* everything OK */ /* everything OK */

View File

@ -38,14 +38,14 @@ static bool ShouldEvaluateFunctionWithMasterContext(MasterEvaluationContext *
evaluationContext); evaluationContext);
/* /*
* RequiresMastereEvaluation returns the executor needs to reparse and * RequiresMasterEvaluation returns the executor needs to reparse and
* try to execute this query, which is the case if the query contains * try to execute this query, which is the case if the query contains
* any stable or volatile function. * any stable or volatile function.
*/ */
bool bool
RequiresMasterEvaluation(Query *query) RequiresMasterEvaluation(Query *query)
{ {
if (query->commandType == CMD_SELECT) if (query->commandType == CMD_SELECT && !query->hasModifyingCTE)
{ {
return false; return false;
} }
@ -55,32 +55,23 @@ RequiresMasterEvaluation(Query *query)
/* /*
* ExecuteMasterEvaluableFunctionsAndParameters evaluates expressions and parameters * ExecuteMasterEvaluableExpressions evaluates expressions and parameters
* that can be resolved to a constant. * that can be resolved to a constant.
*/ */
void void
ExecuteMasterEvaluableFunctionsAndParameters(Query *query, PlanState *planState) ExecuteMasterEvaluableExpressions(Query *query, PlanState *planState)
{ {
MasterEvaluationContext masterEvaluationContext; MasterEvaluationContext masterEvaluationContext;
masterEvaluationContext.planState = planState; masterEvaluationContext.planState = planState;
masterEvaluationContext.evaluationMode = EVALUATE_FUNCTIONS_PARAMS; if (query->commandType == CMD_SELECT)
PartiallyEvaluateExpression((Node *) query, &masterEvaluationContext);
}
/*
* ExecuteMasterEvaluableParameters evaluates external parameters that can be
* resolved to a constant.
*/
void
ExecuteMasterEvaluableParameters(Query *query, PlanState *planState)
{ {
MasterEvaluationContext masterEvaluationContext;
masterEvaluationContext.planState = planState;
masterEvaluationContext.evaluationMode = EVALUATE_PARAMS; masterEvaluationContext.evaluationMode = EVALUATE_PARAMS;
}
else
{
masterEvaluationContext.evaluationMode = EVALUATE_FUNCTIONS_PARAMS;
}
PartiallyEvaluateExpression((Node *) query, &masterEvaluationContext); PartiallyEvaluateExpression((Node *) query, &masterEvaluationContext);
} }
@ -146,9 +137,22 @@ PartiallyEvaluateExpression(Node *expression,
} }
else if (nodeTag == T_Query) else if (nodeTag == T_Query)
{ {
return (Node *) query_tree_mutator((Query *) expression, Query *query = (Query *) expression;
MasterEvaluationContext subContext = *masterEvaluationContext;
if (query->commandType != CMD_SELECT)
{
/*
* Currently INSERT SELECT evaluates stable functions on master,
* while a plain SELECT does not. For evaluating SELECT evaluationMode is
* EVALUATE_PARAMS, but if recursing into a modifying CTE switch into
* EVALUATE_FUNCTIONS_PARAMS.
*/
subContext.evaluationMode = EVALUATE_FUNCTIONS_PARAMS;
}
return (Node *) query_tree_mutator(query,
PartiallyEvaluateExpression, PartiallyEvaluateExpression,
masterEvaluationContext, &subContext,
QTW_DONT_COPY_QUERY); QTW_DONT_COPY_QUERY);
} }
else else
@ -359,6 +363,8 @@ citus_evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod,
resultTypByVal); resultTypByVal);
} }
/* *INDENT-ON* */
/* /*
* CitusIsVolatileFunctionIdChecker checks if the given function id is * CitusIsVolatileFunctionIdChecker checks if the given function id is
@ -446,6 +452,3 @@ CitusIsMutableFunction(Node *node)
return false; return false;
} }
/* *INDENT-ON* */

View File

@ -44,9 +44,7 @@ typedef struct MasterEvaluationContext
extern bool RequiresMasterEvaluation(Query *query); extern bool RequiresMasterEvaluation(Query *query);
extern void ExecuteMasterEvaluableFunctionsAndParameters(Query *query, extern void ExecuteMasterEvaluableExpressions(Query *query, PlanState *planState);
PlanState *planState);
extern void ExecuteMasterEvaluableParameters(Query *query, PlanState *planState);
extern Node * PartiallyEvaluateExpression(Node *expression, extern Node * PartiallyEvaluateExpression(Node *expression,
MasterEvaluationContext *masterEvaluationContext); MasterEvaluationContext *masterEvaluationContext);
extern bool CitusIsVolatileFunction(Node *node); extern bool CitusIsVolatileFunction(Node *node);

View File

@ -123,7 +123,7 @@ extern uint64 ExecuteTaskListExtended(ExecutionParams *executionParams);
extern uint64 ExecuteTaskListIntoTupleStore(RowModifyLevel modLevel, List *taskList, extern uint64 ExecuteTaskListIntoTupleStore(RowModifyLevel modLevel, List *taskList,
TupleDesc tupleDescriptor, TupleDesc tupleDescriptor,
Tuplestorestate *tupleStore, Tuplestorestate *tupleStore,
bool hasReturning); bool expectResults);
extern bool IsCitusCustomState(PlanState *planState); extern bool IsCitusCustomState(PlanState *planState);
extern TupleTableSlot * CitusExecScan(CustomScanState *node); extern TupleTableSlot * CitusExecScan(CustomScanState *node);
extern TupleTableSlot * ReturnTupleFromTuplestore(CitusScanState *scanState); extern TupleTableSlot * ReturnTupleFromTuplestore(CitusScanState *scanState);

View File

@ -193,6 +193,8 @@ extern bool TargetListOnPartitionColumn(Query *query, List *targetEntryList);
extern bool FindNodeCheckInRangeTableList(List *rtable, bool (*check)(Node *)); extern bool FindNodeCheckInRangeTableList(List *rtable, bool (*check)(Node *));
extern bool IsCitusTableRTE(Node *node); extern bool IsCitusTableRTE(Node *node);
extern bool IsDistributedTableRTE(Node *node); extern bool IsDistributedTableRTE(Node *node);
extern bool IsReferenceTableRTE(Node *node);
extern bool QueryContainsDistributedTableRTE(Query *query);
extern bool IsCitusExtraDataContainerRelation(RangeTblEntry *rte); extern bool IsCitusExtraDataContainerRelation(RangeTblEntry *rte);
extern bool ContainsReadIntermediateResultFunction(Node *node); extern bool ContainsReadIntermediateResultFunction(Node *node);
extern bool ContainsReadIntermediateResultArrayFunction(Node *node); extern bool ContainsReadIntermediateResultArrayFunction(Node *node);

View File

@ -60,6 +60,9 @@ s/(job_[0-9]+\/task_[0-9]+\/p_[0-9]+\.)[0-9]+/\1xxxx/g
# isolation_ref2ref_foreign_keys # isolation_ref2ref_foreign_keys
s/"(ref_table_[0-9]_|ref_table_[0-9]_value_fkey_)[0-9]+"/"\1xxxxxxx"/g s/"(ref_table_[0-9]_|ref_table_[0-9]_value_fkey_)[0-9]+"/"\1xxxxxxx"/g
# pg11/pg12 varies in isolation debug output
s/s1: DEBUG:/DEBUG:/g
# commands cascading to shard relations # commands cascading to shard relations
s/(NOTICE: .*_)[0-9]{5,}( CASCADE)/\1xxxxx\2/g s/(NOTICE: .*_)[0-9]{5,}( CASCADE)/\1xxxxx\2/g
s/(NOTICE: [a-z]+ cascades to table ".*)_[0-9]{5,}"/\1_xxxxx"/g s/(NOTICE: [a-z]+ cascades to table ".*)_[0-9]{5,}"/\1_xxxxx"/g

View File

@ -924,7 +924,7 @@ DEBUG: Plan is router executable
-- we don't inline CTEs if they are modifying CTEs -- we don't inline CTEs if they are modifying CTEs
WITH cte_1 AS (DELETE FROM test_table WHERE key % 3 = 1 RETURNING key) WITH cte_1 AS (DELETE FROM test_table WHERE key % 3 = 1 RETURNING key)
SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3; SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE cte_1: DELETE FROM cte_inline.test_table WHERE ((key OPERATOR(pg_catalog.%) 3) OPERATOR(pg_catalog.=) 1) RETURNING key DEBUG: generating subplan XXX_1 for CTE cte_1: DELETE FROM cte_inline.test_table WHERE ((key OPERATOR(pg_catalog.%) 3) OPERATOR(pg_catalog.=) 1) RETURNING key
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -941,7 +941,7 @@ DEBUG: Plan is router executable
-- NOT MATERIALIZED should not affect modifying CTEs -- NOT MATERIALIZED should not affect modifying CTEs
WITH cte_1 AS NOT MATERIALIZED (DELETE FROM test_table WHERE key % 3 = 0 RETURNING key) WITH cte_1 AS NOT MATERIALIZED (DELETE FROM test_table WHERE key % 3 = 0 RETURNING key)
SELECT count(*) FROM cte_1; SELECT count(*) FROM cte_1;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE cte_1: DELETE FROM cte_inline.test_table WHERE ((key OPERATOR(pg_catalog.%) 3) OPERATOR(pg_catalog.=) 0) RETURNING key DEBUG: generating subplan XXX_1 for CTE cte_1: DELETE FROM cte_inline.test_table WHERE ((key OPERATOR(pg_catalog.%) 3) OPERATOR(pg_catalog.=) 0) RETURNING key
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable

View File

@ -801,7 +801,7 @@ ERROR: syntax error at or near "NOT"
-- we don't inline CTEs if they are modifying CTEs -- we don't inline CTEs if they are modifying CTEs
WITH cte_1 AS (DELETE FROM test_table WHERE key % 3 = 1 RETURNING key) WITH cte_1 AS (DELETE FROM test_table WHERE key % 3 = 1 RETURNING key)
SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3; SELECT * FROM cte_1 ORDER BY 1 DESC LIMIT 3;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE cte_1: DELETE FROM cte_inline.test_table WHERE ((key OPERATOR(pg_catalog.%) 3) OPERATOR(pg_catalog.=) 1) RETURNING key DEBUG: generating subplan XXX_1 for CTE cte_1: DELETE FROM cte_inline.test_table WHERE ((key OPERATOR(pg_catalog.%) 3) OPERATOR(pg_catalog.=) 1) RETURNING key
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable

View File

@ -146,7 +146,7 @@ ERROR: non-IMMUTABLE functions are not allowed in the RETURNING clause
-- modifying ctes are not supported via fast-path -- modifying ctes are not supported via fast-path
WITH t1 AS (DELETE FROM modify_fast_path WHERE key = 1), t2 AS (SELECT * FROM modify_fast_path) SELECT * FROM t2; WITH t1 AS (DELETE FROM modify_fast_path WHERE key = 1), t2 AS (SELECT * FROM modify_fast_path) SELECT * FROM t2;
DEBUG: CTE t2 is going to be inlined via distributed planning DEBUG: CTE t2 is going to be inlined via distributed planning
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE t1: DELETE FROM fast_path_router_modify.modify_fast_path WHERE (key OPERATOR(pg_catalog.=) 1) DEBUG: generating subplan XXX_1 for CTE t1: DELETE FROM fast_path_router_modify.modify_fast_path WHERE (key OPERATOR(pg_catalog.=) 1)
DEBUG: Distributed planning for a fast-path router query DEBUG: Distributed planning for a fast-path router query
DEBUG: Creating router plan DEBUG: Creating router plan

View File

@ -920,6 +920,48 @@ BEGIN;
ERROR: cannot execute DML on reference table "transitive_reference_table" because there was a parallel DML access to distributed table "on_update_fkey_table" in the same transaction ERROR: cannot execute DML on reference table "transitive_reference_table" because there was a parallel DML access to distributed table "on_update_fkey_table" in the same transaction
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';" HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
ROLLBACK; ROLLBACK;
BEGIN;
WITH cte AS (UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15 RETURNING *)
SELECT * FROM cte;
id | value_1
---------------------------------------------------------------------
15 | 16
115 | 16
215 | 16
315 | 16
415 | 16
515 | 16
615 | 16
715 | 16
815 | 16
915 | 16
(10 rows)
UPDATE reference_table SET id = 160 WHERE id = 15;
ERROR: cannot execute DML on reference table "reference_table" because there was a parallel DML access to distributed table "on_update_fkey_table" in the same transaction
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
ROLLBACK;
BEGIN;
WITH cte AS (UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15 RETURNING *)
SELECT * FROM cte;
id | value_1
---------------------------------------------------------------------
15 | 16
115 | 16
215 | 16
315 | 16
415 | 16
515 | 16
615 | 16
715 | 16
815 | 16
915 | 16
(10 rows)
UPDATE transitive_reference_table SET id = 160 WHERE id = 15;
ERROR: cannot execute DML on reference table "transitive_reference_table" because there was a parallel DML access to distributed table "on_update_fkey_table" in the same transaction
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
ROLLBACK;
-- case 5.3: Parallel UPDATE on distributed table follow by an unrelated DDL on reference table -- case 5.3: Parallel UPDATE on distributed table follow by an unrelated DDL on reference table
BEGIN; BEGIN;
UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15; UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15;

View File

@ -670,7 +670,7 @@ WITH r AS (
) )
INSERT INTO target_table SELECT source_table.a, max(source_table.b) FROM source_table NATURAL JOIN r GROUP BY source_table.a; INSERT INTO target_table SELECT source_table.a, max(source_table.b) FROM source_table NATURAL JOIN r GROUP BY source_table.a;
DEBUG: INSERT target table and the source relation of the SELECT partition column value must be colocated in distributed INSERT ... SELECT DEBUG: INSERT target table and the source relation of the SELECT partition column value must be colocated in distributed INSERT ... SELECT
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: only SELECT, UPDATE, or DELETE common table expressions may be router planned
DEBUG: generating subplan XXX_1 for CTE r: INSERT INTO insert_select_repartition.target_table (a, b) SELECT a, b FROM insert_select_repartition.source_table RETURNING target_table.a, target_table.b DEBUG: generating subplan XXX_1 for CTE r: INSERT INTO insert_select_repartition.target_table (a, b) SELECT a, b FROM insert_select_repartition.source_table RETURNING target_table.a, target_table.b
DEBUG: INSERT target table and the source relation of the SELECT partition column value must be colocated in distributed INSERT ... SELECT DEBUG: INSERT target table and the source relation of the SELECT partition column value must be colocated in distributed INSERT ... SELECT
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, max AS b FROM (SELECT source_table.a, max(source_table.b) AS max FROM (insert_select_repartition.source_table JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) r USING (a, b)) GROUP BY source_table.a) citus_insert_select_subquery DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT a, max AS b FROM (SELECT source_table.a, max(source_table.b) AS max FROM (insert_select_repartition.source_table JOIN (SELECT intermediate_result.a, intermediate_result.b FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a integer, b integer)) r USING (a, b)) GROUP BY source_table.a) citus_insert_select_subquery

View File

@ -237,7 +237,7 @@ step s1-begin:
step s1-select-from-t1-within-cte: step s1-select-from-t1-within-cte:
WITH first_value AS (SELECT val_1 FROM test_table_1_rf1 WHERE id = 1 FOR UPDATE) WITH first_value AS (SELECT val_1 FROM test_table_1_rf1 WHERE id = 1 FOR UPDATE)
SELECT * FROM first_value; SELECT * FROM first_value WHERE EXISTS (SELECT * FROM first_value);
val_1 val_1
@ -272,7 +272,7 @@ step s1-begin:
step s1-select-from-t1-within-cte: step s1-select-from-t1-within-cte:
WITH first_value AS (SELECT val_1 FROM test_table_1_rf1 WHERE id = 1 FOR UPDATE) WITH first_value AS (SELECT val_1 FROM test_table_1_rf1 WHERE id = 1 FOR UPDATE)
SELECT * FROM first_value; SELECT * FROM first_value WHERE EXISTS (SELECT * FROM first_value);
val_1 val_1
@ -298,9 +298,14 @@ starting permutation: s1-begin s1-select-from-t1-with-subquery s2-begin s2-updat
step s1-begin: step s1-begin:
BEGIN; BEGIN;
DEBUG: Creating router plan
step s1-select-from-t1-with-subquery: step s1-select-from-t1-with-subquery:
SET client_min_messages TO DEBUG2;
SELECT * FROM (SELECT * FROM test_table_1_rf1 FOR UPDATE) foo WHERE id = 1; SELECT * FROM (SELECT * FROM test_table_1_rf1 FOR UPDATE) foo WHERE id = 1;
RESET client_min_messages;
DEBUG: Plan is router executable
DETAIL: distribution column value: 1
id val_1 id val_1
1 2 1 2
@ -381,7 +386,7 @@ step s1-begin:
step s1-update-rt-with-cte-select-from-rt: step s1-update-rt-with-cte-select-from-rt:
WITH foo AS (SELECT * FROM ref_table FOR UPDATE) WITH foo AS (SELECT * FROM ref_table FOR UPDATE)
UPDATE ref_table SET val_1 = 4 FROM foo WHERE ref_table.id = foo.id; UPDATE ref_table SET val_1 = 4 FROM foo WHERE ref_table.id = foo.id AND EXISTS (SELECT * FROM foo);
step s2-begin: step s2-begin:
BEGIN; BEGIN;

View File

@ -20,6 +20,32 @@ restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
4 l
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update s2-delete s1-commit s2-commit s1-select-count starting permutation: s1-initialize s1-begin s2-begin s1-update s2-delete s1-commit s2-commit s1-select-count
create_distributed_table create_distributed_table
@ -295,6 +321,289 @@ restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-delete s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-delete: DELETE FROM update_hash WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-delete: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
4
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-truncate s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-truncate: TRUNCATE update_hash; <waiting ...>
step s1-commit: COMMIT;
step s2-truncate: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
0
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-drop s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-drop: DROP TABLE update_hash; <waiting ...>
step s1-commit: COMMIT;
step s2-drop: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
ERROR: relation "update_hash" does not exist
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-ddl-create-index s1-commit s2-commit s1-select-count s1-show-indexes
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-ddl-create-index: CREATE INDEX update_hash_index ON update_hash(id); <waiting ...>
step s1-commit: COMMIT;
step s2-ddl-create-index: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''update_hash%''');
run_command_on_workers
(localhost,57637,t,2)
(localhost,57638,t,2)
restore_isolation_tester_func
starting permutation: s1-initialize s1-ddl-create-index s1-begin s2-begin s1-update-cte s2-ddl-drop-index s1-commit s2-commit s1-select-count s1-show-indexes
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-ddl-create-index: CREATE INDEX update_hash_index ON update_hash(id);
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-ddl-drop-index: DROP INDEX update_hash_index; <waiting ...>
step s1-commit: COMMIT;
step s2-ddl-drop-index: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''update_hash%''');
run_command_on_workers
(localhost,57637,t,0)
(localhost,57638,t,0)
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s1-update-cte s2-ddl-create-index-concurrently s1-commit s1-select-count s1-show-indexes
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-ddl-create-index-concurrently: CREATE INDEX CONCURRENTLY update_hash_index ON update_hash(id); <waiting ...>
step s1-commit: COMMIT;
step s2-ddl-create-index-concurrently: <... completed>
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''update_hash%''');
run_command_on_workers
(localhost,57637,t,2)
(localhost,57638,t,2)
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-ddl-add-column s1-commit s2-commit s1-select-count s1-show-columns
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-ddl-add-column: ALTER TABLE update_hash ADD new_column int DEFAULT 0; <waiting ...>
step s1-commit: COMMIT;
step s2-ddl-add-column: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''update_hash%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
run_command_on_workers
(localhost,57637,t,new_column)
(localhost,57638,t,new_column)
restore_isolation_tester_func
starting permutation: s1-initialize s1-ddl-add-column s1-begin s2-begin s1-update-cte s2-ddl-drop-column s1-commit s2-commit s1-select-count s1-show-columns
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-ddl-add-column: ALTER TABLE update_hash ADD new_column int DEFAULT 0;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data new_column
4 l 0
step s2-ddl-drop-column: ALTER TABLE update_hash DROP new_column; <waiting ...>
step s1-commit: COMMIT;
step s2-ddl-drop-column: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''update_hash%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
run_command_on_workers
(localhost,57637,t,"")
(localhost,57638,t,"")
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-ddl-rename-column s1-commit s2-commit s1-select-count s1-show-columns
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-ddl-rename-column: ALTER TABLE update_hash RENAME data TO new_column; <waiting ...>
step s1-commit: COMMIT;
step s2-ddl-rename-column: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''update_hash%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
run_command_on_workers
(localhost,57637,t,new_column)
(localhost,57638,t,new_column)
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-table-size s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-table-size: SELECT citus_total_relation_size('update_hash');
citus_total_relation_size
57344
step s1-commit: COMMIT;
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-update-cte s2-master-modify-multiple-shards s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s2-master-modify-multiple-shards: DELETE FROM update_hash; <waiting ...>
step s1-commit: COMMIT;
step s2-master-modify-multiple-shards: <... completed>
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
0
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-delete s2-update s1-commit s2-commit s1-select-count starting permutation: s1-initialize s1-begin s2-begin s1-delete s2-update s1-commit s2-commit s1-select-count
create_distributed_table create_distributed_table
@ -548,3 +857,282 @@ count
restore_isolation_tester_func restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-delete s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-delete: DELETE FROM update_hash WHERE id = 4;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
4
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-truncate s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-truncate: TRUNCATE update_hash;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
0
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-drop s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-drop: DROP TABLE update_hash;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
error in steps s1-commit s2-update-cte: ERROR: relation "update_hash" does not exist
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
ERROR: relation "update_hash" does not exist
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-ddl-create-index s2-update-cte s1-commit s2-commit s1-select-count s1-show-indexes
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-ddl-create-index: CREATE INDEX update_hash_index ON update_hash(id);
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
4 l
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''update_hash%''');
run_command_on_workers
(localhost,57637,t,2)
(localhost,57638,t,2)
restore_isolation_tester_func
starting permutation: s1-initialize s1-ddl-create-index s1-begin s2-begin s1-ddl-drop-index s2-update-cte s1-commit s2-commit s1-select-count s1-show-indexes
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-ddl-create-index: CREATE INDEX update_hash_index ON update_hash(id);
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-ddl-drop-index: DROP INDEX update_hash_index;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
4 l
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-indexes: SELECT run_command_on_workers('SELECT COUNT(*) FROM pg_indexes WHERE tablename LIKE ''update_hash%''');
run_command_on_workers
(localhost,57637,t,0)
(localhost,57638,t,0)
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-ddl-add-column s2-update-cte s1-commit s2-commit s1-select-count s1-show-columns
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-ddl-add-column: ALTER TABLE update_hash ADD new_column int DEFAULT 0;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data new_column
4 l 0
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''update_hash%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
run_command_on_workers
(localhost,57637,t,new_column)
(localhost,57638,t,new_column)
restore_isolation_tester_func
starting permutation: s1-initialize s1-ddl-add-column s1-begin s2-begin s1-ddl-drop-column s2-update-cte s1-commit s2-commit s1-select-count s1-show-columns
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-ddl-add-column: ALTER TABLE update_hash ADD new_column int DEFAULT 0;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-ddl-drop-column: ALTER TABLE update_hash DROP new_column;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
4 l
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''update_hash%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
run_command_on_workers
(localhost,57637,t,"")
(localhost,57638,t,"")
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-ddl-rename-column s2-update-cte s1-commit s2-commit s1-select-count s1-show-columns
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-ddl-rename-column: ALTER TABLE update_hash RENAME data TO new_column;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
error in steps s1-commit s2-update-cte: ERROR: column "data" of relation "update_hash" does not exist
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
step s1-show-columns: SELECT run_command_on_workers('SELECT column_name FROM information_schema.columns WHERE table_name LIKE ''update_hash%'' AND column_name = ''new_column'' ORDER BY 1 LIMIT 1');
run_command_on_workers
(localhost,57637,t,new_column)
(localhost,57638,t,new_column)
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-table-size s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-table-size: SELECT citus_total_relation_size('update_hash');
citus_total_relation_size
57344
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4;
id data
4 l
step s1-commit: COMMIT;
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
5
restore_isolation_tester_func
starting permutation: s1-initialize s1-begin s2-begin s1-master-modify-multiple-shards s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-master-modify-multiple-shards: DELETE FROM update_hash;
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
0
restore_isolation_tester_func
starting permutation: s1-drop s1-create-non-distributed-table s1-initialize s1-begin s2-begin s1-distribute-table s2-update-cte s1-commit s2-commit s1-select-count
create_distributed_table
step s1-drop: DROP TABLE update_hash;
step s1-create-non-distributed-table: CREATE TABLE update_hash(id integer, data text); COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-initialize: COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV;
step s1-begin: BEGIN;
step s2-begin: BEGIN;
step s1-distribute-table: SELECT create_distributed_table('update_hash', 'id');
create_distributed_table
step s2-update-cte: WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; <waiting ...>
step s1-commit: COMMIT;
step s2-update-cte: <... completed>
id data
4 l
4 l
step s2-commit: COMMIT;
step s1-select-count: SELECT COUNT(*) FROM update_hash;
count
10
restore_isolation_tester_func

View File

@ -314,6 +314,44 @@ DETAIL: distribution column value: 1
41 41
(5 rows) (5 rows)
-- SELECT FOR UPDATE is supported if not involving reference table
BEGIN;
WITH first_author AS (
SELECT articles_hash.id, auref.name FROM articles_hash, authors_reference auref
WHERE author_id = 2 AND auref.id = author_id
FOR UPDATE
)
UPDATE articles_hash SET title = first_author.name
FROM first_author WHERE articles_hash.author_id = 2 AND articles_hash.id = first_author.id;
DEBUG: Router planner doesn't support SELECT FOR UPDATE in common table expressions involving reference tables.
DEBUG: generating subplan XXX_1 for CTE first_author: SELECT articles_hash.id, auref.name FROM public.articles_hash, public.authors_reference auref WHERE ((articles_hash.author_id OPERATOR(pg_catalog.=) 2) AND (auref.id OPERATOR(pg_catalog.=) articles_hash.author_id)) FOR UPDATE OF articles_hash FOR UPDATE OF auref
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 2
DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE public.articles_hash SET title = first_author.name FROM (SELECT intermediate_result.id, intermediate_result.name FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(id bigint, name character varying(20))) first_author WHERE ((articles_hash.author_id OPERATOR(pg_catalog.=) 2) AND (articles_hash.id OPERATOR(pg_catalog.=) first_author.id))
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 2
WITH first_author AS (
SELECT id, word_count FROM articles_hash WHERE author_id = 2
FOR UPDATE
)
UPDATE articles_hash SET title = first_author.word_count::text
FROM first_author WHERE articles_hash.author_id = 2 AND articles_hash.id = first_author.id;
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 2
-- Without FOR UPDATE this is router plannable
WITH first_author AS (
SELECT articles_hash.id, auref.name FROM articles_hash, authors_reference auref
WHERE author_id = 2 AND auref.id = author_id
)
UPDATE articles_hash SET title = first_author.name
FROM first_author WHERE articles_hash.author_id = 2 AND articles_hash.id = first_author.id;
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 2
ROLLBACK;
-- queries with CTEs are supported even if CTE is not referenced inside query -- queries with CTEs are supported even if CTE is not referenced inside query
WITH first_author AS ( SELECT id FROM articles_hash WHERE author_id = 1) WITH first_author AS ( SELECT id FROM articles_hash WHERE author_id = 1)
SELECT title FROM articles_hash WHERE author_id = 1; SELECT title FROM articles_hash WHERE author_id = 1;
@ -476,7 +514,7 @@ WITH new_article AS (
INSERT INTO articles_hash VALUES (1, 1, 'arsenous', 9) RETURNING * INSERT INTO articles_hash VALUES (1, 1, 'arsenous', 9) RETURNING *
) )
SELECT * FROM new_article; SELECT * FROM new_article;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: only SELECT, UPDATE, or DELETE common table expressions may be router planned
DEBUG: generating subplan XXX_1 for CTE new_article: INSERT INTO public.articles_hash (id, author_id, title, word_count) VALUES (1, 1, 'arsenous'::character varying, 9) RETURNING id, author_id, title, word_count DEBUG: generating subplan XXX_1 for CTE new_article: INSERT INTO public.articles_hash (id, author_id, title, word_count) VALUES (1, 1, 'arsenous'::character varying, 9) RETURNING id, author_id, title, word_count
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -493,7 +531,7 @@ WITH update_article AS (
UPDATE articles_hash SET word_count = 10 WHERE id = 1 AND word_count = 9 RETURNING * UPDATE articles_hash SET word_count = 10 WHERE id = 1 AND word_count = 9 RETURNING *
) )
SELECT * FROM update_article; SELECT * FROM update_article;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE update_article: UPDATE public.articles_hash SET word_count = 10 WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 9)) RETURNING id, author_id, title, word_count DEBUG: generating subplan XXX_1 for CTE update_article: UPDATE public.articles_hash SET word_count = 10 WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 9)) RETURNING id, author_id, title, word_count
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -509,7 +547,7 @@ WITH delete_article AS (
DELETE FROM articles_hash WHERE id = 1 AND word_count = 10 RETURNING * DELETE FROM articles_hash WHERE id = 1 AND word_count = 10 RETURNING *
) )
SELECT * FROM delete_article; SELECT * FROM delete_article;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE delete_article: DELETE FROM public.articles_hash WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 10)) RETURNING id, author_id, title, word_count DEBUG: generating subplan XXX_1 for CTE delete_article: DELETE FROM public.articles_hash WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 10)) RETURNING id, author_id, title, word_count
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -2241,7 +2279,8 @@ DEBUG: Router planner cannot handle multi-shard select queries
PREPARE author_1_articles as PREPARE author_1_articles as
SELECT * SELECT *
FROM articles_hash FROM articles_hash
WHERE author_id = 1; WHERE author_id = 1
ORDER BY 1;
EXECUTE author_1_articles; EXECUTE author_1_articles;
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -2259,7 +2298,8 @@ DETAIL: distribution column value: 1
PREPARE author_articles(int) as PREPARE author_articles(int) as
SELECT * SELECT *
FROM articles_hash FROM articles_hash
WHERE author_id = $1; WHERE author_id = $1
ORDER BY 1;
EXECUTE author_articles(1); EXECUTE author_articles(1);
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -2310,7 +2350,7 @@ BEGIN
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
SELECT * FROM author_articles_id_word_count(); SELECT * FROM author_articles_id_word_count() ORDER BY 1;
DEBUG: Creating router plan DEBUG: Creating router plan
CONTEXT: SQL statement "SELECT ah.id, ah.word_count CONTEXT: SQL statement "SELECT ah.id, ah.word_count
FROM articles_hash ah FROM articles_hash ah
@ -2369,7 +2409,8 @@ SELECT * FROM mv_articles_hash_data ORDER BY 1, 2, 3, 4;
SET citus.task_executor_type to 'task-tracker'; SET citus.task_executor_type to 'task-tracker';
SELECT id SELECT id
FROM articles_hash FROM articles_hash
WHERE author_id = 1; WHERE author_id = 1
ORDER BY 1;
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
DETAIL: distribution column value: 1 DETAIL: distribution column value: 1
@ -2390,7 +2431,8 @@ DETAIL: distribution column value: 1
-- verify insert is successful (not router plannable and executable) -- verify insert is successful (not router plannable and executable)
SELECT id SELECT id
FROM articles_hash FROM articles_hash
WHERE author_id = 1; WHERE author_id = 1
ORDER BY 1;
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
DETAIL: distribution column value: 1 DETAIL: distribution column value: 1

View File

@ -319,7 +319,7 @@ WITH update_article AS (
UPDATE articles_hash SET word_count = 10 WHERE id = 1 AND word_count = 9 RETURNING * UPDATE articles_hash SET word_count = 10 WHERE id = 1 AND word_count = 9 RETURNING *
) )
SELECT * FROM update_article; SELECT * FROM update_article;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE update_article: UPDATE fast_path_router_select.articles_hash SET word_count = 10 WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 9)) RETURNING id, author_id, title, word_count DEBUG: generating subplan XXX_1 for CTE update_article: UPDATE fast_path_router_select.articles_hash SET word_count = 10 WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 9)) RETURNING id, author_id, title, word_count
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable
@ -334,7 +334,7 @@ WITH delete_article AS (
DELETE FROM articles_hash WHERE id = 1 AND word_count = 10 RETURNING * DELETE FROM articles_hash WHERE id = 1 AND word_count = 10 RETURNING *
) )
SELECT * FROM delete_article; SELECT * FROM delete_article;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: generating subplan XXX_1 for CTE delete_article: DELETE FROM fast_path_router_select.articles_hash WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 10)) RETURNING id, author_id, title, word_count DEBUG: generating subplan XXX_1 for CTE delete_article: DELETE FROM fast_path_router_select.articles_hash WHERE ((id OPERATOR(pg_catalog.=) 1) AND (word_count OPERATOR(pg_catalog.=) 10)) RETURNING id, author_id, title, word_count
DEBUG: Creating router plan DEBUG: Creating router plan
DEBUG: Plan is router executable DEBUG: Plan is router executable

View File

@ -44,7 +44,7 @@ BEGIN
END IF; END IF;
END; END;
$$ LANGUAGE 'plpgsql' IMMUTABLE; $$ LANGUAGE 'plpgsql' IMMUTABLE;
CREATE VIEW relation_acesses AS CREATE VIEW relation_accesses AS
SELECT table_name, SELECT table_name,
relation_access_mode_to_text(table_name, relation_select_access_mode(table_name::regclass)) as select_access, relation_access_mode_to_text(table_name, relation_select_access_mode(table_name::regclass)) as select_access,
relation_access_mode_to_text(table_name, relation_dml_access_mode(table_name::regclass)) as dml_access, relation_access_mode_to_text(table_name, relation_dml_access_mode(table_name::regclass)) as dml_access,
@ -109,21 +109,21 @@ BEGIN;
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_7') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_7') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_7 | not_parallel_accessed | not_parallel_accessed | parallel_access table_7 | not_parallel_accessed | not_parallel_accessed | parallel_access
(1 row) (1 row)
COMMIT; COMMIT;
-- outisde the transaction blocks, the function always returns zero -- outside the transaction blocks, the function always returns zero
SELECT count(*) FROM table_1; SELECT count(*) FROM table_1;
count count
--------------------------------------------------------------------- ---------------------------------------------------------------------
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -132,7 +132,7 @@ SELECT * FROM relation_acesses WHERE table_name = 'table_1';
-- a very simple test that first checks sequential -- a very simple test that first checks sequential
-- and parallel SELECTs,DMLs, and DDLs -- and parallel SELECTs,DMLs, and DDLs
BEGIN; BEGIN;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -144,7 +144,7 @@ BEGIN;
1 1
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -156,21 +156,21 @@ BEGIN;
2 2
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
(1 row) (1 row)
INSERT INTO table_1 VALUES (1,1); INSERT INTO table_1 VALUES (1,1);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
(1 row) (1 row)
INSERT INTO table_1 VALUES (1,1), (2,2); INSERT INTO table_1 VALUES (1,1), (2,2);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -178,7 +178,7 @@ BEGIN;
ALTER TABLE table_1 ADD COLUMN test_col INT; ALTER TABLE table_1 ADD COLUMN test_col INT;
-- now see that the other tables are not accessed at all -- now see that the other tables are not accessed at all
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | parallel_access table_1 | parallel_access | not_parallel_accessed | parallel_access
@ -194,7 +194,7 @@ BEGIN;
1 1
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -206,21 +206,21 @@ BEGIN;
1 1
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
(1 row) (1 row)
INSERT INTO table_1 VALUES (1,1); INSERT INTO table_1 VALUES (1,1);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
(1 row) (1 row)
INSERT INTO table_1 VALUES (2,2); INSERT INTO table_1 VALUES (2,2);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -230,7 +230,7 @@ ROLLBACK;
-- a sample DDL example -- a sample DDL example
BEGIN; BEGIN;
ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -252,7 +252,7 @@ BEGIN;
1 1
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name LIKE 'table_%' ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name LIKE 'table_%' ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -278,7 +278,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -301,7 +301,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -328,7 +328,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name LIKE 'table_%' ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name LIKE 'table_%' ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -346,7 +346,7 @@ ROLLBACK;
-- access for all the shards accessed. But, sequential mode is OK -- access for all the shards accessed. But, sequential mode is OK
BEGIN; BEGIN;
UPDATE table_1 SET value = 15; UPDATE table_1 SET value = 15;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | parallel_access | not_parallel_accessed table_1 | parallel_access | parallel_access | not_parallel_accessed
@ -354,7 +354,7 @@ BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
UPDATE table_2 SET value = 15; UPDATE table_2 SET value = 15;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | parallel_access | not_parallel_accessed table_1 | parallel_access | parallel_access | not_parallel_accessed
@ -367,7 +367,7 @@ BEGIN;
UPDATE UPDATE
table_1 SET value = 15 table_1 SET value = 15
WHERE key IN (SELECT key FROM table_2 JOIN table_3 USING (key) WHERE table_2.value = 15); WHERE key IN (SELECT key FROM table_2 JOIN table_3 USING (key) WHERE table_2.value = 15);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | parallel_access | not_parallel_accessed table_1 | parallel_access | parallel_access | not_parallel_accessed
@ -379,7 +379,7 @@ ROLLBACK;
-- INSERT .. SELECT pushdown -- INSERT .. SELECT pushdown
BEGIN; BEGIN;
INSERT INTO table_2 SELECT * FROM table_1; INSERT INTO table_2 SELECT * FROM table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -391,7 +391,7 @@ ROLLBACK;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
INSERT INTO table_2 SELECT * FROM table_1; INSERT INTO table_2 SELECT * FROM table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -403,7 +403,7 @@ ROLLBACK;
BEGIN; BEGIN;
-- We use offset 1 to make sure the result needs to be pulled to the coordinator, offset 0 would be optimized away -- We use offset 1 to make sure the result needs to be pulled to the coordinator, offset 0 would be optimized away
INSERT INTO table_2 SELECT * FROM table_1 OFFSET 1; INSERT INTO table_2 SELECT * FROM table_1 OFFSET 1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -430,7 +430,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -453,7 +453,7 @@ BEGIN;
table_1.key = table_2.key table_1.key = table_2.key
OFFSET 0 OFFSET 0
) as foo; ) as foo;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -479,7 +479,7 @@ BEGIN;
AND table_1.key = 1 AND table_1.key = 1
OFFSET 0 OFFSET 0
) as foo; ) as foo;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -505,7 +505,7 @@ BEGIN;
OFFSET 0 OFFSET 0
) as foo ) as foo
) AND value IN (SELECT key FROM table_4); ) AND value IN (SELECT key FROM table_4);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3', 'table_4') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3', 'table_4') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -521,7 +521,7 @@ BEGIN;
1 1 1 1
2 2 2 2
3 3 3 3
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -531,7 +531,7 @@ ROLLBACK;
-- copy in -- copy in
BEGIN; BEGIN;
COPY table_1 FROM STDIN WITH CSV; COPY table_1 FROM STDIN WITH CSV;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | parallel_access | not_parallel_accessed table_1 | not_parallel_accessed | parallel_access | not_parallel_accessed
@ -541,7 +541,7 @@ ROLLBACK;
-- copy in single shard -- copy in single shard
BEGIN; BEGIN;
COPY table_1 FROM STDIN WITH CSV; COPY table_1 FROM STDIN WITH CSV;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -556,21 +556,21 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_6'); SELECT * FROM relation_accesses WHERE table_name IN ('table_6');
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_6 | reference_table_access | not_accessed | not_accessed table_6 | reference_table_access | not_accessed | not_accessed
(1 row) (1 row)
UPDATE table_6 SET value = 15; UPDATE table_6 SET value = 15;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6'); SELECT * FROM relation_accesses WHERE table_name IN ('table_6');
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_6 | reference_table_access | reference_table_access | not_accessed table_6 | reference_table_access | reference_table_access | not_accessed
(1 row) (1 row)
ALTER TABLE table_6 ADD COLUMN x INT; ALTER TABLE table_6 ADD COLUMN x INT;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6'); SELECT * FROM relation_accesses WHERE table_name IN ('table_6');
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_6 | reference_table_access | reference_table_access | reference_table_access table_6 | reference_table_access | reference_table_access | reference_table_access
@ -585,7 +585,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_6', 'table_1') ORDER BY 1,2; SELECT * FROM relation_accesses WHERE table_name IN ('table_6', 'table_1') ORDER BY 1,2;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -596,7 +596,7 @@ ROLLBACK;
-- TRUNCATE should be DDL -- TRUNCATE should be DDL
BEGIN; BEGIN;
TRUNCATE table_1; TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -607,7 +607,7 @@ ROLLBACK;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
TRUNCATE table_1; TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -617,7 +617,7 @@ ROLLBACK;
-- TRUNCATE on a reference table should be sequential -- TRUNCATE on a reference table should be sequential
BEGIN; BEGIN;
TRUNCATE table_6; TRUNCATE table_6;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_6') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_6 | not_accessed | not_accessed | reference_table_access table_6 | not_accessed | not_accessed | reference_table_access
@ -628,7 +628,7 @@ ROLLBACK;
ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key);
BEGIN; BEGIN;
ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -641,7 +641,7 @@ ROLLBACK;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -659,7 +659,7 @@ SELECT create_distributed_table('partitioning_test', 'id');
-- Adding partition tables via CREATE TABLE should have DDL access the partitioned table as well -- Adding partition tables via CREATE TABLE should have DDL access the partitioned table as well
BEGIN; BEGIN;
CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -671,7 +671,7 @@ ROLLBACK;
CREATE TABLE partitioning_test_2009 AS SELECT * FROM partitioning_test; CREATE TABLE partitioning_test_2009 AS SELECT * FROM partitioning_test;
BEGIN; BEGIN;
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -689,7 +689,7 @@ SELECT create_distributed_table('partitioning_test_2010', 'id');
BEGIN; BEGIN;
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 FOR VALUES FROM ('2010-01-01') TO ('2011-01-01'); ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -705,7 +705,7 @@ BEGIN;
0 0
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | parallel_access | not_parallel_accessed | not_parallel_accessed partitioning_test | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -723,7 +723,7 @@ BEGIN;
0 0
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -735,7 +735,7 @@ COMMIT;
-- updating partitioned table marks all of its partitions -- updating partitioned table marks all of its partitions
BEGIN; BEGIN;
UPDATE partitioning_test SET time = now(); UPDATE partitioning_test SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | parallel_access | parallel_access | not_parallel_accessed partitioning_test | parallel_access | parallel_access | not_parallel_accessed
@ -748,7 +748,7 @@ COMMIT;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
UPDATE partitioning_test SET time = now(); UPDATE partitioning_test SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -760,7 +760,7 @@ COMMIT;
-- DDLs on partitioned table marks all of its partitions -- DDLs on partitioned table marks all of its partitions
BEGIN; BEGIN;
ALTER TABLE partitioning_test ADD COLUMN X INT; ALTER TABLE partitioning_test ADD COLUMN X INT;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -773,7 +773,7 @@ ROLLBACK;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
ALTER TABLE partitioning_test ADD COLUMN X INT; ALTER TABLE partitioning_test ADD COLUMN X INT;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -790,7 +790,7 @@ BEGIN;
0 0
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | parallel_access | not_parallel_accessed | not_parallel_accessed partitioning_test | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -808,7 +808,7 @@ BEGIN;
0 0
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -820,7 +820,7 @@ COMMIT;
-- updating from partition table marks its parent -- updating from partition table marks its parent
BEGIN; BEGIN;
UPDATE partitioning_test_2009 SET time = now(); UPDATE partitioning_test_2009 SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | parallel_access | parallel_access | not_parallel_accessed partitioning_test | parallel_access | parallel_access | not_parallel_accessed
@ -833,7 +833,7 @@ COMMIT;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
UPDATE partitioning_test_2009 SET time = now(); UPDATE partitioning_test_2009 SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -845,7 +845,7 @@ COMMIT;
-- DDLs on partition table marks its parent -- DDLs on partition table marks its parent
BEGIN; BEGIN;
CREATE INDEX i1000000 ON partitioning_test_2009 (id); CREATE INDEX i1000000 ON partitioning_test_2009 (id);
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access partitioning_test | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -858,7 +858,7 @@ ROLLBACK;
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
CREATE INDEX i1000000 ON partitioning_test_2009 (id); CREATE INDEX i1000000 ON partitioning_test_2009 (id);
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed partitioning_test | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -872,7 +872,7 @@ ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_
BEGIN; BEGIN;
TRUNCATE table_1 CASCADE; TRUNCATE table_1 CASCADE;
NOTICE: truncate cascades to table "table_2" NOTICE: truncate cascades to table "table_2"
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access table_1 | not_parallel_accessed | not_parallel_accessed | parallel_access
@ -889,7 +889,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed table_1 | parallel_access | not_parallel_accessed | not_parallel_accessed
@ -906,7 +906,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -924,7 +924,7 @@ BEGIN;
1002 | 1002 1002 | 1002
(3 rows) (3 rows)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
@ -940,7 +940,7 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | parallel_access | not_parallel_accessed table_1 | parallel_access | parallel_access | not_parallel_accessed
@ -949,6 +949,7 @@ BEGIN;
ROLLBACK; ROLLBACK;
-- modifying CTEs should work fine with sequential mode -- modifying CTEs should work fine with sequential mode
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential';
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *) WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1; SELECT count(*) FROM cte_1 ORDER BY 1;
count count
@ -956,10 +957,43 @@ BEGIN;
101 101
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_1 | parallel_access | parallel_access | not_parallel_accessed table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
(1 row)
ROLLBACK;
-- router planned modifying CTEs should work fine with parallel mode
BEGIN;
WITH cte_1 AS (UPDATE table_1 SET value = 15 WHERE key = 6 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1;
count
---------------------------------------------------------------------
1
(1 row)
SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access
---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
(1 row)
ROLLBACK;
-- router planned modifying CTEs should work fine with sequential mode
BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential';
WITH cte_1 AS (UPDATE table_1 SET value = 15 WHERE key = 6 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1;
count
---------------------------------------------------------------------
1
(1 row)
SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
table_name | select_access | dml_access | ddl_access
---------------------------------------------------------------------
table_1 | not_parallel_accessed | not_parallel_accessed | not_parallel_accessed
(1 row) (1 row)
ROLLBACK; ROLLBACK;
@ -979,7 +1013,7 @@ HINT: To remove the local data, run: SELECT truncate_local_data_after_distribut
(1 row) (1 row)
SELECT * FROM relation_acesses WHERE table_name IN ('table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_3') ORDER BY 1;
table_name | select_access | dml_access | ddl_access table_name | select_access | dml_access | ddl_access
--------------------------------------------------------------------- ---------------------------------------------------------------------
table_3 | not_parallel_accessed | parallel_access | parallel_access table_3 | not_parallel_accessed | parallel_access | parallel_access
@ -994,7 +1028,7 @@ drop cascades to function access_tracking.relation_dml_access_mode(oid)
drop cascades to function access_tracking.relation_ddl_access_mode(oid) drop cascades to function access_tracking.relation_ddl_access_mode(oid)
drop cascades to function access_tracking.distributed_relation(text) drop cascades to function access_tracking.distributed_relation(text)
drop cascades to function access_tracking.relation_access_mode_to_text(text,integer) drop cascades to function access_tracking.relation_access_mode_to_text(text,integer)
drop cascades to view access_tracking.relation_acesses drop cascades to view access_tracking.relation_accesses
drop cascades to table access_tracking.table_1 drop cascades to table access_tracking.table_1
drop cascades to table access_tracking.table_2 drop cascades to table access_tracking.table_2
drop cascades to table access_tracking.table_4 drop cascades to table access_tracking.table_4

View File

@ -2,6 +2,7 @@
SET citus.next_shard_id TO 1502000; SET citus.next_shard_id TO 1502000;
CREATE SCHEMA with_modifying; CREATE SCHEMA with_modifying;
SET search_path TO with_modifying, public; SET search_path TO with_modifying, public;
CREATE TABLE with_modifying.local_table (id int, val int);
CREATE TABLE with_modifying.modify_table (id int, val int); CREATE TABLE with_modifying.modify_table (id int, val int);
SELECT create_distributed_table('modify_table', 'id'); SELECT create_distributed_table('modify_table', 'id');
create_distributed_table create_distributed_table
@ -667,6 +668,157 @@ SELECT * FROM raw_data ORDER BY val;
--------------------------------------------------------------------- ---------------------------------------------------------------------
(0 rows) (0 rows)
-- Test that local tables are barred
UPDATE local_table lt SET val = mt.val
FROM modify_table mt WHERE mt.id = lt.id;
ERROR: cannot plan modifications of local tables involving distributed tables
-- Including inside CTEs
WITH cte AS (
UPDATE local_table lt SET val = mt.val
FROM modify_table mt WHERE mt.id = lt.id
RETURNING lt.id, lt.val
) SELECT * FROM cte JOIN modify_table mt ON mt.id = cte.id ORDER BY 1,2;
ERROR: cannot plan modifications of local tables involving distributed tables
-- Make sure checks for volatile functions apply to CTEs too
WITH cte AS (UPDATE modify_table SET val = random() WHERE id = 3 RETURNING *)
SELECT * FROM cte JOIN modify_table mt ON mt.id = 3 AND mt.id = cte.id ORDER BY 1,2;
ERROR: functions used in UPDATE queries on distributed tables must not be VOLATILE
-- Two queries from HammerDB:
-- 1
CREATE TABLE with_modifying.stock (s_i_id numeric(6,0) NOT NULL, s_w_id numeric(4,0) NOT NULL, s_quantity numeric(6,0), s_dist_01 character(24)) WITH (fillfactor='50');
ALTER TABLE with_modifying.stock ADD CONSTRAINT stock_i1 PRIMARY KEY (s_i_id, s_w_id);
SELECT create_distributed_table('stock', 's_w_id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
INSERT INTO with_modifying.stock VALUES
(64833, 10, 3, 'test1'),
(64834, 10, 3, 'test2'),
(63867, 10, 3, 'test3');
PREPARE su_after(INT[], SMALLINT[], SMALLINT[], NUMERIC(5,2)[], NUMERIC, NUMERIC, NUMERIC) AS
WITH stock_update AS (
UPDATE stock
SET s_quantity = ( CASE WHEN s_quantity < (item_stock.quantity + 10) THEN s_quantity + 91 ELSE s_quantity END) - item_stock.quantity
FROM UNNEST($1, $2, $3, $4) AS item_stock (item_id, supply_wid, quantity, price)
WHERE stock.s_i_id = item_stock.item_id
AND stock.s_w_id = item_stock.supply_wid
AND stock.s_w_id = ANY ($2)
RETURNING stock.s_dist_01 as s_dist, stock.s_quantity, ( item_stock.quantity + item_stock.price * ( 1 + $5 + $6 ) * ( 1 - $7) ) amount
)
SELECT array_agg ( s_dist ), array_agg ( s_quantity ), array_agg ( amount )
FROM stock_update;
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{"test1 "} | {86} | {24.7958000000}
(1 row)
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{"test1 "} | {78} | {24.7958000000}
(1 row)
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{"test1 "} | {70} | {24.7958000000}
(1 row)
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{"test1 "} | {62} | {24.7958000000}
(1 row)
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{"test1 "} | {54} | {24.7958000000}
(1 row)
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{"test1 "} | {46} | {24.7958000000}
(1 row)
-- 2
CREATE TABLE with_modifying.orders (o_id numeric NOT NULL, o_w_id numeric NOT NULL, o_d_id numeric NOT NULL, o_c_id numeric) WITH (fillfactor='50');
CREATE UNIQUE INDEX orders_i2 ON with_modifying.orders USING btree (o_w_id, o_d_id, o_c_id, o_id) TABLESPACE pg_default;
ALTER TABLE with_modifying.orders ADD CONSTRAINT orders_i1 PRIMARY KEY (o_w_id, o_d_id, o_id);
CREATE TABLE with_modifying.order_line (ol_w_id numeric NOT NULL, ol_d_id numeric NOT NULL, ol_o_id numeric NOT NULL, ol_number numeric NOT NULL, ol_delivery_d timestamp without time zone, ol_amount numeric) WITH (fillfactor='50');
ALTER TABLE with_modifying.order_line ADD CONSTRAINT order_line_i1 PRIMARY KEY (ol_w_id, ol_d_id, ol_o_id, ol_number);
SELECT create_distributed_table('orders', 'o_w_id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('order_line', 'ol_w_id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
INSERT INTO orders VALUES (1, 1, 1, 1), (2, 2, 2, 2), (3, 3, 3, 3);
INSERT INTO order_line VALUES (1, 1, 1, 10), (2, 2, 2, 20), (3, 3, 3, 30);
PREPARE olu(int,int[],int[]) AS
WITH order_line_update AS (
UPDATE order_line
SET ol_delivery_d = current_timestamp
FROM UNNEST($2, $3) AS ids(o_id, d_id)
WHERE ol_o_id = ids.o_id
AND ol_d_id = ids.d_id
AND ol_w_id = $1
RETURNING ol_d_id, ol_o_id, ol_amount
)
SELECT array_agg(ol_d_id), array_agg(c_id), array_agg(sum_amount)
FROM (
SELECT ol_d_id,
(SELECT DISTINCT o_c_id FROM orders WHERE o_id = ol_o_id AND o_d_id = ol_d_id AND o_w_id = $1) AS c_id,
sum(ol_amount) AS sum_amount
FROM order_line_update
GROUP BY ol_d_id, ol_o_id
) AS inner_sum;
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{1} | {1} | {NULL}
(1 row)
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{1} | {1} | {NULL}
(1 row)
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{1} | {1} | {NULL}
(1 row)
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{1} | {1} | {NULL}
(1 row)
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{1} | {1} | {NULL}
(1 row)
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
array_agg | array_agg | array_agg
---------------------------------------------------------------------
{1} | {1} | {NULL}
(1 row)
-- Test with replication factor 2 -- Test with replication factor 2
SET citus.shard_replication_factor to 2; SET citus.shard_replication_factor to 2;
DROP TABLE modify_table; DROP TABLE modify_table;
@ -737,10 +889,81 @@ ROLLBACK;
1 1
(1 row) (1 row)
SET client_min_messages TO debug2;
-- pushed down without the insert
WITH mb AS (UPDATE modify_table SET val = 3 WHERE id = 3 RETURNING NULL) INSERT INTO modify_table WITH ma AS (SELECT * FROM modify_table LIMIT 10) SELECT count(*) FROM mb;
DEBUG: LIMIT clauses are not allowed in distributed INSERT ... SELECT queries
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 3
DEBUG: Collecting INSERT ... SELECT results on coordinator
-- not pushed down due to volatile
WITH ma AS (SELECT count(*) FROM modify_table where id = 1), mu AS (WITH allref AS (SELECT random() a FROM modify_table limit 4) UPDATE modify_table SET val = 3 WHERE id = 1 AND val IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu, ma;
DEBUG: CTE ma is going to be inlined via distributed planning
DEBUG: Router planner doesn't support VOLATILE functions in common table expressions.
DEBUG: generating subplan XXX_1 for CTE mu: WITH allref AS (SELECT random() AS a FROM with_modifying.modify_table modify_table_1 LIMIT 4) UPDATE with_modifying.modify_table SET val = 3 WHERE ((id OPERATOR(pg_catalog.=) 1) AND ((val)::double precision OPERATOR(pg_catalog.=) ANY (SELECT allref.a FROM allref))) RETURNING (id OPERATOR(pg_catalog.+) 1)
DEBUG: Router planner doesn't support VOLATILE functions in common table expressions.
DEBUG: generating subplan XXX_1 for CTE allref: SELECT random() AS a FROM with_modifying.modify_table LIMIT 4
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: push down of limit count: 4
DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE with_modifying.modify_table SET val = 3 WHERE ((id OPERATOR(pg_catalog.=) 1) AND ((val)::double precision OPERATOR(pg_catalog.=) ANY (SELECT allref.a FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a double precision)) allref))) RETURNING (id OPERATOR(pg_catalog.+) 1)
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 1
DEBUG: Distributed planning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 1
DEBUG: generating subplan XXX_2 for subquery SELECT count(*) AS count FROM with_modifying.modify_table WHERE (id OPERATOR(pg_catalog.=) 1)
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer)) mu, (SELECT intermediate_result.count FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) ma
DEBUG: Creating router plan
DEBUG: Plan is router executable
count
---------------------------------------------------------------------
0
(1 row)
WITH mu AS (WITH allref AS (SELECT random() a FROM anchor_table) UPDATE modify_table SET val = 3 WHERE id = 1 AND val IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu;
DEBUG: Router planner doesn't support VOLATILE functions in common table expressions.
DEBUG: generating subplan XXX_1 for CTE mu: WITH allref AS (SELECT random() AS a FROM with_modifying.anchor_table) UPDATE with_modifying.modify_table SET val = 3 WHERE ((id OPERATOR(pg_catalog.=) 1) AND ((val)::double precision OPERATOR(pg_catalog.=) ANY (SELECT allref.a FROM allref))) RETURNING (id OPERATOR(pg_catalog.+) 1)
DEBUG: Router planner doesn't support VOLATILE functions in common table expressions.
DEBUG: generating subplan XXX_1 for CTE allref: SELECT random() AS a FROM with_modifying.anchor_table
DEBUG: Distributed planning for a fast-path router query
DEBUG: Creating router plan
DEBUG: Plan is router executable
DEBUG: Plan XXX query after replacing subqueries and CTEs: UPDATE with_modifying.modify_table SET val = 3 WHERE ((id OPERATOR(pg_catalog.=) 1) AND ((val)::double precision OPERATOR(pg_catalog.=) ANY (SELECT allref.a FROM (SELECT intermediate_result.a FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(a double precision)) allref))) RETURNING (id OPERATOR(pg_catalog.+) 1)
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 1
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT count(*) AS count FROM (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result("?column?" integer)) mu
DEBUG: Creating router plan
DEBUG: Plan is router executable
count
---------------------------------------------------------------------
0
(1 row)
-- pushed down
WITH mu AS (WITH allref AS (SELECT id a FROM anchor_table) UPDATE modify_table SET val = 3 WHERE id = 1 AND val IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu;
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 1
count
---------------------------------------------------------------------
0
(1 row)
-- pushed down and stable function evaluated
WITH mu AS (WITH allref AS (SELECT now() a FROM anchor_table) UPDATE modify_table SET val = 3 WHERE id = 1 AND now() IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu;
DEBUG: Creating router plan
DEBUG: Plan is router executable
DETAIL: distribution column value: 1
count
---------------------------------------------------------------------
0
(1 row)
RESET client_min_messages;
\set VERBOSITY terse
DROP SCHEMA with_modifying CASCADE; DROP SCHEMA with_modifying CASCADE;
NOTICE: drop cascades to 5 other objects NOTICE: drop cascades to 9 other objects
DETAIL: drop cascades to table users_table
drop cascades to table anchor_table
drop cascades to function raise_failed_execution_cte(text)
drop cascades to table modify_table
drop cascades to table summary_table

View File

@ -186,6 +186,31 @@ FROM
event_id event_id
WHERE WHERE
events_user_id IN (SELECT user_id FROM users_table); events_user_id IN (SELECT user_id FROM users_table);
-- Prepare routable modifying CTEs
PREPARE prepared_test_7 AS
WITH basic_delete AS (
DELETE FROM users_table WHERE user_id=6 RETURNING *
)
SELECT
*
FROM
basic_delete
ORDER BY
user_id,
time
LIMIT 10;
PREPARE prepared_test_8 AS
WITH basic_delete AS (
UPDATE users_table SET value_1 = value_1 + 1 WHERE user_id=6 RETURNING *
)
SELECT
*
FROM
basic_delete
ORDER BY
user_id,
time
LIMIT 10;
EXECUTE prepared_test_1; EXECUTE prepared_test_1;
user_id | time | value_1 | value_2 | value_3 | value_4 user_id | time | value_1 | value_2 | value_3 | value_4
--------------------------------------------------------------------- ---------------------------------------------------------------------
@ -590,6 +615,274 @@ EXECUTE prepared_test_6;
101 101
(1 row) (1 row)
BEGIN;
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 1 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 2 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 1 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 5 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 2 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 0 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 5 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 2 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 0 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 3 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
ROLLBACK;
BEGIN;
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 1 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 2 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 1 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 5 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 2 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 0 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 5 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 2 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 0 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 3 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
EXECUTE prepared_test_7;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
(0 rows)
ROLLBACK;
BEGIN;
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 2 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 3 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 2 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 6 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 3 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 1 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 6 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 3 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 1 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 4 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 3 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 4 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 3 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 7 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 4 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 2 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 7 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 4 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 2 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 5 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 4 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 5 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 4 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 8 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 5 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 3 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 8 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 5 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 3 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 6 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 5 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 6 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 5 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 9 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 6 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 4 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 9 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 6 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 4 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 7 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 6 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 7 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 6 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 10 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 7 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 5 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 10 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 7 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 5 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 8 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 7 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 8 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 7 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 11 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 8 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 6 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 11 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 8 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 6 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 9 | 2 | 5 |
(10 rows)
ROLLBACK;
BEGIN;
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 2 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 3 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 2 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 6 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 3 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 1 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 6 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 3 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 1 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 4 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 3 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 4 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 3 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 7 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 4 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 2 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 7 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 4 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 2 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 5 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 4 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 5 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 4 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 8 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 5 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 3 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 8 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 5 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 3 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 6 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 5 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 6 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 5 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 9 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 6 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 4 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 9 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 6 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 4 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 7 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 6 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 7 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 6 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 10 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 7 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 5 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 10 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 7 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 5 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 8 | 2 | 5 |
(10 rows)
EXECUTE prepared_test_8;
user_id | time | value_1 | value_2 | value_3 | value_4
---------------------------------------------------------------------
6 | Wed Nov 22 20:15:53.317797 2017 | 7 | 1 | 1 |
6 | Wed Nov 22 23:01:24.82289 2017 | 8 | 4 | 1 |
6 | Thu Nov 23 00:07:11.068353 2017 | 7 | 1 | 4 |
6 | Thu Nov 23 00:09:44.19812 2017 | 11 | 2 | 0 |
6 | Thu Nov 23 01:13:50.526322 2017 | 8 | 4 | 1 |
6 | Thu Nov 23 01:14:55.769581 2017 | 6 | 0 | 5 |
6 | Thu Nov 23 10:22:11.02918 2017 | 11 | 0 | 5 |
6 | Thu Nov 23 11:08:04.244582 2017 | 8 | 3 | 2 |
6 | Thu Nov 23 13:51:16.92838 2017 | 6 | 4 | 2 |
6 | Thu Nov 23 14:43:18.024104 2017 | 9 | 2 | 5 |
(10 rows)
ROLLBACK;
EXECUTE prepared_partition_column_insert(1); EXECUTE prepared_partition_column_insert(1);
user_id | time | value_1 | value_2 | value_3 | value_4 user_id | time | value_1 | value_2 | value_3 | value_4
--------------------------------------------------------------------- ---------------------------------------------------------------------

View File

@ -77,18 +77,20 @@ step "s1-select-from-t1-rt-with-lc-for-update"
step "s1-select-from-t1-within-cte" step "s1-select-from-t1-within-cte"
{ {
WITH first_value AS (SELECT val_1 FROM test_table_1_rf1 WHERE id = 1 FOR UPDATE) WITH first_value AS (SELECT val_1 FROM test_table_1_rf1 WHERE id = 1 FOR UPDATE)
SELECT * FROM first_value; SELECT * FROM first_value WHERE EXISTS (SELECT * FROM first_value);
} }
step "s1-update-rt-with-cte-select-from-rt" step "s1-update-rt-with-cte-select-from-rt"
{ {
WITH foo AS (SELECT * FROM ref_table FOR UPDATE) WITH foo AS (SELECT * FROM ref_table FOR UPDATE)
UPDATE ref_table SET val_1 = 4 FROM foo WHERE ref_table.id = foo.id; UPDATE ref_table SET val_1 = 4 FROM foo WHERE ref_table.id = foo.id AND EXISTS (SELECT * FROM foo);
} }
step "s1-select-from-t1-with-subquery" step "s1-select-from-t1-with-subquery"
{ {
SET client_min_messages TO DEBUG2;
SELECT * FROM (SELECT * FROM test_table_1_rf1 FOR UPDATE) foo WHERE id = 1; SELECT * FROM (SELECT * FROM test_table_1_rf1 FOR UPDATE) foo WHERE id = 1;
RESET client_min_messages;
} }
step "s1-select-from-rt-with-subquery" step "s1-select-from-rt-with-subquery"

View File

@ -26,6 +26,7 @@ session "s1"
step "s1-initialize" { COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV; } step "s1-initialize" { COPY update_hash FROM PROGRAM 'echo 0, a && echo 1, b && echo 2, c && echo 3, d && echo 4, e' WITH CSV; }
step "s1-begin" { BEGIN; } step "s1-begin" { BEGIN; }
step "s1-update" { UPDATE update_hash SET data = 'l' WHERE id = 4; } step "s1-update" { UPDATE update_hash SET data = 'l' WHERE id = 4; }
step "s1-update-cte" { WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; }
step "s1-delete" { DELETE FROM update_hash WHERE id = 4; } step "s1-delete" { DELETE FROM update_hash WHERE id = 4; }
step "s1-truncate" { TRUNCATE update_hash; } step "s1-truncate" { TRUNCATE update_hash; }
step "s1-drop" { DROP TABLE update_hash; } step "s1-drop" { DROP TABLE update_hash; }
@ -47,6 +48,7 @@ step "s1-commit" { COMMIT; }
session "s2" session "s2"
step "s2-begin" { BEGIN; } step "s2-begin" { BEGIN; }
step "s2-update" { UPDATE update_hash SET data = 'l' WHERE id = 4; } step "s2-update" { UPDATE update_hash SET data = 'l' WHERE id = 4; }
step "s2-update-cte" { WITH cte AS (UPDATE update_hash SET data = 'l' WHERE id = 4 RETURNING *) SELECT * FROM cte WHERE id = 4; }
step "s2-delete" { DELETE FROM update_hash WHERE id = 4; } step "s2-delete" { DELETE FROM update_hash WHERE id = 4; }
step "s2-truncate" { TRUNCATE update_hash; } step "s2-truncate" { TRUNCATE update_hash; }
step "s2-drop" { DROP TABLE update_hash; } step "s2-drop" { DROP TABLE update_hash; }
@ -63,6 +65,7 @@ step "s2-commit" { COMMIT; }
// permutations - UPDATE vs UPDATE // permutations - UPDATE vs UPDATE
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-update" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-update" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"
// permutations - UPDATE first // permutations - UPDATE first
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-delete" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-delete" "s1-commit" "s2-commit" "s1-select-count"
@ -78,6 +81,18 @@ permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-table-size" "s
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-master-modify-multiple-shards" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-master-modify-multiple-shards" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-drop" "s1-create-non-distributed-table" "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-distribute-table" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-drop" "s1-create-non-distributed-table" "s1-initialize" "s1-begin" "s2-begin" "s1-update" "s2-distribute-table" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-delete" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-truncate" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-drop" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-ddl-create-index" "s1-commit" "s2-commit" "s1-select-count" "s1-show-indexes"
permutation "s1-initialize" "s1-ddl-create-index" "s1-begin" "s2-begin" "s1-update-cte" "s2-ddl-drop-index" "s1-commit" "s2-commit" "s1-select-count" "s1-show-indexes"
permutation "s1-initialize" "s1-begin" "s1-update-cte" "s2-ddl-create-index-concurrently" "s1-commit" "s1-select-count" "s1-show-indexes"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-ddl-add-column" "s1-commit" "s2-commit" "s1-select-count" "s1-show-columns"
permutation "s1-initialize" "s1-ddl-add-column" "s1-begin" "s2-begin" "s1-update-cte" "s2-ddl-drop-column" "s1-commit" "s2-commit" "s1-select-count" "s1-show-columns"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-ddl-rename-column" "s1-commit" "s2-commit" "s1-select-count" "s1-show-columns"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-table-size" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-update-cte" "s2-master-modify-multiple-shards" "s1-commit" "s2-commit" "s1-select-count"
// permutations - UPDATE second // permutations - UPDATE second
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-delete" "s2-update" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-delete" "s2-update" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-truncate" "s2-update" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-truncate" "s2-update" "s1-commit" "s2-commit" "s1-select-count"
@ -90,3 +105,15 @@ permutation "s1-initialize" "s1-begin" "s2-begin" "s1-ddl-rename-column" "s2-upd
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-table-size" "s2-update" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-table-size" "s2-update" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-master-modify-multiple-shards" "s2-update" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-initialize" "s1-begin" "s2-begin" "s1-master-modify-multiple-shards" "s2-update" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-drop" "s1-create-non-distributed-table" "s1-initialize" "s1-begin" "s2-begin" "s1-distribute-table" "s2-update" "s1-commit" "s2-commit" "s1-select-count" permutation "s1-drop" "s1-create-non-distributed-table" "s1-initialize" "s1-begin" "s2-begin" "s1-distribute-table" "s2-update" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-delete" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-truncate" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-drop" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-ddl-create-index" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count" "s1-show-indexes"
permutation "s1-initialize" "s1-ddl-create-index" "s1-begin" "s2-begin" "s1-ddl-drop-index" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count" "s1-show-indexes"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-ddl-add-column" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count" "s1-show-columns"
permutation "s1-initialize" "s1-ddl-add-column" "s1-begin" "s2-begin" "s1-ddl-drop-column" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count" "s1-show-columns"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-ddl-rename-column" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count" "s1-show-columns"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-table-size" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-initialize" "s1-begin" "s2-begin" "s1-master-modify-multiple-shards" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"
permutation "s1-drop" "s1-create-non-distributed-table" "s1-initialize" "s1-begin" "s2-begin" "s1-distribute-table" "s2-update-cte" "s1-commit" "s2-commit" "s1-select-count"

View File

@ -532,6 +532,18 @@ BEGIN;
UPDATE transitive_reference_table SET id = 160 WHERE id = 15; UPDATE transitive_reference_table SET id = 160 WHERE id = 15;
ROLLBACK; ROLLBACK;
BEGIN;
WITH cte AS (UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15 RETURNING *)
SELECT * FROM cte;
UPDATE reference_table SET id = 160 WHERE id = 15;
ROLLBACK;
BEGIN;
WITH cte AS (UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15 RETURNING *)
SELECT * FROM cte;
UPDATE transitive_reference_table SET id = 160 WHERE id = 15;
ROLLBACK;
-- case 5.3: Parallel UPDATE on distributed table follow by an unrelated DDL on reference table -- case 5.3: Parallel UPDATE on distributed table follow by an unrelated DDL on reference table
BEGIN; BEGIN;
UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15; UPDATE on_update_fkey_table SET value_1 = 16 WHERE value_1 = 15;

View File

@ -171,6 +171,32 @@ SELECT * FROM articles_hash WHERE author_id IN (1, NULL) ORDER BY id;
WITH first_author AS ( SELECT id FROM articles_hash WHERE author_id = 1) WITH first_author AS ( SELECT id FROM articles_hash WHERE author_id = 1)
SELECT * FROM first_author; SELECT * FROM first_author;
-- SELECT FOR UPDATE is supported if not involving reference table
BEGIN;
WITH first_author AS (
SELECT articles_hash.id, auref.name FROM articles_hash, authors_reference auref
WHERE author_id = 2 AND auref.id = author_id
FOR UPDATE
)
UPDATE articles_hash SET title = first_author.name
FROM first_author WHERE articles_hash.author_id = 2 AND articles_hash.id = first_author.id;
WITH first_author AS (
SELECT id, word_count FROM articles_hash WHERE author_id = 2
FOR UPDATE
)
UPDATE articles_hash SET title = first_author.word_count::text
FROM first_author WHERE articles_hash.author_id = 2 AND articles_hash.id = first_author.id;
-- Without FOR UPDATE this is router plannable
WITH first_author AS (
SELECT articles_hash.id, auref.name FROM articles_hash, authors_reference auref
WHERE author_id = 2 AND auref.id = author_id
)
UPDATE articles_hash SET title = first_author.name
FROM first_author WHERE articles_hash.author_id = 2 AND articles_hash.id = first_author.id;
ROLLBACK;
-- queries with CTEs are supported even if CTE is not referenced inside query -- queries with CTEs are supported even if CTE is not referenced inside query
WITH first_author AS ( SELECT id FROM articles_hash WHERE author_id = 1) WITH first_author AS ( SELECT id FROM articles_hash WHERE author_id = 1)
SELECT title FROM articles_hash WHERE author_id = 1; SELECT title FROM articles_hash WHERE author_id = 1;
@ -1038,7 +1064,8 @@ SELECT count(*), count(*) FILTER (WHERE id < 3)
PREPARE author_1_articles as PREPARE author_1_articles as
SELECT * SELECT *
FROM articles_hash FROM articles_hash
WHERE author_id = 1; WHERE author_id = 1
ORDER BY 1;
EXECUTE author_1_articles; EXECUTE author_1_articles;
@ -1046,7 +1073,8 @@ EXECUTE author_1_articles;
PREPARE author_articles(int) as PREPARE author_articles(int) as
SELECT * SELECT *
FROM articles_hash FROM articles_hash
WHERE author_id = $1; WHERE author_id = $1
ORDER BY 1;
EXECUTE author_articles(1); EXECUTE author_articles(1);
@ -1076,7 +1104,7 @@ BEGIN
END; END;
$$ LANGUAGE plpgsql; $$ LANGUAGE plpgsql;
SELECT * FROM author_articles_id_word_count(); SELECT * FROM author_articles_id_word_count() ORDER BY 1;
-- materialized views can be created for router plannable queries -- materialized views can be created for router plannable queries
CREATE MATERIALIZED VIEW mv_articles_hash_empty AS CREATE MATERIALIZED VIEW mv_articles_hash_empty AS
@ -1091,7 +1119,8 @@ SELECT * FROM mv_articles_hash_data ORDER BY 1, 2, 3, 4;
SET citus.task_executor_type to 'task-tracker'; SET citus.task_executor_type to 'task-tracker';
SELECT id SELECT id
FROM articles_hash FROM articles_hash
WHERE author_id = 1; WHERE author_id = 1
ORDER BY 1;
-- insert query is router plannable even under task-tracker -- insert query is router plannable even under task-tracker
INSERT INTO articles_hash VALUES (51, 1, 'amateus', 1814), (52, 1, 'second amateus', 2824); INSERT INTO articles_hash VALUES (51, 1, 'amateus', 1814), (52, 1, 'second amateus', 2824);
@ -1099,7 +1128,8 @@ INSERT INTO articles_hash VALUES (51, 1, 'amateus', 1814), (52, 1, 'second amate
-- verify insert is successful (not router plannable and executable) -- verify insert is successful (not router plannable and executable)
SELECT id SELECT id
FROM articles_hash FROM articles_hash
WHERE author_id = 1; WHERE author_id = 1
ORDER BY 1;
-- https://github.com/citusdata/citus/issues/3624 -- https://github.com/citusdata/citus/issues/3624
UPDATE articles_hash SET id = id UPDATE articles_hash SET id = id

View File

@ -55,7 +55,7 @@ $$ LANGUAGE 'plpgsql' IMMUTABLE;
CREATE VIEW relation_acesses AS CREATE VIEW relation_accesses AS
SELECT table_name, SELECT table_name,
relation_access_mode_to_text(table_name, relation_select_access_mode(table_name::regclass)) as select_access, relation_access_mode_to_text(table_name, relation_select_access_mode(table_name::regclass)) as select_access,
relation_access_mode_to_text(table_name, relation_dml_access_mode(table_name::regclass)) as dml_access, relation_access_mode_to_text(table_name, relation_dml_access_mode(table_name::regclass)) as dml_access,
@ -93,29 +93,29 @@ INSERT INTO table_6 SELECT i, i FROM generate_series(0,100) i;
BEGIN; BEGIN;
CREATE TABLE table_7 (key int, value int); CREATE TABLE table_7 (key int, value int);
SELECT create_distributed_table('table_7', 'key'); SELECT create_distributed_table('table_7', 'key');
SELECT * FROM relation_acesses WHERE table_name IN ('table_7') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_7') ORDER BY 1;
COMMIT; COMMIT;
-- outisde the transaction blocks, the function always returns zero -- outside the transaction blocks, the function always returns zero
SELECT count(*) FROM table_1; SELECT count(*) FROM table_1;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
-- a very simple test that first checks sequential -- a very simple test that first checks sequential
-- and parallel SELECTs,DMLs, and DDLs -- and parallel SELECTs,DMLs, and DDLs
BEGIN; BEGIN;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
SELECT count(*) FROM table_1 WHERE key = 1; SELECT count(*) FROM table_1 WHERE key = 1;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
SELECT count(*) FROM table_1 WHERE key = 1 OR key = 2; SELECT count(*) FROM table_1 WHERE key = 1 OR key = 2;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
INSERT INTO table_1 VALUES (1,1); INSERT INTO table_1 VALUES (1,1);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
INSERT INTO table_1 VALUES (1,1), (2,2); INSERT INTO table_1 VALUES (1,1), (2,2);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
ALTER TABLE table_1 ADD COLUMN test_col INT; ALTER TABLE table_1 ADD COLUMN test_col INT;
-- now see that the other tables are not accessed at all -- now see that the other tables are not accessed at all
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
ROLLBACK; ROLLBACK;
@ -124,19 +124,19 @@ ROLLBACK;
-- commands executed, we can treat the transaction as sequential -- commands executed, we can treat the transaction as sequential
BEGIN; BEGIN;
SELECT count(*) FROM table_1 WHERE key = 1; SELECT count(*) FROM table_1 WHERE key = 1;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
SELECT count(*) FROM table_1 WHERE key = 2; SELECT count(*) FROM table_1 WHERE key = 2;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
INSERT INTO table_1 VALUES (1,1); INSERT INTO table_1 VALUES (1,1);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
INSERT INTO table_1 VALUES (2,2); INSERT INTO table_1 VALUES (2,2);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
ROLLBACK; ROLLBACK;
-- a sample DDL example -- a sample DDL example
BEGIN; BEGIN;
ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key);
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
ROLLBACK; ROLLBACK;
-- a simple join touches single shard per table -- a simple join touches single shard per table
@ -150,7 +150,7 @@ BEGIN;
table_3.key = table_4.key AND table_4.key = table_5.key AND table_3.key = table_4.key AND table_4.key = table_5.key AND
table_1.key = 1; table_1.key = 1;
SELECT * FROM relation_acesses WHERE table_name LIKE 'table_%' ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name LIKE 'table_%' ORDER BY 1;
ROLLBACK; ROLLBACK;
-- a simple real-time join touches all shard per table -- a simple real-time join touches all shard per table
@ -162,7 +162,7 @@ BEGIN;
WHERE WHERE
table_1.key = table_2.key; table_1.key = table_2.key;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- a simple real-time join touches all shard per table -- a simple real-time join touches all shard per table
@ -177,7 +177,7 @@ BEGIN;
WHERE WHERE
table_1.key = table_2.key; table_1.key = table_2.key;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- a simple subquery pushdown that touches all shards -- a simple subquery pushdown that touches all shards
@ -196,7 +196,7 @@ BEGIN;
table_3.key = table_4.key AND table_4.key = table_5.key table_3.key = table_4.key AND table_4.key = table_5.key
) as foo; ) as foo;
SELECT * FROM relation_acesses WHERE table_name LIKE 'table_%' ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name LIKE 'table_%' ORDER BY 1;
ROLLBACK; ROLLBACK;
-- simple multi shard update both sequential and parallel modes -- simple multi shard update both sequential and parallel modes
@ -204,10 +204,10 @@ ROLLBACK;
-- access for all the shards accessed. But, sequential mode is OK -- access for all the shards accessed. But, sequential mode is OK
BEGIN; BEGIN;
UPDATE table_1 SET value = 15; UPDATE table_1 SET value = 15;
SELECT * FROM relation_acesses WHERE table_name = 'table_1'; SELECT * FROM relation_accesses WHERE table_name = 'table_1';
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
UPDATE table_2 SET value = 15; UPDATE table_2 SET value = 15;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- now UPDATE/DELETE with subselect pushdown -- now UPDATE/DELETE with subselect pushdown
@ -215,13 +215,13 @@ BEGIN;
UPDATE UPDATE
table_1 SET value = 15 table_1 SET value = 15
WHERE key IN (SELECT key FROM table_2 JOIN table_3 USING (key) WHERE table_2.value = 15); WHERE key IN (SELECT key FROM table_2 JOIN table_3 USING (key) WHERE table_2.value = 15);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- INSERT .. SELECT pushdown -- INSERT .. SELECT pushdown
BEGIN; BEGIN;
INSERT INTO table_2 SELECT * FROM table_1; INSERT INTO table_2 SELECT * FROM table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- INSERT .. SELECT pushdown in sequential mode should be OK -- INSERT .. SELECT pushdown in sequential mode should be OK
@ -229,14 +229,14 @@ BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
INSERT INTO table_2 SELECT * FROM table_1; INSERT INTO table_2 SELECT * FROM table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- coordinator INSERT .. SELECT -- coordinator INSERT .. SELECT
BEGIN; BEGIN;
-- We use offset 1 to make sure the result needs to be pulled to the coordinator, offset 0 would be optimized away -- We use offset 1 to make sure the result needs to be pulled to the coordinator, offset 0 would be optimized away
INSERT INTO table_2 SELECT * FROM table_1 OFFSET 1; INSERT INTO table_2 SELECT * FROM table_1 OFFSET 1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
@ -257,7 +257,7 @@ BEGIN;
OFFSET 0 OFFSET 0
) as foo; ) as foo;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- recursively planned SELECT and coordinator INSERT .. SELECT -- recursively planned SELECT and coordinator INSERT .. SELECT
@ -277,7 +277,7 @@ BEGIN;
OFFSET 0 OFFSET 0
) as foo; ) as foo;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- recursively planned SELECT and coordinator INSERT .. SELECT -- recursively planned SELECT and coordinator INSERT .. SELECT
@ -299,7 +299,7 @@ BEGIN;
OFFSET 0 OFFSET 0
) as foo; ) as foo;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- recursively planned SELECT and recursively planned multi-shard DELETE -- recursively planned SELECT and recursively planned multi-shard DELETE
@ -320,13 +320,13 @@ BEGIN;
) as foo ) as foo
) AND value IN (SELECT key FROM table_4); ) AND value IN (SELECT key FROM table_4);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2', 'table_3', 'table_4') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2', 'table_3', 'table_4') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- copy out -- copy out
BEGIN; BEGIN;
COPY (SELECT * FROM table_1 WHERE key IN (1,2,3) ORDER BY 1) TO stdout; COPY (SELECT * FROM table_1 WHERE key IN (1,2,3) ORDER BY 1) TO stdout;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- copy in -- copy in
@ -336,7 +336,7 @@ BEGIN;
2,2 2,2
3,3 3,3
\. \.
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- copy in single shard -- copy in single shard
@ -346,51 +346,51 @@ BEGIN;
1,2 1,2
1,3 1,3
\. \.
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- reference table accesses should always be a sequential -- reference table accesses should always be a sequential
BEGIN; BEGIN;
SELECT count(*) FROM table_6; SELECT count(*) FROM table_6;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6'); SELECT * FROM relation_accesses WHERE table_name IN ('table_6');
UPDATE table_6 SET value = 15; UPDATE table_6 SET value = 15;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6'); SELECT * FROM relation_accesses WHERE table_name IN ('table_6');
ALTER TABLE table_6 ADD COLUMN x INT; ALTER TABLE table_6 ADD COLUMN x INT;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6'); SELECT * FROM relation_accesses WHERE table_name IN ('table_6');
ROLLBACK; ROLLBACK;
-- reference table join with a distributed table -- reference table join with a distributed table
BEGIN; BEGIN;
SELECT count(*) FROM table_1 JOIN table_6 USING(key); SELECT count(*) FROM table_1 JOIN table_6 USING(key);
SELECT * FROM relation_acesses WHERE table_name IN ('table_6', 'table_1') ORDER BY 1,2; SELECT * FROM relation_accesses WHERE table_name IN ('table_6', 'table_1') ORDER BY 1,2;
ROLLBACK; ROLLBACK;
-- TRUNCATE should be DDL -- TRUNCATE should be DDL
BEGIN; BEGIN;
TRUNCATE table_1; TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- TRUNCATE can be a sequential DDL -- TRUNCATE can be a sequential DDL
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
TRUNCATE table_1; TRUNCATE table_1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- TRUNCATE on a reference table should be sequential -- TRUNCATE on a reference table should be sequential
BEGIN; BEGIN;
TRUNCATE table_6; TRUNCATE table_6;
SELECT * FROM relation_acesses WHERE table_name IN ('table_6') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_6') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- creating foreign keys should consider adding the placement accesses for the referenced table -- creating foreign keys should consider adding the placement accesses for the referenced table
ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key); ALTER TABLE table_1 ADD CONSTRAINT table_1_u UNIQUE (key);
BEGIN; BEGIN;
ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- creating foreign keys should consider adding the placement accesses for the referenced table -- creating foreign keys should consider adding the placement accesses for the referenced table
@ -399,7 +399,7 @@ BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential'; SET LOCAL citus.multi_shard_modify_mode = 'sequential';
ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key);
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time); CREATE TABLE partitioning_test(id int, time date) PARTITION BY RANGE (time);
@ -408,14 +408,14 @@ SELECT create_distributed_table('partitioning_test', 'id');
-- Adding partition tables via CREATE TABLE should have DDL access the partitioned table as well -- Adding partition tables via CREATE TABLE should have DDL access the partitioned table as well
BEGIN; BEGIN;
CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); CREATE TABLE partitioning_test_2009 PARTITION OF partitioning_test FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- Adding partition tables via ATTACH PARTITION on local tables should have DDL access the partitioned table as well -- Adding partition tables via ATTACH PARTITION on local tables should have DDL access the partitioned table as well
CREATE TABLE partitioning_test_2009 AS SELECT * FROM partitioning_test; CREATE TABLE partitioning_test_2009 AS SELECT * FROM partitioning_test;
BEGIN; BEGIN;
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01'); ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2009 FOR VALUES FROM ('2009-01-01') TO ('2010-01-01');
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009') ORDER BY 1;
COMMIT; COMMIT;
-- Adding partition tables via ATTACH PARTITION on distributed tables should have DDL access the partitioned table as well -- Adding partition tables via ATTACH PARTITION on distributed tables should have DDL access the partitioned table as well
@ -423,95 +423,95 @@ CREATE TABLE partitioning_test_2010 AS SELECT * FROM partitioning_test;
SELECT create_distributed_table('partitioning_test_2010', 'id'); SELECT create_distributed_table('partitioning_test_2010', 'id');
BEGIN; BEGIN;
ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 FOR VALUES FROM ('2010-01-01') TO ('2011-01-01'); ALTER TABLE partitioning_test ATTACH PARTITION partitioning_test_2010 FOR VALUES FROM ('2010-01-01') TO ('2011-01-01');
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- reading from partitioned table marks all of its partitions -- reading from partitioned table marks all of its partitions
BEGIN; BEGIN;
SELECT count(*) FROM partitioning_test; SELECT count(*) FROM partitioning_test;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- reading from partitioned table sequentially marks all of its partitions with sequential accesses -- reading from partitioned table sequentially marks all of its partitions with sequential accesses
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
SELECT count(*) FROM partitioning_test; SELECT count(*) FROM partitioning_test;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- updating partitioned table marks all of its partitions -- updating partitioned table marks all of its partitions
BEGIN; BEGIN;
UPDATE partitioning_test SET time = now(); UPDATE partitioning_test SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- updating partitioned table sequentially marks all of its partitions with sequential accesses -- updating partitioned table sequentially marks all of its partitions with sequential accesses
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
UPDATE partitioning_test SET time = now(); UPDATE partitioning_test SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- DDLs on partitioned table marks all of its partitions -- DDLs on partitioned table marks all of its partitions
BEGIN; BEGIN;
ALTER TABLE partitioning_test ADD COLUMN X INT; ALTER TABLE partitioning_test ADD COLUMN X INT;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- DDLs on partitioned table sequentially marks all of its partitions with sequential accesses -- DDLs on partitioned table sequentially marks all of its partitions with sequential accesses
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
ALTER TABLE partitioning_test ADD COLUMN X INT; ALTER TABLE partitioning_test ADD COLUMN X INT;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- reading from partition table marks its parent -- reading from partition table marks its parent
BEGIN; BEGIN;
SELECT count(*) FROM partitioning_test_2009; SELECT count(*) FROM partitioning_test_2009;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- rreading from partition table marks its parent with sequential accesses -- rreading from partition table marks its parent with sequential accesses
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
SELECT count(*) FROM partitioning_test_2009; SELECT count(*) FROM partitioning_test_2009;
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- updating from partition table marks its parent -- updating from partition table marks its parent
BEGIN; BEGIN;
UPDATE partitioning_test_2009 SET time = now(); UPDATE partitioning_test_2009 SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- updating from partition table marks its parent sequential accesses -- updating from partition table marks its parent sequential accesses
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
UPDATE partitioning_test_2009 SET time = now(); UPDATE partitioning_test_2009 SET time = now();
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
COMMIT; COMMIT;
-- DDLs on partition table marks its parent -- DDLs on partition table marks its parent
BEGIN; BEGIN;
CREATE INDEX i1000000 ON partitioning_test_2009 (id); CREATE INDEX i1000000 ON partitioning_test_2009 (id);
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- DDLs on partition table marks its parent in sequential mode -- DDLs on partition table marks its parent in sequential mode
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential'; SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
CREATE INDEX i1000000 ON partitioning_test_2009 (id); CREATE INDEX i1000000 ON partitioning_test_2009 (id);
SELECT * FROM relation_acesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('partitioning_test', 'partitioning_test_2009', 'partitioning_test_2010') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- TRUNCATE CASCADE works fine -- TRUNCATE CASCADE works fine
ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key); ALTER TABLE table_2 ADD CONSTRAINT table_2_u FOREIGN KEY (key) REFERENCES table_1(key);
BEGIN; BEGIN;
TRUNCATE table_1 CASCADE; TRUNCATE table_1 CASCADE;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1', 'table_2') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- CTEs with SELECT only should work fine -- CTEs with SELECT only should work fine
@ -519,7 +519,7 @@ BEGIN;
WITH cte AS (SELECT count(*) FROM table_1) WITH cte AS (SELECT count(*) FROM table_1)
SELECT * FROM cte; SELECT * FROM cte;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
COMMIT; COMMIT;
-- CTEs with SELECT only in sequential mode should work fine -- CTEs with SELECT only in sequential mode should work fine
@ -528,7 +528,7 @@ BEGIN;
WITH cte AS (SELECT count(*) FROM table_1) WITH cte AS (SELECT count(*) FROM table_1)
SELECT * FROM cte; SELECT * FROM cte;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
COMMIT; COMMIT;
-- modifying CTEs should work fine with multi-row inserts, which are by default in sequential -- modifying CTEs should work fine with multi-row inserts, which are by default in sequential
@ -536,7 +536,7 @@ BEGIN;
WITH cte_1 AS (INSERT INTO table_1 VALUES (1000,1000), (1001, 1001), (1002, 1002) RETURNING *) WITH cte_1 AS (INSERT INTO table_1 VALUES (1000,1000), (1001, 1001), (1002, 1002) RETURNING *)
SELECT * FROM cte_1 ORDER BY 1; SELECT * FROM cte_1 ORDER BY 1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- modifying CTEs should work fine with parallel mode -- modifying CTEs should work fine with parallel mode
@ -544,15 +544,33 @@ BEGIN;
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *) WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1; SELECT count(*) FROM cte_1 ORDER BY 1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- modifying CTEs should work fine with sequential mode -- modifying CTEs should work fine with sequential mode
BEGIN; BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential';
WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *) WITH cte_1 AS (UPDATE table_1 SET value = 15 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1; SELECT count(*) FROM cte_1 ORDER BY 1;
SELECT * FROM relation_acesses WHERE table_name IN ('table_1') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK;
-- router planned modifying CTEs should work fine with parallel mode
BEGIN;
WITH cte_1 AS (UPDATE table_1 SET value = 15 WHERE key = 6 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1;
SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK;
-- router planned modifying CTEs should work fine with sequential mode
BEGIN;
SET LOCAL citus.multi_shard_modify_mode = 'sequential';
WITH cte_1 AS (UPDATE table_1 SET value = 15 WHERE key = 6 RETURNING *)
SELECT count(*) FROM cte_1 ORDER BY 1;
SELECT * FROM relation_accesses WHERE table_name IN ('table_1') ORDER BY 1;
ROLLBACK; ROLLBACK;
-- create distributed table with data loading -- create distributed table with data loading
@ -562,7 +580,7 @@ CREATE TABLE table_3 (key int, value int);
INSERT INTO table_3 SELECT i, i FROM generate_series(0,100) i; INSERT INTO table_3 SELECT i, i FROM generate_series(0,100) i;
BEGIN; BEGIN;
SELECT create_distributed_table('table_3', 'key'); SELECT create_distributed_table('table_3', 'key');
SELECT * FROM relation_acesses WHERE table_name IN ('table_3') ORDER BY 1; SELECT * FROM relation_accesses WHERE table_name IN ('table_3') ORDER BY 1;
COMMIT; COMMIT;
SET search_path TO 'public'; SET search_path TO 'public';

View File

@ -4,6 +4,8 @@ SET citus.next_shard_id TO 1502000;
CREATE SCHEMA with_modifying; CREATE SCHEMA with_modifying;
SET search_path TO with_modifying, public; SET search_path TO with_modifying, public;
CREATE TABLE with_modifying.local_table (id int, val int);
CREATE TABLE with_modifying.modify_table (id int, val int); CREATE TABLE with_modifying.modify_table (id int, val int);
SELECT create_distributed_table('modify_table', 'id'); SELECT create_distributed_table('modify_table', 'id');
@ -410,6 +412,84 @@ raw_data AS (
) )
SELECT * FROM raw_data ORDER BY val; SELECT * FROM raw_data ORDER BY val;
-- Test that local tables are barred
UPDATE local_table lt SET val = mt.val
FROM modify_table mt WHERE mt.id = lt.id;
-- Including inside CTEs
WITH cte AS (
UPDATE local_table lt SET val = mt.val
FROM modify_table mt WHERE mt.id = lt.id
RETURNING lt.id, lt.val
) SELECT * FROM cte JOIN modify_table mt ON mt.id = cte.id ORDER BY 1,2;
-- Make sure checks for volatile functions apply to CTEs too
WITH cte AS (UPDATE modify_table SET val = random() WHERE id = 3 RETURNING *)
SELECT * FROM cte JOIN modify_table mt ON mt.id = 3 AND mt.id = cte.id ORDER BY 1,2;
-- Two queries from HammerDB:
-- 1
CREATE TABLE with_modifying.stock (s_i_id numeric(6,0) NOT NULL, s_w_id numeric(4,0) NOT NULL, s_quantity numeric(6,0), s_dist_01 character(24)) WITH (fillfactor='50');
ALTER TABLE with_modifying.stock ADD CONSTRAINT stock_i1 PRIMARY KEY (s_i_id, s_w_id);
SELECT create_distributed_table('stock', 's_w_id');
INSERT INTO with_modifying.stock VALUES
(64833, 10, 3, 'test1'),
(64834, 10, 3, 'test2'),
(63867, 10, 3, 'test3');
PREPARE su_after(INT[], SMALLINT[], SMALLINT[], NUMERIC(5,2)[], NUMERIC, NUMERIC, NUMERIC) AS
WITH stock_update AS (
UPDATE stock
SET s_quantity = ( CASE WHEN s_quantity < (item_stock.quantity + 10) THEN s_quantity + 91 ELSE s_quantity END) - item_stock.quantity
FROM UNNEST($1, $2, $3, $4) AS item_stock (item_id, supply_wid, quantity, price)
WHERE stock.s_i_id = item_stock.item_id
AND stock.s_w_id = item_stock.supply_wid
AND stock.s_w_id = ANY ($2)
RETURNING stock.s_dist_01 as s_dist, stock.s_quantity, ( item_stock.quantity + item_stock.price * ( 1 + $5 + $6 ) * ( 1 - $7) ) amount
)
SELECT array_agg ( s_dist ), array_agg ( s_quantity ), array_agg ( amount )
FROM stock_update;
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
EXECUTE su_after('{64833,63857,13941,76514,35858,10004,88553,34483,91251,28144,51687,36407,54436,72873}', '{10,10,10,10,10,10,10,10,10,10,10,10,10,10}', '{8,2,2,6,7,4,6,1,1,5,6,7,6,2}', '{26.04,4.79,67.84,77.66,47.06,23.12,32.74,56.99,84.75,37.52,73.52,98.86,49.96,29.47}', 0.1800, 0.1100, 0.5000);
-- 2
CREATE TABLE with_modifying.orders (o_id numeric NOT NULL, o_w_id numeric NOT NULL, o_d_id numeric NOT NULL, o_c_id numeric) WITH (fillfactor='50');
CREATE UNIQUE INDEX orders_i2 ON with_modifying.orders USING btree (o_w_id, o_d_id, o_c_id, o_id) TABLESPACE pg_default;
ALTER TABLE with_modifying.orders ADD CONSTRAINT orders_i1 PRIMARY KEY (o_w_id, o_d_id, o_id);
CREATE TABLE with_modifying.order_line (ol_w_id numeric NOT NULL, ol_d_id numeric NOT NULL, ol_o_id numeric NOT NULL, ol_number numeric NOT NULL, ol_delivery_d timestamp without time zone, ol_amount numeric) WITH (fillfactor='50');
ALTER TABLE with_modifying.order_line ADD CONSTRAINT order_line_i1 PRIMARY KEY (ol_w_id, ol_d_id, ol_o_id, ol_number);
SELECT create_distributed_table('orders', 'o_w_id');
SELECT create_distributed_table('order_line', 'ol_w_id');
INSERT INTO orders VALUES (1, 1, 1, 1), (2, 2, 2, 2), (3, 3, 3, 3);
INSERT INTO order_line VALUES (1, 1, 1, 10), (2, 2, 2, 20), (3, 3, 3, 30);
PREPARE olu(int,int[],int[]) AS
WITH order_line_update AS (
UPDATE order_line
SET ol_delivery_d = current_timestamp
FROM UNNEST($2, $3) AS ids(o_id, d_id)
WHERE ol_o_id = ids.o_id
AND ol_d_id = ids.d_id
AND ol_w_id = $1
RETURNING ol_d_id, ol_o_id, ol_amount
)
SELECT array_agg(ol_d_id), array_agg(c_id), array_agg(sum_amount)
FROM (
SELECT ol_d_id,
(SELECT DISTINCT o_c_id FROM orders WHERE o_id = ol_o_id AND o_d_id = ol_d_id AND o_w_id = $1) AS c_id,
sum(ol_amount) AS sum_amount
FROM order_line_update
GROUP BY ol_d_id, ol_o_id
) AS inner_sum;
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
EXECUTE olu(1,ARRAY[1,2],ARRAY[1,2]);
-- Test with replication factor 2 -- Test with replication factor 2
SET citus.shard_replication_factor to 2; SET citus.shard_replication_factor to 2;
@ -444,4 +524,20 @@ ROLLBACK;
WITH first_query AS (INSERT INTO modify_table (id) VALUES (10001)), WITH first_query AS (INSERT INTO modify_table (id) VALUES (10001)),
second_query AS (SELECT * FROM modify_table) SELECT count(*) FROM second_query; second_query AS (SELECT * FROM modify_table) SELECT count(*) FROM second_query;
SET client_min_messages TO debug2;
-- pushed down without the insert
WITH mb AS (UPDATE modify_table SET val = 3 WHERE id = 3 RETURNING NULL) INSERT INTO modify_table WITH ma AS (SELECT * FROM modify_table LIMIT 10) SELECT count(*) FROM mb;
-- not pushed down due to volatile
WITH ma AS (SELECT count(*) FROM modify_table where id = 1), mu AS (WITH allref AS (SELECT random() a FROM modify_table limit 4) UPDATE modify_table SET val = 3 WHERE id = 1 AND val IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu, ma;
WITH mu AS (WITH allref AS (SELECT random() a FROM anchor_table) UPDATE modify_table SET val = 3 WHERE id = 1 AND val IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu;
-- pushed down
WITH mu AS (WITH allref AS (SELECT id a FROM anchor_table) UPDATE modify_table SET val = 3 WHERE id = 1 AND val IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu;
-- pushed down and stable function evaluated
WITH mu AS (WITH allref AS (SELECT now() a FROM anchor_table) UPDATE modify_table SET val = 3 WHERE id = 1 AND now() IN (SELECT a FROM allref) RETURNING id+1) SELECT count(*) FROM mu;
RESET client_min_messages;
\set VERBOSITY terse
DROP SCHEMA with_modifying CASCADE; DROP SCHEMA with_modifying CASCADE;

View File

@ -198,6 +198,33 @@ FROM
WHERE WHERE
events_user_id IN (SELECT user_id FROM users_table); events_user_id IN (SELECT user_id FROM users_table);
-- Prepare routable modifying CTEs
PREPARE prepared_test_7 AS
WITH basic_delete AS (
DELETE FROM users_table WHERE user_id=6 RETURNING *
)
SELECT
*
FROM
basic_delete
ORDER BY
user_id,
time
LIMIT 10;
PREPARE prepared_test_8 AS
WITH basic_delete AS (
UPDATE users_table SET value_1 = value_1 + 1 WHERE user_id=6 RETURNING *
)
SELECT
*
FROM
basic_delete
ORDER BY
user_id,
time
LIMIT 10;
EXECUTE prepared_test_1; EXECUTE prepared_test_1;
EXECUTE prepared_test_1; EXECUTE prepared_test_1;
EXECUTE prepared_test_1; EXECUTE prepared_test_1;
@ -240,6 +267,40 @@ EXECUTE prepared_test_6;
EXECUTE prepared_test_6; EXECUTE prepared_test_6;
EXECUTE prepared_test_6; EXECUTE prepared_test_6;
BEGIN;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
ROLLBACK;
BEGIN;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
EXECUTE prepared_test_7;
ROLLBACK;
BEGIN;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
ROLLBACK;
BEGIN;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
EXECUTE prepared_test_8;
ROLLBACK;
EXECUTE prepared_partition_column_insert(1); EXECUTE prepared_partition_column_insert(1);
EXECUTE prepared_partition_column_insert(2); EXECUTE prepared_partition_column_insert(2);
EXECUTE prepared_partition_column_insert(3); EXECUTE prepared_partition_column_insert(3);