Re: [PATCHES] Fwd: WIP: CASE statement for PL/pgSQL

2008-03-31 Thread Pavel Stehule
Hello

On 31/03/2008, Andrew Dunstan <[EMAIL PROTECTED]> wrote:
>
>
>  Pavel Stehule wrote:
>
> > correct queue
> >
> > Hello
> >
> >  I finished this patch.
> >
> >  Proposal:
> http://archives.postgresql.org/pgsql-hackers/2008-01/msg00696.php
> >
> >  It's compatible with PL/SQL (Oracle) and SQL/PSM (ANSI).
> >
> >
> >
>
>  At the very least this patch is missing documentation and regression tests.
>

yes, I know. Regress tests are not problem. This patch is only WIP and
I'll to update this patch after commiting EXECUTE USING patch. But
somebody maybe can comment this patch now, and I can save some time
later.

Pavel

>  cheers
>
>  andrew
>


>
>

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] Fwd: WIP: CASE statement for PL/pgSQL

2008-03-31 Thread Andrew Dunstan



Pavel Stehule wrote:

correct queue

Hello

 I finished this patch.

 Proposal: http://archives.postgresql.org/pgsql-hackers/2008-01/msg00696.php

 It's compatible with PL/SQL (Oracle) and SQL/PSM (ANSI).

 
  


At the very least this patch is missing documentation and regression tests.

cheers

andrew



--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


[PATCHES] Fwd: WIP: CASE statement for PL/pgSQL

2008-03-31 Thread Pavel Stehule
correct queue

Hello

 I finished this patch.

 Proposal: http://archives.postgresql.org/pgsql-hackers/2008-01/msg00696.php

 It's compatible with PL/SQL (Oracle) and SQL/PSM (ANSI).

 CASE statements is parsed and transformed to CASE expression and
 statements paths. Result of CASE expression is used as index to array
 of statements paths. It's fast but I have to once time reparse SQL
 queries - it generate about 150 lines code, because I need to get all
 parameter's positions. It's one disadvantage. On second hand, this
 statement needs only one expression evaluation.

 Sample:

 CREATE OR REPLACE FUNCTION foo(int)
 RETURNS void AS $$
 BEGIN
  CASE $1
  WHEN 1,2,3 THEN
 RAISE NOTICE '1,2';
 RAISE NOTICE '3';
  WHEN 4 THEN
 RAISE NOTICE '4';
  ELSE
 RAISE NOTICE 'other than 1,2,3,4';
  END CASE;
  RETURN;
 END;
 $$ LANGUAGE plpgsql;

 This statement is transformated to:
 three statement paths:
 [0]
 RAISE NOTICE 'other than 1,2,3,4';
 [1]
 RAISE NOTICE '1,2';
 RAISE NOTICE '3';
 [2]
 RAISE NOTICE '4';

 and case expression
 CASE $1
  WHEN 1 THEN 1
  WHEN 2 THEN 1
  WHEN 3 THEN 1
  WHEN 4 THEN 2
 END;

 When result is NULL then it uses 0 path.

 Questions:
 a) is possible to use SQL scanner? Now, scanner isn't directly used everywhere.

 any notes and comments are welcome

 Regards

Pavel Stehule
*** ./gram.y.orig	2008-03-28 17:33:45.0 +0100
--- ./gram.y	2008-03-31 13:46:08.0 +0200
***
*** 15,23 
   */
  
  #include "plpgsql.h"
- 
  #include "parser/parser.h"
! 
  
  static PLpgSQL_expr		*read_sql_construct(int until,
  			int until2,
--- 15,24 
   */
  
  #include "plpgsql.h"
  #include "parser/parser.h"
! #include 
! #include 
! #include 
  
  static PLpgSQL_expr		*read_sql_construct(int until,
  			int until2,
***
*** 46,52 
  static	char			*check_label(const char *yytxt);
  static	void			 check_labels(const char *start_label,
  	  const char *end_label);
! 
  %}
  
  %name-prefix="plpgsql_yy"
--- 47,54 
  static	char			*check_label(const char *yytxt);
  static	void			 check_labels(const char *start_label,
  	  const char *end_label);
! static PLpgSQL_stmt	*make_case(int lineno, PLpgSQL_expr *case_expr, 
! List *when_clause_list, List *else_stmts);
  %}
  
  %name-prefix="plpgsql_yy"
***
*** 79,84 
--- 81,91 
  			char *end_label;
  			List *stmts;
  		}		loop_body;
+ 		struct
+ 		{	
+ 			List *expr_list;
+ 			PLpgSQL_expr	*expr;
+ 		}		when_expr;
  		List	*list;
  		PLpgSQL_type			*dtype;
  		PLpgSQL_datum			*scalar;	/* a VAR, RECFIELD, or TRIGARG */
***
*** 95,100 
--- 102,108 
  		PLpgSQL_nsitem			*nsitem;
  		PLpgSQL_diag_item		*diagitem;
  		PLpgSQL_stmt_fetch		*fetch;
+ 		PLpgSQL_when_clause		*whenclause;
  }
  
  %type  decl_sect
***
*** 109,115 
  %type 		decl_stmts decl_stmt
  
  %type 	expr_until_semi expr_until_rightbracket
! %type 	expr_until_then expr_until_loop
  %type 	opt_exitcond
  
  %type 	assign_var
--- 117,123 
  %type 		decl_stmts decl_stmt
  
  %type 	expr_until_semi expr_until_rightbracket
! %type 	expr_until_then expr_until_loop opt_expr_until_when
  %type 	opt_exitcond
  
  %type 	assign_var
***
*** 128,133 
--- 136,145 
  %type 	stmt_return stmt_raise stmt_execsql stmt_execsql_insert
  %type 	stmt_dynexecute stmt_for stmt_perform stmt_getdiag
  %type 	stmt_open stmt_fetch stmt_move stmt_close stmt_null
+ %type 	stmt_case
+ %type  case_when_expr
+ %type  when_clause
+ %type 	when_clause_list opt_case_default
  
  %type 	proc_exceptions
  %type  exception_sect
***
*** 154,159 
--- 166,172 
  %token	K_ASSIGN
  %token	K_BEGIN
  %token	K_BY
+ %token	K_CASE
  %token	K_CLOSE
  %token	K_CONSTANT
  %token	K_CONTINUE
***
*** 611,616 
--- 624,631 
  		{ $$ = $1; }
  | stmt_if
  		{ $$ = $1; }
+ | stmt_case
+ 		{ $$ = $1; }
  | stmt_loop
  		{ $$ = $1; }
  | stmt_while
***
*** 809,814 
--- 824,869 
  	}
  ;
  
+ stmt_case		: K_CASE lno opt_expr_until_when when_clause_list opt_case_default K_END K_CASE ';'
+ 	{
+ 		$$ = make_case($2, $3, $4, $5);
+ 	}
+ ;
+ 
+ opt_case_default	:
+ 	{
+ 		$$ = NIL;
+ 	}
+ | K_ELSE proc_stmts
+ 	{
+ 		$$ = $2;
+ 	}
+ ;
+ 
+ when_clause_list	: when_clause_list when_clause
+ 	{
+ 		$$ = lappend($1, $2);
+ 	}
+ | when_clause
+ 	{
+ 		$$ = list_make1($1);
+ 	}
+ ;
+ 
+ when_clause		: K_WHEN lno case_when_expr proc_stmts
+ 	{
+ 		PLpgSQL_when_clause *new = palloc0(sizeof(PLpgSQL_when_clause));
+ 
+ 		new->cmd_type		= PLPGSQL_STMT_WHEN_CLAUSE;
+ 		new->lineno	= $2;
+ 		new->when_expr	= $3.expr;
+ 		new->when_expr_list	= $3.expr_list;
+ 		new->then_stmts	= $4;
+ 
+ 		$$ = new;
+ 	}
+ ;