Commit 0041202b authored by Tom Lane's avatar Tom Lane

Disallow DROP TABLE/DROP INDEX inside a transaction block.

We can't support these properly, since once the relation's physical files
are unlinked, there's no way to roll back the transaction.  I suppose
we could postpone the unlink till transaction commit, but then what of
BEGIN; DROP TABLE foo; CREATE TABLE foo; ?
The code does allow dropping a table/index created in the current
transaction block, however, since the post-abort state would be that
the table doesn't exist anyway.
parent 6645a738
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.94 1999/09/04 22:00:29 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.95 1999/09/05 17:43:47 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "miscadmin.h" #include "miscadmin.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "access/xact.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/heap.h" #include "catalog/heap.h"
...@@ -1232,7 +1233,7 @@ heap_destroy_with_catalog(char *relname) ...@@ -1232,7 +1233,7 @@ heap_destroy_with_catalog(char *relname)
bool istemp = (get_temp_rel_by_name(relname) != NULL); bool istemp = (get_temp_rel_by_name(relname) != NULL);
/* ---------------- /* ----------------
* first open the relation. if the relation does exist, * first open the relation. if the relation doesn't exist,
* heap_openr() returns NULL. * heap_openr() returns NULL.
* ---------------- * ----------------
*/ */
...@@ -1253,6 +1254,17 @@ heap_destroy_with_catalog(char *relname) ...@@ -1253,6 +1254,17 @@ heap_destroy_with_catalog(char *relname)
elog(ERROR, "System relation '%s' cannot be destroyed", elog(ERROR, "System relation '%s' cannot be destroyed",
&rel->rd_rel->relname); &rel->rd_rel->relname);
/* ----------------
* We do not allow DROP TABLE within a transaction block, because
* if the transaction is later rolled back there would be no way to
* undo the unlink of the relation's physical file. The sole exception
* is for relations created in the current transaction, since the post-
* abort state would be that they don't exist anyway.
* ----------------
*/
if (IsTransactionBlock() && ! rel->rd_myxactonly)
elog(ERROR, "Cannot destroy relation within a transaction block");
/* ---------------- /* ----------------
* remove inheritance information * remove inheritance information
* ---------------- * ----------------
...@@ -1307,17 +1319,10 @@ heap_destroy_with_catalog(char *relname) ...@@ -1307,17 +1319,10 @@ heap_destroy_with_catalog(char *relname)
*/ */
ReleaseRelationBuffers(rel); ReleaseRelationBuffers(rel);
/* ----------------
* flush the relation from the relcache
* ----------------
* Does nothing!!! Flushing moved below. - vadim 06/04/97
RelationIdInvalidateRelationCacheByRelationId(rel->rd_id);
*/
RemoveConstraints(rel); RemoveConstraints(rel);
/* ---------------- /* ----------------
* unlink the relation and finish up. * unlink the relation's physical file and finish up.
* ---------------- * ----------------
*/ */
if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked)) if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
...@@ -1329,6 +1334,10 @@ heap_destroy_with_catalog(char *relname) ...@@ -1329,6 +1334,10 @@ heap_destroy_with_catalog(char *relname)
heap_close(rel); heap_close(rel);
/* ----------------
* flush the relation from the relcache
* ----------------
*/
RelationForgetRelation(rid); RelationForgetRelation(rid);
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.88 1999/09/04 22:00:29 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.89 1999/09/05 17:43:47 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "access/genam.h" #include "access/genam.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "access/istrat.h" #include "access/istrat.h"
#include "access/xact.h"
#include "bootstrap/bootstrap.h" #include "bootstrap/bootstrap.h"
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/heap.h" #include "catalog/heap.h"
...@@ -1105,6 +1106,17 @@ index_destroy(Oid indexId) ...@@ -1105,6 +1106,17 @@ index_destroy(Oid indexId)
/* Open now to obtain lock by referencing table? bjm */ /* Open now to obtain lock by referencing table? bjm */
userindexRelation = index_open(indexId); userindexRelation = index_open(indexId);
/* ----------------
* We do not allow DROP INDEX within a transaction block, because
* if the transaction is later rolled back there would be no way to
* undo the unlink of the relation's physical file. The sole exception
* is for relations created in the current transaction, since the post-
* abort state would be that they don't exist anyway.
* ----------------
*/
if (IsTransactionBlock() && ! userindexRelation->rd_myxactonly)
elog(ERROR, "Cannot destroy index within a transaction block");
/* ---------------- /* ----------------
* fix RELATION relation * fix RELATION relation
* ---------------- * ----------------
...@@ -1164,7 +1176,7 @@ index_destroy(Oid indexId) ...@@ -1164,7 +1176,7 @@ index_destroy(Oid indexId)
ReleaseRelationBuffers(userindexRelation); ReleaseRelationBuffers(userindexRelation);
if (smgrunlink(DEFAULT_SMGR, userindexRelation) != SM_SUCCESS) if (smgrunlink(DEFAULT_SMGR, userindexRelation) != SM_SUCCESS)
elog(ERROR, "amdestroyr: unlink: %m"); elog(ERROR, "index_destroy: unlink: %m");
index_close(userindexRelation); index_close(userindexRelation);
RelationForgetRelation(RelationGetRelid(userindexRelation)); RelationForgetRelation(RelationGetRelid(userindexRelation));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment