mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-02 13:51:27 +02:00
Fix CLUSTER ... or at least undo the bit-rot it's suffered since 6.5.
It's still pretty fundamentally bogus :-(. Freebie side benefit: ALTER TABLE RENAME works on indexes now.
This commit is contained in:
parent
e10c5597b7
commit
37c652f89b
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.51 2000/04/12 17:14:57 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.52 2000/05/11 03:54:17 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -27,7 +27,6 @@
|
|||||||
#include "catalog/heap.h"
|
#include "catalog/heap.h"
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_type.h"
|
|
||||||
#include "commands/cluster.h"
|
#include "commands/cluster.h"
|
||||||
#include "commands/rename.h"
|
#include "commands/rename.h"
|
||||||
#include "optimizer/internal.h"
|
#include "optimizer/internal.h"
|
||||||
@ -80,26 +79,13 @@ cluster(char *oldrelname, char *oldindexname)
|
|||||||
char saveoldrelname[NAMEDATALEN];
|
char saveoldrelname[NAMEDATALEN];
|
||||||
char saveoldindexname[NAMEDATALEN];
|
char saveoldindexname[NAMEDATALEN];
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the old names because they will get lost when the old
|
* Copy the arguments into local storage, because they are probably
|
||||||
* relations are destroyed.
|
* in palloc'd storage that will go away when we commit a transaction.
|
||||||
*/
|
*/
|
||||||
strcpy(saveoldrelname, oldrelname);
|
strcpy(saveoldrelname, oldrelname);
|
||||||
strcpy(saveoldindexname, oldindexname);
|
strcpy(saveoldindexname, oldindexname);
|
||||||
|
|
||||||
/*
|
|
||||||
* I'm going to force all checking back into the commands.c function.
|
|
||||||
*
|
|
||||||
* Get the list if indicies for this relation. If the index we want is
|
|
||||||
* among them, do not add it to the 'kill' list, as it will be handled
|
|
||||||
* by the 'clean up' code which commits this transaction.
|
|
||||||
*
|
|
||||||
* I'm not using the SysCache, because this will happen but once, and the
|
|
||||||
* slow way is the sure way in this case.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Like vacuum, cluster spans transactions, so I'm going to handle it
|
* Like vacuum, cluster spans transactions, so I'm going to handle it
|
||||||
* in the same way: commit and restart transactions where needed.
|
* in the same way: commit and restart transactions where needed.
|
||||||
@ -108,13 +94,17 @@ cluster(char *oldrelname, char *oldindexname)
|
|||||||
* of the initial transaction.
|
* of the initial transaction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
OldHeap = heap_openr(oldrelname, AccessExclusiveLock);
|
OldHeap = heap_openr(saveoldrelname, AccessExclusiveLock);
|
||||||
OIDOldHeap = RelationGetRelid(OldHeap);
|
OIDOldHeap = RelationGetRelid(OldHeap);
|
||||||
|
|
||||||
OldIndex = index_openr(oldindexname); /* Open old index relation */
|
OldIndex = index_openr(saveoldindexname); /* Open old index relation */
|
||||||
LockRelation(OldIndex, AccessExclusiveLock);
|
LockRelation(OldIndex, AccessExclusiveLock);
|
||||||
OIDOldIndex = RelationGetRelid(OldIndex);
|
OIDOldIndex = RelationGetRelid(OldIndex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Should check that index is in fact an index on this relation?
|
||||||
|
*/
|
||||||
|
|
||||||
heap_close(OldHeap, NoLock);/* do NOT give up the locks */
|
heap_close(OldHeap, NoLock);/* do NOT give up the locks */
|
||||||
index_close(OldIndex);
|
index_close(OldIndex);
|
||||||
|
|
||||||
@ -130,7 +120,6 @@ cluster(char *oldrelname, char *oldindexname)
|
|||||||
OIDNewHeap = RelationGetRelid(NewHeap);
|
OIDNewHeap = RelationGetRelid(NewHeap);
|
||||||
strcpy(NewHeapName, RelationGetRelationName(NewHeap));
|
strcpy(NewHeapName, RelationGetRelationName(NewHeap));
|
||||||
|
|
||||||
|
|
||||||
/* To make the new heap visible (which is until now empty). */
|
/* To make the new heap visible (which is until now empty). */
|
||||||
CommandCounterIncrement();
|
CommandCounterIncrement();
|
||||||
|
|
||||||
@ -150,23 +139,14 @@ cluster(char *oldrelname, char *oldindexname)
|
|||||||
CommitTransactionCommand();
|
CommitTransactionCommand();
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
|
|
||||||
|
|
||||||
/* Destroy old heap (along with its index) and rename new. */
|
/* Destroy old heap (along with its index) and rename new. */
|
||||||
heap_drop_with_catalog(oldrelname);
|
heap_drop_with_catalog(saveoldrelname);
|
||||||
|
|
||||||
CommitTransactionCommand();
|
CommitTransactionCommand();
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
|
|
||||||
renamerel(NewHeapName, saveoldrelname);
|
renamerel(NewHeapName, saveoldrelname);
|
||||||
TypeRename(NewHeapName, saveoldrelname);
|
|
||||||
|
|
||||||
renamerel(NewIndexName, saveoldindexname);
|
renamerel(NewIndexName, saveoldindexname);
|
||||||
|
|
||||||
/*
|
|
||||||
* Again flush all the buffers. XXX perhaps not needed?
|
|
||||||
*/
|
|
||||||
CommitTransactionCommand();
|
|
||||||
StartTransactionCommand();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Relation
|
static Relation
|
||||||
@ -298,6 +278,8 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
|
|||||||
Old_pg_index_Form->indisunique,
|
Old_pg_index_Form->indisunique,
|
||||||
Old_pg_index_Form->indisprimary);
|
Old_pg_index_Form->indisprimary);
|
||||||
|
|
||||||
|
setRelhasindexInplace(OIDNewHeap, true, false);
|
||||||
|
|
||||||
index_close(OldIndex);
|
index_close(OldIndex);
|
||||||
heap_close(NewHeap, AccessExclusiveLock);
|
heap_close(NewHeap, AccessExclusiveLock);
|
||||||
}
|
}
|
||||||
@ -311,9 +293,6 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
|
|||||||
LocalOldIndex;
|
LocalOldIndex;
|
||||||
IndexScanDesc ScanDesc;
|
IndexScanDesc ScanDesc;
|
||||||
RetrieveIndexResult ScanResult;
|
RetrieveIndexResult ScanResult;
|
||||||
HeapTupleData LocalHeapTuple;
|
|
||||||
Buffer LocalBuffer;
|
|
||||||
Oid OIDNewHeapInsert;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the relations I need. Scan through the OldHeap on the OldIndex
|
* Open the relations I need. Scan through the OldHeap on the OldIndex
|
||||||
@ -321,21 +300,24 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
|
|||||||
*/
|
*/
|
||||||
LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
|
LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
|
||||||
LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
|
LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
|
||||||
LocalOldIndex = (Relation) index_open(OIDOldIndex);
|
LocalOldIndex = index_open(OIDOldIndex);
|
||||||
|
|
||||||
ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
|
ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
|
||||||
|
|
||||||
while ((ScanResult = index_getnext(ScanDesc, ForwardScanDirection)) != NULL)
|
while ((ScanResult = index_getnext(ScanDesc, ForwardScanDirection)) != NULL)
|
||||||
{
|
{
|
||||||
|
HeapTupleData LocalHeapTuple;
|
||||||
|
Buffer LocalBuffer;
|
||||||
|
|
||||||
LocalHeapTuple.t_self = ScanResult->heap_iptr;
|
LocalHeapTuple.t_self = ScanResult->heap_iptr;
|
||||||
LocalHeapTuple.t_datamcxt = NULL;
|
LocalHeapTuple.t_datamcxt = NULL;
|
||||||
LocalHeapTuple.t_data = NULL;
|
LocalHeapTuple.t_data = NULL;
|
||||||
heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer);
|
heap_fetch(LocalOldHeap, SnapshotNow, &LocalHeapTuple, &LocalBuffer);
|
||||||
OIDNewHeapInsert = heap_insert(LocalNewHeap, &LocalHeapTuple);
|
heap_insert(LocalNewHeap, &LocalHeapTuple);
|
||||||
pfree(ScanResult);
|
|
||||||
ReleaseBuffer(LocalBuffer);
|
ReleaseBuffer(LocalBuffer);
|
||||||
|
pfree(ScanResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
index_endscan(ScanDesc);
|
index_endscan(ScanDesc);
|
||||||
|
|
||||||
index_close(LocalOldIndex);
|
index_close(LocalOldIndex);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.42 2000/04/12 17:14:59 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.43 2000/05/11 03:54:18 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
|
#include "catalog/pg_type.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "catalog/heap.h"
|
#include "catalog/heap.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
@ -27,6 +28,8 @@
|
|||||||
#include "storage/smgr.h"
|
#include "storage/smgr.h"
|
||||||
#include "optimizer/prep.h"
|
#include "optimizer/prep.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
|
#include "utils/relcache.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* renameatt - changes the name of a attribute in a relation
|
* renameatt - changes the name of a attribute in a relation
|
||||||
@ -180,6 +183,7 @@ renamerel(const char *oldrelname, const char *newrelname)
|
|||||||
Relation targetrelation;
|
Relation targetrelation;
|
||||||
Relation relrelation; /* for RELATION relation */
|
Relation relrelation; /* for RELATION relation */
|
||||||
HeapTuple oldreltup;
|
HeapTuple oldreltup;
|
||||||
|
char relkind;
|
||||||
char oldpath[MAXPGPATH],
|
char oldpath[MAXPGPATH],
|
||||||
newpath[MAXPGPATH],
|
newpath[MAXPGPATH],
|
||||||
toldpath[MAXPGPATH + 10],
|
toldpath[MAXPGPATH + 10],
|
||||||
@ -194,11 +198,20 @@ renamerel(const char *oldrelname, const char *newrelname)
|
|||||||
elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
|
elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
|
||||||
newrelname);
|
newrelname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instead of using heap_openr(), do it the hard way, so that we
|
||||||
|
* can rename indexes as well as regular relations.
|
||||||
|
*/
|
||||||
|
targetrelation = RelationNameGetRelation(oldrelname);
|
||||||
|
|
||||||
|
if (!RelationIsValid(targetrelation))
|
||||||
|
elog(ERROR, "Relation '%s' does not exist", oldrelname);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Grab an exclusive lock on the target table, which we will NOT
|
* Grab an exclusive lock on the target table, which we will NOT
|
||||||
* release until end of transaction.
|
* release until end of transaction.
|
||||||
*/
|
*/
|
||||||
targetrelation = heap_openr(oldrelname, AccessExclusiveLock);
|
LockRelation(targetrelation, AccessExclusiveLock);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* RENAME TABLE within a transaction block is dangerous, because
|
* RENAME TABLE within a transaction block is dangerous, because
|
||||||
@ -215,6 +228,8 @@ renamerel(const char *oldrelname, const char *newrelname)
|
|||||||
if (IsTransactionBlock() && !targetrelation->rd_myxactonly)
|
if (IsTransactionBlock() && !targetrelation->rd_myxactonly)
|
||||||
elog(NOTICE, "Caution: RENAME TABLE cannot be rolled back, so don't abort now");
|
elog(NOTICE, "Caution: RENAME TABLE cannot be rolled back, so don't abort now");
|
||||||
|
|
||||||
|
relkind = targetrelation->rd_rel->relkind;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush all blocks of the relation out of the buffer pool. We need
|
* Flush all blocks of the relation out of the buffer pool. We need
|
||||||
* this because the blocks are marked with the relation's name as well
|
* this because the blocks are marked with the relation's name as well
|
||||||
@ -304,4 +319,10 @@ renamerel(const char *oldrelname, const char *newrelname)
|
|||||||
CatalogCloseIndices(Num_pg_class_indices, irelations);
|
CatalogCloseIndices(Num_pg_class_indices, irelations);
|
||||||
|
|
||||||
heap_close(relrelation, RowExclusiveLock);
|
heap_close(relrelation, RowExclusiveLock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also rename the associated type, if any.
|
||||||
|
*/
|
||||||
|
if (relkind != RELKIND_INDEX)
|
||||||
|
TypeRename(oldrelname, newrelname);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.87 2000/04/25 10:38:38 inoue Exp $
|
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.88 2000/05/11 03:54:18 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "catalog/catalog.h"
|
#include "catalog/catalog.h"
|
||||||
#include "catalog/pg_type.h"
|
|
||||||
#include "commands/async.h"
|
#include "commands/async.h"
|
||||||
#include "commands/cluster.h"
|
#include "commands/cluster.h"
|
||||||
#include "commands/command.h"
|
#include "commands/command.h"
|
||||||
@ -315,8 +314,6 @@ ProcessUtility(Node *parsetree,
|
|||||||
*/
|
*/
|
||||||
renamerel(relname, /* old name */
|
renamerel(relname, /* old name */
|
||||||
stmt->newname); /* new name */
|
stmt->newname); /* new name */
|
||||||
TypeRename(relname, /* old name */
|
|
||||||
stmt->newname); /* new name */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user