On 4/30/06, Jaime Casanova <[EMAIL PROTECTED]> wrote:
On 4/29/06, Andrew Dunstan <[EMAIL PROTECTED]> wrote:
> Tom Lane wrote:
>
> >"Jaime Casanova" <[EMAIL PROTECTED]> writes:
> >
> >
> >>there is a chance to add a STEP clause to the FOR statement in plpgsql?
> >>
> >>
> >
> >This is not free: it'd require making STEP a reserved word (at least
> >within plpgsql) which is contrary to spec.  I think you need to make
> >a pretty good case why the value of the feature outweighs breaking
> >applications that have perfectly-legally used "step" as an identifier.
> >
> >
>
> This isn't available in PL/SQL, is it? That doesn't mean we shouldn't do it, 
of course, but it might lessen any perceived imperative.
>
> Maybe using BY instad of STEP as the keyword would make it easier, since its 
occurrence in SQL makes it less likely to be used as a variable.
>
> cheers
>
> andrew
>
>

Hi,

i make a little patch using BY instead of STEP per Tom's complaint and
Andrew's suggestion.


the patch is ready, at least it seems to me... also i have added some
lines to the docs...

let me know what your decision is about this...

--
regards,
Jaime Casanova

"Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs and the universe trying
to produce bigger and better idiots.
So far, the universe is winning."
                                      Richard Cook
diff -rcEib pgsql-8.2dev/doc/src/sgml/plpgsql.sgml pgsql-8.2fori/doc/src/sgml/plpgsql.sgml
*** pgsql-8.2dev/doc/src/sgml/plpgsql.sgml	2006-05-01 08:49:20.000000000 -0500
--- pgsql-8.2fori/doc/src/sgml/plpgsql.sgml	2006-05-05 17:31:36.000000000 -0500
***************
*** 1960,1966 ****
  
  <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>
--- 1960,1966 ----
  
  <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>
***************
*** 1973,1980 ****
          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>
--- 1973,1982 ----
          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>
***************
*** 1988,1993 ****
--- 1990,2000 ----
  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 -rcEib pgsql-8.2dev/src/pl/plpgsql/src/gram.y pgsql-8.2fori/src/pl/plpgsql/src/gram.y
*** pgsql-8.2dev/src/pl/plpgsql/src/gram.y	2006-05-01 08:49:39.000000000 -0500
--- pgsql-8.2fori/src/pl/plpgsql/src/gram.y	2006-05-05 17:42:08.000000000 -0500
***************
*** 143,148 ****
--- 143,149 ----
  %token	K_ALIAS
  %token	K_ASSIGN
  %token	K_BEGIN
+ %token	K_BY
  %token	K_CLOSE
  %token	K_CONSTANT
  %token	K_CONTINUE
***************
*** 930,935 ****
--- 931,937 ----
  							{
  								/* Saw "..", so it must be an integer loop */
  								PLpgSQL_expr		*expr2;
+ 								PLpgSQL_expr		*expr_by;
  								PLpgSQL_var			*fvar;
  								PLpgSQL_stmt_fori	*new;
  								char				*varname;
***************
*** 937,943 ****
  								/* 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;
--- 939,968 ----
  								/* 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];
! 
! 									expr_by = palloc0(sizeof(PLpgSQL_expr));
! 									expr_by->dtype      		= PLPGSQL_DTYPE_EXPR;
! 									strcpy(buf, "SELECT 1");
! 									expr_by->query				= buf;
! 									expr_by->plan				= NULL;
! 								}
  
  								/* should have had a single variable name */
  								plpgsql_error_lineno = $2.lineno;
***************
*** 965,970 ****
--- 990,996 ----
  								new->reverse  = reverse;
  								new->lower	  = expr1;
  								new->upper	  = expr2;
+ 								new->by		  = expr_by;
  
  								$$ = (PLpgSQL_stmt *) new;
  							}
diff -rcEib pgsql-8.2dev/src/pl/plpgsql/src/pl_exec.c pgsql-8.2fori/src/pl/plpgsql/src/pl_exec.c
*** pgsql-8.2dev/src/pl/plpgsql/src/pl_exec.c	2006-05-01 08:49:39.000000000 -0500
--- pgsql-8.2fori/src/pl/plpgsql/src/pl_exec.c	2006-05-05 18:18:23.000000000 -0500
***************
*** 1346,1352 ****
  
  /* ----------
   * exec_stmt_fori			Iterate an integer variable
!  *					from a lower to an upper value.
   *					Loop can be left with exit.
   * ----------
   */
--- 1346,1353 ----
  
  /* ----------
   * 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.
   * ----------
   */
***************
*** 1355,1360 ****
--- 1356,1362 ----
  {
  	PLpgSQL_var *var;
  	Datum		value;
+ 	Datum		by_value;
  	Oid			valtype;
  	bool		isnull;
  	bool		found = false;
***************
*** 1393,1398 ****
--- 1395,1415 ----
  	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 (;;)
***************
*** 1468,1476 ****
  		 * Increase/decrease loop var
  		 */
  		if (stmt->reverse)
! 			var->value--;
  		else
! 			var->value++;
  	}
  
  	/*
--- 1485,1493 ----
  		 * Increase/decrease loop var
  		 */
  		if (stmt->reverse)
! 			var->value -= by_value;
  		else
! 			var->value += by_value;
  	}
  
  	/*
diff -rcEib pgsql-8.2dev/src/pl/plpgsql/src/pl_funcs.c pgsql-8.2fori/src/pl/plpgsql/src/pl_funcs.c
*** pgsql-8.2dev/src/pl/plpgsql/src/pl_funcs.c	2006-05-01 08:49:39.000000000 -0500
--- pgsql-8.2fori/src/pl/plpgsql/src/pl_funcs.c	2006-05-05 17:48:53.000000000 -0500
***************
*** 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);
diff -rcEib pgsql-8.2dev/src/pl/plpgsql/src/plpgsql.h pgsql-8.2fori/src/pl/plpgsql/src/plpgsql.h
*** pgsql-8.2dev/src/pl/plpgsql/src/plpgsql.h	2006-05-01 08:49:39.000000000 -0500
--- pgsql-8.2fori/src/pl/plpgsql/src/plpgsql.h	2006-04-30 09:49:39.000000000 -0500
***************
*** 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;
diff -rcEib pgsql-8.2dev/src/pl/plpgsql/src/scan.l pgsql-8.2fori/src/pl/plpgsql/src/scan.l
*** pgsql-8.2dev/src/pl/plpgsql/src/scan.l	2006-05-01 08:49:39.000000000 -0500
--- pgsql-8.2fori/src/pl/plpgsql/src/scan.l	2006-04-30 09:49:25.000000000 -0500
***************
*** 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;		}
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to