diff options
Diffstat (limited to 'src/backend/access/gist')
-rw-r--r-- | src/backend/access/gist/gistget.c | 29 | ||||
-rw-r--r-- | src/backend/access/gist/gistscan.c | 6 |
2 files changed, 23 insertions, 12 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) |