Set relispartition correctly for index partitions
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Thu, 12 Apr 2018 00:27:12 +0000 (21:27 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Thu, 12 Apr 2018 00:27:12 +0000 (21:27 -0300)
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
src/backend/commands/tablecmds.c

index 5d73e92901f1dc473873d21c0856442e7bf04ed3..218c457fa4365cfd159aead40e5593a7f4d063da 100644 (file)
@@ -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
index f8108858ae7e8413969c5d9af14d14d82f52233a..562c815c63fd52b5fbb796dc9d4c21cc25bd1291 100644 (file)
@@ -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);
+}