|
3 | 3 | * procedural language
|
4 | 4 | *
|
5 | 5 | * IDENTIFICATION
|
6 |
| - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.93.2.4 2010/07/05 09:27:57 heikki Exp $ |
| 6 | + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.93.2.5 2010/08/09 18:51:12 tgl Exp $ |
7 | 7 | *
|
8 | 8 | * This software is copyrighted by Jan Wieck - Hamburg.
|
9 | 9 | *
|
@@ -1919,6 +1919,9 @@ plpgsql_estate_setup(PLpgSQL_execstate * estate,
|
1919 | 1919 | *
|
1920 | 1920 | * NB: the result of the evaluation is no longer valid after this is done,
|
1921 | 1921 | * unless it is a pass-by-value datatype.
|
| 1922 | + * |
| 1923 | + * NB: if you change this code, see also the hacks in exec_assign_value's |
| 1924 | + * PLPGSQL_DTYPE_ARRAYELEM case. |
1922 | 1925 | * ----------
|
1923 | 1926 | */
|
1924 | 1927 | static void
|
@@ -2674,6 +2677,10 @@ exec_assign_expr(PLpgSQL_execstate * estate, PLpgSQL_datum * target,
|
2674 | 2677 |
|
2675 | 2678 | /* ----------
|
2676 | 2679 | * exec_assign_value Put a value into a target field
|
| 2680 | + * |
| 2681 | + * Note: in some code paths, this may leak memory in the eval_econtext; |
| 2682 | + * we assume that will be cleaned up later by exec_eval_cleanup. We cannot |
| 2683 | + * call exec_eval_cleanup here for fear of destroying the input Datum value. |
2677 | 2684 | * ----------
|
2678 | 2685 | */
|
2679 | 2686 | static void
|
@@ -2708,6 +2715,7 @@ exec_assign_value(PLpgSQL_execstate * estate,
|
2708 | 2715 | Datum oldarrayval,
|
2709 | 2716 | coerced_value;
|
2710 | 2717 | ArrayType *newarrayval;
|
| 2718 | + SPITupleTable *save_eval_tuptable; |
2711 | 2719 | HeapTuple newtup;
|
2712 | 2720 |
|
2713 | 2721 | switch (target->dtype)
|
@@ -2868,6 +2876,16 @@ exec_assign_value(PLpgSQL_execstate * estate,
|
2868 | 2876 | /*
|
2869 | 2877 | * Target is an element of an array
|
2870 | 2878 | *
|
| 2879 | + * We need to do subscript evaluation, which might require |
| 2880 | + * evaluating general expressions; and the caller might have |
| 2881 | + * done that too in order to prepare the input Datum. We |
| 2882 | + * have to save and restore the caller's SPI_execute result, |
| 2883 | + * if any. |
| 2884 | + */ |
| 2885 | + save_eval_tuptable = estate->eval_tuptable; |
| 2886 | + estate->eval_tuptable = NULL; |
| 2887 | + |
| 2888 | + /* |
2871 | 2889 | * To handle constructs like x[1][2] := something, we have to be
|
2872 | 2890 | * prepared to deal with a chain of arrayelem datums. Chase
|
2873 | 2891 | * back to find the base array datum, and save the subscript
|
@@ -2910,8 +2928,23 @@ exec_assign_value(PLpgSQL_execstate * estate,
|
2910 | 2928 | subscripts[nsubscripts - 1 - i],
|
2911 | 2929 | &subisnull);
|
2912 | 2930 | havenullsubscript |= subisnull;
|
| 2931 | + |
| 2932 | + /* |
| 2933 | + * Clean up in case the subscript expression wasn't simple. |
| 2934 | + * We can't do exec_eval_cleanup, but we can do this much |
| 2935 | + * (which is safe because the integer subscript value is |
| 2936 | + * surely pass-by-value), and we must do it in case the |
| 2937 | + * next subscript expression isn't simple either. |
| 2938 | + */ |
| 2939 | + if (estate->eval_tuptable != NULL) |
| 2940 | + SPI_freetuptable(estate->eval_tuptable); |
| 2941 | + estate->eval_tuptable = NULL; |
2913 | 2942 | }
|
2914 | 2943 |
|
| 2944 | + /* Now we can restore caller's SPI_execute result if any. */ |
| 2945 | + Assert(estate->eval_tuptable == NULL); |
| 2946 | + estate->eval_tuptable = save_eval_tuptable; |
| 2947 | + |
2915 | 2948 | /*
|
2916 | 2949 | * Skip the assignment if we have any nulls, either in the
|
2917 | 2950 | * original array value, the subscripts, or the righthand
|
|
0 commit comments