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
                                 */
                                        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
                                 */