aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gistscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist/gistscan.c')
-rw-r--r--src/backend/access/gist/gistscan.c51
1 files changed, 29 insertions, 22 deletions
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 26c8cff5a01..b5553ffe69b 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -202,6 +202,8 @@ gistrescan(PG_FUNCTION_ARGS)
/* Update scan key, if a new one is given */
if (key && scan->numberOfKeys > 0)
{
+ void **fn_extras = NULL;
+
/*
* If this isn't the first time through, preserve the fn_extra
* pointers, so that if the consistentFns are using them to cache
@@ -209,13 +211,9 @@ gistrescan(PG_FUNCTION_ARGS)
*/
if (!first_time)
{
+ fn_extras = (void **) palloc(scan->numberOfKeys * sizeof(void *));
for (i = 0; i < scan->numberOfKeys; i++)
- {
- ScanKey skey = scan->keyData + i;
-
- so->giststate->consistentFn[skey->sk_attno - 1].fn_extra =
- skey->sk_func.fn_extra;
- }
+ fn_extras[i] = scan->keyData[i].sk_func.fn_extra;
}
memmove(scan->keyData, key,
@@ -231,10 +229,6 @@ gistrescan(PG_FUNCTION_ARGS)
* Next, if any of keys is a NULL and that key is not marked with
* SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
* assume all indexable operators are strict).
- *
- * Note: we intentionally memcpy the FmgrInfo to sk_func rather than
- * using fmgr_info_copy. This is so that the fn_extra field gets
- * preserved across multiple rescans.
*/
so->qual_ok = true;
@@ -242,7 +236,13 @@ gistrescan(PG_FUNCTION_ARGS)
{
ScanKey skey = scan->keyData + i;
- skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1];
+ fmgr_info_copy(&(skey->sk_func),
+ &(so->giststate->consistentFn[skey->sk_attno - 1]),
+ so->giststate->scanCxt);
+
+ /* Restore prior fn_extra pointers, if not first time */
+ if (!first_time)
+ skey->sk_func.fn_extra = fn_extras[i];
if (skey->sk_flags & SK_ISNULL)
{
@@ -250,21 +250,22 @@ gistrescan(PG_FUNCTION_ARGS)
so->qual_ok = false;
}
}
+
+ if (!first_time)
+ pfree(fn_extras);
}
/* Update order-by key, if a new one is given */
if (orderbys && scan->numberOfOrderBys > 0)
{
+ void **fn_extras = NULL;
+
/* As above, preserve fn_extra if not first time through */
if (!first_time)
{
+ fn_extras = (void **) palloc(scan->numberOfOrderBys * sizeof(void *));
for (i = 0; i < scan->numberOfOrderBys; i++)
- {
- ScanKey skey = scan->orderByData + i;
-
- so->giststate->distanceFn[skey->sk_attno - 1].fn_extra =
- skey->sk_func.fn_extra;
- }
+ fn_extras[i] = scan->orderByData[i].sk_func.fn_extra;
}
memmove(scan->orderByData, orderbys,
@@ -276,21 +277,27 @@ gistrescan(PG_FUNCTION_ARGS)
* function in the form of its strategy number, which is available
* from the sk_strategy field, and its subtype from the sk_subtype
* field.
- *
- * See above comment about why we don't use fmgr_info_copy here.
*/
for (i = 0; i < scan->numberOfOrderBys; i++)
{
ScanKey skey = scan->orderByData + i;
-
- skey->sk_func = so->giststate->distanceFn[skey->sk_attno - 1];
+ FmgrInfo *finfo = &(so->giststate->distanceFn[skey->sk_attno - 1]);
/* Check we actually have a distance function ... */
- if (!OidIsValid(skey->sk_func.fn_oid))
+ if (!OidIsValid(finfo->fn_oid))
elog(ERROR, "missing support function %d for attribute %d of index \"%s\"",
GIST_DISTANCE_PROC, skey->sk_attno,
RelationGetRelationName(scan->indexRelation));
+
+ fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
+
+ /* Restore prior fn_extra pointers, if not first time */
+ if (!first_time)
+ skey->sk_func.fn_extra = fn_extras[i];
}
+
+ if (!first_time)
+ pfree(fn_extras);
}
PG_RETURN_VOID();