From 9e9befac4a2228ae8a5309900645ecd8ead69f53 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Wed, 11 Apr 2018 21:27:12 -0300 Subject: [PATCH] Set relispartition correctly for index partitions MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Oversight in commit 8b08f7d4820f: pg_class.relispartition was not being set for index partitions, which is a bit odd, and was also causing the code to unnecessarily call has_superclass() when simply checking the flag was enough. Author: Álvaro Herrera Reported-by: Amit Langote Discussion: https://postgr.es/m/12085bc4-0bc6-0f3a-4c43-57fe0681772b@lab.ntt.co.jp --- src/backend/catalog/index.c | 1 + src/backend/commands/tablecmds.c | 51 +++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 5d73e92901..218c457fa4 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -933,6 +933,7 @@ index_create(Relation heapRelation, indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner; indexRelation->rd_rel->relam = accessMethodObjectId; indexRelation->rd_rel->relhasoids = false; + indexRelation->rd_rel->relispartition = OidIsValid(parentIndexRelid); /* * store index's pg_class entry diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f8108858ae..562c815c63 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -490,6 +490,8 @@ static ObjectAddress ATExecAttachPartitionIdx(List **wqueue, Relation rel, static void validatePartitionedIndex(Relation partedIdx, Relation partedTbl); static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx, Relation partitionTbl); +static void update_relispartition(Relation classRel, Oid relationId, + bool newval); /* ---------------------------------------------------------------- @@ -14405,10 +14407,11 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel) */ for (i = 0; i < list_length(attachRelIdxs); i++) { + Oid cldIdxId = RelationGetRelid(attachrelIdxRels[i]); Oid cldConstrOid = InvalidOid; /* does this index have a parent? if so, can't use it */ - if (has_superclass(RelationGetRelid(attachrelIdxRels[i]))) + if (attachrelIdxRels[i]->rd_rel->relispartition) continue; if (CompareIndexInfo(attachInfos[i], info, @@ -14429,7 +14432,7 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel) { cldConstrOid = get_relation_idx_constraint_oid(RelationGetRelid(attachrel), - RelationGetRelid(attachrelIdxRels[i])); + cldIdxId); /* no dice */ if (!OidIsValid(cldConstrOid)) continue; @@ -14439,6 +14442,7 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel) IndexSetParentIndex(attachrelIdxRels[i], idx); if (OidIsValid(constraintOid)) ConstraintSetParentConstraint(cldConstrOid, constraintOid); + update_relispartition(NULL, cldIdxId, true); found = true; break; } @@ -14659,7 +14663,6 @@ ATExecDetachPartition(Relation rel, RangeVar *name) ((Form_pg_class) GETSTRUCT(newtuple))->relispartition = false; CatalogTupleUpdate(classRel, &newtuple->t_self, newtuple); heap_freetuple(newtuple); - heap_close(classRel, RowExclusiveLock); if (OidIsValid(defaultPartOid)) { @@ -14692,8 +14695,10 @@ ATExecDetachPartition(Relation rel, RangeVar *name) idx = index_open(idxid, AccessExclusiveLock); IndexSetParentIndex(idx, InvalidOid); + update_relispartition(classRel, idxid, false); relation_close(idx, AccessExclusiveLock); } + heap_close(classRel, RowExclusiveLock); /* * Invalidate the parent's relcache so that the partition is no longer @@ -14815,8 +14820,8 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) ObjectAddressSet(address, RelationRelationId, RelationGetRelid(partIdx)); /* Silently do nothing if already in the right state */ - currParent = !has_superclass(partIdxId) ? InvalidOid : - get_partition_parent(partIdxId); + currParent = partIdx->rd_rel->relispartition ? + get_partition_parent(partIdxId) : InvalidOid; if (currParent != RelationGetRelid(parentIdx)) { IndexInfo *childInfo; @@ -14909,6 +14914,7 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name) IndexSetParentIndex(partIdx, RelationGetRelid(parentIdx)); if (OidIsValid(constraintOid)) ConstraintSetParentConstraint(cldConstrId, constraintOid); + update_relispartition(NULL, partIdxId, true); pfree(attmap); @@ -15036,8 +15042,7 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) * If this index is in turn a partition of a larger index, validating it * might cause the parent to become valid also. Try that. */ - if (updated && - has_superclass(RelationGetRelid(partedIdx))) + if (updated && partedIdx->rd_rel->relispartition) { Oid parentIdxId, parentTblId; @@ -15059,3 +15064,35 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl) relation_close(parentTbl, AccessExclusiveLock); } } + +/* + * Update the relispartition flag of the given relation to the given value. + * + * classRel is the pg_class relation, already open and suitably locked. + * It can be passed as NULL, in which case it's opened and closed locally. + */ +static void +update_relispartition(Relation classRel, Oid relationId, bool newval) +{ + HeapTuple tup; + HeapTuple newtup; + Form_pg_class classForm; + bool opened = false; + + if (classRel == NULL) + { + classRel = heap_open(RelationRelationId, RowExclusiveLock); + opened = true; + } + + tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId)); + newtup = heap_copytuple(tup); + classForm = (Form_pg_class) GETSTRUCT(newtup); + classForm->relispartition = newval; + CatalogTupleUpdate(classRel, &tup->t_self, newtup); + heap_freetuple(newtup); + ReleaseSysCache(tup); + + if (opened) + heap_close(classRel, RowExclusiveLock); +} -- 2.40.0