Hi,

I want to learn, how the pl/plsql-parser/compiler works. Therefore I planned 
to implement a simple ELSIF, like oracle does.

I added the following K_ELSIF branch to gram.y, in the hope that, when ELSIF 
is parsed, simply another if-structure in inserted.

---------------------------------------------------------
stmt_else		:
	{
	    PLpgSQL_stmts	*new;
		
		new = malloc(sizeof(PLpgSQL_stmts));
		memset(new, 0, sizeof(PLpgSQL_stmts));
		$$ = new;
		elog(NOTICE, "empty ELSE detected");
	}
	| K_ELSIF expr_until_then proc_sect stmt_else
	{
		PLpgSQL_stmt_if *new;
		elog(NOTICE, "ELSIF detected");
		new = malloc(sizeof(PLpgSQL_stmt_if));
		memset(new, 0, sizeof(PLpgSQL_stmt_if));
		new->cmd_type	= PLPGSQL_STMT_IF;
		// new->lineno		= $2;
		new->cond		= $2;
		new->true_body	= $3;
		new->false_body = $4;

		$$ = (PLpgSQL_stmts *)new;	

					
	}
	| K_ELSE proc_sect
	{
   	        $$ = $2;				
   	        elog(NOTICE, "ELSE detected (%s)", 
		 strdup(yytext));
	}
	;
--------------------------------------------------------------

A testprocedure, which looks like that:
--------------------------------------------------------------

DECLARE
    iPar1PI ALIAS FOR $1;
    iTmp    integer;
    iResult varchar;

BEGIN

    iTmp = iPar1PI;
    
    raise notice '1.0';

    if iTmp IS NULL then
        raise notice '2.0';
        iResult = 'Echt NULL';

    else
        if iTmp = 0 then
            raise notice '2.1.0';
            iResult = 'Null (0)';

        elsif (iTmp < 0) THEN
            raise notice '2.1.1';
            iResult = 'Negativ';

        elsif (iTmp > 0) THEN
            raise notice '2.1.2';
            iResult = 'Positiv';

        else
            raise notice '2.1.3';
            iResult = 'Gibts nicht!';
        end if;
    end if;
        
    raise notice '3.0';

    return iResult;
END;
--------------------------------------------------------------

is dumped in this way ...

--------------------------------------------------------------
Execution tree of successfully compiled PL/pgSQL function kr_test:
 
Functions data area:
    entry 0: VAR $1               type int4 (typoid 23) atttypmod -1
    entry 1: VAR found            type bool (typoid 16) atttypmod -1
    entry 2: VAR itmp             type int4 (typoid 23) atttypmod -1
    entry 3: VAR iresult          type varchar (typoid 1043) atttypmod -1
 
Functions statements:
  8:BLOCK <<*unnamed*>>
 10:  ASSIGN var 2 := 'SELECT   $1  {$1=0}'
 12:  RAISE ''1.0''
 14:  IF 'SELECT   $1  IS NULL {$1=2}' THEN
 15:    RAISE ''2.0''
 16:    ASSIGN var 3 := 'SELECT  'Echt NULL''
      ELSE
 19:    IF 'SELECT   $1  = 0 {$1=2}' THEN
 20:      RAISE ''2.1.0''
 21:      ASSIGN var 3 := 'SELECT  'Null (0)''
        ELSE
        ENDIF
      ENDIF
 37:  RAISE ''3.0''
 39:  RETURN 'SELECT   $1  {$1=3}'
    END -- *unnamed*
 
End of execution tree of function kr_test
--------------------------------------------------------------

So my question is: Why does my inserted 
PLpgSQL_stmt_if *new;
is not executed, because I do it in the same way like stmt_if does?

Who can halp me (Maybe Jan??)

Regards, Klaus

Wed, 16 May 2001 12:29:16 +0200
Klaus Reger <K.Reger@gmx.de>
Grammar-problems with pl/pgsql in gram.y
Klaus Reger wrote:
> Hi,
>
> I want to learn, how the pl/plsql-parser/compiler works. Therefore I planned
> to implement a simple ELSIF, like oracle does.
>
> I added the following K_ELSIF branch to gram.y, in the hope that, when ELSIF
> is parsed, simply another if-structure in inserted.
>
> ---------------------------------------------------------
> stmt_else         :
>    {
>        PLpgSQL_stmts   *new;
>
>         new = malloc(sizeof(PLpgSQL_stmts));
>         memset(new, 0, sizeof(PLpgSQL_stmts));
>         $$ = new;
>         elog(NOTICE, "empty ELSE detected");
>    }
>    | K_ELSIF expr_until_then proc_sect stmt_else
>    {
>         PLpgSQL_stmt_if *new;
>         elog(NOTICE, "ELSIF detected");
>         new = malloc(sizeof(PLpgSQL_stmt_if));
>         memset(new, 0, sizeof(PLpgSQL_stmt_if));
>         new->cmd_type  = PLPGSQL_STMT_IF;
>         // new->lineno      = $2;
>         new->cond      = $2;
>         new->true_body = $3;
>         new->false_body = $4;
>
>         $$ = (PLpgSQL_stmts *)new;

    Here it is. stmt_else is defined as type <stmts>, not <stmt>.
    The PLpgSQL_stmt_if struct has  a  condition  query  and  two
    statement lists (type <stmts>). You're trying to put a single
    statement into the else part instead of a list of statements.

    Maybe   it'll   work   if   you   surround  it  with  another
    PLpgSQL_stmts struct where your new  PLpgSQL_stmt_if  is  the
    only  statement  in it's list.  Since I have some bigger work
    outstanding for PL/pgSQL, send the resulting  patch  (if  you
    get it to work) directly to me.


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


Wed, 16 May 2001 10:10:41 -0400 (EDT)
Jan Wieck <JanWieck@Yahoo.com>
Re: Grammar-problems with pl/pgsql in gram.y
Am Mittwoch, 16. Mai 2001 16:10 schrieb Jan Wieck:
>     Here it is. stmt_else is defined as type <stmts>, not <stmt>.
>     The PLpgSQL_stmt_if struct has  a  condition  query  and  two
>     statement lists (type <stmts>). You're trying to put a single
>     statement into the else part instead of a list of statements.
Thank you for the hint! That was it.

>     Maybe   it'll   work   if   you   surround  it  with  another
>     PLpgSQL_stmts struct where your new  PLpgSQL_stmt_if  is  the
>     only  statement  in it's list.  Since I have some bigger work
>     outstanding for PL/pgSQL, send the resulting  patch  (if  you
>     get it to work) directly to me.
The patch follows this message. May you tell me what kind of work it is, 
cause I'm so curous :-). By the way, the next thing I try is a
EXCEPTION WHEN OTHER-clause, like in Oracle. Let's look if I'm successful.

Ciao, Klaus

----------------------------------------------------------------------------

diff -Naurb src/gram.y src.elsif/gram.y
--- src/gram.y	Wed May 16 18:00:53 2001
+++ src.elsif/gram.y	Wed May 16 17:39:19 2001
@@ -147,6 +147,7 @@
 %token	K_DIAGNOSTICS
 %token	K_DOTDOT
 %token	K_ELSE
+%token	K_ELSIF
 %token	K_END
 %token	K_EXCEPTION
 %token	K_EXECUTE
@@ -544,6 +545,7 @@
 								new->stmts[0] = (struct PLpgSQL_stmt *)$1;
 
 								$$ = new;
+
 						}
 				;
 
@@ -721,8 +723,53 @@
 							memset(new, 0, sizeof(PLpgSQL_stmts));
 							$$ = new;
 					}
+				| K_ELSIF lno expr_until_then proc_sect stmt_else
+					{
+					  /*
+					   * Translate the structure:	   into:
+					   *
+					   * IF c1 THEN					   IF c1 THEN		 
+					   *	 ...						   ...				 
+					   * ELSIF c2 THEN				   ELSE 
+					   *								   IF c2 THEN	
+					   *	 ...							   ...				 
+					   * ELSE							   ELSE				 
+					   *	 ...							   ...				 
+					   * END IF							   END IF			 
+					   *							   END IF
+					   * 
+					   */
+
+						PLpgSQL_stmts	*new;
+						PLpgSQL_stmt_if *new_if;
+
+						/* first create a new if-statement */
+						new_if = malloc(sizeof(PLpgSQL_stmt_if));
+						memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
+
+						new_if->cmd_type	= PLPGSQL_STMT_IF;
+						new_if->lineno		= $2;
+						new_if->cond		= $3;
+						new_if->true_body	= $4;
+						new_if->false_body	= $5;
+						
+						/* this is a 'container' for the if-statement */
+						new = malloc(sizeof(PLpgSQL_stmts));
+						memset(new, 0, sizeof(PLpgSQL_stmts));
+						
+						new->stmts_alloc = 64;
+						new->stmts_used	 = 1;
+						new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
+						new->stmts[0] = (struct PLpgSQL_stmt *)new_if;
+
+						$$ = new;
+						
+					}
+
 				| K_ELSE proc_sect
-					{ $$ = $2; }
+					{
+						$$ = $2;				
+					}
 				;
 
 stmt_loop		: opt_label K_LOOP lno loop_body
@@ -1271,7 +1318,6 @@
 				break;
 		}
 	}
-
 	expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
 	expr->dtype			= PLPGSQL_DTYPE_EXPR;
 	expr->query			= strdup(plpgsql_dstring_get(&ds));
diff -Naurb src/scan.l src.elsif/scan.l
--- src/scan.l	Wed May 16 18:01:36 2001
+++ src.elsif/scan.l	Tue May 15 12:49:43 2001
@@ -99,6 +99,7 @@
 default			{ return K_DEFAULT;			}
 diagnostics		{ return K_DIAGNOSTICS;		}
 else			{ return K_ELSE;			}
+elsif           { return K_ELSIF;           }
 end				{ return K_END;				}
 exception		{ return K_EXCEPTION;		}
 execute			{ return K_EXECUTE;			}

Wed, 16 May 2001 18:57:13 +0200
Klaus Reger <K.Reger@gmx.de>
Re: Grammar-problems with pl/pgsql in gram.y
Klaus Reger wrote:
> Am Mittwoch, 16. Mai 2001 16:10 schrieb Jan Wieck:
> >     Here it is. stmt_else is defined as type <stmts>, not <stmt>.
> >     The PLpgSQL_stmt_if struct has  a  condition  query  and  two
> >     statement lists (type <stmts>). You're trying to put a single
> >     statement into the else part instead of a list of statements.
> Thank you for the hint! That was it.
>
> >     Maybe   it'll   work   if   you   surround  it  with  another
> >     PLpgSQL_stmts struct where your new  PLpgSQL_stmt_if  is  the
> >     only  statement  in it's list.  Since I have some bigger work
> >     outstanding for PL/pgSQL, send the resulting  patch  (if  you
> >     get it to work) directly to me.
> The patch follows this message. May you tell me what kind of work it is,
> cause I'm so curous :-). By the way, the next thing I try is a
> EXCEPTION WHEN OTHER-clause, like in Oracle. Let's look if I'm successful.

    complete CURSOR support. With some enhancements in SPI plus a
    little fix in ProcessPortalFetch() I have up to now

    Explicit CURSOR:

        DECLARE
            <cursor_name> CURSOR [(<arg> <type> [, ...])]
                          IS <select_statement>;

            The select statement can  use  any  so  far  declared
            variable  or  functions  arguments in addition to the
            optional cursor arguments. These will be evaluated at
            OPEN time.

            There  is  a  new  datatype  'refcursor'.  The  above
            declaration will create a local variable of that type
            with  a  default "value" of the variables name.  This
            "value" will be used  for  the  global  cursors  name
            during OPEN.

        BEGIN
            OPEN <cursor_name> [(<expression> [, ...])];

            FETCH <cursor_name>
                INTO {<record> | <row> | <var> [, ...]};

            CLOSE <cursor_name>;

            The  FETCH command sets the global FOUND variable, so
            a typical loop over a resultset looks like

                LOOP
                    FETCH mycur INTO myrec;
                    EXIT WHEN NOT FOUND;
                    -- Process the row
                END LOOP;

    Reference CURSOR:

        DECLARE
            <cursor_name> REFCURSOR [ := <string> ];

        BEGIN
            OPEN <cursor_name> FOR <select_statement>;

            OPEN <cursor_name> FOR EXECUTE <string>;

    The new datatype 'refcursor' can be used to pass  any  cursor
    around  between  functions  and the application. Cursors used
    inside of functions only don't need  transaction  blocks.  Of
    course, they'll not survive the current transactions end, but
    if funcA() creates a cursor and then  calls  funcB(refcursor)
    with it, there does not need to be a transaction block around
    it.

    What I need to do now is fixing some memory allocation issues
    in  PL/pgSQL  and  move  FOR  loops  to  use implicit cursors
    internally. Your patch looks like it  doesn't  conflict  with
    any of my work. I'll commit it soon.

    For the EXCEPTIONS thing, well that's another issue. We could
    of course simulate/generate some of the exceptions  like  "no
    data found" and the other one I forgot (telling that a SELECT
    INTO returned multiple  results).   But  we  cannot  catch  a
    duplicate  key  error,  a  division  by zero or a referential
    integrity violation, because when it happens a  statement  is
    half way done and the only way to cleanup is rolling back the
    entire transaction (for now, Vadim is working on savepoints).
    So I suggest you don't spend much of your time before we have
    them.


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


Wed, 16 May 2001 15:29:40 -0400 (EDT)
Jan Wieck <JanWieck@Yahoo.com>
Re: Grammar-problems with pl/pgsql in gram.y
Am Mittwoch, 16. Mai 2001 21:29 schrieb Jan Wieck:
>     For the EXCEPTIONS thing, well that's another issue. We could
>     of course simulate/generate some of the exceptions  like  "no
>     data found" and the other one I forgot (telling that a SELECT
>     INTO returned multiple  results).   But  we  cannot  catch  a
>     duplicate  key  error,  a  division  by zero or a referential
>     integrity violation, because when it happens a  statement  is
>     half way done and the only way to cleanup is rolling back the
>     entire transaction (for now, Vadim is working on savepoints).
>     So I suggest you don't spend much of your time before we have
>     them.
OK, I understand. For the beginning I only would like to have a possibility, 
to catch any exception and create my own error handling, ignoring any 
transaction-stuff. Because I have to port Procedures from Oracle to 
PostgreSQL, I am looking, to imitate the way Oracle takes.

As I understand with my actual knowledge, this would mean, that every(!) call 
of elog, which terminates the process, has to be caught. But this seems to 
great for a new Postgres-hacker, like I am. Or do you see any other 
possibility (maybe extending PLpgSQL_execstate)?

CU, Klaus

Fri, 18 May 2001 15:31:35 +0200
Klaus Reger <K.Reger@gmx.de>
Re: Grammar-problems with pl/pgsql in gram.y
Klaus Reger wrote:
> Am Mittwoch, 16. Mai 2001 21:29 schrieb Jan Wieck:
> >     For the EXCEPTIONS thing, well that's another issue. We could
> >     of course simulate/generate some of the exceptions  like  "no
> >     data found" and the other one I forgot (telling that a SELECT
> >     INTO returned multiple  results).   But  we  cannot  catch  a
> >     duplicate  key  error,  a  division  by zero or a referential
> >     integrity violation, because when it happens a  statement  is
> >     half way done and the only way to cleanup is rolling back the
> >     entire transaction (for now, Vadim is working on savepoints).
> >     So I suggest you don't spend much of your time before we have
> >     them.
> OK, I understand. For the beginning I only would like to have a possibility,
> to catch any exception and create my own error handling, ignoring any
> transaction-stuff. Because I have to port Procedures from Oracle to
> PostgreSQL, I am looking, to imitate the way Oracle takes.
>
> As I understand with my actual knowledge, this would mean, that every(!) call
> of elog, which terminates the process, has to be caught. But this seems to
> great for a new Postgres-hacker, like I am. Or do you see any other
> possibility (maybe extending PLpgSQL_execstate)?

    Every(!)  call  to  elog  with  ERROR  (or more severe) level
    causes finally a longjump()  back  into  the  tcop  mainloop.
    PL/pgSQL  and PL/Tcl do catch it - PL/pgSQL to tell something
    on  DEBUG  level  and  PL/Tcl  mainly  to  unwind   the   Tcl
    interpreters   call   stack.   But   the  backend  is  in  an
    inconsistent state at that time, and any subsequent  call  to
    access  methods  could  cause  unpredictable  results  up  to
    complete database corruption. There is no other way right now
    than to go ahead and continue with transaction abort.

    Imitation of the Oracle way is something many ppl around here
    would appreciate, but not  at  the  risk  of  corrupting  the
    entire database - that's too high a price.

    That  said,  you'll  have little to no chance of getting this
    feature  applied  to  the  CVS.  Doing  EXCEPTIONS   requires
    savepoints  and  a  real  "back  to  statements  start state"
    functionality. The recent  approach  of  "simulating  CURSOR"
    just  on  the PL grammar level without real cursor support in
    the SPI layer failed for exactly the same reason.  Before  we
    know   "how"  to  do  it,  we  cannot  decide  on  the  exact
    appearence, because implementation details might "require" at
    least some difference to other databases. If we accept such a
    "fake" only approach,  we  introduce  backward  compatibility
    problems,  since  somebody  will tell us for sure "I used the
    syntax of 7.2 already and porting my  +20K  line  application
    now  ...".  In  PostgreSQL  it's easier to get new *features*
    added than existing features ripped out - and people rely  on
    that.


Jan

PS:
    Aber  laï¿½  mal den Kopf nicht hï¿½ngen, wir finden bestimmt was
    wo Du Dich austoben kannst :-)

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


Fri, 18 May 2001 15:29:50 -0400 (EDT)
Jan Wieck <JanWieck@Yahoo.com>
Re: Grammar-problems with pl/pgsql in gram.y
Klaus Reger wrote:
> Am Mittwoch, 16. Mai 2001 16:10 schrieb Jan Wieck:
> >     Here it is. stmt_else is defined as type <stmts>, not <stmt>.
> >     The PLpgSQL_stmt_if struct has  a  condition  query  and  two
> >     statement lists (type <stmts>). You're trying to put a single
> >     statement into the else part instead of a list of statements.
> Thank you for the hint! That was it.
>
> >     Maybe   it'll   work   if   you   surround  it  with  another
> >     PLpgSQL_stmts struct where your new  PLpgSQL_stmt_if  is  the
> >     only  statement  in it's list.  Since I have some bigger work
> >     outstanding for PL/pgSQL, send the resulting  patch  (if  you
> >     get it to work) directly to me.
> The patch follows this message. May you tell me what kind of work it is,
> cause I'm so curous :-). By the way, the next thing I try is a
> EXCEPTION WHEN OTHER-clause, like in Oracle. Let's look if I'm successful.

    Patch applied.

    Really  a smart solution, just touching the gram.y and scan.l
    files and using the existing instruction  code.   Thanks  for
    the contribution.

    What  about  a  CASE  ...  WHEN  ...?  I  think that could be
    implemented in a similar way. Don't do it right now, I  might
    be ready to commit the cursor stuff early next week and it'll
    touch alot more than just the grammar and scanner.


Jan

--

#======================================================================#
# It's easier to get forgiveness for being wrong than for being right. #
# Let's break this rule - forgive me.                                  #
#================================================== JanWieck@Yahoo.com #



_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


Fri, 18 May 2001 17:28:01 -0400 (EDT)
Jan Wieck <JanWieck@Yahoo.com>
Re: Grammar-problems with pl/pgsql in gram.y
Jan Wieck <JanWieck@Yahoo.com> writes:
>     Patch applied.

How about some documentation?

			regards, tom lane

Fri, 18 May 2001 18:07:24 -0400
Tom Lane <tgl@sss.pgh.pa.us>
Re: Grammar-problems with pl/pgsql in gram.y 
Am Samstag, 19. Mai 2001 00:07 schrieb Tom Lane:
> Jan Wieck <JanWieck@Yahoo.com> writes:
> >     Patch applied.
>
> How about some documentation?
>
> 			regards, tom lane
Good idea! It will follow. 

Regards, Klaus

Sat, 19 May 2001 10:20:36 +0200
Klaus Reger <K.Reger@gmx.de>
Re: Grammar-problems with pl/pgsql in gram.y
Am Samstag, 19. Mai 2001 00:07 schrieben Sie:

> How about some documentation?

Her is some documentation. Because I don't have the tools and scripts 
installed, to format sgml, I never have written SGML-docs and my english is 
bad, please revisit and correct the additions.

Thank you

Klaus

-- 
TWC GmbH
Schlossbergring 9
79098 Freiburg i. Br.
http://www.twc.de
Tue, 22 May 2001 14:42:21 +0200
Klaus Reger <K.Reger@twc.de>
Re: Grammar-problems with pl/pgsql in gram.y
Here is the patch I applied.  I cleaned it up a bit.  Thanks a lot.

[ Charset ISO-8859-1 unsupported, converting... ]
> Am Samstag, 19. Mai 2001 00:07 schrieben Sie:
> 
> > How about some documentation?
> 
> Her is some documentation. Because I don't have the tools and scripts 
> installed, to format sgml, I never have written SGML-docs and my english is 
> bad, please revisit and correct the additions.
> 
> Thank you
> 
> Klaus
> 
> -- 
> TWC GmbH
> Schlossbergring 9
> 79098 Freiburg i. Br.
> http://www.twc.de

[ Attachment, skipping... ]

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Index: plsql.sgml
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/doc/src/sgml/plsql.sgml,v
retrieving revision 2.32
diff -w -b -i -B -c -r2.32 plsql.sgml
*** plsql.sgml	2001/05/17 21:50:16	2.32
--- plsql.sgml	2001/05/22 12:38:49
***************
*** 880,891 ****
      <title>Conditional Control: IF statements</title>
  
      <para>
!      <function>IF</function> statements let you take action
!      according to certain conditions. PL/pgSQL has three forms of
!      IF: IF-THEN, IF-THEN-ELSE, IF-THEN-ELSE IF. NOTE: All
!      PL/pgSQL IF statements need a corresponding <function>END
!      IF</function> statement. In ELSE-IF statements you need two:
!      one for the first IF and one for the second (ELSE IF).
      </para>
  
      <variablelist>
--- 880,890 ----
      <title>Conditional Control: IF statements</title>
  
      <para>
! 	<function>IF</function> statements let you execute commands based on
!       certain conditions. PL/PgSQL has four forms of IF: IF-THEN, IF-THEN-ELSE,
!       IF-THEN-ELSE IF, IF-THEN-ELSIF-THEN-ELSE. NOTE: All PL/PgSQL IF statements need
! 	a corresponding <function>END IF</function> clause. With ELSE-IF statements,
!       you need two: one for the first IF and one for the second (ELSE IF).
      </para>
  
      <variablelist>
***************
*** 979,984 ****
--- 978,1018 ----
         </para>
        </listitem>
       </varlistentry>
+ 
+      <varlistentry>
+       <term>
+        IF-THEN-ELSIF-ELSE
+       </term>
+ 
+       <listitem>
+        <para>
+         IF-THEN-ELSIF-ELSE allows you test multiple conditions
+         in one statement. Internally it is handled as nested 
+         IF-THEN-ELSE-IF-THEN commands. The optional ELSE
+         branch is executed when none of the conditions are met.
+        </para>
+ 
+        <para>
+         Here is an example:
+        </para>
+ 
+ <programlisting>
+ IF number = 0 THEN
+     result := ''zero'';
+ ELSIF number &lt; 0 THEN
+     result := ''negative'';
+ ELSIF number &gt; 0 THEN 
+     result := ''negative'';
+ ELSE
+     -- now it seems to be NULL
+     result := ''NULL'';
+ END IF;
+ </programlisting>
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+ 
      </variablelist>
     </sect3>
Tue, 22 May 2001 09:52:19 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: Grammar-problems with pl/pgsql in gram.y