1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Still more fixes for lossy-GiST-distance-functions patch.

Fix confusion in documentation, substantial memory leakage if float8 or
float4 are pass-by-reference, and assorted comments that were obsoleted
by commit 98edd617f3.
This commit is contained in:
Tom Lane
2015-05-23 15:22:25 -04:00
parent 284bef2977
commit 821b821a24
5 changed files with 55 additions and 41 deletions

View File

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

View File

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