@@ -2197,10 +2197,6 @@ exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
2197
2197
elog (ERROR , "could not open cursor: %s" ,
2198
2198
SPI_result_code_string (SPI_result ));
2199
2199
2200
- /* don't need paramlist any more */
2201
- if (paramLI )
2202
- pfree (paramLI );
2203
-
2204
2200
/*
2205
2201
* If cursor variable was NULL, store the generated portal name in it
2206
2202
*/
@@ -3169,6 +3165,16 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
3169
3165
estate -> datums = palloc (sizeof (PLpgSQL_datum * ) * estate -> ndatums );
3170
3166
/* caller is expected to fill the datums array */
3171
3167
3168
+ /* initialize ParamListInfo with one entry per datum, all invalid */
3169
+ estate -> paramLI = (ParamListInfo )
3170
+ palloc0 (offsetof(ParamListInfoData , params ) +
3171
+ estate -> ndatums * sizeof (ParamExternData ));
3172
+ estate -> paramLI -> paramFetch = plpgsql_param_fetch ;
3173
+ estate -> paramLI -> paramFetchArg = (void * ) estate ;
3174
+ estate -> paramLI -> parserSetup = (ParserSetupHook ) plpgsql_parser_setup ;
3175
+ estate -> paramLI -> parserSetupArg = NULL ; /* filled during use */
3176
+ estate -> paramLI -> numParams = estate -> ndatums ;
3177
+
3172
3178
/* set up for use of appropriate simple-expression EState */
3173
3179
if (simple_eval_estate )
3174
3180
estate -> simple_eval_estate = simple_eval_estate ;
@@ -3179,7 +3185,6 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
3179
3185
estate -> eval_processed = 0 ;
3180
3186
estate -> eval_lastoid = InvalidOid ;
3181
3187
estate -> eval_econtext = NULL ;
3182
- estate -> cur_expr = NULL ;
3183
3188
3184
3189
estate -> err_stmt = NULL ;
3185
3190
estate -> err_text = NULL ;
@@ -3495,9 +3500,6 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
3495
3500
(rc == SPI_OK_SELECT ) ? errhint ("If you want to discard the results of a SELECT, use PERFORM instead." ) : 0 ));
3496
3501
}
3497
3502
3498
- if (paramLI )
3499
- pfree (paramLI );
3500
-
3501
3503
return PLPGSQL_RC_OK ;
3502
3504
}
3503
3505
@@ -3864,8 +3866,6 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
3864
3866
3865
3867
if (curname )
3866
3868
pfree (curname );
3867
- if (paramLI )
3868
- pfree (paramLI );
3869
3869
3870
3870
return PLPGSQL_RC_OK ;
3871
3871
}
@@ -4050,7 +4050,7 @@ exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
4050
4050
4051
4051
4052
4052
/* ----------
4053
- * exec_assign_value Put a value into a target field
4053
+ * exec_assign_value Put a value into a target datum
4054
4054
*
4055
4055
* Note: in some code paths, this will leak memory in the eval_econtext;
4056
4056
* we assume that will be cleaned up later by exec_eval_cleanup. We cannot
@@ -4909,8 +4909,6 @@ exec_run_select(PLpgSQL_execstate *estate,
4909
4909
if (* portalP == NULL )
4910
4910
elog (ERROR , "could not open implicit cursor for query \"%s\": %s" ,
4911
4911
expr -> query , SPI_result_code_string (SPI_result ));
4912
- if (paramLI )
4913
- pfree (paramLI );
4914
4912
return SPI_OK_CURSOR ;
4915
4913
}
4916
4914
@@ -4930,9 +4928,6 @@ exec_run_select(PLpgSQL_execstate *estate,
4930
4928
estate -> eval_processed = SPI_processed ;
4931
4929
estate -> eval_lastoid = SPI_lastoid ;
4932
4930
4933
- if (paramLI )
4934
- pfree (paramLI );
4935
-
4936
4931
return rc ;
4937
4932
}
4938
4933
@@ -5140,7 +5135,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
5140
5135
LocalTransactionId curlxid = MyProc -> lxid ;
5141
5136
CachedPlan * cplan ;
5142
5137
ParamListInfo paramLI ;
5143
- PLpgSQL_expr * save_cur_expr ;
5138
+ void * save_setup_arg ;
5144
5139
MemoryContext oldcontext ;
5145
5140
5146
5141
/*
@@ -5216,14 +5211,10 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
5216
5211
}
5217
5212
5218
5213
/*
5219
- * Create the param list in econtext's temporary memory context. We won't
5220
- * need to free it explicitly, since it will go away at the next reset of
5221
- * that context.
5222
- *
5223
- * Just for paranoia's sake, save and restore the prior value of
5224
- * estate->cur_expr, which setup_param_list() sets.
5214
+ * Set up param list. For safety, save and restore
5215
+ * estate->paramLI->parserSetupArg around our use of the param list.
5225
5216
*/
5226
- save_cur_expr = estate -> cur_expr ;
5217
+ save_setup_arg = estate -> paramLI -> parserSetupArg ;
5227
5218
5228
5219
paramLI = setup_param_list (estate , expr );
5229
5220
econtext -> ecxt_param_list_info = paramLI ;
@@ -5244,7 +5235,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
5244
5235
/* Assorted cleanup */
5245
5236
expr -> expr_simple_in_use = false;
5246
5237
5247
- estate -> cur_expr = save_cur_expr ;
5238
+ estate -> paramLI -> parserSetupArg = save_setup_arg ;
5248
5239
5249
5240
if (!estate -> readonly_func )
5250
5241
PopActiveSnapshot ();
@@ -5268,6 +5259,15 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
5268
5259
/*
5269
5260
* Create a ParamListInfo to pass to SPI
5270
5261
*
5262
+ * We share a single ParamListInfo array across all SPI calls made from this
5263
+ * estate. This is generally OK since any given slot in the array would
5264
+ * need to contain the same current datum value no matter which query or
5265
+ * expression we're evaluating. However, paramLI->parserSetupArg points to
5266
+ * the specific PLpgSQL_expr being evaluated. This is not an issue for
5267
+ * statement-level callers, but lower-level callers should save and restore
5268
+ * estate->paramLI->parserSetupArg just in case there's an active evaluation
5269
+ * at an outer call level.
5270
+ *
5271
5271
* We fill in the values for any expression parameters that are plain
5272
5272
* PLpgSQL_var datums; these are cheap and safe to evaluate, and by setting
5273
5273
* them with PARAM_FLAG_CONST flags, we allow the planner to use those values
@@ -5277,9 +5277,6 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
5277
5277
* the expression that might never be evaluated at runtime. To handle those
5278
5278
* parameters, we set up a paramFetch hook for the executor to call when it
5279
5279
* wants a not-presupplied value.
5280
- *
5281
- * The result is a locally palloc'd array that should be pfree'd after use;
5282
- * but note it can be NULL.
5283
5280
*/
5284
5281
static ParamListInfo
5285
5282
setup_param_list (PLpgSQL_execstate * estate , PLpgSQL_expr * expr )
@@ -5293,22 +5290,28 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
5293
5290
Assert (expr -> plan != NULL );
5294
5291
5295
5292
/*
5296
- * Could we re-use these arrays instead of palloc'ing a new one each time?
5297
- * However, we'd have to re-fill the array each time anyway, since new
5298
- * values might have been assigned to the variables.
5293
+ * We only need a ParamListInfo if the expression has parameters. In
5294
+ * principle we should test with bms_is_empty(), but we use a not-null
5295
+ * test because it's faster. In current usage bits are never removed from
5296
+ * expr->paramnos, only added, so this test is correct anyway.
5299
5297
*/
5300
- if (! bms_is_empty ( expr -> paramnos ) )
5298
+ if (expr -> paramnos )
5301
5299
{
5302
5300
int dno ;
5303
5301
5304
- paramLI = (ParamListInfo )
5305
- palloc0 (offsetof(ParamListInfoData , params ) +
5306
- estate -> ndatums * sizeof (ParamExternData ));
5307
- paramLI -> paramFetch = plpgsql_param_fetch ;
5308
- paramLI -> paramFetchArg = (void * ) estate ;
5309
- paramLI -> parserSetup = (ParserSetupHook ) plpgsql_parser_setup ;
5310
- paramLI -> parserSetupArg = (void * ) expr ;
5311
- paramLI -> numParams = estate -> ndatums ;
5302
+ /* Use the common ParamListInfo for all evals in this estate */
5303
+ paramLI = estate -> paramLI ;
5304
+
5305
+ /*
5306
+ * Reset all entries to "invalid". It's pretty annoying to have to do
5307
+ * this, but we don't currently track enough information to know which
5308
+ * old entries might be obsolete. (There are a couple of nontrivial
5309
+ * issues that would have to be dealt with in order to do better here.
5310
+ * First, ROW and RECFIELD datums depend on other datums, and second,
5311
+ * exec_eval_datum() will return short-lived palloc'd values for ROW
5312
+ * and REC datums.)
5313
+ */
5314
+ MemSet (paramLI -> params , 0 , estate -> ndatums * sizeof (ParamExternData ));
5312
5315
5313
5316
/* Instantiate values for "safe" parameters of the expression */
5314
5317
dno = -1 ;
@@ -5330,10 +5333,10 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
5330
5333
5331
5334
/*
5332
5335
* Set up link to active expr where the hook functions can find it.
5333
- * Callers must save and restore cur_expr if there is any chance that
5334
- * they are interrupting an active use of parameters.
5336
+ * Callers must save and restore parserSetupArg if there is any chance
5337
+ * that they are interrupting an active use of parameters.
5335
5338
*/
5336
- estate -> cur_expr = expr ;
5339
+ paramLI -> parserSetupArg = ( void * ) expr ;
5337
5340
5338
5341
/*
5339
5342
* Also make sure this is set before parser hooks need it. There is
@@ -5373,7 +5376,7 @@ plpgsql_param_fetch(ParamListInfo params, int paramid)
5373
5376
5374
5377
/* fetch back the hook data */
5375
5378
estate = (PLpgSQL_execstate * ) params -> paramFetchArg ;
5376
- expr = estate -> cur_expr ;
5379
+ expr = ( PLpgSQL_expr * ) params -> parserSetupArg ;
5377
5380
Assert (params -> numParams == estate -> ndatums );
5378
5381
5379
5382
/*
0 commit comments