1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add BY clause to PL/PgSQL FOR loop, to control the iteration increment.

Jaime Casanova
This commit is contained in:
Bruce Momjian
2006-06-12 16:45:30 +00:00
parent e6a7b01930
commit 07c25723da
6 changed files with 73 additions and 13 deletions

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.90 2006/05/27 19:45:52 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.91 2006/06/12 16:45:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -144,6 +144,7 @@ static void check_labels(const char *start_label,
%token K_ALIAS
%token K_ASSIGN
%token K_BEGIN
%token K_BY
%token K_CLOSE
%token K_CONSTANT
%token K_CONTINUE
@ -935,6 +936,7 @@ for_control :
{
/* Saw "..", so it must be an integer loop */
PLpgSQL_expr *expr2;
PLpgSQL_expr *expr_by;
PLpgSQL_var *fvar;
PLpgSQL_stmt_fori *new;
char *varname;
@ -942,7 +944,34 @@ for_control :
/* First expression is well-formed */
check_sql_expr(expr1->query);
expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
expr2 = read_sql_construct(K_BY,
K_LOOP,
"LOOP",
"SELECT ",
true,
false,
&tok);
if (tok == K_BY)
expr_by = plpgsql_read_expression(K_LOOP, "LOOP");
else
{
/*
* If there is no BY clause we will assume 1
*/
char buf[1024];
PLpgSQL_dstring ds;
plpgsql_dstring_init(&ds);
expr_by = palloc0(sizeof(PLpgSQL_expr));
expr_by->dtype = PLPGSQL_DTYPE_EXPR;
strcpy(buf, "SELECT 1");
plpgsql_dstring_append(&ds, buf);
expr_by->query = pstrdup(plpgsql_dstring_get(&ds));
expr_by->plan = NULL;
}
/* should have had a single variable name */
plpgsql_error_lineno = $2.lineno;
@ -970,6 +999,7 @@ for_control :
new->reverse = reverse;
new->lower = expr1;
new->upper = expr2;
new->by = expr_by;
$$ = (PLpgSQL_stmt *) new;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.169 2006/05/30 13:40:55 momjian Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.170 2006/06/12 16:45:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -1361,7 +1361,8 @@ exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
/* ----------
* exec_stmt_fori Iterate an integer variable
* from a lower to an upper value.
* from a lower to an upper value
* incrementing or decrementing in BY value
* Loop can be left with exit.
* ----------
*/
@ -1370,6 +1371,7 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
{
PLpgSQL_var *var;
Datum value;
Datum by_value;
Oid valtype;
bool isnull;
bool found = false;
@ -1407,6 +1409,21 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
errmsg("upper bound of FOR loop cannot be NULL")));
exec_eval_cleanup(estate);
/*
* Get the by value
*/
by_value = exec_eval_expr(estate, stmt->by, &isnull, &valtype);
by_value = exec_cast_value(by_value, valtype, var->datatype->typoid,
&(var->datatype->typinput),
var->datatype->typioparam,
var->datatype->atttypmod, isnull);
if (isnull)
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmsg("by value of FOR loop cannot be NULL")));
exec_eval_cleanup(estate);
/*
* Now do the loop
*/
@ -1483,9 +1500,9 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
* Increase/decrease loop var
*/
if (stmt->reverse)
var->value--;
var->value -= by_value;
else
var->value++;
var->value += by_value;
}
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.52 2006/05/30 13:40:55 momjian Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.53 2006/06/12 16:45:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -705,6 +705,10 @@ dump_fori(PLpgSQL_stmt_fori *stmt)
printf(" upper = ");
dump_expr(stmt->upper);
printf("\n");
dump_ind();
printf(" by = ");
dump_expr(stmt->by);
printf("\n");
dump_indent -= 2;
dump_stmts(stmt->body);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.74 2006/05/30 13:40:55 momjian Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.75 2006/06/12 16:45:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -398,6 +398,7 @@ typedef struct
PLpgSQL_var *var;
PLpgSQL_expr *lower;
PLpgSQL_expr *upper;
PLpgSQL_expr *by;
int reverse;
List *body; /* List of statements */
} PLpgSQL_stmt_fori;

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.49 2006/05/30 13:40:55 momjian Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.50 2006/06/12 16:45:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -116,6 +116,7 @@ dolqinside [^$]+
\.\. { return K_DOTDOT; }
alias { return K_ALIAS; }
begin { return K_BEGIN; }
by { return K_BY; }
close { return K_CLOSE; }
constant { return K_CONSTANT; }
continue { return K_CONTINUE; }