From 1af091f1a54c1cc8c6b63af307192e3dd554e0b2 Mon Sep 17 00:00:00 2001 From: shihao zhong Date: Mon, 5 Oct 2026 11:38:02 -0400 Subject: [PATCH v1 1/2] plpgsql: fix SELECT INTO when the expression is no longer simple The "SELECT simple-expression INTO var" path added by ce8d5fe0e28 calls exec_eval_expr(), which runs the query through SPI when replanning finds it is no longer simple. FOUND and ROW_COUNT were then set as if one row came back. Call exec_eval_simple_expr() directly and fall through to the regular code when it fails. --- src/pl/plpgsql/src/pl_exec.c | 38 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 341beb496b8..c641c25d98d 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -4312,6 +4312,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, bool isnull; Oid valtype; int32 valtypmod; + bool simple; /* * Setup error traceback support for ereport(). This is so @@ -4327,9 +4328,13 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, if (expr->plan == NULL) exec_prepare_plan(estate, expr, 0); - /* And evaluate the expression */ - value = exec_eval_expr(estate, expr, - &isnull, &valtype, &valtypmod); + /* + * And evaluate the expression. This fails if the expression + * is busy, or if replanning found it is no longer simple. In + * that case fall through to the SPI code below. + */ + simple = exec_eval_simple_expr(estate, expr, &value, &isnull, + &valtype, &valtypmod); /* * Pop the error context stack: the code below would not use @@ -4337,20 +4342,23 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, */ error_context_stack = plerrcontext.previous; - /* Assign the result to the INTO target */ - exec_assign_value(estate, estate->datums[row->varnos[0]], - value, isnull, valtype, valtypmod); - exec_eval_cleanup(estate); + if (simple) + { + /* Assign the result to the INTO target */ + exec_assign_value(estate, estate->datums[row->varnos[0]], + value, isnull, valtype, valtypmod); + exec_eval_cleanup(estate); - /* - * We must duplicate the other effects of the code below, as - * well. We know that exactly one row was returned, so it - * doesn't matter whether the INTO was STRICT or not. - */ - exec_set_found(estate, true); - estate->eval_processed = 1; + /* + * We must duplicate the other effects of the code below, + * as well. We know that exactly one row was returned, so + * it doesn't matter whether the INTO was STRICT or not. + */ + exec_set_found(estate, true); + estate->eval_processed = 1; - return PLPGSQL_RC_OK; + return PLPGSQL_RC_OK; + } } } } -- 2.37.1 (Apple Git-137.1)