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

Commit8325a8d

Browse files
committed
Make ALTER COLUMN TYPE preserve clustered status for indexes it doesn't
modify. Also fix a passel of problems with ALTER TABLE CLUSTER ON:failure to check that the index is safe to cluster on (or even belongsto the indicated rel, or even exists), and failure to broadcast a relcacheflush event when changing an index's state.
1 parenteee6f9d commit8325a8d

File tree

5 files changed

+100
-39
lines changed

5 files changed

+100
-39
lines changed

‎src/backend/commands/cluster.c

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.121 2004/05/05 04:48:45 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.122 2004/05/06 16:10:57 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -31,6 +31,7 @@
3131
#include"miscadmin.h"
3232
#include"utils/acl.h"
3333
#include"utils/fmgroids.h"
34+
#include"utils/inval.h"
3435
#include"utils/lsyscache.h"
3536
#include"utils/syscache.h"
3637
#include"utils/relcache.h"
@@ -48,7 +49,6 @@ typedef struct
4849
IndexInfo*indexInfo;
4950
OidaccessMethodOID;
5051
Oid*classOID;
51-
boolisclustered;
5252
}IndexAttrs;
5353

5454
/*
@@ -246,8 +246,7 @@ cluster(ClusterStmt *stmt)
246246
staticvoid
247247
cluster_rel(RelToCluster*rvtc,boolrecheck)
248248
{
249-
RelationOldHeap,
250-
OldIndex;
249+
RelationOldHeap;
251250

252251
/* Check for user-requested abort. */
253252
CHECK_FOR_INTERRUPTS();
@@ -300,18 +299,41 @@ cluster_rel(RelToCluster *rvtc, bool recheck)
300299
/*
301300
* We grab exclusive access to the target rel and index for the
302301
* duration of the transaction. (This is redundant for the single-
303-
* transaction case, since cluster() already did it.)
302+
* transaction case, since cluster() already did it.) The index
303+
* lock is taken inside check_index_is_clusterable.
304304
*/
305305
OldHeap=heap_open(rvtc->tableOid,AccessExclusiveLock);
306306

307-
OldIndex=index_open(rvtc->indexOid);
307+
/* Check index is valid to cluster on */
308+
check_index_is_clusterable(OldHeap,rvtc->indexOid);
309+
310+
/* rebuild_relation does all the dirty work */
311+
rebuild_relation(OldHeap,rvtc->indexOid);
312+
313+
/* NB: rebuild_relation does heap_close() on OldHeap */
314+
}
315+
316+
/*
317+
* Verify that the specified index is a legitimate index to cluster on
318+
*
319+
* Side effect: obtains exclusive lock on the index. The caller should
320+
* already have exclusive lock on the table, so the index lock is likely
321+
* redundant, but it seems best to grab it anyway to ensure the index
322+
* definition can't change under us.
323+
*/
324+
void
325+
check_index_is_clusterable(RelationOldHeap,OidindexOid)
326+
{
327+
RelationOldIndex;
328+
329+
OldIndex=index_open(indexOid);
308330
LockRelation(OldIndex,AccessExclusiveLock);
309331

310332
/*
311333
* Check that index is in fact an index on the given relation
312334
*/
313335
if (OldIndex->rd_index==NULL||
314-
OldIndex->rd_index->indrelid!=rvtc->tableOid)
336+
OldIndex->rd_index->indrelid!=RelationGetRelid(OldHeap))
315337
ereport(ERROR,
316338
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
317339
errmsg("\"%s\" is not an index for table \"%s\"",
@@ -386,11 +408,6 @@ cluster_rel(RelToCluster *rvtc, bool recheck)
386408

387409
/* Drop relcache refcnt on OldIndex, but keep lock */
388410
index_close(OldIndex);
389-
390-
/* rebuild_relation does all the dirty work */
391-
rebuild_relation(OldHeap,rvtc->indexOid);
392-
393-
/* NB: rebuild_relation does heap_close() on OldHeap */
394411
}
395412

396413
/*
@@ -410,13 +427,14 @@ void
410427
rebuild_relation(RelationOldHeap,OidindexOid)
411428
{
412429
OidtableOid=RelationGetRelid(OldHeap);
430+
OidoldClusterIndex;
413431
List*indexes;
414432
OidOIDNewHeap;
415433
charNewHeapName[NAMEDATALEN];
416434
ObjectAddressobject;
417435

418436
/* Save the information about all indexes on the relation. */
419-
indexes=get_indexattr_list(OldHeap,indexOid);
437+
indexes=get_indexattr_list(OldHeap,&oldClusterIndex);
420438

421439
/* Close relcache entry, but keep lock until transaction commit */
422440
heap_close(OldHeap,NoLock);
@@ -469,7 +487,8 @@ rebuild_relation(Relation OldHeap, Oid indexOid)
469487
* Recreate each index on the relation. We do not need
470488
* CommandCounterIncrement() because rebuild_indexes does it.
471489
*/
472-
rebuild_indexes(tableOid,indexes);
490+
rebuild_indexes(tableOid,indexes,
491+
(OidIsValid(indexOid) ?indexOid :oldClusterIndex));
473492
}
474493

475494
/*
@@ -572,14 +591,18 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
572591

573592
/*
574593
* Get the necessary info about the indexes of the relation and
575-
* return a list of IndexAttrs structures.
594+
* return a list of IndexAttrs structures. Also, *OldClusterIndex
595+
* is set to the OID of the existing clustered index, or InvalidOid
596+
* if there is none.
576597
*/
577598
List*
578-
get_indexattr_list(RelationOldHeap,OidOldIndex)
599+
get_indexattr_list(RelationOldHeap,Oid*OldClusterIndex)
579600
{
580601
List*indexes=NIL;
581602
List*indlist;
582603

604+
*OldClusterIndex=InvalidOid;
605+
583606
/* Ask the relcache to produce a list of the indexes of the old rel */
584607
foreach(indlist,RelationGetIndexList(OldHeap))
585608
{
@@ -598,16 +621,12 @@ get_indexattr_list(Relation OldHeap, Oid OldIndex)
598621
palloc(sizeof(Oid)*attrs->indexInfo->ii_NumIndexAttrs);
599622
memcpy(attrs->classOID,oldIndex->rd_index->indclass,
600623
sizeof(Oid)*attrs->indexInfo->ii_NumIndexAttrs);
601-
/* We adjust the isclustered attribute to correct new state */
602-
attrs->isclustered=(indexOID==OldIndex);
624+
if (oldIndex->rd_index->indisclustered)
625+
*OldClusterIndex=indexOID;
603626

604627
index_close(oldIndex);
605628

606-
/*
607-
* Cons the gathered data into the list. We do not care about
608-
* ordering, and this is more efficient than append.
609-
*/
610-
indexes=lcons(attrs,indexes);
629+
indexes=lappend(indexes,attrs);
611630
}
612631

613632
returnindexes;
@@ -616,25 +635,30 @@ get_indexattr_list(Relation OldHeap, Oid OldIndex)
616635
/*
617636
* Create new indexes and swap the filenodes with old indexes.Then drop
618637
* the new index (carrying the old index filenode along).
638+
*
639+
* OIDClusterIndex is the OID of the index to be marked as clustered, or
640+
* InvalidOid if none should be marked clustered.
619641
*/
620642
void
621-
rebuild_indexes(OidOIDOldHeap,List*indexes)
643+
rebuild_indexes(OidOIDOldHeap,List*indexes,OidOIDClusterIndex)
622644
{
623645
List*elem;
624646

625647
foreach(elem,indexes)
626648
{
627649
IndexAttrs*attrs= (IndexAttrs*)lfirst(elem);
650+
OidoldIndexOID=attrs->indexOID;
628651
OidnewIndexOID;
629652
charnewIndexName[NAMEDATALEN];
653+
boolisclustered;
630654
ObjectAddressobject;
631655
Form_pg_indexindex;
632656
HeapTupletuple;
633657
Relationpg_index;
634658

635659
/* Create the new index under a temporary name */
636660
snprintf(newIndexName,sizeof(newIndexName),
637-
"pg_temp_%u",attrs->indexOID);
661+
"pg_temp_%u",oldIndexOID);
638662

639663
/*
640664
* The new index will have primary and constraint status set to
@@ -654,26 +678,30 @@ rebuild_indexes(Oid OIDOldHeap, List *indexes)
654678
CommandCounterIncrement();
655679

656680
/* Swap the filenodes. */
657-
swap_relfilenodes(attrs->indexOID,newIndexOID);
681+
swap_relfilenodes(oldIndexOID,newIndexOID);
658682

659683
CommandCounterIncrement();
660684

661685
/*
662686
* Make sure that indisclustered is correct: it should be set only
663-
* for the indexwe just clustered on.
687+
* for the indexspecified by the caller.
664688
*/
689+
isclustered= (oldIndexOID==OIDClusterIndex);
690+
665691
pg_index=heap_openr(IndexRelationName,RowExclusiveLock);
666692
tuple=SearchSysCacheCopy(INDEXRELID,
667-
ObjectIdGetDatum(attrs->indexOID),
693+
ObjectIdGetDatum(oldIndexOID),
668694
0,0,0);
669695
if (!HeapTupleIsValid(tuple))
670-
elog(ERROR,"cache lookup failed for index %u",attrs->indexOID);
696+
elog(ERROR,"cache lookup failed for index %u",oldIndexOID);
671697
index= (Form_pg_index)GETSTRUCT(tuple);
672-
if (index->indisclustered!=attrs->isclustered)
698+
if (index->indisclustered!=isclustered)
673699
{
674-
index->indisclustered=attrs->isclustered;
700+
index->indisclustered=isclustered;
675701
simple_heap_update(pg_index,&tuple->t_self,tuple);
676702
CatalogUpdateIndexes(pg_index,tuple);
703+
/* Ensure we see the update in the index's relcache entry */
704+
CacheInvalidateRelcacheByRelid(oldIndexOID);
677705
}
678706
heap_freetuple(tuple);
679707
heap_close(pg_index,RowExclusiveLock);

‎src/backend/commands/tablecmds.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.103 2004/05/05 04:48:45 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.104 2004/05/06 16:10:57 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2099,12 +2099,13 @@ ATRewriteTables(List **wqueue)
20992099
OidOIDNewHeap;
21002100
charNewHeapName[NAMEDATALEN];
21012101
List*indexes;
2102+
OidoldClusterIndex;
21022103
RelationOldHeap;
21032104
ObjectAddressobject;
21042105

21052106
/* Save the information about all indexes on the relation. */
21062107
OldHeap=heap_open(tab->relid,NoLock);
2107-
indexes=get_indexattr_list(OldHeap,InvalidOid);
2108+
indexes=get_indexattr_list(OldHeap,&oldClusterIndex);
21082109
heap_close(OldHeap,NoLock);
21092110

21102111
/*
@@ -2148,7 +2149,7 @@ ATRewriteTables(List **wqueue)
21482149
* Rebuild each index on the relation. We do not need
21492150
* CommandCounterIncrement() because rebuild_indexes does it.
21502151
*/
2151-
rebuild_indexes(tab->relid,indexes);
2152+
rebuild_indexes(tab->relid,indexes,oldClusterIndex);
21522153
}
21532154
else
21542155
{
@@ -5004,6 +5005,9 @@ ATExecClusterOn(Relation rel, const char *indexName)
50045005
errmsg("index \"%s\" for table \"%s\" does not exist",
50055006
indexName,RelationGetRelationName(rel))));
50065007

5008+
/* Check index is valid to cluster on */
5009+
check_index_is_clusterable(rel,indexOid);
5010+
50075011
indexTuple=SearchSysCache(INDEXRELID,
50085012
ObjectIdGetDatum(indexOid),
50095013
0,0,0);
@@ -5050,12 +5054,16 @@ ATExecClusterOn(Relation rel, const char *indexName)
50505054
idxForm->indisclustered= false;
50515055
simple_heap_update(pg_index,&idxtuple->t_self,idxtuple);
50525056
CatalogUpdateIndexes(pg_index,idxtuple);
5057+
/* Ensure we see the update in the index's relcache entry */
5058+
CacheInvalidateRelcacheByRelid(indexOid);
50535059
}
50545060
elseif (idxForm->indexrelid==indexForm->indexrelid)
50555061
{
50565062
idxForm->indisclustered= true;
50575063
simple_heap_update(pg_index,&idxtuple->t_self,idxtuple);
50585064
CatalogUpdateIndexes(pg_index,idxtuple);
5065+
/* Ensure we see the update in the index's relcache entry */
5066+
CacheInvalidateRelcacheByRelid(indexOid);
50595067
}
50605068
heap_freetuple(idxtuple);
50615069
}

‎src/backend/utils/cache/inval.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
* Portions Copyright (c) 1994, Regents of the University of California
7575
*
7676
* IDENTIFICATION
77-
* $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.60 2004/02/10 01:55:26 tgl Exp $
77+
* $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.61 2004/05/06 16:10:57 tgl Exp $
7878
*
7979
*-------------------------------------------------------------------------
8080
*/
@@ -88,6 +88,7 @@
8888
#include"utils/inval.h"
8989
#include"utils/memutils.h"
9090
#include"utils/relcache.h"
91+
#include"utils/syscache.h"
9192

9293

9394
/*
@@ -765,6 +766,26 @@ CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
765766
RegisterRelcacheInvalidation(databaseId,relationId,rnode);
766767
}
767768

769+
/*
770+
* CacheInvalidateRelcacheByRelid
771+
*As above, but relation is identified by passing its OID.
772+
*This is the least efficient of the three options; use one of
773+
*the above routines if you have a Relation or pg_class tuple.
774+
*/
775+
void
776+
CacheInvalidateRelcacheByRelid(Oidrelid)
777+
{
778+
HeapTupletup;
779+
780+
tup=SearchSysCache(RELOID,
781+
ObjectIdGetDatum(relid),
782+
0,0,0);
783+
if (!HeapTupleIsValid(tup))
784+
elog(ERROR,"cache lookup failed for relation %u",relid);
785+
CacheInvalidateRelcacheByTuple(tup);
786+
ReleaseSysCache(tup);
787+
}
788+
768789
/*
769790
* CacheRegisterSyscacheCallback
770791
*Register the specified function to be called for all future

‎src/include/commands/cluster.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/include/commands/cluster.h,v 1.21 2004/05/05 04:48:47 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/commands/cluster.h,v 1.22 2004/05/06 16:10:57 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -19,10 +19,12 @@
1919

2020
externvoidcluster(ClusterStmt*stmt);
2121

22+
externvoidcheck_index_is_clusterable(RelationOldHeap,OidindexOid);
2223
externvoidrebuild_relation(RelationOldHeap,OidindexOid);
2324
externOidmake_new_heap(OidOIDOldHeap,constchar*NewName);
24-
externList*get_indexattr_list(RelationOldHeap,OidOldIndex);
25-
externvoidrebuild_indexes(OidOIDOldHeap,List*indexes);
25+
externList*get_indexattr_list(RelationOldHeap,Oid*OldClusterIndex);
26+
externvoidrebuild_indexes(OidOIDOldHeap,List*indexes,
27+
OidOIDClusterIndex);
2628
externvoidswap_relfilenodes(Oidr1,Oidr2);
2729

2830
#endif/* CLUSTER_H */

‎src/include/utils/inval.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/inval.h,v 1.30 2004/02/10 01:55:26 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/inval.h,v 1.31 2004/05/06 16:10:57 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -32,6 +32,8 @@ extern void CacheInvalidateRelcache(Relation relation);
3232

3333
externvoidCacheInvalidateRelcacheByTuple(HeapTupleclassTuple);
3434

35+
externvoidCacheInvalidateRelcacheByRelid(Oidrelid);
36+
3537
externvoidCacheRegisterSyscacheCallback(intcacheid,
3638
CacheCallbackFunctionfunc,
3739
Datumarg);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp