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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers