Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit05dbd4a

Browse files
committed
Fix plpgsql named-cursor-parameter feature for variable name conflicts.
The parser got confused if a cursor parameter had the same name asa plpgsql variable. Reported and diagnosed by Yeb Havinga, thoughthis isn't exactly his proposed fix.Also, some mostly-but-not-entirely-cosmetic adjustments to the originalnamed-cursor-parameter patch, for code readability and better errordiagnostics.
1 parent6f922ef commit05dbd4a

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

‎src/pl/plpgsql/src/gram.y

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3394,11 +3394,11 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
33943394
PLpgSQL_expr *expr;
33953395
PLpgSQL_row *row;
33963396
inttok;
3397-
intargc = 0;
3397+
intargc;
33983398
char **argv;
33993399
StringInfoData ds;
34003400
char *sqlstart = "SELECT ";
3401-
boolnamed = false;
3401+
boolany_named = false;
34023402

34033403
tok = yylex();
34043404
if (cursor->cursor_explicit_argrow < 0)
@@ -3417,9 +3417,6 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
34173417
return NULL;
34183418
}
34193419

3420-
row = (PLpgSQL_row *) plpgsql_Datums[cursor->cursor_explicit_argrow];
3421-
argv = (char **) palloc0(row->nfields * sizeof(char *));
3422-
34233420
/* Else better provide arguments*/
34243421
if (tok != '(')
34253422
ereport(ERROR,
@@ -3431,6 +3428,9 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
34313428
/*
34323429
* Read the arguments, one by one.
34333430
*/
3431+
row = (PLpgSQL_row *) plpgsql_Datums[cursor->cursor_explicit_argrow];
3432+
argv = (char **) palloc0(row->nfields * sizeof(char *));
3433+
34343434
for (argc = 0; argc < row->nfields; argc++)
34353435
{
34363436
PLpgSQL_expr *item;
@@ -3445,11 +3445,16 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
34453445
if (tok1 == IDENT && tok2 == COLON_EQUALS)
34463446
{
34473447
char *argname;
3448+
IdentifierLookup save_IdentifierLookup;
34483449

3449-
/* Read the argument name, and find its position*/
3450+
/* Read the argument name, ignoring any matching variable*/
3451+
save_IdentifierLookup = plpgsql_IdentifierLookup;
3452+
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_DECLARE;
34503453
yylex();
34513454
argname = yylval.str;
3455+
plpgsql_IdentifierLookup = save_IdentifierLookup;
34523456

3457+
/* Match argument name to cursor arguments*/
34533458
for (argpos = 0; argpos < row->nfields; argpos++)
34543459
{
34553460
if (strcmp(row->fieldnames[argpos], argname) == 0)
@@ -3470,11 +3475,18 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
34703475
if (tok2 != COLON_EQUALS)
34713476
yyerror("syntax error");
34723477

3473-
named = true;
3478+
any_named = true;
34743479
}
34753480
else
34763481
argpos = argc;
34773482

3483+
if (argv[argpos] != NULL)
3484+
ereport(ERROR,
3485+
(errcode(ERRCODE_SYNTAX_ERROR),
3486+
errmsg("duplicate value for cursor \"%s\" parameter \"%s\"",
3487+
cursor->refname, row->fieldnames[argpos]),
3488+
parser_errposition(arglocation)));
3489+
34783490
/*
34793491
* Read the value expression. To provide the user with meaningful
34803492
* parse error positions, we check the syntax immediately, instead of
@@ -3491,6 +3503,8 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
34913503
false,/* do not trim*/
34923504
NULL, &endtoken);
34933505

3506+
argv[argpos] = item->query + strlen(sqlstart);
3507+
34943508
if (endtoken == ')' && !(argc == row->nfields - 1))
34953509
ereport(ERROR,
34963510
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -3504,15 +3518,6 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
35043518
errmsg("too many arguments for cursor \"%s\"",
35053519
cursor->refname),
35063520
parser_errposition(yylloc)));
3507-
3508-
if (argv[argpos] != NULL)
3509-
ereport(ERROR,
3510-
(errcode(ERRCODE_SYNTAX_ERROR),
3511-
errmsg("duplicate value for cursor \"%s\" parameter \"%s\"",
3512-
cursor->refname, row->fieldnames[argpos]),
3513-
parser_errposition(arglocation)));
3514-
3515-
argv[argpos] = item->query + strlen(sqlstart);
35163521
}
35173522

35183523
/* Make positional argument list*/
@@ -3527,7 +3532,7 @@ read_cursor_args(PLpgSQL_var *cursor, int until, const char *expected)
35273532
* the parameter name for meaningful runtime errors.
35283533
*/
35293534
appendStringInfoString(&ds, argv[argc]);
3530-
if (named)
3535+
if (any_named)
35313536
appendStringInfo(&ds, " AS %s",
35323537
quote_identifier(row->fieldnames[argc]));
35333538
if (argc < row->nfields - 1)

‎src/test/regress/expected/plpgsql.out

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2420,6 +2420,25 @@ select namedparmcursor_test8();
24202420
0
24212421
(1 row)
24222422

2423+
-- cursor parameter name can match plpgsql variable or unreserved keyword
2424+
create function namedparmcursor_test9(p1 int) returns int4 as $$
2425+
declare
2426+
c1 cursor (p1 int, p2 int, debug int) for
2427+
select count(*) from tenk1 where thousand = p1 and tenthous = p2
2428+
and four = debug;
2429+
p2 int4 := 1006;
2430+
n int4;
2431+
begin
2432+
open c1 (p1 := p1, p2 := p2, debug := 2);
2433+
fetch c1 into n;
2434+
return n;
2435+
end $$ language plpgsql;
2436+
select namedparmcursor_test9(6);
2437+
namedparmcursor_test9
2438+
-----------------------
2439+
1
2440+
(1 row)
2441+
24232442
--
24242443
-- tests for "raise" processing
24252444
--

‎src/test/regress/sql/plpgsql.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,6 +2053,21 @@ begin
20532053
end $$ language plpgsql;
20542054
select namedparmcursor_test8();
20552055

2056+
-- cursor parameter name can match plpgsql variable or unreserved keyword
2057+
createfunctionnamedparmcursor_test9(p1int) returns int4as $$
2058+
declare
2059+
c1 cursor (p1int, p2int, debugint) for
2060+
selectcount(*)from tenk1where thousand= p1and tenthous= p2
2061+
and four= debug;
2062+
p2 int4 :=1006;
2063+
n int4;
2064+
begin
2065+
open c1 (p1 := p1, p2 := p2, debug :=2);
2066+
fetch c1 into n;
2067+
return n;
2068+
end $$ language plpgsql;
2069+
select namedparmcursor_test9(6);
2070+
20562071
--
20572072
-- tests for "raise" processing
20582073
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp