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
This commit is contained in:
Teodor Sigaev 2016-03-30 18:29:28 +03:00
parent 3063e7a840
commit ccd6eb49a4
3 changed files with 37 additions and 0 deletions

View File

@ -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;
</programlisting>
@ -593,6 +597,9 @@ typedef struct spgInnerConsistentOut
inner tuple, and
<structfield>nodeLabels</> is an array of their label values, or
NULL if the nodes do not have labels.
<structfield>traversalValue</> is a pointer to data that
<function>inner_consistent</> gets when called on child nodes from an
outer call of <function>inner_consistent</> on parent nodes.
</para>
<para>
@ -612,6 +619,13 @@ typedef struct spgInnerConsistentOut
responsible for palloc'ing the
<structfield>nodeNumbers</>, <structfield>levelAdds</> and
<structfield>reconstructedValues</> arrays.
Sometimes accumulating some information is needed, while
descending from parent to child node was happened. In this case
<structfield>traversalValues</> array keeps pointers to
specific data you need to accumulate for every child node.
Memory for <structfield>traversalValues</> should be allocated in
the default context, but each element of it should be allocated in
<structfield>traversalMemoryContext</>.
</para>
</listitem>
</varlistentry>
@ -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? */

View File

@ -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);
}
}

View File

@ -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? */