diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 341beb496b8..bc1667f7a13 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -4307,11 +4307,13 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, if (row->nfields == 1) { + /* OK, there is a single target variable */ ErrorContextCallback plerrcontext; Datum value; bool isnull; Oid valtype; int32 valtypmod; + bool simple; /* * Setup error traceback support for ereport(). This is so @@ -4323,13 +4325,15 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, plerrcontext.previous = error_context_stack; error_context_stack = &plerrcontext; - /* If first time through, create a plan for this expression */ - if (expr->plan == NULL) - exec_prepare_plan(estate, expr, 0); - - /* And evaluate the expression */ - value = exec_eval_expr(estate, expr, - &isnull, &valtype, &valtypmod); + /* + * Evaluate the already-planned expression. This fails if the + * expression is busy, or if replanning occurs and we find it + * is no longer simple. In such cases, 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 +4341,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) + { + /* Success; 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; + } } } }