Commit 86d911ec authored by Tom Lane's avatar Tom Lane

Allow index AMs to cache data across aminsert calls within a SQL command.

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
parent 7c5d8c16
...@@ -190,7 +190,9 @@ blbuildempty(Relation index) ...@@ -190,7 +190,9 @@ blbuildempty(Relation index)
*/ */
bool bool
blinsert(Relation index, Datum *values, bool *isnull, 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; BloomState blstate;
BloomTuple *itup; BloomTuple *itup;
......
...@@ -189,7 +189,8 @@ extern bool blvalidate(Oid opclassoid); ...@@ -189,7 +189,8 @@ extern bool blvalidate(Oid opclassoid);
/* index access method interface functions */ /* index access method interface functions */
extern bool blinsert(Relation index, Datum *values, bool *isnull, extern bool blinsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern IndexScanDesc blbeginscan(Relation r, int nkeys, int norderbys); extern IndexScanDesc blbeginscan(Relation r, int nkeys, int norderbys);
extern int64 blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm); extern int64 blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
extern void blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, extern void blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
......
...@@ -259,7 +259,8 @@ aminsert (Relation indexRelation, ...@@ -259,7 +259,8 @@ aminsert (Relation indexRelation,
bool *isnull, bool *isnull,
ItemPointer heap_tid, ItemPointer heap_tid,
Relation heapRelation, Relation heapRelation,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
IndexInfo *indexInfo);
</programlisting> </programlisting>
Insert a new tuple into an existing index. The <literal>values</> and Insert a new tuple into an existing index. The <literal>values</> and
<literal>isnull</> arrays give the key values to be indexed, and <literal>isnull</> arrays give the key values to be indexed, and
...@@ -287,6 +288,14 @@ aminsert (Relation indexRelation, ...@@ -287,6 +288,14 @@ aminsert (Relation indexRelation,
indexed, <function>aminsert</> should just return without doing anything. indexed, <function>aminsert</> should just return without doing anything.
</para> </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> <para>
<programlisting> <programlisting>
IndexBulkDeleteResult * IndexBulkDeleteResult *
......
...@@ -131,14 +131,15 @@ brinhandler(PG_FUNCTION_ARGS) ...@@ -131,14 +131,15 @@ brinhandler(PG_FUNCTION_ARGS)
bool bool
brininsert(Relation idxRel, Datum *values, bool *nulls, brininsert(Relation idxRel, Datum *values, bool *nulls,
ItemPointer heaptid, Relation heapRel, ItemPointer heaptid, Relation heapRel,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
BlockNumber pagesPerRange; BlockNumber pagesPerRange;
BrinDesc *bdesc = NULL; BrinDesc *bdesc = (BrinDesc *) indexInfo->ii_AmCache;
BrinRevmap *revmap; BrinRevmap *revmap;
Buffer buf = InvalidBuffer; Buffer buf = InvalidBuffer;
MemoryContext tupcxt = NULL; MemoryContext tupcxt = NULL;
MemoryContext oldcxt = NULL; MemoryContext oldcxt = CurrentMemoryContext;
revmap = brinRevmapInitialize(idxRel, &pagesPerRange, NULL); revmap = brinRevmapInitialize(idxRel, &pagesPerRange, NULL);
...@@ -163,14 +164,21 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, ...@@ -163,14 +164,21 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
if (!brtup) if (!brtup)
break; break;
/* First time through? */ /* First time through in this statement? */
if (bdesc == NULL) if (bdesc == NULL)
{ {
MemoryContextSwitchTo(indexInfo->ii_Context);
bdesc = brin_build_desc(idxRel); 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, tupcxt = AllocSetContextCreate(CurrentMemoryContext,
"brininsert cxt", "brininsert cxt",
ALLOCSET_DEFAULT_SIZES); ALLOCSET_DEFAULT_SIZES);
oldcxt = MemoryContextSwitchTo(tupcxt); MemoryContextSwitchTo(tupcxt);
} }
dtup = brin_deform_tuple(bdesc, brtup); dtup = brin_deform_tuple(bdesc, brtup);
...@@ -261,12 +269,9 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, ...@@ -261,12 +269,9 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
brinRevmapTerminate(revmap); brinRevmapTerminate(revmap);
if (BufferIsValid(buf)) if (BufferIsValid(buf))
ReleaseBuffer(buf); ReleaseBuffer(buf);
if (bdesc != NULL) MemoryContextSwitchTo(oldcxt);
{ if (tupcxt != NULL)
brin_free_desc(bdesc);
MemoryContextSwitchTo(oldcxt);
MemoryContextDelete(tupcxt); MemoryContextDelete(tupcxt);
}
return false; return false;
} }
......
...@@ -482,39 +482,48 @@ ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum, ...@@ -482,39 +482,48 @@ ginHeapTupleInsert(GinState *ginstate, OffsetNumber attnum,
bool bool
gininsert(Relation index, Datum *values, bool *isnull, gininsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
GinState ginstate; GinState *ginstate = (GinState *) indexInfo->ii_AmCache;
MemoryContext oldCtx; MemoryContext oldCtx;
MemoryContext insertCtx; MemoryContext insertCtx;
int i; 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, insertCtx = AllocSetContextCreate(CurrentMemoryContext,
"Gin insert temporary context", "Gin insert temporary context",
ALLOCSET_DEFAULT_SIZES); ALLOCSET_DEFAULT_SIZES);
oldCtx = MemoryContextSwitchTo(insertCtx); oldCtx = MemoryContextSwitchTo(insertCtx);
initGinState(&ginstate, index);
if (GinGetUseFastUpdate(index)) if (GinGetUseFastUpdate(index))
{ {
GinTupleCollector collector; GinTupleCollector collector;
memset(&collector, 0, sizeof(GinTupleCollector)); memset(&collector, 0, sizeof(GinTupleCollector));
for (i = 0; i < ginstate.origTupdesc->natts; i++) for (i = 0; i < ginstate->origTupdesc->natts; i++)
ginHeapTupleFastCollect(&ginstate, &collector, ginHeapTupleFastCollect(ginstate, &collector,
(OffsetNumber) (i + 1), (OffsetNumber) (i + 1),
values[i], isnull[i], values[i], isnull[i],
ht_ctid); ht_ctid);
ginHeapTupleFastInsert(&ginstate, &collector); ginHeapTupleFastInsert(ginstate, &collector);
} }
else else
{ {
for (i = 0; i < ginstate.origTupdesc->natts; i++) for (i = 0; i < ginstate->origTupdesc->natts; i++)
ginHeapTupleInsert(&ginstate, (OffsetNumber) (i + 1), ginHeapTupleInsert(ginstate, (OffsetNumber) (i + 1),
values[i], isnull[i], values[i], isnull[i],
ht_ctid); ht_ctid);
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "access/gistscan.h" #include "access/gistscan.h"
#include "catalog/pg_collation.h" #include "catalog/pg_collation.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/execnodes.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/index_selfuncs.h" #include "utils/index_selfuncs.h"
#include "utils/memutils.h" #include "utils/memutils.h"
...@@ -144,21 +145,23 @@ gistbuildempty(Relation index) ...@@ -144,21 +145,23 @@ gistbuildempty(Relation index)
bool bool
gistinsert(Relation r, Datum *values, bool *isnull, gistinsert(Relation r, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
GISTSTATE *giststate = (GISTSTATE *) indexInfo->ii_AmCache;
IndexTuple itup; IndexTuple itup;
GISTSTATE *giststate;
MemoryContext oldCxt; 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); oldCxt = MemoryContextSwitchTo(giststate->tempCxt);
itup = gistFormTuple(giststate, r, itup = gistFormTuple(giststate, r,
...@@ -169,7 +172,7 @@ gistinsert(Relation r, Datum *values, bool *isnull, ...@@ -169,7 +172,7 @@ gistinsert(Relation r, Datum *values, bool *isnull,
/* cleanup */ /* cleanup */
MemoryContextSwitchTo(oldCxt); MemoryContextSwitchTo(oldCxt);
freeGISTstate(giststate); MemoryContextReset(giststate->tempCxt);
return false; return false;
} }
......
...@@ -232,7 +232,8 @@ hashbuildCallback(Relation index, ...@@ -232,7 +232,8 @@ hashbuildCallback(Relation index,
bool bool
hashinsert(Relation rel, Datum *values, bool *isnull, hashinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
Datum index_values[1]; Datum index_values[1];
bool index_isnull[1]; bool index_isnull[1];
......
...@@ -1604,7 +1604,9 @@ toast_save_datum(Relation rel, Datum value, ...@@ -1604,7 +1604,9 @@ toast_save_datum(Relation rel, Datum value,
* Create the index entry. We cheat a little here by not using * Create the index entry. We cheat a little here by not using
* FormIndexDatum: this relies on the knowledge that the index columns * FormIndexDatum: this relies on the knowledge that the index columns
* are the same as the initial columns of the table for all the * 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 * 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. * the TOAST table, since we don't bother to update anything else.
...@@ -1617,7 +1619,8 @@ toast_save_datum(Relation rel, Datum value, ...@@ -1617,7 +1619,8 @@ toast_save_datum(Relation rel, Datum value,
&(toasttup->t_self), &(toasttup->t_self),
toastrel, toastrel,
toastidxs[i]->rd_index->indisunique ? toastidxs[i]->rd_index->indisunique ?
UNIQUE_CHECK_YES : UNIQUE_CHECK_NO); UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
NULL);
} }
/* /*
......
...@@ -196,7 +196,8 @@ index_insert(Relation indexRelation, ...@@ -196,7 +196,8 @@ index_insert(Relation indexRelation,
bool *isnull, bool *isnull,
ItemPointer heap_t_ctid, ItemPointer heap_t_ctid,
Relation heapRelation, Relation heapRelation,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
RELATION_CHECKS; RELATION_CHECKS;
CHECK_REL_PROCEDURE(aminsert); CHECK_REL_PROCEDURE(aminsert);
...@@ -208,7 +209,7 @@ index_insert(Relation indexRelation, ...@@ -208,7 +209,7 @@ index_insert(Relation indexRelation,
return indexRelation->rd_amroutine->aminsert(indexRelation, values, isnull, return indexRelation->rd_amroutine->aminsert(indexRelation, values, isnull,
heap_t_ctid, heapRelation, heap_t_ctid, heapRelation,
checkUnique); checkUnique, indexInfo);
} }
/* /*
......
...@@ -276,7 +276,8 @@ btbuildempty(Relation index) ...@@ -276,7 +276,8 @@ btbuildempty(Relation index)
bool bool
btinsert(Relation rel, Datum *values, bool *isnull, btinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
bool result; bool result;
IndexTuple itup; IndexTuple itup;
......
...@@ -206,7 +206,8 @@ spgbuildempty(Relation index) ...@@ -206,7 +206,8 @@ spgbuildempty(Relation index)
bool bool
spginsert(Relation index, Datum *values, bool *isnull, spginsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique) IndexUniqueCheck checkUnique,
IndexInfo *indexInfo)
{ {
SpGistState spgstate; SpGistState spgstate;
MemoryContext oldCtx; MemoryContext oldCtx;
......
...@@ -1687,6 +1687,10 @@ BuildIndexInfo(Relation index) ...@@ -1687,6 +1687,10 @@ BuildIndexInfo(Relation index)
ii->ii_Concurrent = false; ii->ii_Concurrent = false;
ii->ii_BrokenHotChain = false; ii->ii_BrokenHotChain = false;
/* set up for possible use by index AM */
ii->ii_AmCache = NULL;
ii->ii_Context = CurrentMemoryContext;
return ii; return ii;
} }
...@@ -3158,7 +3162,8 @@ validate_index_heapscan(Relation heapRelation, ...@@ -3158,7 +3162,8 @@ validate_index_heapscan(Relation heapRelation,
&rootTuple, &rootTuple,
heapRelation, heapRelation,
indexInfo->ii_Unique ? indexInfo->ii_Unique ?
UNIQUE_CHECK_YES : UNIQUE_CHECK_NO); UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
indexInfo);
state->tups_inserted += 1; state->tups_inserted += 1;
} }
......
...@@ -139,7 +139,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple) ...@@ -139,7 +139,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
&(heapTuple->t_self), /* tid of heap tuple */ &(heapTuple->t_self), /* tid of heap tuple */
heapRelation, heapRelation,
relationDescs[i]->rd_index->indisunique ? relationDescs[i]->rd_index->indisunique ?
UNIQUE_CHECK_YES : UNIQUE_CHECK_NO); UNIQUE_CHECK_YES : UNIQUE_CHECK_NO,
indexInfo);
} }
ExecDropSingleTupleTableSlot(slot); ExecDropSingleTupleTableSlot(slot);
......
...@@ -315,6 +315,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, ...@@ -315,6 +315,8 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
indexInfo->ii_ReadyForInserts = true; indexInfo->ii_ReadyForInserts = true;
indexInfo->ii_Concurrent = false; indexInfo->ii_Concurrent = false;
indexInfo->ii_BrokenHotChain = false; indexInfo->ii_BrokenHotChain = false;
indexInfo->ii_AmCache = NULL;
indexInfo->ii_Context = CurrentMemoryContext;
collationObjectId[0] = InvalidOid; collationObjectId[0] = InvalidOid;
collationObjectId[1] = InvalidOid; collationObjectId[1] = InvalidOid;
......
...@@ -165,7 +165,8 @@ unique_key_recheck(PG_FUNCTION_ARGS) ...@@ -165,7 +165,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
* index will know about. * index will know about.
*/ */
index_insert(indexRel, values, isnull, &(new_row->t_self), index_insert(indexRel, values, isnull, &(new_row->t_self),
trigdata->tg_relation, UNIQUE_CHECK_EXISTING); trigdata->tg_relation, UNIQUE_CHECK_EXISTING,
indexInfo);
} }
else else
{ {
......
...@@ -183,6 +183,8 @@ CheckIndexCompatible(Oid oldId, ...@@ -183,6 +183,8 @@ CheckIndexCompatible(Oid oldId,
indexInfo->ii_ExclusionOps = NULL; indexInfo->ii_ExclusionOps = NULL;
indexInfo->ii_ExclusionProcs = NULL; indexInfo->ii_ExclusionProcs = NULL;
indexInfo->ii_ExclusionStrats = NULL; indexInfo->ii_ExclusionStrats = NULL;
indexInfo->ii_AmCache = NULL;
indexInfo->ii_Context = CurrentMemoryContext;
typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
...@@ -562,6 +564,8 @@ DefineIndex(Oid relationId, ...@@ -562,6 +564,8 @@ DefineIndex(Oid relationId,
indexInfo->ii_ReadyForInserts = !stmt->concurrent; indexInfo->ii_ReadyForInserts = !stmt->concurrent;
indexInfo->ii_Concurrent = stmt->concurrent; indexInfo->ii_Concurrent = stmt->concurrent;
indexInfo->ii_BrokenHotChain = false; indexInfo->ii_BrokenHotChain = false;
indexInfo->ii_AmCache = NULL;
indexInfo->ii_Context = CurrentMemoryContext;
typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); typeObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); collationObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
......
...@@ -391,7 +391,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot, ...@@ -391,7 +391,8 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
isnull, /* null flags */ isnull, /* null flags */
tupleid, /* tid of heap tuple */ tupleid, /* tid of heap tuple */
heapRelation, /* heap relation */ 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. * If the index has an associated exclusion constraint, check that.
......
...@@ -72,7 +72,8 @@ typedef bool (*aminsert_function) (Relation indexRelation, ...@@ -72,7 +72,8 @@ typedef bool (*aminsert_function) (Relation indexRelation,
bool *isnull, bool *isnull,
ItemPointer heap_tid, ItemPointer heap_tid,
Relation heapRelation, Relation heapRelation,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
/* bulk delete */ /* bulk delete */
typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info, typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info,
......
...@@ -89,7 +89,8 @@ extern IndexBuildResult *brinbuild(Relation heap, Relation index, ...@@ -89,7 +89,8 @@ extern IndexBuildResult *brinbuild(Relation heap, Relation index,
extern void brinbuildempty(Relation index); extern void brinbuildempty(Relation index);
extern bool brininsert(Relation idxRel, Datum *values, bool *nulls, extern bool brininsert(Relation idxRel, Datum *values, bool *nulls,
ItemPointer heaptid, Relation heapRel, ItemPointer heaptid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern IndexScanDesc brinbeginscan(Relation r, int nkeys, int norderbys); extern IndexScanDesc brinbeginscan(Relation r, int nkeys, int norderbys);
extern int64 bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm); extern int64 bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
extern void brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, extern void brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#include "utils/relcache.h" #include "utils/relcache.h"
#include "utils/snapshot.h" #include "utils/snapshot.h"
/* We don't want this file to depend on execnodes.h. */
struct IndexInfo;
/* /*
* Struct for statistics returned by ambuild * Struct for statistics returned by ambuild
*/ */
...@@ -131,7 +134,8 @@ extern bool index_insert(Relation indexRelation, ...@@ -131,7 +134,8 @@ extern bool index_insert(Relation indexRelation,
Datum *values, bool *isnull, Datum *values, bool *isnull,
ItemPointer heap_t_ctid, ItemPointer heap_t_ctid,
Relation heapRelation, Relation heapRelation,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern IndexScanDesc index_beginscan(Relation heapRelation, extern IndexScanDesc index_beginscan(Relation heapRelation,
Relation indexRelation, Relation indexRelation,
......
...@@ -617,7 +617,8 @@ extern IndexBuildResult *ginbuild(Relation heap, Relation index, ...@@ -617,7 +617,8 @@ extern IndexBuildResult *ginbuild(Relation heap, Relation index,
extern void ginbuildempty(Relation index); extern void ginbuildempty(Relation index);
extern bool gininsert(Relation index, Datum *values, bool *isnull, extern bool gininsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern void ginEntryInsert(GinState *ginstate, extern void ginEntryInsert(GinState *ginstate,
OffsetNumber attnum, Datum key, GinNullCategory category, OffsetNumber attnum, Datum key, GinNullCategory category,
ItemPointerData *items, uint32 nitem, ItemPointerData *items, uint32 nitem,
......
...@@ -426,7 +426,8 @@ typedef struct GiSTOptions ...@@ -426,7 +426,8 @@ typedef struct GiSTOptions
extern void gistbuildempty(Relation index); extern void gistbuildempty(Relation index);
extern bool gistinsert(Relation r, Datum *values, bool *isnull, extern bool gistinsert(Relation r, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern MemoryContext createTempGistContext(void); extern MemoryContext createTempGistContext(void);
extern GISTSTATE *initGISTstate(Relation index); extern GISTSTATE *initGISTstate(Relation index);
extern void freeGISTstate(GISTSTATE *giststate); extern void freeGISTstate(GISTSTATE *giststate);
......
...@@ -277,7 +277,8 @@ extern IndexBuildResult *hashbuild(Relation heap, Relation index, ...@@ -277,7 +277,8 @@ extern IndexBuildResult *hashbuild(Relation heap, Relation index,
extern void hashbuildempty(Relation index); extern void hashbuildempty(Relation index);
extern bool hashinsert(Relation rel, Datum *values, bool *isnull, extern bool hashinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern bool hashgettuple(IndexScanDesc scan, ScanDirection dir); extern bool hashgettuple(IndexScanDesc scan, ScanDirection dir);
extern int64 hashgetbitmap(IndexScanDesc scan, TIDBitmap *tbm); extern int64 hashgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
extern IndexScanDesc hashbeginscan(Relation rel, int nkeys, int norderbys); extern IndexScanDesc hashbeginscan(Relation rel, int nkeys, int norderbys);
......
...@@ -659,7 +659,8 @@ extern IndexBuildResult *btbuild(Relation heap, Relation index, ...@@ -659,7 +659,8 @@ extern IndexBuildResult *btbuild(Relation heap, Relation index,
extern void btbuildempty(Relation index); extern void btbuildempty(Relation index);
extern bool btinsert(Relation rel, Datum *values, bool *isnull, extern bool btinsert(Relation rel, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
extern IndexScanDesc btbeginscan(Relation rel, int nkeys, int norderbys); extern IndexScanDesc btbeginscan(Relation rel, int nkeys, int norderbys);
extern bool btgettuple(IndexScanDesc scan, ScanDirection dir); extern bool btgettuple(IndexScanDesc scan, ScanDirection dir);
extern int64 btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm); extern int64 btgetbitmap(IndexScanDesc scan, TIDBitmap *tbm);
......
...@@ -191,7 +191,8 @@ extern IndexBuildResult *spgbuild(Relation heap, Relation index, ...@@ -191,7 +191,8 @@ extern IndexBuildResult *spgbuild(Relation heap, Relation index,
extern void spgbuildempty(Relation index); extern void spgbuildempty(Relation index);
extern bool spginsert(Relation index, Datum *values, bool *isnull, extern bool spginsert(Relation index, Datum *values, bool *isnull,
ItemPointer ht_ctid, Relation heapRel, ItemPointer ht_ctid, Relation heapRel,
IndexUniqueCheck checkUnique); IndexUniqueCheck checkUnique,
struct IndexInfo *indexInfo);
/* spgscan.c */ /* spgscan.c */
extern IndexScanDesc spgbeginscan(Relation rel, int keysz, int orderbysz); extern IndexScanDesc spgbeginscan(Relation rel, int keysz, int orderbysz);
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
* ReadyForInserts is it valid for inserts? * ReadyForInserts is it valid for inserts?
* Concurrent are we doing a concurrent index build? * Concurrent are we doing a concurrent index build?
* BrokenHotChain did we detect any broken HOT chains? * 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; * ii_Concurrent and ii_BrokenHotChain are used only during index build;
* they're conventionally set to false otherwise. * they're conventionally set to false otherwise.
...@@ -76,6 +78,8 @@ typedef struct IndexInfo ...@@ -76,6 +78,8 @@ typedef struct IndexInfo
bool ii_ReadyForInserts; bool ii_ReadyForInserts;
bool ii_Concurrent; bool ii_Concurrent;
bool ii_BrokenHotChain; bool ii_BrokenHotChain;
void *ii_AmCache;
MemoryContext ii_Context;
} IndexInfo; } IndexInfo;
/* ---------------- /* ----------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment