Skip to content

Commit 9e3ad1a

Browse files
committed
Use fast path in plpgsql's RETURN/RETURN NEXT in more cases.
exec_stmt_return() and exec_stmt_return_next() have fast-path code for handling a simple variable reference (i.e. "return var") without going through the full expression evaluation machinery. For some reason, pl_gram.y was under the impression that this fast path only applied for record/row variables; but in reality code for handling regular scalar variables has been there all along. Adjusting the logic to allow that code to be used actually results in a net savings of code in pl_gram.y (by eliminating some redundancy), and it buys a measurable though not very impressive amount of speedup. Noted while fooling with my expanded-array patch, wherein this makes a much bigger difference because it enables returning an expanded array variable without an extra flattening step. But AFAICS this is a win regardless, so commit it separately.
1 parent 2c75531 commit 9e3ad1a

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,8 +2452,9 @@ exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
24522452
estate->retisnull = true;
24532453

24542454
/*
2455-
* This special-case path covers record/row variables in fn_retistuple
2456-
* functions, as well as functions with one or more OUT parameters.
2455+
* Special case path when the RETURN expression is a simple variable
2456+
* reference; in particular, this path is always taken in functions with
2457+
* one or more OUT parameters.
24572458
*/
24582459
if (stmt->retvarno >= 0)
24592460
{
@@ -2576,8 +2577,9 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
25762577
natts = tupdesc->natts;
25772578

25782579
/*
2579-
* This special-case path covers record/row variables in fn_retistuple
2580-
* functions, as well as functions with one or more OUT parameters.
2580+
* Special case path when the RETURN NEXT expression is a simple variable
2581+
* reference; in particular, this path is always taken in functions with
2582+
* one or more OUT parameters.
25812583
*/
25822584
if (stmt->retvarno >= 0)
25832585
{

src/pl/plpgsql/src/pl_gram.y

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,16 +3036,17 @@ make_return_stmt(int location)
30363036
errmsg("RETURN cannot have a parameter in function returning void"),
30373037
parser_errposition(yylloc)));
30383038
}
3039-
else if (plpgsql_curr_compile->fn_retistuple)
3039+
else
30403040
{
30413041
/*
3042-
* We want to special-case simple row or record references for
3043-
* efficiency. So peek ahead to see if that's what we have.
3042+
* We want to special-case simple variable references for efficiency.
3043+
* So peek ahead to see if that's what we have.
30443044
*/
30453045
int tok = yylex();
30463046

30473047
if (tok == T_DATUM && plpgsql_peek() == ';' &&
3048-
(yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
3048+
(yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR ||
3049+
yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
30493050
yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC))
30503051
{
30513052
new->retvarno = yylval.wdatum.datum->dno;
@@ -3055,19 +3056,16 @@ make_return_stmt(int location)
30553056
}
30563057
else
30573058
{
3058-
/* Not (just) a row/record name, so treat as expression */
3059+
/*
3060+
* Not (just) a variable name, so treat as expression.
3061+
*
3062+
* Note that a well-formed expression is _required_ here;
3063+
* anything else is a compile-time error.
3064+
*/
30593065
plpgsql_push_back_token(tok);
30603066
new->expr = read_sql_expression(';', ";");
30613067
}
30623068
}
3063-
else
3064-
{
3065-
/*
3066-
* Note that a well-formed expression is _required_ here;
3067-
* anything else is a compile-time error.
3068-
*/
3069-
new->expr = read_sql_expression(';', ";");
3070-
}
30713069

30723070
return (PLpgSQL_stmt *) new;
30733071
}
@@ -3099,16 +3097,17 @@ make_return_next_stmt(int location)
30993097
parser_errposition(yylloc)));
31003098
new->retvarno = plpgsql_curr_compile->out_param_varno;
31013099
}
3102-
else if (plpgsql_curr_compile->fn_retistuple)
3100+
else
31033101
{
31043102
/*
3105-
* We want to special-case simple row or record references for
3106-
* efficiency. So peek ahead to see if that's what we have.
3103+
* We want to special-case simple variable references for efficiency.
3104+
* So peek ahead to see if that's what we have.
31073105
*/
31083106
int tok = yylex();
31093107

31103108
if (tok == T_DATUM && plpgsql_peek() == ';' &&
3111-
(yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
3109+
(yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_VAR ||
3110+
yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
31123111
yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC))
31133112
{
31143113
new->retvarno = yylval.wdatum.datum->dno;
@@ -3118,13 +3117,16 @@ make_return_next_stmt(int location)
31183117
}
31193118
else
31203119
{
3121-
/* Not (just) a row/record name, so treat as expression */
3120+
/*
3121+
* Not (just) a variable name, so treat as expression.
3122+
*
3123+
* Note that a well-formed expression is _required_ here;
3124+
* anything else is a compile-time error.
3125+
*/
31223126
plpgsql_push_back_token(tok);
31233127
new->expr = read_sql_expression(';', ";");
31243128
}
31253129
}
3126-
else
3127-
new->expr = read_sql_expression(';', ";");
31283130

31293131
return (PLpgSQL_stmt *) new;
31303132
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy