Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit200b151

Browse files
committed
Fix places that were using IsTransactionBlock() as an (inadequate) check
that they'd get to commit immediately on finishing. There's now acentralized routine PreventTransactionChain() that implements thenecessary tests.
1 parentf724c16 commit200b151

File tree

9 files changed

+107
-87
lines changed

9 files changed

+107
-87
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.133 2002/10/2119:46:45 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.134 2002/10/2122:06:18 tgl Exp $
1212
*
1313
* NOTES
1414
*Transaction aborts can now occur two ways:
@@ -1280,9 +1280,12 @@ CommitTransactionCommand(bool forceCommit)
12801280
*
12811281
* Autocommit mode is forced by either a true forceCommit
12821282
* parameter to me, or a true preventChain parameter to the
1283-
* preceding StartTransactionCommand call.This is needed so
1284-
* that commands like VACUUM can ensure that the right things
1285-
* happen.
1283+
* preceding StartTransactionCommand call, or a
1284+
* PreventTransactionChain call during the transaction.
1285+
* (The parameters could be omitted, but it turns out most
1286+
* callers of StartTransactionCommand/CommitTransactionCommand
1287+
* want to force autocommit, so making them all call
1288+
* PreventTransactionChain would just be extra notation.)
12861289
*/
12871290
caseTBLOCK_DEFAULT:
12881291
if (autocommit||forceCommit||suppressChain)
@@ -1429,6 +1432,60 @@ AbortCurrentTransaction(void)
14291432
}
14301433
}
14311434

1435+
/* --------------------------------
1436+
*PreventTransactionChain
1437+
*
1438+
* This routine is to be called by statements that must not run inside
1439+
* a transaction block, typically because they have non-rollback-able
1440+
* side effects or do internal commits.
1441+
*
1442+
* If we have already started a transaction block, issue an error; also issue
1443+
* an error if we appear to be running inside a user-defined function (which
1444+
* could issue more commands and possibly cause a failure after the statement
1445+
* completes). In autocommit-off mode, we allow the statement if a block is
1446+
* not already started, and force the statement to be autocommitted despite
1447+
* the mode.
1448+
*
1449+
* stmtNode: pointer to parameter block for statement; this is used in
1450+
* a very klugy way to determine whether we are inside a function.
1451+
* stmtType: statement type name for error messages.
1452+
* --------------------------------
1453+
*/
1454+
void
1455+
PreventTransactionChain(void*stmtNode,constchar*stmtType)
1456+
{
1457+
/*
1458+
* xact block already started?
1459+
*/
1460+
if (IsTransactionBlock())
1461+
{
1462+
/* translator: %s represents an SQL statement name */
1463+
elog(ERROR,"%s cannot run inside a transaction block",stmtType);
1464+
}
1465+
/*
1466+
* Are we inside a function call? If the statement's parameter block
1467+
* was allocated in QueryContext, assume it is an interactive command.
1468+
* Otherwise assume it is coming from a function.
1469+
*/
1470+
if (!MemoryContextContains(QueryContext,stmtNode))
1471+
{
1472+
/* translator: %s represents an SQL statement name */
1473+
elog(ERROR,"%s cannot be executed from a function",stmtType);
1474+
}
1475+
/* If we got past IsTransactionBlock test, should be in default state */
1476+
if (CurrentTransactionState->blockState!=TBLOCK_DEFAULT)
1477+
elog(ERROR,"PreventTransactionChain: can't prevent chain");
1478+
/* okay to set the flag */
1479+
suppressChain= true;
1480+
/* If we're in autocommit-off node, generate a notice */
1481+
if (!autocommit)
1482+
{
1483+
/* translator: %s represents an SQL statement name */
1484+
elog(NOTICE,"%s will be committed automatically",stmtType);
1485+
}
1486+
}
1487+
1488+
14321489
/* ----------------------------------------------------------------
14331490
* transaction block support
14341491
* ----------------------------------------------------------------

‎src/backend/catalog/heap.c

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.231 2002/09/22 19:42:50 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.232 2002/10/21 22:06:18 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1917,19 +1917,8 @@ heap_truncate(Oid rid)
19171917
Relationrel;
19181918

19191919
/* Open relation for processing, and grab exclusive access on it. */
1920-
19211920
rel=heap_open(rid,AccessExclusiveLock);
19221921

1923-
/*
1924-
* TRUNCATE TABLE within a transaction block is dangerous, because if
1925-
* the transaction is later rolled back we have no way to undo
1926-
* truncation of the relation's physical file. Disallow it except for
1927-
* a rel created in the current xact (which would be deleted on abort,
1928-
* anyway).
1929-
*/
1930-
if (IsTransactionBlock()&& !rel->rd_isnew)
1931-
elog(ERROR,"TRUNCATE TABLE cannot run inside a transaction block");
1932-
19331922
/*
19341923
* Release any buffers associated with this relation. If they're
19351924
* dirty, they're just dropped without bothering to flush to disk.

‎src/backend/catalog/index.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.201 2002/09/27 15:05:23 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.202 2002/10/21 22:06:19 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1740,16 +1740,6 @@ reindex_index(Oid indexId, bool force, bool inplace)
17401740
OidheapId;
17411741
boolold;
17421742

1743-
/*
1744-
* REINDEX within a transaction block is dangerous, because if the
1745-
* transaction is later rolled back we have no way to undo truncation
1746-
* of the index's physical file. Disallow it.
1747-
*
1748-
* XXX if we're not doing an inplace rebuild, wouldn't this be okay?
1749-
*/
1750-
if (IsTransactionBlock())
1751-
elog(ERROR,"REINDEX cannot run inside a transaction block");
1752-
17531743
/*
17541744
* Open our index relation and get an exclusive lock on it.
17551745
*

‎src/backend/commands/dbcommands.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.105 2002/09/04 20:31:15 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.106 2002/10/21 22:06:19 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -152,8 +152,7 @@ createdb(const CreatedbStmt *stmt)
152152
}
153153

154154
/* don't call this in a transaction block */
155-
if (IsTransactionBlock())
156-
elog(ERROR,"CREATE DATABASE: may not be called in a transaction block");
155+
PreventTransactionChain((void*)stmt,"CREATE DATABASE");
157156

158157
/*
159158
* Check for db name conflict.There is a race condition here, since
@@ -382,8 +381,7 @@ dropdb(const char *dbname)
382381
if (strcmp(dbname,DatabaseName)==0)
383382
elog(ERROR,"DROP DATABASE: cannot be executed on the currently open database");
384383

385-
if (IsTransactionBlock())
386-
elog(ERROR,"DROP DATABASE: may not be called in a transaction block");
384+
PreventTransactionChain((void*)dbname,"DROP DATABASE");
387385

388386
/*
389387
* Obtain exclusive lock on pg_database. We need this to ensure that

‎src/backend/commands/indexcmds.c

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.91 2002/10/19 20:15:08 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.92 2002/10/21 22:06:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -560,15 +560,10 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ )
560560
{
561561
OidindOid;
562562
HeapTupletuple;
563-
booloverwrite= false;
563+
booloverwrite;
564564

565-
/*
566-
* REINDEX within a transaction block is dangerous, because if the
567-
* transaction is later rolled back we have no way to undo truncation
568-
* of the index's physical file. Disallow it.
569-
*/
570-
if (IsTransactionBlock())
571-
elog(ERROR,"REINDEX cannot run inside a BEGIN/END block");
565+
/* Choose in-place-or-not mode */
566+
overwrite=IsIgnoringSystemIndexes();
572567

573568
indOid=RangeVarGetRelid(indexRelation, false);
574569
tuple=SearchSysCache(RELOID,
@@ -595,8 +590,14 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ )
595590

596591
ReleaseSysCache(tuple);
597592

598-
if (IsIgnoringSystemIndexes())
599-
overwrite= true;
593+
/*
594+
* In-place REINDEX within a transaction block is dangerous, because
595+
* if the transaction is later rolled back we have no way to undo
596+
* truncation of the index's physical file. Disallow it.
597+
*/
598+
if (overwrite)
599+
PreventTransactionChain((void*)indexRelation,"REINDEX");
600+
600601
if (!reindex_index(indOid,force,overwrite))
601602
elog(WARNING,"index \"%s\" wasn't reindexed",indexRelation->relname);
602603
}
@@ -611,21 +612,24 @@ ReindexTable(RangeVar *relation, bool force)
611612
OidheapOid;
612613
charrelkind;
613614

614-
/*
615-
* REINDEX within a transaction block is dangerous, because if the
616-
* transaction is later rolled back we have no way to undo truncation
617-
* of the index's physical file. Disallow it.
618-
*/
619-
if (IsTransactionBlock())
620-
elog(ERROR,"REINDEX cannot run inside a BEGIN/END block");
621-
622615
heapOid=RangeVarGetRelid(relation, false);
623616
relkind=get_rel_relkind(heapOid);
624617

625618
if (relkind!=RELKIND_RELATION&&relkind!=RELKIND_TOASTVALUE)
626619
elog(ERROR,"relation \"%s\" is of type \"%c\"",
627620
relation->relname,relkind);
628621

622+
/*
623+
* In-place REINDEX within a transaction block is dangerous, because
624+
* if the transaction is later rolled back we have no way to undo
625+
* truncation of the index's physical file. Disallow it.
626+
*
627+
* XXX we assume that in-place reindex will only be done if
628+
* IsIgnoringSystemIndexes() is true.
629+
*/
630+
if (IsIgnoringSystemIndexes())
631+
PreventTransactionChain((void*)relation,"REINDEX");
632+
629633
if (!reindex_relation(heapOid,force))
630634
elog(WARNING,"table \"%s\" wasn't reindexed",relation->relname);
631635
}
@@ -666,12 +670,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
666670
* transaction, then our commit- and start-transaction-command calls
667671
* would not have the intended effect!
668672
*/
669-
if (IsTransactionBlock())
670-
elog(ERROR,"REINDEX DATABASE cannot run inside a BEGIN/END block");
671-
672-
/* Running this from a function would free the function context */
673-
if (!MemoryContextContains(QueryContext, (void*)dbname))
674-
elog(ERROR,"REINDEX DATABASE cannot be executed from a function");
673+
PreventTransactionChain((void*)dbname,"REINDEX");
675674

676675
/*
677676
* Create a memory context that will survive forced transaction

‎src/backend/commands/tablecmds.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.49 2002/10/2120:31:51 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.50 2002/10/2122:06:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -375,6 +375,16 @@ TruncateRelation(const RangeVar *relation)
375375
if (!pg_class_ownercheck(relid,GetUserId()))
376376
aclcheck_error(ACLCHECK_NOT_OWNER,RelationGetRelationName(rel));
377377

378+
/*
379+
* Truncate within a transaction block is dangerous, because if
380+
* the transaction is later rolled back we have no way to undo
381+
* truncation of the relation's physical file. Disallow it except for
382+
* a rel created in the current xact (which would be deleted on abort,
383+
* anyway).
384+
*/
385+
if (!rel->rd_isnew)
386+
PreventTransactionChain((void*)relation,"TRUNCATE TABLE");
387+
378388
/*
379389
* Don't allow truncate on temp tables of other backends ... their
380390
* local buffer manager is not going to cope.

‎src/backend/commands/vacuum.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.242 2002/10/19 20:15:09 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.243 2002/10/21 22:06:19 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -177,12 +177,8 @@ vacuum(VacuumStmt *vacstmt)
177177
* user's transaction too, which would certainly not be the desired
178178
* behavior.
179179
*/
180-
if (vacstmt->vacuum&&IsTransactionBlock())
181-
elog(ERROR,"%s cannot run inside a BEGIN/END block",stmttype);
182-
183-
/* Running VACUUM from a function would free the function context */
184-
if (vacstmt->vacuum&& !MemoryContextContains(QueryContext,vacstmt))
185-
elog(ERROR,"%s cannot be executed from a function",stmttype);
180+
if (vacstmt->vacuum)
181+
PreventTransactionChain((void*)vacstmt,stmttype);
186182

187183
/*
188184
* Send info about dead objects to the statistics collector

‎src/backend/parser/analyze.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
*$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.252 2002/10/20 00:31:53 tgl Exp $
9+
*$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.253 2002/10/21 22:06:19 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -1631,16 +1631,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
16311631
if (stmt->forUpdate)
16321632
elog(ERROR,"DECLARE/UPDATE is not supported"
16331633
"\n\tCursors must be READ ONLY");
1634-
1635-
/*
1636-
* 15 august 1991 -- since 3.0 postgres does locking right, we
1637-
* discovered that portals were violating locking protocol. portal
1638-
* locks cannot span xacts. as a short-term fix, we installed the
1639-
* check here. -- mao
1640-
*/
1641-
if (!IsTransactionBlock())
1642-
elog(ERROR,"DECLARE CURSOR may only be used in begin/end transaction blocks");
1643-
16441634
qry->into=makeNode(RangeVar);
16451635
qry->into->relname=stmt->portalname;
16461636
qry->isPortal= TRUE;
@@ -1849,16 +1839,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
18491839
if (forUpdate)
18501840
elog(ERROR,"DECLARE/UPDATE is not supported"
18511841
"\n\tCursors must be READ ONLY");
1852-
1853-
/*
1854-
* 15 august 1991 -- since 3.0 postgres does locking right, we
1855-
* discovered that portals were violating locking protocol. portal
1856-
* locks cannot span xacts. as a short-term fix, we installed the
1857-
* check here. -- mao
1858-
*/
1859-
if (!IsTransactionBlock())
1860-
elog(ERROR,"DECLARE CURSOR may only be used in begin/end transaction blocks");
1861-
18621842
qry->into=makeNode(RangeVar);
18631843
qry->into->relname=portalname;
18641844
qry->isPortal= TRUE;

‎src/include/access/xact.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: xact.h,v 1.45 2002/08/30 22:18:07 tgl Exp $
10+
* $Id: xact.h,v 1.46 2002/10/21 22:06:20 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -113,6 +113,7 @@ extern void EndTransactionBlock(void);
113113
externboolIsTransactionBlock(void);
114114
externvoidUserAbortTransactionBlock(void);
115115
externvoidAbortOutOfAnyTransaction(void);
116+
externvoidPreventTransactionChain(void*stmtNode,constchar*stmtType);
116117

117118
externvoidRecordTransactionCommit(void);
118119

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp