diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index df785c98511b98e928735f744fb226f9d83e5850..1f1acdc5e0af3d184d3b6f85092aebabc25f6fc1 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3012,11 +3012,6 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, int rc; PLpgSQL_expr *expr = stmt->sqlstmt; - /* - * Set up ParamListInfo (hook function and possibly data values) - */ - paramLI = setup_param_list(estate, expr); - /* * On the first call for this statement generate the plan, and detect * whether the statement is INSERT/UPDATE/DELETE @@ -3049,6 +3044,11 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, } } + /* + * Set up ParamListInfo (hook function and possibly data values) + */ + paramLI = setup_param_list(estate, expr); + /* * If we have INTO, then we only need one row back ... but if we have INTO * STRICT, ask for two rows, so that we can verify the statement returns @@ -5000,12 +5000,18 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) { ParamListInfo paramLI; + /* + * We must have created the SPIPlan already (hence, query text has been + * parsed/analyzed at least once); else we cannot rely on expr->paramnos. + */ + Assert(expr->plan != NULL); + /* * Could we re-use these arrays instead of palloc'ing a new one each time? * However, we'd have to re-fill the array each time anyway, since new * values might have been assigned to the variables. */ - if (estate->ndatums > 0) + if (!bms_is_empty(expr->paramnos)) { Bitmapset *tmpset; int dno; @@ -5048,12 +5054,19 @@ setup_param_list(PLpgSQL_execstate *estate, PLpgSQL_expr *expr) /* * Also make sure this is set before parser hooks need it. There is * no need to save and restore, since the value is always correct once - * set. + * set. (Should be set already, but let's be sure.) */ expr->func = estate->func; } else + { + /* + * Expression requires no parameters. Be sure we represent this case + * as a NULL ParamListInfo, so that plancache.c knows there is no + * point in a custom plan. + */ paramLI = NULL; + } return paramLI; }