/* * 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(); }
/* * Implements the 'PREPARE' utility statement. */ void PrepareQuery(PrepareStmt *stmt) { const char *commandTag; Query *query; List *query_list, *plan_list; /* * Disallow empty-string statement name (conflicts with protocol-level * unnamed statement). */ if (!stmt->name || stmt->name[0] == '\0') ereport(ERROR, (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION), errmsg("invalid statement name: must not be empty"))); switch (stmt->query->commandType) { case CMD_SELECT: commandTag = "SELECT"; break; case CMD_INSERT: commandTag = "INSERT"; break; case CMD_UPDATE: commandTag = "UPDATE"; break; case CMD_DELETE: commandTag = "DELETE"; break; default: ereport(ERROR, (errcode(ERRCODE_INVALID_PSTATEMENT_DEFINITION), errmsg("utility statements cannot be prepared"))); commandTag = NULL; /* keep compiler quiet */ break; } /* * Parse analysis is already done, but we must still rewrite and plan the * query. */ /* * Because the planner is not cool about not scribbling on its input, we * make a preliminary copy of the source querytree. This prevents * problems in the case that the PREPARE is in a portal or plpgsql * function and is executed repeatedly. (See also the same hack in * DECLARE CURSOR and EXPLAIN.) XXX the planner really shouldn't modify * its input ... FIXME someday. */ query = copyObject(stmt->query); /* Rewrite the query. The result could be 0, 1, or many queries. */ AcquireRewriteLocks(query); query_list = QueryRewrite(query); /* Generate plans for queries. Snapshot is already set. */ plan_list = pg_plan_queries(query_list, NULL, false); /* * Save the results. We don't have the query string for this PREPARE, but * we do have the string we got from the client, so use that. */ StorePreparedStatement(stmt->name, debug_query_string, commandTag, query_list, plan_list, stmt->argtype_oids, true); }
/* * 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); }