Allow TIMESTAMP, VARCHAR, et al to be used as unquoted column names,
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 10 Nov 2001 22:31:49 +0000 (22:31 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 10 Nov 2001 22:31:49 +0000 (22:31 +0000)
though alas not as unquoted function names.  De-reserve a bunch of
keywords that could have been in ColId rather than ColLabel all along.
Per recent proposal in pgsql-patches.

src/backend/parser/gram.y
src/interfaces/ecpg/preproc/preproc.y

index 63465c916861ce5d257989489aa753b7edd2282e..6c6b7e359c9d9a19e2790926ed4796510555eaf8 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.272 2001/11/05 05:00:14 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.273 2001/11/10 22:31:49 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -257,8 +257,8 @@ static void doNegateFloat(Value *v);
 %type <paramno> ParamNo
 
 %type <typnam> Typename, SimpleTypename, ConstTypename
-               GenericType, Numeric, Geometric, Character, ConstDatetime, ConstInterval, Bit
-%type <str>        character, datetime, bit
+               GenericType, Numeric, Character, ConstDatetime, ConstInterval, Bit
+%type <str>        character, bit
 %type <str>        extract_arg
 %type <str>        opt_charset, opt_collate
 %type <str>        opt_float
@@ -268,7 +268,7 @@ static void doNegateFloat(Value *v);
 %type <ival>   Iconst
 %type <str>        Sconst, comment_text
 %type <str>        UserId, opt_boolean, var_value, ColId_or_Sconst
-%type <str>        ColId, ColLabel, TokenId
+%type <str>        ColId, TypeFuncId, ColLabel
 %type <node>   zone_value
 
 %type <node>   TableConstraint
@@ -1007,11 +1007,11 @@ constraints_set_list:   ALL
        ;
 
 
-constraints_set_namelist:  IDENT
+constraints_set_namelist:  ColId
                {
                    $$ = makeList1($1);
                }
-       | constraints_set_namelist ',' IDENT
+       | constraints_set_namelist ',' ColId
                {
                    $$ = lappend($1, $3);
                }
@@ -2007,8 +2007,8 @@ def_elem:  ColLabel '=' def_arg
                }
        ;
 
+/* Note: any simple identifier will be returned as a type name! */
 def_arg:  func_return                      {  $$ = (Node *)$1; }
-       | TokenId                       {  $$ = (Node *)makeString($1); }
        | all_Op                        {  $$ = (Node *)makeString($1); }
        | NumericOnly                   {  $$ = (Node *)$1; }
        | Sconst                        {  $$ = (Node *)makeString($1); }
@@ -2629,11 +2629,15 @@ func_return:  func_type
                }
        ;
 
+/*
+ * We would like to make the second production here be ColId '.' ColId etc,
+ * but that causes reduce/reduce conflicts.  TypeFuncId is next best choice.
+ */
 func_type: Typename
                {
                    $$ = $1;
                }
-       | IDENT '.' ColId '%' TYPE_P
+       | TypeFuncId '.' ColId '%' TYPE_P
                {
                    $$ = makeNode(TypeName);
                    $$->name = $1;
@@ -4064,13 +4068,12 @@ SimpleTypename:  ConstTypename
 
 ConstTypename:  GenericType
        | Numeric
-       | Geometric
        | Bit
        | Character
        | ConstDatetime
        ;
 
-GenericType:  IDENT
+GenericType:  TypeFuncId
                {
                    $$ = makeNode(TypeName);
                    $$->name = xlateSqlType($1);
@@ -4086,7 +4089,7 @@ GenericType:  IDENT
 Numeric:  FLOAT opt_float
                {
                    $$ = makeNode(TypeName);
-                   $$->name = xlateSqlType($2);
+                   $$->name = $2; /* already xlated */
                    $$->typmod = -1;
                }
        | DOUBLE PRECISION
@@ -4115,14 +4118,6 @@ Numeric:  FLOAT opt_float
                }
        ;
 
-Geometric:  PATH_P
-               {
-                   $$ = makeNode(TypeName);
-                   $$->name = xlateSqlType("path");
-                   $$->typmod = -1;
-               }
-       ;
-
 opt_float:  '(' Iconst ')'
                {
                    if ($2 < 1)
@@ -4299,13 +4294,7 @@ opt_collate:  COLLATE ColId                      { $$ = $2; }
        | /*EMPTY*/                             { $$ = NULL; }
        ;
 
-ConstDatetime:  datetime
-               {
-                   $$ = makeNode(TypeName);
-                   $$->name = xlateSqlType($1);
-                   $$->typmod = -1;
-               }
-       | TIMESTAMP '(' Iconst ')' opt_timezone_x
+ConstDatetime:  TIMESTAMP '(' Iconst ')' opt_timezone_x
                {
                    $$ = makeNode(TypeName);
                    if ($5)
@@ -4371,14 +4360,6 @@ ConstInterval:  INTERVAL
                }
        ;
 
-datetime:  YEAR_P                              { $$ = "year"; }
-       | MONTH_P                               { $$ = "month"; }
-       | DAY_P                                 { $$ = "day"; }
-       | HOUR_P                                { $$ = "hour"; }
-       | MINUTE_P                              { $$ = "minute"; }
-       | SECOND_P                              { $$ = "second"; }
-       ;
-
 /* XXX Make the default be WITH TIME ZONE for 7.2 to help with database upgrades
  * but revert this back to WITHOUT TIME ZONE for 7.3.
  * Do this by simply reverting opt_timezone_x to opt_timezone - thomas 2001-09-06
@@ -5270,9 +5251,14 @@ extract_list:  extract_arg FROM a_expr
  * - thomas 2001-04-12
  */
 
-extract_arg:  datetime                     { $$ = $1; }
-       | SCONST                            { $$ = $1; }
-       | IDENT                             { $$ = $1; }
+extract_arg:  IDENT                        { $$ = $1; }
+       | YEAR_P                        { $$ = "year"; }
+       | MONTH_P                       { $$ = "month"; }
+       | DAY_P                         { $$ = "day"; }
+       | HOUR_P                        { $$ = "hour"; }
+       | MINUTE_P                      { $$ = "minute"; }
+       | SECOND_P                      { $$ = "second"; }
+       | SCONST                        { $$ = $1; }
        ;
 
 /* position_list uses b_expr not a_expr to avoid conflict with general IN */
@@ -5555,32 +5541,6 @@ access_method:           ColId           { $$ = $1; };
 attr_name:             ColId           { $$ = $1; };
 class:                 ColId           { $$ = $1; };
 index_name:                ColId           { $$ = $1; };
-
-/* Functions
- * Include date/time keywords as SQL92 extension.
- * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
- * Any tokens which show up as operators will screw up the parsing if
- * allowed as identifiers, but are acceptable as ColLabels:
- *  BETWEEN, IN, IS, ISNULL, NOTNULL, OVERLAPS
- * Thanks to Tom Lane for pointing this out. - thomas 2000-03-29
- * We need OVERLAPS allowed as a function name to enable the implementation
- *  of argument type variations on the underlying implementation. These
- *  variations are done as SQL-language entries in the pg_proc catalog.
- * Do not include SUBSTRING here since it has explicit productions
- *  in a_expr to support the goofy SQL9x argument syntax.
- *  - thomas 2000-11-28
- */
-func_name:  ColId                      { $$ = xlateSqlFunc($1); }
-       | BETWEEN                       { $$ = xlateSqlFunc("between"); }
-       | ILIKE                         { $$ = xlateSqlFunc("ilike"); }
-       | IN                            { $$ = xlateSqlFunc("in"); }
-       | IS                            { $$ = xlateSqlFunc("is"); }
-       | ISNULL                        { $$ = xlateSqlFunc("isnull"); }
-       | LIKE                          { $$ = xlateSqlFunc("like"); }
-       | NOTNULL                       { $$ = xlateSqlFunc("notnull"); }
-       | OVERLAPS                      { $$ = xlateSqlFunc("overlaps"); }
-       ;
-
 file_name:             Sconst          { $$ = $1; };
 
 /* Constants
@@ -5692,27 +5652,23 @@ Iconst:  ICONST                         { $$ = $1; };
 Sconst:  SCONST                            { $$ = $1; };
 UserId:  ColId                         { $$ = $1; };
 
-/* Column identifier
- * Include date/time keywords as SQL92 extension.
- * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
- * Add other keywords. Note that as the syntax expands,
- *  some of these keywords will have to be removed from this
- *  list due to shift/reduce conflicts in yacc. If so, move
- *  down to the ColLabel entity. - thomas 1997-11-06
+/*
+ * Keyword classification lists.  Generally, every keyword present in
+ * the Postgres grammar should be in one of these lists.  (Presently,
+ * "AS" is the sole exception: it is our only completely-reserved word.)
+ *
+ * Put a new keyword into the earliest list (of TypeFuncId, ColId, ColLabel)
+ * that it can go into without creating shift or reduce conflicts.  The
+ * earlier lists define "less reserved" categories of keywords.  Notice that
+ * each list includes by reference the ones before it.
  */
-ColId:  IDENT                          { $$ = $1; }
-       | datetime                      { $$ = $1; }
-       | TokenId                       { $$ = $1; }
-       | NATIONAL                      { $$ = "national"; }
-       | NONE                          { $$ = "none"; }
-       | PATH_P                        { $$ = "path"; }
-       ;
 
-/* Parser tokens to be used as identifiers.
- * Tokens involving data types should appear in ColId only,
- * since they will conflict with real TypeName productions.
+/* Type/func identifier --- names that can be type and function names
+ * (as well as ColIds --- ie, these are completely unreserved keywords).
  */
-TokenId:  ABSOLUTE                     { $$ = "absolute"; }
+TypeFuncId:  IDENT                     { $$ = $1; }
+       | ABORT_TRANS                   { $$ = "abort"; }
+       | ABSOLUTE                      { $$ = "absolute"; }
        | ACCESS                        { $$ = "access"; }
        | ACTION                        { $$ = "action"; }
        | ADD                           { $$ = "add"; }
@@ -5731,16 +5687,19 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | CHARACTERISTICS               { $$ = "characteristics"; }
        | CHECKPOINT                    { $$ = "checkpoint"; }
        | CLOSE                         { $$ = "close"; }
+       | CLUSTER                       { $$ = "cluster"; }
        | COMMENT                       { $$ = "comment"; }
        | COMMIT                        { $$ = "commit"; }
        | COMMITTED                     { $$ = "committed"; }
        | CONSTRAINTS                   { $$ = "constraints"; }
+       | COPY                          { $$ = "copy"; }
        | CREATE                        { $$ = "create"; }
        | CREATEDB                      { $$ = "createdb"; }
        | CREATEUSER                    { $$ = "createuser"; }
        | CURSOR                        { $$ = "cursor"; }
        | CYCLE                         { $$ = "cycle"; }
        | DATABASE                      { $$ = "database"; }
+       | DAY_P                         { $$ = "day"; }
        | DECLARE                       { $$ = "declare"; }
        | DEFERRED                      { $$ = "deferred"; }
        | DELETE                        { $$ = "delete"; }
@@ -5753,16 +5712,20 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | ESCAPE                        { $$ = "escape"; }
        | EXCLUSIVE                     { $$ = "exclusive"; }
        | EXECUTE                       { $$ = "execute"; }
+       | EXPLAIN                       { $$ = "explain"; }
        | FETCH                         { $$ = "fetch"; }
        | FORCE                         { $$ = "force"; }
        | FORWARD                       { $$ = "forward"; }
        | FUNCTION                      { $$ = "function"; }
+       | GLOBAL                        { $$ = "global"; }
        | GRANT                         { $$ = "grant"; }
        | HANDLER                       { $$ = "handler"; }
+       | HOUR_P                        { $$ = "hour"; }
        | IMMEDIATE                     { $$ = "immediate"; }
        | INCREMENT                     { $$ = "increment"; }
        | INDEX                         { $$ = "index"; }
        | INHERITS                      { $$ = "inherits"; }
+       | INOUT                         { $$ = "inout"; }
        | INSENSITIVE                   { $$ = "insensitive"; }
        | INSERT                        { $$ = "insert"; }
        | INSTEAD                       { $$ = "instead"; }
@@ -5771,12 +5734,20 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | LANGUAGE                      { $$ = "language"; }
        | LANCOMPILER                   { $$ = "lancompiler"; }
        | LEVEL                         { $$ = "level"; }
+       | LISTEN                        { $$ = "listen"; }
+       | LOAD                          { $$ = "load"; }
+       | LOCAL                         { $$ = "local"; }
        | LOCATION                      { $$ = "location"; }
+       | LOCK_P                        { $$ = "lock"; }
        | MATCH                         { $$ = "match"; }
        | MAXVALUE                      { $$ = "maxvalue"; }
+       | MINUTE_P                      { $$ = "minute"; }
        | MINVALUE                      { $$ = "minvalue"; }
        | MODE                          { $$ = "mode"; }
+       | MONTH_P                       { $$ = "month"; }
+       | MOVE                          { $$ = "move"; }
        | NAMES                         { $$ = "names"; }
+       | NATIONAL                      { $$ = "national"; }
        | NEXT                          { $$ = "next"; }
        | NO                            { $$ = "no"; }
        | NOCREATEDB                    { $$ = "nocreatedb"; }
@@ -5787,10 +5758,13 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | OIDS                          { $$ = "oids"; }
        | OPERATOR                      { $$ = "operator"; }
        | OPTION                        { $$ = "option"; }
+       | OUT                           { $$ = "out"; }
        | OWNER                         { $$ = "owner"; }
        | PARTIAL                       { $$ = "partial"; }
        | PASSWORD                      { $$ = "password"; }
+       | PATH_P                        { $$ = "path"; }
        | PENDANT                       { $$ = "pendant"; }
+       | PRECISION                     { $$ = "precision"; }
        | PRIOR                         { $$ = "prior"; }
        | PRIVILEGES                    { $$ = "privileges"; }
        | PROCEDURAL                    { $$ = "procedural"; }
@@ -5800,6 +5774,7 @@ TokenId:  ABSOLUTE                        { $$ = "absolute"; }
        | RELATIVE                      { $$ = "relative"; }
        | RENAME                        { $$ = "rename"; }
        | REPLACE                       { $$ = "replace"; }
+       | RESET                         { $$ = "reset"; }
        | RESTRICT                      { $$ = "restrict"; }
        | RETURNS                       { $$ = "returns"; }
        | REVOKE                        { $$ = "revoke"; }
@@ -5808,11 +5783,13 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | RULE                          { $$ = "rule"; }
        | SCHEMA                        { $$ = "schema"; }
        | SCROLL                        { $$ = "scroll"; }
+       | SECOND_P                      { $$ = "second"; }
        | SESSION                       { $$ = "session"; }
        | SEQUENCE                      { $$ = "sequence"; }
        | SERIALIZABLE                  { $$ = "serializable"; }
        | SET                           { $$ = "set"; }
        | SHARE                         { $$ = "share"; }
+       | SHOW                          { $$ = "show"; }
        | START                         { $$ = "start"; }
        | STATEMENT                     { $$ = "statement"; }
        | STATISTICS                    { $$ = "statistics"; }
@@ -5823,14 +5800,17 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | TEMPLATE                      { $$ = "template"; }
        | TEMPORARY                     { $$ = "temporary"; }
        | TOAST                         { $$ = "toast"; }
+       | TRANSACTION                   { $$ = "transaction"; }
        | TRIGGER                       { $$ = "trigger"; }
        | TRUNCATE                      { $$ = "truncate"; }
        | TRUSTED                       { $$ = "trusted"; }
        | TYPE_P                        { $$ = "type"; }
        | UNENCRYPTED                   { $$ = "unencrypted"; }
+       | UNKNOWN                       { $$ = "unknown"; }
        | UNLISTEN                      { $$ = "unlisten"; }
        | UNTIL                         { $$ = "until"; }
        | UPDATE                        { $$ = "update"; }
+       | VACUUM                        { $$ = "vacuum"; }
        | VALID                         { $$ = "valid"; }
        | VALUES                        { $$ = "values"; }
        | VARYING                       { $$ = "varying"; }
@@ -5839,21 +5819,45 @@ TokenId:  ABSOLUTE                      { $$ = "absolute"; }
        | WITH                          { $$ = "with"; }
        | WITHOUT                       { $$ = "without"; }
        | WORK                          { $$ = "work"; }
+       | YEAR_P                        { $$ = "year"; }
        | ZONE                          { $$ = "zone"; }
        ;
 
-/* Column label
- * Allowed labels in "AS" clauses.
- * Include TRUE/FALSE SQL3 reserved words for Postgres backward
- *  compatibility. Cannot allow this for column names since the
- *  syntax would not distinguish between the constant value and
- *  a column name. - thomas 1997-10-24
- * Add other keywords to this list. Note that they appear here
- *  rather than in ColId if there was a shift/reduce conflict
- *  when used as a full identifier. - thomas 1997-11-06
+/* Column identifier --- names that can be column, table, etc names.
+ *
+ * This contains the TypeFuncId list plus those keywords that conflict
+ * only with typename productions, not with other uses.  Note that
+ * most of these keywords will in fact be recognized as type names too;
+ * they just have to have special productions for the purpose.
+ *
+ * Most of these cannot be in TypeFuncId (ie, are not also usable as function
+ * names) because they can be followed by '(' in typename productions, which
+ * looks too much like a function call for a LALR(1) parser.
+ */
+ColId:  TypeFuncId                     { $$ = $1; }
+       | BIT                           { $$ = "bit"; }
+       | CHAR                          { $$ = "char"; }
+       | CHARACTER                     { $$ = "character"; }
+       | DEC                           { $$ = "dec"; }
+       | DECIMAL                       { $$ = "decimal"; }
+       | FLOAT                         { $$ = "float"; }
+       | INTERVAL                      { $$ = "interval"; }
+       | NCHAR                         { $$ = "nchar"; }
+       | NONE                          { $$ = "none"; }
+       | NUMERIC                       { $$ = "numeric"; }
+       | SETOF                         { $$ = "setof"; }
+       | TIME                          { $$ = "time"; }
+       | TIMESTAMP                     { $$ = "timestamp"; }
+       | VARCHAR                       { $$ = "varchar"; }
+       ;
+
+/* Column label --- allowed labels in "AS" clauses.
+ *
+ * Keywords appear here if they could not be distinguished from variable,
+ * type, or function names in some contexts.
+ * When adding a ColLabel, consider whether it can be added to func_name.
  */
 ColLabel:  ColId                       { $$ = $1; }
-       | ABORT_TRANS                   { $$ = "abort"; }
        | ALL                           { $$ = "all"; }
        | ANALYSE                       { $$ = "analyse"; } /* British */
        | ANALYZE                       { $$ = "analyze"; }
@@ -5862,26 +5866,19 @@ ColLabel:  ColId                        { $$ = $1; }
        | ASC                           { $$ = "asc"; }
        | BETWEEN                       { $$ = "between"; }
        | BINARY                        { $$ = "binary"; }
-       | BIT                           { $$ = "bit"; }
        | BOTH                          { $$ = "both"; }
        | CASE                          { $$ = "case"; }
        | CAST                          { $$ = "cast"; }
-       | CHAR                          { $$ = "char"; }
-       | CHARACTER                     { $$ = "character"; }
        | CHECK                         { $$ = "check"; }
-       | CLUSTER                       { $$ = "cluster"; }
        | COALESCE                      { $$ = "coalesce"; }
        | COLLATE                       { $$ = "collate"; }
        | COLUMN                        { $$ = "column"; }
        | CONSTRAINT                    { $$ = "constraint"; }
-       | COPY                          { $$ = "copy"; }
        | CROSS                         { $$ = "cross"; }
        | CURRENT_DATE                  { $$ = "current_date"; }
        | CURRENT_TIME                  { $$ = "current_time"; }
        | CURRENT_TIMESTAMP             { $$ = "current_timestamp"; }
        | CURRENT_USER                  { $$ = "current_user"; }
-       | DEC                           { $$ = "dec"; }
-       | DECIMAL                       { $$ = "decimal"; }
        | DEFAULT                       { $$ = "default"; }
        | DEFERRABLE                    { $$ = "deferrable"; }
        | DESC                          { $$ = "desc"; }
@@ -5891,25 +5888,20 @@ ColLabel:  ColId                        { $$ = $1; }
        | END_TRANS                     { $$ = "end"; }
        | EXCEPT                        { $$ = "except"; }
        | EXISTS                        { $$ = "exists"; }
-       | EXPLAIN                       { $$ = "explain"; }
        | EXTRACT                       { $$ = "extract"; }
        | FALSE_P                       { $$ = "false"; }
-       | FLOAT                         { $$ = "float"; }
        | FOR                           { $$ = "for"; }
        | FOREIGN                       { $$ = "foreign"; }
        | FREEZE                        { $$ = "freeze"; }
        | FROM                          { $$ = "from"; }
        | FULL                          { $$ = "full"; }
-       | GLOBAL                        { $$ = "global"; }
        | GROUP                         { $$ = "group"; }
        | HAVING                        { $$ = "having"; }
        | ILIKE                         { $$ = "ilike"; }
        | IN                            { $$ = "in"; }
        | INITIALLY                     { $$ = "initially"; }
        | INNER_P                       { $$ = "inner"; }
-       | INOUT                         { $$ = "inout"; }
        | INTERSECT                     { $$ = "intersect"; }
-       | INTERVAL                      { $$ = "interval"; }
        | INTO                          { $$ = "into"; }
        | IS                            { $$ = "is"; }
        | ISNULL                        { $$ = "isnull"; }
@@ -5918,19 +5910,12 @@ ColLabel:  ColId                        { $$ = $1; }
        | LEFT                          { $$ = "left"; }
        | LIKE                          { $$ = "like"; }
        | LIMIT                         { $$ = "limit"; }
-       | LISTEN                        { $$ = "listen"; }
-       | LOAD                          { $$ = "load"; }
-       | LOCAL                         { $$ = "local"; }
-       | LOCK_P                        { $$ = "lock"; }
-       | MOVE                          { $$ = "move"; }
        | NATURAL                       { $$ = "natural"; }
-       | NCHAR                         { $$ = "nchar"; }
        | NEW                           { $$ = "new"; }
        | NOT                           { $$ = "not"; }
        | NOTNULL                       { $$ = "notnull"; }
        | NULLIF                        { $$ = "nullif"; }
        | NULL_P                        { $$ = "null"; }
-       | NUMERIC                       { $$ = "numeric"; }
        | OFF                           { $$ = "off"; }
        | OFFSET                        { $$ = "offset"; }
        | OLD                           { $$ = "old"; }
@@ -5938,43 +5923,66 @@ ColLabel:  ColId                        { $$ = $1; }
        | ONLY                          { $$ = "only"; }
        | OR                            { $$ = "or"; }
        | ORDER                         { $$ = "order"; }
-       | OUT                           { $$ = "out"; }
        | OUTER_P                       { $$ = "outer"; }
        | OVERLAPS                      { $$ = "overlaps"; }
        | POSITION                      { $$ = "position"; }
-       | PRECISION                     { $$ = "precision"; }
        | PRIMARY                       { $$ = "primary"; }
        | PUBLIC                        { $$ = "public"; }
        | REFERENCES                    { $$ = "references"; }
-       | RESET                         { $$ = "reset"; }
        | RIGHT                         { $$ = "right"; }
        | SELECT                        { $$ = "select"; }
        | SESSION_USER                  { $$ = "session_user"; }
-       | SETOF                         { $$ = "setof"; }
-       | SHOW                          { $$ = "show"; }
        | SOME                          { $$ = "some"; }
        | SUBSTRING                     { $$ = "substring"; }
        | TABLE                         { $$ = "table"; }
        | THEN                          { $$ = "then"; }
-       | TIME                          { $$ = "time"; }
-       | TIMESTAMP                     { $$ = "timestamp"; }
        | TO                            { $$ = "to"; }
        | TRAILING                      { $$ = "trailing"; }
-       | TRANSACTION                   { $$ = "transaction"; }
        | TRIM                          { $$ = "trim"; }
        | TRUE_P                        { $$ = "true"; }
        | UNION                         { $$ = "union"; }
        | UNIQUE                        { $$ = "unique"; }
-       | UNKNOWN                       { $$ = "unknown"; }
        | USER                          { $$ = "user"; }
        | USING                         { $$ = "using"; }
-       | VACUUM                        { $$ = "vacuum"; }
-       | VARCHAR                       { $$ = "varchar"; }
        | VERBOSE                       { $$ = "verbose"; }
        | WHEN                          { $$ = "when"; }
        | WHERE                         { $$ = "where"; }
        ;
 
+/* Function identifier --- names that can be function names.
+ *
+ * This contains the TypeFuncId list plus some ColLabel keywords
+ * that are used as operators in expressions; in general such keywords
+ * can't be ColId because they would be ambiguous with variable names,
+ * but they are unambiguous as function identifiers.
+ *
+ * Do not include POSITION, SUBSTRING, etc here since they have explicit
+ * productions in a_expr to support the goofy SQL9x argument syntax.
+ *  - thomas 2000-11-28
+ */
+func_name:  TypeFuncId                 { $$ = xlateSqlFunc($1); }
+       | BETWEEN                       { $$ = xlateSqlFunc("between"); }
+       | BINARY                        { $$ = xlateSqlFunc("binary"); }
+       | CROSS                         { $$ = xlateSqlFunc("cross"); }
+       | FREEZE                        { $$ = xlateSqlFunc("freeze"); }
+       | FULL                          { $$ = xlateSqlFunc("full"); }
+       | ILIKE                         { $$ = xlateSqlFunc("ilike"); }
+       | IN                            { $$ = xlateSqlFunc("in"); }
+       | INNER_P                       { $$ = xlateSqlFunc("inner"); }
+       | IS                            { $$ = xlateSqlFunc("is"); }
+       | ISNULL                        { $$ = xlateSqlFunc("isnull"); }
+       | JOIN                          { $$ = xlateSqlFunc("join"); }
+       | LEFT                          { $$ = xlateSqlFunc("left"); }
+       | LIKE                          { $$ = xlateSqlFunc("like"); }
+       | NATURAL                       { $$ = xlateSqlFunc("natural"); }
+       | NOTNULL                       { $$ = xlateSqlFunc("notnull"); }
+       | OUTER_P                       { $$ = xlateSqlFunc("outer"); }
+       | OVERLAPS                      { $$ = xlateSqlFunc("overlaps"); }
+       | PUBLIC                        { $$ = xlateSqlFunc("public"); }
+       | RIGHT                         { $$ = xlateSqlFunc("right"); }
+       | VERBOSE                       { $$ = xlateSqlFunc("verbose"); }
+       ;
+
 SpecialRuleRelation:  OLD
                {
                    if (QueryIsRule)
index dfa16e119a1614a98dd0100e29fcc61b7f16c5e1..04296d42aab8d865301b1a455321b4401032540a 100644 (file)
@@ -88,7 +88,7 @@ cat_str(int count, ...)
 char *
 make_str(const char *str)
 {
-        char * res_str = (char *)mm_alloc(strlen(str) + 1);
+   char * res_str = (char *)mm_alloc(strlen(str) + 1);
 
    strcpy(res_str, str);
    return res_str;
@@ -279,7 +279,7 @@ make_name(void)
 %type  <str>    key_match ColLabel SpecialRuleRelation ColId columnDef
 %type  <str>    ColConstraint ColConstraintElem drop_type Bitconst
 %type  <str>    OptTableElementList OptTableElement TableConstraint
-%type  <str>    ConstraintElem key_actions ColQualList TokenId DropSchemaStmt
+%type  <str>    ConstraintElem key_actions ColQualList TypeFuncId DropSchemaStmt
 %type  <str>    target_list target_el update_target_list alias_clause
 %type  <str>    update_target_el opt_id relation_name database_name
 %type  <str>    access_method attr_name class index_name name func_name
@@ -288,9 +288,9 @@ make_name(void)
 %type  <str>   opt_indirection expr_list extract_list extract_arg
 %type  <str>   position_list substr_list substr_from alter_column_default
 %type  <str>   trim_list in_expr substr_for attr attrs drop_behavior
-%type  <str>   Typename SimpleTypename Generic Numeric generic opt_float opt_numeric
+%type  <str>   Typename SimpleTypename Generic Numeric opt_float opt_numeric
 %type  <str>   opt_decimal Character character opt_varying opt_charset
-%type  <str>   opt_collate datetime opt_timezone opt_interval table_ref
+%type  <str>   opt_collate opt_timezone opt_interval table_ref
 %type  <str>   row_expr row_descriptor row_list ConstDatetime opt_chain
 %type  <str>   SelectStmt into_clause OptTemp ConstraintAttributeSpec
 %type  <str>   opt_table opt_all sort_clause sortby_list ConstraintAttr 
@@ -324,7 +324,7 @@ make_name(void)
 %type  <str>    TriggerActionTime CreateTrigStmt DropPLangStmt 
 %type  <str>    CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select
 %type  <str>    ViewStmt LoadStmt CreatedbStmt createdb_opt_item
-%type  <str>   createdb_opt_list opt_encoding OptInherit Geometric
+%type  <str>   createdb_opt_list opt_encoding OptInherit
 %type  <str>    DropdbStmt ClusterStmt grantee RevokeStmt Bit bit
 %type  <str>   GrantStmt privileges operation_commalist operation PosAllConst
 %type  <str>   opt_with_grant opt_cursor ConstraintsSetStmt AllConst
@@ -357,12 +357,12 @@ make_name(void)
 %type  <str>    struct_type s_struct declaration declarations variable_declarations
 %type  <str>    s_union union_type ECPGSetAutocommit on_off
 %type  <str>   ECPGAllocateDescr ECPGDeallocateDescr symbol opt_symbol
-%type  <str>   ECPGGetDescriptorHeader ECPGColLabel ECPGTypeName
-%type  <str>   ECPGLabelTypeName ECPGColId variablelist cvariable
+%type  <str>   ECPGGetDescriptorHeader ECPGTypeFuncId ECPGColId ECPGColLabel
+%type  <str>   ECPGTypeName variablelist cvariable
 
 %type  <descriptor> ECPGGetDescriptor
 
-%type  <type_enum> simple_type signed_type unsigned_type varchar_type
+%type  <type_enum> simple_type signed_type unsigned_type
 
 %type  <dtype_enum> descriptor_item desc_header_item
 
@@ -913,11 +913,11 @@ constraints_set_list:  ALL
                ;
 
 
-constraints_set_namelist:      IDENT
+constraints_set_namelist:      ColId
                                {
                                        $$ = $1;
                                }
-               | constraints_set_namelist ',' IDENT
+               | constraints_set_namelist ',' ColId
                                {
                                        $$ = cat_str(3, $1, make_str(","), $3);
                                }
@@ -1529,8 +1529,8 @@ def_elem:  ColLabel '=' def_arg   {
                }
        ;
 
+/* Note: any simple identifier will be returned as a type name! */
 def_arg:  func_return      {  $$ = $1; }
-       | TokenId   {  $$ = $1; }
        | all_Op    {  $$ = $1; }
        | AllConst  {  $$ = $1; }
        ;
@@ -1964,7 +1964,7 @@ func_type:    Typename
                {
                    $$ = $1;
                }
-       | IDENT '.' ColId '%' TYPE_P   
+       | TypeFuncId '.' ColId '%' TYPE_P   
                {
                    $$ = cat_str(4, $1, make_str("."), $3, make_str("% type"));
                }
@@ -2974,20 +2974,11 @@ SimpleTypename:  ConstTypename                  { $$ = $1; }
 ConstTypename:  Generic    { $$ = $1; }
        | ConstDatetime { $$ = $1; }
        | Numeric   { $$ = $1; }
-       | Geometric { $$ = $1; }
        | Bit       { $$ = $1; }
        | Character { $$ = $1; }
        ;
 
-Generic:  generic
-               {
-                   $$ = $1;
-               }
-       ;
-
-generic:  ident                    { $$ = $1; }
-       | TYPE_P            { $$ = make_str("type"); }
-       | ECPGKeywords          { $$ = $1; }
+Generic:  TypeFuncId           { $$ = $1; }
        | ECPGTypeName          { $$ = $1; }
        ;
 
@@ -3018,8 +3009,6 @@ Numeric:  FLOAT opt_float
                }
        ;
 
-Geometric:  PATH_P     { $$ = make_str("path"); };
-
 opt_float:  '(' PosIntConst ')'
                {
                    $$ = cat_str(3, make_str("("), $2, make_str(")"));
@@ -3115,11 +3104,7 @@ opt_collate:  COLLATE ColId      { $$ = cat2_str(make_str("collate"), $2); }
        | /*EMPTY*/                 { $$ = EMPTY; }
        ;
 
-ConstDatetime:  datetime
-               {
-                   $$ = $1;
-               }
-       | TIMESTAMP '(' PosIntConst ')' opt_timezone
+ConstDatetime:  TIMESTAMP '(' PosIntConst ')' opt_timezone
                {
                    $$ = cat_str(4, make_str("timestamp("), $3, make_str(")"), $5);
                }
@@ -3143,14 +3128,6 @@ ConstInterval:   INTERVAL
                }
        ;
 
-datetime:  YEAR_P                              { $$ = make_str("year"); }
-       | MONTH_P                               { $$ = make_str("month"); }
-       | DAY_P                                 { $$ = make_str("day"); }
-       | HOUR_P                                { $$ = make_str("hour"); }
-       | MINUTE_P                              { $$ = make_str("minute"); }
-       | SECOND_P                              { $$ = make_str("second"); }
-       ;
-
 opt_timezone:  WITH TIME ZONE              { $$ = make_str("with time zone"); }
        | WITHOUT TIME ZONE             { $$ = make_str("without time zone"); }
        | /*EMPTY*/                 { $$ = EMPTY; }
@@ -3544,9 +3521,14 @@ extract_list:  extract_arg FROM a_expr
  * - thomas 2001-04-12
  */
 
-extract_arg:  datetime     { $$ = $1; }
-   | StringConst               { $$ = $1; }
-   | IDENT                 { $$ = $1; }
+extract_arg:  IDENT                        { $$ = $1; }
+       | YEAR_P                        { $$ = make_str("year"); }
+       | MONTH_P                       { $$ = make_str("month"); }
+       | DAY_P                         { $$ = make_str("day"); }
+       | HOUR_P                        { $$ = make_str("hour"); }
+       | MINUTE_P                      { $$ = make_str("minute"); }
+       | SECOND_P                      { $$ = make_str("second"); }
+       | StringConst                   { $$ = $1; }
        ;
 
 /* position_list uses b_expr not a_expr to avoid conflict with general IN */
@@ -3750,22 +3732,6 @@ attr_name:               ColId           { $$ = $1; };
 class:                 ColId           { $$ = $1; };
 index_name:                ColId           { $$ = $1; };
 
-/* Functions
- * Include date/time keywords as SQL92 extension.
- * Include TYPE as a SQL92 unreserved keyword. - thomas 1997-10-05
- */
-func_name: ColId           { $$ = $1; };
-       | BETWEEN       { $$ = make_str("between");}
-       | ILIKE         { $$ = make_str("ilike");}
-       | IN            { $$ = make_str("in");}
-       | IS            { $$ = make_str("is");}
-       | ISNULL        { $$ = make_str("isnull");}
-       | LIKE          { $$ = make_str("like");}
-       | NOTNULL       { $$ = make_str("notnull");}
-       | OVERLAPS      { $$ = make_str("overlaps");}
-       ;
-
-
 file_name:             StringConst         { $$ = $1; };
 
 /* Constants
@@ -3859,26 +3825,6 @@ PosAllConst: Sconst      { $$ = $1; }
 
 UserId:  ColId                                  { $$ = $1;};
 
-/* Column identifier
- */
-ColId: ECPGColId           { $$ = $1; }
-/* | ECPGTypeName                  { $$ = $1; }*/
-   ;
-
-/* Column label
- * Allowed labels in "AS" clauses.
- * Include TRUE/FALSE SQL3 reserved words for Postgres backward
- *  compatibility. Cannot allow this for column names since the
- *  syntax would not distinguish between the constant value and
- *  a column name. - thomas 1997-10-24
- * Add other keywords to this list. Note that they appear here
- *  rather than in ColId if there was a shift/reduce conflict
- *  when used as a full identifier. - thomas 1997-11-06
- */
-ColLabel:  ECPGLabelTypeName           { $$ = $1; }
-   | ECPGColLabel                  { $$ = $1; }
-   ;
-
 SpecialRuleRelation:  OLD
                {
                    if (!QueryIsRule)
@@ -4220,13 +4166,6 @@ type: simple_type
            $$.type_dimension = -1;
            $$.type_index = -1;
        }
-   | varchar_type
-       {
-           $$.type_enum = ECPGt_varchar;
-           $$.type_str = make_str("varchar");;
-           $$.type_dimension = -1;
-           $$.type_index = -1;
-       }
    | struct_type
        {
            $$.type_enum = ECPGt_struct;
@@ -4250,14 +4189,42 @@ type: simple_type
        }
    | ECPGColLabel
        {
-           /* this is for typedef'ed types */
-           struct typedefs *this = get_typedef($1);
-
-           $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
-                        $$.type_enum = this->type->type_enum;
-           $$.type_dimension = this->type->type_dimension;
-           $$.type_index = this->type->type_index;
-           struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+           /*
+            * Check for type names that the SQL grammar treats as
+            * unreserved keywords
+            */
+           if (strcmp($1, "varchar") == 0)
+           {
+               $$.type_enum = ECPGt_varchar;
+               $$.type_str = make_str("varchar");
+               $$.type_dimension = -1;
+               $$.type_index = -1;
+           }
+           else if (strcmp($1, "float") == 0)
+           {
+               $$.type_enum = ECPGt_float;
+               $$.type_str = make_str("float");
+               $$.type_dimension = -1;
+               $$.type_index = -1;
+           }
+           else if (strcmp($1, "double") == 0)
+           {
+               $$.type_enum = ECPGt_double;
+               $$.type_str = make_str("double");
+               $$.type_dimension = -1;
+               $$.type_index = -1;
+           }
+           else
+           {
+               /* this is for typedef'ed types */
+               struct typedefs *this = get_typedef($1);
+
+               $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
+               $$.type_enum = this->type->type_enum;
+               $$.type_dimension = this->type->type_dimension;
+               $$.type_index = this->type->type_index;
+               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+           }
        }
    ;
 
@@ -4359,9 +4326,7 @@ signed_type: SQL_SHORT            { $$ = ECPGt_short; }
                                  $$ = ECPGt_long;
 #endif
                                }
-           | SQL_BOOL          { $$ = ECPGt_bool; };
-           | FLOAT                 { $$ = ECPGt_float; }
-           | DOUBLE                { $$ = ECPGt_double; }
+           | SQL_BOOL          { $$ = ECPGt_bool; }
            | CHAR                  { $$ = ECPGt_char; }
       ;
 
@@ -4369,8 +4334,6 @@ opt_signed:   SQL_SIGNED
    |   /* EMPTY */
    ;
 
-varchar_type:  VARCHAR     { $$ = ECPGt_varchar; };
-
 variable_list: variable 
    {
        $$ = $1;
@@ -4686,7 +4649,7 @@ ECPGSetConnection:  SET SQL_CONNECTION to_equal connection_object
 /*
  * define a new type for embedded SQL
  */
-ECPGTypedef: TYPE_P ECPGColLabel IS type opt_type_array_bounds opt_reference
+ECPGTypedef: TYPE_P ColLabel IS type opt_type_array_bounds opt_reference
    {
        /* add entry to list */
        struct typedefs *ptr, *this;
@@ -4779,7 +4742,7 @@ opt_reference: SQL_REFERENCE { $$ = make_str("reference"); }
 /*
  * define the type of one variable for embedded SQL
  */
-ECPGVar: SQL_VAR ECPGColLabel IS type opt_type_array_bounds opt_reference
+ECPGVar: SQL_VAR ColLabel IS type opt_type_array_bounds opt_reference
    {
        struct variable *p = find_variable($2);
        int dimension = $5.index1;
@@ -4956,16 +4919,6 @@ ECPGTypeName:      SQL_BOOL      { $$ = make_str("bool"); }
        | SQL_STRUCT        { $$ = make_str("struct"); }
        | SQL_SIGNED        { $$ = make_str("signed"); }
        | SQL_UNSIGNED      { $$ = make_str("unsigned"); }
-       | DOUBLE        { $$ = make_str("double"); }
-       ;
-
-/* not needed at the moment
- *             | UNION     { $$ = make_str("union"); }
- */
-ECPGLabelTypeName:   CHAR          { $$ = make_str("char"); }
-           | FLOAT     { $$ = make_str("float"); }
-           | VARCHAR   { $$ = make_str("varchar"); }
-/*         | ECPGTypeName  { $$ = $1; }*/
        ;
 
 opt_symbol:    symbol      { $$ = $1; }
@@ -4974,258 +4927,352 @@ opt_symbol:   symbol      { $$ = $1; }
 
 symbol:        ColLabel    { $$ = $1; };
 
-/* Parser tokens to be used as identifiers.
- * Tokens involving data types should appear in ColId only,
- * since they will conflict with real TypeName productions.
+/*
+ * Keyword classification lists.  Generally, every keyword present in
+ * the Postgres grammar should be in one of these lists.  (Presently,
+ * "AS" is the sole exception: it is our only completely-reserved word.)
+ *
+ * Put a new keyword into the earliest list (of TypeFuncId, ColId, ColLabel)
+ * that it can go into without creating shift or reduce conflicts.  The
+ * earlier lists define "less reserved" categories of keywords.  Notice that
+ * each list includes by reference the ones before it.
  */
-TokenId:  ABSOLUTE         { $$ = make_str("absolute"); }
-   | ACCESS            { $$ = make_str("access"); }
-   | ACTION            { $$ = make_str("action"); }
-   | ADD               { $$ = make_str("add"); }
-   | AFTER             { $$ = make_str("after"); }
-   | AGGREGATE         { $$ = make_str("aggregate"); }
-   | ALTER             { $$ = make_str("alter"); }
-   | AT                { $$ = make_str("at"); }
-   | AUTHORIZATION         { $$ = make_str("authorization"); }
-   | BACKWARD          { $$ = make_str("backward"); }
-   | BEFORE            { $$ = make_str("before"); }
-   | BEGIN_TRANS           { $$ = make_str("begin"); }
-   | CACHE             { $$ = make_str("cache"); }
-   | CASCADE           { $$ = make_str("cascade"); }
-   | CHAIN             { $$ = make_str("chain"); }
-   | CHARACTERISTICS       { $$ = make_str("characteristics"); }
-   | CHECKPOINT            { $$ = make_str("checkpoint"); }
-   | CLOSE             { $$ = make_str("close"); }
-   | COMMENT           { $$ = make_str("comment"); } 
-   | COMMIT            { $$ = make_str("commit"); }
-   | COMMITTED         { $$ = make_str("committed"); }
-   | CONSTRAINTS           { $$ = make_str("constraints"); }
-   | CREATEDB          { $$ = make_str("createdb"); }
-   | CREATEUSER            { $$ = make_str("createuser"); }
-   | CYCLE             { $$ = make_str("cycle"); }
-   | DATABASE          { $$ = make_str("database"); }
-   | DECLARE           { $$ = make_str("declare"); }
-   | DEFERRED          { $$ = make_str("deferred"); }  
-   | DELETE            { $$ = make_str("delete"); }
-   | DELIMITERS            { $$ = make_str("delimiters"); }
-   | DROP              { $$ = make_str("drop"); }
-   | EACH              { $$ = make_str("each"); }
-   | ENCODING          { $$ = make_str("encoding"); }
-   | ENCRYPTED         { $$ = make_str("encrypted"); }
-   | ESCAPE            { $$ = make_str("escape"); }
-   | EXCLUSIVE         { $$ = make_str("exclusive"); }
-   | EXECUTE           { $$ = make_str("execute"); }
-   | FETCH             { $$ = make_str("fetch"); }
-   | FORCE             { $$ = make_str("force"); }
-   | FORWARD           { $$ = make_str("forward"); }
-   | FUNCTION          { $$ = make_str("function"); }
-   | GRANT             { $$ = make_str("grant"); }
-   | HANDLER           { $$ = make_str("handler"); }
-   | IMMEDIATE         { $$ = make_str("immediate"); } 
-   | INCREMENT         { $$ = make_str("increment"); }
-   | INDEX             { $$ = make_str("index"); }
-   | INHERITS          { $$ = make_str("inherits"); }
-   | INSENSITIVE           { $$ = make_str("insensitive"); }
-   | INSERT            { $$ = make_str("insert"); }
-   | INSTEAD           { $$ = make_str("instead"); }
-   | ISOLATION         { $$ = make_str("isolation"); }
-   | KEY               { $$ = make_str("key"); }
-   | LANGUAGE          { $$ = make_str("language"); }
-   | LANCOMPILER           { $$ = make_str("lancompiler"); }
-   | LEVEL             { $$ = make_str("level"); }
-   | LOCATION          { $$ = make_str("location"); }
-   | MATCH             { $$ = make_str("match"); }
-   | MAXVALUE          { $$ = make_str("maxvalue"); }
-   | MINVALUE          { $$ = make_str("minvalue"); }
-   | MODE              { $$ = make_str("mode"); }
-   | NAMES             { $$ = make_str("names"); }
-   | NEXT              { $$ = make_str("next"); }
-   | NO                { $$ = make_str("no"); }
-   | NOCREATEDB            { $$ = make_str("nocreatedb"); }
-   | NOCREATEUSER          { $$ = make_str("nocreateuser"); }
-   | NOTHING           { $$ = make_str("nothing"); }
-   | NOTIFY            { $$ = make_str("notify"); }
-   | OF                { $$ = make_str("of"); }
-   | OIDS              { $$ = make_str("oids"); }
-   | OPERATOR          { $$ = make_str("operator"); }
-   | OPTION            { $$ = make_str("option"); }
-   | OWNER             { $$ = make_str("owner"); }
-   | PARTIAL           { $$ = make_str("partial"); }
-   | PASSWORD          { $$ = make_str("password"); }
-   | PENDANT           { $$ = make_str("pendant"); }
-   | PRIOR             { $$ = make_str("prior"); }
-   | PRIVILEGES            { $$ = make_str("privileges"); }
-   | PROCEDURAL            { $$ = make_str("procedural"); }
-   | PROCEDURE         { $$ = make_str("procedure"); }
-   | READ              { $$ = make_str("read"); }
-   | REINDEX           { $$ = make_str("reindex"); }
-   | RELATIVE          { $$ = make_str("relative"); }
-   | RENAME            { $$ = make_str("rename"); }
-   | REPLACE           { $$ = make_str("replace"); }
-   | RESTRICT          { $$ = make_str("restrict"); }
-   | RETURNS           { $$ = make_str("returns"); }
-   | REVOKE            { $$ = make_str("revoke"); }
-   | ROLLBACK          { $$ = make_str("rollback"); }
-   | ROW               { $$ = make_str("row"); }
-   | RULE              { $$ = make_str("rule"); }
-   | SCHEMA            { $$ = make_str("schema"); }
-   | SCROLL            { $$ = make_str("scroll"); }
-   | SESSION           { $$ = make_str("session"); }
-   | SEQUENCE                      { $$ = make_str("sequence"); }
-   | SERIALIZABLE          { $$ = make_str("serializable"); }
-   | SET               { $$ = make_str("set"); }
-   | SHARE             { $$ = make_str("share"); }
-   | START             { $$ = make_str("start"); }
-   | STATEMENT         { $$ = make_str("statement"); }
-   | STATISTICS            { $$ = make_str("statistics"); }
-   | STDIN                         { $$ = make_str("stdin"); }
-   | STDOUT                        { $$ = make_str("stdout"); }
-   | SYSID                         { $$ = make_str("sysid"); }
-   | TEMP              { $$ = make_str("temp"); }
-   | TEMPLATE          { $$ = make_str("template"); }
-   | TEMPORARY         { $$ = make_str("temporary"); }
-        | TOAST                        { $$ = make_str("toast"); }
-   | TRIGGER           { $$ = make_str("trigger"); }
-   | TRUNCATE          { $$ = make_str("truncate"); }
-   | TRUSTED           { $$ = make_str("trusted"); }
-   | UNENCRYPTED           { $$ = make_str("unencrypted"); }
-   | UNLISTEN          { $$ = make_str("unlisten"); }
-   | UNTIL             { $$ = make_str("until"); }
-   | UPDATE            { $$ = make_str("update"); }
-   | VALID             { $$ = make_str("valid"); }
-   | VALUES            { $$ = make_str("values"); }
-   | VARYING           { $$ = make_str("varying"); }
-   | VERSION           { $$ = make_str("version"); }
-   | VIEW              { $$ = make_str("view"); }
-   | WITH              { $$ = make_str("with"); }
-   | WITHOUT           { $$ = make_str("without"); }
-   | WORK              { $$ = make_str("work"); }
-   | ZONE              { $$ = make_str("zone"); }
-   ;
 
-ECPGColId: ident           { $$ = $1; }
-   | TYPE_P            { $$ = make_str("type"); }
-   | datetime          { $$ = $1; }
-   | TokenId           { $$ = $1; }
-   | NATIONAL          { $$ = make_str("national"); }
-   | NONE              { $$ = make_str("none"); }
-   | PATH_P            { $$ = make_str("path_p"); }
-   | ECPGKeywords                  { $$ = $1; }
-   ;
+/* Type/func identifier --- names that can be type and function names
+ * (as well as ColIds --- ie, these are completely unreserved keywords).
+ */
+TypeFuncId:  ECPGTypeFuncId                { $$ = $1; }
+       | ECPGKeywords                  { $$ = $1; }
+       ;
+
+ECPGTypeFuncId:  ident                 { $$ = $1; }
+       | ABORT_TRANS                   { $$ = make_str("abort"); }
+       | ABSOLUTE                      { $$ = make_str("absolute"); }
+       | ACCESS                        { $$ = make_str("access"); }
+       | ACTION                        { $$ = make_str("action"); }
+       | ADD                           { $$ = make_str("add"); }
+       | AFTER                         { $$ = make_str("after"); }
+       | AGGREGATE                     { $$ = make_str("aggregate"); }
+       | ALTER                         { $$ = make_str("alter"); }
+       | AT                            { $$ = make_str("at"); }
+       | AUTHORIZATION                 { $$ = make_str("authorization"); }
+       | BACKWARD                      { $$ = make_str("backward"); }
+       | BEFORE                        { $$ = make_str("before"); }
+       | BEGIN_TRANS                   { $$ = make_str("begin"); }
+       | BY                            { $$ = make_str("by"); }
+       | CACHE                         { $$ = make_str("cache"); }
+       | CASCADE                       { $$ = make_str("cascade"); }
+       | CHAIN                         { $$ = make_str("chain"); }
+       | CHARACTERISTICS               { $$ = make_str("characteristics"); }
+       | CHECKPOINT                    { $$ = make_str("checkpoint"); }
+       | CLOSE                         { $$ = make_str("close"); }
+       | CLUSTER                       { $$ = make_str("cluster"); }
+       | COMMENT                       { $$ = make_str("comment"); }
+       | COMMIT                        { $$ = make_str("commit"); }
+       | COMMITTED                     { $$ = make_str("committed"); }
+       | CONSTRAINTS                   { $$ = make_str("constraints"); }
+       | COPY                          { $$ = make_str("copy"); }
+       | CREATE                        { $$ = make_str("create"); }
+       | CREATEDB                      { $$ = make_str("createdb"); }
+       | CREATEUSER                    { $$ = make_str("createuser"); }
+       | CURSOR                        { $$ = make_str("cursor"); }
+       | CYCLE                         { $$ = make_str("cycle"); }
+       | DATABASE                      { $$ = make_str("database"); }
+       | DAY_P                         { $$ = make_str("day"); }
+       | DECLARE                       { $$ = make_str("declare"); }
+       | DEFERRED                      { $$ = make_str("deferred"); }
+       | DELETE                        { $$ = make_str("delete"); }
+       | DELIMITERS                    { $$ = make_str("delimiters"); }
+       | DOUBLE                        { $$ = make_str("double"); }
+       | DROP                          { $$ = make_str("drop"); }
+       | EACH                          { $$ = make_str("each"); }
+       | ENCODING                      { $$ = make_str("encoding"); }
+       | ENCRYPTED                     { $$ = make_str("encrypted"); }
+       | ESCAPE                        { $$ = make_str("escape"); }
+       | EXCLUSIVE                     { $$ = make_str("exclusive"); }
+       | EXECUTE                       { $$ = make_str("execute"); }
+       | EXPLAIN                       { $$ = make_str("explain"); }
+       | FETCH                         { $$ = make_str("fetch"); }
+       | FORCE                         { $$ = make_str("force"); }
+       | FORWARD                       { $$ = make_str("forward"); }
+       | FUNCTION                      { $$ = make_str("function"); }
+       | GLOBAL                        { $$ = make_str("global"); }
+       | GRANT                         { $$ = make_str("grant"); }
+       | HANDLER                       { $$ = make_str("handler"); }
+       | HOUR_P                        { $$ = make_str("hour"); }
+       | IMMEDIATE                     { $$ = make_str("immediate"); }
+       | INCREMENT                     { $$ = make_str("increment"); }
+       | INDEX                         { $$ = make_str("index"); }
+       | INHERITS                      { $$ = make_str("inherits"); }
+       | INOUT                         { $$ = make_str("inout"); }
+       | INSENSITIVE                   { $$ = make_str("insensitive"); }
+       | INSERT                        { $$ = make_str("insert"); }
+       | INSTEAD                       { $$ = make_str("instead"); }
+       | ISOLATION                     { $$ = make_str("isolation"); }
+       | KEY                           { $$ = make_str("key"); }
+       | LANGUAGE                      { $$ = make_str("language"); }
+       | LANCOMPILER                   { $$ = make_str("lancompiler"); }
+       | LEVEL                         { $$ = make_str("level"); }
+       | LISTEN                        { $$ = make_str("listen"); }
+       | LOAD                          { $$ = make_str("load"); }
+       | LOCAL                         { $$ = make_str("local"); }
+       | LOCATION                      { $$ = make_str("location"); }
+       | LOCK_P                        { $$ = make_str("lock"); }
+       | MATCH                         { $$ = make_str("match"); }
+       | MAXVALUE                      { $$ = make_str("maxvalue"); }
+       | MINUTE_P                      { $$ = make_str("minute"); }
+       | MINVALUE                      { $$ = make_str("minvalue"); }
+       | MODE                          { $$ = make_str("mode"); }
+       | MONTH_P                       { $$ = make_str("month"); }
+       | MOVE                          { $$ = make_str("move"); }
+       | NAMES                         { $$ = make_str("names"); }
+       | NATIONAL                      { $$ = make_str("national"); }
+       | NEXT                          { $$ = make_str("next"); }
+       | NO                            { $$ = make_str("no"); }
+       | NOCREATEDB                    { $$ = make_str("nocreatedb"); }
+       | NOCREATEUSER                  { $$ = make_str("nocreateuser"); }
+       | NOTHING                       { $$ = make_str("nothing"); }
+       | NOTIFY                        { $$ = make_str("notify"); }
+       | OF                            { $$ = make_str("of"); }
+       | OIDS                          { $$ = make_str("oids"); }
+       | OPERATOR                      { $$ = make_str("operator"); }
+       | OPTION                        { $$ = make_str("option"); }
+       | OUT                           { $$ = make_str("out"); }
+       | OWNER                         { $$ = make_str("owner"); }
+       | PARTIAL                       { $$ = make_str("partial"); }
+       | PASSWORD                      { $$ = make_str("password"); }
+       | PATH_P                        { $$ = make_str("path"); }
+       | PENDANT                       { $$ = make_str("pendant"); }
+       | PRECISION                     { $$ = make_str("precision"); }
+       | PRIOR                         { $$ = make_str("prior"); }
+       | PRIVILEGES                    { $$ = make_str("privileges"); }
+       | PROCEDURAL                    { $$ = make_str("procedural"); }
+       | PROCEDURE                     { $$ = make_str("procedure"); }
+       | READ                          { $$ = make_str("read"); }
+       | REINDEX                       { $$ = make_str("reindex"); }
+       | RELATIVE                      { $$ = make_str("relative"); }
+       | RENAME                        { $$ = make_str("rename"); }
+       | REPLACE                       { $$ = make_str("replace"); }
+       | RESET                         { $$ = make_str("reset"); }
+       | RESTRICT                      { $$ = make_str("restrict"); }
+       | RETURNS                       { $$ = make_str("returns"); }
+       | REVOKE                        { $$ = make_str("revoke"); }
+       | ROLLBACK                      { $$ = make_str("rollback"); }
+       | ROW                           { $$ = make_str("row"); }
+       | RULE                          { $$ = make_str("rule"); }
+       | SCHEMA                        { $$ = make_str("schema"); }
+       | SCROLL                        { $$ = make_str("scroll"); }
+       | SECOND_P                      { $$ = make_str("second"); }
+       | SESSION                       { $$ = make_str("session"); }
+       | SEQUENCE                      { $$ = make_str("sequence"); }
+       | SERIALIZABLE                  { $$ = make_str("serializable"); }
+       | SET                           { $$ = make_str("set"); }
+       | SHARE                         { $$ = make_str("share"); }
+       | SHOW                          { $$ = make_str("show"); }
+       | START                         { $$ = make_str("start"); }
+       | STATEMENT                     { $$ = make_str("statement"); }
+       | STATISTICS                    { $$ = make_str("statistics"); }
+       | STDIN                         { $$ = make_str("stdin"); }
+       | STDOUT                        { $$ = make_str("stdout"); }
+       | SYSID                         { $$ = make_str("sysid"); }
+       | TEMP                          { $$ = make_str("temp"); }
+       | TEMPLATE                      { $$ = make_str("template"); }
+       | TEMPORARY                     { $$ = make_str("temporary"); }
+       | TOAST                         { $$ = make_str("toast"); }
+       | TRANSACTION                   { $$ = make_str("transaction"); }
+       | TRIGGER                       { $$ = make_str("trigger"); }
+       | TRUNCATE                      { $$ = make_str("truncate"); }
+       | TRUSTED                       { $$ = make_str("trusted"); }
+       | TYPE_P                        { $$ = make_str("type"); }
+       | UNENCRYPTED                   { $$ = make_str("unencrypted"); }
+       | UNKNOWN                       { $$ = make_str("unknown"); }
+       | UNLISTEN                      { $$ = make_str("unlisten"); }
+       | UNTIL                         { $$ = make_str("until"); }
+       | UPDATE                        { $$ = make_str("update"); }
+       | VACUUM                        { $$ = make_str("vacuum"); }
+       | VALID                         { $$ = make_str("valid"); }
+       | VALUES                        { $$ = make_str("values"); }
+       | VARYING                       { $$ = make_str("varying"); }
+       | VERSION                       { $$ = make_str("version"); }
+       | VIEW                          { $$ = make_str("view"); }
+       | WITH                          { $$ = make_str("with"); }
+       | WITHOUT                       { $$ = make_str("without"); }
+       | WORK                          { $$ = make_str("work"); }
+       | YEAR_P                        { $$ = make_str("year"); }
+       | ZONE                          { $$ = make_str("zone"); }
+       ;
+
+/* Column identifier --- names that can be column, table, etc names.
+ *
+ * This contains the TypeFuncId list plus those keywords that conflict
+ * only with typename productions, not with other uses.  Note that
+ * most of these keywords will in fact be recognized as type names too;
+ * they just have to have special productions for the purpose.
+ *
+ * Most of these cannot be in TypeFuncId (ie, are not also usable as function
+ * names) because they can be followed by '(' in typename productions, which
+ * looks too much like a function call for a LALR(1) parser.
+ */
+ColId:  ECPGColId                      { $$ = $1; }
+       | CHAR                          { $$ = make_str("char"); }
+       ;
 
-ECPGColLabel:  ECPGColId   { $$ = $1; }
-       | ABORT_TRANS   { $$ = make_str("abort"); }
-       | ALL       { $$ = make_str("all"); }
-       | ANALYSE       { $$ = make_str("analyse"); }
-       | ANALYZE       { $$ = make_str("analyze"); }
-       | ANY       { $$ = make_str("any"); }
-       | ASC       { $$ = make_str("asc"); }
-           | BETWEEN       { $$ = make_str("between"); }
-       | BINARY        { $$ = make_str("binary"); }
-       | BIT           { $$ = make_str("bit"); }
-       | BOTH      { $$ = make_str("both"); }
-       | CASE          { $$ = make_str("case"); }
-       | CAST      { $$ = make_str("cast"); }
-       | CHARACTER     { $$ = make_str("character"); }
-       | CHECK     { $$ = make_str("check"); }
-       | CLUSTER   { $$ = make_str("cluster"); }
-       | COALESCE      { $$ = make_str("coalesce"); }
-       | COLLATE   { $$ = make_str("collate"); }
-       | COLUMN    { $$ = make_str("column"); }
-       | CONSTRAINT    { $$ = make_str("constraint"); }
-       | COPY      { $$ = make_str("copy"); }
-       | CROSS     { $$ = make_str("cross"); }
-       | CURRENT_DATE  { $$ = make_str("current_date"); }
-       | CURRENT_TIME  { $$ = make_str("current_time"); }
-       | CURRENT_TIMESTAMP { $$ = make_str("current_timestamp"); }
-       | CURRENT_USER      { $$ = make_str("current_user"); }
-       | DEC       { $$ = make_str("dec"); }
-       | DECIMAL   { $$ = make_str("decimal"); }
-       | DEFAULT   { $$ = make_str("default"); }
-       | DEFERRABLE    { $$ = make_str("deferrable"); }
-       | DESC      { $$ = make_str("desc"); }
-       | DISTINCT  { $$ = make_str("distinct"); }
-       | DO        { $$ = make_str("do"); }
-       | ELSE          { $$ = make_str("else"); }
-       | END_TRANS     { $$ = make_str("end"); }
-       | EXCEPT    { $$ = make_str("except"); }
-       | EXISTS    { $$ = make_str("exists"); }
-       | EXPLAIN   { $$ = make_str("explain"); }
-       | EXTRACT   { $$ = make_str("extract"); }
-       | FALSE_P   { $$ = make_str("false"); }
-       | FOR       { $$ = make_str("for"); }
-       | FOREIGN   { $$ = make_str("foreign"); }
-       | FREEZE    { $$ = make_str("freeze"); }
-       | FROM      { $$ = make_str("from"); }
-       | FULL      { $$ = make_str("full"); }
-       | GLOBAL    { $$ = make_str("global"); }
-       | GROUP     { $$ = make_str("group"); }
-       | HAVING    { $$ = make_str("having"); }
-       | ILIKE     { $$ = make_str("ilike"); }
-       | IN        { $$ = make_str("in"); }
-       | INITIALLY { $$ = make_str("initially"); }
-       | INNER_P   { $$ = make_str("inner"); }
-       | INOUT         { $$ = make_str("inout"); }
-       | INTERSECT { $$ = make_str("intersect"); }
-       | INTERVAL  { $$ = make_str("interval"); }
-       | INTO      { $$ = make_str("into"); }
-       | IS        { $$ = make_str("is"); }
-       | ISNULL    { $$ = make_str("isnull"); }
-       | JOIN      { $$ = make_str("join"); }
-       | LEADING   { $$ = make_str("leading"); }
-       | LEFT      { $$ = make_str("left"); }
-       | LIKE      { $$ = make_str("like"); }
-       | LIMIT     { $$ = make_str("limit"); }
-       | LISTEN    { $$ = make_str("listen"); }
-       | LOAD      { $$ = make_str("load"); }
-       | LOCK_P    { $$ = make_str("lock"); }
-       | MOVE      { $$ = make_str("move"); }
-       | NATURAL   { $$ = make_str("natural"); }
-       | NCHAR     { $$ = make_str("nchar"); }
-       | NEW       { $$ = make_str("new"); }
-       | NOT       { $$ = make_str("not"); }
-       | NOTNULL       { $$ = make_str("notnull"); }
-       | NULLIF    { $$ = make_str("nullif"); }
-       | NULL_P    { $$ = make_str("null"); }
-       | NUMERIC   { $$ = make_str("numeric"); }
-       | OFF       { $$ = make_str("off"); }
-       | OFFSET    { $$ = make_str("offset"); }
-       | OLD       { $$ = make_str("old"); }
-       | ON        { $$ = make_str("on"); }
-       | ONLY      { $$ = make_str("only"); }
-       | OR        { $$ = make_str("or"); }
-       | ORDER     { $$ = make_str("order"); }
-       | OUT       { $$ = make_str("out"); }
-       | OUTER_P   { $$ = make_str("outer"); }
-           | OVERLAPS      { $$ = make_str("overlaps"); }
-       | POSITION  { $$ = make_str("position"); }
-       | PRECISION { $$ = make_str("precision"); }
-       | PRIMARY   { $$ = make_str("primary"); }
-       | PUBLIC    { $$ = make_str("public"); }
-       | REFERENCES    { $$ = make_str("references"); }
-       | RESET     { $$ = make_str("reset"); }
-       | RIGHT     { $$ = make_str("right"); }
-       | SELECT    { $$ = make_str("select"); }
-       | SESSION_USER  { $$ = make_str("session_user"); }
-       | SETOF     { $$ = make_str("setof"); }
-       | SHOW      { $$ = make_str("show"); }
-       | SUBSTRING { $$ = make_str("substring"); }
-       | TABLE     { $$ = make_str("table"); }
-       | THEN          { $$ = make_str("then"); }
-       | TIME      { $$ = make_str("time"); }
-       | TIMESTAMP { $$ = make_str("timestamp"); }
-       | TO        { $$ = make_str("to"); }
-       | TRANSACTION   { $$ = make_str("transaction"); }
-       | TRIM      { $$ = make_str("trim"); }
-       | TRUE_P    { $$ = make_str("true"); }
-       | UNIQUE    { $$ = make_str("unique"); }
-       | UNKNOWN   { $$ = make_str("unknown"); }
-       | USER      { $$ = make_str("user"); }
-       | USING     { $$ = make_str("using"); }
-       | VACUUM    { $$ = make_str("vacuum"); }
-       | VERBOSE   { $$ = make_str("verbose"); }
-       | WHEN          { $$ = make_str("when"); }
-       | WHERE     { $$ = make_str("where"); }
+ECPGColId:  TypeFuncId                 { $$ = $1; }
+       | BIT                           { $$ = make_str("bit"); }
+/* CHAR must be excluded from ECPGColLabel because of conflict with UNSIGNED
+       | CHAR                          { $$ = make_str("char"); }
+ */
+       | CHARACTER                     { $$ = make_str("character"); }
+       | DEC                           { $$ = make_str("dec"); }
+       | DECIMAL                       { $$ = make_str("decimal"); }
+       | FLOAT                         { $$ = make_str("float"); }
+       | INTERVAL                      { $$ = make_str("interval"); }
+       | NCHAR                         { $$ = make_str("nchar"); }
+       | NONE                          { $$ = make_str("none"); }
+       | NUMERIC                       { $$ = make_str("numeric"); }
+       | SETOF                         { $$ = make_str("setof"); }
+       | TIME                          { $$ = make_str("time"); }
+       | TIMESTAMP                     { $$ = make_str("timestamp"); }
+       | VARCHAR                       { $$ = make_str("varchar"); }
+       ;
+
+/* Column label --- allowed labels in "AS" clauses.
+ *
+ * Keywords appear here if they could not be distinguished from variable,
+ * type, or function names in some contexts.
+ * When adding a ColLabel, consider whether it can be added to func_name.
+ */
+ColLabel:  ECPGColLabel                    { $$ = $1; }
+       | CHAR                          { $$ = make_str("char"); }
+       | UNION                         { $$ = make_str("union"); }
+       ;
+
+ECPGColLabel:  ECPGColId               { $$ = $1; }
+       | ALL                           { $$ = make_str("all"); }
+       | ANALYSE                       { $$ = make_str("analyse"); } /* British */
+       | ANALYZE                       { $$ = make_str("analyze"); }
+       | AND                           { $$ = make_str("and"); }
+       | ANY                           { $$ = make_str("any"); }
+       | ASC                           { $$ = make_str("asc"); }
+       | BETWEEN                       { $$ = make_str("between"); }
+       | BINARY                        { $$ = make_str("binary"); }
+       | BOTH                          { $$ = make_str("both"); }
+       | CASE                          { $$ = make_str("case"); }
+       | CAST                          { $$ = make_str("cast"); }
+       | CHECK                         { $$ = make_str("check"); }
+       | COALESCE                      { $$ = make_str("coalesce"); }
+       | COLLATE                       { $$ = make_str("collate"); }
+       | COLUMN                        { $$ = make_str("column"); }
+       | CONSTRAINT                    { $$ = make_str("constraint"); }
+       | CROSS                         { $$ = make_str("cross"); }
+       | CURRENT_DATE                  { $$ = make_str("current_date"); }
+       | CURRENT_TIME                  { $$ = make_str("current_time"); }
+       | CURRENT_TIMESTAMP             { $$ = make_str("current_timestamp"); }
+       | CURRENT_USER                  { $$ = make_str("current_user"); }
+       | DEFAULT                       { $$ = make_str("default"); }
+       | DEFERRABLE                    { $$ = make_str("deferrable"); }
+       | DESC                          { $$ = make_str("desc"); }
+       | DISTINCT                      { $$ = make_str("distinct"); }
+       | DO                            { $$ = make_str("do"); }
+       | ELSE                          { $$ = make_str("else"); }
+       | END_TRANS                     { $$ = make_str("end"); }
+       | EXCEPT                        { $$ = make_str("except"); }
+       | EXISTS                        { $$ = make_str("exists"); }
+       | EXTRACT                       { $$ = make_str("extract"); }
+       | FALSE_P                       { $$ = make_str("false"); }
+       | FOR                           { $$ = make_str("for"); }
+       | FOREIGN                       { $$ = make_str("foreign"); }
+       | FREEZE                        { $$ = make_str("freeze"); }
+       | FROM                          { $$ = make_str("from"); }
+       | FULL                          { $$ = make_str("full"); }
+       | GROUP                         { $$ = make_str("group"); }
+       | HAVING                        { $$ = make_str("having"); }
+       | ILIKE                         { $$ = make_str("ilike"); }
+       | IN                            { $$ = make_str("in"); }
+       | INITIALLY                     { $$ = make_str("initially"); }
+       | INNER_P                       { $$ = make_str("inner"); }
+       | INTERSECT                     { $$ = make_str("intersect"); }
+       | INTO                          { $$ = make_str("into"); }
+       | IS                            { $$ = make_str("is"); }
+       | ISNULL                        { $$ = make_str("isnull"); }
+       | JOIN                          { $$ = make_str("join"); }
+       | LEADING                       { $$ = make_str("leading"); }
+       | LEFT                          { $$ = make_str("left"); }
+       | LIKE                          { $$ = make_str("like"); }
+       | LIMIT                         { $$ = make_str("limit"); }
+       | NATURAL                       { $$ = make_str("natural"); }
+       | NEW                           { $$ = make_str("new"); }
+       | NOT                           { $$ = make_str("not"); }
+       | NOTNULL                       { $$ = make_str("notnull"); }
+       | NULLIF                        { $$ = make_str("nullif"); }
+       | NULL_P                        { $$ = make_str("null"); }
+       | OFF                           { $$ = make_str("off"); }
+       | OFFSET                        { $$ = make_str("offset"); }
+       | OLD                           { $$ = make_str("old"); }
+       | ON                            { $$ = make_str("on"); }
+       | ONLY                          { $$ = make_str("only"); }
+       | OR                            { $$ = make_str("or"); }
+       | ORDER                         { $$ = make_str("order"); }
+       | OUTER_P                       { $$ = make_str("outer"); }
+       | OVERLAPS                      { $$ = make_str("overlaps"); }
+       | POSITION                      { $$ = make_str("position"); }
+       | PRIMARY                       { $$ = make_str("primary"); }
+       | PUBLIC                        { $$ = make_str("public"); }
+       | REFERENCES                    { $$ = make_str("references"); }
+       | RIGHT                         { $$ = make_str("right"); }
+       | SELECT                        { $$ = make_str("select"); }
+       | SESSION_USER                  { $$ = make_str("session_user"); }
+       | SOME                          { $$ = make_str("some"); }
+       | SUBSTRING                     { $$ = make_str("substring"); }
+       | TABLE                         { $$ = make_str("table"); }
+       | THEN                          { $$ = make_str("then"); }
+       | TO                            { $$ = make_str("to"); }
+       | TRAILING                      { $$ = make_str("trailing"); }
+       | TRIM                          { $$ = make_str("trim"); }
+       | TRUE_P                        { $$ = make_str("true"); }
+/* UNION must be excluded from ECPGColLabel because of conflict with s_union
+       | UNION                         { $$ = make_str("union"); }
+ */
+       | UNIQUE                        { $$ = make_str("unique"); }
+       | USER                          { $$ = make_str("user"); }
+       | USING                         { $$ = make_str("using"); }
+       | VERBOSE                       { $$ = make_str("verbose"); }
+       | WHEN                          { $$ = make_str("when"); }
+       | WHERE                         { $$ = make_str("where"); }
+       ;
+
+/* Function identifier --- names that can be function names.
+ *
+ * This contains the TypeFuncId list plus some ColLabel keywords
+ * that are used as operators in expressions; in general such keywords
+ * can't be ColId because they would be ambiguous with variable names,
+ * but they are unambiguous as function identifiers.
+ *
+ * Do not include POSITION, SUBSTRING, etc here since they have explicit
+ * productions in a_expr to support the goofy SQL9x argument syntax.
+ *  - thomas 2000-11-28
+ */
+func_name:  TypeFuncId                 { $$ = $1; }
+       | BETWEEN                       { $$ = make_str("between"); }
+       | BINARY                        { $$ = make_str("binary"); }
+       | CROSS                         { $$ = make_str("cross"); }
+       | FREEZE                        { $$ = make_str("freeze"); }
+       | FULL                          { $$ = make_str("full"); }
+       | ILIKE                         { $$ = make_str("ilike"); }
+       | IN                            { $$ = make_str("in"); }
+       | INNER_P                       { $$ = make_str("inner"); }
+       | IS                            { $$ = make_str("is"); }
+       | ISNULL                        { $$ = make_str("isnull"); }
+       | JOIN                          { $$ = make_str("join"); }
+       | LEFT                          { $$ = make_str("left"); }
+       | LIKE                          { $$ = make_str("like"); }
+       | NATURAL                       { $$ = make_str("natural"); }
+       | NOTNULL                       { $$ = make_str("notnull"); }
+       | OUTER_P                       { $$ = make_str("outer"); }
+       | OVERLAPS                      { $$ = make_str("overlaps"); }
+       | PUBLIC                        { $$ = make_str("public"); }
+       | RIGHT                         { $$ = make_str("right"); }
+       | VERBOSE                       { $$ = make_str("verbose"); }
        ;
 
 into_list : coutputvariable | into_list ',' coutputvariable;