*** ./src/pl/plpgsql/src/pl_exec.c.orig	2011-01-16 14:18:59.000000000 +0100
--- ./src/pl/plpgsql/src/pl_exec.c	2011-01-16 18:45:59.659254108 +0100
***************
*** 255,260 ****
--- 255,264 ----
  					var->value = fcinfo->arg[i];
  					var->isnull = fcinfo->argnull[i];
  					var->freeval = false;
+ 
+ 					/* only varlena types should be detoasted */
+ 					var->should_be_detoasted = !var->isnull && !var->datatype->typbyval
+ 											&& var->datatype->typlen == -1;
  				}
  				break;
  
***************
*** 570,581 ****
--- 574,587 ----
  		elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, UPDATE, or TRUNCATE");
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_name_varno]);
  	var->value = DirectFunctionCall1(namein,
  							  CStringGetDatum(trigdata->tg_trigger->tgname));
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
  	if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
***************
*** 588,593 ****
--- 594,600 ----
  		elog(ERROR, "unrecognized trigger execution time: not BEFORE, AFTER, or INSTEAD OF");
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_level_varno]);
  	if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
***************
*** 598,620 ****
--- 605,631 ----
  		elog(ERROR, "unrecognized trigger event type: not ROW or STATEMENT");
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_relid_varno]);
  	var->value = ObjectIdGetDatum(trigdata->tg_relation->rd_id);
  	var->isnull = false;
  	var->freeval = false;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_relname_varno]);
  	var->value = DirectFunctionCall1(namein,
  			CStringGetDatum(RelationGetRelationName(trigdata->tg_relation)));
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_table_name_varno]);
  	var->value = DirectFunctionCall1(namein,
  			CStringGetDatum(RelationGetRelationName(trigdata->tg_relation)));
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_table_schema_varno]);
  	var->value = DirectFunctionCall1(namein,
***************
*** 624,634 ****
--- 635,647 ----
  												   trigdata->tg_relation))));
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]);
  	var->value = Int16GetDatum(trigdata->tg_trigger->tgnargs);
  	var->isnull = false;
  	var->freeval = false;
+ 	var->should_be_detoasted = false;
  
  	var = (PLpgSQL_var *) (estate.datums[func->tg_argv_varno]);
  	if (trigdata->tg_trigger->tgnargs > 0)
***************
*** 654,665 ****
--- 667,680 ----
  														-1, false, 'i'));
  		var->isnull = false;
  		var->freeval = true;
+ 		var->should_be_detoasted = false;
  	}
  	else
  	{
  		var->value = (Datum) 0;
  		var->isnull = true;
  		var->freeval = false;
+ 		var->should_be_detoasted = false;
  	}
  
  	estate.err_text = gettext_noop("during function entry");
***************
*** 841,846 ****
--- 856,862 ----
  				new->value = 0;
  				new->isnull = true;
  				new->freeval = false;
+ 				new->should_be_detoasted = false;
  
  				result = (PLpgSQL_datum *) new;
  			}
***************
*** 2652,2657 ****
--- 2668,2683 ----
  	estate->exitlabel = NULL;
  	estate->cur_error = NULL;
  
+ 	/*
+ 	 * Store a execution top memory context. The top context isn't usually
+ 	 * explicitly selected, but there is one exception. We would to detoast
+ 	 * datuns in this context. Varlena datums are explicitly detoasted in 
+ 	 * exec_eval_datum routine. This routine can be called from plpgsql_param_fetch,
+ 	 * what is callback for parser - etc different memory context, and then 
+ 	 * we have to access top execution memory context. 
+ 	 */
+ 	estate->top_exec_cxt = CurrentMemoryContext;
+ 
  	estate->tuple_store = NULL;
  	if (rsi)
  	{
***************
*** 3544,3550 ****
--- 3570,3579 ----
  				var->value = newvalue;
  				var->isnull = *isNull;
  				if (!var->datatype->typbyval && !*isNull)
+ 				{
  					var->freeval = true;
+ 					var->should_be_detoasted = var->datatype->typlen == -1;
+ 				}
  				break;
  			}
  
***************
*** 3944,3949 ****
--- 3973,4007 ----
  
  				*typeid = var->datatype->typoid;
  				*typetypmod = var->datatype->atttypmod;
+ 
+ 				/*
+ 				 * explicit deTOAST and decompress for varlena types
+ 				 */
+ 				if (var->should_be_detoasted)
+ 				{
+ 					Datum dvalue;
+ 
+ 					Assert(!var->isnull);
+ 
+ 					/*
+ 					 * We should to detoast variables in top execution context,
+ 					 * and then is necessary to switch to it (this routine
+ 					 * can be called from parser with different current 
+ 					 * context.
+ 					 */
+ 					oldcontext = MemoryContextSwitchTo(estate->top_exec_cxt);
+ 					dvalue = PointerGetDatum(PG_DETOAST_DATUM(var->value));
+ 					if (dvalue != var->value)
+ 					{
+ 						if (var->freeval)
+ 							free_var(var);
+ 						var->value = dvalue;
+ 						var->freeval = true;
+ 					}
+ 					MemoryContextSwitchTo(oldcontext); 
+ 					var->should_be_detoasted = false;
+ 				}
+ 
  				*value = var->value;
  				*isnull = var->isnull;
  				break;
***************
*** 5552,5557 ****
--- 5610,5616 ----
  	var->value = CStringGetTextDatum(str);
  	var->isnull = false;
  	var->freeval = true;
+ 	var->should_be_detoasted = false;
  }
  
  /*
*** ./src/pl/plpgsql/src/plpgsql.h.orig	2011-01-16 14:18:59.000000000 +0100
--- ./src/pl/plpgsql/src/plpgsql.h	2011-01-16 18:41:54.104294898 +0100
***************
*** 242,247 ****
--- 242,248 ----
  	Datum		value;
  	bool		isnull;
  	bool		freeval;
+ 	bool		should_be_detoasted;
  } PLpgSQL_var;
  
  
***************
*** 643,649 ****
  	ItemPointerData fn_tid;
  	bool		fn_is_trigger;
  	PLpgSQL_func_hashkey *fn_hashkey;	/* back-link to hashtable key */
! 	MemoryContext fn_cxt;
  
  	Oid			fn_rettype;
  	int			fn_rettyplen;
--- 644,650 ----
  	ItemPointerData fn_tid;
  	bool		fn_is_trigger;
  	PLpgSQL_func_hashkey *fn_hashkey;	/* back-link to hashtable key */
! 	MemoryContext fn_cxt;			/* function's persistent context */
  
  	Oid			fn_rettype;
  	int			fn_rettyplen;
***************
*** 692,697 ****
--- 693,700 ----
  	Oid			rettype;		/* type of current retval */
  
  	Oid			fn_rettype;		/* info about declared function rettype */
+ 	MemoryContext	top_exec_cxt;			/* function's top execution memory context */
+ 
  	bool		retistuple;
  	bool		retisset;
  
