1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-03 20:02:46 +03:00

First phase of plan-invalidation project: create a plan cache management

module and teach PREPARE and protocol-level prepared statements to use it.
In service of this, rearrange utility-statement processing so that parse
analysis does not assume table schemas can't change before execution for
utility statements (necessary because we don't attempt to re-acquire locks
for utility statements when reusing a stored plan).  This requires some
refactoring of the ProcessUtility API, but it ends up cleaner anyway,
for instance we can get rid of the QueryContext global.

Still to do: fix up SPI and related code to use the plan cache; I'm tempted to
try to make SQL functions use it too.  Also, there are at least some aspects
of system state that we want to ensure remain the same during a replan as in
the original processing; search_path certainly ought to behave that way for
instance, and perhaps there are others.
This commit is contained in:
Tom Lane
2007-03-13 00:33:44 +00:00
parent f84308f195
commit b9527e9840
61 changed files with 2478 additions and 1354 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.277 2007/03/03 19:32:54 neilc Exp $
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.278 2007/03/13 00:33:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -713,7 +713,7 @@ CopyLoadRawBuf(CopyState cstate)
* the table.
*/
uint64
DoCopy(const CopyStmt *stmt)
DoCopy(const CopyStmt *stmt, const char *queryString)
{
CopyState cstate;
bool is_from = stmt->is_from;
@ -982,13 +982,11 @@ DoCopy(const CopyStmt *stmt)
}
else
{
Query *query = stmt->query;
List *rewritten;
Query *query;
PlannedStmt *plan;
DestReceiver *dest;
Assert(query);
Assert(query->commandType == CMD_SELECT);
Assert(!is_from);
cstate->rel = NULL;
@ -998,33 +996,18 @@ DoCopy(const CopyStmt *stmt)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY (SELECT) WITH OIDS is not supported")));
/* Query mustn't use INTO, either */
if (query->into)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY (SELECT INTO) is not supported")));
/*
* The query has already been through parse analysis, but not
* rewriting or planning. Do that now.
* Run parse analysis and rewrite. Note this also acquires sufficient
* locks on the source table(s).
*
* Because the planner is not cool about not scribbling on its input,
* we make a preliminary copy of the source querytree. This prevents
* Because the parser and planner tend to scribble on their input, we
* make a preliminary copy of the source querytree. This prevents
* problems in the case that the COPY is in a portal or plpgsql
* function and is executed repeatedly. (See also the same hack in
* EXPLAIN, DECLARE CURSOR and PREPARE.) XXX the planner really
* shouldn't modify its input ... FIXME someday.
* DECLARE CURSOR and PREPARE.) XXX FIXME someday.
*/
query = copyObject(query);
/*
* Must acquire locks in case we didn't come fresh from the parser.
* XXX this also scribbles on query, another reason for copyObject
*/
AcquireRewriteLocks(query);
/* Rewrite through rule system */
rewritten = QueryRewrite(query);
rewritten = pg_analyze_and_rewrite((Node *) copyObject(stmt->query),
queryString, NULL, 0);
/* We don't expect more or less than one result query */
if (list_length(rewritten) != 1)
@ -1033,6 +1016,12 @@ DoCopy(const CopyStmt *stmt)
query = (Query *) linitial(rewritten);
Assert(query->commandType == CMD_SELECT);
/* Query mustn't use INTO, either */
if (query->into)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY (SELECT INTO) is not supported")));
/* plan the query */
plan = planner(query, false, 0, NULL);