8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.262 2010/08/09 02:25:05 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.263 2010/08/09 18:50:10 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -1099,6 +1099,9 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
1099
1099
*/
1100
1100
SPI_restore_connection ();
1101
1101
1102
+ /* Must clean up the econtext too */
1103
+ exec_eval_cleanup (estate );
1104
+
1102
1105
/* Look for a matching exception handler */
1103
1106
foreach (e , block -> exceptions -> exc_list )
1104
1107
{
@@ -2701,6 +2704,9 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
2701
2704
*
2702
2705
* NB: the result of the evaluation is no longer valid after this is done,
2703
2706
* unless it is a pass-by-value datatype.
2707
+ *
2708
+ * NB: if you change this code, see also the hacks in exec_assign_value's
2709
+ * PLPGSQL_DTYPE_ARRAYELEM case.
2704
2710
* ----------
2705
2711
*/
2706
2712
static void
@@ -3464,6 +3470,10 @@ exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
3464
3470
3465
3471
/* ----------
3466
3472
* exec_assign_value Put a value into a target field
3473
+ *
3474
+ * Note: in some code paths, this may leak memory in the eval_econtext;
3475
+ * we assume that will be cleaned up later by exec_eval_cleanup. We cannot
3476
+ * call exec_eval_cleanup here for fear of destroying the input Datum value.
3467
3477
* ----------
3468
3478
*/
3469
3479
static void
@@ -3714,6 +3724,9 @@ exec_assign_value(PLpgSQL_execstate *estate,
3714
3724
3715
3725
case PLPGSQL_DTYPE_ARRAYELEM :
3716
3726
{
3727
+ /*
3728
+ * Target is an element of an array
3729
+ */
3717
3730
int nsubscripts ;
3718
3731
int i ;
3719
3732
PLpgSQL_expr * subscripts [MAXDIM ];
@@ -3729,10 +3742,19 @@ exec_assign_value(PLpgSQL_execstate *estate,
3729
3742
coerced_value ;
3730
3743
ArrayType * oldarrayval ;
3731
3744
ArrayType * newarrayval ;
3745
+ SPITupleTable * save_eval_tuptable ;
3746
+
3747
+ /*
3748
+ * We need to do subscript evaluation, which might require
3749
+ * evaluating general expressions; and the caller might have
3750
+ * done that too in order to prepare the input Datum. We
3751
+ * have to save and restore the caller's SPI_execute result,
3752
+ * if any.
3753
+ */
3754
+ save_eval_tuptable = estate -> eval_tuptable ;
3755
+ estate -> eval_tuptable = NULL ;
3732
3756
3733
3757
/*
3734
- * Target is an element of an array
3735
- *
3736
3758
* To handle constructs like x[1][2] := something, we have to
3737
3759
* be prepared to deal with a chain of arrayelem datums. Chase
3738
3760
* back to find the base array datum, and save the subscript
@@ -3786,8 +3808,23 @@ exec_assign_value(PLpgSQL_execstate *estate,
3786
3808
ereport (ERROR ,
3787
3809
(errcode (ERRCODE_NULL_VALUE_NOT_ALLOWED ),
3788
3810
errmsg ("array subscript in assignment must not be null" )));
3811
+
3812
+ /*
3813
+ * Clean up in case the subscript expression wasn't simple.
3814
+ * We can't do exec_eval_cleanup, but we can do this much
3815
+ * (which is safe because the integer subscript value is
3816
+ * surely pass-by-value), and we must do it in case the
3817
+ * next subscript expression isn't simple either.
3818
+ */
3819
+ if (estate -> eval_tuptable != NULL )
3820
+ SPI_freetuptable (estate -> eval_tuptable );
3821
+ estate -> eval_tuptable = NULL ;
3789
3822
}
3790
3823
3824
+ /* Now we can restore caller's SPI_execute result if any. */
3825
+ Assert (estate -> eval_tuptable == NULL );
3826
+ estate -> eval_tuptable = save_eval_tuptable ;
3827
+
3791
3828
/* Coerce source value to match array element type. */
3792
3829
coerced_value = exec_simple_cast_value (value ,
3793
3830
valtype ,
0 commit comments