*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.133 2009/07/18 19:15:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.134 2009/08/23 18:26:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
{
int j;
+ MemoryContext oldContext;
+
+ /* We want to keep the key values in per-tuple memory */
+ oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
for (j = 0; j < numRuntimeKeys; j++)
{
* econtext->ecxt_per_tuple_memory. We assume that the outer tuple
* will stay put throughout our scan. If this is wrong, we could copy
* the result into our context explicitly, but I think that's not
- * necessary...
+ * necessary.
+ *
+ * It's also entirely possible that the result of the eval is a
+ * toasted value. In this case we should forcibly detoast it,
+ * to avoid repeat detoastings each time the value is examined
+ * by an index support function.
*/
- scanvalue = ExecEvalExprSwitchContext(key_expr,
- econtext,
- &isNull,
- NULL);
- scan_key->sk_argument = scanvalue;
+ scanvalue = ExecEvalExpr(key_expr,
+ econtext,
+ &isNull,
+ NULL);
if (isNull)
+ {
+ scan_key->sk_argument = scanvalue;
scan_key->sk_flags |= SK_ISNULL;
+ }
else
+ {
+ if (runtimeKeys[j].key_toastable)
+ scanvalue = PointerGetDatum(PG_DETOAST_DATUM(scanvalue));
+ scan_key->sk_argument = scanvalue;
scan_key->sk_flags &= ~SK_ISNULL;
+ }
}
+
+ MemoryContextSwitchTo(oldContext);
}
/*
runtime_keys[n_runtime_keys].scan_key = this_scan_key;
runtime_keys[n_runtime_keys].key_expr =
ExecInitExpr(rightop, planstate);
+ runtime_keys[n_runtime_keys].key_toastable =
+ TypeIsToastable(op_righttype);
n_runtime_keys++;
scanvalue = (Datum) 0;
}
varattno = ((Var *) leftop)->varattno;
/*
+ * We have to look up the operator's associated btree support
+ * function
+ */
+ opno = lfirst_oid(opnos_cell);
+ opnos_cell = lnext(opnos_cell);
+
+ if (index->rd_rel->relam != BTREE_AM_OID ||
+ varattno < 1 || varattno > index->rd_index->indnatts)
+ elog(ERROR, "bogus RowCompare index qualification");
+ opfamily = index->rd_opfamily[varattno - 1];
+
+ get_op_opfamily_properties(opno, opfamily,
+ &op_strategy,
+ &op_lefttype,
+ &op_righttype);
+
+ if (op_strategy != rc->rctype)
+ elog(ERROR, "RowCompare index qualification contains wrong operator");
+
+ opfuncid = get_opfamily_proc(opfamily,
+ op_lefttype,
+ op_righttype,
+ BTORDER_PROC);
+
+ /*
* rightop is the constant or variable comparison value
*/
rightop = (Expr *) lfirst(rargs_cell);
runtime_keys[n_runtime_keys].scan_key = this_sub_key;
runtime_keys[n_runtime_keys].key_expr =
ExecInitExpr(rightop, planstate);
+ runtime_keys[n_runtime_keys].key_toastable =
+ TypeIsToastable(op_righttype);
n_runtime_keys++;
scanvalue = (Datum) 0;
}
/*
- * We have to look up the operator's associated btree support
- * function
- */
- opno = lfirst_oid(opnos_cell);
- opnos_cell = lnext(opnos_cell);
-
- if (index->rd_rel->relam != BTREE_AM_OID ||
- varattno < 1 || varattno > index->rd_index->indnatts)
- elog(ERROR, "bogus RowCompare index qualification");
- opfamily = index->rd_opfamily[varattno - 1];
-
- get_op_opfamily_properties(opno, opfamily,
- &op_strategy,
- &op_lefttype,
- &op_righttype);
-
- if (op_strategy != rc->rctype)
- elog(ERROR, "RowCompare index qualification contains wrong operator");
-
- opfuncid = get_opfamily_proc(opfamily,
- op_lefttype,
- op_righttype,
- BTORDER_PROC);
-
- /*
* initialize the subsidiary scan key's fields appropriately
*/
ScanKeyEntryInitialize(this_sub_key,