1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +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

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.235 2007/03/12 22:09:27 petere Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.236 2007/03/13 00:33:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -2504,12 +2504,13 @@ AbortCurrentTransaction(void)
* could issue more commands and possibly cause a failure after the statement
* completes). Subtransactions are verboten too.
*
* stmtNode: pointer to parameter block for statement; this is used in
* a very klugy way to determine whether we are inside a function.
* stmtType: statement type name for error messages.
* isTopLevel: passed down from ProcessUtility to determine whether we are
* inside a function. (We will always fail if this is false, but it's
* convenient to centralize the check here instead of making callers do it.)
* stmtType: statement type name, for error messages.
*/
void
PreventTransactionChain(void *stmtNode, const char *stmtType)
PreventTransactionChain(bool isTopLevel, const char *stmtType)
{
/*
* xact block already started?
@ -2532,11 +2533,9 @@ PreventTransactionChain(void *stmtNode, const char *stmtType)
stmtType)));
/*
* Are we inside a function call? If the statement's parameter block was
* allocated in QueryContext, assume it is an interactive command.
* Otherwise assume it is coming from a function.
* inside a function call?
*/
if (!MemoryContextContains(QueryContext, stmtNode))
if (!isTopLevel)
ereport(ERROR,
(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
/* translator: %s represents an SQL statement name */
@ -2562,12 +2561,12 @@ PreventTransactionChain(void *stmtNode, const char *stmtType)
* use of the current statement's results. Likewise subtransactions.
* Thus this is an inverse for PreventTransactionChain.
*
* stmtNode: pointer to parameter block for statement; this is used in
* a very klugy way to determine whether we are inside a function.
* stmtType: statement type name for error messages.
* isTopLevel: passed down from ProcessUtility to determine whether we are
* inside a function.
* stmtType: statement type name, for error messages.
*/
void
RequireTransactionChain(void *stmtNode, const char *stmtType)
RequireTransactionChain(bool isTopLevel, const char *stmtType)
{
/*
* xact block already started?
@ -2582,12 +2581,11 @@ RequireTransactionChain(void *stmtNode, const char *stmtType)
return;
/*
* Are we inside a function call? If the statement's parameter block was
* allocated in QueryContext, assume it is an interactive command.
* Otherwise assume it is coming from a function.
* inside a function call?
*/
if (!MemoryContextContains(QueryContext, stmtNode))
if (!isTopLevel)
return;
ereport(ERROR,
(errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
/* translator: %s represents an SQL statement name */
@ -2602,11 +2600,11 @@ RequireTransactionChain(void *stmtNode, const char *stmtType)
* a transaction block than when running as single commands. ANALYZE is
* currently the only example.
*
* stmtNode: pointer to parameter block for statement; this is used in
* a very klugy way to determine whether we are inside a function.
* isTopLevel: passed down from ProcessUtility to determine whether we are
* inside a function.
*/
bool
IsInTransactionChain(void *stmtNode)
IsInTransactionChain(bool isTopLevel)
{
/*
* Return true on same conditions that would make PreventTransactionChain
@ -2618,7 +2616,7 @@ IsInTransactionChain(void *stmtNode)
if (IsSubTransaction())
return true;
if (!MemoryContextContains(QueryContext, stmtNode))
if (!isTopLevel)
return true;
if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&