mirror of https://github.com/citusdata/citus.git
Make router planner error handling more flexible.
So far router planner had encapsulated different functionality in MultiRouterPlanCreate. Modifications always go through router, selects sometimes. Modifications always error out if the query is unsupported, selects return NULL. Especially the error handling is a problem for the upcoming extension of prepared statement support. Split MultiRouterPlanCreate into CreateRouterPlan and CreateModifyPlan, and change them to not throw errors. Instead errors are now reported by setting the new MultiPlan->plannigError. Callers of router planner functionality now have to throw errors themselves if desired, but also can skip doing so. This is a pre-requisite for expanding prepared statement support. While touching all those lines, improve a number of error messages by getting them closer to the postgres error message guidelines.pull/1134/head
parent
7681f6ab9d
commit
c244b8ef4a
|
@ -139,7 +139,11 @@ master_modify_multiple_shards(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
if (modifyQuery->commandType != CMD_UTILITY)
|
if (modifyQuery->commandType != CMD_UTILITY)
|
||||||
{
|
{
|
||||||
ErrorIfModifyQueryNotSupported(modifyQuery);
|
DeferredErrorMessage *error = ModifyQuerySupported(modifyQuery);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
RaiseDeferredError(error, ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reject queries with a returning list */
|
/* reject queries with a returning list */
|
||||||
|
|
|
@ -120,40 +120,94 @@ multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IsModifyCommand returns true if the query performs modifications, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
IsModifyCommand(Query *query)
|
||||||
|
{
|
||||||
|
CmdType commandType = query->commandType;
|
||||||
|
|
||||||
|
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
|
||||||
|
commandType == CMD_DELETE || query->hasModifyingCTE)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CreateDistributedPlan encapsulates the logic needed to transform a particular
|
* CreateDistributedPlan encapsulates the logic needed to transform a particular
|
||||||
* query into a distributed plan. For modifications, queries immediately enter
|
* query into a distributed plan.
|
||||||
* the physical planning stage, since they are essentially "routed" to remote
|
|
||||||
* target shards. SELECT queries go through the full logical plan/optimize/
|
|
||||||
* physical plan process needed to produce distributed query plans.
|
|
||||||
*/
|
*/
|
||||||
static PlannedStmt *
|
static PlannedStmt *
|
||||||
CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query,
|
CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query,
|
||||||
RelationRestrictionContext *restrictionContext)
|
RelationRestrictionContext *restrictionContext)
|
||||||
{
|
{
|
||||||
MultiPlan *physicalPlan = MultiRouterPlanCreate(originalQuery, query,
|
MultiPlan *distributedPlan = NULL;
|
||||||
restrictionContext);
|
|
||||||
if (physicalPlan == NULL)
|
if (IsModifyCommand(query))
|
||||||
{
|
{
|
||||||
/* Create and optimize logical plan */
|
|
||||||
MultiTreeRoot *logicalPlan = MultiLogicalPlanCreate(query);
|
|
||||||
MultiLogicalPlanOptimize(logicalPlan);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This check is here to make it likely that all node types used in
|
* Modifications are always routed through the same
|
||||||
* Citus are dumpable. Explain can dump logical and physical plans
|
* planner/executor. As there's currently no other way to plan these,
|
||||||
* using the extended outfuncs infrastructure, but it's infeasible to
|
* error out if the query is unsupported.
|
||||||
* test most plans. MultiQueryContainerNode always serializes the
|
|
||||||
* physical plan, so there's no need to check that separately.
|
|
||||||
*/
|
*/
|
||||||
CheckNodeIsDumpable((Node *) logicalPlan);
|
distributedPlan = CreateModifyPlan(originalQuery, query, restrictionContext);
|
||||||
|
Assert(distributedPlan);
|
||||||
|
if (distributedPlan->planningError)
|
||||||
|
{
|
||||||
|
RaiseDeferredError(distributedPlan->planningError, ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For select queries we, if router executor is enabled, first try to
|
||||||
|
* plan the query as a router query. If not supported, otherwise try
|
||||||
|
* the full blown plan/optimize/physical planing process needed to
|
||||||
|
* produce distributed query plans.
|
||||||
|
*/
|
||||||
|
if (EnableRouterExecution)
|
||||||
|
{
|
||||||
|
distributedPlan = CreateRouterPlan(originalQuery, query, restrictionContext);
|
||||||
|
|
||||||
/* Create the physical plan */
|
/* for debugging it's useful to display why query was not router plannable */
|
||||||
physicalPlan = MultiPhysicalPlanCreate(logicalPlan);
|
if (distributedPlan && distributedPlan->planningError)
|
||||||
|
{
|
||||||
|
RaiseDeferredError(distributedPlan->planningError, DEBUG1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* router didn't yield a plan, try the full distributed planner */
|
||||||
|
if (!distributedPlan || distributedPlan->planningError)
|
||||||
|
{
|
||||||
|
/* Create and optimize logical plan */
|
||||||
|
MultiTreeRoot *logicalPlan = MultiLogicalPlanCreate(query);
|
||||||
|
MultiLogicalPlanOptimize(logicalPlan);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This check is here to make it likely that all node types used in
|
||||||
|
* Citus are dumpable. Explain can dump logical and physical plans
|
||||||
|
* using the extended outfuncs infrastructure, but it's infeasible to
|
||||||
|
* test most plans. MultiQueryContainerNode always serializes the
|
||||||
|
* physical plan, so there's no need to check that separately.
|
||||||
|
*/
|
||||||
|
CheckNodeIsDumpable((Node *) logicalPlan);
|
||||||
|
|
||||||
|
/* Create the physical plan */
|
||||||
|
distributedPlan = MultiPhysicalPlanCreate(logicalPlan);
|
||||||
|
|
||||||
|
/* distributed plan currently should always succeed or error out */
|
||||||
|
Assert(distributedPlan && distributedPlan->planningError == NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store required data into the planned statement */
|
/* store required data into the planned statement */
|
||||||
return MultiQueryContainerNode(localPlan, physicalPlan);
|
return MultiQueryContainerNode(localPlan, distributedPlan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "distributed/citus_nodefuncs.h"
|
#include "distributed/citus_nodefuncs.h"
|
||||||
#include "distributed/deparse_shard_query.h"
|
#include "distributed/deparse_shard_query.h"
|
||||||
#include "distributed/distribution_column.h"
|
#include "distributed/distribution_column.h"
|
||||||
|
#include "distributed/errormessage.h"
|
||||||
#include "distributed/master_metadata_utility.h"
|
#include "distributed/master_metadata_utility.h"
|
||||||
#include "distributed/master_protocol.h"
|
#include "distributed/master_protocol.h"
|
||||||
#include "distributed/metadata_cache.h"
|
#include "distributed/metadata_cache.h"
|
||||||
|
@ -74,7 +75,8 @@ typedef struct WalkerState
|
||||||
bool EnableRouterExecution = true;
|
bool EnableRouterExecution = true;
|
||||||
|
|
||||||
/* planner functions forward declarations */
|
/* planner functions forward declarations */
|
||||||
static MultiPlan * CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
static MultiPlan * CreateSingleTaskRouterPlan(Query *originalQuery,
|
||||||
|
Query *query,
|
||||||
RelationRestrictionContext *
|
RelationRestrictionContext *
|
||||||
restrictionContext);
|
restrictionContext);
|
||||||
static MultiPlan * CreateInsertSelectRouterPlan(Query *originalQuery,
|
static MultiPlan * CreateInsertSelectRouterPlan(Query *originalQuery,
|
||||||
|
@ -114,58 +116,64 @@ static bool MultiRouterPlannableQuery(Query *query,
|
||||||
static RelationRestrictionContext * CopyRelationRestrictionContext(
|
static RelationRestrictionContext * CopyRelationRestrictionContext(
|
||||||
RelationRestrictionContext *oldContext);
|
RelationRestrictionContext *oldContext);
|
||||||
static Node * InstantiatePartitionQual(Node *node, void *context);
|
static Node * InstantiatePartitionQual(Node *node, void *context);
|
||||||
static void ErrorIfInsertSelectQueryNotSupported(Query *queryTree,
|
static DeferredErrorMessage * InsertSelectQuerySupported(Query *queryTree,
|
||||||
RangeTblEntry *insertRte,
|
RangeTblEntry *insertRte,
|
||||||
RangeTblEntry *subqueryRte,
|
RangeTblEntry *subqueryRte,
|
||||||
bool allReferenceTables);
|
bool allReferenceTables);
|
||||||
static void ErrorIfMultiTaskRouterSelectQueryUnsupported(Query *query);
|
static DeferredErrorMessage * MultiTaskRouterSelectQuerySupported(Query *query);
|
||||||
static void ErrorIfInsertPartitionColumnDoesNotMatchSelect(Query *query,
|
static DeferredErrorMessage * InsertPartitionColumnMatchesSelect(Query *query,
|
||||||
RangeTblEntry *insertRte,
|
RangeTblEntry *insertRte,
|
||||||
RangeTblEntry *subqueryRte,
|
RangeTblEntry *
|
||||||
Oid *
|
subqueryRte,
|
||||||
selectPartitionColumnTableId);
|
Oid *
|
||||||
|
selectPartitionColumnTableId);
|
||||||
static void AddUninstantiatedEqualityQual(Query *query, Var *targetPartitionColumnVar);
|
static void AddUninstantiatedEqualityQual(Query *query, Var *targetPartitionColumnVar);
|
||||||
static void ErrorIfQueryHasModifyingCTE(Query *queryTree);
|
static DeferredErrorMessage * ErrorIfQueryHasModifyingCTE(Query *queryTree);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MultiRouterPlanCreate creates a multi plan for the queries
|
* CreateRouterPlan attempts to create a router executor plan for the given
|
||||||
* that includes the following:
|
* SELECT statement. If planning fails either NULL is returned, or
|
||||||
* (i) modification queries that hit a single shard
|
* ->planningError is set to a description of the failure.
|
||||||
* (ii) select queries hat can be executed on a single worker
|
|
||||||
* node and does not require any operations on the master node.
|
|
||||||
* (iii) INSERT INTO .... SELECT queries
|
|
||||||
*
|
|
||||||
* The function returns NULL if it cannot create the plan for SELECT
|
|
||||||
* queries and errors out if it cannot plan the modify queries.
|
|
||||||
*/
|
*/
|
||||||
MultiPlan *
|
MultiPlan *
|
||||||
MultiRouterPlanCreate(Query *originalQuery, Query *query,
|
CreateRouterPlan(Query *originalQuery, Query *query,
|
||||||
RelationRestrictionContext *restrictionContext)
|
RelationRestrictionContext *restrictionContext)
|
||||||
{
|
{
|
||||||
MultiPlan *multiPlan = NULL;
|
Assert(EnableRouterExecution);
|
||||||
|
|
||||||
bool routerPlannable = MultiRouterPlannableQuery(query, restrictionContext);
|
if (MultiRouterPlannableQuery(query, restrictionContext))
|
||||||
if (!routerPlannable)
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return CreateSingleTaskRouterPlan(originalQuery, query,
|
||||||
|
restrictionContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Instead have MultiRouterPlannableQuery set an error describing
|
||||||
|
* why router cannot support the query.
|
||||||
|
*/
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CreateModifyPlan attempts to create a plan the given modification
|
||||||
|
* statement. If planning fails ->planningError is set to a description of
|
||||||
|
* the failure.
|
||||||
|
*/
|
||||||
|
MultiPlan *
|
||||||
|
CreateModifyPlan(Query *originalQuery, Query *query,
|
||||||
|
RelationRestrictionContext *restrictionContext)
|
||||||
|
{
|
||||||
if (InsertSelectQuery(originalQuery))
|
if (InsertSelectQuery(originalQuery))
|
||||||
{
|
{
|
||||||
multiPlan = CreateInsertSelectRouterPlan(originalQuery, restrictionContext);
|
return CreateInsertSelectRouterPlan(originalQuery, restrictionContext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
multiPlan = CreateSingleTaskRouterPlan(originalQuery, query, restrictionContext);
|
return CreateSingleTaskRouterPlan(originalQuery, query,
|
||||||
|
restrictionContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* plans created by router planner are always router executable */
|
|
||||||
if (multiPlan != NULL)
|
|
||||||
{
|
|
||||||
multiPlan->routerExecutable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return multiPlan;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,8 +181,8 @@ MultiRouterPlanCreate(Query *originalQuery, Query *query,
|
||||||
* CreateSingleTaskRouterPlan creates a physical plan for given query. The created plan is
|
* CreateSingleTaskRouterPlan creates a physical plan for given query. The created plan is
|
||||||
* either a modify task that changes a single shard, or a router task that returns
|
* either a modify task that changes a single shard, or a router task that returns
|
||||||
* query results from a single worker. Supported modify queries (insert/update/delete)
|
* query results from a single worker. Supported modify queries (insert/update/delete)
|
||||||
* are router plannable by default. If query is not router plannable then the function
|
* are router plannable by default. If query is not router plannable then either NULL is
|
||||||
* returns NULL.
|
* returned, or the returned plan has planningError set to a description of the problem.
|
||||||
*/
|
*/
|
||||||
static MultiPlan *
|
static MultiPlan *
|
||||||
CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
||||||
|
@ -185,7 +193,7 @@ CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
||||||
Job *job = NULL;
|
Job *job = NULL;
|
||||||
Task *task = NULL;
|
Task *task = NULL;
|
||||||
List *placementList = NIL;
|
List *placementList = NIL;
|
||||||
MultiPlan *multiPlan = NULL;
|
MultiPlan *multiPlan = CitusMakeNode(MultiPlan);
|
||||||
|
|
||||||
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
|
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
|
||||||
commandType == CMD_DELETE)
|
commandType == CMD_DELETE)
|
||||||
|
@ -195,12 +203,23 @@ CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
||||||
|
|
||||||
if (modifyTask)
|
if (modifyTask)
|
||||||
{
|
{
|
||||||
ErrorIfModifyQueryNotSupported(query);
|
/* FIXME: this should probably rather be inlined into CreateModifyPlan */
|
||||||
|
multiPlan->planningError = ModifyQuerySupported(query);
|
||||||
|
if (multiPlan->planningError)
|
||||||
|
{
|
||||||
|
return multiPlan;
|
||||||
|
}
|
||||||
task = RouterModifyTask(originalQuery, query);
|
task = RouterModifyTask(originalQuery, query);
|
||||||
|
Assert(task);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ErrorIfQueryHasModifyingCTE(query);
|
/* FIXME: this should probably rather be inlined into CreateSelectPlan */
|
||||||
|
multiPlan->planningError = ErrorIfQueryHasModifyingCTE(query);
|
||||||
|
if (multiPlan->planningError)
|
||||||
|
{
|
||||||
|
return multiPlan;
|
||||||
|
}
|
||||||
task = RouterSelectTask(originalQuery, restrictionContext, &placementList);
|
task = RouterSelectTask(originalQuery, restrictionContext, &placementList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,10 +232,10 @@ CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
||||||
|
|
||||||
job = RouterQueryJob(originalQuery, task, placementList);
|
job = RouterQueryJob(originalQuery, task, placementList);
|
||||||
|
|
||||||
multiPlan = CitusMakeNode(MultiPlan);
|
|
||||||
multiPlan->workerJob = job;
|
multiPlan->workerJob = job;
|
||||||
multiPlan->masterQuery = NULL;
|
multiPlan->masterQuery = NULL;
|
||||||
multiPlan->masterTableName = NULL;
|
multiPlan->masterTableName = NULL;
|
||||||
|
multiPlan->routerExecutable = true;
|
||||||
|
|
||||||
return multiPlan;
|
return multiPlan;
|
||||||
}
|
}
|
||||||
|
@ -237,7 +256,7 @@ CreateInsertSelectRouterPlan(Query *originalQuery,
|
||||||
uint32 taskIdIndex = 1; /* 0 is reserved for invalid taskId */
|
uint32 taskIdIndex = 1; /* 0 is reserved for invalid taskId */
|
||||||
Job *workerJob = NULL;
|
Job *workerJob = NULL;
|
||||||
uint64 jobId = INVALID_JOB_ID;
|
uint64 jobId = INVALID_JOB_ID;
|
||||||
MultiPlan *multiPlan = NULL;
|
MultiPlan *multiPlan = CitusMakeNode(MultiPlan);
|
||||||
RangeTblEntry *insertRte = ExtractInsertRangeTableEntry(originalQuery);
|
RangeTblEntry *insertRte = ExtractInsertRangeTableEntry(originalQuery);
|
||||||
RangeTblEntry *subqueryRte = ExtractSelectRangeTableEntry(originalQuery);
|
RangeTblEntry *subqueryRte = ExtractSelectRangeTableEntry(originalQuery);
|
||||||
Oid targetRelationId = insertRte->relid;
|
Oid targetRelationId = insertRte->relid;
|
||||||
|
@ -249,8 +268,13 @@ CreateInsertSelectRouterPlan(Query *originalQuery,
|
||||||
* Error semantics for INSERT ... SELECT queries are different than regular
|
* Error semantics for INSERT ... SELECT queries are different than regular
|
||||||
* modify queries. Thus, handle separately.
|
* modify queries. Thus, handle separately.
|
||||||
*/
|
*/
|
||||||
ErrorIfInsertSelectQueryNotSupported(originalQuery, insertRte, subqueryRte,
|
multiPlan->planningError = InsertSelectQuerySupported(originalQuery, insertRte,
|
||||||
allReferenceTables);
|
subqueryRte,
|
||||||
|
allReferenceTables);
|
||||||
|
if (multiPlan->planningError)
|
||||||
|
{
|
||||||
|
return multiPlan;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Plan select query for each shard in the target table. Do so by replacing the
|
* Plan select query for each shard in the target table. Do so by replacing the
|
||||||
|
@ -291,10 +315,10 @@ CreateInsertSelectRouterPlan(Query *originalQuery,
|
||||||
workerJob->requiresMasterEvaluation = RequiresMasterEvaluation(originalQuery);
|
workerJob->requiresMasterEvaluation = RequiresMasterEvaluation(originalQuery);
|
||||||
|
|
||||||
/* and finally the multi plan */
|
/* and finally the multi plan */
|
||||||
multiPlan = CitusMakeNode(MultiPlan);
|
|
||||||
multiPlan->workerJob = workerJob;
|
multiPlan->workerJob = workerJob;
|
||||||
multiPlan->masterTableName = NULL;
|
multiPlan->masterTableName = NULL;
|
||||||
multiPlan->masterQuery = NULL;
|
multiPlan->masterQuery = NULL;
|
||||||
|
multiPlan->routerExecutable = true;
|
||||||
|
|
||||||
return multiPlan;
|
return multiPlan;
|
||||||
}
|
}
|
||||||
|
@ -628,18 +652,19 @@ ExtractInsertRangeTableEntry(Query *query)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ErrorIfInsertSelectQueryNotSupported errors out for unsupported
|
* InsertSelectQueryNotSupported returns NULL if the INSERT ... SELECT query
|
||||||
* INSERT ... SELECT queries.
|
* is supported, or a description why not.
|
||||||
*/
|
*/
|
||||||
static void
|
static DeferredErrorMessage *
|
||||||
ErrorIfInsertSelectQueryNotSupported(Query *queryTree, RangeTblEntry *insertRte,
|
InsertSelectQuerySupported(Query *queryTree, RangeTblEntry *insertRte,
|
||||||
RangeTblEntry *subqueryRte, bool allReferenceTables)
|
RangeTblEntry *subqueryRte, bool allReferenceTables)
|
||||||
{
|
{
|
||||||
Query *subquery = NULL;
|
Query *subquery = NULL;
|
||||||
Oid selectPartitionColumnTableId = InvalidOid;
|
Oid selectPartitionColumnTableId = InvalidOid;
|
||||||
Oid targetRelationId = insertRte->relid;
|
Oid targetRelationId = insertRte->relid;
|
||||||
char targetPartitionMethod = PartitionMethod(targetRelationId);
|
char targetPartitionMethod = PartitionMethod(targetRelationId);
|
||||||
ListCell *rangeTableCell = NULL;
|
ListCell *rangeTableCell = NULL;
|
||||||
|
DeferredErrorMessage *error = NULL;
|
||||||
|
|
||||||
/* we only do this check for INSERT ... SELECT queries */
|
/* we only do this check for INSERT ... SELECT queries */
|
||||||
AssertArg(InsertSelectQuery(queryTree));
|
AssertArg(InsertSelectQuery(queryTree));
|
||||||
|
@ -653,8 +678,9 @@ ErrorIfInsertSelectQueryNotSupported(Query *queryTree, RangeTblEntry *insertRte,
|
||||||
if (rangeTableEntry->rtekind == RTE_RELATION &&
|
if (rangeTableEntry->rtekind == RTE_RELATION &&
|
||||||
rangeTableEntry->relkind == RELKIND_VIEW)
|
rangeTableEntry->relkind == RELKIND_VIEW)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot insert into view over distributed table")));
|
"cannot insert into view over distributed table",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,15 +688,18 @@ ErrorIfInsertSelectQueryNotSupported(Query *queryTree, RangeTblEntry *insertRte,
|
||||||
|
|
||||||
if (contain_volatile_functions((Node *) queryTree))
|
if (contain_volatile_functions((Node *) queryTree))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"volatile functions are not allowed in INSERT ... SELECT "
|
||||||
"modification"),
|
"queries",
|
||||||
errdetail("Volatile functions are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we don't support LIMIT, OFFSET and WINDOW functions */
|
/* we don't support LIMIT, OFFSET and WINDOW functions */
|
||||||
ErrorIfMultiTaskRouterSelectQueryUnsupported(subquery);
|
error = MultiTaskRouterSelectQuerySupported(subquery);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're inserting into a reference table, all participating tables
|
* If we're inserting into a reference table, all participating tables
|
||||||
|
@ -680,18 +709,23 @@ ErrorIfInsertSelectQueryNotSupported(Query *queryTree, RangeTblEntry *insertRte,
|
||||||
{
|
{
|
||||||
if (!allReferenceTables)
|
if (!allReferenceTables)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("If data inserted into a reference table, "
|
"only reference tables may be queried when targeting "
|
||||||
"all of the participating tables in the "
|
"a reference table with INSERT ... SELECT",
|
||||||
"INSERT INTO ... SELECT query should be "
|
NULL, NULL);
|
||||||
"reference tables.")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DeferredErrorMessage *error = NULL;
|
||||||
|
|
||||||
/* ensure that INSERT's partition column comes from SELECT's partition column */
|
/* ensure that INSERT's partition column comes from SELECT's partition column */
|
||||||
ErrorIfInsertPartitionColumnDoesNotMatchSelect(queryTree, insertRte, subqueryRte,
|
error = InsertPartitionColumnMatchesSelect(queryTree, insertRte, subqueryRte,
|
||||||
&selectPartitionColumnTableId);
|
&selectPartitionColumnTableId);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We expect partition column values come from colocated tables. Note that we
|
* We expect partition column values come from colocated tables. Note that we
|
||||||
|
@ -700,22 +734,23 @@ ErrorIfInsertSelectQueryNotSupported(Query *queryTree, RangeTblEntry *insertRte,
|
||||||
*/
|
*/
|
||||||
if (!TablesColocated(insertRte->relid, selectPartitionColumnTableId))
|
if (!TablesColocated(insertRte->relid, selectPartitionColumnTableId))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("INSERT target table and the source relation "
|
"INSERT target table and the source relation of the SELECT partition "
|
||||||
"of the SELECT partition column value "
|
"column value must be colocated",
|
||||||
"must be colocated")));
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ErrorUnsupportedMultiTaskSelectQuery errors out on queries that we support
|
* MultiTaskRouterSelectQuerySupported returns NULL if the query may be used
|
||||||
* for single task router queries, but, cannot allow for multi task router
|
* as the source for an INSERT ... SELECT or returns a description why not.
|
||||||
* queries. We do these checks recursively to prevent any wrong results.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static DeferredErrorMessage *
|
||||||
ErrorIfMultiTaskRouterSelectQueryUnsupported(Query *query)
|
MultiTaskRouterSelectQuerySupported(Query *query)
|
||||||
{
|
{
|
||||||
List *queryList = NIL;
|
List *queryList = NIL;
|
||||||
ListCell *queryCell = NULL;
|
ListCell *queryCell = NULL;
|
||||||
|
@ -730,21 +765,19 @@ ErrorIfMultiTaskRouterSelectQueryUnsupported(Query *query)
|
||||||
/* pushing down limit per shard would yield wrong results */
|
/* pushing down limit per shard would yield wrong results */
|
||||||
if (subquery->limitCount != NULL)
|
if (subquery->limitCount != NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"LIMIT clauses are not allowed in INSERT ... SELECT "
|
||||||
"modification"),
|
"queries",
|
||||||
errdetail("LIMIT clauses are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pushing down limit offest per shard would yield wrong results */
|
/* pushing down limit offest per shard would yield wrong results */
|
||||||
if (subquery->limitOffset != NULL)
|
if (subquery->limitOffset != NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"OFFSET clauses are not allowed in INSERT ... SELECT "
|
||||||
"modification"),
|
"queries",
|
||||||
errdetail("OFFSET clauses are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -754,21 +787,19 @@ ErrorIfMultiTaskRouterSelectQueryUnsupported(Query *query)
|
||||||
*/
|
*/
|
||||||
if (subquery->windowClause != NULL)
|
if (subquery->windowClause != NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"window functions are not allowed in INSERT ... SELECT "
|
||||||
"modification"),
|
"queries",
|
||||||
errdetail("Window functions are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see comment on AddUninstantiatedPartitionRestriction() */
|
/* see comment on AddUninstantiatedPartitionRestriction() */
|
||||||
if (subquery->setOperations != NULL)
|
if (subquery->setOperations != NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"set operations are not allowed in INSERT ... SELECT "
|
||||||
"modification"),
|
"queries",
|
||||||
errdetail("Set operations are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -779,11 +810,10 @@ ErrorIfMultiTaskRouterSelectQueryUnsupported(Query *query)
|
||||||
*/
|
*/
|
||||||
if (subquery->groupingSets != NULL)
|
if (subquery->groupingSets != NULL)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"grouping sets are not allowed in INSERT ... SELECT "
|
||||||
"modification"),
|
"queries",
|
||||||
errdetail("Grouping sets are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -792,27 +822,29 @@ ErrorIfMultiTaskRouterSelectQueryUnsupported(Query *query)
|
||||||
*/
|
*/
|
||||||
if (subquery->hasDistinctOn)
|
if (subquery->hasDistinctOn)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"DISTINCT ON clauses are not allowed in "
|
||||||
"modification"),
|
"INSERT ... SELECT queries",
|
||||||
errdetail("DISTINCT ON clauses are not allowed in "
|
NULL, NULL);
|
||||||
"INSERT ... SELECT queries")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ErrorIfInsertPartitionColumnDoesNotMatchSelect checks whether the INSERTed table's
|
* InsertPartitionColumnMatchesSelect returns NULL the partition column in the
|
||||||
* partition column value matches with the any of the SELECTed table's partition column.
|
* table targeted by INSERTed matches with the any of the SELECTed table's
|
||||||
|
* partition column. Returns the error description if there's no match.
|
||||||
*
|
*
|
||||||
* On return without error (i.e., if partition columns match), the function also sets
|
* On return without error (i.e., if partition columns match), the function
|
||||||
* selectPartitionColumnTableId.
|
* also sets selectPartitionColumnTableId.
|
||||||
*/
|
*/
|
||||||
static void
|
static DeferredErrorMessage *
|
||||||
ErrorIfInsertPartitionColumnDoesNotMatchSelect(Query *query, RangeTblEntry *insertRte,
|
InsertPartitionColumnMatchesSelect(Query *query, RangeTblEntry *insertRte,
|
||||||
RangeTblEntry *subqueryRte,
|
RangeTblEntry *subqueryRte,
|
||||||
Oid *selectPartitionColumnTableId)
|
Oid *selectPartitionColumnTableId)
|
||||||
{
|
{
|
||||||
ListCell *targetEntryCell = NULL;
|
ListCell *targetEntryCell = NULL;
|
||||||
uint32 rangeTableId = 1;
|
uint32 rangeTableId = 1;
|
||||||
|
@ -972,14 +1004,13 @@ ErrorIfInsertPartitionColumnDoesNotMatchSelect(Query *query, RangeTblEntry *inse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot plan INSERT INTO ... SELECT "
|
"INSERT INTO ... SELECT partition columns in the source "
|
||||||
"because partition columns in the target table "
|
"table and subquery do not match",
|
||||||
"and the subquery do not match"),
|
psprintf(errorDetailTemplate, exprDescription),
|
||||||
errdetail(errorDetailTemplate, exprDescription),
|
"Ensure the target table's partition column has a "
|
||||||
errhint("Ensure the target table's partition column has a "
|
"corresponding simple column reference to a distributed "
|
||||||
"corresponding simple column reference to a distributed "
|
"table's partition column in the subquery.");
|
||||||
"table's partition column in the subquery.")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -988,27 +1019,24 @@ ErrorIfInsertPartitionColumnDoesNotMatchSelect(Query *query, RangeTblEntry *inse
|
||||||
*/
|
*/
|
||||||
if (!IsA(targetEntry->expr, Var))
|
if (!IsA(targetEntry->expr, Var))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot plan INSERT INTO ... SELECT "
|
"INSERT INTO ... SELECT partition columns in the source "
|
||||||
"because partition columns in the target table "
|
"table and subquery do not match",
|
||||||
"and the subquery do not match"),
|
"The data type of the target table's partition column "
|
||||||
errdetail(
|
"should exactly match the data type of the "
|
||||||
"The data type of the target table's partition column "
|
"corresponding simple column reference in the subquery.",
|
||||||
"should exactly match the data type of the "
|
NULL);
|
||||||
"corresponding simple column reference in the subquery.")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finally, check that the select target column is a partition column */
|
/* finally, check that the select target column is a partition column */
|
||||||
if (!IsPartitionColumn(selectTargetExpr, subquery))
|
if (!IsPartitionColumn(selectTargetExpr, subquery))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot plan INSERT INTO ... SELECT "
|
"INSERT INTO ... SELECT partition columns in the source "
|
||||||
"because partition columns in the target table "
|
"table and subquery do not match",
|
||||||
"and the subquery do not match"),
|
"The target table's partition column should correspond "
|
||||||
errdetail(
|
"to a partition column in the subquery.",
|
||||||
"The target table's partition column "
|
NULL);
|
||||||
"should correspond to a partition column "
|
|
||||||
"in the subquery.")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we can set the select relation id */
|
/* we can set the select relation id */
|
||||||
|
@ -1019,11 +1047,15 @@ ErrorIfInsertPartitionColumnDoesNotMatchSelect(Query *query, RangeTblEntry *inse
|
||||||
|
|
||||||
if (!targetTableHasPartitionColumn)
|
if (!targetTableHasPartitionColumn)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot plan INSERT INTO ... SELECT "
|
"INSERT INTO ... SELECT partition columns in the source "
|
||||||
"because the query doesn't include the target table's "
|
"table and subquery do not match",
|
||||||
"partition column")));
|
"the query doesn't include the target table's "
|
||||||
|
"partition column",
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1155,11 +1187,11 @@ AddUninstantiatedEqualityQual(Query *query, Var *partitionColumn)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ErrorIfModifyQueryNotSupported checks if the query contains unsupported features,
|
* ModifyQuerySupported returns NULL if the query only contains supported
|
||||||
* and errors out if it does.
|
* features, otherwise it returns an error description.
|
||||||
*/
|
*/
|
||||||
void
|
DeferredErrorMessage *
|
||||||
ErrorIfModifyQueryNotSupported(Query *queryTree)
|
ModifyQuerySupported(Query *queryTree)
|
||||||
{
|
{
|
||||||
Oid distributedTableId = ExtractFirstDistributedTableId(queryTree);
|
Oid distributedTableId = ExtractFirstDistributedTableId(queryTree);
|
||||||
uint32 rangeTableId = 1;
|
uint32 rangeTableId = 1;
|
||||||
|
@ -1185,21 +1217,18 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
*/
|
*/
|
||||||
if (queryTree->hasSubLinks == true)
|
if (queryTree->hasSubLinks == true)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given"
|
"subqueries are not supported in distributed modifications",
|
||||||
" modification"),
|
NULL, NULL);
|
||||||
errdetail("Subqueries are not supported in distributed"
|
|
||||||
" modifications.")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reject queries which include CommonTableExpr */
|
/* reject queries which include CommonTableExpr */
|
||||||
if (queryTree->cteList != NIL)
|
if (queryTree->cteList != NIL)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given"
|
"common table expressions are not supported in distributed "
|
||||||
" modification"),
|
"modifications",
|
||||||
errdetail("Common table expressions are not supported in"
|
NULL, NULL);
|
||||||
" distributed modifications.")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extract range table entries */
|
/* extract range table entries */
|
||||||
|
@ -1227,11 +1256,12 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
|
|
||||||
if (referenceTable && !schemaNode)
|
if (referenceTable && !schemaNode)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given"
|
"cannot perform distributed planning for the given"
|
||||||
" modification"),
|
" modification",
|
||||||
errdetail("Modifications to reference tables are "
|
"Modifications to reference tables are "
|
||||||
"supported only from the schema node.")));
|
"supported only from the schema node.",
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
queryTableCount++;
|
queryTableCount++;
|
||||||
|
@ -1239,8 +1269,9 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
/* we do not expect to see a view in modify query */
|
/* we do not expect to see a view in modify query */
|
||||||
if (rangeTableEntry->relkind == RELKIND_VIEW)
|
if (rangeTableEntry->relkind == RELKIND_VIEW)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot modify views over distributed tables")));
|
"cannot modify views over distributed tables",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rangeTableEntry->rtekind == RTE_VALUES)
|
else if (rangeTableEntry->rtekind == RTE_VALUES)
|
||||||
|
@ -1277,10 +1308,11 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
rangeTableEntryErrorDetail = "Unrecognized range table entry.";
|
rangeTableEntryErrorDetail = "Unrecognized range table entry.";
|
||||||
}
|
}
|
||||||
|
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given"
|
"cannot perform distributed planning for the given "
|
||||||
" modifications"),
|
"modifications",
|
||||||
errdetail("%s", rangeTableEntryErrorDetail)));
|
rangeTableEntryErrorDetail,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1291,11 +1323,12 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
*/
|
*/
|
||||||
if (commandType != CMD_INSERT && queryTableCount != 1)
|
if (commandType != CMD_INSERT && queryTableCount != 1)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given"
|
"cannot perform distributed planning for the given"
|
||||||
" modification"),
|
" modification",
|
||||||
errdetail("Joins are not supported in distributed "
|
"Joins are not supported in distributed "
|
||||||
"modifications.")));
|
"modifications.",
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reject queries which involve multi-row inserts */
|
/* reject queries which involve multi-row inserts */
|
||||||
|
@ -1308,11 +1341,12 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
* with a constant, and if you're inserting multiple rows at once the function
|
* with a constant, and if you're inserting multiple rows at once the function
|
||||||
* should return a different value for each row.
|
* should return a different value for each row.
|
||||||
*/
|
*/
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given"
|
"cannot perform distributed planning for the given"
|
||||||
" modification"),
|
" modification",
|
||||||
errdetail("Multi-row INSERTs to distributed tables are not "
|
"Multi-row INSERTs to distributed tables are not "
|
||||||
"supported.")));
|
"supported.",
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
|
if (commandType == CMD_INSERT || commandType == CMD_UPDATE ||
|
||||||
|
@ -1347,9 +1381,10 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
if (commandType == CMD_UPDATE &&
|
if (commandType == CMD_UPDATE &&
|
||||||
contain_volatile_functions((Node *) targetEntry->expr))
|
contain_volatile_functions((Node *) targetEntry->expr))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("functions used in UPDATE queries on distributed "
|
"functions used in UPDATE queries on distributed "
|
||||||
"tables must not be VOLATILE")));
|
"tables must not be VOLATILE",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandType == CMD_UPDATE && targetEntryPartitionColumn &&
|
if (commandType == CMD_UPDATE && targetEntryPartitionColumn &&
|
||||||
|
@ -1362,9 +1397,10 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
if (commandType == CMD_INSERT && targetEntryPartitionColumn &&
|
if (commandType == CMD_INSERT && targetEntryPartitionColumn &&
|
||||||
!IsA(targetEntry->expr, Const))
|
!IsA(targetEntry->expr, Const))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("values given for the partition column must be"
|
"values given for the partition column must be"
|
||||||
" constants or constant expressions")));
|
" constants or constant expressions",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandType == CMD_UPDATE &&
|
if (commandType == CMD_UPDATE &&
|
||||||
|
@ -1379,10 +1415,10 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
{
|
{
|
||||||
if (contain_volatile_functions(joinTree->quals))
|
if (contain_volatile_functions(joinTree->quals))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("functions used in the WHERE clause of "
|
"functions used in the WHERE clause of modification "
|
||||||
"modification queries on distributed tables "
|
"queries on distributed tables must not be VOLATILE",
|
||||||
"must not be VOLATILE")));
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
else if (MasterIrreducibleExpression(joinTree->quals, &hasVarArgument,
|
else if (MasterIrreducibleExpression(joinTree->quals, &hasVarArgument,
|
||||||
&hasBadCoalesce))
|
&hasBadCoalesce))
|
||||||
|
@ -1393,23 +1429,26 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
|
|
||||||
if (hasVarArgument)
|
if (hasVarArgument)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("STABLE functions used in UPDATE queries"
|
"STABLE functions used in UPDATE queries "
|
||||||
" cannot be called with column references")));
|
"cannot be called with column references",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasBadCoalesce)
|
if (hasBadCoalesce)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("non-IMMUTABLE functions are not allowed in CASE or"
|
"non-IMMUTABLE functions are not allowed in CASE or "
|
||||||
" COALESCE statements")));
|
"COALESCE statements",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contain_mutable_functions((Node *) queryTree->returningList))
|
if (contain_mutable_functions((Node *) queryTree->returningList))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("non-IMMUTABLE functions are not allowed in the"
|
"non-IMMUTABLE functions are not allowed in the "
|
||||||
" RETURNING clause")));
|
"RETURNING clause",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1470,10 +1509,11 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
}
|
}
|
||||||
else if (contain_mutable_functions((Node *) setTargetEntry->expr))
|
else if (contain_mutable_functions((Node *) setTargetEntry->expr))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("functions used in the DO UPDATE SET clause of "
|
"functions used in the DO UPDATE SET clause of "
|
||||||
"INSERTs on distributed tables must be marked "
|
"INSERTs on distributed tables must be marked "
|
||||||
"IMMUTABLE")));
|
"IMMUTABLE",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1482,17 +1522,22 @@ ErrorIfModifyQueryNotSupported(Query *queryTree)
|
||||||
if (contain_mutable_functions((Node *) arbiterWhere) ||
|
if (contain_mutable_functions((Node *) arbiterWhere) ||
|
||||||
contain_mutable_functions((Node *) onConflictWhere))
|
contain_mutable_functions((Node *) onConflictWhere))
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("functions used in the WHERE clause of the ON CONFLICT "
|
"functions used in the WHERE clause of the "
|
||||||
"clause of INSERTs on distributed tables must be marked "
|
"ON CONFLICT clause of INSERTs on distributed "
|
||||||
"IMMUTABLE")));
|
"tables must be marked IMMUTABLE",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specifiesPartitionValue)
|
if (specifiesPartitionValue)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("modifying the partition value of rows is not allowed")));
|
"modifying the partition value of rows is not "
|
||||||
|
"allowed",
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2579,7 +2624,7 @@ RouterQueryJob(Query *query, Task *task, List *placementList)
|
||||||
* the same node. Router plannable checks for select queries can be turned off
|
* the same node. Router plannable checks for select queries can be turned off
|
||||||
* by setting citus.enable_router_execution flag to false.
|
* by setting citus.enable_router_execution flag to false.
|
||||||
*/
|
*/
|
||||||
bool
|
static bool
|
||||||
MultiRouterPlannableQuery(Query *query, RelationRestrictionContext *restrictionContext)
|
MultiRouterPlannableQuery(Query *query, RelationRestrictionContext *restrictionContext)
|
||||||
{
|
{
|
||||||
CmdType commandType = query->commandType;
|
CmdType commandType = query->commandType;
|
||||||
|
@ -3021,19 +3066,13 @@ InstantiatePartitionQual(Node *node, void *context)
|
||||||
* ErrorIfQueryHasModifyingCTE checks if the query contains modifying common table
|
* ErrorIfQueryHasModifyingCTE checks if the query contains modifying common table
|
||||||
* expressions and errors out if it does.
|
* expressions and errors out if it does.
|
||||||
*/
|
*/
|
||||||
static void
|
static DeferredErrorMessage *
|
||||||
ErrorIfQueryHasModifyingCTE(Query *queryTree)
|
ErrorIfQueryHasModifyingCTE(Query *queryTree)
|
||||||
{
|
{
|
||||||
ListCell *cteCell = NULL;
|
ListCell *cteCell = NULL;
|
||||||
|
|
||||||
Assert(queryTree->commandType == CMD_SELECT);
|
Assert(queryTree->commandType == CMD_SELECT);
|
||||||
|
|
||||||
/* we do not need to do anything if there are no CTEs */
|
|
||||||
if (queryTree->cteList == NIL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(cteCell, queryTree->cteList)
|
foreach(cteCell, queryTree->cteList)
|
||||||
{
|
{
|
||||||
CommonTableExpr *cte = (CommonTableExpr *) lfirst(cteCell);
|
CommonTableExpr *cte = (CommonTableExpr *) lfirst(cteCell);
|
||||||
|
@ -3047,11 +3086,13 @@ ErrorIfQueryHasModifyingCTE(Query *queryTree)
|
||||||
*/
|
*/
|
||||||
if (cteQuery->commandType != CMD_SELECT)
|
if (cteQuery->commandType != CMD_SELECT)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
errmsg("cannot perform distributed planning for the given "
|
"data-modifying statements are not supported in "
|
||||||
"modification"),
|
"the WITH clauses of distributed queries",
|
||||||
errdetail("Data-modifying statements are not supported in "
|
NULL, NULL);
|
||||||
"the WITH clauses of distributed queries.")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* everything OK */
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,6 +280,7 @@ OutMultiPlan(OUTFUNC_ARGS)
|
||||||
WRITE_NODE_FIELD(masterQuery);
|
WRITE_NODE_FIELD(masterQuery);
|
||||||
WRITE_STRING_FIELD(masterTableName);
|
WRITE_STRING_FIELD(masterTableName);
|
||||||
WRITE_BOOL_FIELD(routerExecutable);
|
WRITE_BOOL_FIELD(routerExecutable);
|
||||||
|
WRITE_NODE_FIELD(planningError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,7 @@ ReadMultiPlan(READFUNC_ARGS)
|
||||||
READ_NODE_FIELD(masterQuery);
|
READ_NODE_FIELD(masterQuery);
|
||||||
READ_STRING_FIELD(masterTableName);
|
READ_STRING_FIELD(masterTableName);
|
||||||
READ_BOOL_FIELD(routerExecutable);
|
READ_BOOL_FIELD(routerExecutable);
|
||||||
|
READ_NODE_FIELD(planningError);
|
||||||
|
|
||||||
READ_DONE();
|
READ_DONE();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "datatype/timestamp.h"
|
#include "datatype/timestamp.h"
|
||||||
#include "distributed/citus_nodes.h"
|
#include "distributed/citus_nodes.h"
|
||||||
|
#include "distributed/errormessage.h"
|
||||||
#include "distributed/master_metadata_utility.h"
|
#include "distributed/master_metadata_utility.h"
|
||||||
#include "distributed/multi_logical_planner.h"
|
#include "distributed/multi_logical_planner.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
|
@ -215,6 +216,13 @@ typedef struct MultiPlan
|
||||||
Query *masterQuery;
|
Query *masterQuery;
|
||||||
char *masterTableName;
|
char *masterTableName;
|
||||||
bool routerExecutable;
|
bool routerExecutable;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NULL if this a valid plan, an error description otherwise. This will
|
||||||
|
* e.g. be set if SQL features are present that a planner doesn't support,
|
||||||
|
* or if prepared statement parameters prevented successful planning.
|
||||||
|
*/
|
||||||
|
DeferredErrorMessage *planningError;
|
||||||
} MultiPlan;
|
} MultiPlan;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,5 +56,6 @@ struct MultiPlan;
|
||||||
extern struct MultiPlan * GetMultiPlan(PlannedStmt *planStatement);
|
extern struct MultiPlan * GetMultiPlan(PlannedStmt *planStatement);
|
||||||
extern void multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo,
|
extern void multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo,
|
||||||
Index index, RangeTblEntry *rte);
|
Index index, RangeTblEntry *rte);
|
||||||
|
extern bool IsModifyCommand(Query *query);
|
||||||
|
|
||||||
#endif /* MULTI_PLANNER_H */
|
#endif /* MULTI_PLANNER_H */
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "c.h"
|
#include "c.h"
|
||||||
|
|
||||||
|
#include "distributed/errormessage.h"
|
||||||
#include "distributed/multi_logical_planner.h"
|
#include "distributed/multi_logical_planner.h"
|
||||||
#include "distributed/multi_physical_planner.h"
|
#include "distributed/multi_physical_planner.h"
|
||||||
#include "distributed/multi_planner.h"
|
#include "distributed/multi_planner.h"
|
||||||
|
@ -28,10 +29,13 @@
|
||||||
|
|
||||||
extern bool EnableRouterExecution;
|
extern bool EnableRouterExecution;
|
||||||
|
|
||||||
extern MultiPlan * MultiRouterPlanCreate(Query *originalQuery, Query *query,
|
extern MultiPlan * CreateRouterPlan(Query *originalQuery, Query *query,
|
||||||
RelationRestrictionContext *restrictionContext);
|
RelationRestrictionContext *restrictionContext);
|
||||||
|
extern MultiPlan * CreateModifyPlan(Query *originalQuery, Query *query,
|
||||||
|
RelationRestrictionContext *restrictionContext);
|
||||||
|
|
||||||
extern void AddUninstantiatedPartitionRestriction(Query *originalQuery);
|
extern void AddUninstantiatedPartitionRestriction(Query *originalQuery);
|
||||||
extern void ErrorIfModifyQueryNotSupported(Query *queryTree);
|
extern DeferredErrorMessage * ModifyQuerySupported(Query *queryTree);
|
||||||
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
|
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
|
||||||
RangeTblEntry *insertRte,
|
RangeTblEntry *insertRte,
|
||||||
RangeTblEntry *subqueryRte);
|
RangeTblEntry *subqueryRte);
|
||||||
|
|
|
@ -177,16 +177,14 @@ SELECT
|
||||||
user_id, (random()*10)::int
|
user_id, (random()*10)::int
|
||||||
FROM
|
FROM
|
||||||
raw_events_first;
|
raw_events_first;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: volatile functions are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Volatile functions are not allowed in INSERT ... SELECT queries
|
|
||||||
INSERT INTO raw_events_second (user_id, value_1)
|
INSERT INTO raw_events_second (user_id, value_1)
|
||||||
WITH sub_cte AS (SELECT (random()*10)::int)
|
WITH sub_cte AS (SELECT (random()*10)::int)
|
||||||
SELECT
|
SELECT
|
||||||
user_id, (SELECT * FROM sub_cte)
|
user_id, (SELECT * FROM sub_cte)
|
||||||
FROM
|
FROM
|
||||||
raw_events_first;
|
raw_events_first;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: volatile functions are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Volatile functions are not allowed in INSERT ... SELECT queries
|
|
||||||
-- add one more row
|
-- add one more row
|
||||||
INSERT INTO raw_events_first (user_id, time) VALUES
|
INSERT INTO raw_events_first (user_id, time) VALUES
|
||||||
(7, now());
|
(7, now());
|
||||||
|
@ -1098,8 +1096,7 @@ INSERT INTO agg_events (value_1_agg, user_id)
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: DISTINCT ON clauses are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: DISTINCT ON clauses are not allowed in INSERT ... SELECT queries
|
|
||||||
-- We do not support some CTEs
|
-- We do not support some CTEs
|
||||||
WITH fist_table_agg AS
|
WITH fist_table_agg AS
|
||||||
(SELECT sum(value_1) as v1_agg, user_id FROM raw_events_first GROUP BY user_id)
|
(SELECT sum(value_1) as v1_agg, user_id FROM raw_events_first GROUP BY user_id)
|
||||||
|
@ -1112,7 +1109,7 @@ INSERT INTO agg_events
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
||||||
-- We do support some CTEs
|
-- We do support some CTEs
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
|
@ -1156,8 +1153,7 @@ FROM
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: set operations are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Set operations are not allowed in INSERT ... SELECT queries
|
|
||||||
-- We do not support any set operations
|
-- We do not support any set operations
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
raw_events_first(user_id)
|
raw_events_first(user_id)
|
||||||
|
@ -1166,8 +1162,7 @@ INSERT INTO
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: set operations are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Set operations are not allowed in INSERT ... SELECT queries
|
|
||||||
-- We do not support any set operations
|
-- We do not support any set operations
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
raw_events_first(user_id)
|
raw_events_first(user_id)
|
||||||
|
@ -1179,8 +1174,7 @@ FROM
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: set operations are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Set operations are not allowed in INSERT ... SELECT queries
|
|
||||||
-- unsupported JOIN
|
-- unsupported JOIN
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
(value_4_agg,
|
(value_4_agg,
|
||||||
|
@ -1219,7 +1213,7 @@ FROM (SELECT SUM(raw_events_second.value_4) AS v4,
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The data type of the target table's partition column should exactly match the data type of the corresponding simple column reference in the subquery.
|
DETAIL: The data type of the target table's partition column should exactly match the data type of the corresponding simple column reference in the subquery.
|
||||||
-- error cases
|
-- error cases
|
||||||
-- no part column at all
|
-- no part column at all
|
||||||
|
@ -1230,7 +1224,8 @@ FROM raw_events_first;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because the query doesn't include the target table's partition column
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
|
DETAIL: the query doesn't include the target table's partition column
|
||||||
INSERT INTO raw_events_second
|
INSERT INTO raw_events_second
|
||||||
(value_1)
|
(value_1)
|
||||||
SELECT user_id
|
SELECT user_id
|
||||||
|
@ -1238,7 +1233,8 @@ FROM raw_events_first;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because the query doesn't include the target table's partition column
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
|
DETAIL: the query doesn't include the target table's partition column
|
||||||
INSERT INTO raw_events_second
|
INSERT INTO raw_events_second
|
||||||
(user_id)
|
(user_id)
|
||||||
SELECT value_1
|
SELECT value_1
|
||||||
|
@ -1246,7 +1242,7 @@ FROM raw_events_first;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
||||||
INSERT INTO raw_events_second
|
INSERT INTO raw_events_second
|
||||||
(user_id)
|
(user_id)
|
||||||
|
@ -1255,7 +1251,7 @@ FROM raw_events_first;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an operator in the same position as the target table's partition column.
|
DETAIL: Subquery contains an operator in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO raw_events_second
|
INSERT INTO raw_events_second
|
||||||
|
@ -1265,7 +1261,7 @@ FROM raw_events_first;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an explicit cast in the same position as the target table's partition column.
|
DETAIL: Subquery contains an explicit cast in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
|
@ -1284,7 +1280,7 @@ GROUP BY user_id;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an aggregation in the same position as the target table's partition column.
|
DETAIL: Subquery contains an aggregation in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO agg_events
|
INSERT INTO agg_events
|
||||||
|
@ -1304,7 +1300,7 @@ GROUP BY user_id,
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
||||||
-- tables should be co-located
|
-- tables should be co-located
|
||||||
INSERT INTO agg_events (user_id)
|
INSERT INTO agg_events (user_id)
|
||||||
|
@ -1315,7 +1311,7 @@ FROM
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
||||||
-- unsupported joins between subqueries
|
-- unsupported joins between subqueries
|
||||||
-- we do not return bare partition column on the inner query
|
-- we do not return bare partition column on the inner query
|
||||||
|
@ -1344,7 +1340,7 @@ ON (f.id = f2.id);
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
-- the second part of the query is not routable since
|
-- the second part of the query is not routable since
|
||||||
|
@ -1428,8 +1424,7 @@ GROUP BY grouping sets ( ( user_id ), ( value_1 ), ( user_id, value_1 ), ( ) );
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
DEBUG: StartTransaction
|
DEBUG: StartTransaction
|
||||||
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 0/1/0, nestlvl: 1, children:
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: grouping sets are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Grouping sets are not allowed in INSERT ... SELECT queries
|
|
||||||
-- set back to INFO
|
-- set back to INFO
|
||||||
SET client_min_messages TO INFO;
|
SET client_min_messages TO INFO;
|
||||||
DEBUG: StartTransactionCommand
|
DEBUG: StartTransactionCommand
|
||||||
|
@ -1999,8 +1994,7 @@ FROM
|
||||||
table_with_defaults
|
table_with_defaults
|
||||||
GROUP BY
|
GROUP BY
|
||||||
store_id;
|
store_id;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: volatile functions are not allowed in INSERT ... SELECT queries
|
||||||
DETAIL: Volatile functions are not allowed in INSERT ... SELECT queries
|
|
||||||
-- do some more error/error message checks
|
-- do some more error/error message checks
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET citus.shard_replication_factor TO 1;
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
@ -2030,42 +2024,42 @@ INSERT INTO text_table (part_col)
|
||||||
CASE WHEN part_col = 'onder' THEN 'marco'
|
CASE WHEN part_col = 'onder' THEN 'marco'
|
||||||
END
|
END
|
||||||
FROM text_table ;
|
FROM text_table ;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains a case expression in the same position as the target table's partition column.
|
DETAIL: Subquery contains a case expression in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT COALESCE(part_col, 'onder') FROM text_table;
|
INSERT INTO text_table (part_col) SELECT COALESCE(part_col, 'onder') FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains a coalesce expression in the same position as the target table's partition column.
|
DETAIL: Subquery contains a coalesce expression in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT GREATEST(part_col, 'jason') FROM text_table;
|
INSERT INTO text_table (part_col) SELECT GREATEST(part_col, 'jason') FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains a min/max expression in the same position as the target table's partition column.
|
DETAIL: Subquery contains a min/max expression in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT LEAST(part_col, 'andres') FROM text_table;
|
INSERT INTO text_table (part_col) SELECT LEAST(part_col, 'andres') FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains a min/max expression in the same position as the target table's partition column.
|
DETAIL: Subquery contains a min/max expression in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT NULLIF(part_col, 'metin') FROM text_table;
|
INSERT INTO text_table (part_col) SELECT NULLIF(part_col, 'metin') FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT part_col isnull FROM text_table;
|
INSERT INTO text_table (part_col) SELECT part_col isnull FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT part_col::text from char_table;
|
INSERT INTO text_table (part_col) SELECT part_col::text from char_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an explicit coercion in the same position as the target table's partition column.
|
DETAIL: Subquery contains an explicit coercion in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT (part_col = 'burak') is true FROM text_table;
|
INSERT INTO text_table (part_col) SELECT (part_col = 'burak') is true FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
DETAIL: Subquery contains an expression that is not a simple column reference in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT val FROM text_table;
|
INSERT INTO text_table (part_col) SELECT val FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The data type of the target table's partition column should exactly match the data type of the corresponding simple column reference in the subquery.
|
DETAIL: The data type of the target table's partition column should exactly match the data type of the corresponding simple column reference in the subquery.
|
||||||
INSERT INTO text_table (part_col) SELECT val::text FROM text_table;
|
INSERT INTO text_table (part_col) SELECT val::text FROM text_table;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: Subquery contains an explicit coercion in the same position as the target table's partition column.
|
DETAIL: Subquery contains an explicit coercion in the same position as the target table's partition column.
|
||||||
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
HINT: Ensure the target table's partition column has a corresponding simple column reference to a distributed table's partition column in the subquery.
|
||||||
insert into table_with_starts_with_defaults (b,c) select b,c FROM table_with_starts_with_defaults;
|
insert into table_with_starts_with_defaults (b,c) select b,c FROM table_with_starts_with_defaults;
|
||||||
|
|
|
@ -216,8 +216,7 @@ DETAIL: Multi-row INSERTs to distributed tables are not supported.
|
||||||
-- commands containing a CTE are unsupported
|
-- commands containing a CTE are unsupported
|
||||||
WITH deleted_orders AS (DELETE FROM limit_orders RETURNING *)
|
WITH deleted_orders AS (DELETE FROM limit_orders RETURNING *)
|
||||||
INSERT INTO limit_orders DEFAULT VALUES;
|
INSERT INTO limit_orders DEFAULT VALUES;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: common table expressions are not supported in distributed modifications
|
||||||
DETAIL: Common table expressions are not supported in distributed modifications.
|
|
||||||
-- test simple DELETE
|
-- test simple DELETE
|
||||||
INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69);
|
INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69);
|
||||||
SELECT COUNT(*) FROM limit_orders WHERE id = 246;
|
SELECT COUNT(*) FROM limit_orders WHERE id = 246;
|
||||||
|
@ -275,8 +274,7 @@ ERROR: cannot plan queries that include both regular and partitioned relations
|
||||||
-- commands containing a CTE are unsupported
|
-- commands containing a CTE are unsupported
|
||||||
WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *)
|
WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *)
|
||||||
DELETE FROM limit_orders;
|
DELETE FROM limit_orders;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: common table expressions are not supported in distributed modifications
|
||||||
DETAIL: Common table expressions are not supported in distributed modifications.
|
|
||||||
-- cursors are not supported
|
-- cursors are not supported
|
||||||
DELETE FROM limit_orders WHERE CURRENT OF cursor_name;
|
DELETE FROM limit_orders WHERE CURRENT OF cursor_name;
|
||||||
ERROR: distributed modifications must target exactly one shard
|
ERROR: distributed modifications must target exactly one shard
|
||||||
|
@ -421,8 +419,7 @@ ERROR: cannot plan queries that include both regular and partitioned relations
|
||||||
-- commands containing a CTE are unsupported
|
-- commands containing a CTE are unsupported
|
||||||
WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *)
|
WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *)
|
||||||
UPDATE limit_orders SET symbol = 'GM';
|
UPDATE limit_orders SET symbol = 'GM';
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: common table expressions are not supported in distributed modifications
|
||||||
DETAIL: Common table expressions are not supported in distributed modifications.
|
|
||||||
SELECT symbol, bidder_id FROM limit_orders WHERE id = 246;
|
SELECT symbol, bidder_id FROM limit_orders WHERE id = 246;
|
||||||
symbol | bidder_id
|
symbol | bidder_id
|
||||||
--------+-----------
|
--------+-----------
|
||||||
|
|
|
@ -1091,7 +1091,7 @@ FROM
|
||||||
colocated_table_test, colocated_table_test_2
|
colocated_table_test, colocated_table_test_2
|
||||||
WHERE
|
WHERE
|
||||||
colocated_table_test.value_1 = colocated_table_test.value_1;
|
colocated_table_test.value_1 = colocated_table_test.value_1;
|
||||||
ERROR: If data inserted into a reference table, all of the participating tables in the INSERT INTO ... SELECT query should be reference tables.
|
ERROR: only reference tables may be queried when targeting a reference table with INSERT ... SELECT
|
||||||
-- should error out, same as the above
|
-- should error out, same as the above
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
reference_table_test (value_1)
|
reference_table_test (value_1)
|
||||||
|
@ -1101,7 +1101,7 @@ FROM
|
||||||
colocated_table_test, reference_table_test
|
colocated_table_test, reference_table_test
|
||||||
WHERE
|
WHERE
|
||||||
colocated_table_test.value_1 = reference_table_test.value_1;
|
colocated_table_test.value_1 = reference_table_test.value_1;
|
||||||
ERROR: If data inserted into a reference table, all of the participating tables in the INSERT INTO ... SELECT query should be reference tables.
|
ERROR: only reference tables may be queried when targeting a reference table with INSERT ... SELECT
|
||||||
-- now, insert into the hash partitioned table and use reference
|
-- now, insert into the hash partitioned table and use reference
|
||||||
-- tables in the SELECT queries
|
-- tables in the SELECT queries
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
|
@ -1146,7 +1146,7 @@ FROM
|
||||||
WHERE
|
WHERE
|
||||||
colocated_table_test_2.value_4 = reference_table_test.value_4
|
colocated_table_test_2.value_4 = reference_table_test.value_4
|
||||||
RETURNING value_1, value_2;
|
RETURNING value_1, value_2;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The data type of the target table's partition column should exactly match the data type of the corresponding simple column reference in the subquery.
|
DETAIL: The data type of the target table's partition column should exactly match the data type of the corresponding simple column reference in the subquery.
|
||||||
-- partition column value comes from reference table which should error out
|
-- partition column value comes from reference table which should error out
|
||||||
INSERT INTO
|
INSERT INTO
|
||||||
|
@ -1158,7 +1158,7 @@ FROM
|
||||||
WHERE
|
WHERE
|
||||||
colocated_table_test_2.value_4 = reference_table_test.value_4
|
colocated_table_test_2.value_4 = reference_table_test.value_4
|
||||||
RETURNING value_1, value_2;
|
RETURNING value_1, value_2;
|
||||||
ERROR: cannot plan INSERT INTO ... SELECT because partition columns in the target table and the subquery do not match
|
ERROR: INSERT INTO ... SELECT partition columns in the source table and subquery do not match
|
||||||
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
DETAIL: The target table's partition column should correspond to a partition column in the subquery.
|
||||||
-- some tests for mark_tables_colocated
|
-- some tests for mark_tables_colocated
|
||||||
-- should error out
|
-- should error out
|
||||||
|
|
|
@ -444,8 +444,7 @@ WITH new_article AS (
|
||||||
INSERT INTO articles_hash VALUES (1, 1, 'arsenous', 9572) RETURNING *
|
INSERT INTO articles_hash VALUES (1, 1, 'arsenous', 9572) RETURNING *
|
||||||
)
|
)
|
||||||
SELECT * FROM new_article;
|
SELECT * FROM new_article;
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: data-modifying statements are not supported in the WITH clauses of distributed queries
|
||||||
DETAIL: Data-modifying statements are not supported in the WITH clauses of distributed queries.
|
|
||||||
-- Modifying statement in nested CTE case is covered by PostgreSQL itself
|
-- Modifying statement in nested CTE case is covered by PostgreSQL itself
|
||||||
WITH new_article AS (
|
WITH new_article AS (
|
||||||
WITH nested_cte AS (
|
WITH nested_cte AS (
|
||||||
|
|
|
@ -92,8 +92,7 @@ SELECT master_modify_multiple_shards('DELETE FROM multi_shard_modify_test WHERE
|
||||||
ERROR: master_modify_multiple_shards() does not support RETURNING
|
ERROR: master_modify_multiple_shards() does not support RETURNING
|
||||||
-- commands containing a CTE are unsupported
|
-- commands containing a CTE are unsupported
|
||||||
SELECT master_modify_multiple_shards('WITH deleted_stuff AS (INSERT INTO multi_shard_modify_test DEFAULT VALUES RETURNING *) DELETE FROM multi_shard_modify_test');
|
SELECT master_modify_multiple_shards('WITH deleted_stuff AS (INSERT INTO multi_shard_modify_test DEFAULT VALUES RETURNING *) DELETE FROM multi_shard_modify_test');
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: common table expressions are not supported in distributed modifications
|
||||||
DETAIL: Common table expressions are not supported in distributed modifications.
|
|
||||||
-- Check that we can successfully delete from multiple shards with 1PC
|
-- Check that we can successfully delete from multiple shards with 1PC
|
||||||
SET citus.multi_shard_commit_protocol TO '1pc';
|
SET citus.multi_shard_commit_protocol TO '1pc';
|
||||||
SELECT count(*) FROM multi_shard_modify_test;
|
SELECT count(*) FROM multi_shard_modify_test;
|
||||||
|
@ -234,8 +233,7 @@ SELECT master_modify_multiple_shards('UPDATE multi_shard_modify_test SET t_name=
|
||||||
ERROR: master_modify_multiple_shards() does not support RETURNING
|
ERROR: master_modify_multiple_shards() does not support RETURNING
|
||||||
-- commands containing a CTE are unsupported
|
-- commands containing a CTE are unsupported
|
||||||
SELECT master_modify_multiple_shards('WITH t AS (INSERT INTO multi_shard_modify_test DEFAULT VALUES RETURNING *) UPDATE multi_shard_modify_test SET t_name = ''FAIL'' ');
|
SELECT master_modify_multiple_shards('WITH t AS (INSERT INTO multi_shard_modify_test DEFAULT VALUES RETURNING *) UPDATE multi_shard_modify_test SET t_name = ''FAIL'' ');
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: common table expressions are not supported in distributed modifications
|
||||||
DETAIL: Common table expressions are not supported in distributed modifications.
|
|
||||||
-- updates referencing just a var are supported
|
-- updates referencing just a var are supported
|
||||||
SELECT master_modify_multiple_shards('UPDATE multi_shard_modify_test SET t_value=t_key WHERE t_key = 10');
|
SELECT master_modify_multiple_shards('UPDATE multi_shard_modify_test SET t_value=t_key WHERE t_key = 10');
|
||||||
master_modify_multiple_shards
|
master_modify_multiple_shards
|
||||||
|
|
|
@ -237,8 +237,7 @@ INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFL
|
||||||
-- subquery in the SET clause
|
-- subquery in the SET clause
|
||||||
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
|
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
|
||||||
UPDATE SET other_col = (SELECT count(*) from upsert_test);
|
UPDATE SET other_col = (SELECT count(*) from upsert_test);
|
||||||
ERROR: cannot perform distributed planning for the given modification
|
ERROR: subqueries are not supported in distributed modifications
|
||||||
DETAIL: Subqueries are not supported in distributed modifications.
|
|
||||||
-- non mutable function call in the SET
|
-- non mutable function call in the SET
|
||||||
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
|
INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO
|
||||||
UPDATE SET other_col = random()::int;
|
UPDATE SET other_col = random()::int;
|
||||||
|
|
Loading…
Reference in New Issue