aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpgsql/src/gram.y93
-rw-r--r--src/test/regress/expected/plpgsql.out20
-rw-r--r--src/test/regress/sql/plpgsql.sql22
3 files changed, 117 insertions, 18 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 72735873c4e..a23e57a158b 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -4,7 +4,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.83 2006/02/12 04:59:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.84 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)
{
diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out
index aef73e1eee7..3bcafcfb4d0 100644
--- a/src/test/regress/expected/plpgsql.out
+++ b/src/test/regress/expected/plpgsql.out
@@ -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;
diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql
index fdb2f46ff89..63b8bef14eb 100644
--- a/src/test/regress/sql/plpgsql.sql
+++ b/src/test/regress/sql/plpgsql.sql
@@ -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;