]> granicus.if.org Git - postgresql/blobdiff - src/backend/parser/gram.y
From: t-ishii@sra.co.jp
[postgresql] / src / backend / parser / gram.y
index c64acc5fc301a80f094166a516e47f97611151b8..0d3924590e5f3a7ab7be25bbd835c24484a8e4b7 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.98 1998/01/25 04:10:32 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.19 1998/07/26 04:30:31 scrappy Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
 #include "utils/elog.h"
 #include "access/xact.h"
 
+#ifdef MULTIBYTE
+#include "mb/pg_wchar.h"
+#endif
+
 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
 static bool QueryIsRule = FALSE;
 static List *saved_In_Expr = NIL;
@@ -61,6 +65,7 @@ extern List *parsetree;
  */
 /*#define __YYSCLASS*/
 
+static char *xlateSqlFunc(char *);
 static char *xlateSqlType(char *);
 static Node *makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr);
 static Node *makeRowExpr(char *opr, List *largs, List *rargs);
@@ -87,7 +92,7 @@ Oid   param_type(int t); /* used in parse_expr.c */
        char                            chr;
        char                            *str;
        bool                            boolean;
-       bool*                           pboolean;       /* for pg_user privileges */
+       bool*                           pboolean;       /* for pg_shadow privileges */
        List                            *list;
        Node                            *node;
        Value                           *value;
@@ -120,14 +125,12 @@ Oid       param_type(int t); /* used in parse_expr.c */
                ProcedureStmt,  RecipeStmt, RemoveAggrStmt, RemoveOperStmt,
                RemoveFuncStmt, RemoveStmt,
                RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
-               CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
+               CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect, SubUnion,
                UpdateStmt, InsertStmt, SelectStmt, NotifyStmt, DeleteStmt, ClusterStmt,
                ExplainStmt, VariableSetStmt, VariableShowStmt, VariableResetStmt,
                CreateUserStmt, AlterUserStmt, DropUserStmt
 
-%type <rtstmt> 
-
-%type <str>            opt_database, location
+%type <str>    opt_database1, opt_database2, location, encoding
 
 %type <pboolean> user_createdb_clause, user_createuser_clause
 %type <str>   user_passwd_clause
@@ -141,7 +144,7 @@ Oid param_type(int t); /* used in parse_expr.c */
 
 %type <str>            relation_name, copy_file_name, copy_delimiter, def_name,
                database_name, access_method_clause, access_method, attr_name,
-               class, index_name, name, file_name, recipe_name, aggr_argtype
+               class, index_name, name, func_name, file_name, recipe_name, aggr_argtype
 
 %type <str>            opt_id, opt_portal_name,
                all_Op, MathOp, opt_name, opt_unique,
@@ -153,7 +156,7 @@ Oid param_type(int t); /* used in parse_expr.c */
 %type <list>   stmtblock, stmtmulti,
                relation_name_list, OptTableElementList,
                OptInherit, definition,
-               opt_with, def_args, def_name_list, func_argtypes,
+               opt_with, func_args, func_args_list,
                oper_argtypes, OptStmtList, OptStmtBlock, OptStmtMulti,
                opt_column_list, columnList, opt_va_list, va_list,
                sort_clause, sortby_list, index_params, index_list, name_list,
@@ -161,11 +164,18 @@ Oid       param_type(int t); /* used in parse_expr.c */
                expr_list, attrs, res_target_list, res_target_list2,
                def_list, opt_indirection, group_clause, groupby_list, TriggerFuncArgs
 
+%type <node>   func_return
+%type <boolean>        set_opt
+
+%type <boolean>        TriggerForOpt, TriggerForType
+
 %type <list>   union_clause, select_list
 %type <list>   join_list
 %type <sortgroupby>
                                join_using
 %type <boolean>        opt_union
+%type <boolean>        opt_table
+%type <boolean>        opt_trans
 
 %type <node>   position_expr
 %type <list>   extract_list, position_list
@@ -190,14 +200,16 @@ Oid       param_type(int t); /* used in parse_expr.c */
 %type <node>   columnDef, alter_clause
 %type <defelt> def_elem
 %type <node>   def_arg, columnElem, where_clause,
-                               a_expr, a_expr_or_null, AexprConst,
+                               a_expr, a_expr_or_null, b_expr, AexprConst,
                                in_expr, in_expr_nodes, not_in_expr, not_in_expr_nodes,
                                having_clause
 %type <list>   row_descriptor, row_list
 %type <node>   row_expr
+%type <str>            row_op
+%type <ival>   sub_type
 %type <list>   OptCreateAs, CreateAsList
 %type <node>   CreateAsElement
-%type <value>  NumConst
+%type <value>  NumericOnly, FloatOnly, IntegerOnly
 %type <attr>   event_object, attr
 %type <sortgroupby>            groupby
 %type <sortgroupby>            sortby
@@ -208,15 +220,17 @@ Oid       param_type(int t); /* used in parse_expr.c */
 %type <paramno> ParamNo
 
 %type <typnam> Typename, opt_type, Array, Generic, Character, Datetime, Numeric
-%type <str>            generic, character, datetime
+%type <str>            generic, numeric, character, datetime
+%type <str>            extract_arg
 %type <str>            opt_charset, opt_collate
 %type <str>            opt_float, opt_numeric, opt_decimal
 %type <boolean>        opt_varying, opt_timezone
 
 %type <ival>   Iconst
 %type <str>            Sconst
-%type <str>            Id, var_value, zone_value
+%type <str>            UserId, var_value, zone_value
 %type <str>            ColId, ColLabel
+%type <str>            TypeId
 
 %type <node>   TableConstraint
 %type <list>   constraint_list, constraint_expr
@@ -253,15 +267,16 @@ Oid       param_type(int t); /* used in parse_expr.c */
                GRANT, GROUP, HAVING, HOUR_P,
                IN, INNER_P, INSERT, INTERVAL, INTO, IS,
                JOIN, KEY, LANGUAGE, LEADING, LEFT, LIKE, LOCAL,
-               MATCH, MINUTE_P, MONTH_P,
+               MATCH, MINUTE_P, MONTH_P, NAMES,
                NATIONAL, NATURAL, NCHAR, NO, NOT, NOTIFY, NULL_P, NUMERIC,
                ON, OPTION, OR, ORDER, OUTER_P,
                PARTIAL, POSITION, PRECISION, PRIMARY, PRIVILEGES, PROCEDURE, PUBLIC,
                REFERENCES, REVOKE, RIGHT, ROLLBACK,
                SECOND_P, SELECT, SET, SUBSTRING,
-               TABLE, TIME, TIMESTAMP, TO, TRAILING, TRANSACTION, TRIM,
-               UNION, UNIQUE, UPDATE, USING,
-               VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW,
+               TABLE, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE,
+               TO, TRAILING, TRANSACTION, TRIM,
+               UNION, UNIQUE, UPDATE, USER, USING,
+               VALUES, VARCHAR, VARYING, VIEW,
                WHERE, WITH, WORK, YEAR_P, ZONE
 
 /* Keywords (in SQL3 reserved words) */
@@ -271,18 +286,18 @@ Oid       param_type(int t); /* used in parse_expr.c */
 %token TYPE_P
 
 /* Keywords for Postgres support (not in SQL92 reserved words) */
-%token ABORT_TRANS, ACL, AFTER, AGGREGATE, ANALYZE,
-               APPEND, BACKWARD, BEFORE, BINARY, CHANGE, CLUSTER, COPY,
-               DATABASE, DELIMITERS, DO, EXPLAIN, EXTEND,
+%token ABORT_TRANS, AFTER, AGGREGATE, ANALYZE,
+               BACKWARD, BEFORE, BINARY, CACHE, CLUSTER, COPY, CYCLE,
+               DATABASE, DELIMITERS, DO, EACH, EXPLAIN, EXTEND,
                FORWARD, FUNCTION, HANDLER,
-               INDEX, INHERITS, INSTEAD, ISNULL,
-               LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MERGE, MOVE,
+               INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
+               LANCOMPILER, LISTEN, LOAD, LOCK_P, LOCATION, MAXVALUE, MINVALUE, MOVE,
                NEW, NONE, NOTHING, NOTNULL, OIDS, OPERATOR, PROCEDURAL,
-               RECIPE, RENAME, REPLACE, RESET, RETURNS, RULE,
-               SEQUENCE, SETOF, SHOW, STDIN, STDOUT, TRUSTED, 
-               VACUUM, VERBOSE, VERSION
+               RECIPE, RENAME, RESET, RETURNS, ROW, RULE,
+               SEQUENCE, SETOF, SHOW, START, STATEMENT, STDIN, STDOUT, TRUSTED, 
+               VACUUM, VERBOSE, VERSION, ENCODING
 
-/* Keywords (obsolete; retain temporarily for parser - thomas 1997-12-04) */
+/* Keywords (obsolete; retain through next version for parser - thomas 1997-12-04) */
 %token ARCHIVE
 
 /*
@@ -291,7 +306,7 @@ Oid param_type(int t); /* used in parse_expr.c */
  *
  *                                    Todd A. Brandys
  */
-%token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
+%token PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
 
 /* Special keywords, not in the query language - see the "lex" file */
 %token <str>   IDENT, SCONST, Op
@@ -324,7 +339,6 @@ Oid param_type(int t); /* used in parse_expr.c */
 %left          '.'
 %left          '[' ']'
 %nonassoc      TYPECAST
-%nonassoc      REDUCE
 %left          UNION
 %%
 
@@ -393,7 +407,7 @@ stmt :        AddAttrStmt
  *
  *****************************************************************************/
 
-CreateUserStmt:  CREATE USER Id user_passwd_clause user_createdb_clause
+CreateUserStmt:  CREATE USER UserId user_passwd_clause user_createdb_clause
                        user_createuser_clause user_group_clause user_valid_clause
                                {
                                        CreateUserStmt *n = makeNode(CreateUserStmt);
@@ -414,7 +428,7 @@ CreateUserStmt:  CREATE USER Id user_passwd_clause user_createdb_clause
  *
  *****************************************************************************/
 
-AlterUserStmt:  ALTER USER Id user_passwd_clause user_createdb_clause
+AlterUserStmt:  ALTER USER UserId user_passwd_clause user_createdb_clause
                        user_createuser_clause user_group_clause user_valid_clause
                                {
                                        AlterUserStmt *n = makeNode(AlterUserStmt);
@@ -435,7 +449,7 @@ AlterUserStmt:  ALTER USER Id user_passwd_clause user_createdb_clause
  *
  *****************************************************************************/
 
-DropUserStmt:  DROP USER Id
+DropUserStmt:  DROP USER UserId
                                {
                                        DropUserStmt *n = makeNode(DropUserStmt);
                                        n->user = $3;
@@ -443,7 +457,7 @@ DropUserStmt:  DROP USER Id
                                }
                ;
 
-user_passwd_clause:  WITH PASSWORD Id                  { $$ = $3; }
+user_passwd_clause:  WITH PASSWORD UserId              { $$ = $3; }
                        | /*EMPTY*/                                                     { $$ = NULL; }
                ;
 
@@ -477,11 +491,11 @@ user_createuser_clause:  CREATEUSER
                        | /*EMPTY*/                                                     { $$ = NULL; }
                ;
 
-user_group_list:  user_group_list ',' Id
+user_group_list:  user_group_list ',' UserId
                                {
                                        $$ = lcons((void*)makeString($3), $1);
                                }
-                       | Id
+                       | UserId
                                {
                                        $$ = lcons((void*)makeString($1), NIL);
                                }
@@ -525,6 +539,17 @@ VariableSetStmt:  SET ColId TO var_value
                                        n->value = $4;
                                        $$ = (Node *) n;
                                }
+               | SET NAMES encoding
+                               {
+#ifdef MB
+                                       VariableSetStmt *n = makeNode(VariableSetStmt);
+                                       n->name  = "client_encoding";
+                                       n->value = $3;
+                                       $$ = (Node *) n;
+#else
+                                       elog(ERROR, "SET NAMES is not supported");
+#endif
+                               }
                ;
 
 var_value:  Sconst                     { $$ = $1; }
@@ -533,7 +558,7 @@ var_value:  Sconst                  { $$ = $1; }
 
 zone_value:  Sconst                    { $$ = $1; }
                | DEFAULT                       { $$ = NULL; }
-               | LOCAL                         { $$ = "default"; }
+               | LOCAL                         { $$ = NULL; }
                ;
 
 VariableShowStmt:  SHOW ColId
@@ -694,8 +719,19 @@ CreateStmt:  CREATE TABLE relation_name '(' OptTableElementList ')'
                ;
 
 OptTableElementList:  OptTableElementList ',' OptTableElement
-                                                                                               { $$ = lappend($1, $3); }
-                       | OptTableElement                                       { $$ = lcons($1, NIL); }
+                               {
+                                       if ($3 != NULL)
+                                               $$ = lappend($1, $3);
+                                       else
+                                               $$ = $1;
+                               }
+                       | OptTableElement
+                               {
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, NIL);
+                                       else
+                                               $$ = NULL;
+                               }
                        | /*EMPTY*/                                                     { $$ = NULL; }
                ;
 
@@ -719,15 +755,27 @@ ColQualifier:  ColQualList                                                { $$ = $1; }
                        | /*EMPTY*/                                                     { $$ = NULL; }
                ;
 
-ColQualList:  ColQualList ColConstraint                        { $$ = lappend($1,$2); }
-                       | ColConstraint                                         { $$ = lcons($1, NIL); }
+ColQualList:  ColQualList ColConstraint
+                               {
+                                       if ($2 != NULL)
+                                               $$ = lappend($1, $2);
+                                       else
+                                               $$ = $1;
+                               }
+                       | ColConstraint
+                               {
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, NIL);
+                                       else
+                                               $$ = NULL;
+                               }
                ;
 
 ColConstraint:
                CONSTRAINT name ColConstraintElem
                                {
                                                Constraint *n = (Constraint *)$3;
-                                               n->name = fmtId($2);
+                                               if (n != NULL) n->name = fmtId($2);
                                                $$ = $3;
                                }
                | ColConstraintElem
@@ -828,19 +876,19 @@ default_expr:  AexprConst
                                        $3->name = fmtId($3->name);
                                        $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
                                }
-                       | CAST default_expr AS Typename
+                       | CAST '(' default_expr AS Typename ')'
                                {
-                                       $4->name = fmtId($4->name);
-                                       $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
+                                       $5->name = fmtId($5->name);
+                                       $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
                                }
                        | '(' default_expr ')'
                                {       $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
-                       | name '(' ')'
+                       | func_name '(' ')'
                                {
                                        $$ = makeList( makeString($1), makeString("("), -1);
                                        $$ = lappend( $$, makeString(")"));
                                }
-                       | name '(' default_list ')'
+                       | func_name '(' default_list ')'
                                {
                                        $$ = makeList( makeString($1), makeString("("), -1);
                                        $$ = nconc( $$, $3);
@@ -877,6 +925,8 @@ default_expr:  AexprConst
                                }
                        | CURRENT_USER
                                {       $$ = lcons( makeString( "CURRENT_USER"), NIL); }
+                       | USER
+                               {       $$ = lcons( makeString( "USER"), NIL); }
                ;
 
 /* ConstraintElem specifies constraint syntax which is not embedded into
@@ -886,7 +936,7 @@ default_expr:  AexprConst
 TableConstraint:  CONSTRAINT name ConstraintElem
                                {
                                                Constraint *n = (Constraint *)$3;
-                                               n->name = fmtId($2);
+                                               if (n != NULL) n->name = fmtId($2);
                                                $$ = $3;
                                }
                | ConstraintElem
@@ -920,7 +970,10 @@ ConstraintElem:  CHECK '(' constraint_expr ')'
                                        $$ = (Node *)n;
                                }
                | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
-                               {       elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented"); }
+                               {
+                                       elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
+                                       $$ = NULL;
+                               }
                ;
 
 constraint_list:  constraint_list ',' constraint_expr
@@ -969,19 +1022,19 @@ constraint_expr:  AexprConst
                                        $3->name = fmtId($3->name);
                                        $$ = nconc( lcons( makeString( "CAST"), $1), makeList( makeString("AS"), $3, -1));
                                }
-                       | CAST constraint_expr AS Typename
+                       | CAST '(' constraint_expr AS Typename ')'
                                {
-                                       $4->name = fmtId($4->name);
-                                       $$ = nconc( lcons( makeString( "CAST"), $2), makeList( makeString("AS"), $4, -1));
+                                       $5->name = fmtId($5->name);
+                                       $$ = nconc( lcons( makeString( "CAST"), $3), makeList( makeString("AS"), $5, -1));
                                }
                        | '(' constraint_expr ')'
                                {       $$ = lappend( lcons( makeString( "("), $2), makeString( ")")); }
-                       | name '(' ')'
+                       | func_name '(' ')'
                                {
                                        $$ = makeList( makeString($1), makeString("("), -1);
                                        $$ = lappend( $$, makeString(")"));
                                }
-                       | name '(' constraint_list ')'
+                       | func_name '(' constraint_list ')'
                                {
                                        $$ = makeList( makeString($1), makeString("("), -1);
                                        $$ = nconc( $$, $3);
@@ -989,6 +1042,8 @@ constraint_expr:  AexprConst
                                }
                        | constraint_expr Op constraint_expr
                                {       $$ = nconc( $1, lcons( makeString( $2), $3)); }
+                       | constraint_expr LIKE constraint_expr
+                               {       $$ = nconc( $1, lcons( makeString( "like"), $3)); }
                        | constraint_expr AND constraint_expr
                                {       $$ = nconc( $1, lcons( makeString( "AND"), $3)); }
                        | constraint_expr OR constraint_expr
@@ -1087,7 +1142,7 @@ CreateAsElement:  ColId
  *
  *****************************************************************************/
 
-CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
+CreateSeqStmt:  CREATE SEQUENCE relation_name OptSeqList
                                {
                                        CreateSeqStmt *n = makeNode(CreateSeqStmt);
                                        n->seqname = $3;
@@ -1096,24 +1151,72 @@ CreateSeqStmt:  CREATE SEQUENCE relation_name OptSeqList
                                }
                ;
 
-OptSeqList:
-                               OptSeqList OptSeqElem
+OptSeqList:  OptSeqList OptSeqElem
                                { $$ = lappend($1, $2); }
-               |               { $$ = NIL; }
+                       |       { $$ = NIL; }
                ;
 
-OptSeqElem:            IDENT NumConst
+OptSeqElem:  CACHE IntegerOnly
                                {
                                        $$ = makeNode(DefElem);
-                                       $$->defname = $1;
+                                       $$->defname = "cache";
                                        $$->arg = (Node *)$2;
                                }
-               |               IDENT
+                       | CYCLE
                                {
                                        $$ = makeNode(DefElem);
-                                       $$->defname = $1;
+                                       $$->defname = "cycle";
                                        $$->arg = (Node *)NULL;
                                }
+                       | INCREMENT IntegerOnly
+                               {
+                                       $$ = makeNode(DefElem);
+                                       $$->defname = "increment";
+                                       $$->arg = (Node *)$2;
+                               }
+                       | MAXVALUE IntegerOnly
+                               {
+                                       $$ = makeNode(DefElem);
+                                       $$->defname = "maxvalue";
+                                       $$->arg = (Node *)$2;
+                               }
+                       | MINVALUE IntegerOnly
+                               {
+                                       $$ = makeNode(DefElem);
+                                       $$->defname = "minvalue";
+                                       $$->arg = (Node *)$2;
+                               }
+                       | START IntegerOnly
+                               {
+                                       $$ = makeNode(DefElem);
+                                       $$->defname = "start";
+                                       $$->arg = (Node *)$2;
+                               }
+               ;
+
+NumericOnly:  FloatOnly                                        { $$ = $1; }
+                       | IntegerOnly                           { $$ = $1; }
+
+FloatOnly:  FCONST
+                               {
+                                       $$ = makeFloat($1);
+                               }
+                       | '-' FCONST
+                               {
+                                       $$ = makeFloat($2);
+                                       $$->val.dval = - $$->val.dval;
+                               }
+               ;
+
+IntegerOnly:  Iconst
+                               {
+                                       $$ = makeInteger($1);
+                               }
+                       | '-' Iconst
+                               {
+                                       $$ = makeInteger($2);
+                                       $$->val.ival = - $$->val.ival;
+                               }
                ;
 
 /*****************************************************************************
@@ -1171,71 +1274,72 @@ CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
                                }
                ;
 
-TriggerActionTime:             BEFORE  { $$ = TRUE; }
-                               |               AFTER   { $$ = FALSE; }
+TriggerActionTime:  BEFORE                                             { $$ = TRUE; }
+                       | AFTER                                                         { $$ = FALSE; }
                ;
 
 TriggerEvents: TriggerOneEvent
-                                       {
-                                                       char *e = palloc (4);
-                                                       e[0] = $1; e[1] = 0; $$ = e;
-                                       }
-                               | TriggerOneEvent OR TriggerOneEvent
-                                       {
-                                                       char *e = palloc (4);
-                                                       e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
-                                       }
-                               | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
-                                       {
-                                                       char *e = palloc (4);
-                                                       e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
-                                                       $$ = e;
-                                       }
+                               {
+                                       char *e = palloc (4);
+                                       e[0] = $1; e[1] = 0; $$ = e;
+                               }
+                       | TriggerOneEvent OR TriggerOneEvent
+                               {
+                                       char *e = palloc (4);
+                                       e[0] = $1; e[1] = $3; e[2] = 0; $$ = e;
+                               }
+                       | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
+                               {
+                                       char *e = palloc (4);
+                                       e[0] = $1; e[1] = $3; e[2] = $5; e[3] = 0;
+                                       $$ = e;
+                               }
                ;
 
-TriggerOneEvent:               INSERT  { $$ = 'i'; }
-                               |               DELETE  { $$ = 'd'; }
-                               |               UPDATE  { $$ = 'u'; }
+TriggerOneEvent:  INSERT                                       { $$ = 'i'; }
+                       | DELETE                                                { $$ = 'd'; }
+                       | UPDATE                                                { $$ = 'u'; }
                ;
 
-TriggerForSpec:  FOR name name
+TriggerForSpec:  FOR TriggerForOpt TriggerForType
                                {
-                                               if ( strcmp ($2, "each") != 0 )
-                                                               elog(ERROR,"parser: syntax error near %s",$2);
-                                               if ( strcmp ($3, "row") == 0 )
-                                                               $$ = TRUE;
-                                               else if ( strcmp ($3, "statement") == 0 )
-                                                               $$ = FALSE;
-                                               else
-                                                               elog(ERROR,"parser: syntax error near %s",$3);
+                                       $$ = $3;
                                }
                ;
 
+TriggerForOpt:  EACH                                           { $$ = TRUE; }
+                       | /*EMPTY*/                                             { $$ = FALSE; }
+               ;
+
+TriggerForType:  ROW                                           { $$ = TRUE; }
+                       | STATEMENT                                             { $$ = FALSE; }
+               ;
+
 TriggerFuncArgs:  TriggerFuncArg
                                { $$ = lcons($1, NIL); }
-               | TriggerFuncArgs ',' TriggerFuncArg
+                       | TriggerFuncArgs ',' TriggerFuncArg
                                { $$ = lappend($1, $3); }
-               | /*EMPTY*/
+                       | /*EMPTY*/
                                { $$ = NIL; }
                ;
 
 TriggerFuncArg:  ICONST
-                                       {
-                                               char *s = (char *) palloc (256);
-                                               sprintf (s, "%d", $1);
-                                               $$ = s;
-                                       }
-                               | FCONST
-                                       {
-                                               char *s = (char *) palloc (256);
-                                               sprintf (s, "%g", $1);
-                                               $$ = s;
-                                       }
-                               | Sconst                {  $$ = $1; }
-                               | IDENT                 {  $$ = $1; }
+                               {
+                                       char *s = (char *) palloc (256);
+                                       sprintf (s, "%d", $1);
+                                       $$ = s;
+                               }
+                       | FCONST
+                               {
+                                       char *s = (char *) palloc (256);
+                                       sprintf (s, "%g", $1);
+                                       $$ = s;
+                               }
+                       | Sconst                                                {  $$ = $1; }
+                       | IDENT                                                 {  $$ = $1; }
                ;
 
-DropTrigStmt:  DROP TRIGGER name ON relation_name
+DropTrigStmt:  DROP TRIGGER name ON relation_name
                                {
                                        DropTrigStmt *n = makeNode(DropTrigStmt);
                                        n->trigname = $3;
@@ -1308,7 +1412,7 @@ def_elem:  def_name '=' def_arg
 
 def_arg:  ColId                                                        {  $$ = (Node *)makeString($1); }
                | all_Op                                                {  $$ = (Node *)makeString($1); }
-               | NumConst                                              {  $$ = (Node *)$1; /* already a Value */ }
+               | NumericOnly                                   {  $$ = (Node *)$1; }
                | Sconst                                                {  $$ = (Node *)makeString($1); }
                | SETOF ColId
                                {
@@ -1316,9 +1420,9 @@ def_arg:  ColId                                                   {  $$ = (Node *)makeString($1); }
                                        n->name = $2;
                                        n->setof = TRUE;
                                        n->arrayBounds = NULL;
+                                       n->typmod = -1;
                                        $$ = (Node *)n;
                                }
-               | DOUBLE                                                {  $$ = (Node *)makeString("double"); }
                ;
 
 
@@ -1400,8 +1504,6 @@ opt_portal_name:  IN name                         { $$ = $2; }
 GrantStmt:  GRANT privileges ON relation_name_list TO grantee opt_with_grant
                                {
                                        $$ = (Node*)makeAclStmt($2,$4,$6,'+');
-                                       pfree($2);
-                                       pfree($6);
                                }
                ;
 
@@ -1426,7 +1528,6 @@ operation_commalist:  operation
                | operation_commalist ',' operation
                                {
                                                $$ = aclmakepriv($1,$3);
-                                               pfree($1);
                                }
                ;
 
@@ -1531,7 +1632,7 @@ index_list:  index_list ',' index_elem                    { $$ = lappend($1, $3); }
                | index_elem                                                    { $$ = lcons($1, NIL); }
                ;
 
-func_index:  name '(' name_list ')' opt_type opt_class
+func_index:  func_name '(' name_list ')' opt_type opt_class
                                {
                                        $$ = makeNode(IndexElem);
                                        $$->name = $1;
@@ -1621,13 +1722,13 @@ RecipeStmt:  EXECUTE RECIPE recipe_name
  *
  *****************************************************************************/
 
-ProcedureStmt: CREATE FUNCTION def_name def_args
-                        RETURNS def_arg opt_with AS Sconst LANGUAGE Sconst
+ProcedureStmt: CREATE FUNCTION func_name func_args
+                        RETURNS func_return opt_with AS Sconst LANGUAGE Sconst
                                {
                                        ProcedureStmt *n = makeNode(ProcedureStmt);
                                        n->funcname = $3;
                                        n->defArgs = $4;
-                                       n->returnType = (Node *)$6;
+                                       n->returnType = $6;
                                        n->withClause = $7;
                                        n->as = $9;
                                        n->language = $11;
@@ -1635,14 +1736,32 @@ ProcedureStmt:  CREATE FUNCTION def_name def_args
                                };
 
 opt_with:  WITH definition                                             { $$ = $2; }
-               | /*EMPTY*/                                                     { $$ = NIL; }
+               | /*EMPTY*/                                                             { $$ = NIL; }
                ;
 
-def_args:  '(' def_name_list ')'                               { $$ = $2; }
+func_args:  '(' func_args_list ')'                             { $$ = $2; }
                | '(' ')'                                                               { $$ = NIL; }
                ;
 
-def_name_list: name_list;
+func_args_list:  TypeId
+                               {       $$ = lcons(makeString($1),NIL); }
+               | func_args_list ',' TypeId
+                               {       $$ = lappend($1,makeString($3)); }
+               ;
+
+func_return:  set_opt TypeId
+                               {
+                                       TypeName *n = makeNode(TypeName);
+                                       n->name = $2;
+                                       n->setof = $1;
+                                       n->arrayBounds = NULL;
+                                       $$ = (Node *)n;
+                               }
+               ;
+
+set_opt:  SETOF                                                                        { $$ = TRUE; }
+               | /*EMPTY*/                                                             { $$ = FALSE; }
+               ;
 
 /*****************************************************************************
  *
@@ -1676,6 +1795,7 @@ remove_type:  TYPE_P                                                      {  $$ = TYPE_P; }
                | VIEW                                                                  {  $$ = VIEW; }
                ;
 
+
 RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
                                {
                                                RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
@@ -1689,18 +1809,16 @@ aggr_argtype:  name                                                             { $$ = $1; }
                | '*'                                                                   { $$ = NULL; }
                ;
 
-RemoveFuncStmt:  DROP FUNCTION name '(' func_argtypes ')'
+
+RemoveFuncStmt:  DROP FUNCTION func_name func_args
                                {
                                        RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
                                        n->funcname = $3;
-                                       n->args = $5;
+                                       n->args = $4;
                                        $$ = (Node *)n;
                                }
                ;
 
-func_argtypes: name_list                                               { $$ = $1; }
-               | /*EMPTY*/                                                             { $$ = NIL; }
-               ;
 
 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')'
                                {
@@ -1834,7 +1952,7 @@ event:    SELECT                                                  { $$ = CMD_SELECT; }
                 ;
 
 opt_instead:  INSTEAD                                  { $$ = TRUE; }
-               | /*EMPTY*/                                     { $$ = FALSE; }
+               | /*EMPTY*/                                             { $$ = FALSE; }
                ;
 
 
@@ -1876,74 +1994,41 @@ ListenStmt:  LISTEN relation_name
  *
  *****************************************************************************/
 
-TransactionStmt:  ABORT_TRANS TRANSACTION
+TransactionStmt: ABORT_TRANS opt_trans
                                {
                                        TransactionStmt *n = makeNode(TransactionStmt);
                                        n->command = ABORT_TRANS;
                                        $$ = (Node *)n;
                                }
-               | BEGIN_TRANS TRANSACTION
-                               {
-                                       TransactionStmt *n = makeNode(TransactionStmt);
-                                       n->command = BEGIN_TRANS;
-                                       $$ = (Node *)n;
-                               }
-               | BEGIN_TRANS WORK
+               | BEGIN_TRANS opt_trans
                                {
                                        TransactionStmt *n = makeNode(TransactionStmt);
                                        n->command = BEGIN_TRANS;
                                        $$ = (Node *)n;
                                }
-               | COMMIT WORK
+               | COMMIT opt_trans
                                {
                                        TransactionStmt *n = makeNode(TransactionStmt);
                                        n->command = END_TRANS;
                                        $$ = (Node *)n;
                                }
-               | END_TRANS TRANSACTION
+               | END_TRANS opt_trans
                                {
                                        TransactionStmt *n = makeNode(TransactionStmt);
                                        n->command = END_TRANS;
                                        $$ = (Node *)n;
                                }
-               | ROLLBACK WORK
-                               {
-                                       TransactionStmt *n = makeNode(TransactionStmt);
-                                       n->command = ABORT_TRANS;
-                                       $$ = (Node *)n;
-                               }
-
-               | ABORT_TRANS
+               | ROLLBACK opt_trans
                                {
                                        TransactionStmt *n = makeNode(TransactionStmt);
                                        n->command = ABORT_TRANS;
                                        $$ = (Node *)n;
                                }
-               | BEGIN_TRANS
-                               {
-                                       TransactionStmt *n = makeNode(TransactionStmt);
-                                       n->command = BEGIN_TRANS;
-                                       $$ = (Node *)n;
-                               }
-               | COMMIT
-                               {
-                                       TransactionStmt *n = makeNode(TransactionStmt);
-                                       n->command = END_TRANS;
-                                       $$ = (Node *)n;
-                               }
+               ;
 
-               | END_TRANS
-                               {
-                                       TransactionStmt *n = makeNode(TransactionStmt);
-                                       n->command = END_TRANS;
-                                       $$ = (Node *)n;
-                               }
-               | ROLLBACK
-                               {
-                                       TransactionStmt *n = makeNode(TransactionStmt);
-                                       n->command = ABORT_TRANS;
-                                       $$ = (Node *)n;
-                               }
+opt_trans: WORK                                                                        { $$ = TRUE; }
+               | TRANSACTION                                                   { $$ = TRUE; }
+               | /*EMPTY*/                                                             { $$ = TRUE; }
                ;
 
 
@@ -1991,16 +2076,45 @@ LoadStmt:  LOAD file_name
  *
  *****************************************************************************/
 
-CreatedbStmt:  CREATE DATABASE database_name opt_database
+CreatedbStmt:  CREATE DATABASE database_name WITH opt_database1 opt_database2
+                               {
+                                       CreatedbStmt *n = makeNode(CreatedbStmt);
+                                       if ($5 == NULL && $6 == NULL) {
+                                               elog(ERROR, "CREATE DATABASE WITH requires at least an option");
+                                       }
+                                       n->dbname = $3;
+                                       n->dbpath = $5;
+#ifdef MULTIBYTE
+                                       if ($6 != NULL) {
+                                               n->encoding = pg_char_to_encoding($6);
+                                               if (n->encoding < 0) {
+                                                       elog(ERROR, "invalid encoding name %s", $6);
+                                               }
+                                       } else {
+                                               n->encoding = GetTemplateEncoding();
+                                       }
+#else
+                                       elog(ERROR, "WITH ENCODING is not supported");
+#endif
+                                       $$ = (Node *)n;
+                               }
+               | CREATE DATABASE database_name
                                {
                                        CreatedbStmt *n = makeNode(CreatedbStmt);
                                        n->dbname = $3;
-                                       n->dbpath = $4;
+                                       n->dbpath = NULL;
+#ifdef MULTIBYTE
+                                       n->encoding = GetTemplateEncoding();
+#endif
                                        $$ = (Node *)n;
                                }
                ;
 
-opt_database:  WITH LOCATION '=' location              { $$ = $4; }
+opt_database1:  LOCATION '=' location                  { $$ = $3; }
+               | /*EMPTY*/                                                             { $$ = NULL; }
+               ;
+
+opt_database2:  ENCODING '=' encoding                  { $$ = $3; }
                | /*EMPTY*/                                                             { $$ = NULL; }
                ;
 
@@ -2009,6 +2123,11 @@ location:  Sconst                                                                { $$ = $1; }
                | /*EMPTY*/                                                             { $$ = NULL; }
                ;
 
+encoding:  Sconst                                                              { $$ = $1; }
+               | DEFAULT                                                               { $$ = NULL; }
+               | /*EMPTY*/                                                             { $$ = NULL; }
+               ;
+
 /*****************************************************************************
  *
  *             QUERY:
@@ -2079,10 +2198,8 @@ opt_analyze:  ANALYZE                                                    { $$ = TRUE; }
                | /*EMPTY*/                                                             { $$ = FALSE; }
                ;
 
-opt_va_list:  '(' va_list ')'
-                               { $$ = $2; }
-               | /* EMPTY */
-                               { $$ = NIL; }
+opt_va_list:  '(' va_list ')'                                  { $$ = $2; }
+               | /*EMPTY*/                                                             { $$ = NIL; }
                ;
 
 va_list:  name
@@ -2214,7 +2331,7 @@ DeleteStmt:  DELETE FROM relation_name
  *     Is it worth making this a separate command, with
  *     its own node type and file.  I don't think so. bjm 1998/1/22
  */
-LockStmt:  LOCK_P relation_name
+LockStmt:  LOCK_P opt_table relation_name
                                {
                                        DeleteStmt *n = makeNode(DeleteStmt);
                                        A_Const *c = makeNode(A_Const);
@@ -2223,9 +2340,10 @@ LockStmt:  LOCK_P relation_name
                                        c->val.val.str = "f";
                                        c->typename = makeNode(TypeName);
                                        c->typename->name = xlateSqlType("bool");
+                                       c->typename->typmod = -1;
 
-                                       n->relname = $2;
-                                       n->whereClause = c;
+                                       n->relname = $3;
+                                       n->whereClause = (Node *)c;
                                        $$ = (Node *)n;
                                }
                ;
@@ -2319,6 +2437,23 @@ SelectStmt:  SELECT opt_unique res_target_list2
                                }
                ;
 
+SubSelect:  SELECT opt_unique res_target_list2
+                        from_clause where_clause
+                        group_clause having_clause
+                        union_clause
+                               {
+                                       SelectStmt *n = makeNode(SelectStmt);
+                                       n->unique = $2;
+                                       n->targetList = $3;
+                                       n->fromClause = $4;
+                                       n->whereClause = $5;
+                                       n->groupClause = $6;
+                                       n->havingClause = $7;
+                                       n->unionClause = $8;
+                                       $$ = (Node *)n;
+                               }
+               ;
+
 union_clause:  UNION opt_union select_list
                                {
                                        SelectStmt *n = (SelectStmt *)lfirst($3);
@@ -2329,17 +2464,17 @@ union_clause:  UNION opt_union select_list
                                { $$ = NIL; }
                ;
 
-select_list:  select_list UNION opt_union SubSelect
+select_list:  select_list UNION opt_union SubUnion
                                {
                                        SelectStmt *n = (SelectStmt *)$4;
                                        n->unionall = $3;
                                        $$ = lappend($1, $4);
                                }
-               | SubSelect
+               | SubUnion
                                { $$ = lcons($1, NIL); }
                ;
 
-SubSelect:     SELECT opt_unique res_target_list2
+SubUnion:      SELECT opt_unique res_target_list2
                         from_clause where_clause
                         group_clause having_clause
                                {
@@ -2355,10 +2490,12 @@ SubSelect:      SELECT opt_unique res_target_list2
                                }
                ;
 
-result:  INTO TABLE relation_name
-                               {       $$= $3; }
-               | /*EMPTY*/
-                               {       $$ = NULL; }
+result:  INTO opt_table relation_name                  { $$= $3; }
+               | /*EMPTY*/                                                             { $$ = NULL; }
+               ;
+
+opt_table:  TABLE                                                              { $$ = TRUE; }
+               | /*EMPTY*/                                                             { $$ = FALSE; }
                ;
 
 opt_union:  ALL                                                                        { $$ = TRUE; }
@@ -2468,7 +2605,6 @@ groupby:  ColId
 
 having_clause:  HAVING a_expr
                                {
-                                       elog(NOTICE, "HAVING not yet supported; ignore clause");
                                        $$ = $2;
                                }
                | /*EMPTY*/                                                             { $$ = NULL; }
@@ -2661,12 +2797,12 @@ Generic:  generic
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType($1);
+                                       $$->typmod = -1;
                                }
                ;
 
-generic:  Id                                                                   { $$ = $1; }
+generic:  IDENT                                                                        { $$ = $1; }
                | TYPE_P                                                                { $$ = xlateSqlType("type"); }
-               | DOUBLE PRECISION                                              { $$ = xlateSqlType("float8"); }
                ;
 
 /* SQL92 numeric data types
@@ -2679,19 +2815,37 @@ Numeric:  FLOAT opt_float
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType($2);
+                                       $$->typmod = -1;
+                               }
+               | DOUBLE PRECISION
+                               {
+                                       $$ = makeNode(TypeName);
+                                       $$->name = xlateSqlType("float");
                                }
                | DECIMAL opt_decimal
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType("integer");
+                                       $$->typmod = -1;
                                }
                | NUMERIC opt_numeric
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType("integer");
+                                       $$->typmod = -1;
                                }
                ;
 
+numeric:  FLOAT
+                               {       $$ = xlateSqlType("float8"); }
+               | DOUBLE PRECISION
+                               {       $$ = xlateSqlType("float8"); }
+               | DECIMAL
+                               {       $$ = xlateSqlType("decimal"); }
+               | NUMERIC
+                               {       $$ = xlateSqlType("numeric"); }
+               ;
+
 opt_float:  '(' Iconst ')'
                                {
                                        if ($2 < 1)
@@ -2757,12 +2911,13 @@ opt_decimal:  '(' Iconst ',' Iconst ')'
 Character:  character '(' Iconst ')'
                                {
                                        $$ = makeNode(TypeName);
-                                       if (!strcasecmp($1, "char"))
+                                       if (strcasecmp($1, "char") == 0)
                                                $$->name = xlateSqlType("bpchar");
-                                       else if (!strcasecmp($1, "varchar"))
+                                       else if (strcasecmp($1, "varchar") == 0)
                                                $$->name = xlateSqlType("varchar");
                                        else
-                                               yyerror("parse error");
+                                               yyerror("internal parsing error; unrecognized character type");
+
                                        if ($3 < 1)
                                                elog(ERROR,"length for '%s' type must be at least 1",$1);
                                        else if ($3 > 4096)
@@ -2783,7 +2938,19 @@ Character:  character '(' Iconst ')'
                | character
                                {
                                        $$ = makeNode(TypeName);
-                                       $$->name = xlateSqlType($1);
+                                       /* Let's try to make all single-character types into bpchar(1)
+                                        * - thomas 1998-05-07
+                                        */
+                                       if (strcasecmp($1, "char") == 0)
+                                       {
+                                               $$->name = xlateSqlType("bpchar");
+                                               $$->typmod = VARHDRSZ + 1;
+                                       }
+                                       else
+                                       {
+                                               $$->name = xlateSqlType($1);
+                                               $$->typmod = -1;
+                                       }
                                }
                ;
 
@@ -2804,7 +2971,7 @@ character:  CHARACTER opt_varying opt_charset opt_collate
                                                }
                                        };
                                        if ($4 != NULL)
-                                       elog(ERROR,"COLLATE %s not yet implemented",$4);
+                                               elog(NOTICE,"COLLATE %s not yet implemented; clause ignored",$4);
                                        $$ = type;
                                }
                | CHAR opt_varying                                              { $$ = xlateSqlType($2? "varchar": "char"); }
@@ -2829,22 +2996,26 @@ Datetime:  datetime
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType($1);
+                                       $$->typmod = -1;
                                }
                | TIMESTAMP opt_timezone
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType("timestamp");
                                        $$->timezone = $2;
+                                       $$->typmod = -1;
                                }
                | TIME
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType("time");
+                                       $$->typmod = -1;
                                }
                | INTERVAL opt_interval
                                {
                                        $$ = makeNode(TypeName);
                                        $$->name = xlateSqlType("interval");
+                                       $$->typmod = -1;
                                }
                ;
 
@@ -2867,6 +3038,7 @@ opt_interval:  datetime                                                   { $$ = lcons($1, NIL); }
                | DAY_P TO SECOND_P                                             { $$ = NIL; }
                | HOUR_P TO MINUTE_P                                    { $$ = NIL; }
                | HOUR_P TO SECOND_P                                    { $$ = NIL; }
+               | MINUTE_P TO SECOND_P                                  { $$ = NIL; }
                | /*EMPTY*/                                                             { $$ = NIL; }
                ;
 
@@ -2890,6 +3062,11 @@ a_expr_or_null:  a_expr
 /* Expressions using row descriptors
  * Define row_descriptor to allow yacc to break the reduce/reduce conflict
  *  with singleton expressions.
+ * Eliminated lots of code by defining row_op and sub_type clauses.
+ * However, can not consolidate EXPR_LINK case with others subselects
+ *  due to shift/reduce conflict with the non-subselect clause (the parser
+ *  would have to look ahead more than one token to resolve the conflict).
+ * - thomas 1998-05-09
  */
 row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
                                {
@@ -2911,27 +3088,20 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
                                        n->subselect = $7;
                                        $$ = (Node *)n;
                                }
-               | '(' row_descriptor ')' Op ANY '(' SubSelect ')'
-                               {
-                                       SubLink *n = makeNode(SubLink);
-                                       n->lefthand = $2;
-                                       n->oper = lcons($4,NIL);
-                                       n->useor = false;
-                                       n->subLinkType = ANY_SUBLINK;
-                                       n->subselect = $7;
-                                       $$ = (Node *)n;
-                               }
-               | '(' row_descriptor ')' Op ALL '(' SubSelect ')'
+               | '(' row_descriptor ')' row_op sub_type '(' SubSelect ')'
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->lefthand = $2;
-                                       n->oper = lcons($4,NIL);
-                                       n->useor = false;
-                                       n->subLinkType = ALL_SUBLINK;
+                                       n->oper = lcons($4, NIL);
+                                       if (strcmp($4,"<>") == 0)
+                                               n->useor = true;
+                                       else
+                                               n->useor = false;
+                                       n->subLinkType = $5;
                                        n->subselect = $7;
                                        $$ = (Node *)n;
                                }
-               | '(' row_descriptor ')' Op '(' SubSelect ')'
+               | '(' row_descriptor ')' row_op '(' SubSelect ')'
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->lefthand = $2;
@@ -2944,7 +3114,7 @@ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
                                        n->subselect = $6;
                                        $$ = (Node *)n;
                                }
-               | '(' row_descriptor ')' Op '(' row_descriptor ')'
+               | '(' row_descriptor ')' row_op '(' row_descriptor ')'
                                {
                                        $$ = makeRowExpr($4, $2, $6);
                                }
@@ -2966,6 +3136,28 @@ row_list:  row_list ',' a_expr
                                }
                ;
 
+row_op:  Op                                                                    { $$ = $1; }
+               | '<'                                                           { $$ = "<"; }
+               | '='                                                           { $$ = "="; }
+               | '>'                                                           { $$ = ">"; }
+               | '+'                                                           { $$ = "+"; }
+               | '-'                                                           { $$ = "-"; }
+               | '*'                                                           { $$ = "*"; }
+               | '/'                                                           { $$ = "/"; }
+               ;
+
+sub_type:  ANY                                                         { $$ = ANY_SUBLINK; }
+               | ALL                                                           { $$ = ALL_SUBLINK; }
+               ;
+
+/*
+ * This is the heart of the expression syntax.
+ * Note that the BETWEEN clause looks similar to a boolean expression
+ *  and so we must define b_expr which is almost the same as a_expr
+ *  but without the boolean expressions.
+ * All operations are allowed in a BETWEEN clause if surrounded by parens.
+ */
+
 a_expr:  attr opt_indirection
                                {
                                        $1->indirection = $2;
@@ -2975,6 +3167,14 @@ a_expr:  attr opt_indirection
                                {       $$ = $1;  }
                | AexprConst
                                {       $$ = $1;  }
+               | ColId
+                               {
+                                       /* could be a column name or a relation_name */
+                                       Ident *n = makeNode(Ident);
+                                       n->name = $1;
+                                       n->indirection = NULL;
+                                       $$ = (Node *)n;
+                               }
                | '-' a_expr %prec UMINUS
                                {       $$ = makeA_Expr(OP, "-", NULL, $2); }
                | a_expr '+' a_expr
@@ -3013,19 +3213,19 @@ a_expr:  attr opt_indirection
                                                $$ = (Node *)n;
                                        }
                                }
-               | CAST a_expr AS Typename
+               | CAST '(' a_expr AS Typename ')'
                                {
-                                       $$ = (Node *)$2;
+                                       $$ = (Node *)$3;
                                        /* AexprConst can be either A_Const or ParamNo */
-                                       if (nodeTag($2) == T_A_Const) {
-                                               ((A_Const *)$2)->typename = $4;
-                                       } else if (nodeTag($2) == T_Param) {
-                                               ((ParamNo *)$2)->typename = $4;
+                                       if (nodeTag($3) == T_A_Const) {
+                                               ((A_Const *)$3)->typename = $5;
+                                       } else if (nodeTag($5) == T_Param) {
+                                               ((ParamNo *)$3)->typename = $5;
                                        /* otherwise, try to transform to a function call */
                                        } else {
                                                FuncCall *n = makeNode(FuncCall);
-                                               n->funcname = $4->name;
-                                               n->args = lcons($2,NIL);
+                                               n->funcname = $5->name;
+                                               n->args = lcons($3,NIL);
                                                $$ = (Node *)n;
                                        }
                                }
@@ -3041,15 +3241,7 @@ a_expr:  attr opt_indirection
                                {       $$ = makeA_Expr(OP, $1, NULL, $2); }
                | a_expr Op
                                {       $$ = makeA_Expr(OP, $2, $1, NULL); }
-               | ColId
-                               {
-                                       /* could be a column name or a relation_name */
-                                       Ident *n = makeNode(Ident);
-                                       n->name = $1;
-                                       n->indirection = NULL;
-                                       $$ = (Node *)n;
-                               }
-               | name '(' '*' ')'
+               | func_name '(' '*' ')'
                                {
                                        /* cheap hack for aggregate (eg. count) */
                                        FuncCall *n = makeNode(FuncCall);
@@ -3061,14 +3253,14 @@ a_expr:  attr opt_indirection
                                        n->args = lcons(star, NIL);
                                        $$ = (Node *)n;
                                }
-               | name '(' ')'
+               | func_name '(' ')'
                                {
                                        FuncCall *n = makeNode(FuncCall);
                                        n->funcname = $1;
                                        n->args = NIL;
                                        $$ = (Node *)n;
                                }
-               | name '(' expr_list ')'
+               | func_name '(' expr_list ')'
                                {
                                        FuncCall *n = makeNode(FuncCall);
                                        n->funcname = $1;
@@ -3086,7 +3278,8 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("date");
                                        t->setof = FALSE;
-
+                                       t->typmod = -1;
                                        $$ = (Node *)n;
                                }
                | CURRENT_TIME
@@ -3100,6 +3293,7 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("time");
                                        t->setof = FALSE;
+                                       t->typmod = -1;
 
                                        $$ = (Node *)n;
                                }
@@ -3118,6 +3312,7 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("time");
                                        t->setof = FALSE;
+                                       t->typmod = -1;
 
                                        if ($3 != 0)
                                                elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
@@ -3135,6 +3330,7 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("timestamp");
                                        t->setof = FALSE;
+                                       t->typmod = -1;
 
                                        $$ = (Node *)n;
                                }
@@ -3153,6 +3349,7 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("timestamp");
                                        t->setof = FALSE;
+                                       t->typmod = -1;
 
                                        if ($3 != 0)
                                                elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
@@ -3166,6 +3363,13 @@ a_expr:  attr opt_indirection
                                        n->args = NIL;
                                        $$ = (Node *)n;
                                }
+               | USER
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "getpgusername";
+                                       n->args = NIL;
+                                       $$ = (Node *)n;
+                               }
                | EXISTS '(' SubSelect ')'
                                {
                                        SubLink *n = makeNode(SubLink);
@@ -3246,6 +3450,7 @@ a_expr:  attr opt_indirection
                                        n->val.val.str = "t";
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("bool");
+                                       n->typename->typmod = -1;
                                        $$ = makeA_Expr(OP, "=", $1,(Node *)n);
                                }
                | a_expr IS NOT FALSE_P
@@ -3255,6 +3460,7 @@ a_expr:  attr opt_indirection
                                        n->val.val.str = "t";
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("bool");
+                                       n->typename->typmod = -1;
                                        $$ = makeA_Expr(OP, "=", $1,(Node *)n);
                                }
                | a_expr IS FALSE_P
@@ -3264,6 +3470,7 @@ a_expr:  attr opt_indirection
                                        n->val.val.str = "f";
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("bool");
+                                       n->typename->typmod = -1;
                                        $$ = makeA_Expr(OP, "=", $1,(Node *)n);
                                }
                | a_expr IS NOT TRUE_P
@@ -3273,22 +3480,24 @@ a_expr:  attr opt_indirection
                                        n->val.val.str = "f";
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("bool");
+                                       n->typename->typmod = -1;
                                        $$ = makeA_Expr(OP, "=", $1,(Node *)n);
                                }
-               | a_expr BETWEEN AexprConst AND AexprConst
+               | a_expr BETWEEN b_expr AND b_expr
                                {
                                        $$ = makeA_Expr(AND, NULL,
                                                makeA_Expr(OP, ">=", $1, $3),
                                                makeA_Expr(OP, "<=", $1, $5));
                                }
-               | a_expr NOT BETWEEN AexprConst AND AexprConst
+               | a_expr NOT BETWEEN b_expr AND b_expr
                                {
                                        $$ = makeA_Expr(OR, NULL,
                                                makeA_Expr(OP, "<", $1, $4),
                                                makeA_Expr(OP, ">", $1, $6));
                                }
-               | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')' { saved_In_Expr = lnext(saved_In_Expr); }
+               | a_expr IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' in_expr ')'
                                {
+                                       saved_In_Expr = lnext(saved_In_Expr);
                                        if (nodeTag($5) == T_SubLink)
                                        {
                                                        SubLink *n = (SubLink *)$5;
@@ -3300,8 +3509,9 @@ a_expr:  attr opt_indirection
                                        }
                                        else    $$ = $5;
                                }
-               | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')' { saved_In_Expr = lnext(saved_In_Expr); }
+               | a_expr NOT IN { saved_In_Expr = lcons($1,saved_In_Expr); } '(' not_in_expr ')'
                                {
+                                       saved_In_Expr = lnext(saved_In_Expr);
                                        if (nodeTag($6) == T_SubLink)
                                        {
                                                        SubLink *n = (SubLink *)$6;
@@ -3313,34 +3523,493 @@ a_expr:  attr opt_indirection
                                        }
                                        else    $$ = $6;
                                }
-               | a_expr Op ANY '(' SubSelect ')'
+               | a_expr Op '(' SubSelect ')'
                                {
                                        SubLink *n = makeNode(SubLink);
-                                       n->lefthand = lcons($1,NIL);
+                                       n->lefthand = lcons($1, NULL);
                                        n->oper = lcons($2,NIL);
                                        n->useor = false;
-                                       n->subLinkType = ANY_SUBLINK;
-                                       n->subselect = $5;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
                                        $$ = (Node *)n;
                                }
-               | a_expr Op ALL '(' SubSelect ')'
+               | a_expr '+' '(' SubSelect ')'
                                {
                                        SubLink *n = makeNode(SubLink);
                                        n->lefthand = lcons($1, NULL);
-                                       n->oper = lcons($2,NIL);
+                                       n->oper = lcons("+",NIL);
                                        n->useor = false;
-                                       n->subLinkType = ALL_SUBLINK;
-                                       n->subselect = $5;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
                                        $$ = (Node *)n;
                                }
-               | a_expr AND a_expr
-                               {       $$ = makeA_Expr(AND, NULL, $1, $3); }
-               | a_expr OR a_expr
+               | a_expr '-' '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("-",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '/' '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("/",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '*' '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("*",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '<' '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("<",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '>' '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons(">",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '=' '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("=",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $4;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr Op ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons($2,NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '+' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons("+",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '-' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons("-",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '/' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons("/",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '*' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons("*",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '<' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons("<",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '>' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons(">",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '=' ANY '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1,NIL);
+                                       n->oper = lcons("=",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr Op ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons($2,NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '+' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("+",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '-' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("-",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '/' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("/",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '*' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("*",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '<' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("<",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '>' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons(">",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr '=' ALL '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons("=",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $5;
+                                       $$ = (Node *)n;
+                               }
+               | a_expr AND a_expr
+                               {       $$ = makeA_Expr(AND, NULL, $1, $3); }
+               | a_expr OR a_expr
                                {       $$ = makeA_Expr(OR, NULL, $1, $3); }
                | NOT a_expr
                                {       $$ = makeA_Expr(NOT, NULL, NULL, $2); }
                ;
 
+/*
+ * b_expr is a subset of the complete expression syntax
+ *  defined by a_expr. b_expr is used in BETWEEN clauses
+ *  to eliminate parser ambiguities stemming from the AND keyword.
+ */
+
+b_expr:  attr opt_indirection
+                               {
+                                       $1->indirection = $2;
+                                       $$ = (Node *)$1;
+                               }
+               | AexprConst
+                               {       $$ = $1;  }
+               | ColId
+                               {
+                                       /* could be a column name or a relation_name */
+                                       Ident *n = makeNode(Ident);
+                                       n->name = $1;
+                                       n->indirection = NULL;
+                                       $$ = (Node *)n;
+                               }
+               | '-' b_expr %prec UMINUS
+                               {       $$ = makeA_Expr(OP, "-", NULL, $2); }
+               | b_expr '+' b_expr
+                               {       $$ = makeA_Expr(OP, "+", $1, $3); }
+               | b_expr '-' b_expr
+                               {       $$ = makeA_Expr(OP, "-", $1, $3); }
+               | b_expr '/' b_expr
+                               {       $$ = makeA_Expr(OP, "/", $1, $3); }
+               | b_expr '*' b_expr
+                               {       $$ = makeA_Expr(OP, "*", $1, $3); }
+               | ':' b_expr
+                               {       $$ = makeA_Expr(OP, ":", NULL, $2); }
+               | ';' b_expr
+                               {       $$ = makeA_Expr(OP, ";", NULL, $2); }
+               | '|' b_expr
+                               {       $$ = makeA_Expr(OP, "|", NULL, $2); }
+               | b_expr TYPECAST Typename
+                               {
+                                       $$ = (Node *)$1;
+                                       /* AexprConst can be either A_Const or ParamNo */
+                                       if (nodeTag($1) == T_A_Const) {
+                                               ((A_Const *)$1)->typename = $3;
+                                       } else if (nodeTag($1) == T_Param) {
+                                               ((ParamNo *)$1)->typename = $3;
+                                       /* otherwise, try to transform to a function call */
+                                       } else {
+                                               FuncCall *n = makeNode(FuncCall);
+                                               n->funcname = $3->name;
+                                               n->args = lcons($1,NIL);
+                                               $$ = (Node *)n;
+                                       }
+                               }
+               | CAST '(' b_expr AS Typename ')'
+                               {
+                                       $$ = (Node *)$3;
+                                       /* AexprConst can be either A_Const or ParamNo */
+                                       if (nodeTag($3) == T_A_Const) {
+                                               ((A_Const *)$3)->typename = $5;
+                                       } else if (nodeTag($3) == T_Param) {
+                                               ((ParamNo *)$3)->typename = $5;
+                                       /* otherwise, try to transform to a function call */
+                                       } else {
+                                               FuncCall *n = makeNode(FuncCall);
+                                               n->funcname = $5->name;
+                                               n->args = lcons($3,NIL);
+                                               $$ = (Node *)n;
+                                       }
+                               }
+               | '(' a_expr ')'
+                               {       $$ = $2; }
+               | b_expr Op b_expr
+                               {       $$ = makeIndexable($2,$1,$3);   }
+               | Op b_expr
+                               {       $$ = makeA_Expr(OP, $1, NULL, $2); }
+               | b_expr Op
+                               {       $$ = makeA_Expr(OP, $2, $1, NULL); }
+               | func_name '(' ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = $1;
+                                       n->args = NIL;
+                                       $$ = (Node *)n;
+                               }
+               | func_name '(' expr_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = $1;
+                                       n->args = $3;
+                                       $$ = (Node *)n;
+                               }
+               | CURRENT_DATE
+                               {
+                                       A_Const *n = makeNode(A_Const);
+                                       TypeName *t = makeNode(TypeName);
+
+                                       n->val.type = T_String;
+                                       n->val.val.str = "now";
+                                       n->typename = t;
+
+                                       t->name = xlateSqlType("date");
+                                       t->setof = FALSE;
+                                       t->typmod = -1;
+
+                                       $$ = (Node *)n;
+                               }
+               | CURRENT_TIME
+                               {
+                                       A_Const *n = makeNode(A_Const);
+                                       TypeName *t = makeNode(TypeName);
+
+                                       n->val.type = T_String;
+                                       n->val.val.str = "now";
+                                       n->typename = t;
+
+                                       t->name = xlateSqlType("time");
+                                       t->setof = FALSE;
+                                       t->typmod = -1;
+
+                                       $$ = (Node *)n;
+                               }
+               | CURRENT_TIME '(' Iconst ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       A_Const *s = makeNode(A_Const);
+                                       TypeName *t = makeNode(TypeName);
+
+                                       n->funcname = xlateSqlType("time");
+                                       n->args = lcons(s, NIL);
+
+                                       s->val.type = T_String;
+                                       s->val.val.str = "now";
+                                       s->typename = t;
+
+                                       t->name = xlateSqlType("time");
+                                       t->setof = FALSE;
+                                       t->typmod = -1;
+
+                                       if ($3 != 0)
+                                               elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
+
+                                       $$ = (Node *)n;
+                               }
+               | CURRENT_TIMESTAMP
+                               {
+                                       A_Const *n = makeNode(A_Const);
+                                       TypeName *t = makeNode(TypeName);
+
+                                       n->val.type = T_String;
+                                       n->val.val.str = "now";
+                                       n->typename = t;
+
+                                       t->name = xlateSqlType("timestamp");
+                                       t->setof = FALSE;
+                                       t->typmod = -1;
+
+                                       $$ = (Node *)n;
+                               }
+               | CURRENT_TIMESTAMP '(' Iconst ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       A_Const *s = makeNode(A_Const);
+                                       TypeName *t = makeNode(TypeName);
+
+                                       n->funcname = xlateSqlType("timestamp");
+                                       n->args = lcons(s, NIL);
+
+                                       s->val.type = T_String;
+                                       s->val.val.str = "now";
+                                       s->typename = t;
+
+                                       t->name = xlateSqlType("timestamp");
+                                       t->setof = FALSE;
+                                       t->typmod = -1;
+
+                                       if ($3 != 0)
+                                               elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
+
+                                       $$ = (Node *)n;
+                               }
+               | CURRENT_USER
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "getpgusername";
+                                       n->args = NIL;
+                                       $$ = (Node *)n;
+                               }
+               | USER
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "getpgusername";
+                                       n->args = NIL;
+                                       $$ = (Node *)n;
+                               }
+               | POSITION '(' position_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "strpos";
+                                       n->args = $3;
+                                       $$ = (Node *)n;
+                               }
+               | SUBSTRING '(' substr_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "substr";
+                                       n->args = $3;
+                                       $$ = (Node *)n;
+                               }
+               /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
+               | TRIM '(' BOTH trim_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "btrim";
+                                       n->args = $4;
+                                       $$ = (Node *)n;
+                               }
+               | TRIM '(' LEADING trim_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "ltrim";
+                                       n->args = $4;
+                                       $$ = (Node *)n;
+                               }
+               | TRIM '(' TRAILING trim_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "rtrim";
+                                       n->args = $4;
+                                       $$ = (Node *)n;
+                               }
+               | TRIM '(' trim_list ')'
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "btrim";
+                                       n->args = $3;
+                                       $$ = (Node *)n;
+                               }
+               ;
+
 opt_indirection:  '[' a_expr ']' opt_indirection
                                {
                                        A_Indices *ai = makeNode(A_Indices);
@@ -3367,7 +4036,7 @@ expr_list:  a_expr_or_null
                                { $$ = lappend($1, $3); }
                ;
 
-extract_list:  datetime FROM a_expr
+extract_list:  extract_arg FROM a_expr
                                {
                                        A_Const *n = makeNode(A_Const);
                                        n->val.type = T_String;
@@ -3378,6 +4047,11 @@ extract_list:  datetime FROM a_expr
                                {       $$ = NIL; }
                ;
 
+extract_arg:  datetime                                         { $$ = $1; }
+               | TIMEZONE_HOUR                                         { $$ = "tz_hour"; }
+               | TIMEZONE_MINUTE                                       { $$ = "tz_minute"; }
+               ;
+
 position_list:  position_expr IN position_expr
                                {       $$ = makeList($3, $1, -1); }
                | /* EMPTY */
@@ -3419,19 +4093,19 @@ position_expr:  attr opt_indirection
                                                $$ = (Node *)n;
                                        }
                                }
-               | CAST position_expr AS Typename
+               | CAST '(' position_expr AS Typename ')'
                                {
-                                       $$ = (Node *)$2;
+                                       $$ = (Node *)$3;
                                        /* AexprConst can be either A_Const or ParamNo */
-                                       if (nodeTag($2) == T_A_Const) {
-                                               ((A_Const *)$2)->typename = $4;
-                                       } else if (nodeTag($2) == T_Param) {
-                                               ((ParamNo *)$2)->typename = $4;
+                                       if (nodeTag($3) == T_A_Const) {
+                                               ((A_Const *)$3)->typename = $5;
+                                       } else if (nodeTag($3) == T_Param) {
+                                               ((ParamNo *)$3)->typename = $5;
                                        /* otherwise, try to transform to a function call */
                                        } else {
                                                FuncCall *n = makeNode(FuncCall);
-                                               n->funcname = $4->name;
-                                               n->args = lcons($2,NIL);
+                                               n->funcname = $5->name;
+                                               n->args = lcons($3,NIL);
                                                $$ = (Node *)n;
                                        }
                                }
@@ -3451,14 +4125,14 @@ position_expr:  attr opt_indirection
                                        n->indirection = NULL;
                                        $$ = (Node *)n;
                                }
-               | name '(' ')'
+               | func_name '(' ')'
                                {
                                        FuncCall *n = makeNode(FuncCall);
                                        n->funcname = $1;
                                        n->args = NIL;
                                        $$ = (Node *)n;
                                }
-               | name '(' expr_list ')'
+               | func_name '(' expr_list ')'
                                {
                                        FuncCall *n = makeNode(FuncCall);
                                        n->funcname = $1;
@@ -3733,9 +4407,9 @@ relation_name:    SpecialRuleRelation
                ;
 
 database_name:                 ColId                   { $$ = $1; };
-access_method:                 Id                              { $$ = $1; };
+access_method:                 IDENT                   { $$ = $1; };
 attr_name:                             ColId                   { $$ = $1; };
-class:                                 Id                              { $$ = $1; };
+class:                                 IDENT                   { $$ = $1; };
 index_name:                            ColId                   { $$ = $1; };
 
 /* Functions
@@ -3743,9 +4417,10 @@ index_name:                              ColId                   { $$ = $1; };
  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
  */
 name:                                  ColId                   { $$ = $1; };
+func_name:                             ColId                   { $$ = xlateSqlFunc($1); };
 
 file_name:                             Sconst                  { $$ = $1; };
-recipe_name:                   Id                              { $$ = $1; };
+recipe_name:                   IDENT                   { $$ = $1; };
 
 /* Constants
  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
@@ -3788,6 +4463,7 @@ AexprConst:  Iconst
                                        n->val.val.str = "t";
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("bool");
+                                       n->typename->typmod = -1;
                                        $$ = (Node *)n;
                                }
                | FALSE_P
@@ -3797,6 +4473,7 @@ AexprConst:  Iconst
                                        n->val.val.str = "f";
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("bool");
+                                       n->typename->typmod = -1;
                                        $$ = (Node *)n;
                                }
                ;
@@ -3808,20 +4485,22 @@ ParamNo:  PARAM
                                }
                ;
 
-NumConst:  Iconst                                              { $$ = makeInteger($1); }
-               | FCONST                                                { $$ = makeFloat($1); }
-               ;
-
 Iconst:  ICONST                                                        { $$ = $1; };
 Sconst:  SCONST                                                        { $$ = $1; };
+UserId:  IDENT                                                 { $$ = $1; };
 
 /* Column and type identifier
  * Does not include explicit datetime types
  *  since these must be decoupled in Typename syntax.
  * Use ColId for most identifiers. - thomas 1997-10-21
  */
-Id:  IDENT                                                             { $$ = $1; };
-
+TypeId:  ColId
+                       {       $$ = xlateSqlType($1); }
+               | numeric
+                       {       $$ = xlateSqlType($1); }
+               | character
+                       {       $$ = xlateSqlType($1); }
+               ;
 /* Column identifier
  * Include date/time keywords as SQL92 extension.
  * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
@@ -3830,24 +4509,39 @@ Id:  IDENT                                                              { $$ = $1; };
  *  list due to shift/reduce conflicts in yacc. If so, move
  *  down to the ColLabel entity. - thomas 1997-11-06
  */
-ColId:  Id                                                             { $$ = $1; }
+ColId:  IDENT                                                  { $$ = $1; }
                | datetime                                              { $$ = $1; }
                | ACTION                                                { $$ = "action"; }
+               | CACHE                                                 { $$ = "cache"; }
+               | CYCLE                                                 { $$ = "cycle"; }
                | DATABASE                                              { $$ = "database"; }
                | DELIMITERS                                    { $$ = "delimiters"; }
+               | DOUBLE                                                { $$ = "double"; }
+               | EACH                                                  { $$ = "each"; }
+               | ENCODING                                              { $$ = "encoding"; }
                | FUNCTION                                              { $$ = "function"; }
+               | INCREMENT                                             { $$ = "increment"; }
                | INDEX                                                 { $$ = "index"; }
                | KEY                                                   { $$ = "key"; }
                | LANGUAGE                                              { $$ = "language"; }
                | LOCATION                                              { $$ = "location"; }
                | MATCH                                                 { $$ = "match"; }
+               | MAXVALUE                                              { $$ = "maxvalue"; }
+               | MINVALUE                                              { $$ = "minvalue"; }
                | OPERATOR                                              { $$ = "operator"; }
                | OPTION                                                { $$ = "option"; }
+               | PASSWORD                                              { $$ = "password"; }
                | PRIVILEGES                                    { $$ = "privileges"; }
                | RECIPE                                                { $$ = "recipe"; }
+               | ROW                                                   { $$ = "row"; }
+               | START                                                 { $$ = "start"; }
+               | STATEMENT                                             { $$ = "statement"; }
                | TIME                                                  { $$ = "time"; }
+               | TIMEZONE_HOUR                                 { $$ = "timezone_hour"; }
+               | TIMEZONE_MINUTE                               { $$ = "timezone_minute"; }
                | TRIGGER                                               { $$ = "trigger"; }
                | TYPE_P                                                { $$ = "type"; }
+               | VALID                                                 { $$ = "valid"; }
                | VERSION                                               { $$ = "version"; }
                | ZONE                                                  { $$ = "zone"; }
                ;
@@ -4059,15 +4753,16 @@ static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
        
                        for (pos = 0; n->val.val.str[pos]; pos++)
                        {
-                               if ((n->val.val.str[pos] == '%' &&
-                                        n->val.val.str[pos+1] != '%') ||
-                                   (n->val.val.str[pos] == '_' &&
-                                n->val.val.str[pos+1] != '_'))
-                               break;
-                       if (n->val.val.str[pos] == '%' ||
-                                   n->val.val.str[pos] == '_' ||
-                                   n->val.val.str[pos] == '\\')
+                               if (n->val.val.str[pos] == '%' &&
+                                        n->val.val.str[pos+1] != '%')
+                                       break;
+                               if(n->val.val.str[pos] == '_')
+                                       break;
+                               if (n->val.val.str[pos] == '\\' ||
+                                       n->val.val.str[pos] == '%')
                                        pos++;
+                               if (n->val.val.str[pos] == '\0')
+                                       break;
                                match_least[match_pos] = n->val.val.str[pos];
                                match_most[match_pos++] = n->val.val.str[pos];
                        }
@@ -4100,12 +4795,25 @@ static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr)
 } /* makeIndexable() */
 
 
-/* xlateSqlType()
+/* xlateSqlFunc()
  * Convert alternate type names to internal Postgres types.
  * Do not convert "float", since that is handled elsewhere
  *  for FLOAT(p) syntax.
  */
 static char *
+xlateSqlFunc(char *name)
+{
+       if (!strcasecmp(name,"character_length")
+        || !strcasecmp(name,"char_length"))
+               return "length";
+       else
+               return name;
+} /* xlateSqlFunc() */
+
+/* xlateSqlType()
+ * Convert alternate type names to internal Postgres types.
+ */
+static char *
 xlateSqlType(char *name)
 {
        if (!strcasecmp(name,"int")
@@ -4113,7 +4821,8 @@ xlateSqlType(char *name)
                return "int4";
        else if (!strcasecmp(name, "smallint"))
                return "int2";
-       else if (!strcasecmp(name, "real"))
+       else if (!strcasecmp(name, "real")
+        || !strcasecmp(name, "float"))
                return "float8";
        else if (!strcasecmp(name, "interval"))
                return "timespan";
@@ -4121,7 +4830,7 @@ xlateSqlType(char *name)
                return "bool";
        else
                return name;
-} /* xlateSqlName() */
+} /* xlateSqlType() */
 
 
 void parser_init(Oid *typev, int nargs)
@@ -4173,10 +4882,10 @@ FlattenStringList(List *list)
        *(s+len) = '\0';
 
 #ifdef PARSEDEBUG
-printf( "flattened string is \"%s\"\n", s);
+       elog(DEBUG, "flattened string is \"%s\"\n", s);
 #endif
 
-       return(s);
+       return (s);
 } /* FlattenStringList() */
 
 
@@ -4186,33 +4895,48 @@ printf( "flattened string is \"%s\"\n", s);
 static List *
 makeConstantList( A_Const *n)
 {
+       List *result = NIL;
+       char *typval = NULL;
        char *defval = NULL;
+
        if (nodeTag(n) != T_A_Const) {
                elog(ERROR,"Cannot handle non-constant parameter");
 
        } else if (n->val.type == T_Float) {
                defval = (char*) palloc(20+1);
                sprintf( defval, "%g", n->val.val.dval);
+               result = lcons( makeString(defval), NIL);
 
        } else if (n->val.type == T_Integer) {
                defval = (char*) palloc(20+1);
                sprintf( defval, "%ld", n->val.val.ival);
+               result = lcons( makeString(defval), NIL);
 
        } else if (n->val.type == T_String) {
                defval = (char*) palloc(strlen( ((A_Const *) n)->val.val.str) + 3);
                strcpy( defval, "'");
                strcat( defval, ((A_Const *) n)->val.val.str);
                strcat( defval, "'");
+               if (n->typename != NULL)
+               {
+                       typval = (char*) palloc(strlen( n->typename->name) + 1);
+                       strcpy(typval, n->typename->name);
+                       result = lappend( lcons( makeString(typval), NIL), makeString(defval));
+               }
+               else
+               {
+                       result = lcons( makeString(defval), NIL);
+               }
 
        } else {
                elog(ERROR,"Internal error in makeConstantList(): cannot encode node");
        };
 
 #ifdef PARSEDEBUG
-printf( "AexprConst argument is \"%s\"\n", defval);
+       elog(DEBUG, "AexprConst argument is \"%s\"\n", defval);
 #endif
 
-       return( lcons( makeString(defval), NIL));
+       return (result);
 } /* makeConstantList() */
 
 
@@ -4238,10 +4962,11 @@ fmtId(char *rawid)
        };
 
 #ifdef PARSEDEBUG
-printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp);
+       elog(DEBUG, "fmtId- %sconvert %s to %s\n",
+        ((cp == rawid)? "do not ": ""), rawid, cp);
 #endif
 
-       return(cp);
+       return (cp);
 }
 
 /*