Add index_get_partition convenience function
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 20 Mar 2019 21:18:50 +0000 (18:18 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 20 Mar 2019 21:18:50 +0000 (18:18 -0300)
This new function simplifies some existing coding, as well as supports
future patches.

Discussion: https://postgr.es/m/201901222145.t6wws6t6vrcu@alvherre.pgsql
Reviewed-by: Amit Langote, Jesper Pedersen
src/backend/catalog/partition.c
src/backend/commands/tablecmds.c
src/include/catalog/partition.h

index 3ccdaff8c458c0cdbcf15618208b8471e198923e..8ea7a62418f3e574d64cab26cdaf174e93bdd2d8 100644 (file)
@@ -145,6 +145,42 @@ get_partition_ancestors_worker(Relation inhRel, Oid relid, List **ancestors)
        get_partition_ancestors_worker(inhRel, parentOid, ancestors);
 }
 
+/*
+ * index_get_partition
+ *             Return the OID of index of the given partition that is a child
+ *             of the given index, or InvalidOid if there isn't one.
+ */
+Oid
+index_get_partition(Relation partition, Oid indexId)
+{
+       List       *idxlist = RelationGetIndexList(partition);
+       ListCell   *l;
+
+       foreach(l, idxlist)
+       {
+               Oid                     partIdx = lfirst_oid(l);
+               HeapTuple       tup;
+               Form_pg_class classForm;
+               bool            ispartition;
+
+               tup = SearchSysCache1(RELOID, ObjectIdGetDatum(partIdx));
+               if (!tup)
+                       elog(ERROR, "cache lookup failed for relation %u", partIdx);
+               classForm = (Form_pg_class) GETSTRUCT(tup);
+               ispartition = classForm->relispartition;
+               ReleaseSysCache(tup);
+               if (!ispartition)
+                       continue;
+               if (get_partition_parent(lfirst_oid(l)) == indexId)
+               {
+                       list_free(idxlist);
+                       return partIdx;
+               }
+       }
+
+       return InvalidOid;
+}
+
 /*
  * map_partition_varattnos - maps varattno of any Vars in expr from the
  * attno's of 'from_rel' to the attno's of 'to_rel' partition, each of which
index 515c29072c811365f6e5b391db4e1a4e904ed31b..3183b2aaa12d693ed49be0467845af3665d9989e 100644 (file)
@@ -15649,36 +15649,18 @@ ATExecAttachPartitionIdx(List **wqueue, Relation parentIdx, RangeVar *name)
 static void
 refuseDupeIndexAttach(Relation parentIdx, Relation partIdx, Relation partitionTbl)
 {
-       Relation        pg_inherits;
-       ScanKeyData key;
-       HeapTuple       tuple;
-       SysScanDesc scan;
-
-       pg_inherits = table_open(InheritsRelationId, AccessShareLock);
-       ScanKeyInit(&key, Anum_pg_inherits_inhparent,
-                               BTEqualStrategyNumber, F_OIDEQ,
-                               ObjectIdGetDatum(RelationGetRelid(parentIdx)));
-       scan = systable_beginscan(pg_inherits, InheritsParentIndexId, true,
-                                                         NULL, 1, &key);
-       while (HeapTupleIsValid(tuple = systable_getnext(scan)))
-       {
-               Form_pg_inherits inhForm;
-               Oid                     tab;
+       Oid                     existingIdx;
 
-               inhForm = (Form_pg_inherits) GETSTRUCT(tuple);
-               tab = IndexGetRelation(inhForm->inhrelid, false);
-               if (tab == RelationGetRelid(partitionTbl))
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-                                        errmsg("cannot attach index \"%s\" as a partition of index \"%s\"",
-                                                       RelationGetRelationName(partIdx),
-                                                       RelationGetRelationName(parentIdx)),
-                                        errdetail("Another index is already attached for partition \"%s\".",
-                                                          RelationGetRelationName(partitionTbl))));
-       }
-
-       systable_endscan(scan);
-       table_close(pg_inherits, AccessShareLock);
+       existingIdx = index_get_partition(partitionTbl,
+                                                                         RelationGetRelid(parentIdx));
+       if (OidIsValid(existingIdx))
+               ereport(ERROR,
+                               (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+                                errmsg("cannot attach index \"%s\" as a partition of index \"%s\"",
+                                               RelationGetRelationName(partIdx),
+                                               RelationGetRelationName(parentIdx)),
+                                errdetail("Another index is already attached for partition \"%s\".",
+                                                  RelationGetRelationName(partitionTbl))));
 }
 
 /*
index d84e32598354d70aa05c5be6c979feb0059bec74..616e18af30884d09fff3ab86c14e7528d0c121b4 100644 (file)
@@ -21,6 +21,7 @@
 
 extern Oid     get_partition_parent(Oid relid);
 extern List *get_partition_ancestors(Oid relid);
+extern Oid     index_get_partition(Relation partition, Oid indexId);
 extern List *map_partition_varattnos(List *expr, int fromrel_varno,
                                                Relation to_rel, Relation from_rel,
                                                bool *found_whole_row);