]> granicus.if.org Git - postgresql/commitdiff
Arrange to cache fmgr lookup information for an index's access method
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 27 May 2005 23:31:21 +0000 (23:31 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 27 May 2005 23:31:21 +0000 (23:31 +0000)
routines in the index's relcache entry, instead of doing a fresh fmgr_info
on every index access.  We were already doing this for the index's opclass
support functions; not sure why we didn't think to do it for the AM
functions too.  This supersedes the former method of caching (only)
amgettuple in indexscan scan descriptors; it's an improvement because the
function lookup can be amortized across multiple statements instead of
being repeated for each statement.  Even though lookup for builtin
functions is pretty cheap, this seems to drop a percent or two off some
simple benchmarks.

src/backend/access/index/genam.c
src/backend/access/index/indexam.c
src/backend/utils/cache/relcache.c
src/include/access/genam.h
src/include/access/relscan.h
src/include/utils/rel.h

index d2504de21900e53d161d5f8f1952187581e8a500..90e910f343f1a152b7d484429479c853ae251f75 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.47 2005/04/14 20:03:23 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.48 2005/05/27 23:31:20 tgl Exp $
  *
  * NOTES
  *       many of the old access method routines have been turned into
@@ -86,6 +86,7 @@ RelationGetIndexScan(Relation indexRelation,
        else
                scan->keyData = NULL;
 
+       scan->is_multiscan = false;                     /* caller may change this */
        scan->kill_prior_tuple = false;
        scan->ignore_killed_tuples = true;      /* default setting */
        scan->keys_are_unique = false;          /* may be set by index AM */
@@ -101,10 +102,6 @@ RelationGetIndexScan(Relation indexRelation,
        scan->xs_ctup.t_data = NULL;
        scan->xs_cbuf = InvalidBuffer;
 
-       /* mark cached function lookup data invalid; it will be set later */
-       scan->fn_getnext.fn_oid = InvalidOid;
-       scan->fn_getmulti.fn_oid = InvalidOid;
-
        scan->unique_tuple_pos = 0;
        scan->unique_tuple_mark = 0;
 
index 13b04a06b1756375d1c55c13d0cf4efd0c1c0163..81c2114976e93f5fe8f74e17c13402bc06e38762 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.81 2005/05/15 21:19:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.82 2005/05/27 23:31:20 tgl Exp $
  *
  * INTERFACE ROUTINES
  *             index_open              - open an index relation by relation OID
@@ -27,6 +27,7 @@
  *             index_vacuum_cleanup    - post-deletion cleanup of an index
  *             index_cost_estimator    - fetch amcostestimate procedure OID
  *             index_getprocid - get a support procedure OID
+ *             index_getprocinfo - get a support procedure's lookup info
  *
  * NOTES
  *             This file contains the index_ routines which used
 )
 
 #define GET_REL_PROCEDURE(pname) \
-( \
-       procedure = indexRelation->rd_am->pname, \
-       (!RegProcedureIsValid(procedure)) ? \
-               elog(ERROR, "invalid %s regproc", CppAsString(pname)) \
-       : (void)NULL \
-)
+do { \
+       procedure = &indexRelation->rd_aminfo->pname; \
+       if (!OidIsValid(procedure->fn_oid)) \
+       { \
+               RegProcedure    procOid = indexRelation->rd_am->pname; \
+               if (!RegProcedureIsValid(procOid)) \
+                       elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
+               fmgr_info_cxt(procOid, procedure, indexRelation->rd_indexcxt); \
+       } \
+} while(0)
 
 #define GET_SCAN_PROCEDURE(pname) \
-( \
-       procedure = scan->indexRelation->rd_am->pname, \
-       (!RegProcedureIsValid(procedure)) ? \
-               elog(ERROR, "invalid %s regproc", CppAsString(pname)) \
-       : (void)NULL \
-)
+do { \
+       procedure = &scan->indexRelation->rd_aminfo->pname; \
+       if (!OidIsValid(procedure->fn_oid)) \
+       { \
+               RegProcedure    procOid = scan->indexRelation->rd_am->pname; \
+               if (!RegProcedureIsValid(procOid)) \
+                       elog(ERROR, "invalid %s regproc", CppAsString(pname)); \
+               fmgr_info_cxt(procOid, procedure, scan->indexRelation->rd_indexcxt); \
+       } \
+} while(0)
 
 static IndexScanDesc index_beginscan_internal(Relation indexRelation,
                                                                                          int nkeys, ScanKey key);
@@ -196,7 +205,7 @@ index_insert(Relation indexRelation,
                         Relation heapRelation,
                         bool check_uniqueness)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        RELATION_CHECKS;
        GET_REL_PROCEDURE(aminsert);
@@ -204,13 +213,13 @@ index_insert(Relation indexRelation,
        /*
         * have the am's insert proc do all the work.
         */
-       return DatumGetBool(OidFunctionCall6(procedure,
-                                                                                PointerGetDatum(indexRelation),
-                                                                                PointerGetDatum(values),
-                                                                                PointerGetDatum(isnull),
-                                                                                PointerGetDatum(heap_t_ctid),
-                                                                                PointerGetDatum(heapRelation),
-                                                                                BoolGetDatum(check_uniqueness)));
+       return DatumGetBool(FunctionCall6(procedure,
+                                                                         PointerGetDatum(indexRelation),
+                                                                         PointerGetDatum(values),
+                                                                         PointerGetDatum(isnull),
+                                                                         PointerGetDatum(heap_t_ctid),
+                                                                         PointerGetDatum(heapRelation),
+                                                                         BoolGetDatum(check_uniqueness)));
 }
 
 /*
@@ -229,7 +238,6 @@ index_beginscan(Relation heapRelation,
                                int nkeys, ScanKey key)
 {
        IndexScanDesc scan;
-       RegProcedure procedure;
 
        scan = index_beginscan_internal(indexRelation, nkeys, key);
 
@@ -237,17 +245,10 @@ index_beginscan(Relation heapRelation,
         * Save additional parameters into the scandesc.  Everything else was
         * set up by RelationGetIndexScan.
         */
+       scan->is_multiscan = false;
        scan->heapRelation = heapRelation;
        scan->xs_snapshot = snapshot;
 
-       /*
-        * We want to look up the amgettuple procedure just once per scan, not
-        * once per index_getnext call.  So do it here and save the fmgr info
-        * result in the scan descriptor.
-        */
-       GET_SCAN_PROCEDURE(amgettuple);
-       fmgr_info(procedure, &scan->fn_getnext);
-
        return scan;
 }
 
@@ -263,7 +264,6 @@ index_beginscan_multi(Relation indexRelation,
                                          int nkeys, ScanKey key)
 {
        IndexScanDesc scan;
-       RegProcedure procedure;
 
        scan = index_beginscan_internal(indexRelation, nkeys, key);
 
@@ -271,16 +271,9 @@ index_beginscan_multi(Relation indexRelation,
         * Save additional parameters into the scandesc.  Everything else was
         * set up by RelationGetIndexScan.
         */
+       scan->is_multiscan = true;
        scan->xs_snapshot = snapshot;
 
-       /*
-        * We want to look up the amgetmulti procedure just once per scan, not
-        * once per index_getmulti call.  So do it here and save the fmgr info
-        * result in the scan descriptor.
-        */
-       GET_SCAN_PROCEDURE(amgetmulti);
-       fmgr_info(procedure, &scan->fn_getmulti);
-
        return scan;
 }
 
@@ -292,7 +285,7 @@ index_beginscan_internal(Relation indexRelation,
                                                 int nkeys, ScanKey key)
 {
        IndexScanDesc scan;
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        RELATION_CHECKS;
        GET_REL_PROCEDURE(ambeginscan);
@@ -312,10 +305,10 @@ index_beginscan_internal(Relation indexRelation,
         * Tell the AM to open a scan.
         */
        scan = (IndexScanDesc)
-               DatumGetPointer(OidFunctionCall3(procedure,
-                                                                                PointerGetDatum(indexRelation),
-                                                                                Int32GetDatum(nkeys),
-                                                                                PointerGetDatum(key)));
+               DatumGetPointer(FunctionCall3(procedure,
+                                                                         PointerGetDatum(indexRelation),
+                                                                         Int32GetDatum(nkeys),
+                                                                         PointerGetDatum(key)));
 
        return scan;
 }
@@ -335,7 +328,7 @@ index_beginscan_internal(Relation indexRelation,
 void
 index_rescan(IndexScanDesc scan, ScanKey key)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(amrescan);
@@ -353,9 +346,9 @@ index_rescan(IndexScanDesc scan, ScanKey key)
        scan->unique_tuple_pos = 0;
        scan->unique_tuple_mark = 0;
 
-       OidFunctionCall2(procedure,
-                                        PointerGetDatum(scan),
-                                        PointerGetDatum(key));
+       FunctionCall2(procedure,
+                                 PointerGetDatum(scan),
+                                 PointerGetDatum(key));
 
        pgstat_reset_index_scan(&scan->xs_pgstat_info);
 }
@@ -367,7 +360,7 @@ index_rescan(IndexScanDesc scan, ScanKey key)
 void
 index_endscan(IndexScanDesc scan)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(amendscan);
@@ -380,7 +373,7 @@ index_endscan(IndexScanDesc scan)
        }
 
        /* End the AM's scan */
-       OidFunctionCall1(procedure, PointerGetDatum(scan));
+       FunctionCall1(procedure, PointerGetDatum(scan));
 
        /* Release index lock and refcount acquired by index_beginscan */
 
@@ -399,14 +392,14 @@ index_endscan(IndexScanDesc scan)
 void
 index_markpos(IndexScanDesc scan)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(ammarkpos);
 
        scan->unique_tuple_mark = scan->unique_tuple_pos;
 
-       OidFunctionCall1(procedure, PointerGetDatum(scan));
+       FunctionCall1(procedure, PointerGetDatum(scan));
 }
 
 /* ----------------
@@ -420,7 +413,7 @@ index_markpos(IndexScanDesc scan)
 void
 index_restrpos(IndexScanDesc scan)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        SCAN_CHECKS;
        GET_SCAN_PROCEDURE(amrestrpos);
@@ -434,7 +427,7 @@ index_restrpos(IndexScanDesc scan)
         */
        scan->unique_tuple_pos = scan->unique_tuple_mark;
 
-       OidFunctionCall1(procedure, PointerGetDatum(scan));
+       FunctionCall1(procedure, PointerGetDatum(scan));
 }
 
 /* ----------------
@@ -451,8 +444,10 @@ HeapTuple
 index_getnext(IndexScanDesc scan, ScanDirection direction)
 {
        HeapTuple       heapTuple = &scan->xs_ctup;
+       FmgrInfo   *procedure;
 
        SCAN_CHECKS;
+       GET_SCAN_PROCEDURE(amgettuple);
 
        /*
         * If we already got a tuple and it must be unique, there's no need to
@@ -525,9 +520,9 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
 
                /*
                 * The AM's gettuple proc finds the next tuple matching the scan
-                * keys.  index_beginscan already set up fn_getnext.
+                * keys.
                 */
-               found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
+               found = DatumGetBool(FunctionCall2(procedure,
                                                                                   PointerGetDatum(scan),
                                                                                   Int32GetDatum(direction)));
 
@@ -605,18 +600,19 @@ bool
 index_getnext_indexitem(IndexScanDesc scan,
                                                ScanDirection direction)
 {
+       FmgrInfo   *procedure;
        bool            found;
 
        SCAN_CHECKS;
+       GET_SCAN_PROCEDURE(amgettuple);
 
        /* just make sure this is false... */
        scan->kill_prior_tuple = false;
 
        /*
-        * have the am's gettuple proc do all the work. index_beginscan
-        * already set up fn_getnext.
+        * have the am's gettuple proc do all the work.
         */
-       found = DatumGetBool(FunctionCall2(&scan->fn_getnext,
+       found = DatumGetBool(FunctionCall2(procedure,
                                                                           PointerGetDatum(scan),
                                                                           Int32GetDatum(direction)));
 
@@ -641,18 +637,19 @@ index_getmulti(IndexScanDesc scan,
                           ItemPointer tids, int32 max_tids,
                           int32 *returned_tids)
 {
+       FmgrInfo   *procedure;
        bool            found;
 
        SCAN_CHECKS;
+       GET_SCAN_PROCEDURE(amgetmulti);
 
        /* just make sure this is false... */
        scan->kill_prior_tuple = false;
 
        /*
-        * have the am's getmulti proc do all the work. index_beginscan_multi
-        * already set up fn_getmulti.
+        * have the am's getmulti proc do all the work.
         */
-       found = DatumGetBool(FunctionCall4(&scan->fn_getmulti,
+       found = DatumGetBool(FunctionCall4(procedure,
                                                                           PointerGetDatum(scan),
                                                                           PointerGetDatum(tids),
                                                                           Int32GetDatum(max_tids),
@@ -675,17 +672,17 @@ index_bulk_delete(Relation indexRelation,
                                  IndexBulkDeleteCallback callback,
                                  void *callback_state)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
        IndexBulkDeleteResult *result;
 
        RELATION_CHECKS;
        GET_REL_PROCEDURE(ambulkdelete);
 
        result = (IndexBulkDeleteResult *)
-               DatumGetPointer(OidFunctionCall3(procedure,
-                                                                                PointerGetDatum(indexRelation),
-                                                                        PointerGetDatum((Pointer) callback),
-                                                                          PointerGetDatum(callback_state)));
+               DatumGetPointer(FunctionCall3(procedure,
+                                                                         PointerGetDatum(indexRelation),
+                                                                         PointerGetDatum((Pointer) callback),
+                                                                         PointerGetDatum(callback_state)));
 
        return result;
 }
@@ -701,7 +698,7 @@ index_vacuum_cleanup(Relation indexRelation,
                                         IndexVacuumCleanupInfo *info,
                                         IndexBulkDeleteResult *stats)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
        IndexBulkDeleteResult *result;
 
        RELATION_CHECKS;
@@ -713,9 +710,9 @@ index_vacuum_cleanup(Relation indexRelation,
        GET_REL_PROCEDURE(amvacuumcleanup);
 
        result = (IndexBulkDeleteResult *)
-               DatumGetPointer(OidFunctionCall3(procedure,
-                                                                                PointerGetDatum(indexRelation),
-                                                                                PointerGetDatum((Pointer) info),
+               DatumGetPointer(FunctionCall3(procedure,
+                                                                         PointerGetDatum(indexRelation),
+                                                                         PointerGetDatum((Pointer) info),
                                                                          PointerGetDatum((Pointer) stats)));
 
        return result;
@@ -734,12 +731,12 @@ index_vacuum_cleanup(Relation indexRelation,
 RegProcedure
 index_cost_estimator(Relation indexRelation)
 {
-       RegProcedure procedure;
+       FmgrInfo   *procedure;
 
        RELATION_CHECKS;
        GET_REL_PROCEDURE(amcostestimate);
 
-       return procedure;
+       return procedure->fn_oid;
 }
 
 /* ----------------
@@ -785,9 +782,13 @@ index_getprocid(Relation irel,
  *
  *             This routine allows index AMs to keep fmgr lookup info for
  *             support procs in the relcache.
+ *
+ * Note: the return value points into cached data that will be lost during
+ * any relcache rebuild!  Therefore, either use the callinfo right away,
+ * or save it only after having acquired some type of lock on the index rel.
  * ----------------
  */
-struct FmgrInfo *
+FmgrInfo *
 index_getprocinfo(Relation irel,
                                  AttrNumber attnum,
                                  uint16 procnum)
index c4dc65f784a7c98df51d2c31bf0be3bc1676e9ae..3123eca518edfc16ae1c9744dc45f3a44febdc3d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.223 2005/05/11 01:26:02 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.224 2005/05/27 23:31:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -904,6 +904,9 @@ RelationInitIndexAccessInfo(Relation relation)
        /*
         * Allocate arrays to hold data
         */
+       relation->rd_aminfo = (RelationAmInfo *)
+               MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
+
        if (amstrategies > 0)
                operator = (Oid *)
                        MemoryContextAllocZero(indexcxt,
@@ -931,8 +934,8 @@ RelationInitIndexAccessInfo(Relation relation)
        relation->rd_supportinfo = supportinfo;
 
        /*
-        * Fill the operator and support procedure OID arrays. (supportinfo is
-        * left as zeroes, and is filled on-the-fly when used)
+        * Fill the operator and support procedure OID arrays.  (aminfo and
+        * supportinfo are left as zeroes, and are filled on-the-fly when used)
         */
        IndexSupportInitialize(relation->rd_indclass,
                                                   operator, support,
@@ -3015,7 +3018,9 @@ load_relcache_init_file(void)
 
                        rel->rd_support = support;
 
-                       /* add a zeroed support-fmgr-info vector */
+                       /* set up zeroed fmgr-info vectors */
+                       rel->rd_aminfo = (RelationAmInfo *)
+                               MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
                        nsupport = relform->relnatts * am->amsupport;
                        rel->rd_supportinfo = (FmgrInfo *)
                                MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
@@ -3031,6 +3036,7 @@ load_relcache_init_file(void)
                        Assert(rel->rd_indclass == NULL);
                        Assert(rel->rd_am == NULL);
                        Assert(rel->rd_indexcxt == NULL);
+                       Assert(rel->rd_aminfo == NULL);
                        Assert(rel->rd_operator == NULL);
                        Assert(rel->rd_support == NULL);
                        Assert(rel->rd_supportinfo == NULL);
index 422e107ec5193d6960ee2a9c8449e2fa06a05b39..3ad0a3d4b2c7ae935db7e95229f6c16c8be28e5d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.50 2005/04/14 20:03:27 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.51 2005/05/27 23:31:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -104,7 +104,7 @@ extern IndexBulkDeleteResult *index_vacuum_cleanup(Relation indexRelation,
 extern RegProcedure index_cost_estimator(Relation indexRelation);
 extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
                                uint16 procnum);
-extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
+extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
                                  uint16 procnum);
 
 /*
index 1cb40445ea47a73d5057da9f273c90d362ddb85b..f84a84b6f7e41105e8704d9be7d118ccfc842bc5 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.38 2005/03/27 23:53:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.39 2005/05/27 23:31:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,9 +40,8 @@ typedef HeapScanDescData *HeapScanDesc;
 
 /*
  * We use the same IndexScanDescData structure for both amgettuple-based
- * and amgetmulti-based index scans.  Which one is being used can be told
- * by looking at fn_getnext and fn_getmulti, only one of which will be
- * initialized.  Some fields are only relevant in amgettuple-based scans.
+ * and amgetmulti-based index scans.  Some fields are only relevant in
+ * amgettuple-based scans.
  */
 typedef struct IndexScanDescData
 {
@@ -52,6 +51,7 @@ typedef struct IndexScanDescData
        Snapshot        xs_snapshot;    /* snapshot to see */
        int                     numberOfKeys;   /* number of scan keys */
        ScanKey         keyData;                /* array of scan key descriptors */
+       bool            is_multiscan;   /* TRUE = using amgetmulti */
 
        /* signaling to index AM about killing index tuples */
        bool            kill_prior_tuple;               /* last-returned tuple is dead */
@@ -75,9 +75,6 @@ typedef struct IndexScanDescData
        Buffer          xs_cbuf;                /* current heap buffer in scan, if any */
        /* NB: if xs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
 
-       FmgrInfo        fn_getnext;             /* cached lookup info for AM's getnext fn */
-       FmgrInfo        fn_getmulti;    /* cached lookup info for AM's getmulti fn */
-
        /*
         * If keys_are_unique and got_tuple are both true, we stop calling the
         * index AM; it is then necessary for index_getnext to keep track of
index b6a1712efa71b27a23d2b4f158e1e303f11f2561..e3f636b83d82217c031eca58a6bf5847228eefa0 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.83 2005/03/29 00:17:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.84 2005/05/27 23:31:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "catalog/pg_am.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_index.h"
+#include "fmgr.h"
 #include "rewrite/prs2lock.h"
 #include "storage/block.h"
 #include "storage/relfilenode.h"
@@ -99,6 +100,27 @@ typedef struct PgStat_Info
 } PgStat_Info;
 
 
+/*
+ * Cached lookup information for the index access method functions defined
+ * by the pg_am row associated with an index relation.
+ */
+typedef struct RelationAmInfo
+{
+       FmgrInfo        aminsert;
+       FmgrInfo        ambeginscan;
+       FmgrInfo        amgettuple;
+       FmgrInfo        amgetmulti;
+       FmgrInfo        amrescan;
+       FmgrInfo        amendscan;
+       FmgrInfo        ammarkpos;
+       FmgrInfo        amrestrpos;
+       FmgrInfo        ambuild;
+       FmgrInfo        ambulkdelete;
+       FmgrInfo        amvacuumcleanup;
+       FmgrInfo        amcostestimate;
+} RelationAmInfo;
+
+
 /*
  * Here are the contents of a relation cache entry.
  */
@@ -150,11 +172,10 @@ typedef struct RelationData
         * that restriction.
         */
        MemoryContext rd_indexcxt;      /* private memory cxt for this stuff */
+       RelationAmInfo *rd_aminfo;      /* lookup info for funcs found in pg_am */
        Oid                *rd_operator;        /* OIDs of index operators */
        RegProcedure *rd_support;       /* OIDs of support procedures */
-       struct FmgrInfo *rd_supportinfo;        /* lookup info for support
-                                                                                * procedures */
-       /* "struct FmgrInfo" avoids need to include fmgr.h here */
+       FmgrInfo   *rd_supportinfo;     /* lookup info for support procedures */
        List       *rd_indexprs;        /* index expression trees, if any */
        List       *rd_indpred;         /* index predicate tree, if any */