diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index ed1704276e9deb8fd790d0eb818b79f9dd4e3a70..80580de50101e53d7ab989a5daf4e15eca19cc92 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -1,38 +1,38 @@
 %{
 /**********************************************************************
- * gram.y		- Parser for the PL/pgSQL
- *			  procedural language
+ * gram.y				- Parser for the PL/pgSQL
+ *						  procedural language
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.13 2001/01/06 01:39:01 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.14 2001/02/10 22:42:01 momjian Exp $
  *
- *    This software is copyrighted by Jan Wieck - Hamburg.
+ *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
- *    The author hereby grants permission  to  use,  copy,  modify,
- *    distribute,  and  license this software and its documentation
- *    for any purpose, provided that existing copyright notices are
- *    retained  in  all  copies  and  that  this notice is included
- *    verbatim in any distributions. No written agreement, license,
- *    or  royalty  fee  is required for any of the authorized uses.
- *    Modifications to this software may be  copyrighted  by  their
- *    author  and  need  not  follow  the licensing terms described
- *    here, provided that the new terms are  clearly  indicated  on
- *    the first page of each file where they apply.
+ *	  The author hereby grants permission  to  use,  copy,	modify,
+ *	  distribute,  and	license this software and its documentation
+ *	  for any purpose, provided that existing copyright notices are
+ *	  retained	in	all  copies  and  that	this notice is included
+ *	  verbatim in any distributions. No written agreement, license,
+ *	  or  royalty  fee	is required for any of the authorized uses.
+ *	  Modifications to this software may be  copyrighted  by  their
+ *	  author  and  need  not  follow  the licensing terms described
+ *	  here, provided that the new terms are  clearly  indicated  on
+ *	  the first page of each file where they apply.
  *
- *    IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
- *    PARTY  FOR  DIRECT,   INDIRECT,   SPECIAL,   INCIDENTAL,   OR
- *    CONSEQUENTIAL   DAMAGES  ARISING  OUT  OF  THE  USE  OF  THIS
- *    SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
- *    IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- *    DAMAGE.
+ *	  IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
+ *	  PARTY  FOR  DIRECT,	INDIRECT,	SPECIAL,   INCIDENTAL,	 OR
+ *	  CONSEQUENTIAL   DAMAGES  ARISING	OUT  OF  THE  USE  OF  THIS
+ *	  SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
+ *	  IF  THE  AUTHOR  HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ *	  DAMAGE.
  *
- *    THE  AUTHOR  AND  DISTRIBUTORS  SPECIFICALLY   DISCLAIM   ANY
- *    WARRANTIES,  INCLUDING,  BUT  NOT  LIMITED  TO,  THE  IMPLIED
- *    WARRANTIES  OF  MERCHANTABILITY,  FITNESS  FOR  A  PARTICULAR
- *    PURPOSE,  AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
- *    AN "AS IS" BASIS, AND THE AUTHOR  AND  DISTRIBUTORS  HAVE  NO
- *    OBLIGATION   TO   PROVIDE   MAINTENANCE,   SUPPORT,  UPDATES,
- *    ENHANCEMENTS, OR MODIFICATIONS.
+ *	  THE  AUTHOR  AND	DISTRIBUTORS  SPECIFICALLY	 DISCLAIM	ANY
+ *	  WARRANTIES,  INCLUDING,  BUT	NOT  LIMITED  TO,  THE	IMPLIED
+ *	  WARRANTIES  OF  MERCHANTABILITY,	FITNESS  FOR  A  PARTICULAR
+ *	  PURPOSE,	AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON
+ *	  AN "AS IS" BASIS, AND THE AUTHOR	AND  DISTRIBUTORS  HAVE  NO
+ *	  OBLIGATION   TO	PROVIDE   MAINTENANCE,	 SUPPORT,  UPDATES,
+ *	  ENHANCEMENTS, OR MODIFICATIONS.
  *
  **********************************************************************/
 
@@ -52,61 +52,61 @@ static	PLpgSQL_expr	*make_tupret_expr(PLpgSQL_row *row);
 %}
 
 %union {
-	int32			ival;
-	char			*str;
-	struct {
-	    char *name;
-	    int  lineno;
-	}			varname;
-	struct {
-	    int  nalloc;
-	    int	 nused;
-	    int	 *dtnums;
-	}			dtlist;
-	struct {
-	    int  reverse;
-	    PLpgSQL_expr *expr;
-	}			forilow;
-	struct {
-	    char *label;
-	    int  n_initvars;
-	    int  *initvarnos;
-	}			declhdr;
-	PLpgSQL_type		*dtype;
-	PLpgSQL_var		*var;
-	PLpgSQL_row		*row;
-	PLpgSQL_rec		*rec;
-	PLpgSQL_recfield	*recfield;
-	PLpgSQL_trigarg		*trigarg;
-	PLpgSQL_expr		*expr;
-	PLpgSQL_stmt		*stmt;
-	PLpgSQL_stmts		*stmts;
-	PLpgSQL_stmt_block	*program;
-	PLpgSQL_nsitem		*nsitem;
+		int32					ival;
+		char					*str;
+		struct {
+			char *name;
+			int  lineno;
+		}						varname;
+		struct {
+			int  nalloc;
+			int  nused;
+			int  *dtnums;
+		}						dtlist;
+		struct {
+			int  reverse;
+			PLpgSQL_expr *expr;
+		}						forilow;
+		struct {
+			char *label;
+			int  n_initvars;
+			int  *initvarnos;
+		}						declhdr;
+		PLpgSQL_type			*dtype;
+		PLpgSQL_var				*var;
+		PLpgSQL_row				*row;
+		PLpgSQL_rec				*rec;
+		PLpgSQL_recfield		*recfield;
+		PLpgSQL_trigarg			*trigarg;
+		PLpgSQL_expr			*expr;
+		PLpgSQL_stmt			*stmt;
+		PLpgSQL_stmts			*stmts;
+		PLpgSQL_stmt_block		*program;
+		PLpgSQL_nsitem			*nsitem;
 }
 
-%type <declhdr>	decl_sect
-%type <varname>	decl_varname
-%type <str>	decl_renname
+%type <declhdr> decl_sect
+%type <varname> decl_varname
+%type <str>		decl_renname
 %type <ival>	decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
 %type <expr>	decl_defval
 %type <dtype>	decl_datatype, decl_dtypename
-%type <row>	decl_rowtype
+%type <row>		decl_rowtype
 %type <nsitem>	decl_aliasitem
-%type <str>	decl_stmts, decl_stmt
+%type <str>		decl_stmts, decl_stmt
 
 %type <expr>	expr_until_semi, expr_until_then, expr_until_loop
 %type <expr>	opt_exitcond
 
 %type <ival>	assign_var
-%type <var>	fori_var
-%type <varname>	fori_varname
-%type <forilow>	fori_lower
-%type <rec>	fors_target
+%type <var>		fori_var
+%type <varname> fori_varname
+%type <forilow> fori_lower
+%type <rec>		fors_target
 
-%type <str>	opt_lblname, opt_label
-%type <str>	opt_exitlabel
-%type <str>	execsql_start
+%type <str>		opt_lblname, opt_label
+%type <str>		opt_exitlabel
+%type <str>		execsql_start
 
 %type <stmts>	proc_sect, proc_stmts, stmt_else, loop_body
 %type <stmt>	proc_stmt, pl_block
@@ -117,16 +117,16 @@ static	PLpgSQL_expr	*make_tupret_expr(PLpgSQL_row *row);
 
 %type <dtlist>	raise_params
 %type <ival>	raise_level, raise_param
-%type <str>	raise_msg
+%type <str>		raise_msg
 
 %type <dtlist>	getdiag_items, getdiag_targets
 %type <ival>	getdiag_item, getdiag_target
 
 %type <ival>	lno
 
-	/*
-	 * Keyword tokens
-	 */
+		/*
+		 * Keyword tokens
+		 */
 %token	K_ALIAS
 %token	K_ASSIGN
 %token	K_BEGIN
@@ -152,7 +152,7 @@ static	PLpgSQL_expr	*make_tupret_expr(PLpgSQL_row *row);
 %token	K_NOTICE
 %token	K_NULL
 %token	K_PERFORM
-%token  K_PROCESSED
+%token	K_PROCESSED
 %token	K_RAISE
 %token	K_RECORD
 %token	K_RENAME
@@ -166,9 +166,9 @@ static	PLpgSQL_expr	*make_tupret_expr(PLpgSQL_row *row);
 %token	K_WHEN
 %token	K_WHILE
 
-	/*
-	 * Other tokens
-	 */
+		/*
+		 * Other tokens
+		 */
 %token	T_FUNCTION
 %token	T_TRIGGER
 %token	T_CHAR
@@ -192,1047 +192,1047 @@ static	PLpgSQL_expr	*make_tupret_expr(PLpgSQL_row *row);
 
 %%
 
-pl_function	: T_FUNCTION comp_optsect pl_block
-		    {
-			yylval.program = (PLpgSQL_stmt_block *)$3;
-		    }
-		| T_TRIGGER comp_optsect pl_block
-		    {
-			yylval.program = (PLpgSQL_stmt_block *)$3;
-		    }
-		;
+pl_function		: T_FUNCTION comp_optsect pl_block
+					{
+						yylval.program = (PLpgSQL_stmt_block *)$3;
+					}
+				| T_TRIGGER comp_optsect pl_block
+					{
+						yylval.program = (PLpgSQL_stmt_block *)$3;
+					}
+				;
 
 comp_optsect	:
-		| comp_options
-		;
+				| comp_options
+				;
 
 comp_options	: comp_options comp_option
-		| comp_option
-		;
-
-comp_option	: O_OPTION O_DUMP
-		    {
-		        plpgsql_DumpExecTree = 1;
-		    }
-		;
-
-pl_block	: decl_sect K_BEGIN lno proc_sect K_END ';'
-		    {
-		        PLpgSQL_stmt_block *new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_block));
-			memset(new, 0, sizeof(PLpgSQL_stmt_block));
-
-			new->cmd_type   = PLPGSQL_STMT_BLOCK;
-			new->lineno     = $3;
-			new->label      = $1.label;
-			new->n_initvars = $1.n_initvars;
-			new->initvarnos = $1.initvarnos;
-			new->body       = $4;
-
-			plpgsql_ns_pop();
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
-
-
-decl_sect	: opt_label
-		    {
-		        plpgsql_ns_setlocal(false);
-			$$.label      = $1;
-			$$.n_initvars = 0;
-			$$.initvarnos = NULL;
-			plpgsql_add_initdatums(NULL);
-		    }
-		| opt_label decl_start
-		    {
-		        plpgsql_ns_setlocal(false);
-			$$.label      = $1;
-			$$.n_initvars = 0;
-			$$.initvarnos = NULL;
-			plpgsql_add_initdatums(NULL);
-		    }
-		| opt_label decl_start decl_stmts
-		    {
-		        plpgsql_ns_setlocal(false);
-			if ($3 != NULL) {
-			    $$.label = $3;
-			} else {
-			    $$.label = $1;
-			}
-			$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
-		    }
-		;
-
-decl_start	: K_DECLARE
-		    {
-		        plpgsql_ns_setlocal(true);
-		    }
-		;
-
-decl_stmts	: decl_stmts decl_stmt
-		    {
-		        $$ = $2;
-		    }
-		| decl_stmt
-		    {
-		        $$ = $1;
-		    }
-		;
-
-decl_stmt	: '<' '<' opt_lblname '>' '>'
-		    {
-			$$ = $3;
-		    }
-		| K_DECLARE
-		    {
-		        $$ = NULL;
-		    }
-		| decl_statement
-		    {
-		        $$ = NULL;
-		    }
-		;
+				| comp_option
+				;
+
+comp_option		: O_OPTION O_DUMP
+					{
+						plpgsql_DumpExecTree = 1;
+					}
+				;
+
+pl_block		: decl_sect K_BEGIN lno proc_sect K_END ';'
+					{
+						PLpgSQL_stmt_block *new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_block));
+						memset(new, 0, sizeof(PLpgSQL_stmt_block));
+
+						new->cmd_type	= PLPGSQL_STMT_BLOCK;
+						new->lineno		= $3;
+						new->label		= $1.label;
+						new->n_initvars = $1.n_initvars;
+						new->initvarnos = $1.initvarnos;
+						new->body		= $4;
+
+						plpgsql_ns_pop();
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+
+decl_sect		: opt_label
+					{
+						plpgsql_ns_setlocal(false);
+						$$.label	  = $1;
+						$$.n_initvars = 0;
+						$$.initvarnos = NULL;
+						plpgsql_add_initdatums(NULL);
+					}
+				| opt_label decl_start
+					{
+						plpgsql_ns_setlocal(false);
+						$$.label	  = $1;
+						$$.n_initvars = 0;
+						$$.initvarnos = NULL;
+						plpgsql_add_initdatums(NULL);
+					}
+				| opt_label decl_start decl_stmts
+					{
+						plpgsql_ns_setlocal(false);
+						if ($3 != NULL) {
+							$$.label = $3;
+						} else {
+							$$.label = $1;
+						}
+						$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
+					}
+				;
+
+decl_start		: K_DECLARE
+					{
+						plpgsql_ns_setlocal(true);
+					}
+				;
+
+decl_stmts		: decl_stmts decl_stmt
+					{
+						$$ = $2;
+					}
+				| decl_stmt
+					{
+						$$ = $1;
+					}
+				;
+
+decl_stmt		: '<' '<' opt_lblname '>' '>'
+					{
+						$$ = $3;
+					}
+				| K_DECLARE
+					{
+						$$ = NULL;
+					}
+				| decl_statement
+					{
+						$$ = NULL;
+					}
+				;
 
 decl_statement	: decl_varname decl_const decl_datatype decl_notnull decl_defval
-		    {
-		        PLpgSQL_var	*new;
-
-			new = malloc(sizeof(PLpgSQL_var));
-
-			new->dtype	= PLPGSQL_DTYPE_VAR;
-			new->refname	= $1.name;
-			new->lineno	= $1.lineno;
-
-			new->datatype	= $3;
-			new->isconst	= $2;
-			new->notnull	= $4;
-			new->default_val = $5;
-
-			plpgsql_adddatum((PLpgSQL_datum *)new);
-			plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
-						$1.name);
-		    }
-		| decl_varname K_RECORD ';'
-		    {
-		        PLpgSQL_rec	*new;
-
-			new = malloc(sizeof(PLpgSQL_var));
-
-			new->dtype	= PLPGSQL_DTYPE_REC;
-			new->refname	= $1.name;
-			new->lineno	= $1.lineno;
-
-			plpgsql_adddatum((PLpgSQL_datum *)new);
-			plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
-						$1.name);
-		    }
-		| decl_varname decl_rowtype ';'
-		    {
-			$2->dtype	= PLPGSQL_DTYPE_ROW;
-			$2->refname	= $1.name;
-			$2->lineno	= $1.lineno;
-
-			plpgsql_adddatum((PLpgSQL_datum *)$2);
-			plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
-						$1.name);
-		    }
-		| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
-		    {
-		        plpgsql_ns_additem($4->itemtype,
-					$4->itemno, $1.name);
-		    }
-		| K_RENAME decl_renname K_TO decl_renname ';'
-		    {
-		        plpgsql_ns_rename($2, $4);
-		    }
-		;
+					{
+						PLpgSQL_var		*new;
+
+						new = malloc(sizeof(PLpgSQL_var));
+
+						new->dtype		= PLPGSQL_DTYPE_VAR;
+						new->refname	= $1.name;
+						new->lineno		= $1.lineno;
+
+						new->datatype	= $3;
+						new->isconst	= $2;
+						new->notnull	= $4;
+						new->default_val = $5;
+
+						plpgsql_adddatum((PLpgSQL_datum *)new);
+						plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
+												$1.name);
+					}
+				| decl_varname K_RECORD ';'
+					{
+						PLpgSQL_rec		*new;
+
+						new = malloc(sizeof(PLpgSQL_var));
+
+						new->dtype		= PLPGSQL_DTYPE_REC;
+						new->refname	= $1.name;
+						new->lineno		= $1.lineno;
+
+						plpgsql_adddatum((PLpgSQL_datum *)new);
+						plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
+												$1.name);
+					}
+				| decl_varname decl_rowtype ';'
+					{
+						$2->dtype		= PLPGSQL_DTYPE_ROW;
+						$2->refname		= $1.name;
+						$2->lineno		= $1.lineno;
+
+						plpgsql_adddatum((PLpgSQL_datum *)$2);
+						plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
+												$1.name);
+					}
+				| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
+					{
+						plpgsql_ns_additem($4->itemtype,
+										$4->itemno, $1.name);
+					}
+				| K_RENAME decl_renname K_TO decl_renname ';'
+					{
+						plpgsql_ns_rename($2, $4);
+					}
+				;
 
 decl_aliasitem	: T_WORD
-		    {
-		        PLpgSQL_nsitem *nsi;
-			char	*name;
-
-			plpgsql_ns_setlocal(false);
-			name = plpgsql_tolower(yytext);
-			if (name[0] != '$') {
-			    elog(ERROR, "can only alias positional parameters");
-			}
-			nsi = plpgsql_ns_lookup(name, NULL);
-			if (nsi == NULL) {
-			    elog(ERROR, "function has no parameter %s", name);
-			}
-
-			plpgsql_ns_setlocal(true);
-
-			$$ = nsi;
-		    }
-		;
+					{
+						PLpgSQL_nsitem *nsi;
+						char	*name;
+
+						plpgsql_ns_setlocal(false);
+						name = plpgsql_tolower(yytext);
+						if (name[0] != '$') {
+							elog(ERROR, "can only alias positional parameters");
+						}
+						nsi = plpgsql_ns_lookup(name, NULL);
+						if (nsi == NULL) {
+							elog(ERROR, "function has no parameter %s", name);
+						}
+
+						plpgsql_ns_setlocal(true);
+
+						$$ = nsi;
+					}
+				;
 
 decl_rowtype	: T_ROW
-		    {
-		        $$ = yylval.row;
-		    }
-		;
+					{
+						$$ = yylval.row;
+					}
+				;
 
 decl_varname	: T_WORD
-		    {
-				/* name should be malloc'd for use as varname */
-				$$.name = strdup(plpgsql_tolower(yytext));
-				$$.lineno  = yylineno;
-		    }
-		;
+					{
+								/* name should be malloc'd for use as varname */
+								$$.name = strdup(plpgsql_tolower(yytext));
+								$$.lineno  = yylineno;
+					}
+				;
 
 decl_renname	: T_WORD
-		    {
-				/* the result must be palloc'd, see plpgsql_ns_rename */
-		        $$ = plpgsql_tolower(yytext);
-		    }
-		;
-
-decl_const	:
-		    { $$ = 0; }
-		| K_CONSTANT
-		    { $$ = 1; }
-		;
+					{
+								/* the result must be palloc'd, see plpgsql_ns_rename */
+						$$ = plpgsql_tolower(yytext);
+					}
+				;
+
+decl_const		:
+					{ $$ = 0; }
+				| K_CONSTANT
+					{ $$ = 1; }
+				;
 
 decl_datatype	: decl_dtypename
-		    {
-		        $$ = $1;
-		    }
-		;
+					{
+						$$ = $1;
+					}
+				;
 
 decl_dtypename	: T_DTYPE
-		    {
-			$$ = yylval.dtype;
-		    }
-		| T_CHAR decl_atttypmod
-		    {
-		        if ($2 < 0) {
-			    plpgsql_parse_word("char");
-			    $$ = yylval.dtype;
-			} else {
-			    plpgsql_parse_word("bpchar");
-			    $$ = yylval.dtype;
-			    $$->atttypmod = $2;
-			}
-		    }
-		| T_VARCHAR decl_atttypmod
-		    {
-		        plpgsql_parse_word("varchar");
-			$$ = yylval.dtype;
-			$$->atttypmod = $2;
-		    }
-		| T_BPCHAR '(' decl_atttypmodval ')'
-		    {
-		        plpgsql_parse_word("bpchar");
-			$$ = yylval.dtype;
-			$$->atttypmod = $3;
-		    }
-		;
+					{
+						$$ = yylval.dtype;
+					}
+				| T_CHAR decl_atttypmod
+					{
+						if ($2 < 0) {
+							plpgsql_parse_word("char");
+							$$ = yylval.dtype;
+						} else {
+							plpgsql_parse_word("bpchar");
+							$$ = yylval.dtype;
+							$$->atttypmod = $2;
+						}
+					}
+				| T_VARCHAR decl_atttypmod
+					{
+						plpgsql_parse_word("varchar");
+						$$ = yylval.dtype;
+						$$->atttypmod = $2;
+					}
+				| T_BPCHAR '(' decl_atttypmodval ')'
+					{
+						plpgsql_parse_word("bpchar");
+						$$ = yylval.dtype;
+						$$->atttypmod = $3;
+					}
+				;
 
 decl_atttypmod	:
-		    {
-		        $$ = -1;
-		    }
-		| '(' decl_atttypmodval ')'
-		    {
-		        $$ = $2;
-		    }
-		;
-
-decl_atttypmodval	: T_NUMBER
-		    {
-		        $$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
-		    }
-		;
+					{
+						$$ = -1;
+					}
+				| '(' decl_atttypmodval ')'
+					{
+						$$ = $2;
+					}
+				;
+
+decl_atttypmodval		: T_NUMBER
+					{
+						$$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
+					}
+				;
 
 decl_notnull	:
-		    { $$ = 0; }
-		| K_NOT K_NULL
-		    { $$ = 1; }
-		;
-
-decl_defval	: ';'
-		    { $$ = NULL; }
-		| decl_defkey
-		    {
-			int		tok;
-			int		lno;
-		        PLpgSQL_dstring	ds;
-			PLpgSQL_expr	*expr;
-
-			lno = yylineno;
-			expr = malloc(sizeof(PLpgSQL_expr));
-			plpgsql_dstring_init(&ds);
-			plpgsql_dstring_append(&ds, "SELECT ");
-
-			expr->dtype   = PLPGSQL_DTYPE_EXPR;
-			expr->plan    = NULL;
-			expr->nparams = 0;
-
-			tok = yylex();
-			switch (tok) {
-			    case 0:
-				plpgsql_error_lineno = lno;
-				plpgsql_comperrinfo();
-			    	elog(ERROR, "unexpected end of file");
-			    case K_NULL:
-			        if (yylex() != ';') {
-				    plpgsql_error_lineno = lno;
-				    plpgsql_comperrinfo();
-				    elog(ERROR, "expectec ; after NULL");
-				}
-				free(expr);
-				plpgsql_dstring_free(&ds);
-
-				$$ = NULL;
-				break;
-
-			    default:
-				plpgsql_dstring_append(&ds, yytext);
-				while ((tok = yylex()) != ';') {
-				    if (tok == 0) {
-					plpgsql_error_lineno = lno;
-					plpgsql_comperrinfo();
-					elog(ERROR, "unterminated default value");
-				    }
-				    if (plpgsql_SpaceScanned) {
-					plpgsql_dstring_append(&ds, " ");
-				    }
-				    plpgsql_dstring_append(&ds, yytext);
-				}
-				expr->query = strdup(plpgsql_dstring_get(&ds));
-				plpgsql_dstring_free(&ds);
-
-				$$ = expr;
-				break;
-			}
-		    }
-		;
-
-decl_defkey	: K_ASSIGN
-		| K_DEFAULT
-
-proc_sect	:
-			{
-				PLpgSQL_stmts	*new;
-
-				new = malloc(sizeof(PLpgSQL_stmts));
-				memset(new, 0, sizeof(PLpgSQL_stmts));
-				$$ = new;
-			}
-		| proc_stmts
-			{
-				$$ = $1;
-			}
-		;
-
-proc_stmts	: proc_stmts proc_stmt
-			{
-				if ($1->stmts_used == $1->stmts_alloc) {
-				    $1->stmts_alloc *= 2;
-				    $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
-				}
-				$1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
-
-				$$ = $1;
-			}
-		| proc_stmt
-			{
-				PLpgSQL_stmts	*new;
-
-				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 *)$1;
-
-				$$ = new;
-			}
-		;
-
-proc_stmt	: pl_block
-			{ $$ = $1; }
-		| stmt_assign
-			{ $$ = $1; }
-		| stmt_if
-			{ $$ = $1; }
-		| stmt_loop
-			{ $$ = $1; }
-		| stmt_while
-			{ $$ = $1; }
-		| stmt_fori
-			{ $$ = $1; }
-		| stmt_fors
-			{ $$ = $1; }
-		| stmt_select
-			{ $$ = $1; }
-		| stmt_exit
-			{ $$ = $1; }
-		| stmt_return
-			{ $$ = $1; }
-		| stmt_raise
-			{ $$ = $1; }
-		| stmt_execsql
-			{ $$ = $1; }
-		| stmt_dynexecute
-			{ $$ = $1; }
-		| stmt_dynfors
-			{ $$ = $1; }
-		| stmt_perform
-			{ $$ = $1; }
-		| stmt_getdiag
-			{ $$ = $1; }
-		;
+					{ $$ = 0; }
+				| K_NOT K_NULL
+					{ $$ = 1; }
+				;
+
+decl_defval		: ';'
+					{ $$ = NULL; }
+				| decl_defkey
+					{
+						int				tok;
+						int				lno;
+						PLpgSQL_dstring ds;
+						PLpgSQL_expr	*expr;
+
+						lno = yylineno;
+						expr = malloc(sizeof(PLpgSQL_expr));
+						plpgsql_dstring_init(&ds);
+						plpgsql_dstring_append(&ds, "SELECT ");
+
+						expr->dtype   = PLPGSQL_DTYPE_EXPR;
+						expr->plan	  = NULL;
+						expr->nparams = 0;
+
+						tok = yylex();
+						switch (tok) {
+							case 0:
+								plpgsql_error_lineno = lno;
+								plpgsql_comperrinfo();
+								elog(ERROR, "unexpected end of file");
+							case K_NULL:
+								if (yylex() != ';') {
+									plpgsql_error_lineno = lno;
+									plpgsql_comperrinfo();
+									elog(ERROR, "expectec ; after NULL");
+								}
+								free(expr);
+								plpgsql_dstring_free(&ds);
+
+								$$ = NULL;
+								break;
+
+							default:
+								plpgsql_dstring_append(&ds, yytext);
+								while ((tok = yylex()) != ';') {
+									if (tok == 0) {
+										plpgsql_error_lineno = lno;
+										plpgsql_comperrinfo();
+										elog(ERROR, "unterminated default value");
+									}
+									if (plpgsql_SpaceScanned) {
+										plpgsql_dstring_append(&ds, " ");
+									}
+									plpgsql_dstring_append(&ds, yytext);
+								}
+								expr->query = strdup(plpgsql_dstring_get(&ds));
+								plpgsql_dstring_free(&ds);
+
+								$$ = expr;
+								break;
+						}
+					}
+				;
+
+decl_defkey		: K_ASSIGN
+				| K_DEFAULT
+
+proc_sect		:
+						{
+								PLpgSQL_stmts	*new;
+
+								new = malloc(sizeof(PLpgSQL_stmts));
+								memset(new, 0, sizeof(PLpgSQL_stmts));
+								$$ = new;
+						}
+				| proc_stmts
+						{
+								$$ = $1;
+						}
+				;
+
+proc_stmts		: proc_stmts proc_stmt
+						{
+								if ($1->stmts_used == $1->stmts_alloc) {
+									$1->stmts_alloc *= 2;
+									$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
+								}
+								$1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
+
+								$$ = $1;
+						}
+				| proc_stmt
+						{
+								PLpgSQL_stmts	*new;
+
+								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 *)$1;
+
+								$$ = new;
+						}
+				;
+
+proc_stmt		: pl_block
+						{ $$ = $1; }
+				| stmt_assign
+						{ $$ = $1; }
+				| stmt_if
+						{ $$ = $1; }
+				| stmt_loop
+						{ $$ = $1; }
+				| stmt_while
+						{ $$ = $1; }
+				| stmt_fori
+						{ $$ = $1; }
+				| stmt_fors
+						{ $$ = $1; }
+				| stmt_select
+						{ $$ = $1; }
+				| stmt_exit
+						{ $$ = $1; }
+				| stmt_return
+						{ $$ = $1; }
+				| stmt_raise
+						{ $$ = $1; }
+				| stmt_execsql
+						{ $$ = $1; }
+				| stmt_dynexecute
+						{ $$ = $1; }
+				| stmt_dynfors
+						{ $$ = $1; }
+				| stmt_perform
+						{ $$ = $1; }
+				| stmt_getdiag
+						{ $$ = $1; }
+				;
 
 stmt_perform	: K_PERFORM lno expr_until_semi
-		    {
-		    	PLpgSQL_stmt_assign *new;
+					{
+						PLpgSQL_stmt_assign *new;
 
-			new = malloc(sizeof(PLpgSQL_stmt_assign));
-			memset(new, 0, sizeof(PLpgSQL_stmt_assign));
+						new = malloc(sizeof(PLpgSQL_stmt_assign));
+						memset(new, 0, sizeof(PLpgSQL_stmt_assign));
 
-			new->cmd_type = PLPGSQL_STMT_ASSIGN;
-			new->lineno   = $2;
-			new->varno = -1;
-			new->expr  = $3;
+						new->cmd_type = PLPGSQL_STMT_ASSIGN;
+						new->lineno   = $2;
+						new->varno = -1;
+						new->expr  = $3;
 
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
 
-stmt_assign	: assign_var lno K_ASSIGN expr_until_semi
-		    {
-			PLpgSQL_stmt_assign *new;
+stmt_assign		: assign_var lno K_ASSIGN expr_until_semi
+					{
+						PLpgSQL_stmt_assign *new;
 
-			new = malloc(sizeof(PLpgSQL_stmt_assign));
-			memset(new, 0, sizeof(PLpgSQL_stmt_assign));
+						new = malloc(sizeof(PLpgSQL_stmt_assign));
+						memset(new, 0, sizeof(PLpgSQL_stmt_assign));
 
-			new->cmd_type = PLPGSQL_STMT_ASSIGN;
-			new->lineno   = $2;
-			new->varno = $1;
-			new->expr  = $4;
+						new->cmd_type = PLPGSQL_STMT_ASSIGN;
+						new->lineno   = $2;
+						new->varno = $1;
+						new->expr  = $4;
 
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
 
 stmt_getdiag	: K_GET K_DIAGNOSTICS lno K_SELECT getdiag_items K_INTO getdiag_targets ';'
-                    {
-                        PLpgSQL_stmt_getdiag     *new;
-
-                        new = malloc(sizeof(PLpgSQL_stmt_getdiag));
-                        memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
-
-                        new->cmd_type = PLPGSQL_STMT_GETDIAG;
-                        new->lineno   = $3;
-                        new->nitems   = $5.nused;
-                        new->items    = malloc(sizeof(int) * $5.nused);
-                        new->ntargets = $7.nused;
-                        new->targets  = malloc(sizeof(int) * $7.nused);
-			memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
-			memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
-
-                        if (new->nitems != new->ntargets) {
-			    plpgsql_error_lineno = new->lineno;
-                            plpgsql_comperrinfo();
-                            elog(ERROR, "number of diagnostic items does not match target list");
-                        };
-
-                        $$ = (PLpgSQL_stmt *)new;
-                    }
-                ;
+					{
+						PLpgSQL_stmt_getdiag	 *new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_getdiag));
+						memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
+
+						new->cmd_type = PLPGSQL_STMT_GETDIAG;
+						new->lineno   = $3;
+						new->nitems   = $5.nused;
+						new->items	  = malloc(sizeof(int) * $5.nused);
+						new->ntargets = $7.nused;
+						new->targets  = malloc(sizeof(int) * $7.nused);
+						memcpy(new->items, $5.dtnums, sizeof(int) * $5.nused);
+						memcpy(new->targets, $7.dtnums, sizeof(int) * $7.nused);
+
+						if (new->nitems != new->ntargets) {
+							plpgsql_error_lineno = new->lineno;
+							plpgsql_comperrinfo();
+							elog(ERROR, "number of diagnostic items does not match target list");
+						};
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
 
 getdiag_items : getdiag_items ',' getdiag_item
-                    {
-                        if ($1.nused == $1.nalloc) {
-                            $1.nalloc *= 2;
-                            $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
-                        }
-                        $1.dtnums[$1.nused++] = $3;
-
-                        $$.nalloc = $1.nalloc;
-                        $$.nused  = $1.nused;
-                        $$.dtnums = $1.dtnums;
-                    }
-		| getdiag_item
-                    {
-                        $$.nalloc = 1;
-                        $$.nused  = 1;
-                        $$.dtnums = palloc(sizeof(int) * $$.nalloc);
-                        $$.dtnums[0] = $1;
-                    }
-                ;
+					{
+						if ($1.nused == $1.nalloc) {
+							$1.nalloc *= 2;
+							$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
+						}
+						$1.dtnums[$1.nused++] = $3;
+
+						$$.nalloc = $1.nalloc;
+						$$.nused  = $1.nused;
+						$$.dtnums = $1.dtnums;
+					}
+				| getdiag_item
+					{
+						$$.nalloc = 1;
+						$$.nused  = 1;
+						$$.dtnums = palloc(sizeof(int) * $$.nalloc);
+						$$.dtnums[0] = $1;
+					}
+				;
 
 getdiag_item : K_PROCESSED
-                    {
-                        $$ = PLPGSQL_GETDIAG_PROCESSED;
-                    }
-		| K_RESULT
-                    {
-                        $$ = PLPGSQL_GETDIAG_RESULT;
-                    }
-		;
+					{
+						$$ = PLPGSQL_GETDIAG_PROCESSED;
+					}
+				| K_RESULT
+					{
+						$$ = PLPGSQL_GETDIAG_RESULT;
+					}
+				;
 
 getdiag_targets : getdiag_targets ',' getdiag_target
-                    {
-                        if ($1.nused == $1.nalloc) {
-                            $1.nalloc *= 2;
-                            $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
-                        }
-                        $1.dtnums[$1.nused++] = $3;
-
-                        $$.nalloc = $1.nalloc;
-                        $$.nused  = $1.nused;
-                        $$.dtnums = $1.dtnums;
-                    }
-		| getdiag_target
-                    {
-                        $$.nalloc = 1;
-                        $$.nused  = 1;
-                        $$.dtnums = palloc(sizeof(int) * $$.nalloc);
-                        $$.dtnums[0] = $1;
-                    }
-                ;
-
-
-getdiag_target     : T_VARIABLE
-                    {
-                        if (yylval.var->isconst) {
-                            plpgsql_comperrinfo();
-                            elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
-                        }
-                        $$ = yylval.var->varno;
-                    }
-                | T_RECFIELD
-                    {
-                        $$ = yylval.recfield->rfno;
-                    }
-                ;
- 
-
-assign_var	: T_VARIABLE
-		    {
-			if (yylval.var->isconst) {
-			    plpgsql_comperrinfo();
-			    elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
-			}
-		        $$ = yylval.var->varno;
-		    }
-		| T_RECFIELD
-		    {
-		        $$ = yylval.recfield->rfno;
-		    }
-		;
-
-stmt_if		: K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
-		    {
-			PLpgSQL_stmt_if *new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_if));
-			memset(new, 0, sizeof(PLpgSQL_stmt_if));
-
-			new->cmd_type   = PLPGSQL_STMT_IF;
-			new->lineno     = $2;
-			new->cond       = $3;
-			new->true_body  = $4;
-			new->false_body = $5;
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
-
-stmt_else	:
-			{
-				PLpgSQL_stmts	*new;
-
-				new = malloc(sizeof(PLpgSQL_stmts));
-				memset(new, 0, sizeof(PLpgSQL_stmts));
-				$$ = new;
-			}
-		| K_ELSE proc_sect
-			{ $$ = $2; }
-		;
-
-stmt_loop	: opt_label K_LOOP lno loop_body
-		    {
-			PLpgSQL_stmt_loop *new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_loop));
-			memset(new, 0, sizeof(PLpgSQL_stmt_loop));
-
-			new->cmd_type = PLPGSQL_STMT_LOOP;
-			new->lineno   = $3;
-			new->label    = $1;
-			new->body     = $4;
-
-			plpgsql_ns_pop();
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
-
-stmt_while	: opt_label K_WHILE lno expr_until_loop loop_body
-		    {
-			PLpgSQL_stmt_while *new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_while));
-			memset(new, 0, sizeof(PLpgSQL_stmt_while));
-
-			new->cmd_type = PLPGSQL_STMT_WHILE;
-			new->lineno   = $3;
-			new->label    = $1;
-			new->cond     = $4;
-			new->body     = $5;
-
-			plpgsql_ns_pop();
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
+					{
+						if ($1.nused == $1.nalloc) {
+							$1.nalloc *= 2;
+							$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
+						}
+						$1.dtnums[$1.nused++] = $3;
+
+						$$.nalloc = $1.nalloc;
+						$$.nused  = $1.nused;
+						$$.dtnums = $1.dtnums;
+					}
+				| getdiag_target
+					{
+						$$.nalloc = 1;
+						$$.nused  = 1;
+						$$.dtnums = palloc(sizeof(int) * $$.nalloc);
+						$$.dtnums[0] = $1;
+					}
+				;
+
+
+getdiag_target	   : T_VARIABLE
+					{
+						if (yylval.var->isconst) {
+							plpgsql_comperrinfo();
+							elog(ERROR, "%s is declared CONSTANT; can not receive diagnostics", yylval.var->refname);
+						}
+						$$ = yylval.var->varno;
+					}
+				| T_RECFIELD
+					{
+						$$ = yylval.recfield->rfno;
+					}
+				;
+
+
+assign_var		: T_VARIABLE
+					{
+						if (yylval.var->isconst) {
+							plpgsql_comperrinfo();
+							elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
+						}
+						$$ = yylval.var->varno;
+					}
+				| T_RECFIELD
+					{
+						$$ = yylval.recfield->rfno;
+					}
+				;
+
+stmt_if			: K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
+					{
+						PLpgSQL_stmt_if *new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_if));
+						memset(new, 0, sizeof(PLpgSQL_stmt_if));
+
+						new->cmd_type	= PLPGSQL_STMT_IF;
+						new->lineno		= $2;
+						new->cond		= $3;
+						new->true_body	= $4;
+						new->false_body = $5;
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+stmt_else		:
+						{
+								PLpgSQL_stmts	*new;
+
+								new = malloc(sizeof(PLpgSQL_stmts));
+								memset(new, 0, sizeof(PLpgSQL_stmts));
+								$$ = new;
+						}
+				| K_ELSE proc_sect
+						{ $$ = $2; }
+				;
+
+stmt_loop		: opt_label K_LOOP lno loop_body
+					{
+						PLpgSQL_stmt_loop *new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_loop));
+						memset(new, 0, sizeof(PLpgSQL_stmt_loop));
+
+						new->cmd_type = PLPGSQL_STMT_LOOP;
+						new->lineno   = $3;
+						new->label	  = $1;
+						new->body	  = $4;
+
+						plpgsql_ns_pop();
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+stmt_while		: opt_label K_WHILE lno expr_until_loop loop_body
+					{
+						PLpgSQL_stmt_while *new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_while));
+						memset(new, 0, sizeof(PLpgSQL_stmt_while));
+
+						new->cmd_type = PLPGSQL_STMT_WHILE;
+						new->lineno   = $3;
+						new->label	  = $1;
+						new->cond	  = $4;
+						new->body	  = $5;
+
+						plpgsql_ns_pop();
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+stmt_fori		: opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
+					{
+						PLpgSQL_stmt_fori		*new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_fori));
+						memset(new, 0, sizeof(PLpgSQL_stmt_fori));
+
+						new->cmd_type = PLPGSQL_STMT_FORI;
+						new->lineno   = $3;
+						new->label	  = $1;
+						new->var	  = $4;
+						new->reverse  = $6.reverse;
+						new->lower	  = $6.expr;
+						new->upper	  = $7;
+						new->body	  = $8;
+
+						plpgsql_ns_pop();
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+fori_var		: fori_varname
+					{
+						PLpgSQL_var		*new;
+
+						new = malloc(sizeof(PLpgSQL_var));
 
-stmt_fori	: opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
-		    {
-			PLpgSQL_stmt_fori	*new;
+						new->dtype		= PLPGSQL_DTYPE_VAR;
+						new->refname	= $1.name;
+						new->lineno		= $1.lineno;
 
-			new = malloc(sizeof(PLpgSQL_stmt_fori));
-			memset(new, 0, sizeof(PLpgSQL_stmt_fori));
+						plpgsql_parse_word("integer");
 
-			new->cmd_type = PLPGSQL_STMT_FORI;
-			new->lineno   = $3;
-			new->label    = $1;
-			new->var      = $4;
-			new->reverse  = $6.reverse;
-			new->lower    = $6.expr;
-			new->upper    = $7;
-			new->body     = $8;
+						new->datatype	= yylval.dtype;
+						new->isconst	= false;
+						new->notnull	= false;
+						new->default_val = NULL;
 
-			plpgsql_ns_pop();
+						plpgsql_adddatum((PLpgSQL_datum *)new);
+						plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
+												$1.name);
 
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
+						plpgsql_add_initdatums(NULL);
 
-fori_var	: fori_varname
-		    {
-		        PLpgSQL_var	*new;
-
-			new = malloc(sizeof(PLpgSQL_var));
-
-			new->dtype	= PLPGSQL_DTYPE_VAR;
-			new->refname	= $1.name;
-			new->lineno	= $1.lineno;
-
-			plpgsql_parse_word("integer");
-
-			new->datatype	= yylval.dtype;
-			new->isconst	= false;
-			new->notnull	= false;
-			new->default_val = NULL;
-
-			plpgsql_adddatum((PLpgSQL_datum *)new);
-			plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
-						$1.name);
-
-			plpgsql_add_initdatums(NULL);
-
-		        $$ = new;
-		    }
-		;
+						$$ = new;
+					}
+				;
 
 fori_varname	: T_VARIABLE
-		    {
-		        $$.name = strdup(yytext);
-			$$.lineno = yylineno;
-		    }
-		| T_WORD
-		    {
-		        $$.name = strdup(yytext);
-			$$.lineno = yylineno;
-		    }
-		;
-
-fori_lower	:
-		    {
-			int			tok;
-			int			lno;
-			PLpgSQL_dstring	ds;
-			int			nparams = 0;
-			int			params[1024];
-			char		buf[32];
-			PLpgSQL_expr	*expr;
-			int			firsttok = 1;
-
-			lno = yylineno;
-			plpgsql_dstring_init(&ds);
-			plpgsql_dstring_append(&ds, "SELECT ");
-
-			$$.reverse = 0;
-			while((tok = yylex()) != K_DOTDOT) {
-			    if (firsttok) {
-				firsttok = 0;
-				if (tok == K_REVERSE) {
-				    $$.reverse = 1;
-				    continue;
-				}
-			    }
-			    if (tok == ';') break;
-			    if (plpgsql_SpaceScanned) {
-				plpgsql_dstring_append(&ds, " ");
-			    }
-			    switch (tok) {
-				case T_VARIABLE:
-				    params[nparams] = yylval.var->varno;
-				    sprintf(buf, " $%d ", ++nparams);
-				    plpgsql_dstring_append(&ds, buf);
-				    break;
-				    
-				case T_RECFIELD:
-				    params[nparams] = yylval.recfield->rfno;
-				    sprintf(buf, " $%d ", ++nparams);
-				    plpgsql_dstring_append(&ds, buf);
-				    break;
-				    
-				case T_TGARGV:
-				    params[nparams] = yylval.trigarg->dno;
-				    sprintf(buf, " $%d ", ++nparams);
-				    plpgsql_dstring_append(&ds, buf);
-				    break;
-				    
-				default:
-				    if (tok == 0) {
-					plpgsql_error_lineno = lno;
-					plpgsql_comperrinfo();
-					elog(ERROR, "missing .. to terminate lower bound of for loop");
-				    }
-				    plpgsql_dstring_append(&ds, yytext);
-				    break;
-			    }
-			}
-
-			expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
-			expr->dtype		= PLPGSQL_DTYPE_EXPR;
-			expr->query		= strdup(plpgsql_dstring_get(&ds));
-			expr->plan		= NULL;
-			expr->nparams	= nparams;
-			while(nparams-- > 0) {
-			    expr->params[nparams] = params[nparams];
-			}
-			plpgsql_dstring_free(&ds);
-			$$.expr = expr;
-		    }
-
-stmt_fors	: opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
-		    {
-			PLpgSQL_stmt_fors	*new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_fors));
-			memset(new, 0, sizeof(PLpgSQL_stmt_fors));
-
-			new->cmd_type = PLPGSQL_STMT_FORS;
-			new->lineno   = $3;
-			new->label    = $1;
-			switch ($4->dtype) {
-			    case PLPGSQL_DTYPE_REC:
-			        new->rec = $4;
-				break;
-			    case PLPGSQL_DTYPE_ROW:
-			        new->row = (PLpgSQL_row *)$4;
-				break;
-			    default:
-				plpgsql_comperrinfo();
-			        elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
-			}
-			new->query = $7;
-			new->body  = $8;
-
-			plpgsql_ns_pop();
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
+					{
+						$$.name = strdup(yytext);
+						$$.lineno = yylineno;
+					}
+				| T_WORD
+					{
+						$$.name = strdup(yytext);
+						$$.lineno = yylineno;
+					}
+				;
+
+fori_lower		:
+					{
+						int						tok;
+						int						lno;
+						PLpgSQL_dstring ds;
+						int						nparams = 0;
+						int						params[1024];
+						char			buf[32];
+						PLpgSQL_expr	*expr;
+						int						firsttok = 1;
+
+						lno = yylineno;
+						plpgsql_dstring_init(&ds);
+						plpgsql_dstring_append(&ds, "SELECT ");
+
+						$$.reverse = 0;
+						while((tok = yylex()) != K_DOTDOT) {
+							if (firsttok) {
+								firsttok = 0;
+								if (tok == K_REVERSE) {
+									$$.reverse = 1;
+									continue;
+								}
+							}
+							if (tok == ';') break;
+							if (plpgsql_SpaceScanned) {
+								plpgsql_dstring_append(&ds, " ");
+							}
+							switch (tok) {
+								case T_VARIABLE:
+									params[nparams] = yylval.var->varno;
+									sprintf(buf, " $%d ", ++nparams);
+									plpgsql_dstring_append(&ds, buf);
+									break;
+
+								case T_RECFIELD:
+									params[nparams] = yylval.recfield->rfno;
+									sprintf(buf, " $%d ", ++nparams);
+									plpgsql_dstring_append(&ds, buf);
+									break;
+
+								case T_TGARGV:
+									params[nparams] = yylval.trigarg->dno;
+									sprintf(buf, " $%d ", ++nparams);
+									plpgsql_dstring_append(&ds, buf);
+									break;
+
+								default:
+									if (tok == 0) {
+										plpgsql_error_lineno = lno;
+										plpgsql_comperrinfo();
+										elog(ERROR, "missing .. to terminate lower bound of for loop");
+									}
+									plpgsql_dstring_append(&ds, yytext);
+									break;
+							}
+						}
+
+						expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
+						expr->dtype				= PLPGSQL_DTYPE_EXPR;
+						expr->query				= strdup(plpgsql_dstring_get(&ds));
+						expr->plan				= NULL;
+						expr->nparams	= nparams;
+						while(nparams-- > 0) {
+							expr->params[nparams] = params[nparams];
+						}
+						plpgsql_dstring_free(&ds);
+						$$.expr = expr;
+					}
+
+stmt_fors		: opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
+					{
+						PLpgSQL_stmt_fors		*new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_fors));
+						memset(new, 0, sizeof(PLpgSQL_stmt_fors));
+
+						new->cmd_type = PLPGSQL_STMT_FORS;
+						new->lineno   = $3;
+						new->label	  = $1;
+						switch ($4->dtype) {
+							case PLPGSQL_DTYPE_REC:
+								new->rec = $4;
+								break;
+							case PLPGSQL_DTYPE_ROW:
+								new->row = (PLpgSQL_row *)$4;
+								break;
+							default:
+								plpgsql_comperrinfo();
+								elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
+						}
+						new->query = $7;
+						new->body  = $8;
+
+						plpgsql_ns_pop();
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
 
 stmt_dynfors : opt_label K_FOR lno fors_target K_IN K_EXECUTE expr_until_loop loop_body
-		    {
-			PLpgSQL_stmt_dynfors	*new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_dynfors));
-			memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
-
-			new->cmd_type = PLPGSQL_STMT_DYNFORS;
-			new->lineno   = $3;
-			new->label    = $1;
-			switch ($4->dtype) {
-			    case PLPGSQL_DTYPE_REC:
-			        new->rec = $4;
-				break;
-			    case PLPGSQL_DTYPE_ROW:
-			        new->row = (PLpgSQL_row *)$4;
-				break;
-			    default:
-				plpgsql_comperrinfo();
-			        elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
-			}
-			new->query = $7;
-			new->body  = $8;
-
-			plpgsql_ns_pop();
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-
-fors_target	: T_RECORD
-		    {
-		        $$ = yylval.rec;
-		    }
-		| T_ROW
-		    {
-		    	$$ = (PLpgSQL_rec *)(yylval.row);
-		    }
-		;
-
-stmt_select	: K_SELECT lno
-		    {
-		    	$$ = make_select_stmt();
-			$$->lineno = $2;
-		    }
-		;
-
-stmt_exit	: K_EXIT lno opt_exitlabel opt_exitcond
-		    {
-			PLpgSQL_stmt_exit *new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_exit));
-			memset(new, 0, sizeof(PLpgSQL_stmt_exit));
-
-			new->cmd_type = PLPGSQL_STMT_EXIT;
-			new->lineno   = $2;
-			new->label    = $3;
-			new->cond     = $4;
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
-
-stmt_return	: K_RETURN lno
-		    {
-			PLpgSQL_stmt_return *new;
-			PLpgSQL_expr	*expr = NULL;
-			int		tok;
-
-			new = malloc(sizeof(PLpgSQL_stmt_return));
-			memset(new, 0, sizeof(PLpgSQL_stmt_return));
-
-			if (plpgsql_curr_compile->fn_retistuple) {
-			    new->retistuple = true;
-			    new->retrecno   = -1;
-			    switch (tok = yylex()) {
-			        case K_NULL:
-				    expr = NULL;
-				    break;
-
-			        case T_ROW:
-				    expr = make_tupret_expr(yylval.row);
-				    break;
-
-				case T_RECORD:
-				    new->retrecno = yylval.rec->recno;
-				    expr = NULL;
-				    break;
-
-				default:
-				    yyerror("return type mismatch in function returning table row");
-				    break;
-			    }
-			    if (yylex() != ';') {
-			        yyerror("expected ';'");
-			    }
-			} else {
-			    new->retistuple = false;
-			    expr = plpgsql_read_expression(';', ";");
-			}
-
-			new->cmd_type = PLPGSQL_STMT_RETURN;
-			new->lineno   = $2;
-			new->expr     = expr;
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
-
-stmt_raise	: K_RAISE lno raise_level raise_msg raise_params ';'
-		    {
-		        PLpgSQL_stmt_raise	*new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_raise));
-
-			new->cmd_type	= PLPGSQL_STMT_RAISE;
-			new->lineno     = $2;
-			new->elog_level	= $3;
-			new->message	= $4;
-			new->nparams	= $5.nused;
-			new->params	= malloc(sizeof(int) * $5.nused);
-			memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		| K_RAISE lno raise_level raise_msg ';'
-		    {
-		        PLpgSQL_stmt_raise	*new;
-
-			new = malloc(sizeof(PLpgSQL_stmt_raise));
-
-			new->cmd_type	= PLPGSQL_STMT_RAISE;
-			new->lineno     = $2;
-			new->elog_level	= $3;
-			new->message	= $4;
-			new->nparams	= 0;
-			new->params	= NULL;
-
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
-
-raise_msg	: T_STRING
-		    {
-		        $$ = strdup(yytext);
-		    }
-		;
-
-raise_level	: K_EXCEPTION
-		    {
-		        $$ = ERROR;
-		    }
-		| K_NOTICE
-		    {
-		        $$ = NOTICE;
-		    }
-		| K_DEBUG
-		    {
-		        $$ = DEBUG;
-		    }
-		;
+					{
+						PLpgSQL_stmt_dynfors	*new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_dynfors));
+						memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
+
+						new->cmd_type = PLPGSQL_STMT_DYNFORS;
+						new->lineno   = $3;
+						new->label	  = $1;
+						switch ($4->dtype) {
+							case PLPGSQL_DTYPE_REC:
+								new->rec = $4;
+								break;
+							case PLPGSQL_DTYPE_ROW:
+								new->row = (PLpgSQL_row *)$4;
+								break;
+							default:
+								plpgsql_comperrinfo();
+								elog(ERROR, "unknown dtype %d in stmt_dynfors", $4->dtype);
+						}
+						new->query = $7;
+						new->body  = $8;
+
+						plpgsql_ns_pop();
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+
+fors_target		: T_RECORD
+					{
+						$$ = yylval.rec;
+					}
+				| T_ROW
+					{
+						$$ = (PLpgSQL_rec *)(yylval.row);
+					}
+				;
+
+stmt_select		: K_SELECT lno
+					{
+						$$ = make_select_stmt();
+						$$->lineno = $2;
+					}
+				;
+
+stmt_exit		: K_EXIT lno opt_exitlabel opt_exitcond
+					{
+						PLpgSQL_stmt_exit *new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_exit));
+						memset(new, 0, sizeof(PLpgSQL_stmt_exit));
+
+						new->cmd_type = PLPGSQL_STMT_EXIT;
+						new->lineno   = $2;
+						new->label	  = $3;
+						new->cond	  = $4;
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+stmt_return		: K_RETURN lno
+					{
+						PLpgSQL_stmt_return *new;
+						PLpgSQL_expr	*expr = NULL;
+						int				tok;
+
+						new = malloc(sizeof(PLpgSQL_stmt_return));
+						memset(new, 0, sizeof(PLpgSQL_stmt_return));
+
+						if (plpgsql_curr_compile->fn_retistuple) {
+							new->retistuple = true;
+							new->retrecno	= -1;
+							switch (tok = yylex()) {
+								case K_NULL:
+									expr = NULL;
+									break;
+
+								case T_ROW:
+									expr = make_tupret_expr(yylval.row);
+									break;
+
+								case T_RECORD:
+									new->retrecno = yylval.rec->recno;
+									expr = NULL;
+									break;
+
+								default:
+									yyerror("return type mismatch in function returning table row");
+									break;
+							}
+							if (yylex() != ';') {
+								yyerror("expected ';'");
+							}
+						} else {
+							new->retistuple = false;
+							expr = plpgsql_read_expression(';', ";");
+						}
+
+						new->cmd_type = PLPGSQL_STMT_RETURN;
+						new->lineno   = $2;
+						new->expr	  = expr;
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+stmt_raise		: K_RAISE lno raise_level raise_msg raise_params ';'
+					{
+						PLpgSQL_stmt_raise		*new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_raise));
+
+						new->cmd_type	= PLPGSQL_STMT_RAISE;
+						new->lineno		= $2;
+						new->elog_level = $3;
+						new->message	= $4;
+						new->nparams	= $5.nused;
+						new->params		= malloc(sizeof(int) * $5.nused);
+						memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				| K_RAISE lno raise_level raise_msg ';'
+					{
+						PLpgSQL_stmt_raise		*new;
+
+						new = malloc(sizeof(PLpgSQL_stmt_raise));
+
+						new->cmd_type	= PLPGSQL_STMT_RAISE;
+						new->lineno		= $2;
+						new->elog_level = $3;
+						new->message	= $4;
+						new->nparams	= 0;
+						new->params		= NULL;
+
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
+
+raise_msg		: T_STRING
+					{
+						$$ = strdup(yytext);
+					}
+				;
+
+raise_level		: K_EXCEPTION
+					{
+						$$ = ERROR;
+					}
+				| K_NOTICE
+					{
+						$$ = NOTICE;
+					}
+				| K_DEBUG
+					{
+						$$ = DEBUG;
+					}
+				;
 
 raise_params	: raise_params raise_param
-		    {
-		        if ($1.nused == $1.nalloc) {
-			    $1.nalloc *= 2;
-			    $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
-			}
-			$1.dtnums[$1.nused++] = $2;
-
-			$$.nalloc = $1.nalloc;
-			$$.nused  = $1.nused;
-			$$.dtnums = $1.dtnums;
-		    }
-		| raise_param
-		    {
-		        $$.nalloc = 1;
-			$$.nused  = 1;
-			$$.dtnums = palloc(sizeof(int) * $$.nalloc);
-			$$.dtnums[0] = $1;
-		    }
-		;
-
-raise_param	: ',' T_VARIABLE
-		    {
-		        $$ = yylval.var->varno;
-		    }
-		| ',' T_RECFIELD
-		    {
-		        $$ = yylval.recfield->rfno;
-		    }
-		| ',' T_TGARGV
-		    {
-		        $$ = yylval.trigarg->dno;
-		    }
-		;
-
-loop_body	: proc_sect K_END K_LOOP ';'
-		    { $$ = $1; }
-		;
+					{
+						if ($1.nused == $1.nalloc) {
+							$1.nalloc *= 2;
+							$1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
+						}
+						$1.dtnums[$1.nused++] = $2;
+
+						$$.nalloc = $1.nalloc;
+						$$.nused  = $1.nused;
+						$$.dtnums = $1.dtnums;
+					}
+				| raise_param
+					{
+						$$.nalloc = 1;
+						$$.nused  = 1;
+						$$.dtnums = palloc(sizeof(int) * $$.nalloc);
+						$$.dtnums[0] = $1;
+					}
+				;
+
+raise_param		: ',' T_VARIABLE
+					{
+						$$ = yylval.var->varno;
+					}
+				| ',' T_RECFIELD
+					{
+						$$ = yylval.recfield->rfno;
+					}
+				| ',' T_TGARGV
+					{
+						$$ = yylval.trigarg->dno;
+					}
+				;
+
+loop_body		: proc_sect K_END K_LOOP ';'
+					{ $$ = $1; }
+				;
 
 stmt_execsql	: execsql_start lno
-		    {
-		        PLpgSQL_stmt_execsql	*new;
+					{
+						PLpgSQL_stmt_execsql	*new;
 
-			new = malloc(sizeof(PLpgSQL_stmt_execsql));
-			new->cmd_type = PLPGSQL_STMT_EXECSQL;
-			new->lineno   = $2;
-			new->sqlstmt  = read_sqlstmt(';', ";", $1);
+						new = malloc(sizeof(PLpgSQL_stmt_execsql));
+						new->cmd_type = PLPGSQL_STMT_EXECSQL;
+						new->lineno   = $2;
+						new->sqlstmt  = read_sqlstmt(';', ";", $1);
 
-			$$ = (PLpgSQL_stmt *)new;
-		    }
-		;
+						$$ = (PLpgSQL_stmt *)new;
+					}
+				;
 
-stmt_dynexecute	: K_EXECUTE lno expr_until_semi
-			{
-				PLpgSQL_stmt_dynexecute	*new;
+stmt_dynexecute : K_EXECUTE lno expr_until_semi
+						{
+								PLpgSQL_stmt_dynexecute *new;
 
-			new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
-			new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
-			new->lineno   = $2;
-			new->query    = $3;
+						new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
+						new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
+						new->lineno   = $2;
+						new->query	  = $3;
 
-			$$ = (PLpgSQL_stmt *)new;
-			}
-		;
+						$$ = (PLpgSQL_stmt *)new;
+						}
+				;
 
 execsql_start	: T_WORD
-		    { $$ = strdup(yytext); }
-		| T_ERROR
-		    { $$ = strdup(yytext); }
-		;
-
-expr_until_semi	:
-		    { $$ = plpgsql_read_expression(';', ";"); }
-		;
-
-expr_until_then	:
-		    { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
-		;
-
-expr_until_loop	:
-		    { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
-		;
-
-opt_label	:
-		    {
-			plpgsql_ns_push(NULL);
-			$$ = NULL;
-		    }
-		| '<' '<' opt_lblname '>' '>'
-		    {
-			plpgsql_ns_push($3);
-			$$ = $3;
-		    }
-		;
+					{ $$ = strdup(yytext); }
+				| T_ERROR
+					{ $$ = strdup(yytext); }
+				;
+
+expr_until_semi :
+					{ $$ = plpgsql_read_expression(';', ";"); }
+				;
+
+expr_until_then :
+					{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }
+				;
+
+expr_until_loop :
+					{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
+				;
+
+opt_label		:
+					{
+						plpgsql_ns_push(NULL);
+						$$ = NULL;
+					}
+				| '<' '<' opt_lblname '>' '>'
+					{
+						plpgsql_ns_push($3);
+						$$ = $3;
+					}
+				;
 
 opt_exitlabel	:
-		    { $$ = NULL; }
-		| T_LABEL
-		    { $$ = strdup(yytext); }
-		;
+					{ $$ = NULL; }
+				| T_LABEL
+					{ $$ = strdup(yytext); }
+				;
 
 opt_exitcond	: ';'
-		    { $$ = NULL; }
-		| K_WHEN expr_until_semi
-		    { $$ = $2; }
-		;
-
-opt_lblname	: T_WORD
-		    { $$ = strdup(yytext); }
-		;
-
-lno		:
-		    {
-			plpgsql_error_lineno = yylineno;
-		        $$ = yylineno;
-		    }
-		;
+					{ $$ = NULL; }
+				| K_WHEN expr_until_semi
+					{ $$ = $2; }
+				;
+
+opt_lblname		: T_WORD
+					{ $$ = strdup(yytext); }
+				;
+
+lno				:
+					{
+						plpgsql_error_lineno = yylineno;
+						$$ = yylineno;
+					}
+				;
 
 %%
 
@@ -1244,237 +1244,104 @@ lno		:
 PLpgSQL_expr *
 plpgsql_read_expression (int until, char *s)
 {
-    return read_sqlstmt(until, s, "SELECT ");
+	return read_sqlstmt(until, s, "SELECT ");
 }
 
 
 static PLpgSQL_expr *
 read_sqlstmt (int until, char *s, char *sqlstart)
 {
-    int			tok;
-    int			lno;
-    PLpgSQL_dstring	ds;
-    int			nparams = 0;
-    int			params[1024];
-    char		buf[32];
-    PLpgSQL_expr	*expr;
-
-    lno = yylineno;
-    plpgsql_dstring_init(&ds);
-    plpgsql_dstring_append(&ds, sqlstart);
-
-    while((tok = yylex()) != until) {
-	if (tok == ';') break;
-	if (plpgsql_SpaceScanned) {
-	    plpgsql_dstring_append(&ds, " ");
-	}
-        switch (tok) {
-	    case T_VARIABLE:
-		params[nparams] = yylval.var->varno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-	        
-	    case T_RECFIELD:
-		params[nparams] = yylval.recfield->rfno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-	        
-	    case T_TGARGV:
-		params[nparams] = yylval.trigarg->dno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-	        
-	    default:
-		if (tok == 0) {
-		    plpgsql_error_lineno = lno;
-		    plpgsql_comperrinfo();
-		    elog(ERROR, "missing %s at end of SQL statement", s);
-		}
-		plpgsql_dstring_append(&ds, yytext);
-		break;
-        }
-    }
-
-    expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
-    expr->dtype		= PLPGSQL_DTYPE_EXPR;
-    expr->query		= strdup(plpgsql_dstring_get(&ds));
-    expr->plan		= NULL;
-    expr->nparams	= nparams;
-    while(nparams-- > 0) {
-        expr->params[nparams] = params[nparams];
-    }
-    plpgsql_dstring_free(&ds);
-    
-    return expr;
-}
-
-
-static PLpgSQL_stmt *
-make_select_stmt()
-{
-    int			tok;
-    int			lno;
-    PLpgSQL_dstring	ds;
-    int			nparams = 0;
-    int			params[1024];
-    char		buf[32];
-    PLpgSQL_expr	*expr;
-    PLpgSQL_row		*row = NULL;
-    PLpgSQL_rec		*rec = NULL;
-    PLpgSQL_stmt_select	*select;
-    int			have_nexttok = 0;
-
-    lno = yylineno;
-    plpgsql_dstring_init(&ds);
-    plpgsql_dstring_append(&ds, "SELECT ");
-
-    while((tok = yylex()) != K_INTO) {
-	if (tok == ';') {
-	    PLpgSQL_stmt_execsql	*execsql;
-
-	    expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
-	    expr->dtype		= PLPGSQL_DTYPE_EXPR;
-	    expr->query		= strdup(plpgsql_dstring_get(&ds));
-	    expr->plan		= NULL;
-	    expr->nparams	= nparams;
-	    while(nparams-- > 0) {
-		expr->params[nparams] = params[nparams];
-	    }
-	    plpgsql_dstring_free(&ds);
+	int					tok;
+	int					lno;
+	PLpgSQL_dstring		ds;
+	int					nparams = 0;
+	int					params[1024];
+	char				buf[32];
+	PLpgSQL_expr		*expr;
 
-	    execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
-	    execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
-	    execsql->sqlstmt  = expr;
+	lno = yylineno;
+	plpgsql_dstring_init(&ds);
+	plpgsql_dstring_append(&ds, sqlstart);
 
-	    return (PLpgSQL_stmt *)execsql;
-	}
-
-	if (plpgsql_SpaceScanned) {
-	    plpgsql_dstring_append(&ds, " ");
-	}
-        switch (tok) {
-	    case T_VARIABLE:
-		params[nparams] = yylval.var->varno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-	        
-	    case T_RECFIELD:
-		params[nparams] = yylval.recfield->rfno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-	        
-	    case T_TGARGV:
-		params[nparams] = yylval.trigarg->dno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-	        
-	    default:
-		if (tok == 0) {
-		    plpgsql_error_lineno = yylineno;
-		    plpgsql_comperrinfo();
-		    elog(ERROR, "unexpected end of file");
+	while((tok = yylex()) != until) {
+		if (tok == ';') break;
+		if (plpgsql_SpaceScanned) {
+			plpgsql_dstring_append(&ds, " ");
 		}
-		plpgsql_dstring_append(&ds, yytext);
-		break;
-        }
-    }
-
-    tok = yylex();
-    switch (tok) {
-        case T_ROW:
-	    row = yylval.row;
-	    break;
-
-        case T_RECORD:
-	    rec = yylval.rec;
-	    break;
-
-	case T_VARIABLE:
-	case T_RECFIELD:
-	    {
-		PLpgSQL_var	*var;
-		PLpgSQL_recfield *recfield;
-		int		nfields = 1;
-		char		*fieldnames[1024];
-		int		varnos[1024];
-
 		switch (tok) {
-		    case T_VARIABLE:
-			var = yylval.var;
-			fieldnames[0] = strdup(yytext);
-			varnos[0]     = var->varno;
-			break;
-		    
-		    case T_RECFIELD:
-			recfield = yylval.recfield;
-			fieldnames[0] = strdup(yytext);
-			varnos[0]     = recfield->rfno;
-			break;
-		}
-
-		while ((tok = yylex()) == ',') {
-		    tok = yylex();
-		    switch(tok) {
 			case T_VARIABLE:
-			    var = yylval.var;
-			    fieldnames[nfields] = strdup(yytext);
-			    varnos[nfields++]   = var->varno;
-			    break;
+				params[nparams] = yylval.var->varno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
 
 			case T_RECFIELD:
-			    recfield = yylval.recfield;
-			    fieldnames[0] = strdup(yytext);
-			    varnos[0]     = recfield->rfno;
-			    break;
+				params[nparams] = yylval.recfield->rfno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
+			case T_TGARGV:
+				params[nparams] = yylval.trigarg->dno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
 
 			default:
-			    elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
-		    }
-		}
-		row = malloc(sizeof(PLpgSQL_row));
-		row->dtype = PLPGSQL_DTYPE_ROW;
-		row->refname = strdup("*internal*");
-		row->lineno = yylineno;
-		row->rowtypeclass = InvalidOid;
-		row->nfields = nfields;
-		row->fieldnames = malloc(sizeof(char *) * nfields);
-		row->varnos = malloc(sizeof(int) * nfields);
-		while (--nfields >= 0) {
-		    row->fieldnames[nfields] = fieldnames[nfields];
-		    row->varnos[nfields] = varnos[nfields];
+				if (tok == 0) {
+					plpgsql_error_lineno = lno;
+					plpgsql_comperrinfo();
+					elog(ERROR, "missing %s at end of SQL statement", s);
+				}
+				plpgsql_dstring_append(&ds, yytext);
+				break;
 		}
+	}
 
-		plpgsql_adddatum((PLpgSQL_datum *)row);
+	expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
+	expr->dtype			= PLPGSQL_DTYPE_EXPR;
+	expr->query			= strdup(plpgsql_dstring_get(&ds));
+	expr->plan			= NULL;
+	expr->nparams		= nparams;
+	while(nparams-- > 0) {
+		expr->params[nparams] = params[nparams];
+	}
+	plpgsql_dstring_free(&ds);
 
-		have_nexttok = 1;
-	    }
-	    break;
+	return expr;
+}
 
-        default:
-	    {
-		if (plpgsql_SpaceScanned) {
-		    plpgsql_dstring_append(&ds, " ");
-		}
-		plpgsql_dstring_append(&ds, yytext);
 
-		while(1) {
-		    tok = yylex();
-		    if (tok == ';') {
-			PLpgSQL_stmt_execsql	*execsql;
+static PLpgSQL_stmt *
+make_select_stmt()
+{
+	int					tok;
+	int					lno;
+	PLpgSQL_dstring		ds;
+	int					nparams = 0;
+	int					params[1024];
+	char				buf[32];
+	PLpgSQL_expr		*expr;
+	PLpgSQL_row			*row = NULL;
+	PLpgSQL_rec			*rec = NULL;
+	PLpgSQL_stmt_select *select;
+	int					have_nexttok = 0;
+
+	lno = yylineno;
+	plpgsql_dstring_init(&ds);
+	plpgsql_dstring_append(&ds, "SELECT ");
+
+	while((tok = yylex()) != K_INTO) {
+		if (tok == ';') {
+			PLpgSQL_stmt_execsql		*execsql;
 
 			expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
-			expr->dtype		= PLPGSQL_DTYPE_EXPR;
-			expr->query		= strdup(plpgsql_dstring_get(&ds));
-			expr->plan		= NULL;
-			expr->nparams	= nparams;
+			expr->dtype			= PLPGSQL_DTYPE_EXPR;
+			expr->query			= strdup(plpgsql_dstring_get(&ds));
+			expr->plan			= NULL;
+			expr->nparams		= nparams;
 			while(nparams-- > 0) {
-			    expr->params[nparams] = params[nparams];
+				expr->params[nparams] = params[nparams];
 			}
 			plpgsql_dstring_free(&ds);
 
@@ -1483,134 +1350,267 @@ make_select_stmt()
 			execsql->sqlstmt  = expr;
 
 			return (PLpgSQL_stmt *)execsql;
-		    }
+		}
 
-		    if (plpgsql_SpaceScanned) {
+		if (plpgsql_SpaceScanned) {
 			plpgsql_dstring_append(&ds, " ");
-		    }
-		    switch (tok) {
+		}
+		switch (tok) {
 			case T_VARIABLE:
-			    params[nparams] = yylval.var->varno;
-			    sprintf(buf, " $%d ", ++nparams);
-			    plpgsql_dstring_append(&ds, buf);
-			    break;
-			    
+				params[nparams] = yylval.var->varno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
 			case T_RECFIELD:
-			    params[nparams] = yylval.recfield->rfno;
-			    sprintf(buf, " $%d ", ++nparams);
-			    plpgsql_dstring_append(&ds, buf);
-			    break;
-			    
+				params[nparams] = yylval.recfield->rfno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
 			case T_TGARGV:
-			    params[nparams] = yylval.trigarg->dno;
-			    sprintf(buf, " $%d ", ++nparams);
-			    plpgsql_dstring_append(&ds, buf);
-			    break;
-			    
+				params[nparams] = yylval.trigarg->dno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
 			default:
-			    if (tok == 0) {
-				plpgsql_error_lineno = yylineno;
-				plpgsql_comperrinfo();
-				elog(ERROR, "unexpected end of file");
-			    }
-			    plpgsql_dstring_append(&ds, yytext);
-			    break;
-		    }
+				if (tok == 0) {
+					plpgsql_error_lineno = yylineno;
+					plpgsql_comperrinfo();
+					elog(ERROR, "unexpected end of file");
+				}
+				plpgsql_dstring_append(&ds, yytext);
+				break;
 		}
-	    }
-    }
-
-    /************************************************************
-     * Eat up the rest of the statement after the target fields
-     ************************************************************/
-    while(1) {
-	if (!have_nexttok) {
-	    tok = yylex();
-	}
-	have_nexttok = 0;
-	if (tok == ';') {
-	    break;
 	}
 
-	if (plpgsql_SpaceScanned) {
-	    plpgsql_dstring_append(&ds, " ");
-	}
+	tok = yylex();
 	switch (tok) {
-	    case T_VARIABLE:
-		params[nparams] = yylval.var->varno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-		
-	    case T_RECFIELD:
-		params[nparams] = yylval.recfield->rfno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-		
-	    case T_TGARGV:
-		params[nparams] = yylval.trigarg->dno;
-		sprintf(buf, " $%d ", ++nparams);
-		plpgsql_dstring_append(&ds, buf);
-		break;
-		
-	    default:
-		if (tok == 0) {
-		    plpgsql_error_lineno = yylineno;
-		    plpgsql_comperrinfo();
-		    elog(ERROR, "unexpected end of file");
+		case T_ROW:
+			row = yylval.row;
+			break;
+
+		case T_RECORD:
+			rec = yylval.rec;
+			break;
+
+		case T_VARIABLE:
+		case T_RECFIELD:
+			{
+				PLpgSQL_var		*var;
+				PLpgSQL_recfield *recfield;
+				int				nfields = 1;
+				char			*fieldnames[1024];
+				int				varnos[1024];
+
+				switch (tok) {
+					case T_VARIABLE:
+						var = yylval.var;
+						fieldnames[0] = strdup(yytext);
+						varnos[0]	  = var->varno;
+						break;
+
+					case T_RECFIELD:
+						recfield = yylval.recfield;
+						fieldnames[0] = strdup(yytext);
+						varnos[0]	  = recfield->rfno;
+						break;
+				}
+
+				while ((tok = yylex()) == ',') {
+					tok = yylex();
+					switch(tok) {
+						case T_VARIABLE:
+							var = yylval.var;
+							fieldnames[nfields] = strdup(yytext);
+							varnos[nfields++]	= var->varno;
+							break;
+
+						case T_RECFIELD:
+							recfield = yylval.recfield;
+							fieldnames[0] = strdup(yytext);
+							varnos[0]	  = recfield->rfno;
+							break;
+
+						default:
+							elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
+					}
+				}
+				row = malloc(sizeof(PLpgSQL_row));
+				row->dtype = PLPGSQL_DTYPE_ROW;
+				row->refname = strdup("*internal*");
+				row->lineno = yylineno;
+				row->rowtypeclass = InvalidOid;
+				row->nfields = nfields;
+				row->fieldnames = malloc(sizeof(char *) * nfields);
+				row->varnos = malloc(sizeof(int) * nfields);
+				while (--nfields >= 0) {
+					row->fieldnames[nfields] = fieldnames[nfields];
+					row->varnos[nfields] = varnos[nfields];
+				}
+
+				plpgsql_adddatum((PLpgSQL_datum *)row);
+
+				have_nexttok = 1;
+			}
+			break;
+
+		default:
+			{
+				if (plpgsql_SpaceScanned) {
+					plpgsql_dstring_append(&ds, " ");
+				}
+				plpgsql_dstring_append(&ds, yytext);
+
+				while(1) {
+					tok = yylex();
+					if (tok == ';') {
+						PLpgSQL_stmt_execsql	*execsql;
+
+						expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
+						expr->dtype				= PLPGSQL_DTYPE_EXPR;
+						expr->query				= strdup(plpgsql_dstring_get(&ds));
+						expr->plan				= NULL;
+						expr->nparams	= nparams;
+						while(nparams-- > 0) {
+							expr->params[nparams] = params[nparams];
+						}
+						plpgsql_dstring_free(&ds);
+
+						execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
+						execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
+						execsql->sqlstmt  = expr;
+
+						return (PLpgSQL_stmt *)execsql;
+					}
+
+					if (plpgsql_SpaceScanned) {
+						plpgsql_dstring_append(&ds, " ");
+					}
+					switch (tok) {
+						case T_VARIABLE:
+							params[nparams] = yylval.var->varno;
+							sprintf(buf, " $%d ", ++nparams);
+							plpgsql_dstring_append(&ds, buf);
+							break;
+
+						case T_RECFIELD:
+							params[nparams] = yylval.recfield->rfno;
+							sprintf(buf, " $%d ", ++nparams);
+							plpgsql_dstring_append(&ds, buf);
+							break;
+
+						case T_TGARGV:
+							params[nparams] = yylval.trigarg->dno;
+							sprintf(buf, " $%d ", ++nparams);
+							plpgsql_dstring_append(&ds, buf);
+							break;
+
+						default:
+							if (tok == 0) {
+								plpgsql_error_lineno = yylineno;
+								plpgsql_comperrinfo();
+								elog(ERROR, "unexpected end of file");
+							}
+							plpgsql_dstring_append(&ds, yytext);
+							break;
+					}
+				}
+			}
+	}
+
+	/************************************************************
+	 * Eat up the rest of the statement after the target fields
+	 ************************************************************/
+	while(1) {
+		if (!have_nexttok) {
+			tok = yylex();
+		}
+		have_nexttok = 0;
+		if (tok == ';') {
+			break;
+		}
+
+		if (plpgsql_SpaceScanned) {
+			plpgsql_dstring_append(&ds, " ");
+		}
+		switch (tok) {
+			case T_VARIABLE:
+				params[nparams] = yylval.var->varno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
+			case T_RECFIELD:
+				params[nparams] = yylval.recfield->rfno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
+			case T_TGARGV:
+				params[nparams] = yylval.trigarg->dno;
+				sprintf(buf, " $%d ", ++nparams);
+				plpgsql_dstring_append(&ds, buf);
+				break;
+
+			default:
+				if (tok == 0) {
+					plpgsql_error_lineno = yylineno;
+					plpgsql_comperrinfo();
+					elog(ERROR, "unexpected end of file");
+				}
+				plpgsql_dstring_append(&ds, yytext);
+				break;
 		}
-		plpgsql_dstring_append(&ds, yytext);
-		break;
 	}
-    }
-
-    expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
-    expr->dtype		= PLPGSQL_DTYPE_EXPR;
-    expr->query		= strdup(plpgsql_dstring_get(&ds));
-    expr->plan		= NULL;
-    expr->nparams	= nparams;
-    while(nparams-- > 0) {
-        expr->params[nparams] = params[nparams];
-    }
-    plpgsql_dstring_free(&ds);
-
-    select = malloc(sizeof(PLpgSQL_stmt_select));
-    memset(select, 0, sizeof(PLpgSQL_stmt_select));
-    select->cmd_type = PLPGSQL_STMT_SELECT;
-    select->rec      = rec;
-    select->row      = row;
-    select->query    = expr;
-    
-    return (PLpgSQL_stmt *)select;
+
+	expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
+	expr->dtype			= PLPGSQL_DTYPE_EXPR;
+	expr->query			= strdup(plpgsql_dstring_get(&ds));
+	expr->plan			= NULL;
+	expr->nparams		= nparams;
+	while(nparams-- > 0) {
+		expr->params[nparams] = params[nparams];
+	}
+	plpgsql_dstring_free(&ds);
+
+	select = malloc(sizeof(PLpgSQL_stmt_select));
+	memset(select, 0, sizeof(PLpgSQL_stmt_select));
+	select->cmd_type = PLPGSQL_STMT_SELECT;
+	select->rec		 = rec;
+	select->row		 = row;
+	select->query	 = expr;
+
+	return (PLpgSQL_stmt *)select;
 }
 
 
 static PLpgSQL_expr *
 make_tupret_expr(PLpgSQL_row *row)
 {
-    PLpgSQL_dstring	ds;
-    PLpgSQL_expr	*expr;
-    int			i;
-    char		buf[16];
-
-    expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
-    expr->dtype		= PLPGSQL_DTYPE_EXPR;
-
-    plpgsql_dstring_init(&ds);
-    plpgsql_dstring_append(&ds, "SELECT ");
-
-    for (i = 0; i < row->nfields; i++) {
-        sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
-	plpgsql_dstring_append(&ds, buf);
-	expr->params[i] = row->varnos[i];
-    }
-
-    expr->query         = strdup(plpgsql_dstring_get(&ds));
-    expr->plan          = NULL;
-    expr->plan_argtypes = NULL;
-    expr->nparams       = row->nfields;
-
-    plpgsql_dstring_free(&ds);
-    return expr;
+	PLpgSQL_dstring		ds;
+	PLpgSQL_expr		*expr;
+	int					i;
+	char				buf[16];
+
+	expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
+	expr->dtype			= PLPGSQL_DTYPE_EXPR;
+
+	plpgsql_dstring_init(&ds);
+	plpgsql_dstring_append(&ds, "SELECT ");
+
+	for (i = 0; i < row->nfields; i++) {
+		sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
+		plpgsql_dstring_append(&ds, buf);
+		expr->params[i] = row->varnos[i];
+	}
+
+	expr->query			= strdup(plpgsql_dstring_get(&ds));
+	expr->plan			= NULL;
+	expr->plan_argtypes = NULL;
+	expr->nparams		= row->nfields;
+
+	plpgsql_dstring_free(&ds);
+	return expr;
 }