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 ****
  
  <synopsis>
  <optional> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </optional>
! FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> .. <replaceable>expression</replaceable> LOOP
      <replaceable>statements</replaceable>
  END LOOP <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>
--- 1975,1981 ----
  
  <synopsis>
  <optional> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </optional>
! FOR <replaceable>name</replaceable> IN <optional> REVERSE </optional> <replaceable>expression</replaceable> .. <replaceable>expression</replaceable> <optional> BY <replaceable>expression</replaceable> </optional> LOOP
      <replaceable>statements</replaceable>
  END LOOP <optional> <replaceable>label</replaceable> </optional>;
  </synopsis>
*************** END LOOP <optional> <replaceable>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 <literal>REVERSE</> is
!         specified.
         </para>
  
         <para>
--- 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 <literal>BY</> clause isn't specified the iteration 
!         step is 1 otherwise it's the value specified in the <literal>BY</> 
!         clause. If <literal>REVERSE</> is specified then the step value is 
! 		considered negative.
         </para>
  
         <para>
*************** 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;
  </programlisting>
         </para>
  
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;		}
