1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

Read-only transactions, as defined in SQL.

This commit is contained in:
Peter Eisentraut
2003-01-10 22:03:30 +00:00
parent b7ca9bdf18
commit b65cd56240
16 changed files with 427 additions and 146 deletions

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.196 2003/01/08 23:32:29 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.197 2003/01/10 22:03:27 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -85,6 +85,7 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
static TupleTableSlot *EvalPlanQualNext(EState *estate);
static void EndEvalPlanQual(EState *estate);
static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
static void ExecCheckXactReadOnly(Query *parsetree, CmdType operation);
static void EvalPlanQualStart(evalPlanQual *epq, EState *estate,
evalPlanQual *priorepq);
static void EvalPlanQualStop(evalPlanQual *epq);
@ -201,6 +202,14 @@ ExecutorRun(QueryDesc *queryDesc,
operation = queryDesc->operation;
dest = queryDesc->dest;
/*
* If the transaction is read-only, we need to check if any writes
* are planned to non-temporary tables. This is done here at this
* rather late stage so that we can handle EXPLAIN vs. EXPLAIN
* ANALYZE easily.
*/
ExecCheckXactReadOnly(queryDesc->parsetree, operation);
/*
* startup tuple receiver
*/
@ -385,6 +394,45 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
*/
static void
ExecCheckXactReadOnly(Query *parsetree, CmdType operation)
{
if (!XactReadOnly)
return;
/* CREATE TABLE AS or SELECT INTO */
if (operation == CMD_SELECT && parsetree->into != NULL)
goto fail;
if (operation == CMD_DELETE || operation == CMD_INSERT
|| operation == CMD_UPDATE)
{
List *lp;
foreach(lp, parsetree->rtable)
{
RangeTblEntry *rte = lfirst(lp);
if (rte->rtekind != RTE_RELATION)
continue;
if (!rte->checkForWrite)
continue;
if (isTempNamespace(RelidGetNamespaceId(rte->relid)))
continue;
goto fail;
}
}
return;
fail:
elog(ERROR, "transaction is read-only");
}
/* ----------------------------------------------------------------
* InitPlan
*