33 * procedural language
44 *
55 * IDENTIFICATION
6- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.144 2005/06/14 06:43:14 neilc Exp $
6+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.145 2005/06/20 20:44:44 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
@@ -182,6 +182,7 @@ static bool compatible_tupdesc(TupleDesc td1, TupleDesc td2);
182182static void exec_set_found (PLpgSQL_execstate * estate ,bool state );
183183static void free_var (PLpgSQL_var * var );
184184
185+
185186/* ----------
186187 * plpgsql_exec_functionCalled by the call handler for
187188 *function execution.
@@ -874,13 +875,15 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
874875PLpgSQL_var * state_var ;
875876PLpgSQL_var * errm_var ;
876877
877- state_var = (PLpgSQL_var * ) (estate -> datums [block -> exceptions -> sqlstate_varno ]);
878+ state_var = (PLpgSQL_var * )
879+ estate -> datums [block -> exceptions -> sqlstate_varno ];
878880state_var -> value = DirectFunctionCall1 (textin ,
879881CStringGetDatum (unpack_sql_state (edata -> sqlerrcode )));
880882state_var -> freeval = true;
881883state_var -> isnull = false;
882884
883- errm_var = (PLpgSQL_var * ) (estate -> datums [block -> exceptions -> sqlerrm_varno ]);
885+ errm_var = (PLpgSQL_var * )
886+ estate -> datums [block -> exceptions -> sqlerrm_varno ];
884887errm_var -> value = DirectFunctionCall1 (textin ,
885888CStringGetDatum (edata -> message ));
886889errm_var -> freeval = true;
@@ -2862,8 +2865,6 @@ exec_assign_value(PLpgSQL_execstate *estate,
28622865errmsg ("NULL cannot be assigned to variable \"%s\" declared NOT NULL" ,
28632866var -> refname )));
28642867
2865- free_var (var );
2866-
28672868/*
28682869 * If type is by-reference, make sure we have a freshly
28692870 * palloc'd copy; the originally passed value may not live
@@ -2874,16 +2875,24 @@ exec_assign_value(PLpgSQL_execstate *estate,
28742875if (!var -> datatype -> typbyval && !* isNull )
28752876{
28762877if (newvalue == value )
2877- var -> value = datumCopy (newvalue ,
2878- false,
2879- var -> datatype -> typlen );
2880- else
2881- var -> value = newvalue ;
2882- var -> freeval = true;
2878+ newvalue = datumCopy (newvalue ,
2879+ false,
2880+ var -> datatype -> typlen );
28832881}
2884- else
2885- var -> value = newvalue ;
2882+
2883+ /*
2884+ * Now free the old value. (We can't do this any earlier
2885+ * because of the possibility that we are assigning the
2886+ * var's old value to it, eg "foo := foo". We could optimize
2887+ * out the assignment altogether in such cases, but it's too
2888+ * infrequent to be worth testing for.)
2889+ */
2890+ free_var (var );
2891+
2892+ var -> value = newvalue ;
28862893var -> isnull = * isNull ;
2894+ if (!var -> datatype -> typbyval && !* isNull )
2895+ var -> freeval = true;
28872896break ;
28882897}
28892898
@@ -3740,6 +3749,14 @@ exec_move_row(PLpgSQL_execstate *estate,
37403749 */
37413750if (rec != NULL )
37423751{
3752+ /*
3753+ * copy input first, just in case it is pointing at variable's value
3754+ */
3755+ if (HeapTupleIsValid (tup ))
3756+ tup = heap_copytuple (tup );
3757+ if (tupdesc )
3758+ tupdesc = CreateTupleDescCopy (tupdesc );
3759+
37433760if (rec -> freetup )
37443761{
37453762heap_freetuple (rec -> tup );
@@ -3753,7 +3770,7 @@ exec_move_row(PLpgSQL_execstate *estate,
37533770
37543771if (HeapTupleIsValid (tup ))
37553772{
3756- rec -> tup = heap_copytuple ( tup ) ;
3773+ rec -> tup = tup ;
37573774rec -> freetup = true;
37583775}
37593776else if (tupdesc )
@@ -3774,7 +3791,7 @@ exec_move_row(PLpgSQL_execstate *estate,
37743791
37753792if (tupdesc )
37763793{
3777- rec -> tupdesc = CreateTupleDescCopy ( tupdesc ) ;
3794+ rec -> tupdesc = tupdesc ;
37783795rec -> freetupdesc = true;
37793796}
37803797else