aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gist/gistget.c29
-rw-r--r--src/backend/access/gist/gistscan.c6
-rw-r--r--src/backend/executor/nodeIndexscan.c6
-rw-r--r--src/include/access/relscan.h7
4 files changed, 33 insertions, 15 deletions
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index 09fba06f73e..20f695cee4e 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -191,20 +191,18 @@ gistindex_keytest(IndexScanDesc scan,
/*
* Call the Distance function to evaluate the distance. The
* arguments are the index datum (as a GISTENTRY*), the comparison
- * datum, and the ordering operator's strategy number and subtype
- * from pg_amop.
+ * datum, the ordering operator's strategy number and subtype from
+ * pg_amop, and the recheck flag.
*
* (Presently there's no need to pass the subtype since it'll
* always be zero, but might as well pass it for possible future
* use.)
*
- * Distance functions get a recheck argument as well. In this
- * case the returned distance is the lower bound of distance and
- * needs to be rechecked. We return single recheck flag which
- * means that both quals and distances are to be rechecked. We
- * initialize the flag to 'false'. The flag was added in version
- * 9.5 and the distance operators written before that won't know
- * about the flag, and are never lossy.
+ * If the function sets the recheck flag, the returned distance is
+ * a lower bound on the true distance and needs to be rechecked.
+ * We initialize the flag to 'false'. This flag was added in
+ * version 9.5; distance functions written before that won't know
+ * about the flag, but are expected to never be lossy.
*/
recheck = false;
dist = FunctionCall5Coll(&key->sk_func,
@@ -475,11 +473,22 @@ getNextNearest(IndexScanDesc scan)
{
if (so->orderByTypes[i] == FLOAT8OID)
{
+#ifndef USE_FLOAT8_BYVAL
+ /* must free any old value to avoid memory leakage */
+ if (!scan->xs_orderbynulls[i])
+ pfree(DatumGetPointer(scan->xs_orderbyvals[i]));
+#endif
scan->xs_orderbyvals[i] = Float8GetDatum(item->distances[i]);
scan->xs_orderbynulls[i] = false;
}
else if (so->orderByTypes[i] == FLOAT4OID)
{
+ /* convert distance function's result to ORDER BY type */
+#ifndef USE_FLOAT4_BYVAL
+ /* must free any old value to avoid memory leakage */
+ if (!scan->xs_orderbynulls[i])
+ pfree(DatumGetPointer(scan->xs_orderbyvals[i]));
+#endif
scan->xs_orderbyvals[i] = Float4GetDatum((float4) item->distances[i]);
scan->xs_orderbynulls[i] = false;
}
@@ -491,7 +500,7 @@ getNextNearest(IndexScanDesc scan)
* calculated by the distance function to that. The
* executor won't actually need the order by values we
* return here, if there are no lossy results, so only
- * insist on the datatype if the *recheck is set.
+ * insist on converting if the *recheck flag is set.
*/
if (scan->xs_recheckorderby)
elog(ERROR, "GiST operator family's FOR ORDER BY operator must return float8 or float4 if the distance function is lossy");
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index d0fea2b86ce..beb402357c0 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -88,8 +88,9 @@ gistbeginscan(PG_FUNCTION_ARGS)
so->qual_ok = true; /* in case there are zero keys */
if (scan->numberOfOrderBys > 0)
{
- scan->xs_orderbyvals = palloc(sizeof(Datum) * scan->numberOfOrderBys);
+ scan->xs_orderbyvals = palloc0(sizeof(Datum) * scan->numberOfOrderBys);
scan->xs_orderbynulls = palloc(sizeof(bool) * scan->numberOfOrderBys);
+ memset(scan->xs_orderbynulls, true, sizeof(bool) * scan->numberOfOrderBys);
}
scan->opaque = so;
@@ -284,6 +285,8 @@ gistrescan(PG_FUNCTION_ARGS)
GIST_DISTANCE_PROC, skey->sk_attno,
RelationGetRelationName(scan->indexRelation));
+ fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
+
/*
* Look up the datatype returned by the original ordering operator.
* GiST always uses a float8 for the distance function, but the
@@ -297,7 +300,6 @@ gistrescan(PG_FUNCTION_ARGS)
* first time.
*/
so->orderByTypes[i] = get_func_rettype(skey->sk_func.fn_oid);
- fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
/* Restore prior fn_extra pointers, if not first time */
if (!first_time)
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index d79c1aa8ca9..79133e08b66 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -459,10 +459,16 @@ reorderqueue_pop(IndexScanState *node)
{
HeapTuple result;
ReorderTuple *topmost;
+ int i;
topmost = (ReorderTuple *) pairingheap_remove_first(node->iss_ReorderQueue);
result = topmost->htup;
+ for (i = 0; i < node->iss_NumOrderByKeys; i++)
+ {
+ if (!node->iss_OrderByTypByVals[i] && !topmost->orderbynulls[i])
+ pfree(DatumGetPointer(topmost->orderbyvals[i]));
+ }
pfree(topmost->orderbyvals);
pfree(topmost->orderbynulls);
pfree(topmost);
diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h
index 1b9b2993957..29f5b35b326 100644
--- a/src/include/access/relscan.h
+++ b/src/include/access/relscan.h
@@ -95,12 +95,13 @@ typedef struct IndexScanDescData
/*
* When fetching with an ordering operator, the values of the ORDER BY
* expressions of the last returned tuple, according to the index. If
- * xs_recheck is true, these need to be rechecked just like the scan keys,
- * and the values returned here are a lower-bound on the actual values.
+ * xs_recheckorderby is true, these need to be rechecked just like the
+ * scan keys, and the values returned here are a lower-bound on the actual
+ * values.
*/
Datum *xs_orderbyvals;
bool *xs_orderbynulls;
- bool xs_recheckorderby; /* T means ORDER BY exprs must be rechecked */
+ bool xs_recheckorderby;
/* state data for traversing HOT chains in index_getnext */
bool xs_continue_hot; /* T if must keep walking HOT chain */