* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.52.2.1 2002/03/25 07:41:21 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.52.2.2 2005/06/20 20:45:12 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
*/
var = (PLpgSQL_var *) target;
- if (var->freeval)
- {
- pfree((void *) (var->value));
- var->freeval = false;
- }
-
newvalue = exec_cast_value(value, valtype, var->datatype->typoid,
&(var->datatype->typinput),
var->datatype->typelem,
if (!var->datatype->typbyval && !*isNull)
{
if (newvalue == value)
- {
- int len;
+ newvalue = datumCopy(newvalue,
+ false,
+ var->datatype->typlen);
+ }
- if (var->datatype->typlen < 0)
- len = VARSIZE(newvalue);
- else
- len = var->datatype->typlen;
- var->value = (Datum) palloc(len);
- memcpy((void *) (var->value), (void *) newvalue, len);
- }
- else
- var->value = newvalue;
- var->freeval = true;
+ /*
+ * Now free the old value. (We can't do this any earlier
+ * because of the possibility that we are assigning the
+ * var's old value to it, eg "foo := foo". We could optimize
+ * out the assignment altogether in such cases, but it's too
+ * infrequent to be worth testing for.)
+ */
+ if (var->freeval)
+ {
+ pfree(DatumGetPointer(var->value));
+ var->freeval = false;
}
- else
- var->value = newvalue;
+
+ var->value = newvalue;
var->isnull = *isNull;
+ if (!var->datatype->typbyval && !*isNull)
+ var->freeval = true;
break;
case PLPGSQL_DTYPE_RECFIELD:
*/
if (rec != NULL)
{
+ /*
+ * copy input first, just in case it is pointing at variable's value
+ */
+ if (HeapTupleIsValid(tup))
+ tup = heap_copytuple(tup);
+ if (tupdesc)
+ tupdesc = CreateTupleDescCopy(tupdesc);
+
if (rec->freetup)
{
heap_freetuple(rec->tup);
if (HeapTupleIsValid(tup))
{
- rec->tup = heap_copytuple(tup);
- rec->tupdesc = CreateTupleDescCopy(tupdesc);
+ rec->tup = tup;
+ rec->tupdesc = tupdesc;
rec->freetup = true;
rec->freetupdesc = true;
}