static int executeXMLQuery(char *szXml) { Query *pquery = COptTasks::PqueryFromXML(szXml); PlannedStmt *pplstmt = pg_plan_query(pquery, NULL); DestReceiver *pdest = CreateDestReceiver(DestNone, NULL); QueryDesc *pqueryDesc = CreateQueryDesc(pplstmt, PStrDup("Internal Query") /*plan->query */, ActiveSnapshot, InvalidSnapshot, pdest, NULL /*paramLI*/, false); elog(NOTICE, "Executing thawed plan..."); ExecutorStart(pqueryDesc, 0); ExecutorRun(pqueryDesc, ForwardScanDirection, 0); ExecutorEnd(pqueryDesc); int iProcessed = (int) pqueryDesc->es_processed; FreeQueryDesc(pqueryDesc); return iProcessed; }
static int executeXMLPlan(char *szXml) { PlannedStmt *pplstmt = COptTasks::PplstmtFromXML(szXml); // The following steps are required to be able to execute the query. DestReceiver *pdest = CreateDestReceiver(DestNone, NULL); QueryDesc *pqueryDesc = CreateQueryDesc(pplstmt, PStrDup("Internal Query") /*plan->query */, ActiveSnapshot, InvalidSnapshot, pdest, NULL /*paramLI*/, false); elog(NOTICE, "Executing thawed plan..."); ExecutorStart(pqueryDesc, 0); ExecutorRun(pqueryDesc, ForwardScanDirection, 0); ExecutorEnd(pqueryDesc); int iProcessed = (int) pqueryDesc->es_processed; FreeQueryDesc(pqueryDesc); return iProcessed; }
/* * refresh_matview_datafill */ static void refresh_matview_datafill(DestReceiver *dest, Query *query, const char *queryString) { List *rewritten; PlannedStmt *plan; QueryDesc *queryDesc; Query *copied_query; /* Lock and rewrite, using a copy to preserve the original query. */ copied_query = copyObject(query); AcquireRewriteLocks(copied_query, true, false); rewritten = QueryRewrite(copied_query); /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) elog(ERROR, "unexpected rewrite result for REFRESH MATERIALIZED VIEW"); query = (Query *) linitial(rewritten); /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); /* Plan the query which will generate data for the refresh. */ plan = pg_plan_query(query, 0, NULL); /* * Use a snapshot with an updated command ID to ensure this query sees * results of any previously executed queries. (This could only matter if * the planner executed an allegedly-stable function that changed the * database contents, but let's do it anyway to be safe.) */ PushCopiedSnapshot(GetActiveSnapshot()); UpdateActiveSnapshotCommandId(); /* Create a QueryDesc, redirecting output to our tuple receiver */ queryDesc = CreateQueryDesc(plan, queryString, GetActiveSnapshot(), InvalidSnapshot, dest, NULL, 0); /* call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, EXEC_FLAG_WITHOUT_OIDS); /* run the plan */ ExecutorRun(queryDesc, ForwardScanDirection, 0L); /* and clean up */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); PopActiveSnapshot(); }
static int extractFrozenQueryPlanAndExecute(char *pcQuery) { Assert(pcQuery); ULONG ulQueryLen = -1; memcpy(&ulQueryLen, pcQuery, sizeof(ULONG)); pcQuery+=sizeof(ULONG); Query *pquery = (Query *) readNodeFromBinaryString(pcQuery, ulQueryLen); pcQuery+=ulQueryLen; PlannedStmt *pplstmt = pg_plan_query(pquery, NULL); if (!pplstmt) { elog(ERROR, "Problem with planned statement of query tree %s", gpdb::SzNodeToString(pquery)); } // The following steps are required to be able to execute the query. DestReceiver *pdest = CreateDestReceiver(DestNone, NULL); QueryDesc *pqueryDesc = CreateQueryDesc(pplstmt, PStrDup("Internal Query") /*plan->query */, ActiveSnapshot, InvalidSnapshot, pdest, NULL /*paramLI*/, false); // Do not record gpperfmon information about internal queries pqueryDesc->gpmon_pkt = NULL; elog(NOTICE, "Executing thawed plan..."); ExecutorStart(pqueryDesc, 0); ExecutorRun(pqueryDesc, ForwardScanDirection, 0); ExecutorEnd(pqueryDesc); int iProcessed = (int) pqueryDesc->es_processed; FreeQueryDesc(pqueryDesc); return iProcessed; }
static int extractFrozenPlanAndExecute(char *pcSerializedPS) { Assert(pcSerializedPS); ULONG ulPlannedStmtLen = -1; memcpy(&ulPlannedStmtLen, pcSerializedPS, sizeof(ULONG)); pcSerializedPS+=sizeof(ULONG); PlannedStmt *pplstmt = (PlannedStmt *) readNodeFromBinaryString(pcSerializedPS, ulPlannedStmtLen); pcSerializedPS+=ulPlannedStmtLen; //The following steps are required to be able to execute the query. DestReceiver *pdest = CreateDestReceiver(DestNone, NULL); QueryDesc *pqueryDesc = CreateQueryDesc(pplstmt, PStrDup("Internal Query") /*plan->query */, ActiveSnapshot, InvalidSnapshot, pdest, NULL /*paramLI*/, false); // Do not record gpperfmon information about internal queries pqueryDesc->gpmon_pkt = NULL; elog(NOTICE, "Executing thawed plan..."); ExecutorStart(pqueryDesc, 0); ExecutorRun(pqueryDesc, ForwardScanDirection, 0); ExecutorEnd(pqueryDesc); int iProcessed = (int) pqueryDesc->es_processed; FreeQueryDesc(pqueryDesc); return iProcessed; }
/* * ExecCreateTableAs -- execute a CREATE TABLE AS command */ void ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, ParamListInfo params, char *completionTag) { Query *query = (Query *) stmt->query; IntoClause *into = stmt->into; bool is_matview = (into->viewQuery != NULL); DestReceiver *dest; Oid save_userid = InvalidOid; int save_sec_context = 0; int save_nestlevel = 0; List *rewritten; PlannedStmt *plan; QueryDesc *queryDesc; ScanDirection dir; /* * Create the tuple receiver object and insert info it will need */ dest = CreateIntoRelDestReceiver(into); /* * The contained Query could be a SELECT, or an EXECUTE utility command. * If the latter, we just pass it off to ExecuteQuery. */ Assert(IsA(query, Query)); if (query->commandType == CMD_UTILITY && IsA(query->utilityStmt, ExecuteStmt)) { ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt; Assert(!is_matview); /* excluded by syntax */ ExecuteQuery(estmt, into, queryString, params, dest, completionTag); return; } Assert(query->commandType == CMD_SELECT); /* * For materialized views, lock down security-restricted operations and * arrange to make GUC variable changes local to this command. This is * not necessary for security, but this keeps the behavior similar to * REFRESH MATERIALIZED VIEW. Otherwise, one could create a materialized * view not possible to refresh. */ if (is_matview) { GetUserIdAndSecContext(&save_userid, &save_sec_context); SetUserIdAndSecContext(save_userid, save_sec_context | SECURITY_RESTRICTED_OPERATION); save_nestlevel = NewGUCNestLevel(); } /* * Parse analysis was done already, but we still have to run the rule * rewriter. We do not do AcquireRewriteLocks: we assume the query either * came straight from the parser, or suitable locks were acquired by * plancache.c. * * Because the rewriter and planner tend to scribble on the input, we make * a preliminary copy of the source querytree. This prevents problems in * the case that CTAS is in a portal or plpgsql function and is executed * repeatedly. (See also the same hack in EXPLAIN and PREPARE.) */ rewritten = QueryRewrite((Query *) copyObject(query)); /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) elog(ERROR, "unexpected rewrite result for CREATE TABLE AS SELECT"); query = (Query *) linitial(rewritten); Assert(query->commandType == CMD_SELECT); /* plan the query */ plan = pg_plan_query(query, 0, params); /* * Use a snapshot with an updated command ID to ensure this query sees * results of any previously executed queries. (This could only matter if * the planner executed an allegedly-stable function that changed the * database contents, but let's do it anyway to be parallel to the EXPLAIN * code path.) */ PushCopiedSnapshot(GetActiveSnapshot()); UpdateActiveSnapshotCommandId(); /* Create a QueryDesc, redirecting output to our tuple receiver */ queryDesc = CreateQueryDesc(plan, queryString, GetActiveSnapshot(), InvalidSnapshot, dest, params, 0); /* call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, GetIntoRelEFlags(into)); /* * Normally, we run the plan to completion; but if skipData is specified, * just do tuple receiver startup and shutdown. */ if (into->skipData) dir = NoMovementScanDirection; else dir = ForwardScanDirection; /* run the plan */ ExecutorRun(queryDesc, dir, 0L); /* save the rowcount if we're given a completionTag to fill */ if (completionTag) snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "SELECT %u", queryDesc->estate->es_processed); /* and clean up */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); PopActiveSnapshot(); if (is_matview) { /* Roll back any GUC changes */ AtEOXact_GUC(false, save_nestlevel); /* Restore userid and security context */ SetUserIdAndSecContext(save_userid, save_sec_context); } }
/* * ExecCreateTableAs -- execute a CREATE TABLE AS command */ void ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString, ParamListInfo params, char *completionTag) { Query *query = (Query *) stmt->query; IntoClause *into = stmt->into; DestReceiver *dest; List *rewritten; PlannedStmt *plan; QueryDesc *queryDesc; ScanDirection dir; /* * Create the tuple receiver object and insert info it will need */ dest = CreateIntoRelDestReceiver(into); /* * The contained Query could be a SELECT, or an EXECUTE utility command. * If the latter, we just pass it off to ExecuteQuery. */ Assert(IsA(query, Query)); if (query->commandType == CMD_UTILITY && IsA(query->utilityStmt, ExecuteStmt)) { ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt; ExecuteQuery(estmt, into, queryString, params, dest, completionTag); return; } Assert(query->commandType == CMD_SELECT); /* * Parse analysis was done already, but we still have to run the rule * rewriter. We do not do AcquireRewriteLocks: we assume the query either * came straight from the parser, or suitable locks were acquired by * plancache.c. * * Because the rewriter and planner tend to scribble on the input, we make * a preliminary copy of the source querytree. This prevents problems in * the case that CTAS is in a portal or plpgsql function and is executed * repeatedly. (See also the same hack in EXPLAIN and PREPARE.) */ rewritten = QueryRewrite((Query *) copyObject(query)); /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) elog(ERROR, "unexpected rewrite result for CREATE TABLE AS SELECT"); query = (Query *) linitial(rewritten); Assert(query->commandType == CMD_SELECT); /* plan the query */ plan = pg_plan_query(query, 0, params); /* * Use a snapshot with an updated command ID to ensure this query sees * results of any previously executed queries. (This could only matter if * the planner executed an allegedly-stable function that changed the * database contents, but let's do it anyway to be parallel to the EXPLAIN * code path.) */ PushCopiedSnapshot(GetActiveSnapshot()); UpdateActiveSnapshotCommandId(); /* Create a QueryDesc, redirecting output to our tuple receiver */ queryDesc = CreateQueryDesc(plan, queryString, GetActiveSnapshot(), InvalidSnapshot, dest, params, 0); /* call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, GetIntoRelEFlags(into)); /* * Normally, we run the plan to completion; but if skipData is specified, * just do tuple receiver startup and shutdown. */ if (into->skipData) dir = NoMovementScanDirection; else dir = ForwardScanDirection; /* run the plan */ ExecutorRun(queryDesc, dir, 0L); /* save the rowcount if we're given a completionTag to fill */ if (completionTag) snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "SELECT %u", queryDesc->estate->es_processed); /* and clean up */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); PopActiveSnapshot(); }
/* * ProcessQuery * Execute a single plannable query within a PORTAL_MULTI_QUERY, * PORTAL_ONE_RETURNING, or PORTAL_ONE_MOD_WITH portal * * plan: the plan tree for the query * sourceText: the source text of the query * params: any parameters needed * dest: where to send results * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE * in which to store a command completion status string. * * completionTag may be NULL if caller doesn't want a status string. * * Must be called in a memory context that will be reset or deleted on * error; otherwise the executor's memory usage will be leaked. */ static void ProcessQuery(PlannedStmt *plan, const char *sourceText, ParamListInfo params, DestReceiver *dest, char *completionTag) { QueryDesc *queryDesc; elog(DEBUG3, "ProcessQuery"); /* * Create the QueryDesc object */ queryDesc = CreateQueryDesc(plan, sourceText, GetActiveSnapshot(), InvalidSnapshot, dest, params, 0); /* * Call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, 0); /* * Run the plan to completion. */ ExecutorRun(queryDesc, ForwardScanDirection, 0L); /* * Build command completion status string, if caller wants one. */ if (completionTag) { Oid lastOid; switch (queryDesc->operation) { case CMD_SELECT: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "SELECT %u", queryDesc->estate->es_processed); break; case CMD_INSERT: if (queryDesc->estate->es_processed == 1) lastOid = queryDesc->estate->es_lastoid; else lastOid = InvalidOid; snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "INSERT %u %u", lastOid, queryDesc->estate->es_processed); break; case CMD_UPDATE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "UPDATE %u", queryDesc->estate->es_processed); break; case CMD_DELETE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "DELETE %u", queryDesc->estate->es_processed); break; default: strcpy(completionTag, "???"); break; } } /* * Now, we close down all the scans and free allocated resources. */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); }
/* * refresh_matview_datafill */ static void refresh_matview_datafill(DestReceiver *dest, Query *query, const char *queryString, Oid relowner) { List *rewritten; PlannedStmt *plan; QueryDesc *queryDesc; Oid save_userid; int save_sec_context; int save_nestlevel; Query *copied_query; /* * Switch to the owner's userid, so that any functions are run as that * user. Also lock down security-restricted operations and arrange to * make GUC variable changes local to this command. */ GetUserIdAndSecContext(&save_userid, &save_sec_context); SetUserIdAndSecContext(relowner, save_sec_context | SECURITY_RESTRICTED_OPERATION); save_nestlevel = NewGUCNestLevel(); /* Lock and rewrite, using a copy to preserve the original query. */ copied_query = copyObject(query); AcquireRewriteLocks(copied_query, true, false); rewritten = QueryRewrite(copied_query); /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) elog(ERROR, "unexpected rewrite result for REFRESH MATERIALIZED VIEW"); query = (Query *) linitial(rewritten); /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); /* Plan the query which will generate data for the refresh. */ plan = pg_plan_query(query, 0, NULL); /* * Use a snapshot with an updated command ID to ensure this query sees * results of any previously executed queries. (This could only matter if * the planner executed an allegedly-stable function that changed the * database contents, but let's do it anyway to be safe.) */ PushCopiedSnapshot(GetActiveSnapshot()); UpdateActiveSnapshotCommandId(); /* Create a QueryDesc, redirecting output to our tuple receiver */ queryDesc = CreateQueryDesc(plan, queryString, GetActiveSnapshot(), InvalidSnapshot, dest, NULL, 0); /* call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, EXEC_FLAG_WITHOUT_OIDS); /* run the plan */ ExecutorRun(queryDesc, ForwardScanDirection, 0L); /* and clean up */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); PopActiveSnapshot(); /* Roll back any GUC changes */ AtEOXact_GUC(false, save_nestlevel); /* Restore userid and security context */ SetUserIdAndSecContext(save_userid, save_sec_context); }
/* * refresh_matview_datafill */ static void refresh_matview_datafill(DestReceiver *dest, Query *query, const char *queryString) { List *rewritten; PlannedStmt *plan; QueryDesc *queryDesc; List *rtable; RangeTblEntry *initial_rte; RangeTblEntry *second_rte; rewritten = QueryRewrite((Query *) copyObject(query)); /* SELECT should never rewrite to more or less than one SELECT query */ if (list_length(rewritten) != 1) elog(ERROR, "unexpected rewrite result for REFRESH MATERIALIZED VIEW"); query = (Query *) linitial(rewritten); /* Check for user-requested abort. */ CHECK_FOR_INTERRUPTS(); /* * Kludge here to allow refresh of a materialized view which is invalid * (that is, it was created or refreshed WITH NO DATA. We flag the first * two RangeTblEntry list elements, which were added to the front of the * rewritten Query to keep the rules system happy, with the isResultRel * flag to indicate that it is OK if they are flagged as invalid. See * UpdateRangeTableOfViewParse() for details. * * NOTE: The rewrite has switched the frist two RTEs, but they are still * in the first two positions. If that behavior changes, the asserts here * will fail. */ rtable = query->rtable; initial_rte = ((RangeTblEntry *) linitial(rtable)); Assert(strcmp(initial_rte->alias->aliasname, "new")); initial_rte->isResultRel = true; second_rte = ((RangeTblEntry *) lsecond(rtable)); Assert(strcmp(second_rte->alias->aliasname, "old")); second_rte->isResultRel = true; /* Plan the query which will generate data for the refresh. */ plan = pg_plan_query(query, 0, NULL); /* * Use a snapshot with an updated command ID to ensure this query sees * results of any previously executed queries. (This could only matter if * the planner executed an allegedly-stable function that changed the * database contents, but let's do it anyway to be safe.) */ PushCopiedSnapshot(GetActiveSnapshot()); UpdateActiveSnapshotCommandId(); /* Create a QueryDesc, redirecting output to our tuple receiver */ queryDesc = CreateQueryDesc(plan, queryString, GetActiveSnapshot(), InvalidSnapshot, dest, NULL, 0); /* call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, EXEC_FLAG_WITHOUT_OIDS); /* run the plan */ ExecutorRun(queryDesc, ForwardScanDirection, 0L); /* and clean up */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); PopActiveSnapshot(); }
/* * ProcessQuery * Execute a single plannable query within a PORTAL_MULTI_QUERY * or PORTAL_ONE_RETURNING portal * * parsetree: the query tree * plan: the plan tree for the query * params: any parameters needed * dest: where to send results * completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE * in which to store a command completion status string. * * completionTag may be NULL if caller doesn't want a status string. * * Must be called in a memory context that will be reset or deleted on * error; otherwise the executor's memory usage will be leaked. */ static void ProcessQuery(Query *parsetree, Plan *plan, ParamListInfo params, DestReceiver *dest, char *completionTag) { int operation = parsetree->commandType; QueryDesc *queryDesc; ereport(DEBUG3, (errmsg_internal("ProcessQuery"))); /* * Must always set snapshot for plannable queries. Note we assume that * caller will take care of restoring ActiveSnapshot on exit/error. */ ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); /* * Create the QueryDesc object */ queryDesc = CreateQueryDesc(parsetree, plan, ActiveSnapshot, InvalidSnapshot, dest, params, false); /* * Set up to collect AFTER triggers */ AfterTriggerBeginQuery(); /* * Call ExecutorStart to prepare the plan for execution */ ExecutorStart(queryDesc, 0); /* * Run the plan to completion. */ ExecutorRun(queryDesc, ForwardScanDirection, 0L); /* * Build command completion status string, if caller wants one. */ if (completionTag) { Oid lastOid; switch (operation) { case CMD_SELECT: strcpy(completionTag, "SELECT"); break; case CMD_INSERT: if (queryDesc->estate->es_processed == 1) lastOid = queryDesc->estate->es_lastoid; else lastOid = InvalidOid; snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "INSERT %u %u", lastOid, queryDesc->estate->es_processed); break; case CMD_UPDATE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "UPDATE %u", queryDesc->estate->es_processed); break; case CMD_DELETE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "DELETE %u", queryDesc->estate->es_processed); break; default: strcpy(completionTag, "???"); break; } } /* Now take care of any queued AFTER triggers */ AfterTriggerEndQuery(queryDesc->estate); /* * Now, we close down all the scans and free allocated resources. */ ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); FreeSnapshot(ActiveSnapshot); ActiveSnapshot = NULL; }