Index: src/backend/executor/nodeIndexscan.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v retrieving revision 1.133 diff -c -r1.133 nodeIndexscan.c *** src/backend/executor/nodeIndexscan.c 18 Jul 2009 19:15:41 -0000 1.133 --- src/backend/executor/nodeIndexscan.c 15 Aug 2009 04:28:55 -0000 *************** *** 237,244 **** --- 237,247 ---- ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys) { + MemoryContext oldContext; int j; + oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); + for (j = 0; j < numRuntimeKeys; j++) { ScanKey scan_key = runtimeKeys[j].scan_key; *************** *** 256,273 **** * 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... */ ! scanvalue = ExecEvalExprSwitchContext(key_expr, ! econtext, ! &isNull, ! NULL); ! scan_key->sk_argument = scanvalue; if (isNull) scan_key->sk_flags |= SK_ISNULL; else scan_key->sk_flags &= ~SK_ISNULL; } } /* --- 259,290 ---- * 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. ! * ! * 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 = 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); } /* *************** *** 795,800 **** --- 812,819 ---- 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; } *************** *** 844,849 **** --- 863,893 ---- 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); *************** *** 867,902 **** runtime_keys[n_runtime_keys].scan_key = this_sub_key; runtime_keys[n_runtime_keys].key_expr = ExecInitExpr(rightop, planstate); 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, --- 911,923 ---- 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; } /* * initialize the subsidiary scan key's fields appropriately */ ScanKeyEntryInitialize(this_sub_key, Index: src/include/nodes/execnodes.h =================================================================== RCS file: /cvsroot/pgsql/src/include/nodes/execnodes.h,v retrieving revision 1.206 diff -c -r1.206 execnodes.h *** src/include/nodes/execnodes.h 6 Aug 2009 20:44:31 -0000 1.206 --- src/include/nodes/execnodes.h 15 Aug 2009 04:28:55 -0000 *************** *** 1084,1089 **** --- 1084,1090 ---- { ScanKey scan_key; /* scankey to put value into */ ExprState *key_expr; /* expr to evaluate to get value */ + bool key_toastable; /* is expr's result a toastable datatype? */ } IndexRuntimeKeyInfo; typedef struct