On Sun, Jan 16, 2011 at 06:49:27PM +0100, Pavel Stehule wrote:
> I am sending a updated version with little bit more comments. But I am
> sure, so somebody with good English have to edit my comments.
> Minimally I hope, so your questions will be answered.

Thanks.  I edited the comments and white space somewhat, as attached.  I'll go
ahead and mark it Ready for Committer.
*** a/src/pl/plpgsql/src/pl_exec.c
--- b/src/pl/plpgsql/src/pl_exec.c
***************
*** 255,260 **** plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo 
fcinfo)
--- 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 **** plpgsql_exec_trigger(PLpgSQL_function *func,
--- 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 **** plpgsql_exec_trigger(PLpgSQL_function *func,
--- 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 **** plpgsql_exec_trigger(PLpgSQL_function *func,
--- 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 **** plpgsql_exec_trigger(PLpgSQL_function *func,
--- 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 **** plpgsql_exec_trigger(PLpgSQL_function *func,
--- 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 **** copy_plpgsql_datum(PLpgSQL_datum *datum)
--- 856,862 ----
                                new->value = 0;
                                new->isnull = true;
                                new->freeval = false;
+                               new->should_be_detoasted = false;
  
                                result = (PLpgSQL_datum *) new;
                        }
***************
*** 2652,2657 **** plpgsql_estate_setup(PLpgSQL_execstate *estate,
--- 2668,2679 ----
        estate->exitlabel = NULL;
        estate->cur_error = NULL;
  
+       /*
+        * Store the top execution memory context.  exec_eval_datum() explicity
+        * detoasts varlena datums in this context.
+        */
+       estate->top_exec_cxt = CurrentMemoryContext;
+ 
        estate->tuple_store = NULL;
        if (rsi)
        {
***************
*** 3544,3550 **** exec_assign_value(PLpgSQL_execstate *estate,
--- 3566,3575 ----
                                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 **** exec_eval_datum(PLpgSQL_execstate *estate,
--- 3969,4002 ----
  
                                *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);
+ 
+                                       /*
+                                        * Detoast variables in the top 
execution context.  The
+                                        * parser can call this routine (via 
plpgsql_param_fetch)
+                                        * with a 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 **** assign_text_var(PLpgSQL_var *var, const char *str)
--- 5605,5611 ----
        var->value = CStringGetTextDatum(str);
        var->isnull = false;
        var->freeval = true;
+       var->should_be_detoasted = false;
  }
  
  /*
*** a/src/pl/plpgsql/src/plpgsql.h
--- b/src/pl/plpgsql/src/plpgsql.h
***************
*** 242,247 **** typedef struct
--- 242,248 ----
        Datum           value;
        bool            isnull;
        bool            freeval;
+       bool            should_be_detoasted;
  } PLpgSQL_var;
  
  
***************
*** 643,649 **** typedef struct PLpgSQL_function
        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 **** typedef struct PLpgSQL_execstate
--- 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;
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to