diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index f0cbbf2896cef9e02c486f1b29d0711a1bb5848b..60c7593362beb388cf1e7543607c6a5ae217b691 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.94 2006/05/30 13:40:55 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.95 2006/06/12 16:45:30 momjian Exp $ -->
 
 <chapter id="plpgsql"> 
   <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -1975,7 +1975,7 @@ END LOOP;
 
 <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
+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>
@@ -1988,8 +1988,10 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
         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.
+        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>
@@ -2003,6 +2005,11 @@ END LOOP;
 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>
 
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 2461deaf328d7580342e54068b5b4473c81b37d8..5343dfb1978af529315c9b9c601266719898010d 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -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;
 							}
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index b27849c8913e541717e1e83d30048a2bed85c7d1..3ac48bbcecb55e24871fffc2bf228ef30cf65a43 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -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;
 	}
 
 	/*
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index 9420ab15cf37bffff52c3262a01c53611cb1d89e..a4e661a44af6cb2cebb468a81c409ff5a019cf23 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -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);
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 86fea3ca465620ce16358ccdc6136f215feabf8e..16ffe7e93dfe0a4445f2f457ad4d18e2e812b93a 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -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;
diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l
index dfc2b942ecb92bc6c25fbb632d6b405cf005ab8e..daafe96b87499f02783cf2ec5eb94a831f6e3631 100644
--- a/src/pl/plpgsql/src/scan.l
+++ b/src/pl/plpgsql/src/scan.l
@@ -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;		}