Skip to content

Commit b1f570b

Browse files
committed
Fix partitioned index attachment
When an existing index in a partition is attached to a new index on its parent, we forgot to set the "relispartition" flag correctly, which meant that it was not possible to find the index in various operations, such as adding a foreign key constraint that references that partitioned table. One of four places that was assigning the parent index was forgetting to do that, so fix by shifting responsibility of updating the flag to the routine that changes the parent. Author: Amit Langote, Álvaro Herrera Reported-by: Hubert "depesz" Lubaczewski Discussion: https://postgr.es/m/CA+HiwqHMsRtRYRWYTWavKJ8x14AFsv7bmAV46mYwnfD3vy8goQ@mail.gmail.com
1 parent a98c48d commit b1f570b

File tree

2 files changed

+24
-37
lines changed

2 files changed

+24
-37
lines changed

src/backend/commands/indexcmds.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ static List *ChooseIndexColumnNames(List *indexElems);
8585
static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
8686
Oid relId, Oid oldRelId, void *arg);
8787
static void ReindexPartitionedIndex(Relation parentIdx);
88+
static void update_relispartition(Oid relationId, bool newval);
8889

8990
/*
9091
* CheckIndexCompatible
@@ -2617,6 +2618,9 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
26172618
systable_endscan(scan);
26182619
relation_close(pg_inherits, RowExclusiveLock);
26192620

2621+
/* set relispartition correctly on the partition */
2622+
update_relispartition(partRelid, OidIsValid(parentOid));
2623+
26202624
if (fix_dependencies)
26212625
{
26222626
ObjectAddress partIdx;
@@ -2654,3 +2658,23 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid)
26542658
CommandCounterIncrement();
26552659
}
26562660
}
2661+
2662+
/*
2663+
* Subroutine of IndexSetParentIndex to update the relispartition flag of the
2664+
* given index to the given value.
2665+
*/
2666+
static void
2667+
update_relispartition(Oid relationId, bool newval)
2668+
{
2669+
HeapTuple tup;
2670+
Relation classRel;
2671+
2672+
classRel = heap_open(RelationRelationId, RowExclusiveLock);
2673+
tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
2674+
Assert(((Form_pg_class) GETSTRUCT(tup))->relispartition != newval);
2675+
((Form_pg_class) GETSTRUCT(tup))->relispartition = newval;
2676+
CatalogTupleUpdate(classRel, &tup->t_self, tup);
2677+
heap_freetuple(tup);
2678+
2679+
heap_close(classRel, RowExclusiveLock);
2680+
}

src/backend/commands/tablecmds.c

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,6 @@ static ObjectAddress ATExecAttachPartitionIdx(List **wqueue, Relation rel,
495495
static void validatePartitionedIndex(Relation partedIdx, Relation partedTbl);
496496
static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx,
497497
Relation partitionTbl);
498-
static void update_relispartition(Relation classRel, Oid relationId,
499-
bool newval);
500498

501499

502500
/* ----------------------------------------------------------------
@@ -15036,7 +15034,6 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel)
1503615034
IndexSetParentIndex(attachrelIdxRels[i], idx);
1503715035
if (OidIsValid(constraintOid))
1503815036
ConstraintSetParentConstraint(cldConstrOid, constraintOid);
15039-
update_relispartition(NULL, cldIdxId, true);
1504015037
found = true;
1504115038
break;
1504215039
}
@@ -15287,7 +15284,6 @@ ATExecDetachPartition(Relation rel, RangeVar *name)
1528715284

1528815285
idx = index_open(idxid, AccessExclusiveLock);
1528915286
IndexSetParentIndex(idx, InvalidOid);
15290-
update_relispartition(classRel, idxid, false);
1529115287

1529215288
/* If there's a constraint associated with the index, detach it too */
1529315289
constrOid = get_relation_idx_constraint_oid(RelationGetRelid(partRel),
@@ -15562,7 +15558,6 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name)
1556215558
IndexSetParentIndex(partIdx, RelationGetRelid(parentIdx));
1556315559
if (OidIsValid(constraintOid))
1556415560
ConstraintSetParentConstraint(cldConstrId, constraintOid);
15565-
update_relispartition(NULL, partIdxId, true);
1556615561

1556715562
pfree(attmap);
1556815563

@@ -15712,35 +15707,3 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl)
1571215707
relation_close(parentTbl, AccessExclusiveLock);
1571315708
}
1571415709
}
15715-
15716-
/*
15717-
* Update the relispartition flag of the given relation to the given value.
15718-
*
15719-
* classRel is the pg_class relation, already open and suitably locked.
15720-
* It can be passed as NULL, in which case it's opened and closed locally.
15721-
*/
15722-
static void
15723-
update_relispartition(Relation classRel, Oid relationId, bool newval)
15724-
{
15725-
HeapTuple tup;
15726-
HeapTuple newtup;
15727-
Form_pg_class classForm;
15728-
bool opened = false;
15729-
15730-
if (classRel == NULL)
15731-
{
15732-
classRel = heap_open(RelationRelationId, RowExclusiveLock);
15733-
opened = true;
15734-
}
15735-
15736-
tup = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
15737-
newtup = heap_copytuple(tup);
15738-
classForm = (Form_pg_class) GETSTRUCT(newtup);
15739-
classForm->relispartition = newval;
15740-
CatalogTupleUpdate(classRel, &tup->t_self, newtup);
15741-
heap_freetuple(newtup);
15742-
ReleaseSysCache(tup);
15743-
15744-
if (opened)
15745-
heap_close(classRel, RowExclusiveLock);
15746-
}

0 commit comments

Comments
 (0)