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

Commit55caaae

Browse files
committed
Improve handling of array elements as getdiag_targets and cursor_variables.
There's no good reason why plpgsql's GET DIAGNOSTICS statement can'tsupport an array element as target variable, since the execution codealready uses the generic exec_assign_value() function to assign to it.Hence, refactor the grammar to allow that, by making getdiag_targetdepend on the assign_var production.Ideally we'd also let a cursor_variable expand to an element of arefcursor[] array, but that's substantially harder since those statementsalso have to handle bound-cursor-variable cases. For now, just make surethe reported error is sensible, ie "cursor variable must be a simplevariable" not "variable must be of type cursor or refcursor". The latterwas quite confusing from the user's viewpoint, since what he wrotesatisfies the claimed restriction.Per bug #14463 from Zhou Digoal. Given the lack of previous complaints,I see no need for a back-patch.Discussion:https://postgr.es/m/20161213152548.14897.81245@wrigleys.postgresql.org
1 parent1f542a2 commit55caaae

File tree

3 files changed

+33
-22
lines changed

3 files changed

+33
-22
lines changed

‎src/pl/plpgsql/src/pl_gram.y

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,11 @@ staticvoidcheck_raise_parameters(PLpgSQL_stmt_raise *stmt);
180180
%type<expr>expr_until_thenexpr_until_loopopt_expr_until_when
181181
%type<expr>opt_exitcond
182182

183-
%type<ival>assign_varforeach_slice
183+
%type<datum>assign_var
184184
%type<var>cursor_variable
185185
%type<datum>decl_cursor_arg
186186
%type<forvariable>for_variable
187+
%type<ival>foreach_slice
187188
%type<stmt>for_control
188189

189190
%type<str>any_identifieropt_block_labelopt_loop_labelopt_label
@@ -209,7 +210,8 @@ staticvoidcheck_raise_parameters(PLpgSQL_stmt_raise *stmt);
209210
%type<boolean>getdiag_area_opt
210211
%type<list>getdiag_list
211212
%type<diagitem>getdiag_list_item
212-
%type<ival>getdiag_itemgetdiag_target
213+
%type<datum>getdiag_target
214+
%type<ival>getdiag_item
213215

214216
%type<ival>opt_scrollable
215217
%type<fetch>opt_fetch_direction
@@ -916,7 +918,7 @@ stmt_assign: assign_var assign_operator expr_until_semi
916918
new =palloc0(sizeof(PLpgSQL_stmt_assign));
917919
new->cmd_type = PLPGSQL_STMT_ASSIGN;
918920
new->lineno =plpgsql_location_to_lineno(@1);
919-
new->varno = $1;
921+
new->varno = $1->dno;
920922
new->expr = $3;
921923

922924
$$ = (PLpgSQL_stmt *)new;
@@ -1014,7 +1016,7 @@ getdiag_list_item : getdiag_target assign_operator getdiag_item
10141016
PLpgSQL_diag_item *new;
10151017

10161018
new =palloc(sizeof(PLpgSQL_diag_item));
1017-
new->target = $1;
1019+
new->target = $1->dno;
10181020
new->kind = $3;
10191021

10201022
$$ =new;
@@ -1069,17 +1071,16 @@ getdiag_item :
10691071
}
10701072
;
10711073

1072-
getdiag_target:T_DATUM
1074+
getdiag_target:assign_var
10731075
{
1074-
check_assignable($1.datum, @1);
1075-
if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
1076-
$1.datum->dtype == PLPGSQL_DTYPE_REC)
1076+
if ($1->dtype == PLPGSQL_DTYPE_ROW ||
1077+
$1->dtype == PLPGSQL_DTYPE_REC)
10771078
ereport(ERROR,
10781079
(errcode(ERRCODE_SYNTAX_ERROR),
10791080
errmsg("\"%s\" is not a scalar variable",
1080-
NameOfDatum(&($1))),
1081+
((PLpgSQL_variable *)$1)->refname),
10811082
parser_errposition(@1)));
1082-
$$ = $1.datum->dno;
1083+
$$ = $1;
10831084
}
10841085
| T_WORD
10851086
{
@@ -1097,7 +1098,7 @@ getdiag_target: T_DATUM
10971098
assign_var: T_DATUM
10981099
{
10991100
check_assignable($1.datum, @1);
1100-
$$ = $1.datum->dno;
1101+
$$ = $1.datum;
11011102
}
11021103
| assign_var'[' expr_until_rightbracket
11031104
{
@@ -1106,13 +1107,13 @@ assign_var: T_DATUM
11061107
new =palloc0(sizeof(PLpgSQL_arrayelem));
11071108
new->dtype= PLPGSQL_DTYPE_ARRAYELEM;
11081109
new->subscript= $3;
1109-
new->arrayparentno = $1;
1110+
new->arrayparentno = $1->dno;
11101111
/* initialize cached type data to "not valid"*/
11111112
new->parenttypoid = InvalidOid;
11121113

11131114
plpgsql_adddatum((PLpgSQL_datum *)new);
11141115

1115-
$$ =new->dno;
1116+
$$ =(PLpgSQL_datum *)new;
11161117
}
11171118
;
11181119

@@ -2173,7 +2174,13 @@ stmt_null: K_NULL ';'
21732174

21742175
cursor_variable: T_DATUM
21752176
{
2176-
if ($1.datum->dtype != PLPGSQL_DTYPE_VAR)
2177+
/*
2178+
* In principle we should support a cursor_variable
2179+
* that is an array element, but for now we don't, so
2180+
* just throw an error if next token is '['.
2181+
*/
2182+
if ($1.datum->dtype != PLPGSQL_DTYPE_VAR ||
2183+
plpgsql_peek() =='[')
21772184
ereport(ERROR,
21782185
(errcode(ERRCODE_DATATYPE_MISMATCH),
21792186
errmsg("cursor variable must be a simple variable"),

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4623,6 +4623,7 @@ drop function tftest(int);
46234623
create or replace function rttest()
46244624
returns setof int as $$
46254625
declare rc int;
4626+
rca int[];
46264627
begin
46274628
return query values(10),(20);
46284629
get diagnostics rc = row_count;
@@ -4631,11 +4632,12 @@ begin
46314632
get diagnostics rc = row_count;
46324633
raise notice '% %', found, rc;
46334634
return query execute 'values(10),(20)';
4634-
get diagnostics rc = row_count;
4635-
raise notice '% %', found, rc;
4635+
-- just for fun, let's use array elements as targets
4636+
get diagnostics rca[1] = row_count;
4637+
raise notice '% %', found, rca[1];
46364638
return query execute 'select * from (values(10),(20)) f(a) where false';
4637-
get diagnosticsrc = row_count;
4638-
raise notice '% %', found,rc;
4639+
get diagnosticsrca[2] = row_count;
4640+
raise notice '% %', found,rca[2];
46394641
end;
46404642
$$ language plpgsql;
46414643
select * from rttest();

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3719,6 +3719,7 @@ drop function tftest(int);
37193719
create or replacefunctionrttest()
37203720
returns setofintas $$
37213721
declare rcint;
3722+
rcaint[];
37223723
begin
37233724
return queryvalues(10),(20);
37243725
get diagnostics rc= row_count;
@@ -3727,11 +3728,12 @@ begin
37273728
get diagnostics rc= row_count;
37283729
raise notice'% %', found, rc;
37293730
return query execute'values(10),(20)';
3730-
get diagnostics rc= row_count;
3731-
raise notice'% %', found, rc;
3731+
-- just for fun, let's use array elements as targets
3732+
get diagnostics rca[1]= row_count;
3733+
raise notice'% %', found, rca[1];
37323734
return query execute'select * from (values(10),(20)) f(a) where false';
3733-
get diagnosticsrc= row_count;
3734-
raise notice'% %', found,rc;
3735+
get diagnosticsrca[2]= row_count;
3736+
raise notice'% %', found,rca[2];
37353737
end;
37363738
$$ language plpgsql;
37373739

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp