]> granicus.if.org Git - postgresql/commitdiff
Allow index AMs to cache data across aminsert calls within a SQL command.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 9 Feb 2017 16:52:12 +0000 (11:52 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 9 Feb 2017 16:52:12 +0000 (11:52 -0500)
It's always been possible for index AMs to cache data across successive
amgettuple calls within a single SQL command: the IndexScanDesc.opaque
field is meant for precisely that.  However, no comparable facility
exists for amortizing setup work across successive aminsert calls.
This patch adds such a feature and teaches GIN, GIST, and BRIN to use it
to amortize catalog lookups they'd previously been doing on every call.
(The other standard index AMs keep everything they need in the relcache,
so there's little to improve there.)

For GIN, the overall improvement in a statement that inserts many rows
can be as much as 10%, though it seems a bit less for the other two.
In addition, this makes a really significant difference in runtime
for CLOBBER_CACHE_ALWAYS tests, since in those builds the repeated
catalog lookups are vastly more expensive.

The reason this has been hard up to now is that the aminsert function is
not passed any useful place to cache per-statement data.  What I chose to
do is to add suitable fields to struct IndexInfo and pass that to aminsert.
That's not widening the index AM API very much because IndexInfo is already
within the ken of ambuild; in fact, by passing the same info to aminsert
as to ambuild, this is really removing an inconsistency in the AM API.

Discussion: https://postgr.es/m/27568.1486508680@sss.pgh.pa.us

26 files changed:
contrib/bloom/blinsert.c
contrib/bloom/bloom.h
doc/src/sgml/indexam.sgml
src/backend/access/brin/brin.c
src/backend/access/gin/gininsert.c
src/backend/access/gist/gist.c
src/backend/access/hash/hash.c
src/backend/access/heap/tuptoaster.c
src/backend/access/index/indexam.c
src/backend/access/nbtree/nbtree.c
src/backend/access/spgist/spginsert.c
src/backend/catalog/index.c
src/backend/catalog/indexing.c
src/backend/catalog/toasting.c
src/backend/commands/constraint.c
src/backend/commands/indexcmds.c
src/backend/executor/execIndexing.c
src/include/access/amapi.h
src/include/access/brin_internal.h
src/include/access/genam.h
src/include/access/gin_private.h
src/include/access/gist_private.h
src/include/access/hash.h
src/include/access/nbtree.h
src/include/access/spgist.h
src/include/nodes/execnodes.h

index 29bc5cea799c654beaca4e0dc621415c52b58749..913f1f8a51870667a26c7339dd5b5af255375b52 100644 (file)
@@ -190,7 +190,9 @@ blbuildempty(Relation index)
  */
 bool
 blinsert(Relation index, Datum *values, bool *isnull,
-                ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique)
+                ItemPointer ht_ctid, Relation heapRel,
+                IndexUniqueCheck checkUnique,
+                IndexInfo *indexInfo)
 {
        BloomState      blstate;
        BloomTuple *itup;
index a75a235a4f84e987145c6ceafd8fcf85d1ed710a..39d8d05c5d472214bd44c54a941f8cfaf989188f 100644 (file)
@@ -189,7 +189,8 @@ extern bool blvalidate(Oid opclassoid);
 /* index access method interface functions */
 extern bool blinsert(Relation index, Datum *values, bool *isnull,
                 ItemPointer ht_ctid, Relation heapRel,
-                IndexUniqueCheck checkUnique);
+                IndexUniqueCheck checkUnique,
+                struct IndexInfo *indexInfo);
 extern IndexScanDesc blbeginscan(Relation r, int nkeys, int norderbys);
 extern int64 blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
 extern void blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
index 5d8e5574608316ec248f01549497bdae5ecc70fb..9afd7f64179629ab1b901ea082398951e94fdbbe 100644 (file)
@@ -259,7 +259,8 @@ aminsert (Relation indexRelation,
           bool *isnull,
           ItemPointer heap_tid,
           Relation heapRelation,
-          IndexUniqueCheck checkUnique);
+          IndexUniqueCheck checkUnique,
+          IndexInfo *indexInfo);
 </programlisting>
    Insert a new tuple into an existing index.  The <literal>values</> and
    <literal>isnull</> arrays give the key values to be indexed, and
@@ -287,6 +288,14 @@ aminsert (Relation indexRelation,
    indexed, <function>aminsert</> should just return without doing anything.
   </para>
 
+  <para>
+   If the index AM wishes to cache data across successive index insertions
+   within a SQL statement, it can allocate space
+   in <literal>indexInfo-&gt;ii_Context</literal> and store a pointer to the
+   data in <literal>indexInfo-&gt;ii_AmCache</literal> (which will be NULL
+   initially).
+  </para>
+
   <para>
 <programlisting>
 IndexBulkDeleteResult *
index b2afdb7bedb04933e6bfc3e875f80ae71868ee04..4ff046b4b01e689f61f085c169f150dc402f3725 100644 (file)
@@ -131,14 +131,15 @@ brinhandler(PG_FUNCTION_ARGS)
 bool
 brininsert(Relation idxRel, Datum *values, bool *nulls,
                   ItemPointer heaptid, Relation heapRel,
-                  IndexUniqueCheck checkUnique)
+                  IndexUniqueCheck checkUnique,
+                  IndexInfo *indexInfo)
 {
        BlockNumber pagesPerRange;
-       BrinDesc   *bdesc = NULL;
+       BrinDesc   *bdesc = (BrinDesc *) indexInfo->ii_AmCache;
        BrinRevmap *revmap;
        Buffer          buf = InvalidBuffer;
        MemoryContext tupcxt = NULL;
-       MemoryContext oldcxt = NULL;
+       MemoryContext oldcxt = CurrentMemoryContext;
 
        revmap = brinRevmapInitialize(idxRel, &pagesPerRange, NULL);
 
@@ -163,14 +164,21 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
                if (!brtup)
                        break;
 
-               /* First time through? */
+               /* First time through in this statement? */
                if (bdesc == NULL)
                {
+                       MemoryContextSwitchTo(indexInfo->ii_Context);
                        bdesc = brin_build_desc(idxRel);
+                       indexInfo->ii_AmCache = (void *) bdesc;
+                       MemoryContextSwitchTo(oldcxt);
+               }
+               /* First time through in this brininsert call? */
+               if (tupcxt == NULL)
+               {
                        tupcxt = AllocSetContextCreate(CurrentMemoryContext,
                                                                                   "brininsert cxt",
                                                                                   ALLOCSET_DEFAULT_SIZES);
-                       oldcxt = MemoryContextSwitchTo(tupcxt);
+                       MemoryContextSwitchTo(tupcxt);
                }
 
                dtup = brin_deform_tuple(bdesc, brtup);
@@ -261,12 +269,9 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
        brinRevmapTerminate(revmap);
        if (BufferIsValid(buf))
                ReleaseBuffer(buf);
-       if (bdesc != NULL)
-       {
-               brin_free_desc(bdesc);
-               MemoryContextSwitchTo(oldcxt);
+       MemoryContextSwitchTo(oldcxt);
+       if (tupcxt != NULL)
                MemoryContextDelete(tupcxt);
-       }
 
        return false;
 }
index 03a7235a0a3e79fd846c74e20d6e028c1797e56e..3d3b9e08400f8d8d84feb76276112962a836bba6 100644 (file)
@@ -482,39 +482,48 @@ ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum,
 bool
 gininsert(Relation index, Datum *values, bool *isnull,
                  ItemPointer ht_ctid, Relation heapRel,
-                 IndexUniqueCheck checkUnique)
+                 IndexUniqueCheck checkUnique,
+                 IndexInfo *indexInfo)
 {
-       GinState        ginstate;
+       GinState   *ginstate = (GinState *) indexInfo->ii_AmCache;
        MemoryContext oldCtx;
        MemoryContext insertCtx;
        int                     i;
 
+       /* Initialize GinState cache if first call in this statement */
+       if (ginstate == NULL)
+       {
+               oldCtx = MemoryContextSwitchTo(indexInfo->ii_Context);
+               ginstate = (GinState *) palloc(sizeof(GinState));
+               initGinState(ginstate, index);
+               indexInfo->ii_AmCache = (void *) ginstate;
+               MemoryContextSwitchTo(oldCtx);
+       }
+
        insertCtx = AllocSetContextCreate(CurrentMemoryContext,
                                                                          "Gin insert temporary context",
                                                                          ALLOCSET_DEFAULT_SIZES);
 
        oldCtx = MemoryContextSwitchTo(insertCtx);
 
-       initGinState(&ginstate, index);
-
        if (GinGetUseFastUpdate(index))
        {
                GinTupleCollector collector;
 
                memset(&collector, 0, sizeof(GinTupleCollector));
 
-               for (i = 0; i < ginstate.origTupdesc->natts; i++)
-                       ginHeapTupleFastCollect(&ginstate, &collector,
+               for (i = 0; i < ginstate->origTupdesc->natts; i++)
+                       ginHeapTupleFastCollect(ginstate, &collector,
                                                                        (OffsetNumber) (i + 1),
                                                                        values[i], isnull[i],
                                                                        ht_ctid);
 
-               ginHeapTupleFastInsert(&ginstate, &collector);
+               ginHeapTupleFastInsert(ginstate, &collector);
        }
        else
        {
-               for (i = 0; i < ginstate.origTupdesc->natts; i++)
-                       ginHeapTupleInsert(&ginstate, (OffsetNumber) (i + 1),
+               for (i = 0; i < ginstate->origTupdesc->natts; i++)
+                       ginHeapTupleInsert(ginstate, (OffsetNumber) (i + 1),
                                                           values[i], isnull[i],
                                                           ht_ctid);
        }
index c2247ad2f782ff866788a049d49c09c79ec3ac21..96ead531ea3ba345eeaae797889780d169274182 100644 (file)
@@ -18,6 +18,7 @@
 #include "access/gistscan.h"
 #include "catalog/pg_collation.h"
 #include "miscadmin.h"
+#include "nodes/execnodes.h"
 #include "utils/builtins.h"
 #include "utils/index_selfuncs.h"
 #include "utils/memutils.h"
@@ -144,21 +145,23 @@ gistbuildempty(Relation index)
 bool
 gistinsert(Relation r, Datum *values, bool *isnull,
                   ItemPointer ht_ctid, Relation heapRel,
-                  IndexUniqueCheck checkUnique)
+                  IndexUniqueCheck checkUnique,
+                  IndexInfo *indexInfo)
 {
+       GISTSTATE  *giststate = (GISTSTATE *) indexInfo->ii_AmCache;
        IndexTuple      itup;
-       GISTSTATE  *giststate;
        MemoryContext oldCxt;
 
-       giststate = initGISTstate(r);
+       /* Initialize GISTSTATE cache if first call in this statement */
+       if (giststate == NULL)
+       {
+               oldCxt = MemoryContextSwitchTo(indexInfo->ii_Context);
+               giststate = initGISTstate(r);
+               giststate->tempCxt = createTempGistContext();
+               indexInfo->ii_AmCache = (void *) giststate;
+               MemoryContextSwitchTo(oldCxt);
+       }
 
-       /*
-        * We use the giststate's scan context as temp context too.  This means
-        * that any memory leaked by the support functions is not reclaimed until
-        * end of insert.  In most cases, we aren't going to call the support
-        * functions very many times before finishing the insert, so this seems
-        * cheaper than resetting a temp context for each function call.
-        */
        oldCxt = MemoryContextSwitchTo(giststate->tempCxt);
 
        itup = gistFormTuple(giststate, r,
@@ -169,7 +172,7 @@ gistinsert(Relation r, Datum *values, bool *isnull,
 
        /* cleanup */
        MemoryContextSwitchTo(oldCxt);
-       freeGISTstate(giststate);
+       MemoryContextReset(giststate->tempCxt);
 
        return false;
 }
index 97ad22aa6f3aa88e341962a14c9e2353a7545a7f..bca77a80c3b4592b988c3adb8019576b1525429f 100644 (file)
@@ -232,7 +232,8 @@ hashbuildCallback(Relation index,
 bool
 hashinsert(Relation rel, Datum *values, bool *isnull,
                   ItemPointer ht_ctid, Relation heapRel,
-                  IndexUniqueCheck checkUnique)
+                  IndexUniqueCheck checkUnique,
+                  IndexInfo *indexInfo)
 {
        Datum           index_values[1];
        bool            index_isnull[1];
index 496648c42f00066c1bfb865bfcb5f120b22b802b..19e704800284a45760d708fd989c6b3c5cef740b 100644 (file)
@@ -1604,7 +1604,9 @@ toast_save_datum(Relation rel, Datum value,
                 * Create the index entry.  We cheat a little here by not using
                 * FormIndexDatum: this relies on the knowledge that the index columns
                 * are the same as the initial columns of the table for all the
-                * indexes.
+                * indexes.  We also cheat by not providing an IndexInfo: this is okay
+                * for now because btree doesn't need one, but we might have to be
+                * more honest someday.
                 *
                 * Note also that there had better not be any user-created index on
                 * the TOAST table, since we don't bother to update anything else.
@@ -1617,7 +1619,8 @@ toast_save_datum(Relation rel, Datum value,
                                                         &(toasttup->t_self),
                                                         toastrel,
                                                         toastidxs[i]->rd_index->indisunique ?
-                                                        UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+                                                        UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+                                                        NULL);
                }
 
                /*
index ba27c1e86d9f64de25aa2db6cd8da9b31eb6453b..4e7eca73ccef51e1bed2c8b1f3abd449a7510b84 100644 (file)
@@ -196,7 +196,8 @@ index_insert(Relation indexRelation,
                         bool *isnull,
                         ItemPointer heap_t_ctid,
                         Relation heapRelation,
-                        IndexUniqueCheck checkUnique)
+                        IndexUniqueCheck checkUnique,
+                        IndexInfo *indexInfo)
 {
        RELATION_CHECKS;
        CHECK_REL_PROCEDURE(aminsert);
@@ -208,7 +209,7 @@ index_insert(Relation indexRelation,
 
        return indexRelation->rd_amroutine->aminsert(indexRelation, values, isnull,
                                                                                                 heap_t_ctid, heapRelation,
-                                                                                                checkUnique);
+                                                                                                checkUnique, indexInfo);
 }
 
 /*
index 469e7abe4dff2612eef8f63d223cd96033287125..945e563fcc50bd5c5a629e792909f6fdca4f1bad 100644 (file)
@@ -276,7 +276,8 @@ btbuildempty(Relation index)
 bool
 btinsert(Relation rel, Datum *values, bool *isnull,
                 ItemPointer ht_ctid, Relation heapRel,
-                IndexUniqueCheck checkUnique)
+                IndexUniqueCheck checkUnique,
+                IndexInfo *indexInfo)
 {
        bool            result;
        IndexTuple      itup;
index b42f4b713993ea75a11e187a8e8d9189d235cba4..14f8a9ee8e012e6b98cb2f4b61e00c35bba2a235 100644 (file)
@@ -206,7 +206,8 @@ spgbuildempty(Relation index)
 bool
 spginsert(Relation index, Datum *values, bool *isnull,
                  ItemPointer ht_ctid, Relation heapRel,
-                 IndexUniqueCheck checkUnique)
+                 IndexUniqueCheck checkUnique,
+                 IndexInfo *indexInfo)
 {
        SpGistState spgstate;
        MemoryContext oldCtx;
index 815a694cfcd9b22a8ce154a46ce23ad59fffb418..f8d92145e86f41c7e1bf4f8fb94158e47ec70921 100644 (file)
@@ -1687,6 +1687,10 @@ BuildIndexInfo(Relation index)
        ii->ii_Concurrent = false;
        ii->ii_BrokenHotChain = false;
 
+       /* set up for possible use by index AM */
+       ii->ii_AmCache = NULL;
+       ii->ii_Context = CurrentMemoryContext;
+
        return ii;
 }
 
@@ -3158,7 +3162,8 @@ validate_index_heapscan(Relation heapRelation,
                                                 &rootTuple,
                                                 heapRelation,
                                                 indexInfo->ii_Unique ?
-                                                UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+                                                UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+                                                indexInfo);
 
                        state->tups_inserted += 1;
                }
index 76268e1d2a27a5898bfc5038494d555defbf91ea..abc344ad6992613d0fa0c1cf9332100da94f0bc3 100644 (file)
@@ -139,7 +139,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
                                         &(heapTuple->t_self),          /* tid of heap tuple */
                                         heapRelation,
                                         relationDescs[i]->rd_index->indisunique ?
-                                        UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+                                        UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
+                                        indexInfo);
        }
 
        ExecDropSingleTupleTableSlot(slot);
index e5f773d51d0b2c6802352ecd7007f7df9ef835d3..0e4231668d4e69a9d5b119b3e95b7c162b4aa449 100644 (file)
@@ -315,6 +315,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
        indexInfo->ii_ReadyForInserts = true;
        indexInfo->ii_Concurrent = false;
        indexInfo->ii_BrokenHotChain = false;
+       indexInfo->ii_AmCache = NULL;
+       indexInfo->ii_Context = CurrentMemoryContext;
 
        collationObjectId[0] = InvalidOid;
        collationObjectId[1] = InvalidOid;
index e9eeacd03a9ef39287d1ff0bfe47f5a2683ab251..e2544e51ed5f45cdd037e9281078b95d3ccfb6f8 100644 (file)
@@ -165,7 +165,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
                 * index will know about.
                 */
                index_insert(indexRel, values, isnull, &(new_row->t_self),
-                                        trigdata->tg_relation, UNIQUE_CHECK_EXISTING);
+                                        trigdata->tg_relation, UNIQUE_CHECK_EXISTING,
+                                        indexInfo);
        }
        else
        {
index f4814c095b59884191d3f7e4ad0516bbd35b5241..265e9b33f78bd762909ed90f8cc8e0c4043c4650 100644 (file)
@@ -183,6 +183,8 @@ CheckIndexCompatible(Oid oldId,
        indexInfo->ii_ExclusionOps = NULL;
        indexInfo->ii_ExclusionProcs = NULL;
        indexInfo->ii_ExclusionStrats = NULL;
+       indexInfo->ii_AmCache = NULL;
+       indexInfo->ii_Context = CurrentMemoryContext;
        typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
        collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
        classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
@@ -562,6 +564,8 @@ DefineIndex(Oid relationId,
        indexInfo->ii_ReadyForInserts = !stmt->concurrent;
        indexInfo->ii_Concurrent = stmt->concurrent;
        indexInfo->ii_BrokenHotChain = false;
+       indexInfo->ii_AmCache = NULL;
+       indexInfo->ii_Context = CurrentMemoryContext;
 
        typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
        collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
index 8d119f6a19b306979c3aa66ee3f5a01f159654e7..5242dee00644725ba4eb45727f1d6ad11ec84269 100644 (file)
@@ -391,7 +391,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
                                                 isnull,        /* null flags */
                                                 tupleid,               /* tid of heap tuple */
                                                 heapRelation,  /* heap relation */
-                                                checkUnique);  /* type of uniqueness check to do */
+                                                checkUnique,   /* type of uniqueness check to do */
+                                                indexInfo);    /* index AM may need this */
 
                /*
                 * If the index has an associated exclusion constraint, check that.
index e91e41dc0f405e741bc239adab30eb321a5449df..b0730bfefae0728dcc92a513c1f9494b06781e13 100644 (file)
@@ -72,7 +72,8 @@ typedef bool (*aminsert_function) (Relation indexRelation,
                                                                                           bool *isnull,
                                                                                           ItemPointer heap_tid,
                                                                                           Relation heapRelation,
-                                                                                          IndexUniqueCheck checkUnique);
+                                                                                          IndexUniqueCheck checkUnique,
+                                                                                          struct IndexInfo *indexInfo);
 
 /* bulk delete */
 typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info,
index 40312604f8dc1f7de5594749b09f0db59a87969e..abe887788be39508f4b5081216ddcbb6f7b1fdff 100644 (file)
@@ -89,7 +89,8 @@ extern IndexBuildResult *brinbuild(Relation heap, Relation index,
 extern void brinbuildempty(Relation index);
 extern bool brininsert(Relation idxRel, Datum *values, bool *nulls,
                   ItemPointer heaptid, Relation heapRel,
-                  IndexUniqueCheck checkUnique);
+                  IndexUniqueCheck checkUnique,
+                  struct IndexInfo *indexInfo);
 extern IndexScanDesc brinbeginscan(Relation r, int nkeys, int norderbys);
 extern int64 bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
 extern void brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
index 51466b96e8b079e24f10169c367ff971007db015..f467b18a9c79cabbe1c4024e8d89b92bed1e2e3e 100644 (file)
@@ -21,6 +21,9 @@
 #include "utils/relcache.h"
 #include "utils/snapshot.h"
 
+/* We don't want this file to depend on execnodes.h. */
+struct IndexInfo;
+
 /*
  * Struct for statistics returned by ambuild
  */
@@ -131,7 +134,8 @@ extern bool index_insert(Relation indexRelation,
                         Datum *values, bool *isnull,
                         ItemPointer heap_t_ctid,
                         Relation heapRelation,
-                        IndexUniqueCheck checkUnique);
+                        IndexUniqueCheck checkUnique,
+                        struct IndexInfo *indexInfo);
 
 extern IndexScanDesc index_beginscan(Relation heapRelation,
                                Relation indexRelation,
index d46274ee85d573246c2ff623060173375f1d08e5..7e1557ea85fbd02b349f416f5c240c5ffbdefa1e 100644 (file)
@@ -617,7 +617,8 @@ extern IndexBuildResult *ginbuild(Relation heap, Relation index,
 extern void ginbuildempty(Relation index);
 extern bool gininsert(Relation index, Datum *values, bool *isnull,
                  ItemPointer ht_ctid, Relation heapRel,
-                 IndexUniqueCheck checkUnique);
+                 IndexUniqueCheck checkUnique,
+                 struct IndexInfo *indexInfo);
 extern void ginEntryInsert(GinState *ginstate,
                           OffsetNumber attnum, Datum key, GinNullCategory category,
                           ItemPointerData *items, uint32 nitem,
index f4beeb920949cbbd2d970e7aaa905e8dd0c7009b..873c52a1a220de8c139365131bc341bc1706996c 100644 (file)
@@ -426,7 +426,8 @@ typedef struct GiSTOptions
 extern void gistbuildempty(Relation index);
 extern bool gistinsert(Relation r, Datum *values, bool *isnull,
                   ItemPointer ht_ctid, Relation heapRel,
-                  IndexUniqueCheck checkUnique);
+                  IndexUniqueCheck checkUnique,
+                  struct IndexInfo *indexInfo);
 extern MemoryContext createTempGistContext(void);
 extern GISTSTATE *initGISTstate(Relation index);
 extern void freeGISTstate(GISTSTATE *giststate);
index c0455851f466d3361804f85aa6fe4c40f62589df..3bf587b1b703af89c9fc97e6ca06b5cb386252d5 100644 (file)
@@ -277,7 +277,8 @@ extern IndexBuildResult *hashbuild(Relation heap, Relation index,
 extern void hashbuildempty(Relation index);
 extern bool hashinsert(Relation rel, Datum *values, bool *isnull,
                   ItemPointer ht_ctid, Relation heapRel,
-                  IndexUniqueCheck checkUnique);
+                  IndexUniqueCheck checkUnique,
+                  struct IndexInfo *indexInfo);
 extern bool hashgettuple(IndexScanDesc scan, ScanDirection dir);
 extern int64 hashgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
 extern IndexScanDesc hashbeginscan(Relation rel, int nkeys, int norderbys);
index b2517623aa863a98972238a1ac944bba61f0d215..344ef9933c89e56a00623ec2684735b32c3b6d8b 100644 (file)
@@ -659,7 +659,8 @@ extern IndexBuildResult *btbuild(Relation heap, Relation index,
 extern void btbuildempty(Relation index);
 extern bool btinsert(Relation rel, Datum *values, bool *isnull,
                 ItemPointer ht_ctid, Relation heapRel,
-                IndexUniqueCheck checkUnique);
+                IndexUniqueCheck checkUnique,
+                struct IndexInfo *indexInfo);
 extern IndexScanDesc btbeginscan(Relation rel, int nkeys, int norderbys);
 extern bool btgettuple(IndexScanDesc scan, ScanDirection dir);
 extern int64 btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
index 6f59c0bbc52246897a00c02575f3f66c16bfab81..ee7480ad39e92250ee9c9b9eedfd127e4d985bb4 100644 (file)
@@ -191,7 +191,8 @@ extern IndexBuildResult *spgbuild(Relation heap, Relation index,
 extern void spgbuildempty(Relation index);
 extern bool spginsert(Relation index, Datum *values, bool *isnull,
                  ItemPointer ht_ctid, Relation heapRel,
-                 IndexUniqueCheck checkUnique);
+                 IndexUniqueCheck checkUnique,
+                 struct IndexInfo *indexInfo);
 
 /* spgscan.c */
 extern IndexScanDesc spgbeginscan(Relation rel, int keysz, int orderbysz);
index f9bcdd63de0718a5419649fe7ea4f10e34d913cb..42c6c58ff9c9b934c38e863bf5ffd828b8df0960 100644 (file)
@@ -52,6 +52,8 @@
  *             ReadyForInserts         is it valid for inserts?
  *             Concurrent                      are we doing a concurrent index build?
  *             BrokenHotChain          did we detect any broken HOT chains?
+ *             AmCache                         private cache area for index AM
+ *             Context                         memory context holding this IndexInfo
  *
  * ii_Concurrent and ii_BrokenHotChain are used only during index build;
  * they're conventionally set to false otherwise.
@@ -76,6 +78,8 @@ typedef struct IndexInfo
        bool            ii_ReadyForInserts;
        bool            ii_Concurrent;
        bool            ii_BrokenHotChain;
+       void       *ii_AmCache;
+       MemoryContext ii_Context;
 } IndexInfo;
 
 /* ----------------