Index: doc/src/sgml/plpgsql.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v
retrieving revision 1.94
diff -c -p -r1.94 plpgsql.sgml
*** doc/src/sgml/plpgsql.sgml 30 May 2006 13:40:55 -0000 1.94
--- doc/src/sgml/plpgsql.sgml 7 Jun 2006 05:49:46 -0000
*************** END LOOP;
*** 1975,1981 ****
<<label>>
! FOR name IN REVERSE expression .. expression LOOP
statements
END LOOP label ;
--- 1975,1981 ----
<<label>>
! FOR name IN REVERSE expression .. expression BY expression LOOP
statements
END LOOP label ;
*************** END LOOP label
*** 1988,1995 ****
definition of the variable name is ignored within the loop).
The two expressions giving
the lower and upper bound of the range are evaluated once when entering
! the loop. The iteration step is normally 1, but is -1 when REVERSE> is
! specified.
--- 1988,1997 ----
definition of the variable name is ignored within the loop).
The two expressions giving
the lower and upper bound of the range are evaluated once when entering
! the loop. If the BY> clause isn't specified the iteration
! step is 1 otherwise it's the value specified in the BY>
! clause. If REVERSE> is specified then the step value is
! considered negative.
*************** END LOOP;
*** 2003,2008 ****
--- 2005,2015 ----
FOR i IN REVERSE 10..1 LOOP
-- some computations here
END LOOP;
+
+ FOR i IN REVERSE 10..1 BY 2 LOOP
+ -- some computations here
+ RAISE NOTICE 'i is %', i;
+ END LOOP;
Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.90
diff -c -p -r1.90 gram.y
*** src/pl/plpgsql/src/gram.y 27 May 2006 19:45:52 -0000 1.90
--- src/pl/plpgsql/src/gram.y 7 Jun 2006 05:50:06 -0000
*************** static void check_labels(const char *
*** 144,149 ****
--- 144,150 ----
%token K_ALIAS
%token K_ASSIGN
%token K_BEGIN
+ %token K_BY
%token K_CLOSE
%token K_CONSTANT
%token K_CONTINUE
*************** for_control :
*** 935,940 ****
--- 936,942 ----
{
/* Saw "..", so it must be an integer loop */
PLpgSQL_expr *expr2;
+ PLpgSQL_expr *expr_by;
PLpgSQL_var *fvar;
PLpgSQL_stmt_fori *new;
char *varname;
*************** for_control :
*** 942,948 ****
/* First expression is well-formed */
check_sql_expr(expr1->query);
! expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
/* should have had a single variable name */
plpgsql_error_lineno = $2.lineno;
--- 944,977 ----
/* First expression is well-formed */
check_sql_expr(expr1->query);
!
! 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;
*************** for_control :
*** 970,975 ****
--- 999,1005 ----
new->reverse = reverse;
new->lower = expr1;
new->upper = expr2;
+ new->by = expr_by;
$$ = (PLpgSQL_stmt *) new;
}
Index: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.169
diff -c -p -r1.169 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c 30 May 2006 13:40:55 -0000 1.169
--- src/pl/plpgsql/src/pl_exec.c 7 Jun 2006 05:50:21 -0000
*************** exec_stmt_while(PLpgSQL_execstate *estat
*** 1361,1367 ****
/* ----------
* exec_stmt_fori Iterate an integer variable
! * from a lower to an upper value.
* Loop can be left with exit.
* ----------
*/
--- 1361,1368 ----
/* ----------
* exec_stmt_fori Iterate an integer variable
! * from a lower to an upper value
! * incrementing or decrementing in BY value
* Loop can be left with exit.
* ----------
*/
*************** exec_stmt_fori(PLpgSQL_execstate *estate
*** 1370,1375 ****
--- 1371,1377 ----
{
PLpgSQL_var *var;
Datum value;
+ Datum by_value;
Oid valtype;
bool isnull;
bool found = false;
*************** exec_stmt_fori(PLpgSQL_execstate *estate
*** 1408,1413 ****
--- 1410,1430 ----
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
*/
for (;;)
*************** exec_stmt_fori(PLpgSQL_execstate *estate
*** 1483,1491 ****
* Increase/decrease loop var
*/
if (stmt->reverse)
! var->value--;
else
! var->value++;
}
/*
--- 1500,1508 ----
* Increase/decrease loop var
*/
if (stmt->reverse)
! var->value -= by_value;
else
! var->value += by_value;
}
/*
Index: src/pl/plpgsql/src/pl_funcs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v
retrieving revision 1.52
diff -c -p -r1.52 pl_funcs.c
*** src/pl/plpgsql/src/pl_funcs.c 30 May 2006 13:40:55 -0000 1.52
--- src/pl/plpgsql/src/pl_funcs.c 7 Jun 2006 05:50:25 -0000
*************** dump_fori(PLpgSQL_stmt_fori *stmt)
*** 705,710 ****
--- 705,714 ----
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);
Index: src/pl/plpgsql/src/plpgsql.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v
retrieving revision 1.74
diff -c -p -r1.74 plpgsql.h
*** src/pl/plpgsql/src/plpgsql.h 30 May 2006 13:40:55 -0000 1.74
--- src/pl/plpgsql/src/plpgsql.h 7 Jun 2006 05:50:27 -0000
*************** typedef struct
*** 398,403 ****
--- 398,404 ----
PLpgSQL_var *var;
PLpgSQL_expr *lower;
PLpgSQL_expr *upper;
+ PLpgSQL_expr *by;
int reverse;
List *body; /* List of statements */
} PLpgSQL_stmt_fori;
Index: src/pl/plpgsql/src/scan.l
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpgsql/src/scan.l,v
retrieving revision 1.49
diff -c -p -r1.49 scan.l
*** src/pl/plpgsql/src/scan.l 30 May 2006 13:40:55 -0000 1.49
--- src/pl/plpgsql/src/scan.l 7 Jun 2006 05:50:29 -0000
*************** dolqinside [^$]+
*** 116,121 ****
--- 116,122 ----
\.\. { 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; }