mirror of https://github.com/citusdata/citus.git
Merge pull request #3654 from citusdata/2776_modifying_ctes
Modifying ctes in router plannerpull/3903/head
commit
f344c1a4bc
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
@ -511,7 +511,12 @@ ResultRelationOidForQuery(Query *query)
|
||||||
RangeTblEntry *
|
RangeTblEntry *
|
||||||
ExtractResultRelationRTE(Query *query)
|
ExtractResultRelationRTE(Query *query)
|
||||||
{
|
{
|
||||||
return rt_fetch(query->resultRelation, query->rtable);
|
if (query->resultRelation > 0)
|
||||||
|
{
|
||||||
|
return rt_fetch(query->resultRelation, query->rtable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
"Router planner doesn't support non-select common table expressions with non-select queries.",
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
"Router planner doesn't support non-select common table expressions.",
|
"Router planner doesn't support INSERT common table expressions.",
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cteQuery->hasForUpdate)
|
|
||||||
|
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,14 +640,184 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeferredErrorMessage *cteError = MultiRouterPlannableQuery(cteQuery);
|
if (cteQuery->commandType == CMD_SELECT)
|
||||||
if (cteError)
|
|
||||||
{
|
{
|
||||||
return cteError;
|
DeferredErrorMessage *cteError = MultiRouterPlannableQuery(cteQuery);
|
||||||
|
if (cteError)
|
||||||
|
{
|
||||||
|
return cteError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
* path queries because their definition is a single RTE entry, which is a relation,
|
* path queries because their definition is a single RTE entry, which is a relation,
|
||||||
|
@ -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,10 +1715,10 @@ 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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queries to reference tables, or distributed tables with multiple replica's have
|
* Queries to reference tables, or distributed tables with multiple replica's have
|
||||||
|
@ -1693,10 +1742,10 @@ 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 */
|
||||||
|
|
|
@ -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);
|
masterEvaluationContext.evaluationMode = EVALUATE_PARAMS;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
masterEvaluationContext.evaluationMode = EVALUATE_FUNCTIONS_PARAMS;
|
||||||
* 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;
|
|
||||||
|
|
||||||
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* */
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -2,30 +2,30 @@ Parsed test spec with 2 sessions
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-t2-for-update s2-begin s2-update-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-t2-for-update s2-begin s2-update-t1 s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-t2-for-update:
|
step s1-select-from-t1-t2-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN test_table_2_rf1 as tt2 on tt1.id = tt2.id
|
test_table_1_rf1 as tt1 INNER JOIN test_table_2_rf1 as tt2 on tt1.id = tt2.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE;
|
FOR UPDATE;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-t1:
|
step s2-update-t1:
|
||||||
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-t1: <... completed>
|
step s2-update-t1: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -33,30 +33,30 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-t2-for-share s2-begin s2-delete-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-t2-for-share s2-begin s2-delete-t1 s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-t2-for-share:
|
step s1-select-from-t1-t2-for-share:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN test_table_2_rf1 as tt2 on tt1.id = tt2.id
|
test_table_1_rf1 as tt1 INNER JOIN test_table_2_rf1 as tt2 on tt1.id = tt2.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR SHARE;
|
FOR SHARE;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-delete-t1:
|
step s2-delete-t1:
|
||||||
DELETE FROM test_table_1_rf1 WHERE id = 1;
|
DELETE FROM test_table_1_rf1 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-delete-t1: <... completed>
|
step s2-delete-t1: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -64,30 +64,30 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-rt-for-update s2-begin s2-update-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-rt-for-update s2-begin s2-update-t1 s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-rt-for-update:
|
step s1-select-from-t1-rt-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE;
|
FOR UPDATE;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-t1:
|
step s2-update-t1:
|
||||||
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-t1: <... completed>
|
step s2-update-t1: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -95,31 +95,31 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-rt-with-lc-for-update s2-begin s2-update-rt s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-rt-with-lc-for-update s2-begin s2-update-rt s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-rt-with-lc-for-update:
|
step s1-select-from-t1-rt-with-lc-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE
|
FOR UPDATE
|
||||||
OF rt1;
|
OF rt1;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-rt:
|
step s2-update-rt:
|
||||||
UPDATE ref_table SET val_1 = 5 WHERE id = 1;
|
UPDATE ref_table SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-rt: <... completed>
|
step s2-update-rt: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -127,30 +127,30 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-rt-with-lc-for-update s2-begin s2-update-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-rt-with-lc-for-update s2-begin s2-update-t1 s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-rt-with-lc-for-update:
|
step s1-select-from-t1-rt-with-lc-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE
|
FOR UPDATE
|
||||||
OF rt1;
|
OF rt1;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-t1:
|
step s2-update-t1:
|
||||||
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
||||||
|
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -158,36 +158,36 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-t2-for-share s2-begin s2-select-from-t1-t2-for-share s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-t2-for-share s2-begin s2-select-from-t1-t2-for-share s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-t2-for-share:
|
step s1-select-from-t1-t2-for-share:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN test_table_2_rf1 as tt2 on tt1.id = tt2.id
|
test_table_1_rf1 as tt1 INNER JOIN test_table_2_rf1 as tt2 on tt1.id = tt2.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR SHARE;
|
FOR SHARE;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-select-from-t1-t2-for-share:
|
step s2-select-from-t1-t2-for-share:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN test_table_1_rf1 as tt2 on tt1.id = tt2.id
|
test_table_1_rf1 as tt1 INNER JOIN test_table_1_rf1 as tt2 on tt1.id = tt2.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR SHARE;
|
FOR SHARE;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -195,37 +195,37 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-rt-for-update s2-begin s2-select-from-t1-t2-for-update s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-rt-for-update s2-begin s2-select-from-t1-t2-for-update s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-rt-for-update:
|
step s1-select-from-t1-rt-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
test_table_1_rf1 as tt1 INNER JOIN ref_table as rt1 on tt1.id = rt1.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE;
|
FOR UPDATE;
|
||||||
|
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-select-from-t1-t2-for-update:
|
step s2-select-from-t1-t2-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN test_table_1_rf1 as tt2 on tt1.id = tt2.id
|
test_table_1_rf1 as tt1 INNER JOIN test_table_1_rf1 as tt2 on tt1.id = tt2.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE;
|
FOR UPDATE;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-select-from-t1-t2-for-update: <... completed>
|
step s2-select-from-t1-t2-for-update: <... completed>
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -233,34 +233,34 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-within-cte s2-begin s2-select-from-t1-t2-for-update s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-within-cte s2-begin s2-select-from-t1-t2-for-update s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
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
|
||||||
|
|
||||||
2
|
2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-select-from-t1-t2-for-update:
|
step s2-select-from-t1-t2-for-update:
|
||||||
SELECT * FROM
|
SELECT * FROM
|
||||||
test_table_1_rf1 as tt1 INNER JOIN test_table_1_rf1 as tt2 on tt1.id = tt2.id
|
test_table_1_rf1 as tt1 INNER JOIN test_table_1_rf1 as tt2 on tt1.id = tt2.id
|
||||||
WHERE tt1.id = 1
|
WHERE tt1.id = 1
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
FOR UPDATE;
|
FOR UPDATE;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-select-from-t1-t2-for-update: <... completed>
|
step s2-select-from-t1-t2-for-update: <... completed>
|
||||||
id val_1 id val_1
|
id val_1 id val_1
|
||||||
|
|
||||||
1 2 1 2
|
1 2 1 2
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -268,27 +268,27 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-within-cte s2-begin s2-update-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-within-cte s2-begin s2-update-t1 s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
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
|
||||||
|
|
||||||
2
|
2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-t1:
|
step s2-update-t1:
|
||||||
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-t1: <... completed>
|
step s2-update-t1: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -296,26 +296,31 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-with-subquery s2-begin s2-update-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-with-subquery s2-begin s2-update-t1 s1-commit s2-commit
|
||||||
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:
|
||||||
SELECT * FROM (SELECT * FROM test_table_1_rf1 FOR UPDATE) foo WHERE id = 1;
|
SET client_min_messages TO DEBUG2;
|
||||||
|
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
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-t1:
|
step s2-update-t1:
|
||||||
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-t1: <... completed>
|
step s2-update-t1: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -323,26 +328,26 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-rt-with-subquery s2-begin s2-update-rt s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-rt-with-subquery s2-begin s2-update-rt s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-rt-with-subquery:
|
step s1-select-from-rt-with-subquery:
|
||||||
SELECT * FROM (SELECT * FROM ref_table FOR UPDATE) foo WHERE id = 1;
|
SELECT * FROM (SELECT * FROM ref_table FOR UPDATE) foo WHERE id = 1;
|
||||||
|
|
||||||
id val_1
|
id val_1
|
||||||
|
|
||||||
1 2
|
1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-rt:
|
step s2-update-rt:
|
||||||
UPDATE ref_table SET val_1 = 5 WHERE id = 1;
|
UPDATE ref_table SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-rt: <... completed>
|
step s2-update-rt: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -350,26 +355,26 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-select-from-t1-with-view s2-begin s2-update-t1 s1-commit s2-commit
|
starting permutation: s1-begin s1-select-from-t1-with-view s2-begin s2-update-t1 s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s1-select-from-t1-with-view:
|
step s1-select-from-t1-with-view:
|
||||||
SELECT * FROM test_1 WHERE id = 1 FOR UPDATE;
|
SELECT * FROM test_1 WHERE id = 1 FOR UPDATE;
|
||||||
|
|
||||||
id val_1
|
id val_1
|
||||||
|
|
||||||
1 2
|
1 2
|
||||||
step s2-begin:
|
step s2-begin:
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
step s2-update-t1:
|
step s2-update-t1:
|
||||||
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
UPDATE test_table_1_rf1 SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-t1: <... completed>
|
step s2-update-t1: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
@ -377,24 +382,24 @@ restore_isolation_tester_func
|
||||||
|
|
||||||
starting permutation: s1-begin s1-update-rt-with-cte-select-from-rt s2-begin s2-update-rt s1-commit s2-commit
|
starting permutation: s1-begin s1-update-rt-with-cte-select-from-rt s2-begin s2-update-rt s1-commit s2-commit
|
||||||
step s1-begin:
|
step s1-begin:
|
||||||
BEGIN;
|
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;
|
||||||
|
|
||||||
step s2-update-rt:
|
step s2-update-rt:
|
||||||
UPDATE ref_table SET val_1 = 5 WHERE id = 1;
|
UPDATE ref_table SET val_1 = 5 WHERE id = 1;
|
||||||
<waiting ...>
|
<waiting ...>
|
||||||
step s1-commit:
|
step s1-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
step s2-update-rt: <... completed>
|
step s2-update-rt: <... completed>
|
||||||
step s2-commit:
|
step s2-commit:
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
restore_isolation_tester_func
|
restore_isolation_tester_func
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
@ -192,13 +193,13 @@ INSERT INTO modify_table (SELECT cte_1.user_id FROM cte_1 join cte_2 on cte_1.va
|
||||||
-- between different executors
|
-- between different executors
|
||||||
CREATE FUNCTION raise_failed_execution_cte(query text) RETURNS void AS $$
|
CREATE FUNCTION raise_failed_execution_cte(query text) RETURNS void AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
EXECUTE query;
|
EXECUTE query;
|
||||||
EXCEPTION WHEN OTHERS THEN
|
EXCEPTION WHEN OTHERS THEN
|
||||||
IF SQLERRM LIKE '%more than one row returned by a subquery used as an expression%' THEN
|
IF SQLERRM LIKE '%more than one row returned by a subquery used as an expression%' THEN
|
||||||
RAISE 'Task failed to execute';
|
RAISE 'Task failed to execute';
|
||||||
ELSIF SQLERRM LIKE '%could not receive query results%' THEN
|
ELSIF SQLERRM LIKE '%could not receive query results%' THEN
|
||||||
RAISE 'Task failed to execute';
|
RAISE 'Task failed to execute';
|
||||||
END IF;
|
END IF;
|
||||||
END;
|
END;
|
||||||
$$LANGUAGE plpgsql;
|
$$LANGUAGE plpgsql;
|
||||||
SET client_min_messages TO ERROR;
|
SET client_min_messages TO ERROR;
|
||||||
|
@ -378,11 +379,11 @@ INSERT INTO summary_table SELECT id, COUNT(*) AS counter FROM raw_data GROUP BY
|
||||||
INSERT INTO modify_table VALUES (21, 1), (22, 2), (23, 3);
|
INSERT INTO modify_table VALUES (21, 1), (22, 2), (23, 3);
|
||||||
-- read ids from the same table
|
-- read ids from the same table
|
||||||
WITH distinct_ids AS (
|
WITH distinct_ids AS (
|
||||||
SELECT DISTINCT id FROM modify_table
|
SELECT DISTINCT id FROM modify_table
|
||||||
),
|
),
|
||||||
update_data AS (
|
update_data AS (
|
||||||
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
||||||
id IN (SELECT * FROM distinct_ids) RETURNING *
|
id IN (SELECT * FROM distinct_ids) RETURNING *
|
||||||
)
|
)
|
||||||
SELECT count(*) FROM update_data;
|
SELECT count(*) FROM update_data;
|
||||||
count
|
count
|
||||||
|
@ -392,11 +393,11 @@ SELECT count(*) FROM update_data;
|
||||||
|
|
||||||
-- read ids from a different table
|
-- read ids from a different table
|
||||||
WITH distinct_ids AS (
|
WITH distinct_ids AS (
|
||||||
SELECT DISTINCT id FROM summary_table
|
SELECT DISTINCT id FROM summary_table
|
||||||
),
|
),
|
||||||
update_data AS (
|
update_data AS (
|
||||||
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
||||||
id IN (SELECT * FROM distinct_ids) RETURNING *
|
id IN (SELECT * FROM distinct_ids) RETURNING *
|
||||||
)
|
)
|
||||||
SELECT count(*) FROM update_data;
|
SELECT count(*) FROM update_data;
|
||||||
count
|
count
|
||||||
|
@ -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;
|
||||||
|
@ -730,17 +882,88 @@ BEGIN;
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- similarly, make sure that the intermediate result uses a seperate connection
|
-- similarly, make sure that the intermediate result uses a seperate connection
|
||||||
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;
|
||||||
count
|
count
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
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
|
|
||||||
|
|
|
@ -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
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
|
|
|
@ -76,19 +76,21 @@ 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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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');
|
||||||
|
|
||||||
|
@ -113,13 +115,13 @@ INSERT INTO modify_table (SELECT cte_1.user_id FROM cte_1 join cte_2 on cte_1.va
|
||||||
-- between different executors
|
-- between different executors
|
||||||
CREATE FUNCTION raise_failed_execution_cte(query text) RETURNS void AS $$
|
CREATE FUNCTION raise_failed_execution_cte(query text) RETURNS void AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
EXECUTE query;
|
EXECUTE query;
|
||||||
EXCEPTION WHEN OTHERS THEN
|
EXCEPTION WHEN OTHERS THEN
|
||||||
IF SQLERRM LIKE '%more than one row returned by a subquery used as an expression%' THEN
|
IF SQLERRM LIKE '%more than one row returned by a subquery used as an expression%' THEN
|
||||||
RAISE 'Task failed to execute';
|
RAISE 'Task failed to execute';
|
||||||
ELSIF SQLERRM LIKE '%could not receive query results%' THEN
|
ELSIF SQLERRM LIKE '%could not receive query results%' THEN
|
||||||
RAISE 'Task failed to execute';
|
RAISE 'Task failed to execute';
|
||||||
END IF;
|
END IF;
|
||||||
END;
|
END;
|
||||||
$$LANGUAGE plpgsql;
|
$$LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
@ -236,21 +238,21 @@ INSERT INTO modify_table VALUES (21, 1), (22, 2), (23, 3);
|
||||||
|
|
||||||
-- read ids from the same table
|
-- read ids from the same table
|
||||||
WITH distinct_ids AS (
|
WITH distinct_ids AS (
|
||||||
SELECT DISTINCT id FROM modify_table
|
SELECT DISTINCT id FROM modify_table
|
||||||
),
|
),
|
||||||
update_data AS (
|
update_data AS (
|
||||||
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
||||||
id IN (SELECT * FROM distinct_ids) RETURNING *
|
id IN (SELECT * FROM distinct_ids) RETURNING *
|
||||||
)
|
)
|
||||||
SELECT count(*) FROM update_data;
|
SELECT count(*) FROM update_data;
|
||||||
|
|
||||||
-- read ids from a different table
|
-- read ids from a different table
|
||||||
WITH distinct_ids AS (
|
WITH distinct_ids AS (
|
||||||
SELECT DISTINCT id FROM summary_table
|
SELECT DISTINCT id FROM summary_table
|
||||||
),
|
),
|
||||||
update_data AS (
|
update_data AS (
|
||||||
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
UPDATE modify_table SET val = 100 WHERE id > 10 AND
|
||||||
id IN (SELECT * FROM distinct_ids) RETURNING *
|
id IN (SELECT * FROM distinct_ids) RETURNING *
|
||||||
)
|
)
|
||||||
SELECT count(*) FROM update_data;
|
SELECT count(*) FROM update_data;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -441,7 +521,23 @@ BEGIN;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
-- similarly, make sure that the intermediate result uses a seperate connection
|
-- similarly, make sure that the intermediate result uses a seperate connection
|
||||||
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue