Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
025ffe58
Commit
025ffe58
authored
Feb 12, 2006
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow PL/pgSQL FOR statement to return values to scalars as well as
records and row types. Pavel Stehule
parent
18cbc7ae
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
124 additions
and
23 deletions
+124
-23
doc/src/sgml/plpgsql.sgml
doc/src/sgml/plpgsql.sgml
+7
-5
src/pl/plpgsql/src/gram.y
src/pl/plpgsql/src/gram.y
+75
-18
src/test/regress/expected/plpgsql.out
src/test/regress/expected/plpgsql.out
+20
-0
src/test/regress/sql/plpgsql.sql
src/test/regress/sql/plpgsql.sql
+22
-0
No files found.
doc/src/sgml/plpgsql.sgml
View file @
025ffe58
<!--
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.8
4 2006/02/05 02:47:53
momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.8
5 2006/02/12 06:03:38
momjian Exp $
-->
<chapter id="plpgsql">
...
...
@@ -2008,11 +2008,13 @@ END LOOP;
accordingly. The syntax is:
<synopsis>
<optional> <<<replaceable>label</replaceable>>> </optional>
FOR <replaceable>
record_or_row
</replaceable> IN <replaceable>query</replaceable> LOOP
FOR <replaceable>
target
</replaceable> IN <replaceable>query</replaceable> LOOP
<replaceable>statements</replaceable>
END LOOP <optional> <replaceable>label</replaceable> </optional>;
</synopsis>
The record or row variable is successively assigned each row
<replaceable>Target</replaceable> is a record variable, row variable,
or a comma-separated list of simple variables and record/row fields
which is successively assigned each row
resulting from the <replaceable>query</replaceable> (which must be a
<command>SELECT</command> command) and the loop body is executed for each
row. Here is an example:
...
...
@@ -2047,7 +2049,7 @@ $$ LANGUAGE plpgsql;
rows:
<synopsis>
<optional> <<<replaceable>label</replaceable>>> </optional>
FOR <replaceable>
record_or_row
</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP
FOR <replaceable>
target
</replaceable> IN EXECUTE <replaceable>text_expression</replaceable> LOOP
<replaceable>statements</replaceable>
END LOOP <optional> <replaceable>label</replaceable> </optional>;
</synopsis>
...
...
@@ -2067,7 +2069,7 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
<literal>IN</> and <literal>LOOP</>. If <literal>..</> is not seen then
the loop is presumed to be a loop over rows. Mistyping the <literal>..</>
is thus likely to lead to a complaint along the lines of
<quote>loop variable of loop over rows must be a record or row variable</>,
<quote>loop variable of loop over rows must be a record or row
or scalar
variable</>,
rather than the simple syntax error one might expect to get.
</para>
</note>
...
...
src/pl/plpgsql/src/gram.y
View file @
025ffe58
...
...
@@ -4,7 +4,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.8
3 2006/02/12 04:59:32 tgl
Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.8
4 2006/02/12 06:03:38 momjian
Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
...
...
@@ -58,7 +58,9 @@ static void check_sql_expr(const char *stmt);
static void plpgsql_sql_error_callback(void *arg);
static void check_labels(const char *start_label,
const char *end_label);
static PLpgSQL_row *make_scalar_list1(const char *name,
PLpgSQL_datum *variable);
%}
%union {
...
...
@@ -76,6 +78,7 @@ static void check_labels(const char *start_label,
int lineno;
PLpgSQL_rec *rec;
PLpgSQL_row *row;
PLpgSQL_datum *scalar;
} forvariable;
struct
{
...
...
@@ -890,10 +893,15 @@ for_control :
new->row = $2.row;
check_assignable((PLpgSQL_datum *) new->row);
}
else if ($2.scalar)
{
new->row = make_scalar_list1($2.name, $2.scalar);
check_assignable((PLpgSQL_datum *) new->row);
}
else
{
plpgsql_error_lineno = $1;
yyerror("loop variable of loop over rows must be a record
or row
variable");
yyerror("loop variable of loop over rows must be a record
, row, or scalar
variable");
}
new->query = expr;
...
...
@@ -948,6 +956,15 @@ for_control :
expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
/* T_SCALAR identifier waits for converting */
if ($2.scalar)
{
char *name;
plpgsql_convert_ident($2.name, &name, 1);
pfree($2.name);
$2.name = name;
}
/* create loop's private variable */
fvar = (PLpgSQL_var *)
plpgsql_build_variable($2.name,
...
...
@@ -1002,10 +1019,15 @@ for_control :
new->row = $2.row;
check_assignable((PLpgSQL_datum *) new->row);
}
else if ($2.scalar)
{
new->row = make_scalar_list1($2.name, $2.scalar);
check_assignable((PLpgSQL_datum *) new->row);
}
else
{
plpgsql_error_lineno = $1;
yyerror("loop variable of loop over rows must be record
or row
variable");
yyerror("loop variable of loop over rows must be record
, row, or scalar
variable");
}
new->query = expr1;
...
...
@@ -1027,14 +1049,31 @@ for_control :
* until we know what's what.
*/
for_variable : T_SCALAR
{
{
int tok;
char *name;
name = pstrdup(yytext);
$$.scalar = yylval.scalar;
$$.lineno = plpgsql_scanner_lineno();
plpgsql_convert_ident(yytext, &name, 1);
$$.name = name;
$$.lineno = plpgsql_scanner_lineno();
$$.rec = NULL;
$$.row = NULL;
if((tok = yylex()) == ',')
{
plpgsql_push_back_token(tok);
$$.name = NULL;
$$.row = read_into_scalar_list(name, $$.scalar);
$$.rec = NULL;
$$.scalar = NULL;
pfree(name);
}
else
{
plpgsql_push_back_token(tok);
$$.name = name;
$$.row = NULL;
$$.rec = NULL;
}
}
| T_WORD
{
...
...
@@ -1048,20 +1087,14 @@ for_variable : T_SCALAR
}
| T_RECORD
{
char *name;
plpgsql_convert_ident(yytext, &name, 1);
$$.name = name;
$$.name = NULL;
$$.lineno = plpgsql_scanner_lineno();
$$.rec = yylval.rec;
$$.row = NULL;
}
| T_ROW
{
char *name;
plpgsql_convert_ident(yytext, &name, 1);
$$.name = name;
$$.name = NULL;
$$.lineno = plpgsql_scanner_lineno();
$$.row = yylval.row;
$$.rec = NULL;
...
...
@@ -2088,6 +2121,30 @@ make_fetch_stmt(void)
}
static PLpgSQL_row *
make_scalar_list1(const char *name,
PLpgSQL_datum *variable)
{
PLpgSQL_row *row;
check_assignable(variable);
row = palloc(sizeof(PLpgSQL_row));
row->dtype = PLPGSQL_DTYPE_ROW;
row->refname = pstrdup("*internal*");
row->lineno = plpgsql_scanner_lineno();
row->rowtupdesc = NULL;
row->nfields = 1;
row->fieldnames = palloc(sizeof(char *) * 1);
row->varnos = palloc(sizeof(int) * 1);
row->fieldnames[0] = pstrdup(name);
row->varnos[0] = variable->dno;
plpgsql_adddatum((PLpgSQL_datum *)row);
return row;
}
static void
check_assignable(PLpgSQL_datum *datum)
{
...
...
src/test/regress/expected/plpgsql.out
View file @
025ffe58
...
...
@@ -2721,3 +2721,23 @@ end;
$$ language plpgsql;
ERROR: end label "outer_label" specified for unlabelled block
CONTEXT: compile of PL/pgSQL function "end_label4" near line 5
-- using list of scalars in fori and fore stmts
create function for_vect() returns void as $$
<<lbl>>declare a integer; b varchar; c varchar; r record;
begin
-- old fori
for i in 1 .. 10 loop
raise notice '%', i;
end loop;
for a in select 1 from generate_series(1,4) loop
raise notice '%', a;
end loop;
for a,b,c in select generate_series, 'BB','CC' from generate_series(1,4) loop
raise notice '% % %', a, b, c;
end loop;
-- using qualified names in fors, fore is enabled, disabled only for fori
for lbl.a, lbl.b, lbl.c in execute E'select generate_series, \'bb\',\'cc\' from generate_series(1,4)' loop
raise notice '% % %', a, b, c;
end loop;
end;
$$ language plpgsql;
src/test/regress/sql/plpgsql.sql
View file @
025ffe58
...
...
@@ -2280,3 +2280,25 @@ begin
end
loop
outer_label
;
end
;
$$
language
plpgsql
;
-- using list of scalars in fori and fore stmts
create
function
for_vect
()
returns
void
as
$$
<<
lbl
>>
declare
a
integer
;
b
varchar
;
c
varchar
;
r
record
;
begin
-- old fori
for
i
in
1
..
10
loop
raise
notice
'%'
,
i
;
end
loop
;
for
a
in
select
1
from
generate_series
(
1
,
4
)
loop
raise
notice
'%'
,
a
;
end
loop
;
for
a
,
b
,
c
in
select
generate_series
,
'BB'
,
'CC'
from
generate_series
(
1
,
4
)
loop
raise
notice
'% % %'
,
a
,
b
,
c
;
end
loop
;
-- using qualified names in fors, fore is enabled, disabled only for fori
for
lbl
.
a
,
lbl
.
b
,
lbl
.
c
in
execute
E
'select generate_series,
\'
bb
\'
,
\'
cc
\'
from generate_series(1,4)'
loop
raise
notice
'% % %'
,
a
,
b
,
c
;
end
loop
;
end
;
$$
language
plpgsql
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment