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 labelREVERSE 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; }