aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execParallel.c4
-rw-r--r--src/backend/executor/functions.c92
-rw-r--r--src/backend/executor/spi.c55
3 files changed, 69 insertions, 82 deletions
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index 6cf62daab8a..e01fe6da964 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -156,13 +156,15 @@ ExecSerializePlan(Plan *plan, EState *estate)
pstmt->planTree = plan;
pstmt->rtable = estate->es_range_table;
pstmt->resultRelations = NIL;
- pstmt->utilityStmt = NULL;
pstmt->subplans = NIL;
pstmt->rewindPlanIDs = NULL;
pstmt->rowMarks = NIL;
pstmt->relationOids = NIL;
pstmt->invalItems = NIL; /* workers can't replan anyway... */
pstmt->nParamExec = estate->es_plannedstmt->nParamExec;
+ pstmt->utilityStmt = NULL;
+ pstmt->stmt_location = -1;
+ pstmt->stmt_len = -1;
/* Return serialized copy of our dummy PlannedStmt. */
return nodeToString(pstmt);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 039defa7b85..e4a1da4dbbf 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -66,7 +66,7 @@ typedef struct execution_state
ExecStatus status;
bool setsResult; /* true if this query produces func's result */
bool lazyEval; /* true if should fetch one row at a time */
- Node *stmt; /* PlannedStmt or utility statement */
+ PlannedStmt *stmt; /* plan for this query */
QueryDesc *qd; /* null unless status == RUN */
} execution_state;
@@ -487,45 +487,56 @@ init_execution_state(List *queryTree_list,
foreach(lc2, qtlist)
{
Query *queryTree = (Query *) lfirst(lc2);
- Node *stmt;
+ PlannedStmt *stmt;
execution_state *newes;
Assert(IsA(queryTree, Query));
/* Plan the query if needed */
if (queryTree->commandType == CMD_UTILITY)
- stmt = queryTree->utilityStmt;
+ {
+ /* Utility commands require no planning. */
+ stmt = makeNode(PlannedStmt);
+ stmt->commandType = CMD_UTILITY;
+ stmt->canSetTag = queryTree->canSetTag;
+ stmt->utilityStmt = queryTree->utilityStmt;
+ stmt->stmt_location = queryTree->stmt_location;
+ stmt->stmt_len = queryTree->stmt_len;
+ }
else
- stmt = (Node *) pg_plan_query(queryTree,
+ stmt = pg_plan_query(queryTree,
fcache->readonly_func ? CURSOR_OPT_PARALLEL_OK : 0,
- NULL);
+ NULL);
/*
* Precheck all commands for validity in a function. This should
* generally match the restrictions spi.c applies.
*/
- if (IsA(stmt, CopyStmt) &&
- ((CopyStmt *) stmt)->filename == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ if (stmt->commandType == CMD_UTILITY)
+ {
+ if (IsA(stmt->utilityStmt, CopyStmt) &&
+ ((CopyStmt *) stmt->utilityStmt)->filename == NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot COPY to/from client in a SQL function")));
- if (IsA(stmt, TransactionStmt))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- /* translator: %s is a SQL statement name */
- errmsg("%s is not allowed in a SQL function",
- CreateCommandTag(stmt))));
+ if (IsA(stmt->utilityStmt, TransactionStmt))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ /* translator: %s is a SQL statement name */
+ errmsg("%s is not allowed in a SQL function",
+ CreateCommandTag(stmt->utilityStmt))));
+ }
if (fcache->readonly_func && !CommandIsReadOnly(stmt))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function",
- CreateCommandTag(stmt))));
+ CreateCommandTag((Node *) stmt))));
if (IsInParallelMode() && !CommandIsReadOnly(stmt))
- PreventCommandIfParallelMode(CreateCommandTag(stmt));
+ PreventCommandIfParallelMode(CreateCommandTag((Node *) stmt));
/* OK, build the execution_state for this query */
newes = (execution_state *) palloc(sizeof(execution_state));
@@ -569,15 +580,9 @@ init_execution_state(List *queryTree_list,
{
lasttages->setsResult = true;
if (lazyEvalOK &&
- IsA(lasttages->stmt, PlannedStmt))
- {
- PlannedStmt *ps = (PlannedStmt *) lasttages->stmt;
-
- if (ps->commandType == CMD_SELECT &&
- ps->utilityStmt == NULL &&
- !ps->hasModifyingCTE)
- fcache->lazyEval = lasttages->lazyEval = true;
- }
+ lasttages->stmt->commandType == CMD_SELECT &&
+ !lasttages->stmt->hasModifyingCTE)
+ fcache->lazyEval = lasttages->lazyEval = true;
}
return eslist;
@@ -704,7 +709,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
flat_query_list = NIL;
foreach(lc, raw_parsetree_list)
{
- Node *parsetree = (Node *) lfirst(lc);
+ RawStmt *parsetree = (RawStmt *) lfirst(lc);
List *queryTree_sublist;
queryTree_sublist = pg_analyze_and_rewrite_params(parsetree,
@@ -801,22 +806,15 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
else
dest = None_Receiver;
- if (IsA(es->stmt, PlannedStmt))
- es->qd = CreateQueryDesc((PlannedStmt *) es->stmt,
- fcache->src,
- GetActiveSnapshot(),
- InvalidSnapshot,
- dest,
- fcache->paramLI, 0);
- else
- es->qd = CreateUtilityQueryDesc(es->stmt,
- fcache->src,
- GetActiveSnapshot(),
- dest,
- fcache->paramLI);
+ es->qd = CreateQueryDesc(es->stmt,
+ fcache->src,
+ GetActiveSnapshot(),
+ InvalidSnapshot,
+ dest,
+ fcache->paramLI, 0);
/* Utility commands don't need Executor. */
- if (es->qd->utilitystmt == NULL)
+ if (es->qd->operation != CMD_UTILITY)
{
/*
* In lazyEval mode, do not let the executor set up an AfterTrigger
@@ -844,12 +842,9 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
{
bool result;
- if (es->qd->utilitystmt)
+ if (es->qd->operation == CMD_UTILITY)
{
- /* ProcessUtility needs the PlannedStmt for DECLARE CURSOR */
- ProcessUtility((es->qd->plannedstmt ?
- (Node *) es->qd->plannedstmt :
- es->qd->utilitystmt),
+ ProcessUtility(es->qd->plannedstmt,
fcache->src,
PROCESS_UTILITY_QUERY,
es->qd->params,
@@ -882,7 +877,7 @@ postquel_end(execution_state *es)
es->status = F_EXEC_DONE;
/* Utility commands don't need Executor. */
- if (es->qd->utilitystmt == NULL)
+ if (es->qd->operation != CMD_UTILITY)
{
ExecutorFinish(es->qd);
ExecutorEnd(es->qd);
@@ -1576,8 +1571,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
* entities.
*/
if (parse &&
- parse->commandType == CMD_SELECT &&
- parse->utilityStmt == NULL)
+ parse->commandType == CMD_SELECT)
{
tlist_ptr = &parse->targetList;
tlist = parse->targetList;
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index ee7a7e2d78c..7bd37283b7f 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1232,7 +1232,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
{
if (list_length(stmt_list) == 1 &&
- IsA((Node *) linitial(stmt_list), PlannedStmt) &&
+ ((PlannedStmt *) linitial(stmt_list))->commandType != CMD_UTILITY &&
((PlannedStmt *) linitial(stmt_list))->rowMarks == NIL &&
ExecSupportsBackwardScan(((PlannedStmt *) linitial(stmt_list))->planTree))
portal->cursorOptions |= CURSOR_OPT_SCROLL;
@@ -1248,7 +1248,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
if (portal->cursorOptions & CURSOR_OPT_SCROLL)
{
if (list_length(stmt_list) == 1 &&
- IsA((Node *) linitial(stmt_list), PlannedStmt) &&
+ ((PlannedStmt *) linitial(stmt_list))->commandType != CMD_UTILITY &&
((PlannedStmt *) linitial(stmt_list))->rowMarks != NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1270,7 +1270,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
foreach(lc, stmt_list)
{
- Node *pstmt = (Node *) lfirst(lc);
+ PlannedStmt *pstmt = (PlannedStmt *) lfirst(lc);
if (!CommandIsReadOnly(pstmt))
{
@@ -1279,9 +1279,9 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function",
- CreateCommandTag(pstmt))));
+ CreateCommandTag((Node *) pstmt))));
else
- PreventCommandIfParallelMode(CreateCommandTag(pstmt));
+ PreventCommandIfParallelMode(CreateCommandTag((Node *) pstmt));
}
}
}
@@ -1757,7 +1757,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
foreach(list_item, raw_parsetree_list)
{
- Node *parsetree = (Node *) lfirst(list_item);
+ RawStmt *parsetree = (RawStmt *) lfirst(list_item);
List *stmt_list;
CachedPlanSource *plansource;
@@ -1767,7 +1767,7 @@ _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
*/
plansource = CreateCachedPlan(parsetree,
src,
- CreateCommandTag(parsetree));
+ CreateCommandTag(parsetree->stmt));
/*
* Parameter datatypes are driven by parserSetup hook if provided,
@@ -1859,12 +1859,12 @@ _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
foreach(list_item, raw_parsetree_list)
{
- Node *parsetree = (Node *) lfirst(list_item);
+ RawStmt *parsetree = (RawStmt *) lfirst(list_item);
CachedPlanSource *plansource;
plansource = CreateOneShotCachedPlan(parsetree,
src,
- CreateCommandTag(parsetree));
+ CreateCommandTag(parsetree->stmt));
plancache_list = lappend(plancache_list, plansource);
}
@@ -1959,7 +1959,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
*/
if (plan->oneshot)
{
- Node *parsetree = plansource->raw_parse_tree;
+ RawStmt *parsetree = plansource->raw_parse_tree;
const char *src = plansource->query_string;
List *stmt_list;
@@ -2018,26 +2018,19 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
foreach(lc2, stmt_list)
{
- Node *stmt = (Node *) lfirst(lc2);
- bool canSetTag;
+ PlannedStmt *stmt = (PlannedStmt *) lfirst(lc2);
+ bool canSetTag = stmt->canSetTag;
DestReceiver *dest;
_SPI_current->processed = 0;
_SPI_current->lastoid = InvalidOid;
_SPI_current->tuptable = NULL;
- if (IsA(stmt, PlannedStmt))
+ if (stmt->utilityStmt)
{
- canSetTag = ((PlannedStmt *) stmt)->canSetTag;
- }
- else
- {
- /* utilities are canSetTag if only thing in list */
- canSetTag = (list_length(stmt_list) == 1);
-
- if (IsA(stmt, CopyStmt))
+ if (IsA(stmt->utilityStmt, CopyStmt))
{
- CopyStmt *cstmt = (CopyStmt *) stmt;
+ CopyStmt *cstmt = (CopyStmt *) stmt->utilityStmt;
if (cstmt->filename == NULL)
{
@@ -2045,7 +2038,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
goto fail;
}
}
- else if (IsA(stmt, TransactionStmt))
+ else if (IsA(stmt->utilityStmt, TransactionStmt))
{
my_res = SPI_ERROR_TRANSACTION;
goto fail;
@@ -2057,10 +2050,10 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function",
- CreateCommandTag(stmt))));
+ CreateCommandTag((Node *) stmt))));
if (IsInParallelMode() && !CommandIsReadOnly(stmt))
- PreventCommandIfParallelMode(CreateCommandTag(stmt));
+ PreventCommandIfParallelMode(CreateCommandTag((Node *) stmt));
/*
* If not read-only mode, advance the command counter before each
@@ -2074,8 +2067,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
dest = CreateDestReceiver(canSetTag ? DestSPI : DestNone);
- if (IsA(stmt, PlannedStmt) &&
- ((PlannedStmt *) stmt)->utilityStmt == NULL)
+ if (stmt->utilityStmt == NULL)
{
QueryDesc *qdesc;
Snapshot snap;
@@ -2085,7 +2077,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
else
snap = InvalidSnapshot;
- qdesc = CreateQueryDesc((PlannedStmt *) stmt,
+ qdesc = CreateQueryDesc(stmt,
plansource->query_string,
snap, crosscheck_snapshot,
dest,
@@ -2116,9 +2108,9 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
* Some utility statements return a row count, even though the
* tuples are not returned to the caller.
*/
- if (IsA(stmt, CreateTableAsStmt))
+ if (IsA(stmt->utilityStmt, CreateTableAsStmt))
{
- CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt;
+ CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
if (strncmp(completionTag, "SELECT ", 7) == 0)
_SPI_current->processed =
@@ -2141,7 +2133,7 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
if (ctastmt->is_select_into)
res = SPI_OK_SELINTO;
}
- else if (IsA(stmt, CopyStmt))
+ else if (IsA(stmt->utilityStmt, CopyStmt))
{
Assert(strncmp(completionTag, "COPY ", 5) == 0);
_SPI_current->processed = pg_strtouint64(completionTag + 5,
@@ -2270,7 +2262,6 @@ _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
switch (operation)
{
case CMD_SELECT:
- Assert(queryDesc->plannedstmt->utilityStmt == NULL);
if (queryDesc->dest->mydest != DestSPI)
{
/* Don't return SPI_OK_SELECT if we're discarding result */