]> granicus.if.org Git - postgresql/blobdiff - src/backend/parser/gram.y
From: t-ishii@sra.co.jp
[postgresql] / src / backend / parser / gram.y
index 963d5adf0dc569798affb69d8b0fa2386cf45caf..0d3924590e5f3a7ab7be25bbd835c24484a8e4b7 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.83 1998/01/04 04:31:08 momjian 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 Node *saved_In_Expr;
+static List *saved_In_Expr = NIL;
 static Oid     *param_type_info;
 static int     pfunc_num_args;
 extern List *parsetree;
@@ -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;
@@ -108,7 +113,7 @@ Oid param_type(int t); /* used in parse_expr.c */
        VersionStmt                     *vstmt;
        DefineStmt                      *dstmt;
        RuleStmt                        *rstmt;
-       AppendStmt                      *astmt;
+       InsertStmt                      *astmt;
 }
 
 %type <node>   stmt,
@@ -116,18 +121,16 @@ Oid       param_type(int t); /* used in parse_expr.c */
                CopyStmt, CreateStmt, CreateAsStmt, CreateSeqStmt, DefineStmt, DestroyStmt,
                ExtendStmt, FetchStmt,  GrantStmt, CreateTrigStmt, DropTrigStmt,
                CreatePLangStmt, DropPLangStmt,
-               IndexStmt, ListenStmt, OptimizableStmt,
+               IndexStmt, ListenStmt, LockStmt, OptimizableStmt,
                ProcedureStmt,  RecipeStmt, RemoveAggrStmt, RemoveOperStmt,
                RemoveFuncStmt, RemoveStmt,
                RenameStmt, RevokeStmt, RuleStmt, TransactionStmt, ViewStmt, LoadStmt,
-               CreatedbStmt, DestroydbStmt, VacuumStmt, CursorStmt, SubSelect,
-               ReplaceStmt, AppendStmt, RetrieveStmt, NotifyStmt, DeleteStmt, ClusterStmt,
+               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
@@ -242,7 +256,7 @@ Oid param_type(int t); /* used in parse_expr.c */
  */
 
 /* Keywords (in SQL92 reserved words) */
-%token ACTION, ADD, ALL, ALTER, AND, AS, ASC,
+%token ACTION, ADD, ALL, ALTER, AND, ANY AS, ASC,
                BEGIN_TRANS, BETWEEN, BOTH, BY,
                CASCADE, CAST, CHAR, CHARACTER, CHECK, CLOSE, COLLATE, COLUMN, COMMIT, 
                CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, 
@@ -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, 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, RETRIEVE, 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
 %%
 
@@ -364,6 +378,7 @@ stmt :        AddAttrStmt
                | GrantStmt
                | IndexStmt
                | ListenStmt
+               | LockStmt
                | ProcedureStmt
                | RecipeStmt
                | RemoveAggrStmt
@@ -392,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);
@@ -413,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);
@@ -434,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;
@@ -442,7 +457,7 @@ DropUserStmt:  DROP USER Id
                                }
                ;
 
-user_passwd_clause:  WITH PASSWORD Id                  { $$ = $3; }
+user_passwd_clause:  WITH PASSWORD UserId              { $$ = $3; }
                        | /*EMPTY*/                                                     { $$ = NULL; }
                ;
 
@@ -476,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);
                                }
@@ -524,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; }
@@ -532,7 +558,7 @@ var_value:  Sconst                  { $$ = $1; }
 
 zone_value:  Sconst                    { $$ = $1; }
                | DEFAULT                       { $$ = NULL; }
-               | LOCAL                         { $$ = "default"; }
+               | LOCAL                         { $$ = NULL; }
                ;
 
 VariableShowStmt:  SHOW ColId
@@ -590,17 +616,17 @@ alter_clause:  ADD opt_column columnDef
                                        Node *lp = lfirst($3);
 
                                        if (length($3) != 1)
-                                               elog(WARN,"ALTER TABLE/ADD() allows one column only",NULL);
+                                               elog(ERROR,"ALTER TABLE/ADD() allows one column only");
                                        $$ = lp;
                                }
                        | DROP opt_column ColId
-                               {       elog(WARN,"ALTER TABLE/DROP COLUMN not yet implemented",NULL); }
+                               {       elog(ERROR,"ALTER TABLE/DROP COLUMN not yet implemented"); }
                        | ALTER opt_column ColId SET DEFAULT default_expr
-                               {       elog(WARN,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented",NULL); }
+                               {       elog(ERROR,"ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); }
                        | ALTER opt_column ColId DROP DEFAULT
-                               {       elog(WARN,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented",NULL); }
+                               {       elog(ERROR,"ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); }
                        | ADD ConstraintElem
-                               {       elog(WARN,"ALTER TABLE/ADD CONSTRAINT not yet implemented",NULL); }
+                               {       elog(ERROR,"ALTER TABLE/ADD CONSTRAINT not yet implemented"); }
                ;
 
 
@@ -693,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; }
                ;
 
@@ -718,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
@@ -780,7 +829,7 @@ ColConstraintElem:  CHECK '(' constraint_expr ')'
                                }
                        | REFERENCES ColId opt_column_list key_match key_actions
                                {
-                                       elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented",NULL);
+                                       elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
                                        $$ = NULL;
                                }
                ;
@@ -811,11 +860,11 @@ default_expr:  AexprConst
                        | default_expr '*' default_expr
                                {       $$ = nconc( $1, lcons( makeString( "*"), $3)); }
                        | default_expr '=' default_expr
-                               {       elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+                               {       elog(ERROR,"boolean expressions not supported in DEFAULT"); }
                        | default_expr '<' default_expr
-                               {       elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+                               {       elog(ERROR,"boolean expressions not supported in DEFAULT"); }
                        | default_expr '>' default_expr
-                               {       elog(WARN,"boolean expressions not supported in DEFAULT",NULL); }
+                               {       elog(ERROR,"boolean expressions not supported in DEFAULT"); }
                        | ':' default_expr
                                {       $$ = lcons( makeString( ":"), $2); }
                        | ';' default_expr
@@ -827,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);
@@ -848,7 +897,7 @@ default_expr:  AexprConst
                        | default_expr Op default_expr
                                {
                                        if (!strcmp("<=", $2) || !strcmp(">=", $2))
-                                               elog(WARN,"boolean expressions not supported in DEFAULT",NULL);
+                                               elog(ERROR,"boolean expressions not supported in DEFAULT");
                                        $$ = nconc( $1, lcons( makeString( $2), $3));
                                }
                        | Op default_expr
@@ -876,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
@@ -885,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
@@ -919,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",NULL); }
+                               {
+                                       elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
+                                       $$ = NULL;
+                               }
                ;
 
 constraint_list:  constraint_list ',' constraint_expr
@@ -968,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);
@@ -988,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
@@ -1050,7 +1106,7 @@ OptArchiveType:  ARCHIVE '=' NONE                                         { }
 
 CreateAsStmt:  CREATE TABLE relation_name OptCreateAs AS SubSelect
                                {
-                                       RetrieveStmt *n = (RetrieveStmt *)$6;
+                                       SelectStmt *n = (SelectStmt *)$6;
                                        if ($4 != NIL)
                                                mapTargetColumns($4, n->targetList);
                                        n->into = $3;
@@ -1086,7 +1142,7 @@ CreateAsElement:  ColId
  *
  *****************************************************************************/
 
-CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
+CreateSeqStmt:  CREATE SEQUENCE relation_name OptSeqList
                                {
                                        CreateSeqStmt *n = makeNode(CreateSeqStmt);
                                        n->seqname = $3;
@@ -1095,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;
+                               }
                ;
 
 /*****************************************************************************
@@ -1170,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(WARN,"parser: syntax error near %s",$2);
-                                               if ( strcmp ($3, "row") == 0 )
-                                                               $$ = TRUE;
-                                               else if ( strcmp ($3, "statement") == 0 )
-                                                               $$ = FALSE;
-                                               else
-                                                               elog(WARN,"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;
@@ -1307,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
                                {
@@ -1315,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"); }
                ;
 
 
@@ -1379,7 +1484,7 @@ opt_direction:    FORWARD                                                 { $$ = FORWARD; }
 
 fetch_how_many:  Iconst
                           { $$ = $1;
-                                if ($1 <= 0) elog(WARN,"Please specify nonnegative count for fetch",NULL); }
+                                if ($1 <= 0) elog(ERROR,"Please specify nonnegative count for fetch"); }
                | ALL                                                   { $$ = 0; /* 0 means fetch all tuples*/ }
                | /*EMPTY*/                                             { $$ = 1; /*default*/ }
                ;
@@ -1399,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,'+');
-                                       free($2);
-                                       free($6);
                                }
                ;
 
@@ -1425,7 +1528,6 @@ operation_commalist:  operation
                | operation_commalist ',' operation
                                {
                                                $$ = aclmakepriv($1,$3);
-                                               free($1);
                                }
                ;
 
@@ -1483,8 +1585,6 @@ opt_with_grant:  WITH GRANT OPTION
 RevokeStmt:  REVOKE privileges ON relation_name_list FROM grantee
                                {
                                        $$ = (Node*)makeAclStmt($2,$4,$6,'-');
-                                       free($2);
-                                       free($6);
                                }
                ;
 
@@ -1532,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;
@@ -1597,7 +1697,7 @@ RecipeStmt:  EXECUTE RECIPE recipe_name
                                {
                                        RecipeStmt *n;
                                        if (!IsTransactionBlock())
-                                               elog(WARN,"EXECUTE RECIPE may only be used in begin/end transaction blocks",NULL);
+                                               elog(ERROR,"EXECUTE RECIPE may only be used in begin/end transaction blocks");
 
                                        n = makeNode(RecipeStmt);
                                        n->recipeName = $3;
@@ -1622,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;
@@ -1636,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; }
+               ;
 
 /*****************************************************************************
  *
@@ -1677,6 +1795,7 @@ remove_type:  TYPE_P                                                      {  $$ = TYPE_P; }
                | VIEW                                                                  {  $$ = VIEW; }
                ;
 
+
 RemoveAggrStmt:  DROP AGGREGATE name aggr_argtype
                                {
                                                RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
@@ -1690,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 ')'
                                {
@@ -1725,7 +1842,7 @@ MathOp:   '+'                             { $$ = "+"; }
 
 oper_argtypes: name
                                {
-                                  elog(WARN,"parser: argument type missing (use NONE for unary operators)",NULL);
+                                  elog(ERROR,"parser: argument type missing (use NONE for unary operators)");
                                }
                | name ',' name
                                { $$ = makeList(makeString($1), makeString($3), -1); }
@@ -1835,7 +1952,7 @@ event:    SELECT                                                  { $$ = CMD_SELECT; }
                 ;
 
 opt_instead:  INSTEAD                                  { $$ = TRUE; }
-               | /*EMPTY*/                                     { $$ = FALSE; }
+               | /*EMPTY*/                                             { $$ = FALSE; }
                ;
 
 
@@ -1877,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; }
                ;
 
 
@@ -1955,11 +2039,15 @@ TransactionStmt:  ABORT_TRANS TRANSACTION
  *
  *****************************************************************************/
 
-ViewStmt:  CREATE VIEW name AS RetrieveStmt
+ViewStmt:  CREATE VIEW name AS SelectStmt
                                {
                                        ViewStmt *n = makeNode(ViewStmt);
                                        n->viewname = $3;
                                        n->query = (Query *)$5;
+                                       if (((SelectStmt *)n->query)->sortClause != NULL)
+                                               elog(ERROR,"Order by and Distinct on views is not implemented.");
+                                       if (((SelectStmt *)n->query)->unionClause != NULL)
+                                               elog(ERROR,"Views on unions not implemented.");
                                        $$ = (Node *)n;
                                }
                ;
@@ -1988,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; }
                ;
 
@@ -2006,6 +2123,11 @@ location:  Sconst                                                                { $$ = $1; }
                | /*EMPTY*/                                                             { $$ = NULL; }
                ;
 
+encoding:  Sconst                                                              { $$ = $1; }
+               | DEFAULT                                                               { $$ = NULL; }
+               | /*EMPTY*/                                                             { $$ = NULL; }
+               ;
+
 /*****************************************************************************
  *
  *             QUERY:
@@ -2063,7 +2185,7 @@ VacuumStmt:  VACUUM opt_verbose opt_analyze
                                        n->vacrel = $4;
                                        n->va_spec = $5;
                                        if ( $5 != NIL && !$4 )
-                                               elog(WARN,"parser: syntax error at or near \"(\"",NULL);
+                                               elog(ERROR,"parser: syntax error at or near \"(\"");
                                        $$ = (Node *)n;
                                }
                ;
@@ -2076,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
@@ -2117,10 +2237,10 @@ ExplainStmt:  EXPLAIN opt_verbose OptimizableStmt
  *                                                                                                                                                      *
  *****************************************************************************/
 
-OptimizableStmt:  RetrieveStmt
+OptimizableStmt:  SelectStmt
                | CursorStmt
-               | ReplaceStmt
-               | AppendStmt
+               | UpdateStmt
+               | InsertStmt
                | NotifyStmt
                | DeleteStmt                                    /* by default all are $$=$1 */
                ;
@@ -2133,7 +2253,7 @@ OptimizableStmt:  RetrieveStmt
  *
  *****************************************************************************/
 
-AppendStmt:  INSERT INTO relation_name opt_column_list insert_rest
+InsertStmt:  INSERT INTO relation_name opt_column_list insert_rest
                                {
                                        $5->relname = $3;
                                        $5->cols = $4;
@@ -2143,17 +2263,28 @@ AppendStmt:  INSERT INTO relation_name opt_column_list insert_rest
 
 insert_rest:  VALUES '(' res_target_list2 ')'
                                {
-                                       $$ = makeNode(AppendStmt);
+                                       $$ = makeNode(InsertStmt);
+                                       $$->unique = NULL;
                                        $$->targetList = $3;
                                        $$->fromClause = NIL;
                                        $$->whereClause = NULL;
+                                       $$->groupClause = NIL;
+                                       $$->havingClause = NULL;
+                                       $$->unionClause = NIL;
                                }
-               | SELECT res_target_list2 from_clause where_clause
+               | SELECT opt_unique res_target_list2
+                        from_clause where_clause
+                        group_clause having_clause
+                        union_clause
                                {
-                                       $$ = makeNode(AppendStmt);
-                                       $$->targetList = $2;
-                                       $$->fromClause = $3;
-                                       $$->whereClause = $4;
+                                       $$ = makeNode(InsertStmt);
+                                       $$->unique = $2;
+                                       $$->targetList = $3;
+                                       $$->fromClause = $4;
+                                       $$->whereClause = $5;
+                                       $$->groupClause = $6;
+                                       $$->havingClause = $7;
+                                       $$->unionClause = $8;
                                }
                ;
 
@@ -2195,20 +2326,42 @@ DeleteStmt:  DELETE FROM relation_name
                                }
                ;
 
+/*
+ *     Total hack to just lock a table inside a transaction.
+ *     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 opt_table relation_name
+                               {
+                                       DeleteStmt *n = makeNode(DeleteStmt);
+                                       A_Const *c = makeNode(A_Const);
+
+                                       c->val.type = T_String;
+                                       c->val.val.str = "f";
+                                       c->typename = makeNode(TypeName);
+                                       c->typename->name = xlateSqlType("bool");
+                                       c->typename->typmod = -1;
+
+                                       n->relname = $3;
+                                       n->whereClause = (Node *)c;
+                                       $$ = (Node *)n;
+                               }
+               ;
+
 
 /*****************************************************************************
  *
  *             QUERY:
- *                             ReplaceStmt (UPDATE)
+ *                             UpdateStmt (UPDATE)
  *
  *****************************************************************************/
 
-ReplaceStmt:  UPDATE relation_name
+UpdateStmt:  UPDATE relation_name
                          SET res_target_list
                          from_clause
                          where_clause
                                {
-                                       ReplaceStmt *n = makeNode(ReplaceStmt);
+                                       UpdateStmt *n = makeNode(UpdateStmt);
                                        n->relname = $2;
                                        n->targetList = $4;
                                        n->fromClause = $5;
@@ -2224,12 +2377,13 @@ ReplaceStmt:  UPDATE relation_name
  *                             CURSOR STATEMENTS
  *
  *****************************************************************************/
-
 CursorStmt:  DECLARE name opt_binary CURSOR FOR
-                        SELECT opt_unique res_target_list2
-                        from_clause where_clause group_clause sort_clause
+                        SELECT opt_unique res_target_list2
+                        from_clause where_clause
+                        group_clause having_clause
+                        union_clause sort_clause
                                {
-                                       CursorStmt *n = makeNode(CursorStmt);
+                                       SelectStmt *n = makeNode(SelectStmt);
 
                                        /* from PORTAL name */
                                        /*
@@ -2240,7 +2394,7 @@ CursorStmt:  DECLARE name opt_binary CURSOR FOR
                                         *                                                      -- mao
                                         */
                                        if (!IsTransactionBlock())
-                                               elog(WARN,"Named portals may only be used in begin/end transaction blocks",NULL);
+                                               elog(ERROR,"Named portals may only be used in begin/end transaction blocks");
 
                                        n->portalname = $2;
                                        n->binary = $3;
@@ -2249,7 +2403,9 @@ CursorStmt:  DECLARE name opt_binary CURSOR FOR
                                        n->fromClause = $9;
                                        n->whereClause = $10;
                                        n->groupClause = $11;
-                                       n->sortClause = $12;
+                                       n->havingClause = $12;
+                                       n->unionClause = $13;
+                                       n->sortClause = $14;
                                        $$ = (Node *)n;
                                }
                ;
@@ -2262,12 +2418,12 @@ CursorStmt:  DECLARE name opt_binary CURSOR FOR
  *
  *****************************************************************************/
 
-RetrieveStmt:  SELECT opt_unique res_target_list2
+SelectStmt:  SELECT opt_unique res_target_list2
                         result from_clause where_clause
                         group_clause having_clause
                         union_clause sort_clause
                                {
-                                       RetrieveStmt *n = makeNode(RetrieveStmt);
+                                       SelectStmt *n = makeNode(SelectStmt);
                                        n->unique = $2;
                                        n->targetList = $3;
                                        n->into = $4;
@@ -2281,9 +2437,26 @@ RetrieveStmt:  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
                                {
-                                       RetrieveStmt *n = (RetrieveStmt *)lfirst($3);
+                                       SelectStmt *n = (SelectStmt *)lfirst($3);
                                        n->unionall = $2;
                                        $$ = $3;
                                }
@@ -2291,21 +2464,21 @@ union_clause:  UNION opt_union select_list
                                { $$ = NIL; }
                ;
 
-select_list:  select_list UNION opt_union SubSelect
+select_list:  select_list UNION opt_union SubUnion
                                {
-                                       RetrieveStmt *n = (RetrieveStmt *)$4;
+                                       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
                                {
-                                       RetrieveStmt *n = makeNode(RetrieveStmt);
+                                       SelectStmt *n = makeNode(SelectStmt);
                                        n->unique = $2;
                                        n->unionall = FALSE;
                                        n->targetList = $3;
@@ -2317,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; }
@@ -2428,7 +2603,10 @@ groupby:  ColId
                                }
                ;
 
-having_clause:  HAVING a_expr                                  { $$ = $2; }
+having_clause:  HAVING a_expr
+                               {
+                                       $$ = $2;
+                               }
                | /*EMPTY*/                                                             { $$ = NULL; }
                ;
 
@@ -2444,7 +2622,7 @@ having_clause:  HAVING a_expr                                     { $$ = $2; }
 from_clause:  FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
                                {
                                        $$ = NIL;
-                                       elog(WARN,"JOIN not yet implemented",NULL);
+                                       elog(ERROR,"JOIN not yet implemented");
                                }
                | FROM from_list                                                { $$ = $2; }
                | /*EMPTY*/                                                             { $$ = NIL; }
@@ -2453,7 +2631,7 @@ from_clause:  FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
 from_list:     from_list ',' from_val
                                { $$ = lappend($1, $3); }
                | from_val CROSS JOIN from_val
-                               { elog(WARN,"CROSS JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"CROSS JOIN not yet implemented"); }
                | from_val
                                { $$ = lcons($1, NIL); }
                ;
@@ -2480,19 +2658,19 @@ from_val:  relation_expr AS ColLabel
 
 join_expr:  NATURAL join_expr                                  { $$ = NULL; }
                | FULL join_outer
-                               { elog(WARN,"FULL OUTER JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"FULL OUTER JOIN not yet implemented"); }
                | LEFT join_outer
-                               { elog(WARN,"LEFT OUTER JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"LEFT OUTER JOIN not yet implemented"); }
                | RIGHT join_outer
-                               { elog(WARN,"RIGHT OUTER JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"RIGHT OUTER JOIN not yet implemented"); }
                | OUTER_P
-                               { elog(WARN,"OUTER JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"OUTER JOIN not yet implemented"); }
                | INNER_P
-                               { elog(WARN,"INNER JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"INNER JOIN not yet implemented"); }
                | UNION
-                               { elog(WARN,"UNION JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"UNION JOIN not yet implemented"); }
                | /*EMPTY*/
-                               { elog(WARN,"INNER JOIN not yet implemented",NULL); }
+                               { elog(ERROR,"INNER JOIN not yet implemented"); }
                ;
 
 join_outer:  OUTER_P                                                   { $$ = NULL; }
@@ -2619,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
@@ -2637,29 +2815,47 @@ 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)
-                                               elog(WARN,"precision for FLOAT must be at least 1",NULL);
+                                               elog(ERROR,"precision for FLOAT must be at least 1");
                                        else if ($2 < 7)
                                                $$ = xlateSqlType("float4");
                                        else if ($2 < 16)
                                                $$ = xlateSqlType("float8");
                                        else
-                                               elog(WARN,"precision for FLOAT must be less than 16",NULL);
+                                               elog(ERROR,"precision for FLOAT must be less than 16");
                                }
                | /*EMPTY*/
                                {
@@ -2670,14 +2866,14 @@ opt_float:  '(' Iconst ')'
 opt_numeric:  '(' Iconst ',' Iconst ')'
                                {
                                        if ($2 != 9)
-                                               elog(WARN,"NUMERIC precision %d must be 9",$2);
+                                               elog(ERROR,"NUMERIC precision %d must be 9",$2);
                                        if ($4 != 0)
-                                               elog(WARN,"NUMERIC scale %d must be zero",$4);
+                                               elog(ERROR,"NUMERIC scale %d must be zero",$4);
                                }
                | '(' Iconst ')'
                                {
                                        if ($2 != 9)
-                                               elog(WARN,"NUMERIC precision %d must be 9",$2);
+                                               elog(ERROR,"NUMERIC precision %d must be 9",$2);
                                }
                | /*EMPTY*/
                                {
@@ -2688,15 +2884,15 @@ opt_numeric:  '(' Iconst ',' Iconst ')'
 opt_decimal:  '(' Iconst ',' Iconst ')'
                                {
                                        if ($2 > 9)
-                                               elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
+                                               elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
                                        if ($4 != 0)
-                                               elog(WARN,"DECIMAL scale %d must be zero",$4);
+                                               elog(ERROR,"DECIMAL scale %d must be zero",$4);
                                        $$ = NULL;
                                }
                | '(' Iconst ')'
                                {
                                        if ($2 > 9)
-                                               elog(WARN,"DECIMAL precision %d exceeds implementation limit of 9",$2);
+                                               elog(ERROR,"DECIMAL precision %d exceeds implementation limit of 9",$2);
                                        $$ = NULL;
                                }
                | /*EMPTY*/
@@ -2715,33 +2911,46 @@ 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(WARN,"length for '%s' type must be at least 1",$1);
+                                               elog(ERROR,"length for '%s' type must be at least 1",$1);
                                        else if ($3 > 4096)
                                                /* we can store a char() of length up to the size
                                                 * of a page (8KB) - page headers and friends but
                                                 * just to be safe here...      - ay 6/95
                                                 * XXX note this hardcoded limit - thomas 1997-07-13
                                                 */
-                                               elog(WARN,"length for type '%s' cannot exceed 4096",$1);
+                                               elog(ERROR,"length for type '%s' cannot exceed 4096",$1);
 
                                        /* we actually implement this sort of like a varlen, so
                                         * the first 4 bytes is the length. (the difference
                                         * between this and "text" is that we blank-pad and
                                         * truncate where necessary
                                         */
-                                       $$->typlen = VARHDRSZ + $3;
+                                       $$->typmod = VARHDRSZ + $3;
                                }
                | 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;
+                                       }
                                }
                ;
 
@@ -2762,7 +2971,7 @@ character:  CHARACTER opt_varying opt_charset opt_collate
                                                }
                                        };
                                        if ($4 != NULL)
-                                       elog(WARN,"COLLATE %s not yet implemented",$4);
+                                               elog(NOTICE,"COLLATE %s not yet implemented; clause ignored",$4);
                                        $$ = type;
                                }
                | CHAR opt_varying                                              { $$ = xlateSqlType($2? "varchar": "char"); }
@@ -2787,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;
                                }
                ;
 
@@ -2825,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; }
                ;
 
@@ -2848,28 +3062,59 @@ 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 ')'
                                {
-                                       $$ = NULL;
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = $2;
+                                       n->oper = lcons("=",NIL);
+                                       n->useor = false;
+                                       n->subLinkType = ANY_SUBLINK;
+                                       n->subselect = $6;
+                                       $$ = (Node *)n;
                                }
                | '(' row_descriptor ')' NOT IN '(' SubSelect ')'
                                {
-                                       $$ = NULL;
-                               }
-               | '(' row_descriptor ')' '=' '(' row_descriptor ')'
-                               {
-                                       $$ = makeRowExpr("=", $2, $6);
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = $2;
+                                       n->oper = lcons("<>",NIL);
+                                       n->useor = true;
+                                       n->subLinkType = ALL_SUBLINK;
+                                       n->subselect = $7;
+                                       $$ = (Node *)n;
                                }
-               | '(' row_descriptor ')' '<' '(' row_descriptor ')'
+               | '(' row_descriptor ')' row_op sub_type '(' SubSelect ')'
                                {
-                                       $$ = makeRowExpr("<", $2, $6);
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = $2;
+                                       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 ')' '>' '(' row_descriptor ')'
+               | '(' row_descriptor ')' row_op '(' SubSelect ')'
                                {
-                                       $$ = makeRowExpr("<", $2, $6);
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = $2;
+                                       n->oper = lcons($4, NIL);
+                                       if (strcmp($4,"<>") == 0)
+                                               n->useor = true;
+                                       else
+                                               n->useor = false;
+                                       n->subLinkType = EXPR_SUBLINK;
+                                       n->subselect = $6;
+                                       $$ = (Node *)n;
                                }
-               | '(' row_descriptor ')' Op '(' row_descriptor ')'
+               | '(' row_descriptor ')' row_op '(' row_descriptor ')'
                                {
                                        $$ = makeRowExpr($4, $2, $6);
                                }
@@ -2891,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;
@@ -2900,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
@@ -2938,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;
                                        }
                                }
@@ -2966,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);
@@ -2986,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;
@@ -3011,7 +3278,8 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("date");
                                        t->setof = FALSE;
-
+                                       t->typmod = -1;
                                        $$ = (Node *)n;
                                }
                | CURRENT_TIME
@@ -3025,6 +3293,7 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("time");
                                        t->setof = FALSE;
+                                       t->typmod = -1;
 
                                        $$ = (Node *)n;
                                }
@@ -3043,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);
@@ -3060,6 +3330,7 @@ a_expr:  attr opt_indirection
 
                                        t->name = xlateSqlType("timestamp");
                                        t->setof = FALSE;
+                                       t->typmod = -1;
 
                                        $$ = (Node *)n;
                                }
@@ -3078,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);
@@ -3091,15 +3363,22 @@ a_expr:  attr opt_indirection
                                        n->args = NIL;
                                        $$ = (Node *)n;
                                }
-               /* We probably need to define an "exists" node,
-                *      since the optimizer could choose to find only one match.
-                * Perhaps the first implementation could just check for
-                *      count(*) > 0? - thomas 1997-07-19
-                */
+               | USER
+                               {
+                                       FuncCall *n = makeNode(FuncCall);
+                                       n->funcname = "getpgusername";
+                                       n->args = NIL;
+                                       $$ = (Node *)n;
+                               }
                | EXISTS '(' SubSelect ')'
                                {
-                                       elog(WARN,"EXISTS not yet implemented",NULL);
-                                       $$ = $3;
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = NIL;
+                                       n->useor = false;
+                                       n->oper = NIL;
+                                       n->subLinkType = EXISTS_SUBLINK;
+                                       n->subselect = $3;
+                                       $$ = (Node *)n;
                                }
                | EXTRACT '(' extract_list ')'
                                {
@@ -3171,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
@@ -3180,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
@@ -3189,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
@@ -3198,24 +3480,289 @@ 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 = $1; } '(' in_expr ')'
-                               {       $$ = $5; }
-               | a_expr NOT IN { saved_In_Expr = $1; } '(' not_in_expr ')'
-                               {       $$ = $6; }
+               | 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;
+                                                       n->lefthand = lcons($1, NIL);
+                                                       n->oper = lcons("=",NIL);
+                                                       n->useor = false;
+                                                       n->subLinkType = ANY_SUBLINK;
+                                                       $$ = (Node *)n;
+                                       }
+                                       else    $$ = $5;
+                               }
+               | 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;
+                                                       n->lefthand = lcons($1, NIL);
+                                                       n->oper = lcons("<>",NIL);
+                                                       n->useor = false;
+                                                       n->subLinkType = ALL_SUBLINK;
+                                                       $$ = (Node *)n;
+                                       }
+                                       else    $$ = $6;
+                               }
+               | a_expr Op '(' SubSelect ')'
+                               {
+                                       SubLink *n = makeNode(SubLink);
+                                       n->lefthand = lcons($1, NULL);
+                                       n->oper = lcons($2,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 '>' '(' 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
@@ -3224,6 +3771,245 @@ a_expr:  attr opt_indirection
                                {       $$ = 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);
@@ -3250,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;
@@ -3261,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 */
@@ -3302,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;
                                        }
                                }
@@ -3334,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;
@@ -3428,35 +4219,37 @@ trim_list:  a_expr FROM expr_list
 
 in_expr:  SubSelect
                                {
-                                       elog(WARN,"IN (SUBSELECT) not yet implemented",NULL);
-                                       $$ = $1;
+                                       SubLink *n = makeNode(SubLink);
+                                       n->subselect = $1;
+                                       $$ = (Node *)n;
                                }
                | in_expr_nodes
                                {       $$ = $1; }
                ;
 
 in_expr_nodes:  AexprConst
-                               {       $$ = makeA_Expr(OP, "=", saved_In_Expr, $1); }
+                               {       $$ = makeA_Expr(OP, "=", lfirst(saved_In_Expr), $1); }
                | in_expr_nodes ',' AexprConst
                                {       $$ = makeA_Expr(OR, NULL, $1,
-                                               makeA_Expr(OP, "=", saved_In_Expr, $3));
+                                               makeA_Expr(OP, "=", lfirst(saved_In_Expr), $3));
                                }
                ;
 
 not_in_expr:  SubSelect
                                {
-                                       elog(WARN,"NOT IN (SUBSELECT) not yet implemented",NULL);
-                                       $$ = $1;
+                                       SubLink *n = makeNode(SubLink);
+                                       n->subselect = $1;
+                                       $$ = (Node *)n;
                                }
                | not_in_expr_nodes
                                {       $$ = $1; }
                ;
 
 not_in_expr_nodes:  AexprConst
-                               {       $$ = makeA_Expr(OP, "<>", saved_In_Expr, $1); }
+                               {       $$ = makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $1); }
                | not_in_expr_nodes ',' AexprConst
                                {       $$ = makeA_Expr(AND, NULL, $1,
-                                               makeA_Expr(OP, "<>", saved_In_Expr, $3));
+                                               makeA_Expr(OP, "<>", lfirst(saved_In_Expr), $3));
                                }
                ;
 
@@ -3542,7 +4335,7 @@ res_target_el:  ColId opt_indirection '=' a_expr_or_null
 
 /*
 ** target list for select.
-** should get rid of the other but is still needed by the defunct retrieve into
+** should get rid of the other but is still needed by the defunct select into
 ** and update (uses a subset)
 */
 res_target_list2:  res_target_list2 ',' res_target_el2
@@ -3606,7 +4399,7 @@ relation_name:    SpecialRuleRelation
                                        /* disallow refs to variable system tables */
                                        if (strcmp(LogRelationName, $1) == 0
                                           || strcmp(VariableRelationName, $1) == 0)
-                                               elog(WARN,"%s cannot be accessed by users",$1);
+                                               elog(ERROR,"%s cannot be accessed by users",$1);
                                        else
                                                $$ = $1;
                                        StrNCpy(saved_relname, $1, NAMEDATALEN);
@@ -3614,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
@@ -3624,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
@@ -3669,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
@@ -3678,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;
                                }
                ;
@@ -3689,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
@@ -3711,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"; }
                ;
@@ -3765,14 +4578,14 @@ SpecialRuleRelation:  CURRENT
                                        if (QueryIsRule)
                                                $$ = "*CURRENT*";
                                        else
-                                               elog(WARN,"CURRENT used in non-rule query",NULL);
+                                               elog(ERROR,"CURRENT used in non-rule query");
                                }
                | NEW
                                {
                                        if (QueryIsRule)
                                                $$ = "*NEW*";
                                        else
-                                               elog(WARN,"NEW used in non-rule query",NULL);
+                                               elog(ERROR,"NEW used in non-rule query");
                                }
                ;
 
@@ -3800,7 +4613,7 @@ makeRowExpr(char *opr, List *largs, List *rargs)
        Node *larg, *rarg;
 
        if (length(largs) != length(rargs))
-               elog(WARN,"Unequal number of entries in row expression",NULL);
+               elog(ERROR,"Unequal number of entries in row expression");
 
        if (lnext(largs) != NIL)
                expr = makeRowExpr(opr,lnext(largs),lnext(rargs));
@@ -3828,7 +4641,7 @@ makeRowExpr(char *opr, List *largs, List *rargs)
        }
        else
        {
-               elog(WARN,"Operator '%s' not implemented for row expressions",opr);
+               elog(ERROR,"Operator '%s' not implemented for row expressions",opr);
        }
 
 #if FALSE
@@ -3849,7 +4662,7 @@ makeRowExpr(char *opr, List *largs, List *rargs)
 #endif
 
        return expr;
-} /* makeRowExpr() */
+}
 
 void
 mapTargetColumns(List *src, List *dst)
@@ -3858,7 +4671,7 @@ mapTargetColumns(List *src, List *dst)
        ResTarget *d;
 
        if (length(src) != length(dst))
-               elog(WARN,"CREATE TABLE/AS SELECT has mismatched column count",NULL);
+               elog(ERROR,"CREATE TABLE/AS SELECT has mismatched column count");
 
        while ((src != NIL) && (dst != NIL))
        {
@@ -3940,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];
                        }
@@ -3981,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")
@@ -3994,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";
@@ -4002,7 +4830,7 @@ xlateSqlType(char *name)
                return "bool";
        else
                return name;
-} /* xlateSqlName() */
+} /* xlateSqlType() */
 
 
 void parser_init(Oid *typev, int nargs)
@@ -4054,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() */
 
 
@@ -4067,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(WARN,"Cannot handle non-constant parameter",NULL);
+               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(WARN,"Internal error in makeConstantList(): cannot encode node",NULL);
+               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() */
 
 
@@ -4119,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);
 }
 
 /*