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..56e87d6251 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 partIdxId, + 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 @@ -14772,6 +14777,39 @@ RangeVarCallbackForAttachIndex(const RangeVar *rv, Oid relOid, Oid oldRelOid, } /* + * Update the relispartition flag of the relation with the given OID, to the + * given value. + * + * classRel is the pg_class relation, already open and suitably locked; if + * passed as NULL, we open it internally and close before returning. + */ +static void +update_relispartition(Relation classRel, Oid partIdxId, 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(partIdxId)); + 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); +} + +/* * ALTER INDEX i1 ATTACH PARTITION i2 */ static ObjectAddress @@ -14815,8 +14853,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 +14947,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 +15075,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;