diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml index 56827e5..d558b8e 100644 --- a/doc/src/sgml/spgist.sgml +++ b/doc/src/sgml/spgist.sgml @@ -542,6 +542,8 @@ typedef struct spgInnerConsistentIn int nkeys; /* length of array */ Datum reconstructedValue; /* value reconstructed at parent */ + void *traversalValue; /* opclass-specific traverse value */ + MemoryContext traversalMemoryContext; int level; /* current level (counting from zero) */ bool returnData; /* original data must be returned? */ @@ -559,6 +561,8 @@ typedef struct spgInnerConsistentOut int *nodeNumbers; /* their indexes in the node array */ int *levelAdds; /* increment level by this much for each */ Datum *reconstructedValues; /* associated reconstructed values */ + void **traversalValues; /* opclass-specific traverse values */ + } spgInnerConsistentOut; @@ -593,6 +597,9 @@ typedef struct spgInnerConsistentOut inner tuple, and nodeLabels is an array of their label values, or NULL if the nodes do not have labels. + traversalValue is a pointer to data that + inner_consistent gets when called on child nodes from an + outer call of inner_consistent on parent nodes. @@ -612,6 +619,15 @@ typedef struct spgInnerConsistentOut responsible for palloc'ing the nodeNumbers, levelAdds and reconstructedValues arrays. + Sometimes accumulating some information is needed, while + descending from parent to child node was happened. In this case + + traversalValues array keeps pointers to + specific data you need to accumulate for every child node. + Memory for traversalValues should be allocated in + the default context, but make sure to switch to + traversalMemoryContext before allocating memory + for pointers themselves. @@ -638,6 +654,7 @@ typedef struct spgLeafConsistentIn ScanKey scankeys; /* array of operators and comparison values */ int nkeys; /* length of array */ + void *traversalValue; /* opclass-specific traverse value */ Datum reconstructedValue; /* value reconstructed at parent */ int level; /* current level (counting from zero) */ bool returnData; /* original data must be returned? */ diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c index 8a0d909..bec6daf 100644 --- a/src/backend/access/spgist/spgscan.c +++ b/src/backend/access/spgist/spgscan.c @@ -30,6 +30,7 @@ typedef void (*storeRes_func) (SpGistScanOpaque so, ItemPointer heapPtr, typedef struct ScanStackEntry { Datum reconstructedValue; /* value reconstructed from parent */ + void *traversalValue; /* opclass-specific traverse value */ int level; /* level of items on this page */ ItemPointerData ptr; /* block and offset to scan from */ } ScanStackEntry; @@ -42,6 +43,9 @@ freeScanStackEntry(SpGistScanOpaque so, ScanStackEntry *stackEntry) if (!so->state.attType.attbyval && DatumGetPointer(stackEntry->reconstructedValue) != NULL) pfree(DatumGetPointer(stackEntry->reconstructedValue)); + if (stackEntry->traversalValue) + pfree(stackEntry->traversalValue); + pfree(stackEntry); } @@ -263,6 +267,7 @@ static bool spgLeafTest(Relation index, SpGistScanOpaque so, SpGistLeafTuple leafTuple, bool isnull, int level, Datum reconstructedValue, + void *traversalValue, Datum *leafValue, bool *recheck) { bool result; @@ -289,6 +294,7 @@ spgLeafTest(Relation index, SpGistScanOpaque so, in.scankeys = so->keyData; in.nkeys = so->numberOfKeys; in.reconstructedValue = reconstructedValue; + in.traversalValue = traversalValue; in.level = level; in.returnData = so->want_itup; in.leafDatum = leafDatum; @@ -389,6 +395,7 @@ redirect: leafTuple, isnull, stackEntry->level, stackEntry->reconstructedValue, + stackEntry->traversalValue, &leafValue, &recheck)) { @@ -435,6 +442,7 @@ redirect: leafTuple, isnull, stackEntry->level, stackEntry->reconstructedValue, + stackEntry->traversalValue, &leafValue, &recheck)) { @@ -480,6 +488,8 @@ redirect: in.scankeys = so->keyData; in.nkeys = so->numberOfKeys; in.reconstructedValue = stackEntry->reconstructedValue; + in.traversalMemoryContext = oldCtx; + in.traversalValue = stackEntry->traversalValue; in.level = stackEntry->level; in.returnData = so->want_itup; in.allTheSame = innerTuple->allTheSame; @@ -547,6 +557,9 @@ redirect: else newEntry->reconstructedValue = (Datum) 0; + newEntry->traversalValue = (out.traversalValues) ? + out.traversalValues[i] : NULL; + so->scanStack = lcons(newEntry, so->scanStack); } } diff --git a/src/include/access/spgist.h b/src/include/access/spgist.h index 0cb8fd9..b3bbdf4 100644 --- a/src/include/access/spgist.h +++ b/src/include/access/spgist.h @@ -133,6 +133,8 @@ typedef struct spgInnerConsistentIn int nkeys; /* length of array */ Datum reconstructedValue; /* value reconstructed at parent */ + void *traversalValue; /* opclass-specific traverse value */ + MemoryContext traversalMemoryContext; int level; /* current level (counting from zero) */ bool returnData; /* original data must be returned? */ @@ -150,6 +152,7 @@ typedef struct spgInnerConsistentOut int *nodeNumbers; /* their indexes in the node array */ int *levelAdds; /* increment level by this much for each */ Datum *reconstructedValues; /* associated reconstructed values */ + void **traversalValues; /* opclass-specific traverse values */ } spgInnerConsistentOut; /* @@ -160,6 +163,7 @@ typedef struct spgLeafConsistentIn ScanKey scankeys; /* array of operators and comparison values */ int nkeys; /* length of array */ + void *traversalValue; /* opclass-specific traverse value */ Datum reconstructedValue; /* value reconstructed at parent */ int level; /* current level (counting from zero) */ bool returnData; /* original data must be returned? */