mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Fix places that were using IsTransactionBlock() as an (inadequate) check
that they'd get to commit immediately on finishing. There's now a centralized routine PreventTransactionChain() that implements the necessary tests.
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.105 2002/09/04 20:31:15 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.106 2002/10/21 22:06:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -152,8 +152,7 @@ createdb(const CreatedbStmt *stmt)
|
||||
}
|
||||
|
||||
/* don't call this in a transaction block */
|
||||
if (IsTransactionBlock())
|
||||
elog(ERROR, "CREATE DATABASE: may not be called in a transaction block");
|
||||
PreventTransactionChain((void *) stmt, "CREATE DATABASE");
|
||||
|
||||
/*
|
||||
* Check for db name conflict. There is a race condition here, since
|
||||
@ -382,8 +381,7 @@ dropdb(const char *dbname)
|
||||
if (strcmp(dbname, DatabaseName) == 0)
|
||||
elog(ERROR, "DROP DATABASE: cannot be executed on the currently open database");
|
||||
|
||||
if (IsTransactionBlock())
|
||||
elog(ERROR, "DROP DATABASE: may not be called in a transaction block");
|
||||
PreventTransactionChain((void *) dbname, "DROP DATABASE");
|
||||
|
||||
/*
|
||||
* Obtain exclusive lock on pg_database. We need this to ensure that
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.91 2002/10/19 20:15:08 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.92 2002/10/21 22:06:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -560,15 +560,10 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ )
|
||||
{
|
||||
Oid indOid;
|
||||
HeapTuple tuple;
|
||||
bool overwrite = false;
|
||||
bool overwrite;
|
||||
|
||||
/*
|
||||
* REINDEX within a transaction block is dangerous, because if the
|
||||
* transaction is later rolled back we have no way to undo truncation
|
||||
* of the index's physical file. Disallow it.
|
||||
*/
|
||||
if (IsTransactionBlock())
|
||||
elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
|
||||
/* Choose in-place-or-not mode */
|
||||
overwrite = IsIgnoringSystemIndexes();
|
||||
|
||||
indOid = RangeVarGetRelid(indexRelation, false);
|
||||
tuple = SearchSysCache(RELOID,
|
||||
@ -595,8 +590,14 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ )
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
if (IsIgnoringSystemIndexes())
|
||||
overwrite = true;
|
||||
/*
|
||||
* In-place REINDEX within a transaction block is dangerous, because
|
||||
* if the transaction is later rolled back we have no way to undo
|
||||
* truncation of the index's physical file. Disallow it.
|
||||
*/
|
||||
if (overwrite)
|
||||
PreventTransactionChain((void *) indexRelation, "REINDEX");
|
||||
|
||||
if (!reindex_index(indOid, force, overwrite))
|
||||
elog(WARNING, "index \"%s\" wasn't reindexed", indexRelation->relname);
|
||||
}
|
||||
@ -611,14 +612,6 @@ ReindexTable(RangeVar *relation, bool force)
|
||||
Oid heapOid;
|
||||
char relkind;
|
||||
|
||||
/*
|
||||
* REINDEX within a transaction block is dangerous, because if the
|
||||
* transaction is later rolled back we have no way to undo truncation
|
||||
* of the index's physical file. Disallow it.
|
||||
*/
|
||||
if (IsTransactionBlock())
|
||||
elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
|
||||
|
||||
heapOid = RangeVarGetRelid(relation, false);
|
||||
relkind = get_rel_relkind(heapOid);
|
||||
|
||||
@ -626,6 +619,17 @@ ReindexTable(RangeVar *relation, bool force)
|
||||
elog(ERROR, "relation \"%s\" is of type \"%c\"",
|
||||
relation->relname, relkind);
|
||||
|
||||
/*
|
||||
* In-place REINDEX within a transaction block is dangerous, because
|
||||
* if the transaction is later rolled back we have no way to undo
|
||||
* truncation of the index's physical file. Disallow it.
|
||||
*
|
||||
* XXX we assume that in-place reindex will only be done if
|
||||
* IsIgnoringSystemIndexes() is true.
|
||||
*/
|
||||
if (IsIgnoringSystemIndexes())
|
||||
PreventTransactionChain((void *) relation, "REINDEX");
|
||||
|
||||
if (!reindex_relation(heapOid, force))
|
||||
elog(WARNING, "table \"%s\" wasn't reindexed", relation->relname);
|
||||
}
|
||||
@ -666,12 +670,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
|
||||
* transaction, then our commit- and start-transaction-command calls
|
||||
* would not have the intended effect!
|
||||
*/
|
||||
if (IsTransactionBlock())
|
||||
elog(ERROR, "REINDEX DATABASE cannot run inside a BEGIN/END block");
|
||||
|
||||
/* Running this from a function would free the function context */
|
||||
if (!MemoryContextContains(QueryContext, (void *) dbname))
|
||||
elog(ERROR, "REINDEX DATABASE cannot be executed from a function");
|
||||
PreventTransactionChain((void *) dbname, "REINDEX");
|
||||
|
||||
/*
|
||||
* Create a memory context that will survive forced transaction
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.49 2002/10/21 20:31:51 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.50 2002/10/21 22:06:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -375,6 +375,16 @@ TruncateRelation(const RangeVar *relation)
|
||||
if (!pg_class_ownercheck(relid, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Truncate within a transaction block is dangerous, because if
|
||||
* the transaction is later rolled back we have no way to undo
|
||||
* truncation of the relation's physical file. Disallow it except for
|
||||
* a rel created in the current xact (which would be deleted on abort,
|
||||
* anyway).
|
||||
*/
|
||||
if (!rel->rd_isnew)
|
||||
PreventTransactionChain((void *) relation, "TRUNCATE TABLE");
|
||||
|
||||
/*
|
||||
* Don't allow truncate on temp tables of other backends ... their
|
||||
* local buffer manager is not going to cope.
|
||||
|
@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.242 2002/10/19 20:15:09 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.243 2002/10/21 22:06:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -177,12 +177,8 @@ vacuum(VacuumStmt *vacstmt)
|
||||
* user's transaction too, which would certainly not be the desired
|
||||
* behavior.
|
||||
*/
|
||||
if (vacstmt->vacuum && IsTransactionBlock())
|
||||
elog(ERROR, "%s cannot run inside a BEGIN/END block", stmttype);
|
||||
|
||||
/* Running VACUUM from a function would free the function context */
|
||||
if (vacstmt->vacuum && !MemoryContextContains(QueryContext, vacstmt))
|
||||
elog(ERROR, "%s cannot be executed from a function", stmttype);
|
||||
if (vacstmt->vacuum)
|
||||
PreventTransactionChain((void *) vacstmt, stmttype);
|
||||
|
||||
/*
|
||||
* Send info about dead objects to the statistics collector
|
||||
|
Reference in New Issue
Block a user