]> granicus.if.org Git - postgresql/blobdiff - src/interfaces/ecpg/preproc/preproc.y
Protect ADD and HEADER symbols from conflicting with MIPS includes.
[postgresql] / src / interfaces / ecpg / preproc / preproc.y
index 83015d04a59a4a7a56f683ce2d5773cdc57ff520..39699e8e77174a1bfbd8d4ffd7eeaff19219ba36 100644 (file)
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.230 2003/06/11 06:39:12 meskes Exp $ */
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.314 2005/12/27 04:00:08 momjian Exp $ */
 
 /* Copyright comment */
 %{
  */
 int struct_level = 0;
 int braces_open; /* brace level counter */
-char   errortext[128];
+int ecpg_informix_var = 0;
 char   *connection = NULL;
 char   *input_filename = NULL;
 
 static int     QueryIsRule = 0, FoundInto = 0;
 static int     initializer = 0;
 static struct this_type actual_type[STRUCT_DEPTH];
-static char *actual_storage[STRUCT_DEPTH];
 static char *actual_startline[STRUCT_DEPTH];
 
 /* temporarily store struct members while creating the data structure */
@@ -52,19 +51,37 @@ static struct inf_compat_val
  * Handle parsing errors and warnings
  */
 void
-mmerror(int error_code, enum errortype type, char * error)
+mmerror(int error_code, enum errortype type, char * error, ...)
 {
+       va_list ap;
+       
+       fprintf(stderr, "%s:%d: ", input_filename, yylineno);
+       
+       switch(type)
+       {
+               case ET_WARNING:
+                       fprintf(stderr, "WARNING: ");
+                       break;
+               case ET_ERROR:
+               case ET_FATAL:
+                       fprintf(stderr, "ERROR: ");
+                       break;
+       }
+
+       va_start(ap, error);
+       vfprintf(stderr, error, ap);
+       va_end(ap);
+       
+       fprintf(stderr, "\n");
+       
        switch(type)
        {
                case ET_WARNING:
-                       fprintf(stderr, "%s:%d: WARNING: %s\n", input_filename, yylineno, error);
                        break;
                case ET_ERROR:
-                       fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error);
                        ret_value = error_code;
                        break;
                case ET_FATAL:
-                       fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error);
                        exit(error_code);
        }
 }
@@ -141,6 +158,7 @@ make3_str(char *str1, char *str2, char *str3)
        return(res_str);
 }
 
+/* and the rest */
 static char *
 make_name(void)
 {
@@ -186,6 +204,108 @@ create_questionmarks(char *name, bool array)
        return(result);
 }
 
+static char *
+adjust_informix(struct arguments *list)
+{
+       /* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
+        * for instance you can declare variables in a function, and then subsequently use them
+        * { 
+        *      declare_vars();
+        *      exec sql ... which uses vars declared in the above function
+        *
+        * This breaks standard and leads to some very dangerous programming. 
+        * Since they do, we have to work around and accept their syntax as well.
+        * But we will do so ONLY in Informix mode.
+        * We have to change the variables to our own struct and just store the pointer instead of the variable 
+        */
+
+        struct arguments *ptr;
+        char *result = make_str("");
+
+        for (ptr = list; ptr != NULL; ptr = ptr->next)
+        {
+               char temp[20]; /* this should be sufficient unless you have 8 byte integers */
+               char *original_var;
+               
+               /* change variable name to "ECPG_informix_get_var(<counter>)" */
+               original_var = ptr->variable->name;
+               sprintf(temp, "%d))", ecpg_informix_var);
+               
+               if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
+               {
+                       ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1")), ptr->variable->type->size), 0);
+                       sprintf(temp, "%d, (", ecpg_informix_var++);
+               }
+               else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
+               {
+                       ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size), 0);
+                       sprintf(temp, "%d, (", ecpg_informix_var++);
+               }
+               else
+               {
+                       ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ECPGtype_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size), 0);
+                       sprintf(temp, "%d, &(", ecpg_informix_var++);
+               }
+               
+               /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
+               result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
+               
+               /* now the indicator if there is one */
+               if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
+               {
+                       /* change variable name to "ECPG_informix_get_var(<counter>)" */
+                       original_var = ptr->indicator->name;
+                       sprintf(temp, "%d))", ecpg_informix_var);
+                       
+                       /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
+                       if (atoi(ptr->indicator->type->size) > 1)
+                       {
+                               ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size), 0);
+                               sprintf(temp, "%d, (", ecpg_informix_var++);
+                       }
+                       else
+                       {
+                               ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ECPGtype_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size), 0);
+                               sprintf(temp, "%d, &(", ecpg_informix_var++);
+                       }
+                       result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
+               }
+        }
+
+        return result;
+}
+
+static struct cursor *
+add_additional_variables(char *name, bool insert)
+{
+       struct cursor *ptr;
+       struct arguments *p;
+
+       for (ptr = cur; ptr != NULL; ptr=ptr->next)
+       {
+               if (strcmp(ptr->name, name) == 0)
+                       break;
+       }
+
+       if (ptr == NULL)
+       {
+               mmerror(PARSE_ERROR, ET_ERROR, "trying to access an undeclared cursor %s\n", name);
+               return NULL;
+       }
+       if (insert)
+       {
+               /* add all those input variables that were given earlier 
+                * note that we have to append here but have to keep the existing order */
+               for (p = ptr->argsinsert; p; p = p->next)
+                       add_variable_to_tail(&argsinsert, p->variable, p->indicator);
+       }
+
+       /* add all those output variables that were given earlier */
+       for (p = ptr->argsresult; p; p = p->next)
+               add_variable_to_tail(&argsresult, p->variable, p->indicator);
+       
+       return ptr;
+}
 %}
 
 %union {
@@ -204,7 +324,7 @@ create_questionmarks(char *name, bool array)
 
 /* special embedded SQL token */
 %token SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
-               SQL_CALL SQL_CARDINALITY SQL_CONNECT SQL_CONNECTION
+               SQL_CALL SQL_CARDINALITY SQL_CONNECT 
                SQL_CONTINUE SQL_COUNT SQL_CURRENT SQL_DATA 
                SQL_DATETIME_INTERVAL_CODE
                SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE
@@ -212,7 +332,7 @@ create_questionmarks(char *name, bool array)
                SQL_FREE SQL_GO SQL_GOTO SQL_IDENTIFIED
                SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH
                SQL_LONG SQL_NAME SQL_NULLABLE SQL_OCTET_LENGTH
-               SQL_OPEN SQL_OUTPUT SQL_RELEASE SQL_REFERENCE
+               SQL_OPEN SQL_OUTPUT SQL_REFERENCE
                SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
                SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
                SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
@@ -229,9 +349,9 @@ create_questionmarks(char *name, bool array)
 %token TYPECAST
 
 /* ordinary key words in alphabetical order */
-%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD AFTER
-        AGGREGATE ALL ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
-       ASSERTION ASSIGNMENT AT AUTHORIZATION
+%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
+        AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
+       ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
 
         BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
         BOOLEAN_P BOTH BY
@@ -239,59 +359,69 @@ create_questionmarks(char *name, bool array)
         CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
        CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
        CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
-       COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY
-        CREATE CREATEDB CREATEUSER CROSS CURRENT_DATE CURRENT_TIME
+       COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB
+        CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME
         CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
 
-        DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT
+        DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
        DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS
-       DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP
-        EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUSIVE
+       DESC DISABLE_P DISTINCT DO DOMAIN_P DOUBLE_P DROP
+       
+        EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUSIVE EXCLUDING
         EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
 
         FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM
         FULL FUNCTION
 
-       GET GLOBAL GRANT GROUP_P
-        HANDLER HAVING HOLD HOUR_P
+       GET GLOBAL GRANT GRANTED GREATEST GROUP_P
+
+       HANDLER HAVING HEADER_P HOLD HOUR_P
 
-       ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCREMENT INDEX INHERITS
-        INITIALLY INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P
-        INTEGER INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
+       ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
+       INDEX INHERIT INHERITS INITIALLY INNER_P INOUT INPUT_P
+       INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
+       INTERVAL INTO INVOKER IS ISNULL ISOLATION
 
         JOIN
 
         KEY
 
-       LANCOMPILER LANGUAGE LAST_P LEADING LEFT LEVEL LIKE LIMIT LISTEN
-        LOAD LOCAL LOCATION LOCK_P
+       LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL
+       LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
+       LOCK_P LOGIN_P
 
        MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
 
        NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
-        NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P NULLIF
-        NUMERIC
+        NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
+       NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NUMERIC
 
-       OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR ORDER
+       OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR ORDER
         OUT_P OUTER_P OVERLAPS OVERLAY OWNER
 
-       PARTIAL PASSWORD PATH_P PENDANT PLACING POSITION
-       PRECISION PRESERVE PREPARE PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE
+       PARTIAL PASSWORD PLACING POSITION
+       PRECISION PRESERVE PREPARE PREPARED PRIMARY
+       PRIOR PRIVILEGES PROCEDURAL PROCEDURE
 
-       READ REAL RECHECK REFERENCES REINDEX RELATIVE_P RENAME REPLACE
-       RESET RESTART RESTRICT RETURNS REVOKE RIGHT ROLLBACK ROW ROWS RULE
+       QUOTE
 
-       SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE
-        SESSION SESSION_USER SET SETOF SHARE SHOW SIMILAR SIMPLE SMALLINT SOME
-        STABLE START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P
-        SUBSTRING SYSID
+       READ REAL RECHECK REFERENCES REINDEX RELATIVE_P RELEASE RENAME
+       REPEATABLE REPLACE RESET RESTART RESTRICT RETURNS REVOKE RIGHT
+       ROLE ROLLBACK ROW ROWS RULE
 
-        TABLE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TO TOAST
+       SAVEPOINT SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE
+       SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
+       SHOW SIMILAR SIMPLE SMALLINT SOME STABLE START STATEMENT
+       STATISTICS STDIN STDOUT STORAGE STRICT_P SUBSTRING SUPERUSER_P SYMMETRIC
+       SYSID SYSTEM_P
+
+        TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TO TOAST
         TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P
-        UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USAGE
-        USER USING
+       
+        UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
+       UPDATE USER USING
 
-        VACUUM VALID VALUES VARCHAR VARYING VERBOSE VERSION VIEW VOLATILE
+        VACUUM VALID VALIDATOR VALUES VARCHAR VARYING VERBOSE VIEW VOLATILE
        WHEN WHERE WITH WITHOUT WORK WRITE
         YEAR_P
         ZONE
@@ -302,7 +432,7 @@ create_questionmarks(char *name, bool array)
  */
 %token UNIONJOIN
 
-/* Special keywords, not in the query language - see the "lex" file */
+/* Special token types, not actually keywords - see the "lex" file */
 %token <str>   IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST XCONST
 %token <ival>  ICONST PARAM
 %token <dval>  FCONST
@@ -337,7 +467,7 @@ create_questionmarks(char *name, bool array)
 %left          '.'
 %left          JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
 
-%type  <str>   Iconst Fconst Sconst TransactionStmt CreateStmt UserId
+%type  <str>   Iconst Fconst Sconst TransactionStmt CreateStmt RoleId
 %type  <str>   CreateAsElement OptCreateAs CreateAsList CreateAsStmt
 %type  <str>   comment_text ConstraintDeferrabilitySpec TableElementList
 %type  <str>   key_match ColLabel SpecialRuleRelation ColId columnDef
@@ -345,7 +475,7 @@ create_questionmarks(char *name, bool array)
 %type  <str>   TableConstraint OptTableElementList Xconst opt_transaction 
 %type  <str>   ConstraintElem key_actions ColQualList type_name
 %type  <str>   target_list target_el update_target_list alias_clause
-%type  <str>   update_target_el qualified_name database_name
+%type  <str>   update_target_el qualified_name database_name alter_using
 %type  <str>   access_method attr_name index_name name func_name
 %type  <str>   file_name AexprConst c_expr ConstTypename var_list
 %type  <str>   a_expr b_expr TruncateStmt CommentStmt OnCommitOption opt_by
@@ -354,34 +484,34 @@ create_questionmarks(char *name, bool array)
 %type  <str>   trim_list in_expr substr_for attrs TableFuncElement
 %type  <str>   Typename SimpleTypename Numeric opt_float opt_numeric
 %type  <str>   opt_decimal Character character opt_varying opt_charset
-%type  <str>   opt_collate opt_timezone opt_interval table_ref fetch_direction
-%type  <str>   row_descriptor ConstDatetime AlterDomainStmt AlterSeqStmt
+%type  <str>   opt_timezone opt_interval table_ref fetch_direction
+%type  <str>   ConstDatetime AlterDomainStmt AlterSeqStmt alter_rel_cmds
 %type  <str>   SelectStmt into_clause OptTemp ConstraintAttributeSpec
 %type  <str>   opt_table opt_all sort_clause sortby_list ConstraintAttr
-%type  <str>   sortby OptUseOp qualified_name_list name_list ColId_or_Sconst
+%type  <str>   sortby qualified_name_list name_list ColId_or_Sconst
 %type  <str>   group_clause having_clause from_clause opt_distinct opt_hold
-%type  <str>   join_outer where_clause relation_expr sub_type opt_arg
-%type  <str>   opt_column_list insert_rest InsertStmt
-%type  <str>   columnList DeleteStmt LockStmt UpdateStmt DeclareCursorStmt
+%type  <str>   join_outer where_clause relation_expr sub_type arg_class
+%type  <str>   opt_column_list insert_rest InsertStmt WithOidsAs param_name
+%type  <str>   columnList DeleteStmt UpdateStmt DeclareCursorStmt
 %type  <str>   NotifyStmt columnElem UnlistenStmt TableElement rowdefinition
 %type  <str>   copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
-%type  <str>   FetchStmt from_in CreateOpClassStmt
+%type  <str>   FetchStmt from_in CreateOpClassStmt like_including_defaults
 %type  <str>   ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
-%type  <str>   opt_full func_arg OptWithOids opt_freeze 
+%type  <str>   opt_full func_arg OptWithOids opt_freeze alter_table_cmd 
 %type  <str>   analyze_keyword opt_name_list ExplainStmt index_params
-%type  <str>   index_elem opt_class access_method_clause
+%type  <str>   index_elem opt_class access_method_clause alter_table_cmds
 %type  <str>   index_opt_unique IndexStmt func_return ConstInterval
 %type  <str>   func_args_list func_args opt_with def_arg overlay_placing
 %type  <str>   def_elem def_list definition DefineStmt select_with_parens
 %type  <str>   opt_instead event RuleActionList opt_using CreateAssertStmt
 %type  <str>   RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
-%type  <str>   RuleStmt opt_column opt_name oper_argtypes NumConst
-%type  <str>   MathOp RemoveFuncStmt aggr_argtype for_update_clause
+%type  <str>   RuleStmt opt_column oper_argtypes NumConst var_name
+%type  <str>   MathOp RemoveFuncStmt aggr_argtype ECPGunreserved_con
 %type  <str>   RemoveAggrStmt opt_procedural select_no_parens CreateCastStmt
-%type  <str>   RemoveOperStmt RenameStmt all_Op opt_Trusted opt_lancompiler
+%type  <str>   RemoveOperStmt RenameStmt all_Op opt_trusted opt_lancompiler
 %type  <str>   VariableSetStmt var_value zone_value VariableShowStmt
 %type  <str>   VariableResetStmt AlterTableStmt from_list overlay_list
-%type  <str>   user_list OptUserList OptUserElem relation_name
+%type  <str>   relation_name OptTableSpace LockStmt opt_lock
 %type  <str>   CreateUserStmt AlterUserStmt CreateSeqStmt OptSeqList
 %type  <str>   OptSeqElem TriggerForSpec TriggerForOpt TriggerForType
 %type  <str>   DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt
@@ -389,51 +519,50 @@ create_questionmarks(char *name, bool array)
 %type  <str>   CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select
 %type  <str>   ViewStmt LoadStmt CreatedbStmt createdb_opt_item ExplainableStmt
 %type  <str>   createdb_opt_list opt_encoding OptInherit opt_equal
-%type  <str>   AlterUserSetStmt privilege_list privilege privilege_target
-%type  <str>   opt_grant_grant_option opt_revoke_grant_option cursor_options
+%type  <str>   privilege_list privilege privilege_target
+%type  <str>   opt_grant_grant_option cursor_options
 %type  <str>   transaction_mode_list_or_empty transaction_mode_list
-%type  <str>   function_with_argtypes_list function_with_argtypes
+%type  <str>   function_with_argtypes_list function_with_argtypes IntConstVar
 %type  <str>   DropdbStmt ClusterStmt grantee RevokeStmt Bit DropOpClassStmt
 %type  <str>   GrantStmt privileges PosAllConst constraints_set_list
-%type  <str>   ConstraintsSetStmt AllConst CreateDomainStmt
+%type  <str>   ConstraintsSetStmt AllConst CreateDomainStmt opt_nowait
 %type  <str>   case_expr when_clause_list case_default case_arg when_clause
 %type  <str>   select_clause opt_select_limit select_limit_value opt_recheck
 %type  <str>   ConstraintTimeSpec AlterDatabaseSetStmt DropAssertStmt
 %type  <str>   select_offset_value ReindexStmt join_type opt_boolean
-%type  <str>   join_qual update_list joined_table opclass_item fetch_count
-%type  <str>   opt_lock lock_type OptGroupList OptGroupElem array_expr_list
+%type  <str>   join_qual joined_table opclass_item 
+%type  <str>   lock_type array_expr_list
 %type  <str>   OptConstrFromTable OptTempTableName StringConst array_expr
-%type  <str>   constraints_set_mode comment_type opt_empty_parentheses
+%type  <str>   constraints_set_mode comment_type 
 %type  <str>   CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
 %type  <str>   opt_force key_update CreateSchemaStmt PosIntStringConst
 %type  <str>   IntConst PosIntConst grantee_list func_type opt_or_replace
-%type  <str>   select_limit opt_for_update_clause CheckPointStmt
+%type  <str>   select_limit CheckPointStmt ECPGColId
 %type  <str>   OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior
 %type  <str>   handler_name any_name_list any_name opt_as insert_column_list
-%type  <str>   columnref dotted_name function_name insert_target_el
+%type  <str>   columnref function_name insert_target_el AllConstVar
 %type  <str>   insert_target_list insert_column_item DropRuleStmt
-%type  <str>   createfunc_opt_item set_rest var_list_or_default
+%type  <str>   createfunc_opt_item set_rest var_list_or_default alter_rel_cmd
 %type  <str>   CreateFunctionStmt createfunc_opt_list func_table
 %type  <str>   DropUserStmt copy_from copy_opt_list copy_opt_item
 %type  <str>   opt_oids TableLikeClause key_action opt_definition
-%type  <str>   cast_context row r_expr qual_Op qual_all_Op opt_default
+%type  <str>   cast_context row qual_Op qual_all_Op opt_default
 %type  <str>   CreateConversionStmt any_operator opclass_item_list
 %type  <str>   iso_level type_list CharacterWithLength ConstCharacter
 %type  <str>   CharacterWithoutLength BitWithLength BitWithoutLength
 %type  <str>   ConstBit GenericType TableFuncElementList opt_analyze
-%type  <str>   opt_sort_clause transaction_access_mode
-
+%type  <str>   opt_sort_clause subquery_Op transaction_mode_item
 %type  <str>   ECPGWhenever ECPGConnect connection_target ECPGOpen
 %type  <str>   indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into 
 %type  <str>   storage_declaration storage_clause opt_initializer c_anything
 %type  <str>   variable_list variable c_thing c_term ECPGKeywords_vanames
 %type  <str>   opt_pointer ECPGDisconnect dis_name storage_modifier
-%type  <str>   ECPGRelease execstring server_name ECPGVarDeclaration
+%type  <str>   execstring server_name ECPGVarDeclaration func_expr
 %type  <str>   connection_object opt_server opt_port c_stuff c_stuff_item
 %type  <str>   user_name opt_user char_variable ora_user ident opt_reference
 %type  <str>   var_type_declarations quoted_ident_stringvar ECPGKeywords_rest
 %type  <str>   db_prefix server opt_options opt_connection_name c_list
-%type  <str>   ECPGSetConnection ECPGTypedef c_args ECPGKeywords 
+%type  <str>   ECPGSetConnection ECPGTypedef c_args ECPGKeywords ECPGCKeywords
 %type  <str>   enum_type civar civarind ECPGCursorStmt ECPGDeallocate
 %type  <str>   ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
 %type  <str>   struct_union_type s_struct_union vt_declarations execute_rest
@@ -443,20 +572,28 @@ create_questionmarks(char *name, bool array)
 %type  <str>   ECPGGetDescriptorHeader ECPGColLabel single_var_declaration
 %type  <str>   reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using
 %type  <str>   col_name_keyword func_name_keyword precision opt_scale
-%type  <str>   ECPGTypeName using_list ECPGColLabelCommon 
+%type  <str>   ECPGTypeName using_list ECPGColLabelCommon UsingConst
 %type  <str>   inf_val_list inf_col_list using_descriptor into_descriptor 
-%type  <str>   ecpg_into_using
+%type  <str>   prepared_name struct_union_type_with_symbol OptConsTableSpace
+%type  <str>   ECPGunreserved ECPGunreserved_interval cvariable
+%type  <str>   AlterOwnerStmt OptTableSpaceOwner CreateTableSpaceStmt
+%type  <str>   DropTableSpaceStmt indirection indirection_el ECPGSetDescriptorHeader
+%type  <str>   AlterDatabaseStmt CreateRoleStmt OptRoleList AlterRoleStmt AlterRoleSetStmt
+%type  <str>   DropRoleStmt add_drop opt_validator common_func_opt_item
+%type  <str>   opt_grant_admin_option AlterFunctionStmt alterfunc_opt_list opt_restrict
+%type  <str>   AlterObjectSchemaStmt alterdb_opt_list for_locking_clause opt_for_locking_clause
+%type  <str>   locked_rels_list opt_granted_by RevokeRoleStmt alterdb_opt_item using_clause
+%type  <str>   GrantRoleStmt opt_asymmetric
 
 %type  <struct_union> s_struct_union_symbol
 
-%type  <descriptor> ECPGGetDescriptor 
+%type  <descriptor> ECPGGetDescriptor ECPGSetDescriptor
 
 %type  <type_enum> simple_type signed_type unsigned_type
 
 %type  <dtype_enum> descriptor_item desc_header_item
 
-%type  <type>  var_type common_type single_vt_type 
-%type  <type>  struct_union_type_with_symbol
+%type  <type>  var_type 
 
 %type  <action> action
 
@@ -481,7 +618,7 @@ statement: ecpgstart opt_at stmt ';'        { connection = NULL; }
                | c_thing               { fprintf(yyout, "%s", $1); free($1); }
                | CPP_LINE              { fprintf(yyout, "%s", $1); free($1); }
                | '{'                   { braces_open++; fputs("{", yyout); }
-               | '}'                   { remove_variables(braces_open--); fputs("}", yyout); }
+               | '}'                   { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); }
                ;
 
 opt_at: AT connection_target
@@ -496,16 +633,42 @@ opt_at: AT connection_target
                                argsinsert = NULL;
                };
 
-stmt:  AlterDatabaseSetStmt            { output_statement($1, 0, connection); }
+stmt:  AlterDatabaseStmt               { output_statement($1, 0, connection); }
+               | AlterDatabaseSetStmt  { output_statement($1, 0, connection); }
                | AlterDomainStmt       { output_statement($1, 0, connection); }
+               | AlterFunctionStmt     { output_statement($1, 0, connection); }
                | AlterGroupStmt        { output_statement($1, 0, connection); }
+               | AlterObjectSchemaStmt { output_statement($1, 0, connection); }
+               | AlterOwnerStmt        { output_statement($1, 0, connection); }
                | AlterSeqStmt          { output_statement($1, 0, connection); }
                | AlterTableStmt        { output_statement($1, 0, connection); }
-               | AlterUserSetStmt      { output_statement($1, 0, connection); }
+               | AlterRoleSetStmt      { output_statement($1, 0, connection); }
+               | AlterRoleStmt         { output_statement($1, 0, connection); }
                | AlterUserStmt         { output_statement($1, 0, connection); }
                | AnalyzeStmt           { output_statement($1, 0, connection); }
                | CheckPointStmt        { output_statement($1, 0, connection); }
-               | ClosePortalStmt       { output_statement($1, 0, connection); }
+               | ClosePortalStmt
+               {
+                       if (INFORMIX_MODE)
+                       {
+                               /* Informix also has a CLOSE DATABASE command that
+                                  essantially works like a DISCONNECT CURRENT 
+                                  as far as I know. */
+                               if (pg_strcasecmp($1+strlen("close "), "database") == 0)
+                               {
+                                       if (connection)
+                                               mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement.\n");
+                                                               
+                                       fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
+                                       whenever_action(2);
+                                       free($1);
+                               }
+                               else
+                                       output_statement($1, 0, connection);
+                       }
+                       else
+                               output_statement($1, 0, connection);
+               }
                | ClusterStmt           { output_statement($1, 0, connection); }
                | CommentStmt           { output_statement($1, 0, connection); }
                | ConstraintsSetStmt    { output_statement($1, 0, connection); }
@@ -519,23 +682,27 @@ stmt:  AlterDatabaseSetStmt               { output_statement($1, 0, connection); }
                | CreateGroupStmt       { output_statement($1, 0, connection); }
                | CreatePLangStmt       { output_statement($1, 0, connection); }
                | CreateOpClassStmt     { output_statement($1, 0, connection); }
+               | CreateRoleStmt        { output_statement($1, 0, connection); }
                | CreateSchemaStmt      { output_statement($1, 0, connection); }
                | CreateSeqStmt         { output_statement($1, 0, connection); }
                | CreateStmt            { output_statement($1, 0, connection); }
+               | CreateTableSpaceStmt  { output_statement($1, 0, connection); }
                | CreateTrigStmt        { output_statement($1, 0, connection); }
                | CreateUserStmt        { output_statement($1, 0, connection); }
                | CreatedbStmt          { output_statement($1, 0, connection); }
                /*| DeallocateStmt      { output_statement($1, 0, connection); }*/
                | DeclareCursorStmt     { output_simple_statement($1); }
                | DefineStmt            { output_statement($1, 0, connection); }
-               | DeleteStmt            { output_statement($1, 0, connection); }
+               | DeleteStmt            { output_statement($1, 1, connection); }
                | DropAssertStmt        { output_statement($1, 0, connection); }
                | DropCastStmt          { output_statement($1, 0, connection); }
                | DropGroupStmt         { output_statement($1, 0, connection); }
                | DropOpClassStmt       { output_statement($1, 0, connection); }
                | DropPLangStmt         { output_statement($1, 0, connection); }
+               | DropRoleStmt          { output_statement($1, 0, connection); }
                | DropRuleStmt          { output_statement($1, 0, connection); }
                | DropStmt              { output_statement($1, 0, connection); }
+               | DropTableSpaceStmt    { output_statement($1, 0, connection); }
                | DropTrigStmt          { output_statement($1, 0, connection); }
                | DropUserStmt          { output_statement($1, 0, connection); }
                | DropdbStmt            { output_statement($1, 0, connection); }
@@ -543,8 +710,9 @@ stmt:  AlterDatabaseSetStmt         { output_statement($1, 0, connection); }
 /*             | ExecuteStmt           { output_statement($1, 0, connection); }*/
                | FetchStmt             { output_statement($1, 1, connection); }
                | GrantStmt             { output_statement($1, 0, connection); }
+               | GrantRoleStmt         { output_statement($1, 0, connection); }
                | IndexStmt             { output_statement($1, 0, connection); }
-               | InsertStmt            { output_statement($1, 0, connection); }
+               | InsertStmt            { output_statement($1, 1, connection); }
                | ListenStmt            { output_statement($1, 0, connection); }
                | LoadStmt              { output_statement($1, 0, connection); }
                | LockStmt              { output_statement($1, 0, connection); }
@@ -556,8 +724,9 @@ stmt:  AlterDatabaseSetStmt         { output_statement($1, 0, connection); }
                | RemoveFuncStmt        { output_statement($1, 0, connection); }
                | RenameStmt            { output_statement($1, 0, connection); }
                | RevokeStmt            { output_statement($1, 0, connection); }
+               | RevokeRoleStmt        { output_statement($1, 0, connection); }
                | RuleStmt              { output_statement($1, 0, connection); }
-               | SelectStmt            { output_statement($1, 0, connection); }
+               | SelectStmt            { output_statement($1, 1, connection); }
                | TransactionStmt
                {
                        fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
@@ -566,7 +735,7 @@ stmt:  AlterDatabaseSetStmt         { output_statement($1, 0, connection); }
                }
                | TruncateStmt          { output_statement($1, 0, connection); }
                | UnlistenStmt          { output_statement($1, 0, connection); }
-               | UpdateStmt            { output_statement($1, 0, connection); }
+               | UpdateStmt            { output_statement($1, 1, connection); }
                | VacuumStmt            { output_statement($1, 0, connection); }
                | VariableSetStmt       { output_statement($1, 0, connection); }
                | VariableShowStmt      { output_statement($1, 0, connection); }
@@ -583,10 +752,7 @@ stmt:  AlterDatabaseSetStmt                { output_statement($1, 0, connection); }
                        if (connection)
                                mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n");
 
-                       if (compat == ECPG_COMPAT_INFORMIX)
-                               fprintf(yyout, "{ ECPGconnect_informix(__LINE__, %s, %d); ", $1, autocommit);
-                       else
-                               fprintf(yyout, "{ ECPGconnect(__LINE__, %s, %d); ", $1, autocommit);
+                       fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
                        reset_variables();
                        whenever_action(2);
                        free($1);
@@ -598,15 +764,15 @@ stmt:  AlterDatabaseSetStmt               { output_statement($1, 0, connection); }
                | ECPGDeallocate
                {
                        if (connection)
-                               mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n");
-
-                       fputc('{', yyout);
-                       fputs($1, yyout);
+                               mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement.\n");
+                       fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s);", compat, $1);
                        whenever_action(2);
                        free($1);
                }
                | ECPGDeallocateDescr
                {
+                       if (connection)
+                               mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement.\n");
                        fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1);
                        whenever_action(0);
                        free($1);
@@ -642,7 +808,7 @@ stmt:  AlterDatabaseSetStmt         { output_statement($1, 0, connection); }
                }
                | ECPGFree
                {
-                       fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
+                       fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, \"%s\");", compat, $1);
 
                        whenever_action(2);
                        free($1);
@@ -663,30 +829,10 @@ stmt:  AlterDatabaseSetStmt               { output_statement($1, 0, connection); }
                | ECPGOpen
                {
                        struct cursor *ptr;
-                       struct arguments *p;
-
-                       for (ptr = cur; ptr != NULL; ptr=ptr->next)
-                       {
-                               if (strcmp(ptr->name, $1) == 0)
-                                       break;
-                       }
-
-                       if (ptr == NULL)
-                       {
-                               snprintf(errortext, sizeof(errortext), "trying to open undeclared cursor %s\n", $1);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
-                       else
-                       {
-                               /* merge variables given in prepare statement with those given here */
-                               for (p = ptr->argsinsert; p; p = p->next)
-                                       append_variable(&argsinsert, p->variable, p->indicator);
-
-                               for (p = ptr->argsresult; p; p = p->next)
-                                       add_variable(&argsresult, p->variable, p->indicator);
 
+                       if ((ptr = add_additional_variables($1, true)) != NULL)
                                output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL);
-                       }
+                       ptr->opened = true;
                }
                | ECPGPrepare
                {
@@ -697,7 +843,7 @@ stmt:  AlterDatabaseSetStmt         { output_statement($1, 0, connection); }
                        whenever_action(2);
                        free($1);
                }
-               | ECPGRelease           { /* output already done */ }
+               /* | ECPGRelease                { / * output already done * / } */
                | ECPGSetAutocommit
                {
                        fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
@@ -713,6 +859,19 @@ stmt:  AlterDatabaseSetStmt                { output_statement($1, 0, connection); }
                        whenever_action(2);
                        free($1);
                }
+               | ECPGSetDescriptor
+               {
+                       lookup_descriptor($1.name, connection);
+                       output_set_descr($1.name, $1.str);
+                       free($1.name);
+                       free($1.str);
+               }
+               | ECPGSetDescriptorHeader
+               {
+                       lookup_descriptor($1, connection);
+                       output_set_descr_header($1);
+                       free($1);
+               }
                | ECPGTypedef
                {
                        if (connection)
@@ -745,79 +904,113 @@ stmt:  AlterDatabaseSetStmt              { output_statement($1, 0, connection); }
 
 /*****************************************************************************
  *
- * Create a new Postgres DBMS user
+ * Create a new Postgres DBMS role
  *
  *
  *****************************************************************************/
 
-CreateUserStmt: CREATE USER UserId opt_with OptUserList
-                       { $$ = cat_str(4, make_str("create user"), $3, make_str("with"), $5); }
+CreateRoleStmt: CREATE ROLE RoleId opt_with OptRoleList
+                       { $$ = cat_str(4, make_str("create role"), $3, make_str("with"), $5); }
                ;
 
 opt_with:  WITH                { $$ = make_str("with"); }
                | /*EMPTY*/     { $$ = EMPTY; }
                ;
 
+/*
+ * Options for CREATE ROLE and ALTER ROLE (also used by CREATE/ALTER USER
+ * for backwards compatibility).  Note: the only option required by SQL99
+ * is "WITH ADMIN name".
+ */
+OptRoleList:
+       PASSWORD Sconst                 { $$ = cat2_str(make_str("password"), $2); }
+       | ENCRYPTED PASSWORD Sconst     { $$ = cat2_str(make_str("encrypted password"), $3); }
+       | UNENCRYPTED PASSWORD Sconst   { $$ = cat2_str(make_str("unencrypted password"), $3); }
+       | SUPERUSER_P                   { $$ = make_str("superuser"); }
+       | NOSUPERUSER                   { $$ = make_str("nosuperuser"); }
+       | INHERIT                       { $$ = make_str("inherit"); }
+       | NOINHERIT                     { $$ = make_str("noinherit"); }
+       | CREATEDB                      { $$ = make_str("createdb"); }
+       | NOCREATEDB                    { $$ = make_str("nocreatedb"); }
+       | CREATEROLE                    { $$ = make_str("createrole"); }
+       | NOCREATEROLE                  { $$ = make_str("nocreaterole"); }
+       | LOGIN_P                       { $$ = make_str("login"); }
+       | NOLOGIN_P                     { $$ = make_str("nologin"); }
+       | CONNECTION LIMIT IntConst     { $$ = cat2_str(make_str("connection limit"), $3); }
+       | VALID UNTIL Sconst            { $$ = cat2_str(make_str("valid until"), $3); }
+       | USER name_list                { $$ = cat2_str(make_str("user"), $2); }
+       | SYSID PosIntConst             { $$ = cat2_str(make_str("sysid"), $2); }
+       | ADMIN name_list               { $$ = cat2_str(make_str("admin"), $2); }
+       | ROLE name_list                { $$ = cat2_str(make_str("role"), $2); }
+       | IN_P ROLE name_list           { $$ = cat2_str(make_str("in role"), $3); }
+       | IN_P GROUP_P name_list        { $$ = cat2_str(make_str("in group"), $3); }
+       ;
 
 /*****************************************************************************
  *
- * Alter a postgresql DBMS user
+ * Create a new Postgres DBMS user (role with implied login ability)
+ *
+ *****************************************************************************/
+
+CreateUserStmt:
+                        CREATE USER RoleId opt_with OptRoleList
+                        {
+                               $$ = cat_str(4, make_str("create user"), $3, $4, $5);
+                       }
+                       ;
+
+
+/*****************************************************************************
+ *
+ * Alter a postgresql DBMS role
  *
  *
  *****************************************************************************/
 
-AlterUserStmt: ALTER USER UserId OptUserList
-                       { $$ = cat_str(3, make_str("alter user"), $3, $4); }
-               | ALTER USER UserId WITH OptUserList
-                       { $$ = cat_str(4, make_str("alter user"), $3, make_str("with"), $5); }
+AlterRoleStmt: ALTER ROLE RoleId opt_with OptRoleList
+                       { $$ = cat_str(4, make_str("alter role"), $3, $4, $5); }
+               ;
+
+AlterRoleSetStmt: ALTER ROLE RoleId SET set_rest
+                       { $$ = cat_str(4, make_str("alter role"), $3, make_str("set"), $5); }
+               | ALTER ROLE RoleId VariableResetStmt
+                       { $$ = cat_str(3, make_str("alter role"), $3, $4); }
                ;
 
-AlterUserSetStmt: ALTER USER UserId SET set_rest
+/*****************************************************************************
+ *
+ * Alter a postgresql DBMS user
+ *
+ *****************************************************************************/
+
+AlterUserStmt: ALTER USER RoleId opt_with OptRoleList
+               { $$ = cat_str(4, make_str("alter user"), $3, $4, $5); };
+
+AlterRoleSetStmt: ALTER USER RoleId SET set_rest
                        { $$ = cat_str(4, make_str("alter user"), $3, make_str("set"), $5); }
-               | ALTER USER UserId VariableResetStmt
+               | ALTER USER RoleId VariableResetStmt
                        { $$ = cat_str(3, make_str("alter user"), $3, $4); }
                ;
 
+/*****************************************************************************
+ *
+ * Drop a postgresql DBMS role
+ *
+ *
+ *****************************************************************************/
+DropRoleStmt:  DROP ROLE name_list
+                       { $$ = cat2_str(make_str("drop role"), $3);}
+               ;
+               
 /*****************************************************************************
  *
  * Drop a postgresql DBMS user
  *
  *
  *****************************************************************************/
-DropUserStmt:  DROP USER user_list
+DropUserStmt:  DROP USER name_list
                        { $$ = cat2_str(make_str("drop user"), $3);}
                ;
-/*
- * Options for CREATE USER and ALTER USER
- */
-
-OptUserList: OptUserList OptUserElem   { $$ = cat2_str($1, $2); }
-               | /* EMPTY */                                   { $$ = EMPTY; }
-               ;
-
-OptUserElem:  PASSWORD Sconst
-               { $$ = cat2_str(make_str("password"), $2); }
-               | SYSID PosIntConst
-                       { $$ = cat2_str(make_str("sysid"), $2); }
-               | CREATEDB
-                       { $$ = make_str("createdb"); }
-               | NOCREATEDB
-                       { $$ = make_str("nocreatedb"); }
-               | CREATEUSER
-                       { $$ = make_str("createuser"); }
-               | NOCREATEUSER
-                       { $$ = make_str("nocreateuser"); }
-               | IN_P GROUP_P user_list
-                       { $$ = cat2_str(make_str("in group"), $3); }
-               | VALID UNTIL Sconst
-                       { $$ = cat2_str(make_str("valid until"), $3); }
-               ;
-
-user_list:     user_list ',' UserId
-                       { $$ = cat_str(3, $1, make_str(","), $3); }
-               | UserId
-                       { $$ = $1; }
-               ;
 
 /*****************************************************************************
  *
@@ -825,45 +1018,31 @@ user_list:       user_list ',' UserId
  *
  *
  ****************************************************************************/
-CreateGroupStmt:  CREATE GROUP_P UserId OptGroupList
-                       { $$ = cat_str(3, make_str("create group"), $3, $4); }
-               | CREATE GROUP_P UserId WITH OptGroupList
-                       { $$ = cat_str(4, make_str("create group"), $3, make_str("with"), $5); }
-               ;
-
-/*
- * Options for CREATE GROUP
- */
-OptGroupList: OptGroupList OptGroupElem                { $$ = cat2_str($1, $2); }
-               | /* EMPTY */                                           { $$ = EMPTY; }
+CreateGroupStmt:  CREATE GROUP_P RoleId opt_with OptRoleList
+                       { $$ = cat_str(4, make_str("create group"), $3, $4, $5); }
                ;
 
-OptGroupElem:  USER user_list
-                       { $$ = cat2_str(make_str("user"), $2); }
-               | SYSID PosIntConst
-                       { $$ = cat2_str(make_str("sysid"), $2); }
-               ;
-
-
 /*****************************************************************************
  *
  * Alter a postgresql group
  *
  *
  *****************************************************************************/
-AlterGroupStmt: ALTER GROUP_P UserId ADD USER user_list
-                       { $$ = cat_str(4, make_str("alter group"), $3, make_str("add user"), $6); }
-               | ALTER GROUP_P UserId DROP USER user_list
-                       { $$ = cat_str(4, make_str("alter group"), $3, make_str("drop user"), $6); }
+AlterGroupStmt: ALTER GROUP_P RoleId add_drop USER name_list
+                       { $$ = cat_str(5, make_str("alter group"), $3, $4, make_str("user"), $6); }
                ;
 
+add_drop: ADD_P                { $$ = make_str("add"); } 
+       | DROP          { $$ = make_str("drop"); } 
+       ;
+       
 /*****************************************************************************
  *
  * Drop a postgresql group
  *
  *
  *****************************************************************************/
-DropGroupStmt: DROP GROUP_P UserId
+DropGroupStmt: DROP GROUP_P name_list
                        { $$ = cat2_str(make_str("drop group"), $3); }
                ;
 
@@ -874,10 +1053,10 @@ DropGroupStmt: DROP GROUP_P UserId
  *
  *****************************************************************************/
 
-CreateSchemaStmt:  CREATE SCHEMA UserId OptSchemaName AUTHORIZATION UserId OptSchemaEltList
-                       { $$ = cat_str(6, make_str("create scheme"), $3, $4, make_str("authorization"), $6, $7); }
+CreateSchemaStmt:  CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
+                       { $$ = cat_str(5, make_str("create schema"), $3, make_str("authorization"), $5, $6); }
                | CREATE SCHEMA ColId OptSchemaEltList
-                       { $$ = cat_str(3, make_str("create scheme"), $3, $4); }
+                       { $$ = cat_str(3, make_str("create schema"), $3, $4); }
                ;
 
 OptSchemaName: ColId           { $$ = $1; }
@@ -893,6 +1072,9 @@ OptSchemaEltList: OptSchemaEltList schema_stmt         { $$ = cat2_str($1, $2);
  *     statement (in addition to by themselves).
  */
 schema_stmt: CreateStmt                { $$ = $1; }
+               | IndexStmt     { $$ = $1; }
+               | CreateSeqStmt { $$ = $1; }
+               | CreateTrigStmt        { $$ = $1; }
                | GrantStmt     { $$ = $1; }
                | ViewStmt      { $$ = $1; }
                ;
@@ -915,9 +1097,9 @@ VariableSetStmt:  SET set_rest
                        { $$ = cat2_str(make_str("set session"), $3 ); }
                ;
 
-set_rest:      ColId TO var_list_or_default
+set_rest:      var_name TO var_list_or_default
                        { $$ = cat_str(3, $1, make_str("to"), $3); }
-               | ColId "=" var_list_or_default
+               | var_name "=" var_list_or_default
                         { $$ = cat_str(3, $1, make_str("="), $3); }
                | TIME ZONE zone_value
                        { $$ = cat2_str(make_str("time zone"), $3); }
@@ -927,12 +1109,19 @@ set_rest:        ColId TO var_list_or_default
                        { $$ = cat2_str(make_str("session characteristics as transaction"), $5); }
                | NAMES opt_encoding
                        { $$ = cat2_str(make_str("names"), $2); }
+               | ROLE ColId_or_Sconst
+                       { $$ = cat2_str(make_str("role"), $2); }
                | SESSION AUTHORIZATION ColId_or_Sconst
                        { $$ = cat2_str(make_str("session authorization"), $3); }
                | SESSION AUTHORIZATION DEFAULT
                        { $$ = make_str("session authorization default"); }
                ;
 
+var_name:      ECPGColId               { $$ = $1; }
+               | var_name '.' ColId    { $$ = cat_str(3, $1, make_str("."), $3); }
+               ;
+               
+
 var_list_or_default:  var_list
                        { $$ = $1; }
                | DEFAULT
@@ -945,7 +1134,9 @@ var_list:  var_value
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-iso_level:     READ COMMITTED  { $$ = make_str("read committed"); }
+iso_level:     READ UNCOMMITTED        { $$ = make_str("read uncommitted"); }
+               | READ COMMITTED        { $$ = make_str("read committed"); }
+               | REPEATABLE READ       { $$ = make_str("repeatable read"); }
                | SERIALIZABLE          { $$ = make_str("serializable"); }
                ;
 
@@ -988,7 +1179,7 @@ ColId_or_Sconst: ColId                     { $$ = $1; }
                | StringConst                   { $$ = $1; }
                ;
 
-VariableShowStmt:  SHOW ColId
+VariableShowStmt:  SHOW var_name
                        { $$ = cat2_str(make_str("show"), $2); }
                | SHOW TIME ZONE
                        { $$ = make_str("show time zone"); }
@@ -1000,7 +1191,7 @@ VariableShowStmt:  SHOW ColId
                        { $$ = make_str("show all"); }
                ;
 
-VariableResetStmt:     RESET ColId
+VariableResetStmt:     RESET var_name
                        { $$ = cat2_str(make_str("reset"), $2); }
                | RESET TIME ZONE
                        { $$ = make_str("reset time zone"); }
@@ -1035,50 +1226,98 @@ CheckPointStmt: CHECKPOINT         { $$= make_str("checkpoint"); }
 
 /*****************************************************************************
  *
- *     ALTER TABLE variations
+ *     ALTER [ TABLE | INDEX ] variations
  *
  *****************************************************************************/
 
 AlterTableStmt:
-/* ALTER TABLE <relation> ADD [COLUMN] <coldef> */
-               ALTER TABLE relation_expr ADD opt_column columnDef
-                       { $$ = cat_str(5, make_str("alter table"), $3, make_str("add"), $5, $6); }
+               ALTER TABLE relation_expr alter_table_cmds
+                       { $$ = cat_str(3, make_str("alter table"), $3, $4); }
+               |       ALTER INDEX relation_expr alter_rel_cmds
+                       { $$ = cat_str(3, make_str("alter table"), $3, $4); }
+               ;
+
+/* Subcommands that are for ALTER TABLE only */
+alter_table_cmds:
+               alter_table_cmd                         { $$ = $1; }
+               | alter_table_cmds ',' alter_table_cmd  { $$ = cat_str(3, $1, make_str(","), $3); }
+               ;
+
+alter_table_cmd:
+               ADD_P opt_column columnDef
+/* ALTER TABLE <relation> ADD_P [COLUMN] <coldef> */
+                       { $$ = cat_str(3, make_str("add"), $2, $3); }
 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP DEFAULT} */
-               | ALTER TABLE relation_expr ALTER opt_column ColId alter_column_default
-                       { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, $7); }
+               | ALTER opt_column ColId alter_column_default
+                       { $$ = cat_str(4, make_str("alter"), $2, $3, $4); }
 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> DROP NOT NULL */
-               | ALTER TABLE relation_expr ALTER opt_column ColId DROP NOT NULL_P
-                       { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("drop not null")); }
+               | ALTER opt_column ColId DROP NOT NULL_P
+                       { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("drop not null")); }
 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET NOT NULL */
-               | ALTER TABLE relation_expr ALTER opt_column ColId SET NOT NULL_P
-                       { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set not null")); }
+               | ALTER opt_column ColId SET NOT NULL_P
+                       { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("set not null")); }
 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STATISTICS <IntegerOnly> */
-               | ALTER TABLE relation_expr ALTER opt_column ColId SET STATISTICS PosIntConst
-                       { $$ = cat_str(7, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set statistics"), $9); }
+               | ALTER opt_column ColId SET STATISTICS PosIntConst
+                       { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set statistics"), $6); }
 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
-               | ALTER TABLE relation_expr ALTER opt_column ColId SET STORAGE ColId
-                       { $$ = cat_str(7, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set storage"), $9); }
+               | ALTER opt_column ColId SET STORAGE ColId
+                       { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set storage"), $6); }
 /* ALTER TABLE <relation> DROP [COLUMN] <colname> {RESTRICT|CASCADE} */
-               | ALTER TABLE relation_expr DROP opt_column ColId opt_drop_behavior
-                       { $$ = cat_str(6, make_str("alter table"), $3, make_str("drop"), $5, $6, $7); }
-/* ALTER TABLE <relation> ADD CONSTRAINT ... */
-               | ALTER TABLE relation_expr ADD TableConstraint
-                       { $$ = cat_str(4, make_str("alter table"), $3, make_str("add"), $5); }
+               | DROP opt_column ColId opt_drop_behavior
+                       { $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
+/* ALTER TABLE <relation> ALTER [COLUMN] <colname> TYPE <typename> [ USING <expression> ] */
+               | ALTER opt_column ColId TYPE_P Typename alter_using
+                       { $$ = cat_str(6, make_str("alter"), $2, $3, make_str("type"), $5, $6); }
+/* ALTER TABLE <relation> ADD_P CONSTRAINT ... */
+               | ADD_P TableConstraint
+                       { $$ = cat_str(2, make_str("add"), $2); }
 /* ALTER TABLE <relation> DROP CONSTRAINT ... */
-               | ALTER TABLE relation_expr DROP CONSTRAINT name opt_drop_behavior
-                       { $$ = cat_str(5, make_str("alter table"), $3, make_str("drop constraint"), $6, $7); }
+               | DROP CONSTRAINT name opt_drop_behavior
+                       { $$ = cat_str(3, make_str("drop constraint"), $3, $4); }
 /* ALTER TABLE <relation> SET WITHOUT OIDS  */
-               | ALTER TABLE relation_expr SET WITHOUT OIDS
-                       { $$ = cat_str(3, make_str("alter table"), $3, make_str("set without oids")); }
+               | SET WITHOUT OIDS
+                       { $$ = make_str("set without oids"); }
  /* ALTER TABLE <name> CREATE TOAST TABLE */
-               | ALTER TABLE qualified_name CREATE TOAST TABLE
-                       { $$ = cat_str(3, make_str("alter table"), $3, make_str("create toast table")); }
-/* ALTER TABLE <name> OWNER TO UserId */
-               | ALTER TABLE qualified_name OWNER TO UserId
-                       { $$ = cat_str(4, make_str("alter table"), $3, make_str("owner to"), $6); }
+               | CREATE TOAST TABLE
+                       { $$ = make_str("create toast table"); }
 /* ALTER TABLE <name> CLUSTER ON <indexname> */
-               | ALTER TABLE qualified_name CLUSTER ON name
-                       { $$ = cat_str(4, make_str("alter table"), $3, make_str("cluster on"), $6); }
+               | CLUSTER ON name
+                       { $$ = cat_str(2, make_str("cluster on"), $3); }
+/* ALTER TABLE <name> SET WITHOUT CLUSTER */
+               | SET WITHOUT CLUSTER
+                       { $$ = make_str("set without cluster"); }
+/* ALTER TABLE <name> ENABLE TRIGGER <trig> */
+                | ENABLE_P TRIGGER name
+                       { $$ = cat2_str(make_str("enable trigger"), $3); }
+/* ALTER TABLE <name> ENABLE TRIGGER ALL */
+                | ENABLE_P TRIGGER ALL
+                       { $$ = make_str("enable trigger all"); }
+/* ALTER TABLE <name> ENABLE TRIGGER USER */
+                | ENABLE_P TRIGGER USER
+                       { $$ = make_str("enable trigger user"); }
+/* ALTER TABLE <name> DISABLE TRIGGER <trig> */
+                | DISABLE_P TRIGGER name
+                       { $$ = cat2_str(make_str("disable trigger"), $3); }
+/* ALTER TABLE <name> DISABLE TRIGGER ALL */
+                | DISABLE_P TRIGGER ALL
+                       { $$ = make_str("disable trigger all"); }
+/* ALTER TABLE <name> DISABLE TRIGGER USER */
+                | DISABLE_P TRIGGER USER
+                       { $$ = make_str("disable trigger user"); }
+               ;
+
+alter_rel_cmds: alter_rel_cmd                                  { $$ = $1; }
+               | alter_rel_cmds ',' alter_rel_cmd      { $$ = cat_str(3, $1, make_str(","), $3); }
+               ;
+
+/* Subcommands that are for ALTER TABLE or ALTER INDEX */
+alter_rel_cmd:
+               /* ALTER [TABLE|INDEX] <name> OWNER TO RoleId */
+               OWNER TO RoleId
+                       { $$ = cat_str(2, make_str("owner to"), $3); }
+               /* ALTER [TABLE|INDEX] <name> SET TABLESPACE <tablespacename> */
+               | SET TABLESPACE name
+                       { $$ = cat_str(2, make_str("set tablespace"), $3); }
                ;
 
 alter_column_default:
@@ -1091,6 +1330,10 @@ opt_drop_behavior: CASCADE                       { $$ = make_str("cascade"); }
                | /* EMPTY */                   { $$ = EMPTY; }
                ;
 
+alter_using:   USING a_expr                    { $$ = cat2_str(make_str("using"), $2); }
+               | /* EMPTY */                   { $$ = EMPTY; }
+               ;
+                               
 /*****************************************************************************
  *
  *             QUERY :
@@ -1098,7 +1341,10 @@ opt_drop_behavior: CASCADE                       { $$ = make_str("cascade"); }
  *
  *****************************************************************************/
 
-ClosePortalStmt:  CLOSE name   { $$ = cat2_str(make_str("close"), $2); }
+ClosePortalStmt:  CLOSE name
+               {
+                       $$ = cat2_str(make_str("close"), $2);
+               }
                ;
 
 /*****************************************************************************
@@ -1138,6 +1384,17 @@ copy_opt_item:   BINARY          { $$ = make_str("binary"); }
                        { $$ = cat_str(3, make_str("delimiter"), $2, $3); }
                | NULL_P opt_as StringConst
                        { $$ = cat_str(3, make_str("null"), $2, $3); }
+               | CSV           { $$ = make_str("csv"); }
+               | HEADER_P      { $$ = make_str("header"); }
+               | QUOTE opt_as Sconst
+                       { $$ = cat_str(3, make_str("quote"), $2, $3); }
+               | ESCAPE opt_as Sconst
+                       { $$ = cat_str(3, make_str("escape"), $2, $3); }
+               | FORCE QUOTE columnList
+                       { $$ = cat2_str(make_str("force quote"), $3); }
+               | FORCE NOT NULL_P columnList
+                       { $$ = cat2_str(make_str("force not null"), $4); }
+               
                ;
 
 opt_binary:    BINARY          { $$ = make_str("binary"); }
@@ -1170,11 +1427,11 @@ opt_using:      USING           { $$ = make_str("using"); }
  *****************************************************************************/
 
 CreateStmt:  CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
-                               OptInherit OptWithOids OnCommitOption
-                       { $$ = cat_str(10, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9, $10); }
+                               OptInherit OptWithOids OnCommitOption OptTableSpace
+                       { $$ = cat_str(11, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9, $10, $11); }
                | CREATE OptTemp TABLE qualified_name OF qualified_name
-                       '(' OptTableElementList ')' OptWithOids OnCommitOption
-                       { $$ = cat_str(11, make_str("create"), $2, make_str("table"), $4, make_str("of"), $6, make_str("("), $8, make_str(")"), $10, $11); }
+                       '(' OptTableElementList ')' OptWithOids OnCommitOption OptTableSpace
+                       { $$ = cat_str(12, make_str("create"), $2, make_str("table"), $4, make_str("of"), $6, make_str("("), $8, make_str(")"), $10, $11, $12); }
                ;
 
 /*
@@ -1208,14 +1465,9 @@ TableElement:  columnDef         { $$ = $1; }
                | TableConstraint       { $$ = $1; }
                ;
 
-columnDef:     ColId Typename ColQualList opt_collate
+columnDef:     ColId Typename ColQualList 
                {
-                       if (strlen($4) > 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "Currently unsupported CREATE TABLE / COLLATE %s will be passed to backend", $4);
-                               mmerror(PARSE_ERROR, ET_WARNING, errortext);
-                       }
-                       $$ = cat_str(4, $1, $2, $3, $4);
+                       $$ = cat_str(3, $1, $2, $3);
                }
                ;
 
@@ -1244,10 +1496,10 @@ ColConstraintElem:      NOT NULL_P
                        { $$ = make_str("not null"); }
                | NULL_P
                        { $$ = make_str("null"); }
-               | UNIQUE
-                       { $$ = make_str("unique"); }
-               | PRIMARY KEY
-                       { $$ = make_str("primary key"); }
+               | UNIQUE OptConsTableSpace
+                       { $$ = cat2_str(make_str("unique"), $2); }
+               | PRIMARY KEY OptConsTableSpace
+                       { $$ = cat2_str(make_str("primary key"), $3); }
                | CHECK '(' a_expr ')'
                        { $$ = cat_str(3, make_str("check ("), $3, make_str(")")); }
                | DEFAULT b_expr
@@ -1273,13 +1525,18 @@ ConstraintAttr: DEFERRABLE              { $$ = make_str("deferrable"); }
                | INITIALLY IMMEDIATE   { $$ = make_str("initially immediate"); }
                ;
 
-TableLikeClause:  LIKE any_name
-                       {
-                               mmerror(PARSE_ERROR, ET_ERROR, "LIKE in table definitions not yet supported");
-                               $$ = cat2_str(make_str("like"), $2);
-                       }
+TableLikeClause:  LIKE qualified_name like_including_defaults
+               {
+                       $$ = cat_str(3, make_str("like"), $2, $3);
+               }
                ;
 
+like_including_defaults:
+               INCLUDING DEFAULTS      { $$ = make_str("including defaults"); }
+              | EXCLUDING DEFAULTS     { $$ = make_str("excluding defaults"); }
+              | /* EMPTY */            { $$ = EMPTY; } 
+             ;
+
 /* ConstraintElem specifies constraint syntax which is not embedded into
  *     a column definition. ColConstraintElem specifies the embedded form.
  * - thomas 1997-12-03
@@ -1292,10 +1549,10 @@ TableConstraint:  CONSTRAINT name ConstraintElem
 
 ConstraintElem:  CHECK '(' a_expr ')'
                        { $$ = cat_str(3, make_str("check("), $3, make_str(")")); }
-               | UNIQUE '(' columnList ')'
-                       { $$ = cat_str(3, make_str("unique("), $3, make_str(")")); }
-               | PRIMARY KEY '(' columnList ')'
-                       { $$ = cat_str(3, make_str("primary key("), $4, make_str(")")); }
+               | UNIQUE '(' columnList ')' OptConsTableSpace
+                       { $$ = cat_str(4, make_str("unique("), $3, make_str(")"), $5); }
+               | PRIMARY KEY '(' columnList ')' OptConsTableSpace
+                       { $$ = cat_str(4, make_str("primary key("), $4, make_str(")"), $6); }
                | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name opt_column_list
                        key_match key_actions ConstraintAttributeSpec
                        { $$ = cat_str(8, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10, $11); }
@@ -1364,23 +1621,43 @@ OnCommitOption:   ON COMMIT DROP                { $$ = make_str("on commit drop"); }
                | /*EMPTY*/                     { $$ = EMPTY; }
                ;
 
+OptTableSpace:  TABLESPACE name        { $$ = cat2_str(make_str("tablespace"), $2); }
+               | /*EMPTY*/     { $$ = EMPTY; }
+               ;
 
+OptConsTableSpace: USING INDEX TABLESPACE name { $$ = cat2_str(make_str("using index tablespace"), $4); }
+                       | /*EMPTY*/             { $$ = EMPTY; }
+                       ;
+                       
 /*
  * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
  * SELECT ... INTO.
  */
 
-CreateAsStmt:  CREATE OptTemp TABLE qualified_name OptCreateAs AS
+CreateAsStmt:  CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs
                { FoundInto = 0; }
                SelectStmt
                {
                        if (FoundInto == 1)
                                mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT may not specify INTO");
 
-                       $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4, $5, make_str("as"), $8);
+                       $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4, $5, $6, $8);
                }
                ;
 
+/*
+ * To avoid a shift/reduce conflict in CreateAsStmt, we need to
+ * include the 'AS' terminal in the parsing of WITH/WITHOUT
+ * OIDS. Unfortunately that means this production is effectively a
+ * duplicate of OptWithOids.
+ */
+WithOidsAs:
+                       WITH OIDS AS                 { $$ = make_str("with oids as"); }
+                       | WITHOUT OIDS AS            { $$ = make_str("without oids as"); }
+                       | AS                         { $$ = make_str("as"); }
+                       ;
+
+
 OptCreateAs:  '(' CreateAsList ')'
                        { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
                | /*EMPTY*/
@@ -1405,7 +1682,7 @@ CreateAsElement:  ColId { $$ = $1; }
  *****************************************************************************/
 
 CreateSeqStmt: CREATE OptTemp SEQUENCE qualified_name OptSeqList
-                       { $$ = cat_str(4, make_str("create sequence"), $2, $4, $5); }
+                       { $$ = cat_str(5, make_str("create"), $2, make_str("sequence"), $4, $5); }
                ;
 
 AlterSeqStmt: ALTER SEQUENCE qualified_name OptSeqList
@@ -1450,25 +1727,30 @@ opt_by:         BY      { $$ = make_str("by"); }
  *
  *****************************************************************************/
 
-CreatePLangStmt:  CREATE opt_Trusted opt_procedural LANGUAGE ColId_or_Sconst
-                       HANDLER handler_name opt_lancompiler
-                       { $$ = cat_str(8, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8); }
+CreatePLangStmt:  CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+                       { $$ = cat_str(5, make_str("create"), $2, $3, make_str("language"), $5); }
+               | CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
+                       HANDLER handler_name opt_validator opt_lancompiler
+                       { $$ = cat_str(9, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8, $9); }
                ;
 
-opt_Trusted:   TRUSTED { $$ = make_str("trusted"); }
+opt_trusted:   TRUSTED { $$ = make_str("trusted"); }
                | /*EMPTY*/             { $$ = EMPTY; }
                ;
 
 /* This ought to be just func_name, but that causes reduce/reduce conflicts
  * (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
- * Work around by using name and dotted_name separately.
+ * Work around by using simple names instead.
  */
-handler_name: name
-                               { $$ = $1; }
-       | dotted_name
-                               { $$ = $1; /* XXX changing soon */ }
+handler_name: name     { $$ = $1; }
+       | name attrs    { $$ = cat2_str($1, $2); }
                ;
 
+opt_validator: VALIDATOR handler_name
+                       { $$ = cat2_str(make_str("validator"), $2); }
+               | /*EMPTY*/
+                       { $$ = ""; }
+               ;
 opt_lancompiler: LANCOMPILER StringConst
                        { $$ = cat2_str(make_str("lancompiler"), $2); }
                | /*EMPTY*/
@@ -1483,6 +1765,35 @@ opt_procedural: PROCEDURAL       { $$ = make_str("prcedural"); }
                | /*EMPTY*/                     { $$ = EMPTY; }
                ;
 
+/*****************************************************************************
+ *
+ *             QUERY:
+ *             CREATE TABLESPACE tablespace LOCATION '/path/to/tablespace/'
+ *
+ *****************************************************************************/
+
+CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst
+                       { $$ = cat_str(5,make_str("create tablespace"), $3, $4, make_str("location"), $6); }
+               ;
+
+OptTableSpaceOwner: OWNER name { $$ = cat2_str(make_str("owner"), $2); }
+               | /*EMPTY*/     { $$ = EMPTY; }
+               ;
+
+/*****************************************************************************
+ *
+ *             QUERY :
+ *                             DROP TABLESPACE <tablespace>
+ *
+ *             No need for drop behaviour as we cannot implement dependencies for
+ *             objects in other databases; we can only support RESTRICT.
+ *
+ ****************************************************************************/
+
+
+DropTableSpaceStmt: DROP TABLESPACE name       { $$ = cat2_str(make_str("drop tablespace"), $3); };
+
+
 /*****************************************************************************
  *
  *             QUERIES :
@@ -1642,9 +1953,9 @@ def_elem:  ColLabel '=' def_arg           { $$ = cat_str(3, $1, make_str("="), $3); }
                ;
 
 /* Note: any simple identifier will be returned as a type name! */
-def_arg:  func_return                          {  $$ = $1; }
-               | qual_all_Op                                   {  $$ = $1; }
-               | AllConst                                      {  $$ = $1; }
+def_arg:  func_type                            {  $$ = $1; }
+               | qual_all_Op                   {  $$ = $1; }
+               | AllConst                      {  $$ = $1; }
                ;
 
 CreateOpClassStmt:      CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename
@@ -1692,7 +2003,7 @@ DropStmt:  DROP drop_type any_name_list opt_drop_behavior
                        { $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
                ;
 
-drop_type:     TABLE           { $$ = make_str("table"); }
+drop_type:     TABLE                   { $$ = make_str("table"); }
                | SEQUENCE              { $$ = make_str("sequence"); }
                | VIEW                  { $$ = make_str("view"); }
                | INDEX                 { $$ = make_str("index"); }
@@ -1708,18 +2019,21 @@ any_name_list:  any_name
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-any_name: ColId
-                       { $$ = $1; }
-               | dotted_name
-                       { $$ = $1; }
-                ;
+any_name: ColId        { $$ = $1; }
+       | ColId attrs  { $$ = cat2_str($1, $2); }
+        ;
+
+attrs: '.' attr_name           { $$ = cat2_str(make_str("."), $2); }
+       | attrs '.' attr_name   { $$ = cat_str(3, $1, make_str("."), $3); }
+       ;
+
 /*****************************************************************************
  *
  *                        QUERY:
- *                                                        truncate table relname
+ *                                truncate table relname1, relname2, ....
  *
  *****************************************************************************/
-TruncateStmt:  TRUNCATE opt_table qualified_name
+TruncateStmt:  TRUNCATE opt_table qualified_name_list
                        { $$ = cat_str(3, make_str("truncate table"), $2, $3); }
                ;
 
@@ -1730,52 +2044,76 @@ TruncateStmt:  TRUNCATE opt_table qualified_name
  *
  *****************************************************************************/
 
-FetchStmt: FETCH fetch_direction from_in name ecpg_into_using
-                       { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); }
-               | FETCH name ecpg_into_using
-                       { $$ = cat2_str(make_str("fetch"), $2); }
+/* This is different from the backend as we try to be compatible with many other
+ * embedded SQL implementations. So we accept their syntax as well and 
+ * translate it to the PGSQL syntax. */
+FetchStmt: FETCH fetch_direction from_in name ecpg_into
+                       {
+                               add_additional_variables($4, false);
+                               $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
+                       }
+               | FETCH fetch_direction name ecpg_into
+                       {
+                               add_additional_variables($3, false);
+                               $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
+                       }
+               | FETCH from_in name ecpg_into
+                       {
+                               add_additional_variables($3, false);
+                               $$ = cat_str(3, make_str("fetch"), $2, $3);
+                       }
+               | FETCH name ecpg_into
+                       {
+                               add_additional_variables($2, false);
+                               $$ = cat2_str(make_str("fetch"), $2);
+                       }
+               | FETCH fetch_direction from_in name
+                       {
+                               add_additional_variables($4, false);
+                               $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
+                       }
+               | FETCH fetch_direction name
+                       {
+                               add_additional_variables($3, false);
+                               $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
+                       }
+               | FETCH from_in name 
+                       {
+                               add_additional_variables($3, false);
+                               $$ = cat_str(3, make_str("fetch"), $2, $3);
+                       }
+               | FETCH name 
+                       {
+                               add_additional_variables($2, false);
+                               $$ = cat2_str(make_str("fetch"), $2);
+                       }
                | MOVE fetch_direction from_in name
                        { $$ = cat_str(4, make_str("move"), $2, $3, $4); }
                | MOVE name
                        { $$ = cat2_str(make_str("move"), $2); }
                ;
 
-fetch_direction: /* EMPTY */                   { $$ = EMPTY; }
-               | NEXT                          { $$ = make_str("next"); }
+fetch_direction:  NEXT                         { $$ = make_str("next"); }
                | PRIOR                         { $$ = make_str("prior"); }
                | FIRST_P                       { $$ = make_str("first"); }
                | LAST_P                        { $$ = make_str("last"); }
-               | ABSOLUTE_P fetch_count        { $$ = cat2_str(make_str("absolute"), $2); }
-               | RELATIVE_P fetch_count        { $$ = cat2_str(make_str("relative"), $2); }
-               | fetch_count                   { $$ = $1; }
+               | ABSOLUTE_P IntConst           { $$ = cat2_str(make_str("absolute"), $2); }
+               | RELATIVE_P IntConst           { $$ = cat2_str(make_str("relative"), $2); }
+               | IntConst                      { $$ = $1; }
                | ALL                           { $$ = make_str("all"); }
                | FORWARD                       { $$ = make_str("forward"); }
-               | FORWARD fetch_count           { $$ = cat2_str(make_str("forward"), $2); }
+               | FORWARD IntConst              { $$ = cat2_str(make_str("forward"), $2); }
                | FORWARD ALL                   { $$ = make_str("forward all"); }
                | BACKWARD                      { $$ = make_str("backward"); }
-               | BACKWARD fetch_count          { $$ = cat2_str(make_str("backward"), $2); }
+               | BACKWARD IntConst             { $$ = cat2_str(make_str("backward"), $2); }
                | BACKWARD ALL                  { $$ = make_str("backward all"); }
                ;
 
-fetch_count: IntConst  { $$ = $1; }
-       ;
-
 from_in: IN_P                          { $$ = make_str("in"); }
-               | FROM                          { $$ = make_str("from"); }
+               | FROM                  { $$ = make_str("from"); }
                ;
 
-/*****************************************************************************
- *
- *     The COMMENT ON statement can take different forms based upon the type of
- *     the object associated with the comment. The form of the statement is:
- *
- *     COMMENT ON [ [ DATABASE | DOMAIN | INDEX |  SEQUENCE | TABLE | TYPE | VIEW ]
- *                              <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
- *                             <funcname> (arg1, arg2, ...) | OPERATOR <op>
- *                             (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
- *                             <relname> | RULE <rulename> ON <relname> ] IS 'text'
- *
- *****************************************************************************/
 CommentStmt:   COMMENT ON comment_type name IS comment_text
                        { $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6); }
                | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text
@@ -1790,6 +2128,14 @@ CommentStmt:   COMMENT ON comment_type name IS comment_text
                        { $$ = cat_str(6, make_str("comment on rule"), $4, make_str("on"), $6, make_str("is"), $8); }
                | COMMENT ON RULE name IS comment_text
                        { $$ = cat_str(4, make_str("comment on rule"), $4, make_str("is"), $6); }
+               | COMMENT ON OPERATOR CLASS any_name USING access_method IS comment_text
+                       { $$ = cat_str(6, make_str("comment on operator class"), $5, make_str("using"), $7, make_str("is"), $9); }
+               | COMMENT ON LARGE_P OBJECT_P NumConst IS comment_text
+                       { $$ = cat_str(4, make_str("comment on large object"), $5, make_str("is"), $7); }
+               | COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text
+                       { $$ = cat_str(6, make_str("comment on cast ("), $5, make_str("as"), $7, make_str(") is"), $10); }
+               | COMMENT ON opt_procedural LANGUAGE any_name IS comment_text
+                       { $$ = cat_str(6, make_str("comment on"), $3, make_str("language"), $5, make_str("is"), $7); }
                ;
 
 comment_type:  COLUMN          { $$ = make_str("column"); }
@@ -1801,6 +2147,7 @@ comment_type:  COLUMN             { $$ = make_str("column"); }
                | DOMAIN_P      { $$ = make_str("domain"); }
                | TYPE_P        { $$ = make_str("type"); }
                | VIEW          { $$ = make_str("view"); }
+               | CONVERSION_P  { $$ = make_str("conversion"); }
                ;
 
 comment_text:  StringConst { $$ = $1; }
@@ -1818,9 +2165,13 @@ GrantStmt:       GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_
                        { $$ = cat_str(7, make_str("grant"), $2, make_str("on"), $4, make_str("to"), $6, $7); }
                ;
 
-RevokeStmt:  REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list opt_drop_behavior
+RevokeStmt:  REVOKE privileges ON privilege_target FROM grantee_list opt_drop_behavior
+                       {
+                         $$ = cat_str(7, make_str("revoke"), $2, make_str("on"), $4, make_str("from"), $6, $7);
+                       }
+               | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_drop_behavior
                        {
-                         $$ = cat_str(9, make_str("revoke"), $2, $3, make_str("on"), $5, make_str("from"), $7, $8);
+                         $$ = cat_str(7, make_str("revoke grant option for"), $5, make_str("on"), $7, make_str("from"), $9, $10);
                        }
                          
                ;
@@ -1837,17 +2188,9 @@ privilege_list:  privilege
                ;
 
 privilege:     SELECT                  { $$ = make_str("select"); }
-               | INSERT                        { $$ = make_str("insert"); }
-               | UPDATE                        { $$ = make_str("update"); }
-               | DELETE_P                      { $$ = make_str("delete"); }
-               | RULE                          { $$ = make_str("rule"); }
                | REFERENCES            { $$ = make_str("references"); }
-               | TRIGGER                       { $$ = make_str("trigger"); }
-               | EXECUTE                       { $$ = make_str("execute"); }
-               | USAGE                         { $$ = make_str("usage"); }
-               | CREATE                        { $$ = make_str("create"); }
-               | TEMPORARY                     { $$ = make_str("temporary"); }
-               | TEMP                          { $$ = make_str("temp"); }
+               | CREATE                { $$ = make_str("create"); }
+               | ColId                 { $$ = $1; }
                ;
 
 privilege_target: qualified_name_list
@@ -1862,6 +2205,8 @@ privilege_target: qualified_name_list
                        { $$ = cat2_str(make_str("language") , $2); }
                | SCHEMA name_list
                        { $$ = cat2_str(make_str("schema") , $2); }
+               | TABLESPACE name_list
+                       { $$ = cat2_str(make_str("tablespace") , $2); }
                ;
 
 grantee_list: grantee
@@ -1870,8 +2215,8 @@ grantee_list: grantee
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-grantee:  ColId                        { $$ = $1; }
-               | GROUP_P ColId         { $$ = cat2_str(make_str("group"), $2); }
+grantee:  RoleId                       { $$ = $1; }
+               | GROUP_P RoleId        { $$ = cat2_str(make_str("group"), $2); }
                ;
 
 opt_grant_grant_option:  WITH GRANT OPTION
@@ -1882,14 +2227,6 @@ opt_grant_grant_option:  WITH GRANT OPTION
                | /*EMPTY*/     { $$ = EMPTY; }
                ;
 
-opt_revoke_grant_option: GRANT OPTION FOR
-               {
-                       mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported REVOKE/GRANT OPTION FOR will be passed to backend");
-                       $$ = make_str("with grant option");
-               }
-               | /*EMPTY*/     { $$ = EMPTY; }
-               ;
-
 function_with_argtypes_list: function_with_argtypes
                        { $$ = $1; }
                | function_with_argtypes_list ',' function_with_argtypes
@@ -1898,18 +2235,42 @@ function_with_argtypes_list: function_with_argtypes
 
 function_with_argtypes: func_name func_args { $$ = cat2_str($1, $2); };
 
+/*****************************************************************************
+ *
+ * GRANT and REVOKE ROLE statements
+ *
+ *****************************************************************************/
+
+GrantRoleStmt:
+       GRANT privilege_list TO name_list opt_grant_admin_option opt_granted_by
+       { $$ = cat_str(6, make_str("grant"), $2, make_str("to"), $4, $5, $6); }
+       ;
+
+RevokeRoleStmt:
+       REVOKE privilege_list FROM name_list opt_granted_by opt_drop_behavior
+       { $$ = cat_str(6, make_str("revoke"), $2, make_str("from"), $4, $5, $6); }
+       ;
+
+opt_grant_admin_option: WITH ADMIN OPTION      { $$ = make_str("with admin option"); }
+               | /*EMPTY*/                     { $$ = EMPTY; }
+               ;
+               
+opt_granted_by: GRANTED BY RoleId       { $$ = cat2_str(make_str("granted by"), $3); }
+               | /*EMPTY*/              { $$ = EMPTY; }
+               ;
+
 /*****************************************************************************
  *
  *             QUERY:
  *                             create index <indexname> on <relname>
  *                               [ using <access> ] "(" ( <col> | using <opclass> ] )+ ")"
- *                               [ where <predicate> ]
+ *                               [ tablespace <tablespacename> ] [ where <predicate> ]
  *
  *****************************************************************************/
 
 IndexStmt:     CREATE index_opt_unique INDEX index_name ON qualified_name
-                               access_method_clause '(' index_params ')' where_clause
-                       { $$ = cat_str(11, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11); }
+                               access_method_clause '(' index_params ')' OptTableSpace where_clause
+                       { $$ = cat_str(12, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11, $12); }
                ;
 
 index_opt_unique:  UNIQUE      { $$ = make_str("unique"); }
@@ -1923,13 +2284,13 @@ access_method_clause:  USING access_method
                ;
 
 index_params:  index_elem                      { $$ = $1; }
-               | index_params ',' index_elem   { $$ = $1; }
+               | index_params ',' index_elem   { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-index_elem:  attr_name opt_class
+index_elem:  ColId opt_class
+               { $$ = cat2_str($1, $2); }
+       | func_expr opt_class
                { $$ = cat2_str($1, $2); }
-       | func_name '(' expr_list ')' opt_class
-               { $$ = cat_str(5, $1, make_str("("), $3, ")", $5); }
        | '(' a_expr ')' opt_class
                { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
        ;
@@ -1942,6 +2303,9 @@ opt_class:        any_name        { $$ = $1; }
 CreateFunctionStmt:    CREATE opt_or_replace FUNCTION func_name func_args
                                        RETURNS func_return createfunc_opt_list opt_definition
                        { $$ = cat_str(8, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, $8); }
+                       | CREATE opt_or_replace FUNCTION func_name func_args
+                                       createfunc_opt_list opt_definition
+                       { $$ = cat_str(6, make_str("create"), $2, make_str("function"), $4, $5, $6, $7); }
                ;
 
 opt_or_replace:  OR REPLACE            { $$ = make_str("or replace"); }
@@ -1960,31 +2324,18 @@ func_args_list:  func_arg
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-func_arg:  opt_arg func_type
-               {
-                       /* We can catch over-specified arguments here if we want to,
-                        * but for now better to silently swallow typmod, etc.
-                        * - thomas 2000-03-22
-                        */
-                       $$ = cat2_str($1, $2);
-               }
-               | func_type             { $$ = $1; }
+func_arg:  arg_class param_name func_type              { $$ = cat_str(3, $1, $2, $3); }
+               | param_name arg_class func_type        { $$ = cat_str(3, $1, $2, $3); }
+               | param_name func_type                  { $$ = cat2_str($1, $2); }
+               | arg_class func_type                   { $$ = cat2_str($1, $2); }
+               | func_type                             { $$ = $1; }
                ;
 
-opt_arg:  IN_P { $$ = make_str("in"); }
-               | OUT_P
-               {
-                       mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/OUT will be passed to backend");
-
-                       $$ = make_str("out");
-               }
-               | INOUT
-               {
-                       mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/INOUT will be passed to backend");
-
-                       $$ = make_str("inout");
-               }
-               ;
+arg_class:  IN_P               { $$ = make_str("in"); }
+               | OUT_P         { $$ = make_str("out"); }
+               | INOUT         { $$ = make_str("inout"); }
+               | IN_P OUT_P    { $$ = make_str("in out"); }
+               ;
 
 func_as: StringConst
                        { $$ = $1; }
@@ -1992,6 +2343,8 @@ func_as: StringConst
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
+param_name:    function_name   { $$ = $1; };
+
 func_return:  func_type
                {
                        /* We can catch over-specified arguments here if we want to,
@@ -2015,22 +2368,19 @@ createfunc_opt_list: createfunc_opt_item
                        { $$ = cat2_str($1, $2); }
                ;
 
-createfunc_opt_item: AS func_as
-                               { $$ = cat2_str(make_str("as"), $2); }
-               | LANGUAGE ColId_or_Sconst
-                               { $$ = cat2_str(make_str("language"), $2); }
+common_func_opt_item:
+               CALLED ON NULL_P INPUT_P
+                               { $$ = make_str("called on null input"); }
+               | RETURNS NULL_P ON NULL_P INPUT_P
+                               { $$ = make_str("returns null on null input"); }
+               | STRICT_P
+                               { $$ = make_str("strict"); }
                | IMMUTABLE
                                { $$ = make_str("immutable"); }
                | STABLE
                                { $$ = make_str("stable"); }
                | VOLATILE
                                { $$ = make_str("volatile"); }
-               | CALLED ON NULL_P INPUT_P
-                               { $$ = make_str("called on null input"); }
-               | RETURNS NULL_P ON NULL_P INPUT_P
-                               { $$ = make_str("returns null on null input"); }
-               | STRICT_P
-                               { $$ = make_str("strict"); }
                | EXTERNAL SECURITY DEFINER
                                { $$ = make_str("external security definer"); }
                | EXTERNAL SECURITY INVOKER
@@ -2040,11 +2390,31 @@ createfunc_opt_item: AS func_as
                | SECURITY INVOKER
                                { $$ = make_str("security invoker"); }
                ;
+createfunc_opt_item: AS func_as
+                               { $$ = cat2_str(make_str("as"), $2); }
+               | LANGUAGE ColId_or_Sconst
+                               { $$ = cat2_str(make_str("language"), $2); }
+               | common_func_opt_item
+                               { $$ = $1; }
+               ;
 
 opt_definition: WITH definition        { $$ = cat2_str(make_str("with"), $2); }
                 | /*EMPTY*/     { $$ = EMPTY; }
                ;
 
+AlterFunctionStmt:
+                        ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict
+                               { $$ = cat_str(4, make_str("alter function"), $3, $4, $5); }
+                               ;
+
+alterfunc_opt_list: common_func_opt_item                       { $$ = $1; }
+               | alterfunc_opt_list common_func_opt_item       { $$ = cat2_str($1, $2);}
+               ;
+
+opt_restrict:  RESTRICT        { $$ = make_str("restrict"); }
+                | /*EMPTY*/     { $$ = EMPTY; }
+               ;
+
 /*****************************************************************************
  *
  *             QUERY:
@@ -2115,6 +2485,8 @@ DropCastStmt: DROP CAST '(' Typename AS Typename ')' opt_drop_behavior
  *****************************************************************************/
 ReindexStmt:  REINDEX reindex_type qualified_name opt_force
                        { $$ = cat_str(4, make_str("reindex"), $2, $3, $4); }
+               | REINDEX SYSTEM_P name opt_force
+                       { $$ = cat_str(3, make_str("reindex system"), $3, $4); }
                | REINDEX DATABASE name opt_force
                        { $$ = cat_str(3, make_str("reindex database"), $3, $4); }
                ;
@@ -2135,18 +2507,87 @@ opt_force: FORCE                        { $$ = make_str("force"); }
  *
  *****************************************************************************/
 
-RenameStmt:  ALTER TABLE relation_expr RENAME opt_column opt_name TO name
+RenameStmt:  ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name
+                       { $$ = cat_str(6, make_str("alter aggregate"), $3, make_str("("), $5, make_str(") rename to"), $9); }
+       | ALTER CONVERSION_P any_name RENAME TO name
+                       { $$ = cat_str(4, make_str("alter conversion"), $3, make_str("rename to"), $6); }
+       | ALTER DATABASE database_name RENAME TO database_name
+                       { $$ = cat_str(4, make_str("alter database"), $3, make_str("rename to"), $6); }
+       | ALTER FUNCTION func_name func_args RENAME TO name
+                       { $$ = cat_str(5, make_str("alter function"), $3, $4, make_str("rename to"), $7); }
+       | ALTER GROUP_P RoleId RENAME TO RoleId
+                       { $$ = cat_str(4, make_str("alter group"), $3, make_str("rename to"), $6); }
+       | ALTER LANGUAGE name RENAME TO name
+                       { $$ = cat_str(4, make_str("alter language"), $3, make_str("rename to"), $6); }
+       | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name
+                       { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("rename to"), $9); }
+       | ALTER SCHEMA name RENAME TO name
+                       { $$ = cat_str(4, make_str("alter schema"), $3, make_str("rename to"), $6); }
+       | ALTER TABLE relation_expr RENAME TO name
+                       { $$ = cat_str(4, make_str("alter table"), $3, make_str("rename to"), $6); }
+       | ALTER INDEX relation_expr RENAME TO name
+                       { $$ = cat_str(4, make_str("alter index"), $3, make_str("rename to"), $6); }
+       | ALTER TABLE relation_expr RENAME opt_column name TO name
                        { $$ = cat_str(7, make_str("alter table"), $3, make_str("rename"), $5, $6, make_str("to"), $8); }
        | ALTER TRIGGER name ON relation_expr RENAME TO name
                        { $$ = cat_str(6, make_str("alter trigger"), $3, make_str("on"), $5, make_str("rename to"), $8); }
+       | ALTER USER RoleId RENAME TO RoleId
+                       { $$ = cat_str(4, make_str("alter user"), $3, make_str("rename to"), $6); }
+       | ALTER TABLESPACE name RENAME TO name
+                       { $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("rename to"), $6); }
                ;
 
-opt_name:  name                                { $$ = $1; }
+opt_column:  COLUMN                    { $$ = make_str("column"); }
                | /*EMPTY*/                     { $$ = EMPTY; }
                ;
 
-opt_column:  COLUMN                    { $$ = make_str("column"); }
-               | /*EMPTY*/                     { $$ = EMPTY; }
+/*****************************************************************************
+ *
+ * ALTER THING name SET SCHEMA name
+ *
+ *****************************************************************************/
+
+AlterObjectSchemaStmt:
+               ALTER AGGREGATE func_name '(' aggr_argtype ')' SET SCHEMA name
+                       { $$ = cat_str(6, make_str("alter aggregate"), $3, make_str("("), $5, make_str(") set schema"), $9); }
+               | ALTER DOMAIN_P any_name SET SCHEMA name
+                       { $$ = cat_str(4, make_str("alter domain"), $3, make_str("set schema"), $6); }
+               | ALTER FUNCTION func_name func_args SET SCHEMA name
+                       { $$ = cat_str(5, make_str("alter function"), $3, $4, make_str("set schema"), $7); }
+               | ALTER SEQUENCE relation_expr SET SCHEMA name
+                       { $$ = cat_str(4, make_str("alter sequence"), $3, make_str("set schema"), $6); }
+               | ALTER TABLE relation_expr SET SCHEMA name
+                       { $$ = cat_str(4, make_str("alter sequence"), $3, make_str("set schema"), $6); }
+               | ALTER TYPE_P any_name SET SCHEMA name
+                       { $$ = cat_str(4, make_str("alter type"), $3, make_str("set schema"), $6); }
+               ;
+                           
+/*****************************************************************************
+ *
+ * ALTER THING name OWNER TO newname
+ *
+ *****************************************************************************/
+
+AlterOwnerStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO RoleId
+                       { $$ = cat_str(6, make_str("alter aggregate"), $3, make_str("("), $5, make_str(") owner to"), $9); }
+               | ALTER CONVERSION_P any_name OWNER TO RoleId
+                       { $$ = cat_str(4, make_str("alter conversion"), $3, make_str("owner to"), $6); }
+               | ALTER DATABASE database_name OWNER TO RoleId
+                       { $$ = cat_str(4, make_str("alter database"), $3, make_str("owner to"), $6); }
+               | ALTER DOMAIN_P database_name OWNER TO RoleId
+                       { $$ = cat_str(4, make_str("alter domain"), $3, make_str("owner to"), $6); }
+               | ALTER FUNCTION func_name func_args OWNER TO RoleId
+                       { $$ = cat_str(5, make_str("alter function"), $3, $4, make_str("owner to"), $7); }
+               | ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO RoleId
+                       { $$ = cat_str(6, make_str("alter operator"), $3, make_str("("), $5, make_str(") owner to"), $9); }
+               | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId
+                       { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("owner to"), $9); }
+               | ALTER SCHEMA name OWNER TO RoleId
+                       { $$ = cat_str(4, make_str("alter schema"), $3, make_str("owner to"), $6); }
+               | ALTER TYPE_P any_name OWNER TO RoleId
+                       { $$ = cat_str(4, make_str("alter type"), $3, make_str("owner to"), $6); }
+               | ALTER TABLESPACE name OWNER TO RoleId
+                       { $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("owner to"), $6); }
                ;
 
 
@@ -2197,6 +2638,7 @@ event:    SELECT                          { $$ = make_str("select"); }
                 ;
 
 opt_instead:  INSTEAD          { $$ = make_str("instead"); }
+               | ALSO          { $$ = make_str("also"); }
                | /*EMPTY*/                     { $$ = EMPTY; }
                ;
 
@@ -2235,12 +2677,20 @@ UnlistenStmt:  UNLISTEN qualified_name
  *             (also older versions END / ABORT)
  *
  *****************************************************************************/
-TransactionStmt:  ABORT_P opt_transaction              { $$ = make_str("rollback"); }
-               | BEGIN_P opt_transaction               { $$ = make_str("begin transaction"); }
-               | START TRANSACTION transaction_mode_list_or_empty      { $$ = cat2_str(make_str("start transaction"), $3); }
-               | COMMIT opt_transaction                { $$ = make_str("commit"); }
-               | END_P opt_transaction         { $$ = make_str("commit"); }
-               | ROLLBACK opt_transaction              { $$ = make_str("rollback"); }
+TransactionStmt:  ABORT_P opt_transaction                               { $$ = make_str("rollback"); }
+               | BEGIN_P opt_transaction transaction_mode_list_or_empty { $$ = cat2_str(make_str("begin transaction"), $3); }
+               | START TRANSACTION transaction_mode_list_or_empty       { $$ = cat2_str(make_str("start transaction"), $3); }
+               | COMMIT opt_transaction                                 { $$ = make_str("commit"); }
+               | END_P opt_transaction                                  { $$ = make_str("commit"); }
+               | ROLLBACK opt_transaction                               { $$ = make_str("rollback"); }
+               | SAVEPOINT ColId                                        { $$ = cat2_str(make_str("savepoint"), $2); }
+               | RELEASE SAVEPOINT ColId                                { $$ = cat2_str(make_str("release savepoint"), $3); }
+               | RELEASE ColId                                          { $$ = cat2_str(make_str("release"), $2); }
+               | ROLLBACK opt_transaction TO SAVEPOINT ColId            { $$ = cat_str(4, make_str("rollback"), $2, make_str("to savepoint"), $5); }
+               | ROLLBACK opt_transaction TO ColId                      { $$ = cat_str(4, make_str("rollback"), $2, make_str("to"), $4); }
+               | PREPARE TRANSACTION StringConst                        { $$ = cat2_str(make_str("prepare transaction"), $3); }
+               | COMMIT PREPARED StringConst                            { $$ = cat2_str(make_str("commit prepared"), $3); }
+               | ROLLBACK PREPARED StringConst                          { $$ = cat2_str(make_str("rollback prepared"), $3); }
                ;
 
 opt_transaction: WORK                  { $$ = EMPTY; }
@@ -2248,15 +2698,17 @@ opt_transaction: WORK                   { $$ = EMPTY; }
                | /*EMPTY*/             { $$ = EMPTY; }
                ;
 
-transaction_mode_list:
+transaction_mode_item:
        ISOLATION LEVEL iso_level
        { $$ = cat2_str(make_str("isolation level"), $3); }
-       | transaction_access_mode
-       { $$ = $1; }
-       | ISOLATION LEVEL iso_level transaction_access_mode
-       { $$ = cat_str(3, make_str("isolation level"), $3, $4); }
-       | transaction_access_mode ISOLATION LEVEL iso_level
-       { $$ = cat_str(3, $1, make_str("isolation level"), $4); }
+       | READ ONLY     { $$ = make_str("read only"); }
+       | READ WRITE    { $$ = make_str("read write"); }
+       ;
+       
+transaction_mode_list:
+       transaction_mode_item                                   { $$ = $1; }
+       | transaction_mode_list ',' transaction_mode_item       { $$ = cat_str(3, $1, make_str(","), $3); }
+       | transaction_mode_list transaction_mode_item           { $$ = cat_str(3, $1, make_str(" "), $2); }
        ;
         
 transaction_mode_list_or_empty:
@@ -2264,20 +2716,17 @@ transaction_mode_list_or_empty:
        | /* EMPTY */           { $$ = EMPTY; }
        ;
 
-transaction_access_mode:
-       READ ONLY       { $$ = make_str("read only"); }
-       | READ WRITE    { $$ = make_str("read write"); }
-       ;
-       
 /*****************************************************************************
  *
- *             QUERY:
- *                             define view <viewname> '('target-list ')' [where <quals> ]
+ *     QUERY:
+ *             CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')' AS <query>
  *
  *****************************************************************************/
 
-ViewStmt:  CREATE opt_or_replace VIEW qualified_name opt_column_list AS SelectStmt
+ViewStmt:  CREATE OptTemp VIEW qualified_name opt_column_list AS SelectStmt
                        { $$ = cat_str(7, make_str("create"), $2, make_str("view"), $4, $5, make_str("as"), $7); }
+               | CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list AS SelectStmt
+                       { $$ = cat_str(7, make_str("create or replace"), $4, make_str("view"), $6, $7, make_str("as"), $9); }
                ;
 
 
@@ -2312,7 +2761,11 @@ createdb_opt_list:       createdb_opt_item
                        { $$ = cat2_str($1, $2); }
                ;
 
-createdb_opt_item:     LOCATION opt_equal StringConst
+createdb_opt_item:     TABLESPACE opt_equal name
+                       { $$ = cat_str(3,make_str("tablespace"), $2, $3); }
+               | TABLESPACE opt_equal DEFAULT
+                       { $$ = cat_str(3, make_str("tablespace"), $2, make_str("default")); }
+               | LOCATION opt_equal StringConst
                        { $$ = cat_str(3,make_str("location"), $2, $3); }
                | LOCATION opt_equal DEFAULT
                        { $$ = cat_str(3, make_str("location"), $2, make_str("default")); }
@@ -2324,6 +2777,8 @@ createdb_opt_item:        LOCATION opt_equal StringConst
                        { $$ = cat_str(3, make_str("encoding"), $2, $3); }
                | ENCODING opt_equal DEFAULT
                        { $$ = cat_str(3, make_str("encoding"), $2, make_str("default")); }
+               | CONNECTION LIMIT opt_equal PosIntConst
+                       { $$ = cat_str(3, make_str("connection limit"), $3, $4); }
                | OWNER opt_equal name
                        { $$ = cat_str(3, make_str("owner"), $2, $3); }
                | OWNER opt_equal DEFAULT
@@ -2342,12 +2797,25 @@ opt_equal: '='                                  { $$ = make_str("="); }
  *
  *****************************************************************************/
 
+AlterDatabaseStmt: ALTER DATABASE database_name opt_with alterdb_opt_list
+                       { $$ = cat_str(4, make_str("alter database"), $3, $4, $5); }
+               ;
+               
 AlterDatabaseSetStmt: ALTER DATABASE database_name SET set_rest
                        { $$ = cat_str(4, make_str("alter database"), $3, make_str("set"), $5); }
                | ALTER DATABASE database_name VariableResetStmt
                        { $$ = cat_str(3, make_str("alter database"), $3, $4); }
                ;
 
+alterdb_opt_list:
+               alterdb_opt_list alterdb_opt_item       { $$ = cat2_str($1, $2);}
+               | /* EMPTY */                           { $$ = EMPTY; }
+               ;
+
+alterdb_opt_item:
+                CONNECTION LIMIT opt_equal PosIntConst { $$ = cat_str(3, make_str("connection limit"), $3, $4); }
+               ;
+                                                                                       
 /*****************************************************************************
  *
  *             DROP DATABASE
@@ -2366,9 +2834,9 @@ DropdbStmt: DROP DATABASE database_name
  *
  *****************************************************************************/
 
-CreateDomainStmt:  CREATE DOMAIN_P any_name opt_as Typename ColQualList opt_collate
+CreateDomainStmt:  CREATE DOMAIN_P any_name opt_as Typename ColQualList
                        {
-                               $$ = cat_str(6, make_str("create domain"), $3, $4, $5, $6, $7);
+                               $$ = cat_str(5, make_str("create domain"), $3, $4, $5, $6);
                        }
                ;
 
@@ -2379,12 +2847,10 @@ AlterDomainStmt:
                { $$ = cat_str(3, make_str("alter domain"), $3, make_str("drop not null")); }
        | ALTER DOMAIN_P any_name SET NOT NULL_P
                { $$ = cat_str(3, make_str("alter domain"), $3, make_str("set not null")); }
-       | ALTER DOMAIN_P any_name ADD TableConstraint
+       | ALTER DOMAIN_P any_name ADD_P TableConstraint
                { $$ = cat_str(4, make_str("alter domain"), $3, make_str("add"), $5); }
        | ALTER DOMAIN_P any_name DROP CONSTRAINT name opt_drop_behavior
                { $$ = cat_str(5, make_str("alter domain"), $3, make_str("drop constraint"), $6, $7); }
-       | ALTER DOMAIN_P any_name OWNER TO UserId
-               { $$ = cat_str(4, make_str("alter domain"), $3, make_str("owner to"), $6); }
        ;
        
 opt_as:        AS      {$$ = make_str("as"); }
@@ -2507,8 +2973,11 @@ prep_type_list: Typename         { $$ = $1; }
        | prep_type_list ',' Typename   { $$ = cat_str(3, $1, make_str(","), $3); }
        ;
 
-ExecuteStmt: EXECUTE name execute_param_clause into_clause
-               { $$ = cat_str(4, make_str("execute"), $2, $3, $4); }
+ExecuteStmt: EXECUTE name execute_param_clause
+               { $$ = cat_str(3, make_str("execute"), $2, $3); }
+               | CREATE OptTemp TABLE qualified_name OptCreateAs AS EXECUTE name execute_param_clause
+               { $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, $5, make_str("as execute"), $8, $9); }
+               
                ;
 
 execute_param_clause: '(' expr_list ')'        { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
@@ -2561,12 +3030,16 @@ insert_column_item:  ColId opt_indirection
  *
  *****************************************************************************/
 
-DeleteStmt:  DELETE_P FROM relation_expr where_clause
-                       { $$ = cat_str(3, make_str("delete from"), $3, $4); }
+DeleteStmt:  DELETE_P FROM relation_expr using_clause where_clause
+                       { $$ = cat_str(4, make_str("delete from"), $3, $4, $5); }
+               ;
+
+using_clause: USING from_list  { cat2_str(make_str("using"), $2); }
+                       | /* EMPTY */           { $$ = EMPTY; }
                ;
 
-LockStmt:  LOCK_P opt_table qualified_name_list opt_lock
-                       { $$ = cat_str(4, make_str("lock"), $2, $3, $4); }
+LockStmt:  LOCK_P opt_table qualified_name_list opt_lock opt_nowait
+                       { $$ = cat_str(5, make_str("lock"), $2, $3, $4, $5); }
                ;
 
 opt_lock:  IN_P lock_type MODE
@@ -2585,6 +3058,10 @@ lock_type:       ACCESS SHARE            { $$ = make_str("access share"); }
                | ACCESS EXCLUSIVE              { $$ = make_str("access exclusive"); }
                ;
 
+opt_nowait:    NOWAIT                   { $$ = make_str("nowait"); }
+               | /* EMPTY */           { $$ = EMPTY; }
+               ;
+
 /*****************************************************************************
  *
  *             QUERY:
@@ -2613,11 +3090,8 @@ DeclareCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
                        for (ptr = cur; ptr != NULL; ptr = ptr->next)
                        {
                                if (strcmp($2, ptr->name) == 0)
-                               {
-                                               /* re-definition is a bug */
-                                       snprintf(errortext, sizeof(errortext), "cursor %s already defined", $2);
-                                       mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                               }
+                                       /* re-definition is a bug */
+                                       mmerror(PARSE_ERROR, ET_ERROR, "cursor %s already defined", $2);
                        }
 
                        this = (struct cursor *) mm_alloc(sizeof(struct cursor));
@@ -2626,14 +3100,17 @@ DeclareCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
                        this->next = cur;
                        this->name = $2;
                        this->connection = connection;
+                       this->opened = false;
                        this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
                        this->argsinsert = argsinsert;
                        this->argsresult = argsresult;
                        argsinsert = argsresult = NULL;
-
                        cur = this;
 
-                       $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
+                       if (INFORMIX_MODE)
+                               $$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), mm_strdup(this->command), make_str("*/"));
+                       else
+                               $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
                }
                ;
 
@@ -2644,7 +3121,10 @@ cursor_options:  /* EMPTY */             { $$ = EMPTY; }
        | cursor_options NO SCROLL      { $$ = cat2_str($1, make_str("no scroll")); }
        ;
 
-opt_hold:      /* EMPTY */             { $$ = EMPTY; }
+opt_hold:      /* EMPTY */             { if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
+                                               $$ = make_str("with hold");
+                                         else
+                                                $$ = EMPTY; }
        | WITH HOLD                     { $$ = make_str("with hold"); }
        | WITHOUT HOLD                  { $$ = make_str("without hold"); }
        ;
@@ -2672,9 +3152,9 @@ select_no_parens:    simple_select
                        { $$ = $1; }
                | select_clause sort_clause
                        { $$ = cat2_str($1, $2); }
-               | select_clause opt_sort_clause for_update_clause opt_select_limit
+               | select_clause opt_sort_clause for_locking_clause opt_select_limit
                        { $$ = cat_str(4, $1, $2, $3, $4); }
-               | select_clause opt_sort_clause select_limit opt_for_update_clause
+               | select_clause opt_sort_clause select_limit opt_for_locking_clause
                        { $$ = cat_str(4, $1, $2, $3, $4); }
                ;
 
@@ -2699,7 +3179,7 @@ into_clause:  INTO OptTempTableName
                        FoundInto = 1;
                        $$= cat2_str(make_str("into"), $2);
                }
-               | ecpg_into_using               { $$ = EMPTY; }
+               | ecpg_into                     { $$ = EMPTY; }
                | /*EMPTY*/                     { $$ = EMPTY; }
                ;
 
@@ -2758,14 +3238,14 @@ sortby_list:  sortby                                    { $$ = $1; }
                | sortby_list ',' sortby                { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-sortby: a_expr OptUseOp
-                       { $$ = cat2_str($1, $2); }
-               ;
-
-OptUseOp:  USING all_Op                { $$ = cat2_str(make_str("using"), $2); }
-               | ASC                           { $$ = make_str("asc"); }
-               | DESC                          { $$ = make_str("desc"); }
-               | /*EMPTY*/                     { $$ = EMPTY; }
+sortby: a_expr USING qual_all_Op
+                       { $$ = cat_str(3, $1, make_str("using"), $3); }
+               | a_expr ASC
+                       { $$ = cat2_str($1, make_str("asc")); }
+               | a_expr DESC
+                       { $$ = cat2_str($1, make_str("desc")); }
+               | a_expr
+                       { $$ = $1; }
                ;
 
 select_limit:  LIMIT select_limit_value OFFSET select_offset_value
@@ -2784,23 +3264,11 @@ opt_select_limit:       select_limit    { $$ = $1; }
                | /*EMPTY*/                                     { $$ = EMPTY; }
                ;
 
-select_limit_value: PosIntConst
-               {
-                       if (atoi($1) < 0)
-                               mmerror(PARSE_ERROR, ET_ERROR, "LIMIT must not be negative");
-                       $$ = $1;
-               }
-               | ALL   { $$ = make_str("all"); }
-               | PARAM { $$ = make_name(); }
+select_limit_value: a_expr     { $$ = $1; }
+               | ALL           { $$ = make_str("all"); }
                ;
 
-select_offset_value:   PosIntConst
-               {
-                       if (atoi($1) < 0)
-                               mmerror(PARSE_ERROR, ET_ERROR, "OFFSET must not be negative");
-                       $$ = $1;
-               }
-               | PARAM { $$ = make_name(); }
+select_offset_value: a_expr { $$ = $1; }       
                ;
 
 /*
@@ -2822,17 +3290,20 @@ having_clause:  HAVING a_expr
                        { $$ = EMPTY; }
                ;
 
-for_update_clause:     FOR UPDATE update_list
-                       { $$ = make_str("for update"); }
+for_locking_clause:    FOR UPDATE locked_rels_list opt_nowait
+                       { $$ = cat_str(3, make_str("for update"), $3, $4); }
+               | FOR SHARE locked_rels_list opt_nowait
+                       { $$ = cat_str(3, make_str("for share"), $3, $4); }
                | FOR READ ONLY
                        { $$ = make_str("for read only"); }
                ;
 
-opt_for_update_clause: for_update_clause       { $$ = $1; }
-               | /* EMPTY */                                           { $$ = EMPTY; }
+opt_for_locking_clause: for_locking_clause     { $$ = $1; }
+               | /* EMPTY */                   { $$ = EMPTY; }
                ;
 
-update_list:  OF name_list             { $$ = cat2_str(make_str("of"), $2); }
+locked_rels_list:
+                OF name_list           { $$ = cat2_str(make_str("of"), $2); }
                | /* EMPTY */                   { $$ = EMPTY; }
                ;
 
@@ -2870,7 +3341,7 @@ table_ref:        relation_expr
                | func_table AS '(' TableFuncElementList ')'
                        { $$=cat_str(4, $1, make_str("as ("), $4, make_str(")")); }
                | func_table AS ColId '(' TableFuncElementList ')'
-                       { $$=cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")")); }
+                       { $$=cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")"));}
                | func_table ColId '(' TableFuncElementList ')'
                        { $$=cat_str(5, $1, $2, make_str("("), $4, make_str(")")); }
                | select_with_parens
@@ -2960,10 +3431,7 @@ relation_expr:   qualified_name
                        { /* inheritance query */ $$ = cat_str(3, make_str("only ("), $3, make_str(")")); }
                ;
 
-func_table:  func_name '(' ')'
-               { $$ = cat2_str($1, make_str("()")); }
-       | func_name '(' expr_list ')'
-               { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
+func_table:  func_expr         { $$ = $1; }
        ;
 
 where_clause:  WHERE a_expr            { $$ = cat2_str(make_str("where"), $2); }
@@ -2973,7 +3441,7 @@ where_clause:  WHERE a_expr               { $$ = cat2_str(make_str("where"), $2); }
 TableFuncElementList: TableFuncElement
                         { $$ = $1; }
                | TableFuncElementList ',' TableFuncElement
-                       { $$ = cat_str(3, $1, ',', $3); }
+                       { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
 TableFuncElement:      ColId Typename  { $$ = cat2_str($1, $2); }
@@ -3173,12 +3641,6 @@ opt_charset:  CHARACTER SET ColId
                        { $$ = EMPTY; }
                ;
 
-opt_collate:  COLLATE ColId
-                       { $$ = cat2_str(make_str("collate"), $2); }
-               | /*EMPTY*/
-                       { $$ = EMPTY; }
-               ;
-
 ConstDatetime: TIMESTAMP '(' PosIntConst ')' opt_timezone
                        { $$ = cat_str(4, make_str("timestamp("), $3, make_str(")"), $5); }
                | TIMESTAMP opt_timezone
@@ -3223,73 +3685,7 @@ opt_interval:  YEAR_P                    { $$ = make_str("year"); }
  *     expression grammar
  *
  *****************************************************************************/
-
-/* Expressions using row descriptors
- * Define row_descriptor to allow yacc to break the reduce/reduce conflict
- *     with singleton expressions.
- */
-r_expr: row IN_P select_with_parens
-                       { $$ = cat_str(3, $1, make_str("in"), $3); }
-               | row NOT IN_P select_with_parens
-                       { $$ = cat_str(3, $1, make_str("not in"), $4); }
-               | row qual_all_Op sub_type select_with_parens %prec Op
-                       { $$ = cat_str(4, $1, $2, $3, $4); }
-               | row qual_all_Op select_with_parens %prec Op
-                       { $$ = cat_str(3, $1, $2, $3); }
-               | row qual_all_Op row %prec Op
-                       { $$ = cat_str(3, $1, $2, $3); }
-               | row IS NULL_P
-                       { $$ = cat2_str($1, make_str("is null")); }
-               | row IS NOT NULL_P
-                       { $$ = cat2_str($1, make_str("is not null")); }
-               | row OVERLAPS row
-                       { $$ = cat_str(3, $1, make_str("overlaps"), $3); }
-               | row IS DISTINCT FROM row %prec IS
-                       { $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
-               ;
-
-row: ROW '(' row_descriptor ')'
-               { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
-       | ROW '(' a_expr ')'
-               { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
-       | ROW '(' ')'
-               { $$ = make_str("row()"); }
-       | '(' row_descriptor ')'
-                { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
-       ;
-
-row_descriptor:  expr_list ',' a_expr
-                       { $$ = cat_str(3, $1, make_str(","), $3); }
-               ;
-
-sub_type:  ANY                                 { $$ = make_str("ANY"); }
-               | SOME                                  { $$ = make_str("SOME"); }
-               | ALL                                   { $$ = make_str("ALL"); }
-                         ;
-
-all_Op:  Op                            { $$ = $1; }
-       | MathOp                        { $$ = $1; }
-       ;
-
-MathOp: '+'                            { $$ = make_str("+"); }
-               | '-'                   { $$ = make_str("-"); }
-               | '*'                   { $$ = make_str("*"); }
-               | '%'                   { $$ = make_str("%"); }
-               | '^'                   { $$ = make_str("^"); }
-               | '/'                   { $$ = make_str("/"); }
-               | '<'                   { $$ = make_str("<"); }
-               | '>'                   { $$ = make_str(">"); }
-               | '='                   { $$ = make_str("="); }
-               ;
-
-qual_Op:  Op                           { $$ = $1; }
-               | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
-               ;
-
-qual_all_Op:  all_Op                           { $$ = $1; }
-               | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
-               ;
-
+               
 /* General expressions
  * This is the heart of the expression syntax.
  *
@@ -3310,7 +3706,7 @@ a_expr:  c_expr
                        { $$ = $1; }
                | a_expr TYPECAST Typename
                        { $$ = cat_str(3, $1, make_str("::"), $3); }
-               | a_expr AT TIME ZONE c_expr
+               | a_expr AT TIME ZONE a_expr
                        { $$ = cat_str(3, $1, make_str("at time zone"), $5); }
                /*
                 * These operators must be called out explicitly in order to make use
@@ -3325,14 +3721,6 @@ a_expr:  c_expr
                        { $$ = cat2_str(make_str("+"), $2); }
                | '-' a_expr %prec UMINUS
                        { $$ = cat2_str(make_str("-"), $2); }
-               | '%' a_expr
-                       { $$ = cat2_str(make_str("%"), $2); }
-               | '^' a_expr
-                       { $$ = cat2_str(make_str("^"), $2); }
-               | a_expr '%'
-                       { $$ = cat2_str($1, make_str("%")); }
-               | a_expr '^'
-                       { $$ = cat2_str($1, make_str("^")); }
                | a_expr '+' a_expr
                        { $$ = cat_str(3, $1, make_str("+"), $3); }
                | a_expr '-' a_expr
@@ -3422,20 +3810,24 @@ a_expr:  c_expr
                        { $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
                | a_expr IS NOT OF '(' type_list ')' %prec IS
                        { $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
-               | a_expr BETWEEN b_expr AND b_expr      %prec BETWEEN
-                       { $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5); }
-               | a_expr NOT BETWEEN b_expr AND b_expr  %prec BETWEEN
-                       { $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6); }
+               | a_expr BETWEEN opt_asymmetric b_expr AND b_expr       %prec BETWEEN
+                       { $$ = cat_str(6, $1, make_str("between"), $3, $4, make_str("and"), $6); }
+               | a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr   %prec BETWEEN
+                       { $$ = cat_str(6, $1, make_str("not between"), $4, $5, make_str("and"), $7); }
+               | a_expr BETWEEN SYMMETRIC b_expr AND b_expr    %prec BETWEEN
+                       { $$ = cat_str(5, $1, make_str("between symmetric"), $4, make_str("and"), $6); }
+               | a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr        %prec BETWEEN
+                       { $$ = cat_str(5, $1, make_str("not between symmetric"), $5, make_str("and"), $7); }
                | a_expr IN_P in_expr
                        { $$ = cat_str(3, $1, make_str("in"), $3); }
                | a_expr NOT IN_P in_expr
                        { $$ = cat_str(3, $1, make_str("not in"), $4); }
-               | a_expr qual_all_Op sub_type select_with_parens %prec Op
+               | a_expr subquery_Op sub_type select_with_parens %prec Op
                        { $$ = cat_str(4, $1, $2, $3, $4); }
+               | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
+                       { $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")")); }
                | UNIQUE select_with_parens %prec Op
                        { $$ = cat2_str(make_str("unique"), $2); }
-               | r_expr
-                       { $$ = $1; }
                ;
 
 /* Restricted expressions
@@ -3452,14 +3844,6 @@ b_expr:  c_expr
                        { $$ = cat_str(3, $1, make_str("::"), $3); }
                | '-' b_expr %prec UMINUS
                        { $$ = cat2_str(make_str("-"), $2); }
-               | '%' b_expr
-                       { $$ = cat2_str(make_str("%"), $2); }
-               | '^' b_expr
-                       { $$ = cat2_str(make_str("^"), $2); }
-               | b_expr '%'
-                       { $$ = cat2_str($1, make_str("%")); }
-               | b_expr '^'
-                       { $$ = cat2_str($1, make_str("^")); }
                | b_expr '+' b_expr
                        { $$ = cat_str(3, $1, make_str("+"), $3); }
                | b_expr '-' b_expr
@@ -3504,15 +3888,35 @@ c_expr: columnref
                        { $$ = $1;      }
                | AexprConst
                        { $$ = $1;      }
-               | PARAM attrs opt_indirection
-                       { $$ = cat_str(3, make_str("param"), $2, $3); }
-               | '(' a_expr ')' attrs opt_indirection
-                       { $$ = cat_str(5, make_str("("), $2, make_str(")"), $4, $5); }
+               | PARAM opt_indirection
+                       { $$ = cat2_str(make_str("param"), $2); }
                | '(' a_expr ')' opt_indirection
                        { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
                | case_expr
                        { $$ = $1; }
-               | func_name '(' ')'
+               | func_expr
+                       { $$ = $1; }
+               | select_with_parens    %prec UMINUS
+                       { $$ = $1; }
+               | EXISTS select_with_parens
+                       { $$ = cat2_str(make_str("exists"), $2); }
+               | ARRAY select_with_parens
+                       { $$ = cat2_str(make_str("array"), $2); }
+               | ARRAY array_expr
+                       { $$ = cat2_str(make_str("array"), $2); }
+               | row
+                       { $$ = $1; }
+               ;
+
+/*
+ * func_expr is split out from c_expr just so that we have a classification
+ * for "everything that is a function call or looks like one".  This isn't
+ * very important, but it saves us having to document which variants are
+ * legal in the backwards-compatible functional-index syntax for CREATE INDEX.
+ * (Note that many of the special SQL functions wouldn't actually make any
+ * sense as functional index entries, but we ignore that consideration here.)
+ */
+func_expr:      func_name '(' ')'
                        { $$ = cat2_str($1, make_str("()"));    }
                | func_name '(' expr_list ')'
                        { $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));        }
@@ -3524,20 +3928,30 @@ c_expr: columnref
                        { $$ = cat2_str($1, make_str("(*)")); }
                | CURRENT_DATE
                        { $$ = make_str("current_date"); }
-               | CURRENT_TIME opt_empty_parentheses
-                       { $$ = cat2_str(make_str("current_time"), $2); }
-               | CURRENT_TIME '(' PosIntConst ')'
+               | CURRENT_TIME 
                        { $$ = make_str("current_time"); }
-               | CURRENT_TIMESTAMP opt_empty_parentheses
-                       { $$ = cat2_str(make_str("current_timestamp"), $2); }
-               | CURRENT_TIMESTAMP '(' PosIntConst ')'
+               | CURRENT_TIME '(' PosIntConst ')'
+                       { $$ = cat_str(3, make_str("current_time ("), $3, make_str(")")); }
+               | CURRENT_TIMESTAMP 
                        { $$ = make_str("current_timestamp"); }
-               | CURRENT_USER opt_empty_parentheses
-                       { $$ = cat2_str(make_str("current_user"), $2); }
-               | SESSION_USER opt_empty_parentheses
-                       { $$ = cat2_str(make_str("session_user"), $2); }
-               | USER opt_empty_parentheses
-                       { $$ = cat2_str(make_str("user"), $2); }
+               | CURRENT_TIMESTAMP '(' PosIntConst ')'
+                       { $$ = cat_str(3, make_str("current_timestamp ("), $3, make_str(")")); }
+               | LOCALTIME 
+                       { $$ = make_str("localtime"); }
+               | LOCALTIME '(' PosIntConst ')'
+                       { $$ = cat_str(3, make_str("localtime ("), $3, make_str(")")); }
+               | LOCALTIMESTAMP 
+                       { $$ = make_str("local_timestamp"); }
+               | LOCALTIMESTAMP '(' PosIntConst ')'
+                       { $$ = cat_str(3, make_str("locale_timestamp ("), $3, make_str(")")); }
+               | CURRENT_ROLE
+                       { $$ = make_str("current_role"); }
+               | CURRENT_USER
+                       { $$ = make_str("current_user"); }
+               | SESSION_USER 
+                       { $$ = make_str("session_user"); }
+               | USER 
+                       { $$ = make_str("user"); }
                | CAST '(' a_expr AS Typename ')'
                        { $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); }
                | EXTRACT '(' extract_list ')'
@@ -3563,25 +3977,59 @@ c_expr: columnref
                        { $$ = cat_str(5, make_str("convert("), $3, make_str("using"), $5, make_str(")"));}
                | CONVERT '(' expr_list ')'
                        { $$ = cat_str(3, make_str("convert("), $3, make_str(")")); }
-               | select_with_parens    %prec UMINUS
-                       { $$ = $1; }
-               | EXISTS select_with_parens
-                       { $$ = cat2_str(make_str("exists"), $2); }
-               | ARRAY select_with_parens
-                       { $$ = cat2_str(make_str("array"), $2); }
-               | ARRAY array_expr
-                       { $$ = cat2_str(make_str("array"), $2); }
+               | NULLIF '(' a_expr ',' a_expr ')'
+                        { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); }
+               | COALESCE '(' expr_list ')'
+                       { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); }
+               | GREATEST '(' expr_list ')'
+                       { $$ = cat_str(3, make_str("greatest("), $3, make_str(")")); }
+               | LEAST '(' expr_list ')'
+                       { $$ = cat_str(3, make_str("least("), $3, make_str(")")); }
                ;
-/*
- * This used to use ecpg_expr, but since there is no shift/reduce conflict
- * anymore, we can remove ecpg_expr. - MM
- */
-opt_indirection:  '[' a_expr ']' opt_indirection
-                       { $$ = cat_str(4, make_str("["), $2, make_str("]"), $4); }
-               | '[' a_expr ':' a_expr ']' opt_indirection
-                       { $$ = cat_str(6, make_str("["), $2, make_str(":"), $4, make_str("]"), $6); }
-               | /* EMPTY */
-                       { $$ = EMPTY; }
+
+
+row: ROW '(' expr_list ')'
+               { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
+       | ROW '(' ')'
+               { $$ = make_str("row()"); }
+       | '(' expr_list ',' a_expr ')'
+                { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
+       ;
+
+sub_type:  ANY         { $$ = make_str("ANY"); }
+       | SOME          { $$ = make_str("SOME"); }
+       | ALL           { $$ = make_str("ALL"); }
+       ;
+
+all_Op:  Op                            { $$ = $1; }
+       | MathOp                        { $$ = $1; }
+       ;
+
+MathOp: '+'                            { $$ = make_str("+"); }
+               | '-'                   { $$ = make_str("-"); }
+               | '*'                   { $$ = make_str("*"); }
+               | '%'                   { $$ = make_str("%"); }
+               | '^'                   { $$ = make_str("^"); }
+               | '/'                   { $$ = make_str("/"); }
+               | '<'                   { $$ = make_str("<"); }
+               | '>'                   { $$ = make_str(">"); }
+               | '='                   { $$ = make_str("="); }
+               ;
+
+qual_Op:  Op                           { $$ = $1; }
+               | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
+               ;
+
+qual_all_Op:  all_Op                           { $$ = $1; }
+               | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
+               ;
+
+subquery_Op:  all_Op                           { $$ = $1; }
+               | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
+               | LIKE                          { $$ = make_str("like"); }
+               | NOT LIKE                      { $$ = make_str("not like"); }
+               | ILIKE                         { $$ = make_str("ilike"); }
+               | NOT ILIKE                     { $$ = make_str("not ilike"); }
                ;
 
 expr_list:     a_expr
@@ -3680,25 +4128,9 @@ in_expr:  select_with_parens
 
 /* Case clause
  * Define SQL92-style case clause.
- * Allow all four forms described in the standard:
- * - Full specification
- *     CASE WHEN a = b THEN c ... ELSE d END
- * - Implicit argument
- *     CASE a WHEN b THEN c ... ELSE d END
- * - Conditional NULL
- *     NULLIF(x,y)
- *     same as CASE WHEN x = y THEN NULL ELSE x END
- * - Conditional substitution from list, use first non-null argument
- *     COALESCE(a,b,...)
- * same as CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ... END
- * - thomas 1998-11-09
  */
 case_expr:     CASE case_arg when_clause_list case_default END_P
                        { $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); }
-               | NULLIF '(' a_expr ',' a_expr ')'
-                       { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); }
-               | COALESCE '(' expr_list ')'
-                       { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); }
                ;
 
 when_clause_list:  when_clause_list when_clause
@@ -3718,39 +4150,39 @@ case_default:  ELSE a_expr
                ;
 
 case_arg:  a_expr                      { $$ = $1; }
-               | /*EMPTY*/                     { $$ = EMPTY; }
+               | /*EMPTY*/             { $$ = EMPTY; }
                ;
 
-columnref: relation_name opt_indirection
-               { $$ = cat2_str($1, $2); }
-       | dotted_name opt_indirection
-               { $$ = cat2_str($1, $2); }
+columnref: relation_name               { $$ = $1; }
+       | relation_name indirection     { $$ = cat2_str($1, $2); }
        ;
 
-dotted_name: relation_name attrs
-                       { $$ = cat2_str($1, $2); }
-               ;
+indirection_el:
+       '.' attr_name                   { $$ = cat2_str(make_str("."), $2); }
+       | '.' '*'                       { $$ = make_str(".*"); }
+       | '[' a_expr ']'                { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
+       | '[' a_expr ':' a_expr ']'     { $$ = cat_str(5, make_str("["), $2, make_str(":"), $4, make_str("]")); }
+       ;
 
-attrs: '.' attr_name
-                       { $$ = cat2_str(make_str("."), $2); }
-               | '.' '*'
-                       { $$ = make_str(".*"); }
-               | '.' attr_name attrs
-                       { $$ = cat_str(3, make_str("."), $2, $3); }
-               ;
+indirection:   indirection_el          { $$ = $1; }
+       | indirection indirection_el    { $$ = cat2_str($1, $2); }
+       ;
 
-opt_empty_parentheses: '(' ')' { $$ = make_str("()"); }
-               | /*EMPTY*/                             { $$ = EMPTY; }
-               ;
+opt_indirection:
+       /*EMPTY*/                               { $$ = EMPTY; }
+       | opt_indirection indirection_el        { $$ = cat2_str($1, $2);} 
+       ;
 
+opt_asymmetric: ASYMMETRIC     { $$ = make_str("asymmetric"); }
+       | /*EMPTY*/             { $$ = EMPTY; }
+       ;
 
 /*****************************************************************************
  *
- *     target lists
+ *     target lists for SELECT, UPDATE, INSERT
  *
  *****************************************************************************/
 
-/* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
 target_list:  target_list ',' target_el
                        { $$ = cat_str(3, $1, make_str(","), $3);  }
                | target_el
@@ -3837,6 +4269,8 @@ inf_val_list: a_expr
 
 update_target_el:  ColId opt_indirection '=' a_expr
                        { $$ = cat_str(4, $1, $2, make_str("="), $4); }
+               | ColId opt_indirection '=' DEFAULT
+                       { $$ = cat_str(3, $1, $2, make_str("= default")); }
                ;
 
 insert_target_list:  insert_target_list ',' insert_target_el
@@ -3845,8 +4279,8 @@ insert_target_list:  insert_target_list ',' insert_target_el
                                {       $$ = $1;  }
                ;
 
-insert_target_el:  target_el   {       $$ = $1;  }
-               | DEFAULT       {       $$ = make_str("default"); }
+insert_target_el:  a_expr      { $$ = $1;  }
+               | DEFAULT       { $$ = make_str("default"); }
                ;
 
 
@@ -3868,8 +4302,8 @@ qualified_name_list:  qualified_name
 
 qualified_name: relation_name
                { $$ = $1; }
-               | dotted_name
-               { $$ = $1; }
+               | relation_name indirection
+               { $$ = cat2_str($1, $2); }
                ;
 
 name_list:  name
@@ -3882,23 +4316,15 @@ name_list:  name
 name:                          ColId                   { $$ = $1; };
 database_name:                 ColId                   { $$ = $1; };
 access_method:                 ColId                   { $$ = $1; };
-attr_name:                             ColId                   { $$ = $1; };
+attr_name:                             ColLabel                { $$ = $1; };
 index_name:                            ColId                   { $$ = $1; };
 
 file_name:                             StringConst             { $$ = $1; };
 
-/* func_name will soon return a List ... but not yet */
-/*
-func_name: function_name
-                       { $$ = makeList1(makeString($1)); }
-               | dotted_name
-                       { $$ = $1; }
-               ;
-*/
 func_name: function_name
                        { $$ = $1; }
-               | dotted_name
-                       { $$ = $1; }
+               | relation_name indirection
+                       { $$ = cat2_str($1, $2); }
                ;
 
 
@@ -3913,8 +4339,6 @@ AexprConst:  PosAllConst
                        { $$ = cat_str(3, $1, $2, $3); }
                | ConstInterval  '(' PosIntConst ')' StringConst opt_interval
                        { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
-               | PARAM opt_indirection
-                       { $$ = cat2_str(make_str("param"), $2); }
                | TRUE_P
                        { $$ = make_str("true"); }
                | FALSE_P
@@ -3933,7 +4357,7 @@ Sconst:  SCONST
                {
                        $$ = (char *)mm_alloc(strlen($1) + 3);
                        $$[0]='\'';
-                                       strcpy($$+1, $1);
+                       strcpy($$+1, $1);
                        $$[strlen($1)+2]='\0';
                        $$[strlen($1)+1]='\'';
                        free($1);
@@ -3948,6 +4372,56 @@ IntConst:        PosIntConst             { $$ = $1; }
                | '-' PosIntConst       { $$ = cat2_str(make_str("-"), $2); }
                ;
 
+IntConstVar:   Iconst  
+               {
+                       char *length = mm_alloc(32);
+
+                       sprintf(length, "%d", (int) strlen($1));
+                       new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0);
+                       $$ = $1;
+               }
+               | cvariable     { $$ = $1; }
+               ;
+
+AllConstVar:   Fconst
+               {
+                       char *length = mm_alloc(32);
+                       
+                       sprintf(length, "%d", (int) strlen($1));
+                       new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0);
+                       $$ = $1;
+               }
+               | IntConstVar           { $$ = $1; }
+               | '-' Fconst
+               {
+                       char *length = mm_alloc(32);
+                       char *var = cat2_str(make_str("-"), $2);
+                       
+                       sprintf(length, "%d", (int) strlen(var));
+                       new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
+                       $$ = var;
+               }
+               | '-' Iconst
+               {
+                       char *length = mm_alloc(32);
+                       char *var = cat2_str(make_str("-"), $2);
+                       
+                       sprintf(length, "%d", (int) strlen(var));
+                       new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
+                       $$ = var;
+               }
+               | Sconst                
+               {
+                       char *length = mm_alloc(32);
+                       char *var = $1 + 1;
+                       
+                       var[strlen(var) - 1] = '\0';
+                       sprintf(length, "%d", (int) strlen(var));
+                       new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
+                       $$ = var;
+               }
+               ;
+
 StringConst:   Sconst          { $$ = $1; }
                | civar         { $$ = $1; }
                ;
@@ -3976,7 +4450,7 @@ PosAllConst:      Sconst          { $$ = $1; }
                | civar         { $$ = $1; }
                ;
 
-UserId:  ColId                         { $$ = $1;};
+RoleId:  ColId                         { $$ = $1;};
 
 SpecialRuleRelation:  OLD
                {
@@ -4016,11 +4490,7 @@ connection_target: database_name opt_server opt_port
                {
                        /* old style: dbname[@server][:port] */
                        if (strlen($2) > 0 && *($2) != '@')
-                       {
-                               snprintf(errortext, sizeof(errortext),
-                                                "Expected '@', found '%s'", $2);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "Expected '@', found '%s'", $2);
 
                        $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
                }
@@ -4028,63 +4498,38 @@ connection_target: database_name opt_server opt_port
                {
                        /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
                        if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported");
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported");
 
                        if (strncmp($3, "//", strlen("//")) != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "Expected '://', found '%s'", $3);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "Expected '://', found '%s'", $3);
 
                        if (strncmp($1, "unix", strlen("unix")) == 0 &&
                                strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
                                strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//"));
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//"));
 
                        $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),    $7, make_str("\"")));
                }
-               | StringConst
+               | Sconst
                {
                        if ($1[0] == '\"')
                                $$ = $1;
-                       else if (strcmp($1, " ?") == 0) /* variable */
-                       {
-                               enum ECPGttype type = argsinsert->variable->type->type;
-
-                               /* if array see what's inside */
-                               if (type == ECPGt_array)
-                                       type = argsinsert->variable->type->u.element->type;
-
-                               /* handle varchars */
-                               if (type == ECPGt_varchar)
-                                       $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
-                               else
-                                       $$ = mm_strdup(argsinsert->variable->name);
-                       }
                        else
                                $$ = make3_str(make_str("\""), $1, make_str("\""));
                }
+               | char_variable
+               {
+                       $$ = $1;
+               }
                ;
 
-db_prefix: ident CVARIABLE
+db_prefix: ident cvariable
                {
                        if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "Expected 'postgresql', found '%s'", $2);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "Expected 'postgresql', found '%s'", $2);
 
                        if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "Illegal connection type %s", $1);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "Illegal connection type %s", $1);
 
                        $$ = make3_str($1, make_str(":"), $2);
                }
@@ -4093,10 +4538,7 @@ db_prefix: ident CVARIABLE
 server: Op server_name
                {
                        if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "Expected '@' or '://', found '%s'", $1);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "Expected '@' or '://', found '%s'", $1);
 
                        $$ = make2_str($1, $2);
                }
@@ -4133,7 +4575,7 @@ ora_user: user_name
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-user_name: UserId
+user_name: RoleId
                {
                        if ($1[0] == '\"')
                                $$ = $1;
@@ -4144,7 +4586,7 @@ user_name: UserId
                {
                        if ($1[0] == '\"')
                                $$ = $1;
-                       else if (strcmp($1, "?") == 0) /* variable */
+                       else if (strcmp($1, " ?") == 0) /* variable */
                        {
                                enum ECPGttype type = argsinsert->variable->type->type;
 
@@ -4163,28 +4605,34 @@ user_name: UserId
                }
                ;
 
-char_variable: CVARIABLE
+char_variable: cvariable
                {
-                       /* check if we have a char variable */
+                       /* check if we have a string variable */
                        struct variable *p = find_variable($1);
                        enum ECPGttype type = p->type->type;
 
-                       /* if array see what's inside */
-                       if (type == ECPGt_array)
-                               type = p->type->u.element->type;
-
-                       switch (type)
-                       {
-                               case ECPGt_char:
-                               case ECPGt_unsigned_char:
-                                       $$ = $1;
-                                       break;
-                               case ECPGt_varchar:
-                                       $$ = make2_str($1, make_str(".arr"));
-                                       break;
-                               default:
+                       /* If we have just one character this is not a string */
+                       if (atol(p->type->size) == 1)
                                        mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
-                                       break;
+                       else
+                       {
+                               /* if array see what's inside */
+                               if (type == ECPGt_array)
+                                       type = p->type->u.element->type;
+
+                               switch (type)
+                               {
+                                       case ECPGt_char:
+                                       case ECPGt_unsigned_char:
+                                               $$ = $1;
+                                               break;
+                                       case ECPGt_varchar:
+                                               $$ = make2_str($1, make_str(".arr"));
+                                               break;
+                                       default:
+                                               mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
+                                               break;
+                               }
                        }
                }
                ;
@@ -4195,10 +4643,7 @@ opt_options: Op ColId
                                mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
 
                        if (strcmp($1, "?") != 0)
-                       {
-                               snprintf(errortext, sizeof(errortext), "unrecognised token '%s'", $1);
-                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                       }
+                               mmerror(PARSE_ERROR, ET_ERROR, "unrecognised token '%s'", $1);
 
                        $$ = make2_str(make_str("?"), $2);
                }
@@ -4209,7 +4654,7 @@ opt_options: Op ColId
  * Declare a prepared cursor. The syntax is different from the standard
  * declare statement, so we create a new rule.
  */
-ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR ident
+ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
                {
                        struct cursor *ptr, *this;
                        struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
@@ -4217,11 +4662,8 @@ ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR ident
                        for (ptr = cur; ptr != NULL; ptr = ptr->next)
                        {
                                if (strcmp($2, ptr->name) == 0)
-                               {
-                                               /* re-definition is a bug */
-                                       snprintf(errortext, sizeof(errortext), "cursor %s already defined", $2);
-                                       mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                               }
+                                       /* re-definition is a bug */
+                                       mmerror(PARSE_ERROR, ET_ERROR, "cursor %s already defined", $2);
                        }
 
                        this = (struct cursor *) mm_alloc(sizeof(struct cursor));
@@ -4236,11 +4678,11 @@ ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR ident
                        thisquery->type = &ecpg_query;
                        thisquery->brace_level = 0;
                        thisquery->next = NULL;
-                       thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($7));
-                       sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $7);
+                       thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement()") + strlen($7));
+                       sprintf(thisquery->name, "ECPGprepared_statement(%s)", $7);
 
                        this->argsinsert = NULL;
-                       add_variable(&(this->argsinsert), thisquery, &no_indicator);
+                       add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
 
                        cur = this;
 
@@ -4252,10 +4694,10 @@ ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR ident
  * the exec sql deallocate prepare command to deallocate a previously
  * prepared statement
  */
-ECPGDeallocate: DEALLOCATE PREPARE ident
-                       { $$ = cat_str(3, make_str("ECPGdeallocate(__LINE__, \""), $3, make_str("\");")); }
-               | DEALLOCATE ident
-                       { $$ = cat_str(2, make_str("ECPGdeallocate(__LINE__, \""), $2, make_str("\");")); }
+ECPGDeallocate: DEALLOCATE PREPARE prepared_name
+                       { $$ = $3; }
+               | DEALLOCATE prepared_name
+                       { $$ = $2; }
                ;
 
 /* 
@@ -4268,24 +4710,25 @@ single_vt_declaration: type_declaration         { $$ = $1; }
                ;
        
 single_var_declaration: storage_declaration 
-               single_vt_type
+               var_type
                {
                        actual_type[struct_level].type_enum = $2.type_enum;
                        actual_type[struct_level].type_dimension = $2.type_dimension;
                        actual_type[struct_level].type_index = $2.type_index;
                        actual_type[struct_level].type_sizeof = $2.type_sizeof;
+
+                       actual_startline[struct_level] = hashline_number();
                }
                variable_list ';'
                {
                        $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
                }
-               | single_vt_type
+               | var_type
                {
                        actual_type[struct_level].type_enum = $1.type_enum;
                        actual_type[struct_level].type_dimension = $1.type_dimension;
                        actual_type[struct_level].type_index = $1.type_index;
                        actual_type[struct_level].type_sizeof = $1.type_sizeof;
-                       actual_storage[struct_level] = EMPTY;
 
                        actual_startline[struct_level] = hashline_number();
                }
@@ -4295,34 +4738,7 @@ single_var_declaration: storage_declaration
                }
                | struct_union_type_with_symbol ';'
                {
-                       /* this is essantially a typedef but needs the keyword struct/union as well */
-                       struct typedefs *ptr, *this;
-                       
-                       for (ptr = types; ptr != NULL; ptr = ptr->next)
-                        {
-                                if (strcmp($1.type_str, ptr->name) == 0)
-                                {
-                                        /* re-definition is a bug */
-                                        snprintf(errortext, sizeof(errortext), "Type %s already defined", $1.type_str);
-                                        mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                                }
-                        }
-
-                        this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
-
-                        /* initial definition */
-                        this->next = types;
-                       this->name = $1.type_str;
-                        this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
-                        this->type->type_enum = $1.type_enum;
-                        this->type->type_str = mm_strdup($1.type_str);
-                        this->type->type_dimension = make_str("-1"); /* dimension of array */
-                        this->type->type_index = make_str("-1");    /* length of string */
-                        this->type->type_sizeof = ECPGstruct_sizeof;
-                        this->struct_member_list = struct_member_list[struct_level];
-
-                       types = this;
-                       $$ = cat2_str($1.type_sizeof, make_str(";"));
+                       $$ = cat2_str($1, make_str(";"));
                }
                ;
 
@@ -4339,135 +4755,6 @@ ecpg_interval:  opt_interval    { $$ = $1; }
                | MONTH_P TO MONTH_P    { $$ = make_str("month to month"); }
                ;
 
-single_vt_type: common_type
-               | DOUBLE_P
-               {
-                       $$.type_enum = ECPGt_double;
-                       $$.type_str = make_str("double");
-                       $$.type_dimension = make_str("-1");
-                       $$.type_index = make_str("-1");
-                       $$.type_sizeof = NULL;
-               }
-               | ECPGColLabelCommon ecpg_interval
-               {
-                       if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
-                               mmerror (PARSE_ERROR, ET_ERROR, "Interval specification not allowed here ");
-                       
-                       /*
-                        * Check for type names that the SQL grammar treats as
-                        * unreserved keywords
-                        */
-                       if (strcmp($1, "varchar") == 0)
-                       {
-                               $$.type_enum = ECPGt_varchar;
-                               $$.type_str = EMPTY;
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "float") == 0)
-                       {
-                               $$.type_enum = ECPGt_float;
-                               $$.type_str = make_str("float");
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "numeric") == 0)
-                       {
-                               $$.type_enum = ECPGt_numeric;
-                               $$.type_str = EMPTY;
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "decimal") == 0)
-                       {
-                               $$.type_enum = ECPGt_numeric;
-                               $$.type_str = EMPTY;
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "date") == 0)
-                       {
-                               $$.type_enum = ECPGt_date;
-                               $$.type_str = make_str("Date");
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "timestamp") == 0)
-                       {
-                               $$.type_enum = ECPGt_timestamp;
-                               $$.type_str = make_str("Timestamp");
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "datetime") == 0)
-                       {
-                               $$.type_enum = ECPGt_timestamp;
-                               $$.type_str = make_str("Timestamp");
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       else if (strcmp($1, "interval") == 0)
-                       {
-                               $$.type_enum = ECPGt_interval;
-                               $$.type_str = EMPTY;
-                               $$.type_dimension = make_str("-1");
-                               $$.type_index = make_str("-1");
-                               $$.type_sizeof = NULL;
-                       }
-                       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;
-                               $$.type_sizeof = this->type->type_sizeof;
-                               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
-                       }
-               }
-               | s_struct_union_symbol
-               {
-                       /* this is for named structs/unions */
-                       char *name;
-                       struct typedefs *this;
-                       bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
-
-                       name = cat2_str($1.su, $1.symbol);
-                       /* Do we have a forward definition? */
-                       if (!forward)
-                       {
-                               /* No */
-                               
-                               this = get_typedef(name);
-                               $$.type_str = mm_strdup(this->name);
-                               $$.type_enum = this->type->type_enum;
-                               $$.type_dimension = this->type->type_dimension;
-                               $$.type_index = this->type->type_index;
-                               $$.type_sizeof = this->type->type_sizeof;
-                               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
-                               free(name);
-                       }
-                       else
-                       {
-                               $$.type_str = name;
-                                $$.type_enum = ECPGt_long;
-                                $$.type_dimension = make_str("-1");
-                                $$.type_index = make_str("-1");
-                                $$.type_sizeof = make_str("");
-                                struct_member_list[struct_level] = NULL;
-                       }
-               }
-               ;
-
 /*
  * variable declaration inside exec sql declare block
  */
@@ -4487,12 +4774,14 @@ sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
 
 var_type_declarations: /*EMPTY*/                       { $$ = EMPTY; }
                | vt_declarations                       { $$ = $1; }
+               | CPP_LINE                              { $$ = $1; }
                ;
 
 vt_declarations:  var_declaration                      { $$ = $1; }
                | type_declaration                      { $$ = $1; }
                | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
                | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
+               | vt_declarations CPP_LINE              { $$ = cat2_str($1, $2); }
                ;
 
 variable_declarations: var_declaration                         { $$ = $1; }
@@ -4524,20 +4813,17 @@ type_declaration: S_TYPEDEF
                        for (ptr = types; ptr != NULL; ptr = ptr->next)
                        {
                                if (strcmp($5, ptr->name) == 0)
-                               {
                                        /* re-definition is a bug */
-                                       snprintf(errortext, sizeof(errortext), "Type %s already defined", $5);
-                                       mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                               }
+                                       mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", $5);
                        }
-
-                       adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0);
+                       adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0, true);
 
                        this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
 
                        /* initial definition */
                        this->next = types;
                        this->name = $5;
+                       this->brace_level = braces_open;
                        this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
                        this->type->type_enum = $3.type_enum;
                        this->type->type_str = mm_strdup($5);
@@ -4545,13 +4831,13 @@ type_declaration: S_TYPEDEF
                        this->type->type_index = length;    /* length of string */
                        this->type->type_sizeof = ECPGstruct_sizeof;
                        this->struct_member_list = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ?
-                               struct_member_list[struct_level] : NULL;
+                               ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
 
                        if ($3.type_enum != ECPGt_varchar &&
                            $3.type_enum != ECPGt_char &&
                            $3.type_enum != ECPGt_unsigned_char &&
                            atoi(this->type->type_index) >= 0)
-                               mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
+                               mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
 
                        types = this;
                }
@@ -4568,6 +4854,8 @@ var_declaration: storage_declaration
                        actual_type[struct_level].type_dimension = $2.type_dimension;
                        actual_type[struct_level].type_index = $2.type_index;
                        actual_type[struct_level].type_sizeof = $2.type_sizeof;
+
+                       actual_startline[struct_level] = hashline_number();
                }
                variable_list ';'
                {
@@ -4579,7 +4867,6 @@ var_declaration: storage_declaration
                        actual_type[struct_level].type_dimension = $1.type_dimension;
                        actual_type[struct_level].type_index = $1.type_index;
                        actual_type[struct_level].type_sizeof = $1.type_sizeof;
-                       actual_storage[struct_level] = EMPTY;
                        
                        actual_startline[struct_level] = hashline_number();
                }
@@ -4589,51 +4876,21 @@ var_declaration: storage_declaration
                }
                | struct_union_type_with_symbol ';'
                {
-                       /* this is essantially a typedef but needs the keyword struct/union as well */
-                       struct typedefs *ptr, *this;
-                       
-                       for (ptr = types; ptr != NULL; ptr = ptr->next)
-                        {
-                                if (strcmp($1.type_str, ptr->name) == 0)
-                                {
-                                        /* re-definition is a bug */
-                                        snprintf(errortext, sizeof(errortext), "Type %s already defined", $1.type_str);
-                                        mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                                }
-                        }
-
-                        this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
-
-                        /* initial definition */
-                        this->next = types;
-                       this->name = $1.type_str;
-                        this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
-                        this->type->type_enum = $1.type_enum;
-                        this->type->type_str = mm_strdup($1.type_str);
-                        this->type->type_dimension = make_str("-1"); /* dimension of array */
-                        this->type->type_index = make_str("-1");    /* length of string */
-                        this->type->type_sizeof = ECPGstruct_sizeof;
-                        this->struct_member_list = struct_member_list[struct_level];
-
-                       types = this;
-                       $$ = cat2_str($1.type_sizeof, make_str(";"));
+                       $$ = cat2_str($1, make_str(";"));
                }
                ;
 
 storage_declaration: storage_clause storage_modifier
                {
-                       actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
-                       actual_startline[struct_level] = hashline_number();
+                       $$ = cat2_str ($1, $2);
                }
                | storage_clause
                {
-                       actual_storage[struct_level] = mm_strdup($1);
-                       actual_startline[struct_level] = hashline_number();
+                       $$ = $1;
                }
                | storage_modifier
                {
-                       actual_storage[struct_level] = mm_strdup($1);
-                       actual_startline[struct_level] = hashline_number();
+                       $$ = $1;
                }
                ;
 
@@ -4647,7 +4904,7 @@ storage_modifier : S_CONST                { $$ = make_str("const"); }
                | S_VOLATILE            { $$ = make_str("volatile"); }
                ;
 
-common_type: simple_type
+var_type:      simple_type
                {
                        $$.type_enum = $1;
                        $$.type_str = mm_strdup(ECPGtype_name($1));
@@ -4682,19 +4939,28 @@ common_type: simple_type
                }
                | ECPGColLabelCommon '(' precision opt_scale ')'
                {
-                       if (strcmp($1, "numeric") != 0 && strcmp($1, "decimal") != 0)
+                       if (strcmp($1, "numeric") == 0)
+                       {
+                               $$.type_enum = ECPGt_numeric;
+                               $$.type_str = make_str("numeric");
+                       }
+                       else if (strcmp($1, "decimal") == 0)
+                       {
+                               $$.type_enum = ECPGt_decimal;
+                               $$.type_str = make_str("decimal");
+                       }
+                       else
+                       {
                                mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument");
+                               $$.type_enum = ECPGt_numeric;
+                               $$.type_str = make_str("numeric");
+                       }
                        
-                       $$.type_enum = ECPGt_numeric;
-                       $$.type_str = EMPTY;
                        $$.type_dimension = make_str("-1");
                        $$.type_index = make_str("-1");
                        $$.type_sizeof = NULL;
                }
-               ;
-
-var_type:      common_type
-               | ECPGColLabel ecpg_interval
+               | ECPGColLabelCommon ecpg_interval
                {
                        if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
                                mmerror (PARSE_ERROR, ET_ERROR, "Interval specification not allowed here ");
@@ -4730,15 +4996,15 @@ var_type:       common_type
                        else if (strcmp($1, "numeric") == 0)
                        {
                                $$.type_enum = ECPGt_numeric;
-                               $$.type_str = EMPTY;
+                               $$.type_str = make_str("numeric");
                                $$.type_dimension = make_str("-1");
                                $$.type_index = make_str("-1");
                                $$.type_sizeof = NULL;
                        }
                        else if (strcmp($1, "decimal") == 0)
                        {
-                               $$.type_enum = ECPGt_numeric;
-                               $$.type_str = EMPTY;
+                               $$.type_enum = ECPGt_decimal;
+                               $$.type_str = make_str("decimal");
                                $$.type_dimension = make_str("-1");
                                $$.type_index = make_str("-1");
                                $$.type_sizeof = NULL;
@@ -4746,7 +5012,7 @@ var_type: common_type
                        else if (strcmp($1, "date") == 0)
                        {
                                $$.type_enum = ECPGt_date;
-                               $$.type_str = make_str("Date");
+                               $$.type_str = make_str("date");
                                $$.type_dimension = make_str("-1");
                                $$.type_index = make_str("-1");
                                $$.type_sizeof = NULL;
@@ -4754,7 +5020,7 @@ var_type: common_type
                        else if (strcmp($1, "timestamp") == 0)
                        {
                                $$.type_enum = ECPGt_timestamp;
-                               $$.type_str = make_str("Timestamp");
+                               $$.type_str = make_str("timestamp");
                                $$.type_dimension = make_str("-1");
                                $$.type_index = make_str("-1");
                                $$.type_sizeof = NULL;
@@ -4762,7 +5028,7 @@ var_type: common_type
                        else if (strcmp($1, "interval") == 0)
                        {
                                $$.type_enum = ECPGt_interval;
-                               $$.type_str = EMPTY;
+                               $$.type_str = make_str("interval");
                                $$.type_dimension = make_str("-1");
                                $$.type_index = make_str("-1");
                                $$.type_sizeof = NULL;
@@ -4770,7 +5036,7 @@ var_type: common_type
                        else if (strcmp($1, "datetime") == 0)
                        {
                                $$.type_enum = ECPGt_timestamp;
-                               $$.type_str = make_str("Timestamp");
+                               $$.type_str = make_str("timestamp");
                                $$.type_dimension = make_str("-1");
                                $$.type_index = make_str("-1");
                                $$.type_sizeof = NULL;
@@ -4842,21 +5108,49 @@ struct_union_type_with_symbol: s_struct_union_symbol
                } 
                '{' variable_declarations '}'
                {
+                       struct typedefs *ptr, *this;
+                       struct this_type su_type;
+                       
                        ECPGfree_struct_member(struct_member_list[struct_level]);
                        struct_member_list[struct_level] = NULL;
-                       free(actual_storage[struct_level--]);
+                       struct_level--;
                        if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
-                               $$.type_enum = ECPGt_struct;
+                               su_type.type_enum = ECPGt_struct;
                        else
-                               $$.type_enum = ECPGt_union;
-                       $$.type_str = cat2_str($1.su, $1.symbol);
-                       $$.type_sizeof = cat_str(4, mm_strdup($$.type_str), make_str("{"), $4, make_str("}"));
+                               su_type.type_enum = ECPGt_union;
+                       su_type.type_str = cat2_str($1.su, $1.symbol);
                        free(forward_name);
                        forward_name = NULL;
+                       
+                       /* This is essantially a typedef but needs the keyword struct/union as well.
+                        * So we create the typedef for each struct definition with symbol */
+                       for (ptr = types; ptr != NULL; ptr = ptr->next)
+                        {
+                                if (strcmp(su_type.type_str, ptr->name) == 0)
+                                        /* re-definition is a bug */
+                                        mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", su_type.type_str);
+                        }
+
+                        this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
+
+                        /* initial definition */
+                        this->next = types;
+                       this->name = mm_strdup(su_type.type_str);
+                       this->brace_level = braces_open;
+                        this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+                        this->type->type_enum = su_type.type_enum;
+                        this->type->type_str = mm_strdup(su_type.type_str);
+                        this->type->type_dimension = make_str("-1"); /* dimension of array */
+                        this->type->type_index = make_str("-1");    /* length of string */
+                        this->type->type_sizeof = ECPGstruct_sizeof;
+                        this->struct_member_list = struct_member_list[struct_level];
+
+                       types = this;
+                       $$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}"));
                }
                ;
 
-struct_union_type: struct_union_type_with_symbol       { $$ = $1.type_sizeof; }
+struct_union_type: struct_union_type_with_symbol       { $$ = $1; }
                | s_struct_union
                {
                        struct_member_list[struct_level++] = NULL;
@@ -4867,7 +5161,7 @@ struct_union_type: struct_union_type_with_symbol  { $$ = $1.type_sizeof; }
                {
                        ECPGfree_struct_member(struct_member_list[struct_level]);
                        struct_member_list[struct_level] = NULL;
-                       free(actual_storage[struct_level--]);
+                       struct_level--;
                        $$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
                }
                ;
@@ -4945,6 +5239,7 @@ signed_type: SQL_SHORT                            { $$ = ECPGt_short; }
                }
                | SQL_BOOL                                      { $$ = ECPGt_bool; }
                | CHAR_P                                        { $$ = ECPGt_char; }
+               | DOUBLE_P                                      { $$ = ECPGt_double; }
                ;
 
 opt_signed: SQL_SIGNED
@@ -4957,14 +5252,14 @@ variable_list: variable
                        { $$ = cat_str(3, $1, make_str(","), $3); }
                ;
 
-variable: opt_pointer ECPGColLabelCommon opt_array_bounds opt_initializer
+variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer
                {
                        struct ECPGtype * type;
                        char *dimension = $3.index1; /* dimension of array */
                        char *length = $3.index2;    /* length of string */
                        char dim[14L];
 
-                       adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1));
+                       adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false);
 
                        switch (actual_type[struct_level].type_enum)
                        {
@@ -4988,13 +5283,14 @@ variable: opt_pointer ECPGColLabelCommon opt_array_bounds opt_initializer
                                                        *dim = '\0';
                                        else    
                                                        sprintf(dim, "[%s]", dimension);
-                                       if (strcmp(length, "0") == 0)
+                                       /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */
+                                       if (atoi(length) < 0 || strcmp(length, "0") == 0)
                                                mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
 
                                        if (strcmp(dimension, "0") == 0)
-                                               $$ = cat_str(7, mm_strdup(actual_storage[struct_level]), make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } *"), mm_strdup($2), $4);
+                                               $$ = cat_str(6, make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } *"), mm_strdup($2), $4);
                                        else
-                                          $$ = cat_str(8, mm_strdup(actual_storage[struct_level]), make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4);
+                                               $$ = cat_str(7, make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4);
                                        break;
 
                                case ECPGt_char:
@@ -5007,30 +5303,6 @@ variable: opt_pointer ECPGColLabelCommon opt_array_bounds opt_initializer
                                        $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
                                        break;
 
-                               case ECPGt_numeric:
-                                       if (atoi(dimension) < 0)
-                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
-                                        else
-                                                type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
-
-                                       if (atoi(dimension) < 0)
-                                               $$ = cat_str(4, mm_strdup(actual_storage[struct_level]), make_str("Numeric"), mm_strdup($2), $4);
-                                       else
-                                               $$ = cat_str(5, mm_strdup(actual_storage[struct_level]), make_str("Numeric"), mm_strdup($2), mm_strdup(dim), $4);
-                                       break;
-                               
-                               case ECPGt_interval:
-                                       if (atoi(dimension) < 0)
-                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
-                                        else
-                                                type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
-
-                                       if (atoi(dimension) < 0)
-                                               $$ = cat_str(4, mm_strdup(actual_storage[struct_level]), make_str("Interval"), mm_strdup($2), $4);
-                                       else
-                                               $$ = cat_str(5, mm_strdup(actual_storage[struct_level]), make_str("Interval"), mm_strdup($2), mm_strdup(dim), $4);
-                                       break;
-                                       
                                default:
                                        if (atoi(dimension) < 0)
                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"));
@@ -5065,8 +5337,7 @@ opt_pointer: /*EMPTY*/                            { $$ = EMPTY; }
                ;
 
 /*
- * As long as the prepare statement is not supported by the backend, we will
- * try to simulate it here so we get dynamic SQL
+ * We try to simulate the correct DECLARE syntax here so we get dynamic SQL
  */
 ECPGDeclare: DECLARE STATEMENT ident
                {
@@ -5102,21 +5373,21 @@ ECPGExecute : EXECUTE IMMEDIATE execstring
                        thisquery->next = NULL;
                        thisquery->name = $3;
 
-                       add_variable(&argsinsert, thisquery, &no_indicator);
+                       add_variable_to_head(&argsinsert, thisquery, &no_indicator);
 
                        $$ = make_str("?");
                }
-               | EXECUTE name
+               | EXECUTE prepared_name
                {
                        struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
 
                        thisquery->type = &ecpg_query;
                        thisquery->brace_level = 0;
                        thisquery->next = NULL;
-                       thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($2));
-                       sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $2);
+                       thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement()") + strlen($2));
+                       sprintf(thisquery->name, "ECPGprepared_statement(%s)", $2);
 
-                       add_variable(&argsinsert, thisquery, &no_indicator);
+                       add_variable_to_head(&argsinsert, thisquery, &no_indicator);
                }
                execute_rest
                {
@@ -5137,6 +5408,10 @@ execstring: char_variable
                        { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
                ;
 
+prepared_name: name            { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
+               | char_variable { $$ = $1; }
+               ;
+
 /*
  * the exec sql free command to deallocate a previously
  * prepared statement
@@ -5153,33 +5428,43 @@ opt_ecpg_using: /*EMPTY*/               { $$ = EMPTY; }
                ;
 
 ecpg_using:    USING using_list        { $$ = EMPTY; }
+               | using_descriptor      { $$ = $1; }
                ;
 
 using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
                {
-                       add_variable(&argsresult, descriptor_variable($4,0), &no_indicator);
+                       add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
                        $$ = EMPTY;
                }
                ;
 
 into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
                {
-                       add_variable(&argsresult, descriptor_variable($4,0), &no_indicator);
+                       add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
                        $$ = EMPTY;
                }
                ;
                
 opt_sql: /*EMPTY*/ | SQL_SQL;
 
-ecpg_into_using: ecpg_into             { $$ = EMPTY; }
-               | using_descriptor      { $$ = $1; }
-               ;
-
 ecpg_into: INTO into_list              { $$ = EMPTY; }
                | into_descriptor       { $$ = $1; }
                ;
                
-using_list: civar | civar ',' using_list;
+using_list: UsingConst | UsingConst ',' using_list;
+
+UsingConst: AllConst
+               {
+                       if ($1[1] != '?') /* found a constant */
+                       {
+                               char *length = mm_alloc(32);
+
+                               sprintf(length, "%d", (int) strlen($1));
+                               add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0), &no_indicator);
+                       }
+               }
+               | civarind { $$ = EMPTY; }
+               ;
 
 /*
  * As long as the prepare statement is not supported by the backend, we will
@@ -5187,8 +5472,8 @@ using_list: civar | civar ',' using_list;
  *
  * It is supported now but not usable yet by ecpg.
  */
-ECPGPrepare: PREPARE name FROM execstring
-                       { $$ = cat2_str(make3_str(make_str("\""), $2, make_str("\",")), $4); }
+ECPGPrepare: PREPARE prepared_name FROM execstring
+                       { $$ = cat_str(3, $2, make_str(","), $4); }
                ;
 /* 
  * We accept descibe but do nothing with it so far.
@@ -5219,9 +5504,20 @@ opt_output:      SQL_OUTPUT      { $$ = make_str("output"); }
        
 /*
  * dynamic SQL: descriptor based access
- *     written by Christof Petig <christof.petig@wtal.de>
+ *     originall written by Christof Petig <christof.petig@wtal.de>
+ *                     and Peter Eisentraut <peter.eisentraut@credativ.de>
+ */
+
+/*
+ * allocate a descriptor
  */
+ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
+               {
+                       add_descriptor($3,connection);
+                       $$ = $3;
+               };
 
 /*
  * deallocate a descriptor
  */
@@ -5233,69 +5529,95 @@ ECPGDeallocateDescr:    DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
                ;
 
 /*
- * allocate a descriptor
+ * manipulate a descriptor header
  */
-ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
-               {
-                       add_descriptor($3,connection);
-                       $$ = $3;
-               };
 
-/*
- * read from descriptor
- */
+ECPGGetDescriptorHeader: GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
+                       {  $$ = $3; }
+               ;
+
+ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
+               | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
+               ;
 
-ECPGGetDescHeaderItem: CVARIABLE '=' desc_header_item
+ECPGGetDescHeaderItem: cvariable '=' desc_header_item
                        { push_assignment($1, $3); }
                ;
 
-desc_header_item:      SQL_COUNT                       { $$ = ECPGd_count; }
+
+ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
+                       { $$ = $3; }
                ;
 
-ECPGGetDescItem: CVARIABLE '=' descriptor_item { push_assignment($1, $3); };
+ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
+               | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
+               ;
 
-descriptor_item:       SQL_CARDINALITY         { $$ = ECPGd_cardinality; }
-               | SQL_DATA                                              { $$ = ECPGd_data; }
-               | SQL_DATETIME_INTERVAL_CODE    { $$ = ECPGd_di_code; }
-               | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; }
-               | SQL_INDICATOR                                 { $$ = ECPGd_indicator; }
-               | SQL_KEY_MEMBER                                { $$ = ECPGd_key_member; }
-               | SQL_LENGTH                                    { $$ = ECPGd_length; }
-               | SQL_NAME                                              { $$ = ECPGd_name; }
-               | SQL_NULLABLE                                  { $$ = ECPGd_nullable; }
-               | SQL_OCTET_LENGTH                              { $$ = ECPGd_octet; }
-               | PRECISION                                             { $$ = ECPGd_precision; }
-               | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
-               | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
-               | SQL_SCALE                                             { $$ = ECPGd_scale; }
-               | TYPE_P                                                { $$ = ECPGd_type; }
+ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
+                {
+                       push_assignment($3, $1);
+               }
                ;
 
-ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
-               | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
+
+desc_header_item:      SQL_COUNT                       { $$ = ECPGd_count; }
+               ;
+
+/*
+ * manipulate a descriptor
+ */
+
+ECPGGetDescriptor:     GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE IntConstVar ECPGGetDescItems
+                       {  $$.str = $5; $$.name = $3; }
                ;
 
 ECPGGetDescItems: ECPGGetDescItem
                | ECPGGetDescItems ',' ECPGGetDescItem
                ;
 
-ECPGGetDescriptorHeader:       GET SQL_DESCRIPTOR quoted_ident_stringvar
-                                                               ECPGGetDescHeaderItems
-                       {  $$ = $3; }
-               ;
+ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); };
 
-ECPGGetDescriptor:     GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE CVARIABLE ECPGGetDescItems
-                       {  $$.str = $5; $$.name = $3; }
-               |       GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE Iconst ECPGGetDescItems
+
+ECPGSetDescriptor:     SET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE IntConstVar ECPGSetDescItems
                        {  $$.str = $5; $$.name = $3; }
                ;
 
+ECPGSetDescItems: ECPGSetDescItem
+               | ECPGSetDescItems ',' ECPGSetDescItem
+               ;
+
+ECPGSetDescItem: descriptor_item '=' AllConstVar
+               {
+                       push_assignment($3, $1);
+               }
+               ;
+
+
+descriptor_item:       SQL_CARDINALITY                 { $$ = ECPGd_cardinality; }
+               | SQL_DATA                              { $$ = ECPGd_data; }
+               | SQL_DATETIME_INTERVAL_CODE            { $$ = ECPGd_di_code; }
+               | SQL_DATETIME_INTERVAL_PRECISION       { $$ = ECPGd_di_precision; }
+               | SQL_INDICATOR                         { $$ = ECPGd_indicator; }
+               | SQL_KEY_MEMBER                        { $$ = ECPGd_key_member; }
+               | SQL_LENGTH                            { $$ = ECPGd_length; }
+               | SQL_NAME                              { $$ = ECPGd_name; }
+               | SQL_NULLABLE                          { $$ = ECPGd_nullable; }
+               | SQL_OCTET_LENGTH                      { $$ = ECPGd_octet; }
+               | PRECISION                             { $$ = ECPGd_precision; }
+               | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
+               | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
+               | SQL_SCALE                             { $$ = ECPGd_scale; }
+               | TYPE_P                                { $$ = ECPGd_type; }
+               ;
+
+
 /*
  * for compatibility with ORACLE we will also allow the keyword RELEASE
  * after a transaction statement to disconnect from the database.
  */
 
-ECPGRelease: TransactionStmt SQL_RELEASE
+/* We cannot do that anymore since it causes shift/reduce conflicts. 2004-09-27 Michael Meskes
+ECPGRelease: TransactionStmt RELEASE
                {
                        if (strcmp($1, "begin") == 0)
                                                        mmerror(PARSE_ERROR, ET_ERROR, "RELEASE does not make sense when beginning a transaction");
@@ -5309,6 +5631,7 @@ ECPGRelease: TransactionStmt SQL_RELEASE
                        free($1);
                }
                ;
+*/
 
 /*
  * set/reset the automatic transaction mode, this needs a differnet handling
@@ -5326,9 +5649,9 @@ on_off: ON                                { $$ = make_str("on"); }
  * set the actual connection, this needs a differnet handling as the other
  * set commands
  */
-ECPGSetConnection:     SET SQL_CONNECTION TO connection_object { $$ = $4; }
-               | SET SQL_CONNECTION '=' connection_object { $$ = $4; }
-               | SET SQL_CONNECTION  connection_object { $$ = $3; }
+ECPGSetConnection:     SET CONNECTION TO connection_object { $$ = $4; }
+               | SET CONNECTION '=' connection_object { $$ = $4; }
+               | SET CONNECTION  connection_object { $$ = $3; }
                ;
 
 /*
@@ -5340,7 +5663,7 @@ ECPGTypedef: TYPE_P
                        /* an initializer specified */
                        initializer = 0;
                }
-               ColLabel IS var_type opt_array_bounds opt_reference
+               ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
                {
                        /* add entry to list */
                        struct typedefs *ptr, *this;
@@ -5356,20 +5679,18 @@ ECPGTypedef: TYPE_P
                                for (ptr = types; ptr != NULL; ptr = ptr->next)
                                {
                                        if (strcmp($3, ptr->name) == 0)
-                                       {
                                                /* re-definition is a bug */
-                                               snprintf(errortext, sizeof(errortext), "Type %s already defined", $3);
-                                               mmerror(PARSE_ERROR, ET_ERROR, errortext);
-                                       }
+                                               mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", $3);
                                }
 
-                               adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0);
+                               adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
 
                                this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
 
                                /* initial definition */
                                this->next = types;
                                this->name = $3;
+                               this->brace_level = braces_open;
                                this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
                                this->type->type_enum = $5.type_enum;
                                this->type->type_str = mm_strdup($3);
@@ -5377,13 +5698,13 @@ ECPGTypedef: TYPE_P
                                this->type->type_index = length;        /* length of string */
                                this->type->type_sizeof = ECPGstruct_sizeof;
                                this->struct_member_list = ($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) ?
-                                       struct_member_list[struct_level] : NULL;
+                                       ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
 
                                if ($5.type_enum != ECPGt_varchar &&
                                        $5.type_enum != ECPGt_char &&
                                        $5.type_enum != ECPGt_unsigned_char &&
                                        atoi(this->type->type_index) >= 0)
-                                       mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
+                                       mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
 
                                types = this;
                        }
@@ -5421,7 +5742,7 @@ ECPGVar: SQL_VAR
                                mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
                        else
                        {
-                               adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0);
+                               adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
 
                                switch ($5.type_enum)
                                {
@@ -5450,7 +5771,7 @@ ECPGVar: SQL_VAR
 
                                        default:
                                                if (atoi(length) >= 0)
-                                                       mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
+                                                       mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
 
                                                if (atoi(dimension) < 0)
                                                        type = ECPGmake_simple_type($5.type_enum, make_str("1"));
@@ -5572,7 +5893,6 @@ ECPGKeywords_vanames:  SQL_BREAK          { $$ = make_str("break"); }
                | SQL_NAME                      { $$ = make_str("name"); }
                | SQL_NULLABLE                  { $$ = make_str("nullable"); }
                | SQL_OCTET_LENGTH              { $$ = make_str("octet_length"); }
-               | SQL_RELEASE                   { $$ = make_str("release"); }
                | SQL_RETURNED_LENGTH           { $$ = make_str("returned_length"); }
                | SQL_RETURNED_OCTET_LENGTH     { $$ = make_str("returned_octet_length"); }
                | SQL_SCALE                     { $$ = make_str("scale"); }
@@ -5581,6 +5901,7 @@ ECPGKeywords_vanames:  SQL_BREAK          { $$ = make_str("break"); }
                | SQL_SQLPRINT                  { $$ = make_str("sqlprint"); }
                | SQL_SQLWARNING                { $$ = make_str("sqlwarning"); }
                | SQL_STOP                      { $$ = make_str("stop"); }
+               | SQL_VALUE                     { $$ = make_str("value"); }
                ;
                
 ECPGKeywords_rest:  SQL_CONNECT                        { $$ = make_str("connect"); }
@@ -5615,12 +5936,21 @@ symbol: ColLabel                                { $$ = $1; }
  * is chosen in part to make keywords acceptable as names wherever possible.
  */
 
+ECPGColId:ident                                                { $$ = $1; }
+               | ECPGunreserved_interval               { $$ = $1; }
+               | ECPGunreserved_con                    { $$ = $1; }
+               | col_name_keyword                      { $$ = $1; }
+               | ECPGKeywords                          { $$ = $1; }
+               | ECPGCKeywords                         { $$ = $1; }
+               | CHAR_P                                { $$ = make_str("char"); }
+               ;
 /* Column identifier --- names that can be column, table, etc names.
  */
 ColId: ident                                           { $$ = $1; }
                | unreserved_keyword                    { $$ = $1; }
                | col_name_keyword                      { $$ = $1; }
                | ECPGKeywords                          { $$ = $1; }
+               | ECPGCKeywords                         { $$ = $1; }
                | CHAR_P                                { $$ = make_str("char"); }
                ;
 
@@ -5630,6 +5960,7 @@ type_name:        ident                                   { $$ = $1; }
                | unreserved_keyword                    { $$ = $1; }
                | ECPGKeywords                          { $$ = $1; }
                | ECPGTypeName                          { $$ = $1; }
+               | ECPGCKeywords                         { $$ = $1; }
                ;
 
 /* Function identifier --- names that can be function names.
@@ -5638,6 +5969,7 @@ function_name:    ident                                   { $$ = $1; }
                | unreserved_keyword                    { $$ = $1; }
                | func_name_keyword                     { $$ = $1; }
                | ECPGKeywords                          { $$ = $1; }
+               | ECPGCKeywords                         { $$ = $1; }
                ;
 
 /* Column label --- allowed labels in "AS" clauses.
@@ -5649,6 +5981,9 @@ ColLabel:  ECPGColLabel                           { $$ = $1; }
                | INPUT_P                       { $$ = make_str("input"); }
                | INT_P                         { $$ = make_str("int"); }
                | UNION                         { $$ = make_str("union"); }
+               | TO                            { $$ = make_str("to"); }
+               | ECPGCKeywords                 { $$ = $1; }
+               | ECPGunreserved_interval       { $$ = $1; }
                ;
 
 ECPGColLabelCommon:  ident                              { $$ = $1; }
@@ -5658,11 +5993,20 @@ ECPGColLabelCommon:  ident                              { $$ = $1; }
                 ;
                
 ECPGColLabel:  ECPGColLabelCommon                      { $$ = $1; }
-               | unreserved_keyword                    { $$ = $1; }
                | reserved_keyword                      { $$ = $1; }
+               | ECPGunreserved                        { $$ = $1; }
                | ECPGKeywords_rest                     { $$ = $1; }
                ;
 
+ECPGCKeywords: S_AUTO                  { $$ = make_str("auto"); }
+               | S_CONST               { $$ = make_str("const"); }
+               | S_EXTERN              { $$ = make_str("extern"); }
+               | S_REGISTER            { $$ = make_str("register"); }
+               | S_STATIC              { $$ = make_str("static"); }
+               | S_TYPEDEF             { $$ = make_str("typedef"); }
+               | S_VOLATILE            { $$ = make_str("volatile"); }
+               ;
+       
 /*
  * Keyword classification lists.  Generally, every keyword present in
  * the Postgres grammar should appear in exactly one of these lists.
@@ -5674,14 +6018,37 @@ ECPGColLabel:  ECPGColLabelCommon                       { $$ = $1; }
 
 /* "Unreserved" keywords --- available for use as any kind of name.
  */
-unreserved_keyword:
-                 ABORT_P                       { $$ = make_str("abort"); }
+/* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel
+   to enable C variables to get names from ECPGColLabel:
+   DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P
+ */
+unreserved_keyword: ECPGunreserved_interval | ECPGunreserved;
+
+ECPGunreserved_interval: DAY_P                 { $$ = make_str("day"); }
+               | HOUR_P                        { $$ = make_str("hour"); }
+               | MINUTE_P                      { $$ = make_str("minute"); }
+               | MONTH_P                       { $$ = make_str("month"); }
+               | SECOND_P                      { $$ = make_str("second"); }
+               | YEAR_P                        { $$ = make_str("year"); }
+               ;
+               
+/* The following symbol must be excluded from var_name but still included in ColId
+   to enable ecpg special postgresql variables with this name:
+   CONNECTION
+ */
+ECPGunreserved:        ECPGunreserved_con              { $$ = $1; }
+               | CONNECTION                    { $$ = make_str("connection"); }
+               ;
+       
+ECPGunreserved_con:      ABORT_P                       { $$ = make_str("abort"); }
                | ABSOLUTE_P                    { $$ = make_str("absolute"); }
                | ACCESS                        { $$ = make_str("access"); }
                | ACTION                        { $$ = make_str("action"); }
-               | ADD                           { $$ = make_str("add"); }
+               | ADD_P                         { $$ = make_str("add"); }
+               | ADMIN                         { $$ = make_str("admin"); }
                | AFTER                         { $$ = make_str("after"); }
                | AGGREGATE                     { $$ = make_str("aggregate"); }
+               | ALSO                          { $$ = make_str("also"); }
                | ALTER                         { $$ = make_str("alter"); }
                | ASSERTION                     { $$ = make_str("assertion"); }
                | ASSIGNMENT                    { $$ = make_str("assignment"); }
@@ -5701,28 +6068,35 @@ unreserved_keyword:
                | COMMENT                       { $$ = make_str("comment"); }
                | COMMIT                        { $$ = make_str("commit"); }
                | COMMITTED                     { $$ = make_str("committed"); }
+/*             | CONNECTION                    { $$ = make_str("connection"); }*/
                | CONSTRAINTS                   { $$ = make_str("constraints"); }
                | CONVERSION_P                  { $$ = make_str("conversion"); }
                | COPY                          { $$ = make_str("copy"); }
                | CREATEDB                      { $$ = make_str("createdb"); }
+               | CREATEROLE                    { $$ = make_str("createrole"); }
                | CREATEUSER                    { $$ = make_str("createuser"); }
+               | CSV                           { $$ = make_str("csv"); }
                | CURSOR                        { $$ = make_str("cursor"); }
                | CYCLE                         { $$ = make_str("cycle"); }
                | DATABASE                      { $$ = make_str("database"); }
-               | DAY_P                         { $$ = make_str("day"); }
+/*             | DAY_P                         { $$ = make_str("day"); }*/
                | DEALLOCATE                    { $$ = make_str("deallocate"); }
                | DECLARE                       { $$ = make_str("declare"); }
+               | DEFAULTS                      { $$ = make_str("defaults"); }
                | DEFERRED                      { $$ = make_str("deferred"); }
                | DELETE_P                      { $$ = make_str("delete"); }
                | DELIMITER                     { $$ = make_str("delimiter"); }
                | DELIMITERS                    { $$ = make_str("delimiters"); }
+               | DISABLE_P                     { $$ = make_str("disable"); }
                | DOMAIN_P                      { $$ = make_str("domain"); }
                | DOUBLE_P                      { $$ = make_str("double"); }
                | DROP                          { $$ = make_str("drop"); }
                | EACH                          { $$ = make_str("each"); }
+               | ENABLE_P                      { $$ = make_str("ensable"); }
                | ENCODING                      { $$ = make_str("encoding"); }
                | ENCRYPTED                     { $$ = make_str("encrypted"); }
                | ESCAPE                        { $$ = make_str("escape"); }
+               | EXCLUDING                     { $$ = make_str("excluding"); }
                | EXCLUSIVE                     { $$ = make_str("exclusive"); }
                | EXECUTE                       { $$ = make_str("execute"); }
                | EXPLAIN                       { $$ = make_str("explain"); }
@@ -5732,16 +6106,19 @@ unreserved_keyword:
                | FORWARD                       { $$ = make_str("forward"); }
                | FUNCTION                      { $$ = make_str("function"); }
                | GLOBAL                        { $$ = make_str("global"); }
+               | GRANTED                       { $$ = make_str("granted"); }
                | HANDLER                       { $$ = make_str("handler"); }
+               | HEADER_P                      { $$ = make_str("header"); }
                | HOLD                          { $$ = make_str("hold"); }
-               | HOUR_P                        { $$ = make_str("hour"); }
+/*             | HOUR_P                        { $$ = make_str("hour"); }*/
                | IMMEDIATE                     { $$ = make_str("immediate"); }
                | IMMUTABLE                     { $$ = make_str("immutable"); }
                | IMPLICIT_P                    { $$ = make_str("implicit"); }
+               | INCLUDING                     { $$ = make_str("including"); }
                | INCREMENT                     { $$ = make_str("increment"); }
                | INDEX                         { $$ = make_str("index"); }
+               | INHERIT                       { $$ = make_str("inherit"); }
                | INHERITS                      { $$ = make_str("inherits"); }
-               | INOUT                         { $$ = make_str("inout"); }
                | INSENSITIVE                   { $$ = make_str("insensitive"); }
                | INSERT                        { $$ = make_str("insert"); }
                | INSTEAD                       { $$ = make_str("instead"); }
@@ -5749,6 +6126,7 @@ unreserved_keyword:
                | KEY                           { $$ = make_str("key"); }
                | LANCOMPILER                   { $$ = make_str("lancompiler"); }
                | LANGUAGE                      { $$ = make_str("language"); }
+               | LARGE_P                       { $$ = make_str("large"); }
                | LAST_P                        { $$ = make_str("last"); }
                | LEVEL                         { $$ = make_str("level"); }
                | LISTEN                        { $$ = make_str("listen"); }
@@ -5756,55 +6134,63 @@ unreserved_keyword:
                | LOCAL                         { $$ = make_str("local"); }
                | LOCATION                      { $$ = make_str("location"); }
                | LOCK_P                        { $$ = make_str("lock"); }
+               | LOGIN_P                       { $$ = make_str("login"); }
                | MATCH                         { $$ = make_str("match"); }
                | MAXVALUE                      { $$ = make_str("maxvalue"); }
-               | MINUTE_P                      { $$ = make_str("minute"); }
+/*             | MINUTE_P                      { $$ = make_str("minute"); }*/
                | MINVALUE                      { $$ = make_str("minvalue"); }
                | MODE                          { $$ = make_str("mode"); }
-               | MONTH_P                       { $$ = make_str("month"); }
+/*             | 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"); }
+               | NOCREATEROLE                  { $$ = make_str("nocreaterole"); }
                | NOCREATEUSER                  { $$ = make_str("nocreateuser"); }
+               | NOINHERIT                     { $$ = make_str("noinherit"); }
+               | NOLOGIN_P                     { $$ = make_str("nologin"); }
+               | NOSUPERUSER                   { $$ = make_str("nosuperuser"); }
                | NOTHING                       { $$ = make_str("nothing"); }
                | NOTIFY                        { $$ = make_str("notify"); }
+               | NOWAIT                        { $$ = make_str("nowait"); }
+               | OBJECT_P                      { $$ = make_str("object"); }
                | OF                            { $$ = make_str("of"); }
                | OIDS                          { $$ = make_str("oids"); }
                | OPERATOR                      { $$ = make_str("operator"); }
                | OPTION                        { $$ = make_str("option"); }
-               | OUT_P                         { $$ = 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"); }
                | PREPARE                       { $$ = make_str("prepare"); }
+               | PREPARED                      { $$ = make_str("prepared"); }
                | PRESERVE                      { $$ = make_str("preserver"); }
                | PRIOR                         { $$ = make_str("prior"); }
                | PRIVILEGES                    { $$ = make_str("privileges"); }
                | PROCEDURAL                    { $$ = make_str("procedural"); }
                | PROCEDURE                     { $$ = make_str("procedure"); }
+               | QUOTE                         { $$ = make_str("quote"); }
                | READ                          { $$ = make_str("read"); }
                | RECHECK                       { $$ = make_str("recheck"); }
                | REINDEX                       { $$ = make_str("reindex"); }
                | RELATIVE_P                    { $$ = make_str("relative"); }
+               | RELEASE                       { $$ = make_str("release"); }
                | RENAME                        { $$ = make_str("rename"); }
+               | REPEATABLE                    { $$ = make_str("repeatable"); }
                | REPLACE                       { $$ = make_str("replace"); }
                | RESET                         { $$ = make_str("reset"); }
                | RESTART                       { $$ = make_str("restart"); }
                | RESTRICT                      { $$ = make_str("restrict"); }
                | RETURNS                       { $$ = make_str("returns"); }
                | REVOKE                        { $$ = make_str("revoke"); }
+               | ROLE                          { $$ = make_str("role"); }
                | ROLLBACK                      { $$ = make_str("rollback"); }
                | ROWS                          { $$ = make_str("rows"); }
                | RULE                          { $$ = make_str("rule"); }
+               | SAVEPOINT                     { $$ = make_str("savepoint"); }
                | SCHEMA                        { $$ = make_str("schema"); }
                | SCROLL                        { $$ = make_str("scroll"); }
-               | SECOND_P                      { $$ = make_str("second"); }
+/*             | SECOND_P                      { $$ = make_str("second"); }*/
                | SEQUENCE                      { $$ = make_str("sequence"); }
                | SERIALIZABLE                  { $$ = make_str("serializable"); }
                | SESSION                       { $$ = make_str("session"); }
@@ -5819,8 +6205,11 @@ unreserved_keyword:
                | STDIN                         { $$ = make_str("stdin"); }
                | STDOUT                        { $$ = make_str("stdout"); }
                | STORAGE                       { $$ = make_str("storage"); }
+               | SUPERUSER_P                   { $$ = make_str("superuser"); }
                | STRICT_P                      { $$ = make_str("strict"); }
+               | SYSTEM_P                      { $$ = make_str("system"); }
                | SYSID                         { $$ = make_str("sysid"); }
+               | TABLESPACE                    { $$ = make_str("tablespace"); }
                | TEMP                          { $$ = make_str("temp"); }
                | TEMPLATE                      { $$ = make_str("template"); }
                | TEMPORARY                     { $$ = make_str("temporary"); }
@@ -5830,23 +6219,22 @@ unreserved_keyword:
                | TRUNCATE                      { $$ = make_str("truncate"); }
                | TRUSTED                       { $$ = make_str("trusted"); }
                | TYPE_P                        { $$ = make_str("type"); }
+               | UNCOMMITTED                   { $$ = make_str("uncommitted"); }
                | UNENCRYPTED                   { $$ = make_str("unencrypted"); }
                | UNKNOWN                       { $$ = make_str("unknown"); }
                | UNLISTEN                      { $$ = make_str("unlisten"); }
                | UNTIL                         { $$ = make_str("until"); }
                | UPDATE                        { $$ = make_str("update"); }
-               | USAGE                         { $$ = make_str("usage"); }
                | 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"); }
                | WRITE                         { $$ = make_str("write"); }
-               | YEAR_P                        { $$ = make_str("year"); }
+/*             | YEAR_P                        { $$ = make_str("year"); }*/
                | ZONE                          { $$ = make_str("zone"); }
                ;
 
@@ -5874,16 +6262,23 @@ col_name_keyword:
                | EXISTS                { $$ = make_str("exists"); }
                | EXTRACT               { $$ = make_str("extract"); }
                | FLOAT_P               { $$ = make_str("float"); }
+               | GREATEST              { $$ = make_str("greatest"); }
+               | INOUT                 { $$ = make_str("inout"); }
 /* INT must be excluded from ECPGColLabel because of conflict
                | INT_P                 { $$ = make_str("int"); }
  */
                | INTEGER               { $$ = make_str("integer"); }
                | INTERVAL              { $$ = make_str("interval"); }
+               | LEAST                 { $$ = make_str("least"); }
+               | NATIONAL              { $$ = make_str("national"); }
                | NCHAR                 { $$ = make_str("nchar"); }
                | NONE                  { $$ = make_str("none"); }
                | NULLIF                { $$ = make_str("nullif"); }
                | NUMERIC               { $$ = make_str("numeric"); }
+               | OUT_P                 { $$ = make_str("out"); }
+               | OVERLAY               { $$ = make_str("overlay"); }
                | POSITION              { $$ = make_str("position"); }
+               | PRECISION             { $$ = make_str("precision"); }
                | REAL                  { $$ = make_str("real"); }
                | ROW                   { $$ = make_str("row"); }
                | SETOF                 { $$ = make_str("setof"); }
@@ -5914,7 +6309,6 @@ func_name_keyword:
                | FREEZE                { $$ = make_str("freeze"); }
                | FULL                  { $$ = make_str("full"); }
                | ILIKE                 { $$ = make_str("ilike"); }
-               | IN_P                  { $$ = make_str("in"); }
                | INNER_P               { $$ = make_str("inner"); }
                | IS                    { $$ = make_str("is"); }
                | ISNULL                { $$ = make_str("isnull"); }
@@ -5945,6 +6339,7 @@ reserved_keyword:
                | ARRAY                         { $$ = make_str("array"); }
                | AS                            { $$ = make_str("as"); }
                | ASC                           { $$ = make_str("asc"); }
+               | ASYMMETRIC                    { $$ = make_str("asymmetric"); }
                | BOTH                          { $$ = make_str("both"); }
                | CASE                          { $$ = make_str("case"); }
                | CAST                          { $$ = make_str("cast"); }
@@ -5956,6 +6351,7 @@ reserved_keyword:
                | CURRENT_DATE                  { $$ = make_str("current_date"); }
                | CURRENT_TIME                  { $$ = make_str("current_time"); }
                | CURRENT_TIMESTAMP             { $$ = make_str("current_timestamp"); }
+               | CURRENT_ROLE                  { $$ = make_str("current_role"); }
                | CURRENT_USER                  { $$ = make_str("current_user"); }
                | DEFAULT                       { $$ = make_str("default"); }
                | DEFERRABLE                    { $$ = make_str("deferrable"); }
@@ -5972,6 +6368,7 @@ reserved_keyword:
                | GRANT                         { $$ = make_str("grant"); }
                | GROUP_P                       { $$ = make_str("group"); }
                | HAVING                        { $$ = make_str("having"); }
+               | IN_P                          { $$ = make_str("in"); }
                | INITIALLY                     { $$ = make_str("initially"); }
                | INTERSECT                     { $$ = make_str("intersect"); }
                | INTO                          { $$ = make_str("into"); }
@@ -5992,9 +6389,12 @@ reserved_keyword:
                | SELECT                        { $$ = make_str("select"); }
                | SESSION_USER                  { $$ = make_str("session_user"); }
                | SOME                          { $$ = make_str("some"); }
+               | SYMMETRIC                     { $$ = make_str("symmetric"); }
                | TABLE                         { $$ = make_str("table"); }
                | THEN                          { $$ = make_str("then"); }
+/* TO must be excluded from ECPGColLabel because of a conflict in variable name parsing
                | TO                            { $$ = make_str("to"); }
+ */
                | TRAILING                      { $$ = make_str("trailing"); }
                | TRUE_P                        { $$ = make_str("true"); }
 /* UNION must be excluded from ECPGColLabel because of conflict with s_union
@@ -6018,37 +6418,66 @@ c_args: /*EMPTY*/               { $$ = EMPTY; }
                | c_list                { $$ = $1; }
                ;
 
-coutputvariable: CVARIABLE indicator
-                       { add_variable(&argsresult, find_variable($1), find_variable($2)); }
-               | CVARIABLE
-                       { add_variable(&argsresult, find_variable($1), &no_indicator); }
+coutputvariable: cvariable indicator
+                       { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
+               | cvariable
+                       { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
                ;
 
 
-civarind: CVARIABLE indicator
+civarind: cvariable indicator
                {
                        if (find_variable($2)->type->type == ECPGt_array)
                                mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
 
-                       add_variable(&argsinsert, find_variable($1), find_variable($2));
+                       add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
                        $$ = create_questionmarks($1, false);
                }
                ;
 
-civar: CVARIABLE
+civar: cvariable
                        {
-                               add_variable(&argsinsert, find_variable($1), &no_indicator);
+                               add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
                                $$ = create_questionmarks($1, false);
                        }
                ;
 
-indicator: CVARIABLE                           { check_indicator((find_variable($1))->type); $$ = $1; }
-               | SQL_INDICATOR CVARIABLE       { check_indicator((find_variable($2))->type); $$ = $2; }
+indicator: cvariable                           { check_indicator((find_variable($1))->type); $$ = $1; }
+               | SQL_INDICATOR cvariable       { check_indicator((find_variable($2))->type); $$ = $2; }
                | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
                ;
 
-ident: IDENT                                           { $$ = $1; }
-               | CSTRING                                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
+cvariable:     CVARIABLE 
+               {
+                       /* As long as multidimensional arrays are not implemented we have to check for those here */
+                       char *ptr = $1;
+                       int brace_open=0, brace = false;
+                       
+                       for (; *ptr; ptr++)
+                       {
+                               switch (*ptr)
+                               {
+                                       case '[':       if (brace)
+                                                       {
+                                                               mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support for simple data types");
+                                                       }
+                                                       brace_open++;
+                                                       break;
+                                       case ']':       brace_open--;
+                                                       if (brace_open == 0) brace = true;
+                                                       break;
+                                       case '\t':
+                                       case ' ':       break;
+                                       default:        if (brace_open == 0) brace = false;
+                                                       break;
+                               }
+                       }
+
+                       $$ = $1;
+               }
+               ;
+ident: IDENT                                   { $$ = $1; }
+               | CSTRING                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
                ;
 
 quoted_ident_stringvar: name
@@ -6121,6 +6550,7 @@ c_anything:  IDENT                                { $$ = $1; }
                | S_STATIC                      { $$ = make_str("static"); }
                | S_SUB                         { $$ = make_str("-="); }
                | S_TYPEDEF                     { $$ = make_str("typedef"); }
+               | S_VOLATILE                    { $$ = make_str("volatile"); }
                | SQL_BOOL                      { $$ = make_str("bool"); }
                | SQL_ENUM                      { $$ = make_str("enum"); }
                | HOUR_P                        { $$ = make_str("hour"); }
@@ -6136,6 +6566,7 @@ c_anything:  IDENT                                { $$ = $1; }
                | YEAR_P                        { $$ = make_str("year"); }
                | CHAR_P                        { $$ = make_str("char"); }
                | FLOAT_P                       { $$ = make_str("float"); }
+               | TO                            { $$ = make_str("to"); }
                | UNION                         { $$ = make_str("union"); }
                | VARCHAR                       { $$ = make_str("varchar"); }
                | '['                           { $$ = make_str("["); }