Add try_index_open(), conditional variant of index_open()
authorMichael Paquier <michael@paquier.xyz>
Thu, 18 Jan 2024 06:04:31 +0000 (15:04 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 18 Jan 2024 06:04:31 +0000 (15:04 +0900)
try_index_open() is able to open an index if its relkind fits, except
that it would return NULL instead of generated an error if the relation
does not exist.  This new routine will be used by an upcoming patch to
make REINDEX on partitioned relations more robust when an index in a
partition tree is dropped.

Extracted from a larger patch by the same author.

Author: Fei Changhong
Discussion: https://postgr.es/m/tencent_6A52106095ACDE55333E3AD33F304C0C3909@qq.com
Backpatch-through: 14

src/backend/access/index/indexam.c
src/include/access/genam.h

index b25b03f7abc3299f511a839c847083ebf349eb21..7735ed7384e4f65069a71b2f0b9bb7327abeb719 100644 (file)
@@ -107,6 +107,7 @@ do { \
 static IndexScanDesc index_beginscan_internal(Relation indexRelation,
                                              int nkeys, int norderbys, Snapshot snapshot,
                                              ParallelIndexScanDesc pscan, bool temp_snap);
+static inline void validate_relation_kind(Relation r);
 
 
 /* ----------------------------------------------------------------
@@ -135,12 +136,30 @@ index_open(Oid relationId, LOCKMODE lockmode)
 
    r = relation_open(relationId, lockmode);
 
-   if (r->rd_rel->relkind != RELKIND_INDEX &&
-       r->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
-       ereport(ERROR,
-               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                errmsg("\"%s\" is not an index",
-                       RelationGetRelationName(r))));
+   validate_relation_kind(r);
+
+   return r;
+}
+
+/* ----------------
+ *     try_index_open - open a index relation by relation OID
+ *
+ *     Same as index_open, except return NULL instead of failing
+ *     if the relation does not exist.
+ * ----------------
+ */
+Relation
+try_index_open(Oid relationId, LOCKMODE lockmode)
+{
+   Relation    r;
+
+   r = try_relation_open(relationId, lockmode);
+
+   /* leave if index does not exist */
+   if (!r)
+       return NULL;
+
+   validate_relation_kind(r);
 
    return r;
 }
@@ -168,6 +187,24 @@ index_close(Relation relation, LOCKMODE lockmode)
        UnlockRelationId(&relid, lockmode);
 }
 
+/* ----------------
+ *     validate_relation_kind - check the relation's kind
+ *
+ *     Make sure relkind is an index or a partitioned index.
+ * ----------------
+ */
+static inline void
+validate_relation_kind(Relation r)
+{
+   if (r->rd_rel->relkind != RELKIND_INDEX &&
+       r->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("\"%s\" is not an index",
+                       RelationGetRelationName(r))));
+}
+
+
 /* ----------------
  *     index_insert - insert an index tuple into a relation
  * ----------------
index a30879566549a1894ea01067cc813ef3fcf0121f..b071cedd44beb01e6a8e654f324432be44e59290 100644 (file)
@@ -139,6 +139,7 @@ typedef struct IndexOrderByDistance
 #define IndexScanIsValid(scan) PointerIsValid(scan)
 
 extern Relation index_open(Oid relationId, LOCKMODE lockmode);
+extern Relation try_index_open(Oid relationId, LOCKMODE lockmode);
 extern void index_close(Relation relation, LOCKMODE lockmode);
 
 extern bool index_insert(Relation indexRelation,