2009/9/28 John Naylor <jcnay...@gmail.com>:
> Pavel,
>
> It looks good. My last email didn't go to -hackers, since I wasn't
> subscribed. I had to resend to -hackers so there will be a link for
> the commitfest page. I think you might have to resend your latest
> patch to the list. Sorry!

nothing, patch attached

Pavel

>
> In any case, I will say it's ready for commiter.
>
> Thanks,
> John
>
> On Mon, Sep 28, 2009 at 2:07 AM, Pavel Stehule <pavel.steh...@gmail.com> 
> wrote:
>> Hello
>>
>> I am sending actualised patch as per John comment.
>>
>> regards
>> Pavel Stehule
>>
>> 2009/9/26 John Naylor <jcnay...@gmail.com>:
>>> Hi,
>>>
>>> Sorry, I didn't notice the attachment on Pavel's email, otherwise I
>>> would have done this sooner! :)
>>>
>>> I just applied and tested the new patch. Everything works great.
>>>
>>> The only thing I would change now is some of the comments.
>>>
>>> 1). On line 289, one of the regression test comments got copied:
>>>
>>> +   move forward in c;                --should be at '5'
>>>
>>> change to:
>>>
>>> +   move forward in c;                --should be at '1'
>>>
>>> 2). Lines 79/80:
>>>
>>> +                                                                        
>>> errmsg("statement FETCH returns more rows."),
>>> +                                                                        
>>> errhint("Multirows fetch are not allowed in PL/pgSQL.")));
>>>
>>> This might sound better as "statement FETCH returns multiple rows.",
>>> and "Multirow FETCH is not allowed in PL/pgSQL."
>>>
>>> Everything else looks good to me.
>>> John
>>>
>>>
>>>> Hi Selena and John,
>>>>
>>>> Pavel's latest patch seems to address all the issues you raised in
>>>> your initial review.  Do you have any comments on this new revision?
>>>> If you're happy that your issues have been resolved, please mark the
>>>> patch as Ready for Committer.
>>>>
>>>> Cheers,
>>>> BJ
>>>>
>>>
>>
>
*** ./doc/src/sgml/plpgsql.sgml.orig	2009-09-28 09:38:55.711469112 +0200
--- ./doc/src/sgml/plpgsql.sgml	2009-09-28 09:39:24.613468923 +0200
***************
*** 2656,2670 ****
  
      <para>
       The options for the <replaceable>direction</replaceable> clause are
!      the same as for <command>FETCH</>, namely
       <literal>NEXT</>,
       <literal>PRIOR</>,
       <literal>FIRST</>,
       <literal>LAST</>,
       <literal>ABSOLUTE</> <replaceable>count</replaceable>,
       <literal>RELATIVE</> <replaceable>count</replaceable>,
!      <literal>FORWARD</>, or
!      <literal>BACKWARD</>.
       Omitting <replaceable>direction</replaceable> is the same
       as specifying <literal>NEXT</>.
       <replaceable>direction</replaceable> values that require moving
--- 2656,2670 ----
  
      <para>
       The options for the <replaceable>direction</replaceable> clause are
!      similar to <command>FETCH</>, namely
       <literal>NEXT</>,
       <literal>PRIOR</>,
       <literal>FIRST</>,
       <literal>LAST</>,
       <literal>ABSOLUTE</> <replaceable>count</replaceable>,
       <literal>RELATIVE</> <replaceable>count</replaceable>,
!      <literal>FORWARD</> <optional> <replaceable>count</replaceable> | <literal>ALL</> </optional>, or
!      <literal>BACKWARD</> <optional> <replaceable>count</replaceable> | <literal>ALL</> </optional>.
       Omitting <replaceable>direction</replaceable> is the same
       as specifying <literal>NEXT</>.
       <replaceable>direction</replaceable> values that require moving
***************
*** 2678,2683 ****
--- 2678,2684 ----
  MOVE curs1;
  MOVE LAST FROM curs3;
  MOVE RELATIVE -2 FROM curs4;
+ MOVE FORWARD 2 FROM curs4;
  </programlisting>
         </para>
       </sect3>
*** ./src/pl/plpgsql/src/gram.y.orig	2009-09-28 09:38:55.713470217 +0200
--- ./src/pl/plpgsql/src/gram.y	2009-09-28 11:00:53.811467762 +0200
***************
*** 72,77 ****
--- 72,79 ----
  										  int until, const char *expected);
  static List				*read_raise_options(void);
  
+ static PLpgSQL_stmt_fetch *complete_direction(PLpgSQL_stmt_fetch *fetch, bool *check_FROM);
+ 
  %}
  
  %expect 0
***************
*** 178,183 ****
--- 180,186 ----
  		 * Keyword tokens
  		 */
  %token	K_ALIAS
+ %token	K_ALL
  %token	K_ASSIGN
  %token	K_BEGIN
  %token	K_BY
***************
*** 1621,1626 ****
--- 1624,1635 ----
  
  						if (yylex() != ';')
  							yyerror("syntax error");
+ 							
+ 						if (fetch->returns_multiple_rows)
+ 							ereport(ERROR,
+ 									(errcode(ERRCODE_SYNTAX_ERROR),
+ 									 errmsg("statement FETCH returns multiple rows"),
+ 									 errhint("Multirow FETCH is not allowed in PL/pgSQL.")));
  
  						fetch->lineno = $2;
  						fetch->rec		= rec;
***************
*** 2252,2257 ****
--- 2261,2271 ----
  }
  
  
+ /*
+  * Read FETCH or MOVE statement direction. By default, 
+  * cursor will only move one row. To MOVE more than one row
+  * at a time see complete_direction(). 
+  */
  static PLpgSQL_stmt_fetch *
  read_fetch_direction(void)
  {
***************
*** 2269,2274 ****
--- 2283,2289 ----
  	fetch->direction = FETCH_FORWARD;
  	fetch->how_many  = 1;
  	fetch->expr      = NULL;
+ 	fetch->returns_multiple_rows = false;
  
  	/*
  	 * Most of the direction keywords are not plpgsql keywords, so we
***************
*** 2313,2323 ****
  	}
  	else if (pg_strcasecmp(yytext, "forward") == 0)
  	{
! 		/* use defaults */
  	}
  	else if (pg_strcasecmp(yytext, "backward") == 0)
  	{
  		fetch->direction = FETCH_BACKWARD;
  	}
  	else if (tok != T_SCALAR)
  	{
--- 2328,2339 ----
  	}
  	else if (pg_strcasecmp(yytext, "forward") == 0)
  	{
! 		fetch = complete_direction(fetch, &check_FROM);
  	}
  	else if (pg_strcasecmp(yytext, "backward") == 0)
  	{
  		fetch->direction = FETCH_BACKWARD;
+ 		fetch = complete_direction(fetch, &check_FROM);
  	}
  	else if (tok != T_SCALAR)
  	{
***************
*** 2346,2351 ****
--- 2362,2415 ----
  }
  
  
+ /*
+  * Allows directions:
+  *   FORWARD expr,  FORWARD ALL,  FORWARD
+  *   BACKWARD expr, BACKWARD ALL, BACKWARD
+  *
+  * so plpgsql should fully support PostgreSQL's MOVE statement.
+  */
+ static PLpgSQL_stmt_fetch *
+ complete_direction(PLpgSQL_stmt_fetch *fetch,  bool *check_FROM)
+ {
+ 	int	tok;
+ 
+ 	tok = yylex();
+ 	if (tok == K_FROM || tok == K_IN)
+ 	{
+ 		*check_FROM = false;
+ 		
+ 		return fetch;
+ 	}
+ 	
+ 	if (tok == K_ALL)
+ 	{
+ 		fetch->how_many = fetch->direction == FETCH_FORWARD ? -1 : 0;
+ 		fetch->direction = FETCH_ABSOLUTE;
+ 		fetch->returns_multiple_rows = true;
+ 		*check_FROM = true;
+ 		
+ 		return fetch;
+ 	}
+ 
+ 	plpgsql_push_back_token(tok);
+ 	fetch->expr = read_sql_expression2(K_FROM, K_IN,
+ 							   "FROM or IN",
+ 							   NULL);
+ 							   
+ 	/*
+ 	 * We don't allow multiple rows in PL/pgSQL's FETCH statement. This
+ 	 * limit is enforced by syntax. Only for sure one row directions
+ 	 * are allowed. Because result of expr should be greather than
+ 	 * one, we expect possible multiple rows and disable this direction
+ 	 * when current statement is FETCH statement.
+ 	 */   
+ 	fetch->returns_multiple_rows = true;
+ 	*check_FROM = false;
+ 	
+ 	return fetch;
+ }
+ 
  static PLpgSQL_stmt *
  make_return_stmt(int lineno)
  {
*** ./src/pl/plpgsql/src/plpgsql.h.orig	2009-09-28 09:38:55.715469366 +0200
--- ./src/pl/plpgsql/src/plpgsql.h	2009-09-28 09:39:24.653469785 +0200
***************
*** 520,525 ****
--- 520,526 ----
  	int			how_many;		/* count, if constant (expr is NULL) */
  	PLpgSQL_expr *expr;			/* count, if expression */
  	bool		is_move;		/* is this a fetch or move? */
+ 	bool		returns_multiple_rows;		/* returns more than one rows? */
  } PLpgSQL_stmt_fetch;
  
  
*** ./src/test/regress/expected/plpgsql.out.orig	2009-09-28 09:38:55.719468503 +0200
--- ./src/test/regress/expected/plpgsql.out	2009-09-28 09:39:24.684468331 +0200
***************
*** 3027,3032 ****
--- 3027,3054 ----
  
  create or replace function sc_test() returns setof integer as $$
  declare
+   c refcursor;
+   x integer;
+ begin
+   open c scroll for execute 'select f1 from int4_tbl';
+   fetch last from c into x;
+   while found loop
+     return next x;
+     move backward 2 from c;
+     fetch relative -1 from c into x;
+   end loop;
+   close c;
+ end;
+ $$ language plpgsql;
+ select * from sc_test();
+    sc_test   
+ -------------
+  -2147483647
+       123456
+ (2 rows)
+ 
+ create or replace function sc_test() returns setof integer as $$
+ declare
    c cursor for select * from generate_series(1, 10);
    x integer;
  begin
***************
*** 3052,3057 ****
--- 3074,3149 ----
         9
  (3 rows)
  
+ create or replace function sc_test() returns setof integer as $$
+ declare
+   c cursor for select * from generate_series(1, 10);
+   x integer;
+ begin
+   open c;
+   loop
+       move forward 2 in c;
+       if not found then
+           exit;
+       end if;
+       fetch next from c into x;
+       if found then
+           return next x;
+       end if;
+   end loop;
+   close c;
+ end;
+ $$ language plpgsql;
+ select * from sc_test();
+  sc_test 
+ ---------
+        3
+        6
+        9
+ (3 rows)
+ 
+ drop function sc_test();
+ create or replace function sc_test() returns integer
+ as $$
+ declare
+   c cursor for select * from generate_series(1, 10);
+   x integer;
+ begin
+   open c;
+   move forward in c;                --should be at '5'
+   fetch relative 0 from c into x;     --fetch current position
+   if found then
+     return x;
+   end if;
+   close c;
+ end;
+ $$ language plpgsql;
+ select sc_test();
+  sc_test 
+ ---------
+        1
+ (1 row)
+ 
+ create or replace function sc_test() returns integer
+ as $$
+ declare
+   c cursor for select * from generate_series(1, 10);
+   x integer;
+ begin
+   open c;
+   move forward 5 in c;                --should be at '5'
+   fetch relative 0 from c into x;     --fetch current position
+   if found then
+     return x;
+   end if;
+   close c;
+ end;
+ $$ language plpgsql;
+ select sc_test();
+  sc_test 
+ ---------
+        5
+ (1 row)
+ 
  drop function sc_test();
  -- test qualified variable names
  create function pl_qual_names (param1 int) returns void as $$
*** ./src/test/regress/sql/plpgsql.sql.orig	2009-09-28 09:38:55.721469049 +0200
--- ./src/test/regress/sql/plpgsql.sql	2009-09-28 10:58:39.991468013 +0200
***************
*** 2513,2518 ****
--- 2513,2536 ----
  
  create or replace function sc_test() returns setof integer as $$
  declare
+   c refcursor;
+   x integer;
+ begin
+   open c scroll for execute 'select f1 from int4_tbl';
+   fetch last from c into x;
+   while found loop
+     return next x;
+     move backward 2 from c;
+     fetch relative -1 from c into x;
+   end loop;
+   close c;
+ end;
+ $$ language plpgsql;
+ 
+ select * from sc_test();
+ 
+ create or replace function sc_test() returns setof integer as $$
+ declare
    c cursor for select * from generate_series(1, 10);
    x integer;
  begin
***************
*** 2533,2540 ****
--- 2551,2619 ----
  
  select * from sc_test();
  
+ create or replace function sc_test() returns setof integer as $$
+ declare
+   c cursor for select * from generate_series(1, 10);
+   x integer;
+ begin
+   open c;
+   loop
+       move forward 2 in c;
+       if not found then
+           exit;
+       end if;
+       fetch next from c into x;
+       if found then
+           return next x;
+       end if;
+   end loop;
+   close c;
+ end;
+ $$ language plpgsql;
+ 
+ select * from sc_test();
+ 
+ drop function sc_test();
+ 
+ create or replace function sc_test() returns integer
+ as $$
+ declare
+   c cursor for select * from generate_series(1, 10);
+   x integer;
+ begin
+   open c;
+   move forward in c;                --should be at '1'
+   fetch relative 0 from c into x;     --fetch current position
+   if found then
+     return x;
+   end if;
+   close c;
+ end;
+ $$ language plpgsql;
+ 
+ select sc_test();
+ 
+ create or replace function sc_test() returns integer
+ as $$
+ declare
+   c cursor for select * from generate_series(1, 10);
+   x integer;
+ begin
+   open c;
+   move forward 5 in c;                --should be at '5'
+   fetch relative 0 from c into x;     --fetch current position
+   if found then
+     return x;
+   end if;
+   close c;
+ end;
+ $$ language plpgsql;
+ 
+ select sc_test();
+ 
  drop function sc_test();
  
+ 
  -- test qualified variable names
  
  create function pl_qual_names (param1 int) returns void as $$
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to