diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execParallel.c | 4 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 92 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 55 |
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 */ |