aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/spgist.sgml15
-rw-r--r--src/backend/access/spgist/spgscan.c18
-rw-r--r--src/include/access/spgist.h4
3 files changed, 37 insertions, 0 deletions
diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml
index 56827e520dd..0d44d064aaa 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;
</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? */
diff --git a/src/backend/access/spgist/spgscan.c b/src/backend/access/spgist/spgscan.c
index 620e7461998..8aa28ecbc39 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 1994f718eb1..f39a2d6938c 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? */