@@ -2197,10 +2197,6 @@ exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
21972197		elog (ERROR , "could not open cursor: %s" ,
21982198			 SPI_result_code_string (SPI_result ));
21992199
2200- 	/* don't need paramlist any more */ 
2201- 	if  (paramLI )
2202- 		pfree (paramLI );
2203- 
22042200	/* 
22052201	 * If cursor variable was NULL, store the generated portal name in it 
22062202	 */ 
@@ -3169,6 +3165,16 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
31693165	estate -> datums  =  palloc (sizeof (PLpgSQL_datum  * ) *  estate -> ndatums );
31703166	/* caller is expected to fill the datums array */ 
31713167
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+ 
31723178	/* set up for use of appropriate simple-expression EState */ 
31733179	if  (simple_eval_estate )
31743180		estate -> simple_eval_estate  =  simple_eval_estate ;
@@ -3179,7 +3185,6 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
31793185	estate -> eval_processed  =  0 ;
31803186	estate -> eval_lastoid  =  InvalidOid ;
31813187	estate -> eval_econtext  =  NULL ;
3182- 	estate -> cur_expr  =  NULL ;
31833188
31843189	estate -> err_stmt  =  NULL ;
31853190	estate -> err_text  =  NULL ;
@@ -3495,9 +3500,6 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
34953500					 (rc  ==  SPI_OK_SELECT ) ? errhint ("If you want to discard the results of a SELECT, use PERFORM instead." ) : 0 ));
34963501	}
34973502
3498- 	if  (paramLI )
3499- 		pfree (paramLI );
3500- 
35013503	return  PLPGSQL_RC_OK ;
35023504}
35033505
@@ -3864,8 +3866,6 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
38643866
38653867	if  (curname )
38663868		pfree (curname );
3867- 	if  (paramLI )
3868- 		pfree (paramLI );
38693869
38703870	return  PLPGSQL_RC_OK ;
38713871}
@@ -4050,7 +4050,7 @@ exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
40504050
40514051
40524052/* ---------- 
4053-  * exec_assign_value			Put a value into a target field  
4053+  * exec_assign_value			Put a value into a target datum  
40544054 * 
40554055 * Note: in some code paths, this will leak memory in the eval_econtext; 
40564056 * we assume that will be cleaned up later by exec_eval_cleanup.  We cannot 
@@ -4909,8 +4909,6 @@ exec_run_select(PLpgSQL_execstate *estate,
49094909		if  (* portalP  ==  NULL )
49104910			elog (ERROR , "could not open implicit cursor for query \"%s\": %s" ,
49114911				 expr -> query , SPI_result_code_string (SPI_result ));
4912- 		if  (paramLI )
4913- 			pfree (paramLI );
49144912		return  SPI_OK_CURSOR ;
49154913	}
49164914
@@ -4930,9 +4928,6 @@ exec_run_select(PLpgSQL_execstate *estate,
49304928	estate -> eval_processed  =  SPI_processed ;
49314929	estate -> eval_lastoid  =  SPI_lastoid ;
49324930
4933- 	if  (paramLI )
4934- 		pfree (paramLI );
4935- 
49364931	return  rc ;
49374932}
49384933
@@ -5140,7 +5135,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
51405135	LocalTransactionId  curlxid  =  MyProc -> lxid ;
51415136	CachedPlan  * cplan ;
51425137	ParamListInfo  paramLI ;
5143- 	PLpgSQL_expr   * save_cur_expr ;
5138+ 	void 	    * save_setup_arg ;
51445139	MemoryContext  oldcontext ;
51455140
51465141	/* 
@@ -5216,14 +5211,10 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
52165211	}
52175212
52185213	/* 
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. 
52255216	 */ 
5226- 	save_cur_expr  =  estate -> cur_expr ;
5217+ 	save_setup_arg  =  estate -> paramLI -> parserSetupArg ;
52275218
52285219	paramLI  =  setup_param_list (estate , expr );
52295220	econtext -> ecxt_param_list_info  =  paramLI ;
@@ -5244,7 +5235,7 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
52445235	/* Assorted cleanup */ 
52455236	expr -> expr_simple_in_use  =  false;
52465237
5247- 	estate -> cur_expr  =  save_cur_expr ;
5238+ 	estate -> paramLI -> parserSetupArg  =  save_setup_arg ;
52485239
52495240	if  (!estate -> readonly_func )
52505241		PopActiveSnapshot ();
@@ -5268,6 +5259,15 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
52685259/* 
52695260 * Create a ParamListInfo to pass to SPI 
52705261 * 
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+  * 
52715271 * We fill in the values for any expression parameters that are plain 
52725272 * PLpgSQL_var datums; these are cheap and safe to evaluate, and by setting 
52735273 * 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,
52775277 * the expression that might never be evaluated at runtime.  To handle those 
52785278 * parameters, we set up a paramFetch hook for the executor to call when it 
52795279 * 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. 
52835280 */ 
52845281static  ParamListInfo 
52855282setup_param_list (PLpgSQL_execstate  * estate , PLpgSQL_expr  * expr )
@@ -5293,22 +5290,28 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
52935290	Assert (expr -> plan  !=  NULL );
52945291
52955292	/* 
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. 
52995297	 */ 
5300- 	if  (! bms_is_empty ( expr -> paramnos ) )
5298+ 	if  (expr -> paramnos )
53015299	{
53025300		int 			dno ;
53035301
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 ));
53125315
53135316		/* Instantiate values for "safe" parameters of the expression */ 
53145317		dno  =  -1 ;
@@ -5330,10 +5333,10 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr)
53305333
53315334		/* 
53325335		 * 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. 
53355338		 */ 
5336- 		estate -> cur_expr   =  expr ;
5339+ 		paramLI -> parserSetupArg   =  ( void   * )  expr ;
53375340
53385341		/* 
53395342		 * Also make sure this is set before parser hooks need it.  There is 
@@ -5373,7 +5376,7 @@ plpgsql_param_fetch(ParamListInfo params, int paramid)
53735376
53745377	/* fetch back the hook data */ 
53755378	estate  =  (PLpgSQL_execstate  * ) params -> paramFetchArg ;
5376- 	expr  =  estate -> cur_expr ;
5379+ 	expr  =  ( PLpgSQL_expr   * )  params -> parserSetupArg ;
53775380	Assert (params -> numParams  ==  estate -> ndatums );
53785381
53795382	/* 
0 commit comments