From ccd6eb49a4ae924290ab7eba5540218f5beb48b8 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Wed, 30 Mar 2016 18:29:28 +0300 Subject: [PATCH] Introduce traversalValue for SP-GiST scan During scan sometimes it would be very helpful to know some information about parent node or all ancestor nodes. Right now reconstructedValue could be used but it's not a right usage of it (range opclass uses that). traversalValue is arbitrary piece of memory in separate MemoryContext while reconstructedVale should have the same type as indexed column. Subsequent patches for range opclass and quad4d tree will use it. Author: Alexander Lebedev, Teodor Sigaev --- doc/src/sgml/spgist.sgml | 15 +++++++++++++++ src/backend/access/spgist/spgscan.c | 18 ++++++++++++++++++ src/include/access/spgist.h | 4 ++++ 3 files changed, 37 insertions(+) diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml index 56827e520d..0d44d064aa 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,13 @@ 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 each element of it should be allocated in + traversalMemoryContext. @@ -638,6 +652,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 620e746199..8aa28ecbc3 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); } @@ -239,6 +243,7 @@ static bool spgLeafTest(Relation index, SpGistScanOpaque so, SpGistLeafTuple leafTuple, bool isnull, int level, Datum reconstructedValue, + void *traversalValue, Datum *leafValue, bool *recheck) { bool result; @@ -265,6 +270,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; @@ -365,6 +371,7 @@ redirect: leafTuple, isnull, stackEntry->level, stackEntry->reconstructedValue, + stackEntry->traversalValue, &leafValue, &recheck)) { @@ -411,6 +418,7 @@ redirect: leafTuple, isnull, stackEntry->level, stackEntry->reconstructedValue, + stackEntry->traversalValue, &leafValue, &recheck)) { @@ -456,6 +464,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; @@ -523,6 +533,14 @@ redirect: else newEntry->reconstructedValue = (Datum) 0; + /* + * Elements of out.traversalValues should be allocated in + * in.traversalMemoryContext, which is actually a long + * lived context of index scan. + */ + 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 1994f718eb..f39a2d6938 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? */