]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/preproc.y
Add missing semicolon; some bison versions warn of this.
[postgresql] / src / interfaces / ecpg / preproc / preproc.y
1 /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.295 2004/08/28 18:04:51 tgl Exp $ */
2
3 /* Copyright comment */
4 %{
5 #include "postgres_fe.h"
6
7 #include "extern.h"
8
9 /*
10  * Variables containing simple states.
11  */
12 int struct_level = 0;
13 int braces_open; /* brace level counter */
14 int ecpg_informix_var = 0;
15 char    *connection = NULL;
16 char    *input_filename = NULL;
17
18 static int      QueryIsRule = 0, FoundInto = 0;
19 static int      initializer = 0;
20 static struct this_type actual_type[STRUCT_DEPTH];
21 static char *actual_startline[STRUCT_DEPTH];
22
23 /* temporarily store struct members while creating the data structure */
24 struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
25
26 /* also store struct type so we can do a sizeof() later */
27 static char *ECPGstruct_sizeof = NULL;
28
29 /* for forward declarations we have to store some data as well */
30 static char *forward_name = NULL;
31
32 struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}};
33 struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
34
35 struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, NULL, {NULL}};
36
37 static struct inf_compat_col
38 {
39         char *name;
40         char *indirection;
41         struct inf_compat_col *next;
42 } *informix_col;
43
44 static struct inf_compat_val
45 {
46         char *val;
47         struct inf_compat_val *next;
48 } *informix_val;
49
50 /*
51  * Handle parsing errors and warnings
52  */
53 void
54 mmerror(int error_code, enum errortype type, char * error, ...)
55 {
56         va_list ap;
57         
58         fprintf(stderr, "%s:%d: ", input_filename, yylineno);
59         
60         switch(type)
61         {
62                 case ET_WARNING:
63                         fprintf(stderr, "WARNING: ");
64                         break;
65                 case ET_ERROR:
66                 case ET_FATAL:
67                         fprintf(stderr, "ERROR: ");
68                         break;
69         }
70
71         va_start(ap, error);
72         vfprintf(stderr, error, ap);
73         va_end(ap);
74         
75         fprintf(stderr, "\n");
76         
77         switch(type)
78         {
79                 case ET_WARNING:
80                         break;
81                 case ET_ERROR:
82                         ret_value = error_code;
83                         break;
84                 case ET_FATAL:
85                         exit(error_code);
86         }
87 }
88
89 /*
90  * string concatenation
91  */
92
93 static char *
94 cat2_str(char *str1, char *str2)
95 {
96         char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
97
98         strcpy(res_str, str1);
99         strcat(res_str, " ");
100         strcat(res_str, str2);
101         free(str1);
102         free(str2);
103         return(res_str);
104 }
105
106 static char *
107 cat_str(int count, ...)
108 {
109         va_list         args;
110         int                     i;
111         char            *res_str;
112
113         va_start(args, count);
114
115         res_str = va_arg(args, char *);
116
117         /* now add all other strings */
118         for (i = 1; i < count; i++)
119                 res_str = cat2_str(res_str, va_arg(args, char *));
120
121         va_end(args);
122
123         return(res_str);
124 }
125
126 char *
127 make_str(const char *str)
128 {
129         char * res_str = (char *)mm_alloc(strlen(str) + 1);
130
131         strcpy(res_str, str);
132         return res_str;
133 }
134
135 static char *
136 make2_str(char *str1, char *str2)
137 {
138         char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
139
140         strcpy(res_str, str1);
141         strcat(res_str, str2);
142         free(str1);
143         free(str2);
144         return(res_str);
145 }
146
147 static char *
148 make3_str(char *str1, char *str2, char *str3)
149 {
150         char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
151
152         strcpy(res_str, str1);
153         strcat(res_str, str2);
154         strcat(res_str, str3);
155         free(str1);
156         free(str2);
157         free(str3);
158         return(res_str);
159 }
160
161 /* and the rest */
162 static char *
163 make_name(void)
164 {
165         char * name = (char *)mm_alloc(yyleng + 1);
166
167         strncpy(name, yytext, yyleng);
168         name[yyleng] = '\0';
169         return(name);
170 }
171
172 static char *
173 create_questionmarks(char *name, bool array)
174 {
175         struct variable *p = find_variable(name);
176         int count;
177         char *result = EMPTY;
178
179         /* In case we have a struct, we have to print as many "?" as there are attributes in the struct 
180          * An array is only allowed together with an element argument 
181          * This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else 
182          * so we don't have to worry here. */
183         
184         if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
185         {
186                 struct ECPGstruct_member *m;
187
188                 if (p->type->type == ECPGt_struct)
189                         m = p->type->u.members;
190                 else
191                         m = p->type->u.element->u.members;
192
193                 for (count = 0; m != NULL; m=m->next, count++);
194         }
195         else
196                 count = 1;
197
198         for (; count > 0; count --)
199                 result = cat2_str(result, make_str("? , "));
200
201         /* removed the trailing " ," */
202
203         result[strlen(result)-3] = '\0';
204         return(result);
205 }
206
207 static char *
208 adjust_informix(struct arguments *list)
209 {
210         /* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
211          * This breaks standard and leads to some very dangerous programming. 
212          * Since they do, we have to work around and accept their syntax as well.
213          * But we will do so ONLY in Informix mode.
214          * We have to change the variables to our own struct and just store the pointer instead of the variable */
215
216          struct arguments *ptr;
217          char *result = make_str("");
218
219          for (ptr = list; ptr != NULL; ptr = ptr->next)
220          {
221                 char temp[20]; /* this should be sufficient unless you have 8 byte integers */
222                 char *original_var;
223                 
224                 /* change variable name to "ECPG_informix_get_var(<counter>)" */
225                 original_var = ptr->variable->name;
226                 sprintf(temp, "%d))", ecpg_informix_var);
227                 
228                 if ((ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
229                 {
230                         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);
231                         sprintf(temp, "%d, (", ecpg_informix_var++);
232                 }
233                 else
234                 {
235                         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);
236                         sprintf(temp, "%d, &(", ecpg_informix_var++);
237                 }
238                 
239                 /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
240                 result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
241                 
242                 /* now the indicator if there is one */
243                 if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
244                 {
245                         /* change variable name to "ECPG_informix_get_var(<counter>)" */
246                         original_var = ptr->indicator->name;
247                         sprintf(temp, "%d))", ecpg_informix_var);
248                         
249                         /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
250                         if (atoi(ptr->indicator->type->size) > 1)
251                         {
252                                 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);
253                                 sprintf(temp, "%d, (", ecpg_informix_var++);
254                         }
255                         else
256                         {
257                                 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);
258                                 sprintf(temp, "%d, &(", ecpg_informix_var++);
259                         }
260                         result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
261                 }
262          }
263
264          return result;
265 }
266
267 static struct cursor *
268 add_additional_variables(char *name, bool insert)
269 {
270         struct cursor *ptr;
271         struct arguments *p;
272
273         for (ptr = cur; ptr != NULL; ptr=ptr->next)
274         {
275                 if (strcmp(ptr->name, name) == 0)
276                         break;
277         }
278
279         if (ptr == NULL)
280         {
281                 mmerror(PARSE_ERROR, ET_ERROR, "trying to access an undeclared cursor %s\n", name);
282                 return NULL;
283         }
284         if (insert)
285         {
286                 /* add all those input variables that were given earlier 
287                  * note that we have to append here but have to keep the existing order */
288                 for (p = ptr->argsinsert; p; p = p->next)
289                         add_variable_to_tail(&argsinsert, p->variable, p->indicator);
290         }
291
292         /* add all those output variables that were given earlier */
293         for (p = ptr->argsresult; p; p = p->next)
294                 add_variable_to_tail(&argsresult, p->variable, p->indicator);
295         
296         return ptr;
297 }
298 %}
299
300 %union {
301         double  dval;
302         char    *str;
303         int     ival;
304         struct  when            action;
305         struct  index           index;
306         int             tagname;
307         struct  this_type       type;
308         enum    ECPGttype       type_enum;
309         enum    ECPGdtype       dtype_enum;
310         struct  fetch_desc      descriptor;
311         struct  su_symbol       struct_union;
312 }
313
314 /* special embedded SQL token */
315 %token  SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
316                 SQL_CALL SQL_CARDINALITY SQL_CONNECT SQL_CONNECTION
317                 SQL_CONTINUE SQL_COUNT SQL_CURRENT SQL_DATA 
318                 SQL_DATETIME_INTERVAL_CODE
319                 SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE
320                 SQL_DESCRIPTOR SQL_DISCONNECT SQL_ENUM SQL_FOUND
321                 SQL_FREE SQL_GO SQL_GOTO SQL_IDENTIFIED
322                 SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH
323                 SQL_LONG SQL_NAME SQL_NULLABLE SQL_OCTET_LENGTH
324                 SQL_OPEN SQL_OUTPUT SQL_RELEASE SQL_REFERENCE
325                 SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
326                 SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
327                 SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
328                 SQL_STRUCT SQL_UNSIGNED SQL_VALUE SQL_VAR SQL_WHENEVER
329
330 /* C token */
331 %token  S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV
332                 S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
333                 S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
334                 S_STATIC S_SUB S_VOLATILE
335                 S_TYPEDEF
336
337 /* I need this and don't know where it is defined inside the backend */
338 %token  TYPECAST
339
340 /* ordinary key words in alphabetical order */
341 %token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD AFTER
342         AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC
343         ASSERTION ASSIGNMENT AT AUTHORIZATION
344
345         BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
346         BOOLEAN_P BOTH BY
347
348         CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P
349         CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
350         CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
351         COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY
352         CREATE CREATEDB CREATEUSER CROSS CSV CURRENT_DATE CURRENT_TIME
353         CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
354
355         DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
356         DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS
357         DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP
358         EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUSIVE EXCLUDING
359         EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
360
361         FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM
362         FULL FUNCTION
363
364         GET GLOBAL GRANT GROUP_P
365         HANDLER HAVING HOLD HOUR_P
366
367         ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
368         INDEX INHERITS INITIALLY INNER_P INOUT INPUT_P
369         INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
370         INTERVAL INTO INVOKER IS ISNULL ISOLATION
371
372         JOIN
373
374         KEY
375
376         LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT LISTEN
377         LOAD LOCAL LOCATION LOCK_P
378
379         MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
380
381         NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
382         NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P
383         NULLIF NUMERIC
384
385         OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR ORDER
386         OUT_P OUTER_P OVERLAPS OVERLAY OWNER
387
388         PARTIAL PASSWORD PLACING POSITION
389         PRECISION PRESERVE PREPARE PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE
390
391         QUOTE
392
393         READ REAL RECHECK REFERENCES REINDEX RELATIVE_P RENAME REPEATABLE REPLACE
394         RESET RESTART RESTRICT RETURNS REVOKE RIGHT ROLLBACK ROW ROWS RULE
395
396         SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE
397         SESSION SESSION_USER SET SETOF SHARE SHOW SIMILAR SIMPLE SMALLINT SOME
398         STABLE START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P
399         SUBSTRING SYSID
400
401         TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TO TOAST
402         TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P
403         UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USAGE
404         USER USING
405
406         VACUUM VALID VALUES VARCHAR VARYING VERBOSE VIEW VOLATILE
407         WHEN WHERE WITH WITHOUT WORK WRITE
408         YEAR_P
409         ZONE
410
411 /* The grammar thinks these are keywords, but they are not in the keywords.c
412  * list and so can never be entered directly.  The filter in parser.c
413  * creates these tokens when required.
414  */
415 %token  UNIONJOIN
416
417 /* Special token types, not actually keywords - see the "lex" file */
418 %token <str>    IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST XCONST
419 %token <ival>   ICONST PARAM
420 %token <dval>   FCONST
421
422 /* precedence: lowest to highest */
423 %left           UNION EXCEPT
424 %left           INTERSECT
425 %left           OR
426 %left           AND
427 %right          NOT
428 %right          '='
429 %nonassoc       '<' '>'
430 %nonassoc       LIKE ILIKE SIMILAR
431 %nonassoc       ESCAPE
432 %nonassoc       OVERLAPS
433 %nonassoc       BETWEEN
434 %nonassoc       IN_P
435 %left           POSTFIXOP                                       /* dummy for postfix Op rules */
436 %left           Op OPERATOR                             /* multi-character ops and user-defined operators */
437 %nonassoc       NOTNULL
438 %nonassoc       ISNULL
439 %nonassoc       IS NULL_P TRUE_P FALSE_P UNKNOWN
440 %left           '+' '-'
441 %left           '*' '/' '%'
442 %left           '^'
443 /* Unary Operators */
444 %left           AT ZONE
445 %right          UMINUS
446 %left           '[' ']'
447 %left           '(' ')'
448 %left           TYPECAST
449 %left           '.'
450 %left           JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
451
452 %type  <str>    Iconst Fconst Sconst TransactionStmt CreateStmt UserId
453 %type  <str>    CreateAsElement OptCreateAs CreateAsList CreateAsStmt
454 %type  <str>    comment_text ConstraintDeferrabilitySpec TableElementList
455 %type  <str>    key_match ColLabel SpecialRuleRelation ColId columnDef
456 %type  <str>    ColConstraint ColConstraintElem drop_type Bconst Iresult
457 %type  <str>    TableConstraint OptTableElementList Xconst opt_transaction 
458 %type  <str>    ConstraintElem key_actions ColQualList type_name
459 %type  <str>    target_list target_el update_target_list alias_clause
460 %type  <str>    update_target_el qualified_name database_name alter_using
461 %type  <str>    access_method attr_name index_name name func_name
462 %type  <str>    file_name AexprConst c_expr ConstTypename var_list
463 %type  <str>    a_expr b_expr TruncateStmt CommentStmt OnCommitOption opt_by
464 %type  <str>    opt_indirection expr_list extract_list extract_arg
465 %type  <str>    position_list substr_list substr_from alter_column_default
466 %type  <str>    trim_list in_expr substr_for attrs TableFuncElement
467 %type  <str>    Typename SimpleTypename Numeric opt_float opt_numeric
468 %type  <str>    opt_decimal Character character opt_varying opt_charset
469 %type  <str>    opt_timezone opt_interval table_ref fetch_direction
470 %type  <str>    ConstDatetime AlterDomainStmt AlterSeqStmt
471 %type  <str>    SelectStmt into_clause OptTemp ConstraintAttributeSpec
472 %type  <str>    opt_table opt_all sort_clause sortby_list ConstraintAttr
473 %type  <str>    sortby qualified_name_list name_list ColId_or_Sconst
474 %type  <str>    group_clause having_clause from_clause opt_distinct opt_hold
475 %type  <str>    join_outer where_clause relation_expr sub_type arg_class
476 %type  <str>    opt_column_list insert_rest InsertStmt WithOidsAs param_name
477 %type  <str>    columnList DeleteStmt LockStmt UpdateStmt DeclareCursorStmt
478 %type  <str>    NotifyStmt columnElem UnlistenStmt TableElement rowdefinition
479 %type  <str>    copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
480 %type  <str>    FetchStmt from_in CreateOpClassStmt like_including_defaults
481 %type  <str>    ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
482 %type  <str>    opt_full func_arg OptWithOids opt_freeze alter_table_cmd 
483 %type  <str>    analyze_keyword opt_name_list ExplainStmt index_params
484 %type  <str>    index_elem opt_class access_method_clause alter_table_cmds
485 %type  <str>    index_opt_unique IndexStmt func_return ConstInterval
486 %type  <str>    func_args_list func_args opt_with def_arg overlay_placing
487 %type  <str>    def_elem def_list definition DefineStmt select_with_parens
488 %type  <str>    opt_instead event RuleActionList opt_using CreateAssertStmt
489 %type  <str>    RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
490 %type  <str>    RuleStmt opt_column oper_argtypes NumConst var_name
491 %type  <str>    MathOp RemoveFuncStmt aggr_argtype for_update_clause
492 %type  <str>    RemoveAggrStmt opt_procedural select_no_parens CreateCastStmt
493 %type  <str>    RemoveOperStmt RenameStmt all_Op opt_Trusted opt_lancompiler
494 %type  <str>    VariableSetStmt var_value zone_value VariableShowStmt
495 %type  <str>    VariableResetStmt AlterTableStmt from_list overlay_list
496 %type  <str>    user_list OptUserList OptUserElem relation_name OptTableSpace
497 %type  <str>    CreateUserStmt AlterUserStmt CreateSeqStmt OptSeqList
498 %type  <str>    OptSeqElem TriggerForSpec TriggerForOpt TriggerForType
499 %type  <str>    DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt
500 %type  <str>    TriggerActionTime CreateTrigStmt DropPLangStmt DropCastStmt
501 %type  <str>    CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select
502 %type  <str>    ViewStmt LoadStmt CreatedbStmt createdb_opt_item ExplainableStmt
503 %type  <str>    createdb_opt_list opt_encoding OptInherit opt_equal
504 %type  <str>    AlterUserSetStmt privilege_list privilege privilege_target
505 %type  <str>    opt_grant_grant_option opt_revoke_grant_option cursor_options
506 %type  <str>    transaction_mode_list_or_empty transaction_mode_list
507 %type  <str>    function_with_argtypes_list function_with_argtypes IntConstVar
508 %type  <str>    DropdbStmt ClusterStmt grantee RevokeStmt Bit DropOpClassStmt
509 %type  <str>    GrantStmt privileges PosAllConst constraints_set_list
510 %type  <str>    ConstraintsSetStmt AllConst CreateDomainStmt opt_nowait
511 %type  <str>    case_expr when_clause_list case_default case_arg when_clause
512 %type  <str>    select_clause opt_select_limit select_limit_value opt_recheck
513 %type  <str>    ConstraintTimeSpec AlterDatabaseSetStmt DropAssertStmt
514 %type  <str>    select_offset_value ReindexStmt join_type opt_boolean
515 %type  <str>    join_qual update_list joined_table opclass_item fetch_count
516 %type  <str>    opt_lock lock_type OptGroupList OptGroupElem array_expr_list
517 %type  <str>    OptConstrFromTable OptTempTableName StringConst array_expr
518 %type  <str>    constraints_set_mode comment_type opt_empty_parentheses
519 %type  <str>    CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
520 %type  <str>    opt_force key_update CreateSchemaStmt PosIntStringConst
521 %type  <str>    IntConst PosIntConst grantee_list func_type opt_or_replace
522 %type  <str>    select_limit opt_for_update_clause CheckPointStmt
523 %type  <str>    OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior
524 %type  <str>    handler_name any_name_list any_name opt_as insert_column_list
525 %type  <str>    columnref function_name insert_target_el AllConstVar
526 %type  <str>    insert_target_list insert_column_item DropRuleStmt
527 %type  <str>    createfunc_opt_item set_rest var_list_or_default
528 %type  <str>    CreateFunctionStmt createfunc_opt_list func_table
529 %type  <str>    DropUserStmt copy_from copy_opt_list copy_opt_item
530 %type  <str>    opt_oids TableLikeClause key_action opt_definition
531 %type  <str>    cast_context row qual_Op qual_all_Op opt_default
532 %type  <str>    CreateConversionStmt any_operator opclass_item_list
533 %type  <str>    iso_level type_list CharacterWithLength ConstCharacter
534 %type  <str>    CharacterWithoutLength BitWithLength BitWithoutLength
535 %type  <str>    ConstBit GenericType TableFuncElementList opt_analyze
536 %type  <str>    opt_sort_clause transaction_access_mode subquery_Op
537 %type  <str>    ECPGWhenever ECPGConnect connection_target ECPGOpen
538 %type  <str>    indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into 
539 %type  <str>    storage_declaration storage_clause opt_initializer c_anything
540 %type  <str>    variable_list variable c_thing c_term ECPGKeywords_vanames
541 %type  <str>    opt_pointer ECPGDisconnect dis_name storage_modifier
542 %type  <str>    ECPGRelease execstring server_name ECPGVarDeclaration
543 %type  <str>    connection_object opt_server opt_port c_stuff c_stuff_item
544 %type  <str>    user_name opt_user char_variable ora_user ident opt_reference
545 %type  <str>    var_type_declarations quoted_ident_stringvar ECPGKeywords_rest
546 %type  <str>    db_prefix server opt_options opt_connection_name c_list
547 %type  <str>    ECPGSetConnection ECPGTypedef c_args ECPGKeywords ECPGCKeywords
548 %type  <str>    enum_type civar civarind ECPGCursorStmt ECPGDeallocate
549 %type  <str>    ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
550 %type  <str>    struct_union_type s_struct_union vt_declarations execute_rest
551 %type  <str>    var_declaration type_declaration single_vt_declaration
552 %type  <str>    ECPGSetAutocommit on_off variable_declarations ECPGDescribe
553 %type  <str>    ECPGAllocateDescr ECPGDeallocateDescr symbol opt_output
554 %type  <str>    ECPGGetDescriptorHeader ECPGColLabel single_var_declaration
555 %type  <str>    reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using
556 %type  <str>    col_name_keyword func_name_keyword precision opt_scale
557 %type  <str>    ECPGTypeName using_list ECPGColLabelCommon UsingConst
558 %type  <str>    inf_val_list inf_col_list using_descriptor into_descriptor 
559 %type  <str>    prepared_name struct_union_type_with_symbol
560 %type  <str>    ECPGunreserved ECPGunreserved_interval cvariable
561 %type  <str>    AlterOwnerStmt OptTableSpaceOwner CreateTableSpaceStmt
562 %type  <str>    DropTableSpaceStmt indirection indirection_el ECPGSetDescriptorHeader
563
564 %type  <struct_union> s_struct_union_symbol
565
566 %type  <descriptor> ECPGGetDescriptor ECPGSetDescriptor
567
568 %type  <type_enum> simple_type signed_type unsigned_type
569
570 %type  <dtype_enum> descriptor_item desc_header_item
571
572 %type  <type>   var_type 
573
574 %type  <action> action
575
576 %type  <index>  opt_array_bounds 
577
578 %%
579 prog: statements;
580
581 statements: /*EMPTY*/
582                 | statements statement
583                 ;
584
585 statement: ecpgstart opt_at stmt ';'    { connection = NULL; }
586                 | ecpgstart stmt ';'
587                 | ecpgstart ECPGVarDeclaration
588                 {
589                         fprintf(yyout, "%s", $2);
590                         free($2);
591                         output_line_number();
592                 }
593                 | ECPGDeclaration
594                 | c_thing               { fprintf(yyout, "%s", $1); free($1); }
595                 | CPP_LINE              { fprintf(yyout, "%s", $1); free($1); }
596                 | '{'                   { braces_open++; fputs("{", yyout); }
597                 | '}'                   { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); }
598                 ;
599
600 opt_at: AT connection_target
601                 {
602                         connection = $2;
603                         /*
604                          *      Do we have a variable as connection target?
605                          *      Remove the variable from the variable
606                          *      list or else it will be used twice
607                          */
608                         if (argsinsert != NULL)
609                                 argsinsert = NULL;
610                 };
611
612 stmt:  AlterDatabaseSetStmt             { output_statement($1, 0, connection); }
613                 | AlterDomainStmt       { output_statement($1, 0, connection); }
614                 | AlterGroupStmt        { output_statement($1, 0, connection); }
615                 | AlterOwnerStmt        { output_statement($1, 0, connection); }
616                 | AlterSeqStmt          { output_statement($1, 0, connection); }
617                 | AlterTableStmt        { output_statement($1, 0, connection); }
618                 | AlterUserSetStmt      { output_statement($1, 0, connection); }
619                 | AlterUserStmt         { output_statement($1, 0, connection); }
620                 | AnalyzeStmt           { output_statement($1, 0, connection); }
621                 | CheckPointStmt        { output_statement($1, 0, connection); }
622                 | ClosePortalStmt
623                 {
624                         if (INFORMIX_MODE)
625                         {
626                                 /* Informix also has a CLOSE DATABASE command that
627                                    essantially works like a DISCONNECT CURRENT 
628                                    as far as I know. */
629                                 if (pg_strcasecmp($1+strlen("close "), "database") == 0)
630                                 {
631                                         if (connection)
632                                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement.\n");
633                                                                 
634                                         fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
635                                         whenever_action(2);
636                                         free($1);
637                                 }
638                                 else
639                                         output_statement($1, 0, connection);
640                         }
641                         else
642                                 output_statement($1, 0, connection);
643                 }
644                 | ClusterStmt           { output_statement($1, 0, connection); }
645                 | CommentStmt           { output_statement($1, 0, connection); }
646                 | ConstraintsSetStmt    { output_statement($1, 0, connection); }
647                 | CopyStmt              { output_statement($1, 0, connection); }
648                 | CreateAsStmt          { output_statement($1, 0, connection); }
649                 | CreateAssertStmt      { output_statement($1, 0, connection); }
650                 | CreateCastStmt        { output_statement($1, 0, connection); }
651                 | CreateConversionStmt  { output_statement($1, 0, connection); }
652                 | CreateDomainStmt      { output_statement($1, 0, connection); }
653                 | CreateFunctionStmt    { output_statement($1, 0, connection); }
654                 | CreateGroupStmt       { output_statement($1, 0, connection); }
655                 | CreatePLangStmt       { output_statement($1, 0, connection); }
656                 | CreateOpClassStmt     { output_statement($1, 0, connection); }
657                 | CreateSchemaStmt      { output_statement($1, 0, connection); }
658                 | CreateSeqStmt         { output_statement($1, 0, connection); }
659                 | CreateStmt            { output_statement($1, 0, connection); }
660                 | CreateTrigStmt        { output_statement($1, 0, connection); }
661                 | CreateTableSpaceStmt  { output_statement($1, 0, connection); }
662                 | CreateUserStmt        { output_statement($1, 0, connection); }
663                 | CreatedbStmt          { output_statement($1, 0, connection); }
664                 /*| DeallocateStmt      { output_statement($1, 0, connection); }*/
665                 | DeclareCursorStmt     { output_simple_statement($1); }
666                 | DefineStmt            { output_statement($1, 0, connection); }
667                 | DeleteStmt            { output_statement($1, 1, connection); }
668                 | DropAssertStmt        { output_statement($1, 0, connection); }
669                 | DropCastStmt          { output_statement($1, 0, connection); }
670                 | DropGroupStmt         { output_statement($1, 0, connection); }
671                 | DropOpClassStmt       { output_statement($1, 0, connection); }
672                 | DropPLangStmt         { output_statement($1, 0, connection); }
673                 | DropRuleStmt          { output_statement($1, 0, connection); }
674                 | DropStmt              { output_statement($1, 0, connection); }
675                 | DropTableSpaceStmt    { output_statement($1, 0, connection); }
676                 | DropTrigStmt          { output_statement($1, 0, connection); }
677                 | DropUserStmt          { output_statement($1, 0, connection); }
678                 | DropdbStmt            { output_statement($1, 0, connection); }
679                 | ExplainStmt           { output_statement($1, 0, connection); }
680 /*              | ExecuteStmt           { output_statement($1, 0, connection); }*/
681                 | FetchStmt             { output_statement($1, 1, connection); }
682                 | GrantStmt             { output_statement($1, 0, connection); }
683                 | IndexStmt             { output_statement($1, 0, connection); }
684                 | InsertStmt            { output_statement($1, 1, connection); }
685                 | ListenStmt            { output_statement($1, 0, connection); }
686                 | LoadStmt              { output_statement($1, 0, connection); }
687                 | LockStmt              { output_statement($1, 0, connection); }
688                 | NotifyStmt            { output_statement($1, 0, connection); }
689 /*              | PrepareStmt           { output_statement($1, 0, connection); }*/
690                 | ReindexStmt           { output_statement($1, 0, connection); }
691                 | RemoveAggrStmt        { output_statement($1, 0, connection); }
692                 | RemoveOperStmt        { output_statement($1, 0, connection); }
693                 | RemoveFuncStmt        { output_statement($1, 0, connection); }
694                 | RenameStmt            { output_statement($1, 0, connection); }
695                 | RevokeStmt            { output_statement($1, 0, connection); }
696                 | RuleStmt              { output_statement($1, 0, connection); }
697                 | SelectStmt            { output_statement($1, 1, connection); }
698                 | TransactionStmt
699                 {
700                         fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
701                         whenever_action(2);
702                         free($1);
703                 }
704                 | TruncateStmt          { output_statement($1, 0, connection); }
705                 | UnlistenStmt          { output_statement($1, 0, connection); }
706                 | UpdateStmt            { output_statement($1, 1, connection); }
707                 | VacuumStmt            { output_statement($1, 0, connection); }
708                 | VariableSetStmt       { output_statement($1, 0, connection); }
709                 | VariableShowStmt      { output_statement($1, 0, connection); }
710                 | VariableResetStmt     { output_statement($1, 0, connection); }
711                 | ViewStmt              { output_statement($1, 0, connection); }
712                 | ECPGAllocateDescr
713                 {
714                         fprintf(yyout,"ECPGallocate_desc(__LINE__, %s);",$1);
715                         whenever_action(0);
716                         free($1);
717                 }
718                 | ECPGConnect
719                 {
720                         if (connection)
721                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n");
722
723                         fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
724                         reset_variables();
725                         whenever_action(2);
726                         free($1);
727                 }
728                 | ECPGCursorStmt
729                 {
730                         output_simple_statement($1);
731                 }
732                 | ECPGDeallocate
733                 {
734                         if (connection)
735                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement.\n");
736                         fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s);", compat, $1);
737                         whenever_action(2);
738                         free($1);
739                 }
740                 | ECPGDeallocateDescr
741                 {
742                         if (connection)
743                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement.\n");
744                         fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1);
745                         whenever_action(0);
746                         free($1);
747                 }
748                 | ECPGDeclare
749                 {
750                         output_simple_statement($1);
751                 }
752                 | ECPGDescribe
753                 {
754                         fprintf(yyout, "{ ECPGdescribe(__LINE__, %s,", $1);
755                         dump_variables(argsresult, 1);
756                         fputs("ECPGt_EORT);", yyout);
757                         fprintf(yyout, "}");
758                         output_line_number();
759                                 
760                         /* whenever_action(2); */
761                         free($1);
762                 }
763                 | ECPGDisconnect
764                 {
765                         if (connection)
766                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement.\n");
767
768                         fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);",
769                                         $1 ? $1 : "\"CURRENT\"");
770                         whenever_action(2);
771                         free($1);
772                 }
773                 | ECPGExecute
774                 {
775                         output_statement($1, 0, connection);
776                 }
777                 | ECPGFree
778                 {
779                         fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, \"%s\");", compat, $1);
780
781                         whenever_action(2);
782                         free($1);
783                 }
784                 | ECPGGetDescriptor
785                 {
786                         lookup_descriptor($1.name, connection);
787                         output_get_descr($1.name, $1.str);
788                         free($1.name);
789                         free($1.str);
790                 }
791                 | ECPGGetDescriptorHeader
792                 {
793                         lookup_descriptor($1, connection);
794                         output_get_descr_header($1);
795                         free($1);
796                 }
797                 | ECPGOpen
798                 {
799                         struct cursor *ptr;
800
801                         if ((ptr = add_additional_variables($1, true)) != NULL)
802                                 output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL);
803                         ptr->opened = true;
804                 }
805                 | ECPGPrepare
806                 {
807                         if (connection)
808                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for prepare statement.\n");
809
810                         fprintf(yyout, "{ ECPGprepare(__LINE__, %s);", $1);
811                         whenever_action(2);
812                         free($1);
813                 }
814                 | ECPGRelease           { /* output already done */ }
815                 | ECPGSetAutocommit
816                 {
817                         fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
818                         whenever_action(2);
819                         free($1);
820                 }
821                 | ECPGSetConnection
822                 {
823                         if (connection)
824                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement.\n");
825
826                         fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
827                         whenever_action(2);
828                         free($1);
829                 }
830                 | ECPGSetDescriptor
831                 {
832                         lookup_descriptor($1.name, connection);
833                         output_set_descr($1.name, $1.str);
834                         free($1.name);
835                         free($1.str);
836                 }
837                 | ECPGSetDescriptorHeader
838                 {
839                         lookup_descriptor($1, connection);
840                         output_set_descr_header($1);
841                         free($1);
842                 }
843                 | ECPGTypedef
844                 {
845                         if (connection)
846                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement.\n");
847
848                         fprintf(yyout, "%s", $1);
849                         free($1);
850                         output_line_number();
851                 }
852                 | ECPGVar
853                 {
854                         if (connection)
855                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement.\n");
856
857                         output_simple_statement($1);
858                 }
859                 | ECPGWhenever
860                 {
861                         if (connection)
862                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement.\n");
863
864                         output_simple_statement($1);
865                 }
866                 ;
867
868
869 /*
870  * We start with a lot of stuff that's very similar to the backend's parsing
871  */
872
873 /*****************************************************************************
874  *
875  * Create a new Postgres DBMS user
876  *
877  *
878  *****************************************************************************/
879
880 CreateUserStmt: CREATE USER UserId opt_with OptUserList
881                         { $$ = cat_str(4, make_str("create user"), $3, make_str("with"), $5); }
882                 ;
883
884 opt_with:  WITH                 { $$ = make_str("with"); }
885                 | /*EMPTY*/     { $$ = EMPTY; }
886                 ;
887
888
889 /*****************************************************************************
890  *
891  * Alter a postgresql DBMS user
892  *
893  *
894  *****************************************************************************/
895
896 AlterUserStmt: ALTER USER UserId OptUserList
897                         { $$ = cat_str(3, make_str("alter user"), $3, $4); }
898                 | ALTER USER UserId WITH OptUserList
899                         { $$ = cat_str(4, make_str("alter user"), $3, make_str("with"), $5); }
900                 ;
901
902 AlterUserSetStmt: ALTER USER UserId SET set_rest
903                         { $$ = cat_str(4, make_str("alter user"), $3, make_str("set"), $5); }
904                 | ALTER USER UserId VariableResetStmt
905                         { $$ = cat_str(3, make_str("alter user"), $3, $4); }
906                 ;
907
908 /*****************************************************************************
909  *
910  * Drop a postgresql DBMS user
911  *
912  *
913  *****************************************************************************/
914 DropUserStmt:  DROP USER user_list
915                         { $$ = cat2_str(make_str("drop user"), $3);}
916                 ;
917 /*
918  * Options for CREATE USER and ALTER USER
919  */
920
921 OptUserList: OptUserList OptUserElem    { $$ = cat2_str($1, $2); }
922                 | /* EMPTY */                                   { $$ = EMPTY; }
923                 ;
924
925 OptUserElem:  PASSWORD Sconst
926                 { $$ = cat2_str(make_str("password"), $2); }
927                 | SYSID PosIntConst
928                         { $$ = cat2_str(make_str("sysid"), $2); }
929                 | CREATEDB
930                         { $$ = make_str("createdb"); }
931                 | NOCREATEDB
932                         { $$ = make_str("nocreatedb"); }
933                 | CREATEUSER
934                         { $$ = make_str("createuser"); }
935                 | NOCREATEUSER
936                         { $$ = make_str("nocreateuser"); }
937                 | IN_P GROUP_P user_list
938                         { $$ = cat2_str(make_str("in group"), $3); }
939                 | VALID UNTIL Sconst
940                         { $$ = cat2_str(make_str("valid until"), $3); }
941                 ;
942
943 user_list:      user_list ',' UserId
944                         { $$ = cat_str(3, $1, make_str(","), $3); }
945                 | UserId
946                         { $$ = $1; }
947                 ;
948
949 /*****************************************************************************
950  *
951  * Create a postgresql group
952  *
953  *
954  ****************************************************************************/
955 CreateGroupStmt:  CREATE GROUP_P UserId OptGroupList
956                         { $$ = cat_str(3, make_str("create group"), $3, $4); }
957                 | CREATE GROUP_P UserId WITH OptGroupList
958                         { $$ = cat_str(4, make_str("create group"), $3, make_str("with"), $5); }
959                 ;
960
961 /*
962  * Options for CREATE GROUP
963  */
964 OptGroupList: OptGroupList OptGroupElem         { $$ = cat2_str($1, $2); }
965                 | /* EMPTY */                                           { $$ = EMPTY; }
966                 ;
967
968 OptGroupElem:  USER user_list
969                         { $$ = cat2_str(make_str("user"), $2); }
970                 | SYSID PosIntConst
971                         { $$ = cat2_str(make_str("sysid"), $2); }
972                 ;
973
974
975 /*****************************************************************************
976  *
977  * Alter a postgresql group
978  *
979  *
980  *****************************************************************************/
981 AlterGroupStmt: ALTER GROUP_P UserId ADD USER user_list
982                         { $$ = cat_str(4, make_str("alter group"), $3, make_str("add user"), $6); }
983                 | ALTER GROUP_P UserId DROP USER user_list
984                         { $$ = cat_str(4, make_str("alter group"), $3, make_str("drop user"), $6); }
985                 ;
986
987 /*****************************************************************************
988  *
989  * Drop a postgresql group
990  *
991  *
992  *****************************************************************************/
993 DropGroupStmt: DROP GROUP_P UserId
994                         { $$ = cat2_str(make_str("drop group"), $3); }
995                 ;
996
997 /*****************************************************************************
998  *
999  * Manipulate a schema
1000  *
1001  *
1002  *****************************************************************************/
1003
1004 CreateSchemaStmt:  CREATE SCHEMA OptSchemaName AUTHORIZATION UserId OptTableSpace OptSchemaEltList
1005                         { $$ = cat_str(6, make_str("create schema"), $3, make_str("authorization"), $5, $6, $7); }
1006                 | CREATE SCHEMA ColId OptTableSpace OptSchemaEltList
1007                         { $$ = cat_str(4, make_str("create schema"), $3, $4, $5); }
1008                 ;
1009
1010 OptSchemaName: ColId            { $$ = $1; }
1011                | /* EMPTY */   { $$ = EMPTY; }
1012                ;
1013
1014 OptSchemaEltList: OptSchemaEltList schema_stmt         { $$ = cat2_str($1, $2); }
1015                 | /* EMPTY */   { $$ = EMPTY; }
1016                 ;
1017
1018 /*
1019  *     schema_stmt are the ones that can show up inside a CREATE SCHEMA
1020  *     statement (in addition to by themselves).
1021  */
1022 schema_stmt: CreateStmt         { $$ = $1; }
1023                | IndexStmt      { $$ = $1; }
1024                | CreateSeqStmt  { $$ = $1; }
1025                | CreateTrigStmt { $$ = $1; }
1026                | GrantStmt      { $$ = $1; }
1027                | ViewStmt       { $$ = $1; }
1028                ;
1029
1030
1031
1032 /*****************************************************************************
1033  *
1034  * Set PG internal variable
1035  *        SET name TO 'var_value'
1036  * Include SQL92 syntax (thomas 1997-10-22):
1037  *        SET TIME ZONE 'var_value'
1038  *
1039  *****************************************************************************/
1040 VariableSetStmt:  SET set_rest
1041                         { $$ = cat2_str(make_str("set"), $2 ); }
1042                 | SET LOCAL set_rest
1043                         { $$ = cat2_str(make_str("set local"), $3 ); }
1044                 | SET SESSION set_rest
1045                         { $$ = cat2_str(make_str("set session"), $3 ); }
1046                 ;
1047
1048 set_rest:       var_name TO var_list_or_default
1049                         { $$ = cat_str(3, $1, make_str("to"), $3); }
1050                 | var_name "=" var_list_or_default
1051                         { $$ = cat_str(3, $1, make_str("="), $3); }
1052                 | TIME ZONE zone_value
1053                         { $$ = cat2_str(make_str("time zone"), $3); }
1054                 | TRANSACTION transaction_mode_list
1055                         { $$ = cat2_str(make_str("transaction"), $2); }
1056                 | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list
1057                         { $$ = cat2_str(make_str("session characteristics as transaction"), $5); }
1058                 | NAMES opt_encoding
1059                         { $$ = cat2_str(make_str("names"), $2); }
1060                 | SESSION AUTHORIZATION ColId_or_Sconst
1061                         { $$ = cat2_str(make_str("session authorization"), $3); }
1062                 | SESSION AUTHORIZATION DEFAULT
1063                         { $$ = make_str("session authorization default"); }
1064                 ;
1065
1066 var_name:       ColId                   { $$ = $1; }
1067                 | var_name '.' ColId    { $$ = cat_str(3, $1, make_str("."), $3); }
1068                 ;
1069                 
1070
1071 var_list_or_default:  var_list
1072                         { $$ = $1; }
1073                 | DEFAULT
1074                         { $$ = make_str("default"); }
1075                 ;
1076
1077 var_list:  var_value
1078                         { $$ = $1; }
1079                 | var_list ',' var_value
1080                         { $$ = cat_str(3, $1, make_str(","), $3); }
1081                 ;
1082
1083 iso_level:      READ UNCOMMITTED        { $$ = make_str("read uncommitted"); }
1084                 | READ COMMITTED        { $$ = make_str("read committed"); }
1085                 | REPEATABLE READ       { $$ = make_str("repeatable read"); }
1086                 | SERIALIZABLE          { $$ = make_str("serializable"); }
1087                 ;
1088
1089 var_value:      opt_boolean             { $$ = $1; }
1090                 | AllConst              { $$ = $1; }
1091                 | ColId                 { $$ = $1; }
1092                 ;
1093
1094 opt_boolean:  TRUE_P            { $$ = make_str("true"); }
1095                 | FALSE_P                       { $$ = make_str("false"); }
1096                 | ON                            { $$ = make_str("on"); }
1097                 | OFF                           { $$ = make_str("off"); }
1098                 ;
1099 /* Timezone values can be:
1100  * - a string such as 'pst8pdt'
1101  * - a column identifier such as "pst8pdt"
1102  * - an integer or floating point number
1103  * - a time interval per SQL99
1104  * ConstInterval and ColId give shift/reduce errors,
1105  * so use IDENT and reject anything which is a reserved word.
1106  */
1107 zone_value:  AllConst           { $$ = $1; }
1108                 | ident         { $$ = $1; }
1109                 | ConstInterval StringConst opt_interval
1110                         { $$ = cat_str(3, $1, $2, $3); }
1111                 | ConstInterval '(' PosIntConst ')' StringConst opt_interval
1112                         { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
1113                 | DEFAULT
1114                         { $$ = make_str("default"); }
1115                 | LOCAL
1116                         { $$ = make_str("local"); }
1117                 ;
1118
1119 opt_encoding:   StringConst             { $$ = $1; }
1120                 | DEFAULT                               { $$ = make_str("default"); }
1121                 | /*EMPTY*/                             { $$ = EMPTY; }
1122                 ;
1123
1124 ColId_or_Sconst: ColId                  { $$ = $1; }
1125                 | StringConst                   { $$ = $1; }
1126                 ;
1127
1128 VariableShowStmt:  SHOW ColId
1129                         { $$ = cat2_str(make_str("show"), $2); }
1130                 | SHOW TIME ZONE
1131                         { $$ = make_str("show time zone"); }
1132                 | SHOW TRANSACTION ISOLATION LEVEL
1133                         { $$ = make_str("show transaction isolation level"); }
1134                 | SHOW SESSION AUTHORIZATION
1135                         { $$ = make_str("show session authorization"); }
1136                 | SHOW ALL
1137                         { $$ = make_str("show all"); }
1138                 ;
1139
1140 VariableResetStmt:      RESET ColId
1141                         { $$ = cat2_str(make_str("reset"), $2); }
1142                 | RESET TIME ZONE
1143                         { $$ = make_str("reset time zone"); }
1144                 | RESET TRANSACTION ISOLATION LEVEL
1145                         { $$ = make_str("reset transaction isolation level"); }
1146                 | RESET SESSION AUTHORIZATION
1147                         { $$ = make_str("reset session authorization"); }
1148                 | RESET ALL
1149                         { $$ = make_str("reset all"); }
1150                 ;
1151
1152 ConstraintsSetStmt:    SET CONSTRAINTS constraints_set_list constraints_set_mode
1153                         { $$ = cat_str(3, make_str("set constraints"), $3, $4); }
1154                 ;
1155
1156 constraints_set_list:  ALL
1157                         { $$ = make_str("all"); }
1158                 | name_list
1159                         { $$ = $1; }
1160                 ;
1161
1162 constraints_set_mode:  DEFERRED         { $$ = make_str("deferred"); }
1163                 | IMMEDIATE             { $$ = make_str("immediate"); }
1164                 ;
1165
1166 /*
1167  * Checkpoint statement
1168  */
1169 CheckPointStmt: CHECKPOINT         { $$= make_str("checkpoint"); }
1170                 ;
1171
1172
1173 /*****************************************************************************
1174  *
1175  *      ALTER TABLE variations
1176  *
1177  *****************************************************************************/
1178
1179 AlterTableStmt:
1180                 ALTER TABLE relation_expr alter_table_cmds
1181                         { $$ = cat_str(3, make_str("alter table"), $3, $4); }
1182                 ;
1183
1184 alter_table_cmds:
1185                 alter_table_cmd                         { $$ = $1; }
1186                 | alter_table_cmds ',' alter_table_cmd  { $$ = cat_str(3, $1, make_str(","), $3); }
1187                 ;
1188
1189 alter_table_cmd:
1190                 ADD opt_column columnDef
1191 /* ALTER TABLE <relation> ADD [COLUMN] <coldef> */
1192                         { $$ = cat_str(3, make_str("add"), $2, $3); }
1193 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP DEFAULT} */
1194                 | ALTER opt_column ColId alter_column_default
1195                         { $$ = cat_str(4, make_str("alter"), $2, $3, $4); }
1196 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> DROP NOT NULL */
1197                 | ALTER opt_column ColId DROP NOT NULL_P
1198                         { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("drop not null")); }
1199 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET NOT NULL */
1200                 | ALTER opt_column ColId SET NOT NULL_P
1201                         { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("set not null")); }
1202 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STATISTICS <IntegerOnly> */
1203                 | ALTER opt_column ColId SET STATISTICS PosIntConst
1204                         { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set statistics"), $6); }
1205 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
1206                 | ALTER opt_column ColId SET STORAGE ColId
1207                         { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set storage"), $6); }
1208 /* ALTER TABLE <relation> DROP [COLUMN] <colname> {RESTRICT|CASCADE} */
1209                 | DROP opt_column ColId opt_drop_behavior
1210                         { $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
1211 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> TYPE <typename> [ USING <expression> ] */
1212                 | ALTER opt_column ColId TYPE_P Typename alter_using
1213                         { $$ = cat_str(6, make_str("alter"), $2, $3, make_str("type"), $5, $6); }
1214 /* ALTER TABLE <relation> ADD CONSTRAINT ... */
1215                 | ADD TableConstraint
1216                         { $$ = cat_str(2, make_str("add"), $2); }
1217 /* ALTER TABLE <relation> DROP CONSTRAINT ... */
1218                 | DROP CONSTRAINT name opt_drop_behavior
1219                         { $$ = cat_str(3, make_str("drop constraint"), $3, $4); }
1220 /* ALTER TABLE <relation> SET WITHOUT OIDS  */
1221                 | SET WITHOUT OIDS
1222                         { $$ = make_str("set without oids"); }
1223  /* ALTER TABLE <name> CREATE TOAST TABLE */
1224                 | CREATE TOAST TABLE
1225                         { $$ = make_str("create toast table"); }
1226 /* ALTER TABLE <name> OWNER TO UserId */
1227                 | OWNER TO UserId
1228                         { $$ = cat_str(2, make_str("owner to"), $3); }
1229 /* ALTER TABLE <name> CLUSTER ON <indexname> */
1230                 | CLUSTER ON name
1231                         { $$ = cat_str(2, make_str("cluster on"), $3); }
1232 /* ALTER TABLE <name> SET WITHOUT CLUSTER */
1233                 | SET WITHOUT CLUSTER
1234                         { $$ = make_str("set without cluster"); }
1235                 /* ALTER TABLE <name> SET TABLESPACE <tablespacename> */
1236                 | SET TABLESPACE name
1237                         { $$ = cat_str(2, make_str("set tablespace"), $3); }
1238                 ;
1239
1240 alter_column_default:
1241                 SET DEFAULT a_expr              { $$ = cat2_str(make_str("set default"), $3); }
1242                 | DROP DEFAULT                  { $$ = make_str("drop default"); }
1243                 ;
1244
1245 opt_drop_behavior: CASCADE                      { $$ = make_str("cascade"); }
1246                 | RESTRICT                      { $$ = make_str("restrict"); }
1247                 | /* EMPTY */                   { $$ = EMPTY; }
1248                 ;
1249
1250 alter_using:    USING a_expr                    { $$ = cat2_str(make_str("using"), $2); }
1251                 | /* EMPTY */                   { $$ = EMPTY; }
1252                 ;
1253                                 
1254 /*****************************************************************************
1255  *
1256  *              QUERY :
1257  *                              close <portalname>
1258  *
1259  *****************************************************************************/
1260
1261 ClosePortalStmt:  CLOSE name
1262                 {
1263                         $$ = cat2_str(make_str("close"), $2);
1264                 }
1265                 ;
1266
1267 /*****************************************************************************
1268  *
1269  *              QUERY :
1270  *                              COPY [BINARY] <relname> FROM/TO
1271  *                              [USING DELIMITERS <delimiter>]
1272  *
1273  *****************************************************************************/
1274
1275 CopyStmt:  COPY opt_binary qualified_name opt_oids copy_from
1276                 copy_file_name copy_delimiter opt_with copy_opt_list
1277                         { $$ = cat_str(9, make_str("copy"), $2, $3, $4, $5, $6, $7, $8, $9); }
1278                 ;
1279
1280 copy_from:      TO                                      { $$ = make_str("to"); }
1281                 | FROM                                  { $$ = make_str("from"); }
1282                 ;
1283
1284 /*
1285  * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
1286  * used depends on the direction. (It really doesn't make sense to copy from
1287  * stdout. We silently correct the "typo".               - AY 9/94
1288  */
1289 copy_file_name:  StringConst    { $$ = $1; }
1290                 | STDIN                                 { $$ = make_str("stdin"); }
1291                 | STDOUT                                { $$ = make_str("stdout"); }
1292                 ;
1293
1294 copy_opt_list: copy_opt_list copy_opt_item      { $$ = cat2_str($1, $2); }
1295                 | /* EMPTY */                   { $$ = EMPTY; }
1296                 ;
1297
1298 copy_opt_item:  BINARY          { $$ = make_str("binary"); }
1299                 | OIDS          { $$ = make_str("oids"); }
1300                 | DELIMITER opt_as StringConst
1301                         { $$ = cat_str(3, make_str("delimiter"), $2, $3); }
1302                 | NULL_P opt_as StringConst
1303                         { $$ = cat_str(3, make_str("null"), $2, $3); }
1304                 | CSV           { $$ = make_str("csv"); }
1305                 | QUOTE opt_as Sconst
1306                         { $$ = cat_str(3, make_str("quote"), $2, $3); }
1307                 | ESCAPE opt_as Sconst
1308                         { $$ = cat_str(3, make_str("escape"), $2, $3); }
1309                 | FORCE QUOTE columnList
1310                         { $$ = cat2_str(make_str("force quote"), $3); }
1311                 | FORCE NOT NULL_P columnList
1312                         { $$ = cat2_str(make_str("force not null"), $4); }
1313                 
1314                 ;
1315
1316 opt_binary:     BINARY          { $$ = make_str("binary"); }
1317                 | /* EMPTY */   { $$ = EMPTY; }
1318                 ;
1319
1320 opt_oids:       WITH OIDS       { $$ = make_str("with oids"); }
1321                 | /* EMPTY */   { $$ = EMPTY; }
1322                 ;
1323
1324
1325 /*
1326  * the default copy delimiter is tab but the user can configure it
1327  */
1328 copy_delimiter:  opt_using DELIMITERS StringConst
1329                         { $$ = cat_str(3, $1, make_str("delimiters"), $3); }
1330                 | /*EMPTY*/
1331                         { $$ = EMPTY; }
1332                 ;
1333
1334 opt_using:      USING           { $$ = make_str("using"); }
1335                 | /* EMPTY */   { $$ = EMPTY; }
1336                 ;
1337
1338 /*****************************************************************************
1339  *
1340  *              QUERY :
1341  *                              CREATE TABLE relname
1342  *
1343  *****************************************************************************/
1344
1345 CreateStmt:  CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
1346                                 OptInherit OptWithOids OnCommitOption OptTableSpace
1347                         { $$ = cat_str(11, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9, $10, $11); }
1348                 | CREATE OptTemp TABLE qualified_name OF qualified_name
1349                         '(' OptTableElementList ')' OptWithOids OnCommitOption OptTableSpace
1350                         { $$ = cat_str(12, make_str("create"), $2, make_str("table"), $4, make_str("of"), $6, make_str("("), $8, make_str(")"), $10, $11, $12); }
1351                 ;
1352
1353 /*
1354  * Redundancy here is needed to avoid shift/reduce conflicts,
1355  * since TEMP is not a reserved word.  See also OptTempTableName.
1356  */
1357
1358 OptTemp: TEMPORARY                      { $$ = make_str("temporary"); }
1359                 | TEMP                  { $$ = make_str("temp"); }
1360                 | LOCAL TEMPORARY       { $$ = make_str("local temporary"); }
1361                 | LOCAL TEMP            { $$ = make_str("local temp"); }
1362                 | GLOBAL TEMPORARY      { $$ = make_str("global temporary"); }
1363                 | GLOBAL TEMP           { $$ = make_str("global temp"); }
1364                 | /*EMPTY*/             { $$ = EMPTY; }
1365                 ;
1366
1367
1368 OptTableElementList:  TableElementList
1369                         { $$ = $1; }
1370                 | /*EMPTY*/
1371                         { $$ = EMPTY; }
1372                 ;
1373 TableElementList: TableElement
1374                         { $$ = $1; }
1375                 | TableElementList ',' TableElement
1376                         { $$ = cat_str(3, $1, make_str(","), $3); }
1377                 ;
1378
1379 TableElement:  columnDef                { $$ = $1; }
1380                 | TableLikeClause       { $$ = $1; }
1381                 | TableConstraint       { $$ = $1; }
1382                 ;
1383
1384 columnDef:      ColId Typename ColQualList 
1385                 {
1386                         $$ = cat_str(3, $1, $2, $3);
1387                 }
1388                 ;
1389
1390 ColQualList:  ColQualList ColConstraint { $$ = cat2_str($1,$2); }
1391                 | /*EMPTY*/                                             { $$ = EMPTY; }
1392                 ;
1393
1394 ColConstraint:  CONSTRAINT name ColConstraintElem
1395                         { $$ = cat_str(3, make_str("constraint"), $2, $3); }
1396                 | ColConstraintElem             { $$ = $1; }
1397                 | ConstraintAttr                { $$ = $1; }
1398                 ;
1399
1400 /* DEFAULT NULL is already the default for Postgres.
1401  * But define it here and carry it forward into the system
1402  * to make it explicit.
1403  * - thomas 1998-09-13
1404  *
1405  * WITH NULL and NULL are not SQL92-standard syntax elements,
1406  * so leave them out. Use DEFAULT NULL to explicitly indicate
1407  * that a column may have that value. WITH NULL leads to
1408  * shift/reduce conflicts with WITH TIME ZONE anyway.
1409  * - thomas 1999-01-08
1410  */
1411 ColConstraintElem:      NOT NULL_P
1412                         { $$ = make_str("not null"); }
1413                 | NULL_P
1414                         { $$ = make_str("null"); }
1415                 | UNIQUE
1416                         { $$ = make_str("unique"); }
1417                 | PRIMARY KEY
1418                         { $$ = make_str("primary key"); }
1419                 | CHECK '(' a_expr ')'
1420                         { $$ = cat_str(3, make_str("check ("), $3, make_str(")")); }
1421                 | DEFAULT b_expr
1422                         { $$ = cat2_str(make_str("default"), $2); }
1423                 |  REFERENCES qualified_name opt_column_list key_match key_actions
1424                         { $$ = cat_str(5, make_str("references"), $2, $3, $4, $5); }
1425                 ;
1426
1427 /*
1428  * ConstraintAttr represents constraint attributes, which we parse as if
1429  * they were independent constraint clauses, in order to avoid shift/reduce
1430  * conflicts (since NOT might start either an independent NOT NULL clause
1431  * or an attribute).  analyze.c is responsible for attaching the attribute
1432  * information to the preceding "real" constraint node, and for complaining
1433  * if attribute clauses appear in the wrong place or wrong combinations.
1434  *
1435  * See also ConstraintAttributeSpec, which can be used in places where
1436  * there is no parsing conflict.
1437  */
1438 ConstraintAttr: DEFERRABLE              { $$ = make_str("deferrable"); }
1439                 | NOT DEFERRABLE                { $$ = make_str("not deferrable"); }
1440                 | INITIALLY DEFERRED    { $$ = make_str("initially deferred"); }
1441                 | INITIALLY IMMEDIATE   { $$ = make_str("initially immediate"); }
1442                 ;
1443
1444 TableLikeClause:  LIKE qualified_name like_including_defaults
1445                 {
1446                         $$ = cat_str(3, make_str("like"), $2, $3);
1447                 }
1448                 ;
1449
1450 like_including_defaults:
1451                 INCLUDING DEFAULTS      { $$ = make_str("including defaults"); }
1452               | EXCLUDING DEFAULTS      { $$ = make_str("excluding defaults"); }
1453               | /* EMPTY */             { $$ = EMPTY; } 
1454               ;
1455
1456 /* ConstraintElem specifies constraint syntax which is not embedded into
1457  *      a column definition. ColConstraintElem specifies the embedded form.
1458  * - thomas 1997-12-03
1459  */
1460 TableConstraint:  CONSTRAINT name ConstraintElem
1461                         { $$ = cat_str(3, make_str("constraint"), $2, $3); }
1462                 | ConstraintElem
1463                         { $$ = $1; }
1464                 ;
1465
1466 ConstraintElem:  CHECK '(' a_expr ')'
1467                         { $$ = cat_str(3, make_str("check("), $3, make_str(")")); }
1468                 | UNIQUE '(' columnList ')'
1469                         { $$ = cat_str(3, make_str("unique("), $3, make_str(")")); }
1470                 | PRIMARY KEY '(' columnList ')'
1471                         { $$ = cat_str(3, make_str("primary key("), $4, make_str(")")); }
1472                 | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name opt_column_list
1473                         key_match key_actions ConstraintAttributeSpec
1474                         { $$ = cat_str(8, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10, $11); }
1475                 ;
1476
1477 opt_column_list:  '(' columnList ')'    { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1478                | /*EMPTY*/              { $$ = EMPTY; }
1479                ;
1480
1481 columnList:  columnList ',' columnElem
1482                                { $$ = cat_str(3, $1, make_str(","), $3); }
1483                | columnElem
1484                                { $$ = $1; }
1485                ;
1486
1487 columnElem:  ColId      { $$ = $1; }
1488                 ;
1489
1490 key_match:      MATCH FULL
1491                         { $$ = make_str("match full"); }
1492                 | MATCH PARTIAL
1493                 {
1494                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend");
1495                         $$ = make_str("match partial");
1496                 }
1497                 | /*EMPTY*/
1498                         { $$ = EMPTY; }
1499                 ;
1500
1501 key_actions:  key_delete                        { $$ = $1; }
1502                 | key_update                            { $$ = $1; }
1503                 | key_delete key_update         { $$ = cat2_str($1, $2); }
1504                 | key_update key_delete         { $$ = cat2_str($1, $2); }
1505                 | /*EMPTY*/                                     { $$ = EMPTY; }
1506                 ;
1507
1508 key_delete: ON DELETE_P key_action
1509                         { $$ = cat2_str(make_str("on delete"), $3); }
1510                 ;
1511
1512 key_update: ON UPDATE key_action
1513                         { $$ = cat2_str(make_str("on update"), $3); }
1514                 ;
1515
1516 key_action:     NO ACTION                       { $$ = make_str("no action"); }
1517                 | RESTRICT                                      { $$ = make_str("restrict"); }
1518                 | CASCADE                                       { $$ = make_str("cascade"); }
1519                 | SET DEFAULT                           { $$ = make_str("set default"); }
1520                 | SET NULL_P                            { $$ = make_str("set null"); }
1521                 ;
1522
1523 OptInherit:  INHERITS '(' qualified_name_list ')'
1524                         { $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); }
1525                 | /*EMPTY*/
1526                         { $$ = EMPTY; }
1527                 ;
1528
1529 OptWithOids:  WITH OIDS                         { $$ = make_str("with oids"); }
1530                 | WITHOUT OIDS                          { $$ = make_str("without oids"); }
1531                 | /*EMPTY*/                                     { $$ = EMPTY; }
1532                 ;
1533
1534 OnCommitOption:   ON COMMIT DROP                { $$ = make_str("on commit drop"); }
1535                 | ON COMMIT DELETE_P ROWS       { $$ = make_str("on commit delete rows"); }
1536                 | ON COMMIT PRESERVE ROWS       { $$ = make_str("on commit preserve rows"); }
1537                 | /*EMPTY*/                     { $$ = EMPTY; }
1538                 ;
1539
1540 OptTableSpace:  TABLESPACE name { $$ = cat2_str(make_str("tablespace"), $2); }
1541                 | /*EMPTY*/     { $$ = EMPTY; }
1542                 ;
1543
1544 /*
1545  * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
1546  * SELECT ... INTO.
1547  */
1548
1549 CreateAsStmt:  CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs
1550                 { FoundInto = 0; }
1551                 SelectStmt
1552                 {
1553                         if (FoundInto == 1)
1554                                 mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT may not specify INTO");
1555
1556                         $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, $5, $6, $8);
1557                 }
1558                 ;
1559
1560 /*
1561  * To avoid a shift/reduce conflict in CreateAsStmt, we need to
1562  * include the 'AS' terminal in the parsing of WITH/WITHOUT
1563  * OIDS. Unfortunately that means this production is effectively a
1564  * duplicate of OptWithOids.
1565  */
1566 WithOidsAs:
1567                        WITH OIDS AS                 { $$ = make_str("with oids as"); }
1568                        | WITHOUT OIDS AS            { $$ = make_str("without oids as"); }
1569                        | AS                         { $$ = make_str("as"); }
1570                        ;
1571
1572
1573 OptCreateAs:  '(' CreateAsList ')'
1574                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1575                 | /*EMPTY*/
1576                         { $$ = EMPTY; }
1577                 ;
1578
1579 CreateAsList:  CreateAsList ',' CreateAsElement
1580                         { $$ = cat_str(3, $1, make_str(","), $3); }
1581                 | CreateAsElement
1582                         { $$ = $1; }
1583                 ;
1584
1585 CreateAsElement:  ColId { $$ = $1; }
1586                 ;
1587
1588 /*****************************************************************************
1589  *
1590  *              QUERY :
1591  *                              CREATE SEQUENCE seqname
1592  *                              ALTER SEQUENCE seqname
1593  *
1594  *****************************************************************************/
1595
1596 CreateSeqStmt:  CREATE OptTemp SEQUENCE qualified_name OptSeqList
1597                         { $$ = cat_str(4, make_str("create"), $2, make_str("sequence"), $4, $5); }
1598                 ;
1599
1600 AlterSeqStmt: ALTER SEQUENCE qualified_name OptSeqList
1601                         { $$ = cat_str(3,make_str("alter sequence"), $3, $4); }
1602                 ;
1603
1604 OptSeqList:  OptSeqList OptSeqElem      { $$ = cat2_str($1, $2); }
1605                 | /*EMPTY*/                                     { $$ = EMPTY; }
1606                 ;
1607
1608 OptSeqElem:  CACHE NumConst
1609                         { $$ = cat2_str(make_str("cache"), $2); }
1610                 | CYCLE
1611                         { $$ = make_str("cycle"); }
1612                 | NO CYCLE
1613                         { $$ = make_str("no cycle"); }
1614                 | INCREMENT opt_by NumConst
1615                         { $$ = cat_str(3, make_str("increment"), $2, $3); }
1616                 | MAXVALUE NumConst
1617                         { $$ = cat2_str(make_str("maxvalue"), $2); }
1618                 | MINVALUE NumConst
1619                         { $$ = cat2_str(make_str("minvalue"), $2); }
1620                 | NO MAXVALUE
1621                         { $$ = make_str("no maxvalue"); }
1622                 | NO MINVALUE
1623                         { $$ = make_str("no minvalue"); }
1624                 | START opt_with NumConst
1625                         { $$ = cat_str(3, make_str("start"), $2, $3); }
1626                 | RESTART opt_with NumConst
1627                         { $$ = cat_str(3, make_str("restart"), $2, $3); }
1628                 ;
1629
1630 opt_by:         BY      { $$ = make_str("by"); }
1631                 | /*EMPTY*/     { $$ = EMPTY; }
1632                 ;
1633
1634 /*****************************************************************************
1635  *
1636  *              QUERIES :
1637  *                              CREATE PROCEDURAL LANGUAGE ...
1638  *                              DROP PROCEDURAL LANGUAGE ...
1639  *
1640  *****************************************************************************/
1641
1642 CreatePLangStmt:  CREATE opt_Trusted opt_procedural LANGUAGE ColId_or_Sconst
1643                         HANDLER handler_name opt_lancompiler
1644                         { $$ = cat_str(8, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8); }
1645                 ;
1646
1647 opt_Trusted:    TRUSTED { $$ = make_str("trusted"); }
1648                 | /*EMPTY*/             { $$ = EMPTY; }
1649                 ;
1650
1651 /* This ought to be just func_name, but that causes reduce/reduce conflicts
1652  * (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
1653  * Work around by using simple names instead.
1654  */
1655 handler_name: name      { $$ = $1; }
1656         | name attrs    { $$ = cat2_str($1, $2); }
1657                ;
1658
1659 opt_lancompiler: LANCOMPILER StringConst
1660                         { $$ = cat2_str(make_str("lancompiler"), $2); }
1661                 | /*EMPTY*/
1662                         { $$ = ""; }
1663                 ;
1664
1665 DropPLangStmt:  DROP opt_procedural LANGUAGE StringConst opt_drop_behavior
1666                         { $$ = cat_str(5, make_str("drop"), $2, make_str("language"), $4, $5); }
1667                 ;
1668
1669 opt_procedural: PROCEDURAL      { $$ = make_str("prcedural"); }
1670                 | /*EMPTY*/                     { $$ = EMPTY; }
1671                 ;
1672
1673 /*****************************************************************************
1674  *
1675  *             QUERY:
1676  *             CREATE TABLESPACE tablespace LOCATION '/path/to/tablespace/'
1677  *
1678  *****************************************************************************/
1679
1680 CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst
1681                         { $$ = cat_str(5,make_str("create tablespace"), $3, $4, make_str("location"), $6); }
1682                 ;
1683
1684 OptTableSpaceOwner: OWNER name  { $$ = cat2_str(make_str("owner"), $2); }
1685                 | /*EMPTY*/     { $$ = EMPTY; }
1686                 ;
1687
1688 /*****************************************************************************
1689  *
1690  *             QUERY :
1691  *                             DROP TABLESPACE <tablespace>
1692  *
1693  *             No need for drop behaviour as we cannot implement dependencies for
1694  *             objects in other databases; we can only support RESTRICT.
1695  *
1696  ****************************************************************************/
1697
1698
1699 DropTableSpaceStmt: DROP TABLESPACE name        { $$ = cat2_str(make_str("drop tablespace"), $3); };
1700
1701
1702 /*****************************************************************************
1703  *
1704  *              QUERIES :
1705  *                              CREATE TRIGGER ...
1706  *                              DROP TRIGGER ...
1707  *
1708  *****************************************************************************/
1709
1710 CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
1711                                 qualified_name TriggerForSpec
1712                                 EXECUTE PROCEDURE
1713                                 name '(' TriggerFuncArgs ')'
1714                         { $$ = cat_str(12, make_str("create trigger"), $3, $4, $5, make_str("on"), $7, $8, make_str("execute procedure"), $11, make_str("("), $13, make_str(")")); }
1715                 |       CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
1716                                 qualified_name OptConstrFromTable
1717                                 ConstraintAttributeSpec
1718                                 FOR EACH ROW EXECUTE PROCEDURE
1719                                 func_name '(' TriggerFuncArgs ')'
1720                         { $$ = cat_str(13, make_str("create constraint trigger"), $4, make_str("after"), $6, make_str("on"), $8, $9, $10, make_str("for each row execute procedure"), $16, make_str("("), $18, make_str(")")); }
1721                 ;
1722
1723 TriggerActionTime:      BEFORE          { $$ = make_str("before"); }
1724                 | AFTER                                 { $$ = make_str("after"); }
1725                 ;
1726
1727 TriggerEvents:  TriggerOneEvent
1728                         { $$ = $1; }
1729                 | TriggerOneEvent OR TriggerOneEvent
1730                         { $$ = cat_str(3, $1, make_str("or"), $3); }
1731                 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
1732                         { $$ = cat_str(5, $1, make_str("or"), $3, make_str("or"), $5); }
1733                 ;
1734
1735 TriggerOneEvent:  INSERT        { $$ = make_str("insert"); }
1736                 | DELETE_P                      { $$ = make_str("delete"); }
1737                 | UPDATE                        { $$ = make_str("update"); }
1738                 ;
1739
1740 TriggerForSpec:  FOR TriggerForOpt TriggerForType
1741                         { $$ = cat_str(3, make_str("for"), $2, $3); }
1742                 | /* EMPTY */
1743                         { $$ = EMPTY; }
1744                 ;
1745
1746 TriggerForOpt:  EACH            { $$ = make_str("each"); }
1747                 | /*EMPTY*/                     { $$ = EMPTY; }
1748                 ;
1749
1750 TriggerForType:  ROW            { $$ = make_str("row"); }
1751                 | STATEMENT                     { $$ = make_str("statement"); }
1752                 ;
1753
1754 TriggerFuncArgs:  TriggerFuncArg
1755                         { $$ = $1; }
1756                 | TriggerFuncArgs ',' TriggerFuncArg
1757                         { $$ = cat_str(3, $1, make_str(","), $3); }
1758                 | /*EMPTY*/
1759                         { $$ = EMPTY; }
1760                 ;
1761
1762 TriggerFuncArg:  PosAllConst    { $$ = $1; }
1763                 | ColId         { $$ = $1; }
1764                 ;
1765
1766 OptConstrFromTable: /* Empty */         { $$ = EMPTY; }
1767                 | FROM qualified_name   { $$ = cat2_str(make_str("from"), $2); }
1768                 ;
1769
1770 ConstraintAttributeSpec: ConstraintDeferrabilitySpec    { $$ = $1; }
1771                 | ConstraintDeferrabilitySpec ConstraintTimeSpec
1772                 {
1773                         if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
1774                                 mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
1775
1776                         $$ = cat2_str($1, $2);
1777                 }
1778                 | ConstraintTimeSpec            { $$ = $1; }
1779                 | ConstraintTimeSpec ConstraintDeferrabilitySpec
1780                 {
1781                         if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
1782                                 mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
1783
1784                         $$ = cat2_str($1, $2);
1785                 }
1786                 ;
1787
1788 ConstraintDeferrabilitySpec: NOT DEFERRABLE
1789                         { $$ = make_str("not deferrable"); }
1790                 | DEFERRABLE
1791                         { $$ = make_str("deferrable"); }
1792                 ;
1793
1794 ConstraintTimeSpec: INITIALLY IMMEDIATE
1795                         { $$ = make_str("initially immediate"); }
1796                 | INITIALLY DEFERRED
1797                         { $$ = make_str("initially deferred"); }
1798                 ;
1799
1800 DropTrigStmt:  DROP TRIGGER name ON qualified_name opt_drop_behavior
1801                         { $$ = cat_str(5, make_str("drop trigger"), $3, make_str("on"), $5, $6); }
1802                 ;
1803
1804 /*****************************************************************************
1805  *
1806  *             QUERIES :
1807  *                             CREATE ASSERTION ...
1808  *                             DROP ASSERTION ...
1809  *
1810  *****************************************************************************/
1811 CreateAssertStmt:  CREATE ASSERTION name
1812                        CHECK '(' a_expr ')' ConstraintAttributeSpec
1813                         {
1814                                 mmerror(PARSE_ERROR, ET_ERROR, "CREATE ASSERTION is not yet supported");
1815                                 $$ = cat_str(6, make_str("create assertion"), $3, make_str("check ("), $6, make_str(")"), $8);
1816                         }
1817                 ;
1818
1819 DropAssertStmt:  DROP ASSERTION name
1820         {
1821                 mmerror(PARSE_ERROR, ET_ERROR, "DROP ASSERTION is not yet supported");
1822                 $$ = cat2_str(make_str("drop assertion"), $3);
1823         }
1824         ;
1825
1826
1827 /*****************************************************************************
1828  *
1829  *              QUERY :
1830  *                              define (type,operator,aggregate)
1831  *
1832  *****************************************************************************/
1833
1834 DefineStmt:  CREATE AGGREGATE func_name definition
1835                         { $$ = cat_str(3, make_str("create aggregate"), $3, $4); }
1836                 | CREATE OPERATOR all_Op definition
1837                         { $$ = cat_str(3, make_str("create operator"), $3, $4); }
1838                 | CREATE TYPE_P any_name definition
1839                         { $$ = cat_str(3, make_str("create type"), $3, $4); }
1840                 | CREATE TYPE_P any_name AS rowdefinition
1841                         { $$ = cat_str(4, make_str("create type"), $3, make_str("as"), $5); }
1842                 ;
1843
1844 rowdefinition: '(' TableFuncElementList ')'
1845                         { $$ = cat_str(3, make_str("("), $2, make_str(")"));}
1846                 ;
1847
1848 definition:  '(' def_list ')'
1849                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1850                 ;
1851
1852 def_list:  def_elem                                     { $$ = $1; }
1853                 | def_list ',' def_elem         { $$ = cat_str(3, $1, make_str(","), $3); }
1854                 ;
1855
1856 def_elem:  ColLabel '=' def_arg         { $$ = cat_str(3, $1, make_str("="), $3); }
1857                 | ColLabel                                      { $$ = $1; }
1858                 ;
1859
1860 /* Note: any simple identifier will be returned as a type name! */
1861 def_arg:  func_return                           {  $$ = $1; }
1862                 | qual_all_Op                                   {  $$ = $1; }
1863                 | AllConst                                      {  $$ = $1; }
1864                 ;
1865
1866 CreateOpClassStmt:      CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename
1867                         USING access_method AS opclass_item_list
1868                                 {
1869                                         $$ = cat_str(9, make_str("create operator class"), $4, $5, make_str("for type"), $8, make_str("using"), $10, make_str("as"), $12);
1870                                 }
1871                                 ;
1872
1873 opclass_item_list:      opclass_item            { $$ = $1; }
1874                         | opclass_item_list ',' opclass_item    { $$ = cat_str(3, $1, make_str(","), $3); }
1875                         ;
1876
1877 opclass_item:   OPERATOR PosIntConst any_operator opt_recheck
1878                         { $$ = cat_str(4, make_str("operator"), $2, $3, $4); }
1879                 | OPERATOR PosIntConst any_operator '(' oper_argtypes ')' opt_recheck
1880                         { $$ =  cat_str(7, make_str("operator"), $2, $3, make_str("("), $5, make_str(")"), $7); }
1881                 | FUNCTION PosIntConst func_name func_args
1882                         { $$ = cat_str(4, make_str("function"), $2, $3, $4); }
1883                 | STORAGE Typename
1884                         { $$ = cat2_str(make_str("storage"), $2); }
1885                 ;
1886
1887 opt_default:   DEFAULT  { $$ = make_str("default"); }
1888         |  /*EMPTY*/    { $$ = EMPTY; }
1889         ;
1890
1891 opt_recheck:   RECHECK  { $$ = make_str("recheck"); }
1892         |  /*EMPTY*/    { $$ = EMPTY; }
1893         ;
1894
1895 DropOpClassStmt: DROP OPERATOR CLASS any_name USING access_method opt_drop_behavior
1896                         { $$ = cat_str(5,make_str("drop operator class"), $4, make_str("using"), $6, $7); }
1897                 ;
1898
1899 /*****************************************************************************
1900  *
1901  *              QUERY:
1902  *
1903  *                         DROP itemtype itemname [, itemname ...]
1904  *
1905  *****************************************************************************/
1906
1907 DropStmt:  DROP drop_type any_name_list opt_drop_behavior
1908                         { $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
1909                 ;
1910
1911 drop_type:      TABLE                   { $$ = make_str("table"); }
1912                 | SEQUENCE              { $$ = make_str("sequence"); }
1913                 | VIEW                  { $$ = make_str("view"); }
1914                 | INDEX                 { $$ = make_str("index"); }
1915                 | TYPE_P                { $$ = make_str("type"); }
1916                 | DOMAIN_P              { $$ = make_str("domain"); }
1917                 | CONVERSION_P          { $$ = make_str("conversion"); }
1918                 | SCHEMA                { $$ = make_str("schema"); }
1919                 ;
1920
1921 any_name_list:  any_name
1922                        { $$ = $1; }
1923                | any_name_list ',' any_name
1924                        { $$ = cat_str(3, $1, make_str(","), $3); }
1925                ;
1926
1927 any_name: ColId        { $$ = $1; }
1928         | ColId attrs  { $$ = cat2_str($1, $2); }
1929         ;
1930
1931 /*
1932  * The slightly convoluted way of writing this production avoids reduce/reduce
1933  * errors against indirection_el.
1934  */
1935 attrs: '.' attr_name            { $$ = cat2_str(make_str("."), $2); }
1936         | '.' attr_name attrs   { $$ = cat_str(3, make_str("."), $2, $3); }
1937         ;
1938
1939 /*****************************************************************************
1940  *
1941  *                         QUERY:
1942  *                                                         truncate table relname
1943  *
1944  *****************************************************************************/
1945 TruncateStmt:  TRUNCATE opt_table qualified_name
1946                         { $$ = cat_str(3, make_str("truncate table"), $2, $3); }
1947                 ;
1948
1949 /*****************************************************************************
1950  *
1951  *              QUERY:
1952  *                      fetch/move
1953  *
1954  *****************************************************************************/
1955
1956 /* This is different from the backend as we try to be compatible with many other
1957  * embedded SQL implementations. So we accept their syntax as well and 
1958  * translate it to the PGSQL syntax. */
1959  
1960 FetchStmt: FETCH fetch_direction from_in name ecpg_into
1961                         {
1962                                 add_additional_variables($4, false);
1963                                 $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
1964                         }
1965                 | FETCH fetch_direction name ecpg_into
1966                         {
1967                                 add_additional_variables($3, false);
1968                                 $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
1969                         }
1970                 | FETCH from_in name ecpg_into
1971                         {
1972                                 add_additional_variables($3, false);
1973                                 $$ = cat_str(3, make_str("fetch"), $2, $3);
1974                         }
1975                 | FETCH name ecpg_into
1976                         {
1977                                 add_additional_variables($2, false);
1978                                 $$ = cat2_str(make_str("fetch"), $2);
1979                         }
1980                 | FETCH fetch_direction from_in name
1981                         {
1982                                 add_additional_variables($4, false);
1983                                 $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
1984                         }
1985                 | FETCH fetch_direction name
1986                         {
1987                                 add_additional_variables($3, false);
1988                                 $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
1989                         }
1990                 | FETCH from_in name 
1991                         {
1992                                 add_additional_variables($3, false);
1993                                 $$ = cat_str(3, make_str("fetch"), $2, $3);
1994                         }
1995                 | FETCH name 
1996                         {
1997                                 add_additional_variables($2, false);
1998                                 $$ = cat2_str(make_str("fetch"), $2);
1999                         }
2000                 | MOVE fetch_direction from_in name
2001                         { $$ = cat_str(4, make_str("move"), $2, $3, $4); }
2002                 | MOVE name
2003                         { $$ = cat2_str(make_str("move"), $2); }
2004                 ;
2005
2006 fetch_direction:  NEXT                          { $$ = make_str("next"); }
2007                 | PRIOR                         { $$ = make_str("prior"); }
2008                 | FIRST_P                       { $$ = make_str("first"); }
2009                 | LAST_P                        { $$ = make_str("last"); }
2010                 | ABSOLUTE_P fetch_count        { $$ = cat2_str(make_str("absolute"), $2); }
2011                 | RELATIVE_P fetch_count        { $$ = cat2_str(make_str("relative"), $2); }
2012                 | fetch_count                   { $$ = $1; }
2013                 | ALL                           { $$ = make_str("all"); }
2014                 | FORWARD                       { $$ = make_str("forward"); }
2015                 | FORWARD fetch_count           { $$ = cat2_str(make_str("forward"), $2); }
2016                 | FORWARD ALL                   { $$ = make_str("forward all"); }
2017                 | BACKWARD                      { $$ = make_str("backward"); }
2018                 | BACKWARD fetch_count          { $$ = cat2_str(make_str("backward"), $2); }
2019                 | BACKWARD ALL                  { $$ = make_str("backward all"); }
2020                 ;
2021
2022 fetch_count: IntConst   { $$ = $1; }
2023         ;
2024
2025 from_in: IN_P                           { $$ = make_str("in"); }
2026                 | FROM                  { $$ = make_str("from"); }
2027                 ;
2028
2029 CommentStmt:   COMMENT ON comment_type name IS comment_text
2030                         { $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6); }
2031                 | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text
2032                         { $$ = cat_str(6, make_str("comment on aggregate"), $4, make_str("("), $6, make_str(") is"), $9); }
2033                 | COMMENT ON FUNCTION func_name func_args IS comment_text
2034                         { $$ = cat_str(5, make_str("comment on function"), $4, $5, make_str("is"), $7); }
2035                 | COMMENT ON OPERATOR all_Op '(' oper_argtypes ')' IS comment_text
2036                         { $$ = cat_str(6, make_str("comment on operator"), $4, make_str("("), $6, make_str(") is"), $9); }
2037                 | COMMENT ON TRIGGER name ON any_name IS comment_text
2038                         { $$ = cat_str(6, make_str("comment on trigger"), $4, make_str("on"), $6, make_str("is"), $8); }
2039                 | COMMENT ON RULE name ON any_name IS comment_text
2040                         { $$ = cat_str(6, make_str("comment on rule"), $4, make_str("on"), $6, make_str("is"), $8); }
2041                 | COMMENT ON RULE name IS comment_text
2042                         { $$ = cat_str(4, make_str("comment on rule"), $4, make_str("is"), $6); }
2043                 | COMMENT ON OPERATOR CLASS any_name USING access_method IS comment_text
2044                         { $$ = cat_str(6, make_str("comment on operator class"), $5, make_str("using"), $7, make_str("is"), $9); }
2045                 | COMMENT ON LARGE_P OBJECT_P NumConst IS comment_text
2046                         { $$ = cat_str(4, make_str("comment on large object"), $5, make_str("is"), $7); }
2047                 | COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text
2048                         { $$ = cat_str(6, make_str("comment on cast ("), $5, make_str("as"), $7, make_str(") is"), $10); }
2049                 | COMMENT ON opt_procedural LANGUAGE any_name IS comment_text
2050                         { $$ = cat_str(6, make_str("comment on"), $3, make_str("language"), $5, make_str("is"), $7); }
2051                 ;
2052
2053 comment_type:  COLUMN           { $$ = make_str("column"); }
2054                 | DATABASE      { $$ = make_str("database"); }
2055                 | SCHEMA        { $$ = make_str("schema"); }
2056                 | INDEX         { $$ = make_str("idnex"); }
2057                 | SEQUENCE      { $$ = make_str("sequence"); }
2058                 | TABLE         { $$ = make_str("table"); }
2059                 | DOMAIN_P      { $$ = make_str("domain"); }
2060                 | TYPE_P        { $$ = make_str("type"); }
2061                 | VIEW          { $$ = make_str("view"); }
2062                 | CONVERSION_P  { $$ = make_str("conversion"); }
2063                 ;
2064
2065 comment_text:   StringConst { $$ = $1; }
2066                 | NULL_P                        { $$ = make_str("null"); }
2067                 ;
2068
2069 /*****************************************************************************
2070  *
2071  *              QUERY:
2072  * GRANT and REVOKE statements
2073  *
2074  *****************************************************************************/
2075
2076 GrantStmt:      GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option
2077                         { $$ = cat_str(7, make_str("grant"), $2, make_str("on"), $4, make_str("to"), $6, $7); }
2078                 ;
2079
2080 RevokeStmt:  REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list opt_drop_behavior
2081                         {
2082                           $$ = cat_str(9, make_str("revoke"), $2, $3, make_str("on"), $5, make_str("from"), $7, $8);
2083                         }
2084                           
2085                 ;
2086
2087 privileges:  ALL PRIVILEGES             { $$ = make_str("all privileges"); }
2088                 | ALL                                   { $$ = make_str("all"); }
2089                 | privilege_list                { $$ = $1; }
2090                 ;
2091
2092 privilege_list:  privilege
2093                         { $$ = $1; }
2094                 | privilege_list ',' privilege
2095                         { $$ = cat_str(3, $1, make_str(","), $3); }
2096                 ;
2097
2098 privilege:      SELECT                  { $$ = make_str("select"); }
2099                 | INSERT                        { $$ = make_str("insert"); }
2100                 | UPDATE                        { $$ = make_str("update"); }
2101                 | DELETE_P                      { $$ = make_str("delete"); }
2102                 | RULE                          { $$ = make_str("rule"); }
2103                 | REFERENCES            { $$ = make_str("references"); }
2104                 | TRIGGER                       { $$ = make_str("trigger"); }
2105                 | EXECUTE                       { $$ = make_str("execute"); }
2106                 | USAGE                         { $$ = make_str("usage"); }
2107                 | CREATE                        { $$ = make_str("create"); }
2108                 | TEMPORARY                     { $$ = make_str("temporary"); }
2109                 | TEMP                          { $$ = make_str("temp"); }
2110                 ;
2111
2112 privilege_target: qualified_name_list
2113                         { $$ = $1; }
2114                 | TABLE qualified_name_list
2115                         { $$ = cat2_str(make_str("table"), $2); }
2116                 | FUNCTION function_with_argtypes_list
2117                         { $$ = cat2_str(make_str("function"), $2); }
2118                 | DATABASE name_list
2119                         { $$ = cat2_str(make_str("database"), $2); }
2120                 | LANGUAGE name_list
2121                         { $$ = cat2_str(make_str("language") , $2); }
2122                 | SCHEMA name_list
2123                         { $$ = cat2_str(make_str("schema") , $2); }
2124                 | TABLESPACE name_list
2125                         { $$ = cat2_str(make_str("tablespace") , $2); }
2126                 ;
2127
2128 grantee_list: grantee
2129                         { $$ = $1; }
2130                 | grantee_list ',' grantee
2131                         { $$ = cat_str(3, $1, make_str(","), $3); }
2132                 ;
2133
2134 grantee:  ColId                 { $$ = $1; }
2135                 | GROUP_P ColId         { $$ = cat2_str(make_str("group"), $2); }
2136                 ;
2137
2138 opt_grant_grant_option:  WITH GRANT OPTION
2139                 {
2140                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported GRANT/WITH GRANT OPTION will be passed to backend");
2141                         $$ = make_str("with grant option");
2142                 }
2143                 | /*EMPTY*/     { $$ = EMPTY; }
2144                 ;
2145
2146 opt_revoke_grant_option: GRANT OPTION FOR
2147                 {
2148                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported REVOKE/GRANT OPTION FOR will be passed to backend");
2149                         $$ = make_str("grant option for");
2150                 }
2151                 | /*EMPTY*/     { $$ = EMPTY; }
2152                 ;
2153
2154 function_with_argtypes_list: function_with_argtypes
2155                         { $$ = $1; }
2156                 | function_with_argtypes_list ',' function_with_argtypes
2157                         { $$ = cat_str(3, $1, make_str(","), $3); }
2158                 ;
2159
2160 function_with_argtypes: func_name func_args { $$ = cat2_str($1, $2); };
2161
2162 /*****************************************************************************
2163  *
2164  *              QUERY:
2165  *                              create index <indexname> on <relname>
2166  *                                [ using <access> ] "(" ( <col> | using <opclass> ] )+ ")"
2167  *                                [ tablespace <tablespacename> ] [ where <predicate> ]
2168  *
2169  *****************************************************************************/
2170
2171 IndexStmt:      CREATE index_opt_unique INDEX index_name ON qualified_name
2172                                 access_method_clause '(' index_params ')' OptTableSpace where_clause
2173                         { $$ = cat_str(12, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11, $12); }
2174                 ;
2175
2176 index_opt_unique:  UNIQUE       { $$ = make_str("unique"); }
2177                 | /*EMPTY*/             { $$ = EMPTY; }
2178                 ;
2179
2180 access_method_clause:  USING access_method
2181                         { $$ = cat2_str(make_str("using"), $2); }
2182                 | /*EMPTY*/
2183                         { $$ = EMPTY; }
2184                 ;
2185
2186 index_params:  index_elem                       { $$ = $1; }
2187                 | index_params ',' index_elem   { $$ = cat_str(3, $1, make_str(","), $3); }
2188                 ;
2189
2190 index_elem:  attr_name opt_class
2191                 { $$ = cat2_str($1, $2); }
2192         | func_name '(' expr_list ')' opt_class
2193                 { $$ = cat_str(5, $1, make_str("("), $3, ")", $5); }
2194         | '(' a_expr ')' opt_class
2195                 { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
2196         ;
2197
2198 opt_class:      any_name        { $$ = $1; }
2199                 | USING any_name        { $$ = cat2_str(make_str("using"), $2); }
2200                 | /*EMPTY*/             { $$ = EMPTY; }
2201                 ;
2202
2203 CreateFunctionStmt:     CREATE opt_or_replace FUNCTION func_name func_args
2204                                         RETURNS func_return createfunc_opt_list opt_definition
2205                         { $$ = cat_str(8, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, $8); }
2206                 ;
2207
2208 opt_or_replace:  OR REPLACE             { $$ = make_str("or replace"); }
2209                 | /*EMPTY*/                             { $$ = EMPTY; }
2210                 ;
2211
2212 func_args:      '(' func_args_list ')'
2213                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2214                 | '(' ')'
2215                         { $$ = make_str("()"); }
2216                 ;
2217
2218 func_args_list:  func_arg
2219                         { $$ = $1; }
2220                 | func_args_list ',' func_arg
2221                         { $$ = cat_str(3, $1, make_str(","), $3); }
2222                 ;
2223
2224 func_arg:  arg_class param_name func_type       { $$ = cat_str(3, $1, $2, $3); }
2225                 | arg_class func_type           { $$ = cat2_str($1, $2); }
2226                 ;
2227
2228 arg_class:  IN_P        { $$ = make_str("in"); }
2229                 | OUT_P
2230                 {
2231                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/OUT will be passed to backend");
2232
2233                         $$ = make_str("out");
2234                 }
2235                 | INOUT
2236                 {
2237                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/INOUT will be passed to backend");
2238
2239                         $$ = make_str("inout");
2240                 }
2241                 | /*EMPTY*/
2242                 { $$ = EMPTY; }
2243                 ;
2244
2245 func_as: StringConst
2246                         { $$ = $1; }
2247                 | StringConst ',' StringConst
2248                         { $$ = cat_str(3, $1, make_str(","), $3); }
2249                 ;
2250
2251 param_name:    function_name    { $$ = $1; };
2252
2253 func_return:  func_type
2254                 {
2255                         /* We can catch over-specified arguments here if we want to,
2256                          * but for now better to silently swallow typmod, etc.
2257                          * - thomas 2000-03-22
2258                          */
2259                         $$ = $1;
2260                 }
2261                 ;
2262
2263 func_type:      Typename
2264                         { $$ = $1; }
2265                 | type_name attrs '%' TYPE_P
2266                         { $$ = cat_str(3, $1, $2, make_str("% type")); }
2267                 ;
2268
2269
2270 createfunc_opt_list: createfunc_opt_item
2271                         { $$ = $1; }
2272                 | createfunc_opt_list createfunc_opt_item
2273                         { $$ = cat2_str($1, $2); }
2274                 ;
2275
2276 createfunc_opt_item: AS func_as
2277                                 { $$ = cat2_str(make_str("as"), $2); }
2278                 | LANGUAGE ColId_or_Sconst
2279                                 { $$ = cat2_str(make_str("language"), $2); }
2280                 | IMMUTABLE
2281                                 { $$ = make_str("immutable"); }
2282                 | STABLE
2283                                 { $$ = make_str("stable"); }
2284                 | VOLATILE
2285                                 { $$ = make_str("volatile"); }
2286                 | CALLED ON NULL_P INPUT_P
2287                                 { $$ = make_str("called on null input"); }
2288                 | RETURNS NULL_P ON NULL_P INPUT_P
2289                                 { $$ = make_str("returns null on null input"); }
2290                 | STRICT_P
2291                                 { $$ = make_str("strict"); }
2292                 | EXTERNAL SECURITY DEFINER
2293                                 { $$ = make_str("external security definer"); }
2294                 | EXTERNAL SECURITY INVOKER
2295                                 { $$ = make_str("external security invoker"); }
2296                 | SECURITY DEFINER
2297                                 { $$ = make_str("security definer"); }
2298                 | SECURITY INVOKER
2299                                 { $$ = make_str("security invoker"); }
2300                 ;
2301
2302 opt_definition: WITH definition { $$ = cat2_str(make_str("with"), $2); }
2303                 | /*EMPTY*/     { $$ = EMPTY; }
2304                 ;
2305
2306 /*****************************************************************************
2307  *
2308  *              QUERY:
2309  *
2310  *                         DROP FUNCTION funcname (arg1, arg2, ...)
2311  *                         DROP AGGREGATE aggname (aggtype)
2312  *                         DROP OPERATOR opname (leftoperand_typ rightoperand_typ)
2313  *
2314  *****************************************************************************/
2315
2316 RemoveFuncStmt:  DROP FUNCTION func_name func_args opt_drop_behavior
2317                         { $$ = cat_str(4, make_str("drop function"), $3, $4, $5); }
2318                 ;
2319
2320 RemoveAggrStmt:  DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior
2321                         { $$ = cat_str(6, make_str("drop aggregate"), $3, make_str("("), $5, make_str(")"), $7); }
2322                 ;
2323
2324 aggr_argtype:  Typename         { $$ = $1; }
2325                 | '*'                           { $$ = make_str("*"); }
2326                 ;
2327
2328
2329 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')' opt_drop_behavior
2330                         { $$ = cat_str(6, make_str("drop operator"), $3, make_str("("), $5, make_str(")"), $7); }
2331                 ;
2332
2333 oper_argtypes:  Typename
2334                         { mmerror(PARSE_ERROR, ET_ERROR, "parser: argument type missing (use NONE for unary operators)"); }
2335                 | Typename ',' Typename
2336                         { $$ = cat_str(3, $1, make_str(","), $3); }
2337                 | NONE ',' Typename                     /* left unary */
2338                         { $$ = cat2_str(make_str("none,"), $3); }
2339                 | Typename ',' NONE                     /* right unary */
2340                         { $$ = cat2_str($1, make_str(", none")); }
2341                 ;
2342
2343 any_operator:
2344                         all_Op
2345                                 { $$ = $1; }
2346                         | ColId '.' any_operator
2347                                 { $$ = cat_str(3, $1, make_str("."), $3); }
2348                         ;
2349
2350 CreateCastStmt:         CREATE CAST '(' Typename AS Typename ')'
2351                                 WITH FUNCTION function_with_argtypes cast_context
2352                         { $$ = cat_str(6, make_str("create cast ("), $4, make_str("as"), $6, make_str(") with function"), $10); }
2353                         | CREATE CAST '(' Typename AS Typename ')'
2354                                 WITHOUT FUNCTION cast_context
2355                         { $$ = cat_str(6, make_str("create cast ("), $4, make_str("as"), $6, make_str(") without function"), $10); }
2356                 ;
2357
2358 cast_context: AS ASSIGNMENT   { $$ = make_str("as assignment"); }
2359                 | /*EMPTY*/     { $$ = EMPTY; }
2360                 ;
2361
2362
2363 DropCastStmt: DROP CAST '(' Typename AS Typename ')' opt_drop_behavior
2364                         { $$ = cat_str(6, make_str("drop cast ("), $4, make_str("as"), $6, make_str(")"), $8); }
2365                 ;
2366
2367 /*****************************************************************************
2368  *
2369  *                              QUERY:
2370  *
2371  *                              REINDEX type <typename> [FORCE] [ALL]
2372  *
2373  *****************************************************************************/
2374 ReindexStmt:  REINDEX reindex_type qualified_name opt_force
2375                         { $$ = cat_str(4, make_str("reindex"), $2, $3, $4); }
2376                 | REINDEX DATABASE name opt_force
2377                         { $$ = cat_str(3, make_str("reindex database"), $3, $4); }
2378                 ;
2379
2380 reindex_type:   INDEX           { $$ = make_str("index"); }
2381                 | TABLE         { $$ = make_str("table"); }
2382                 ;
2383
2384 opt_force: FORCE                        { $$ = make_str("force"); }
2385                 | /* EMPTY */           { $$ = EMPTY; }
2386                 ;
2387
2388 /*****************************************************************************
2389  *
2390  *              QUERY:
2391  *                              rename <attrname1> in <relname> [*] to <attrname2>
2392  *                              rename <relname1> to <relname2>
2393  *
2394  *****************************************************************************/
2395
2396 RenameStmt:  ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name
2397                         { $$ = cat_str(6, make_str("alter aggregate"), $3, make_str("("), $5, make_str(") rename to"), $9); }
2398         | ALTER CONVERSION_P any_name RENAME TO name
2399                         { $$ = cat_str(4, make_str("alter conversion"), $3, make_str("rename to"), $6); }
2400         | ALTER DATABASE database_name RENAME TO database_name
2401                         { $$ = cat_str(4, make_str("alter database"), $3, make_str("rename to"), $6); }
2402         | ALTER FUNCTION func_name func_args RENAME TO name
2403                         { $$ = cat_str(5, make_str("alter function"), $3, $4, make_str("rename to"), $7); }
2404         | ALTER GROUP_P UserId RENAME TO UserId
2405                         { $$ = cat_str(4, make_str("alter group"), $3, make_str("rename to"), $6); }
2406         | ALTER LANGUAGE name RENAME TO name
2407                         { $$ = cat_str(4, make_str("alter language"), $3, make_str("rename to"), $6); }
2408         | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name
2409                         { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("rename to"), $9); }
2410         | ALTER SCHEMA name RENAME TO name
2411                         { $$ = cat_str(4, make_str("alter schema"), $3, make_str("rename to"), $6); }
2412         | ALTER TABLE relation_expr RENAME TO name
2413                         { $$ = cat_str(4, make_str("alter table"), $3, make_str("rename to"), $6); }
2414         | ALTER TABLE relation_expr RENAME opt_column name TO name
2415                         { $$ = cat_str(7, make_str("alter table"), $3, make_str("rename"), $5, $6, make_str("to"), $8); }
2416         | ALTER TRIGGER name ON relation_expr RENAME TO name
2417                         { $$ = cat_str(6, make_str("alter trigger"), $3, make_str("on"), $5, make_str("rename to"), $8); }
2418         | ALTER USER UserId RENAME TO UserId
2419                         { $$ = cat_str(4, make_str("alter user"), $3, make_str("rename to"), $6); }
2420         | ALTER TABLESPACE name RENAME TO name
2421                         { $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("rename to"), $6); }
2422                 ;
2423
2424 opt_column:  COLUMN                     { $$ = make_str("column"); }
2425                 | /*EMPTY*/                     { $$ = EMPTY; }
2426                 ;
2427
2428 /*****************************************************************************
2429  *
2430  * ALTER THING name OWNER TO newname.
2431  *
2432  *****************************************************************************/
2433
2434 AlterOwnerStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO UserId
2435                         { $$ = cat_str(6, make_str("alter aggregate"), $3, make_str("("), $5, make_str(") owner to"), $9); }
2436                 | ALTER CONVERSION_P any_name OWNER TO UserId
2437                         { $$ = cat_str(4, make_str("alter conversion"), $3, make_str("owner to"), $6); }
2438                 | ALTER DATABASE database_name OWNER TO UserId
2439                         { $$ = cat_str(4, make_str("alter database"), $3, make_str("owner to"), $6); }
2440                 | ALTER DOMAIN_P database_name OWNER TO UserId
2441                         { $$ = cat_str(4, make_str("alter domain"), $3, make_str("owner to"), $6); }
2442                 | ALTER FUNCTION func_name func_args OWNER TO UserId
2443                         { $$ = cat_str(5, make_str("alter function"), $3, $4, make_str("owner to"), $7); }
2444                 | ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO UserId
2445                         { $$ = cat_str(6, make_str("alter operator"), $3, make_str("("), $5, make_str(") owner to"), $9); }
2446                 | ALTER OPERATOR CLASS any_name USING access_method OWNER TO UserId
2447                         { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("owner to"), $9); }
2448                 | ALTER SCHEMA name OWNER TO UserId
2449                         { $$ = cat_str(4, make_str("alter schema"), $3, make_str("owner to"), $6); }
2450                 | ALTER TYPE_P any_name OWNER TO UserId
2451                         { $$ = cat_str(4, make_str("alter type"), $3, make_str("owner to"), $6); }
2452                 | ALTER TABLESPACE name OWNER TO UserId
2453                         { $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("owner to"), $6); }
2454                 ;
2455
2456
2457 /*****************************************************************************
2458  *
2459  *              QUERY:  Define Rewrite Rule
2460  *
2461  *****************************************************************************/
2462
2463 RuleStmt:  CREATE opt_or_replace RULE name AS
2464                    { QueryIsRule=1; }
2465                    ON event TO qualified_name where_clause
2466                    DO opt_instead RuleActionList
2467                 {
2468                         QueryIsRule=0;
2469                         $$ = cat_str(12, make_str("create"), $2, make_str("rule"), $4, make_str("as on"), $8, make_str("to"), $10, $11, make_str("do"), $13, $14);
2470                 }
2471                 ;
2472
2473 RuleActionList:  NOTHING                                { $$ = make_str("nothing"); }
2474                 | RuleActionStmt                                { $$ = $1; }
2475                 | '(' RuleActionMulti ')'               { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2476                                 ;
2477
2478 /* the thrashing around here is to discard "empty" statements... */
2479 RuleActionMulti:  RuleActionMulti ';' RuleActionStmtOrEmpty
2480                         {  $$ = cat_str(3, $1, make_str(";"), $3); }
2481                 | RuleActionStmtOrEmpty
2482                         { $$ = cat2_str($1, make_str(";")); }
2483                 ;
2484
2485 RuleActionStmt:   SelectStmt
2486                 | InsertStmt
2487                 | UpdateStmt
2488                 | DeleteStmt
2489                 | NotifyStmt
2490                 ;
2491
2492 RuleActionStmtOrEmpty: RuleActionStmt   { $$ = $1; }
2493            | /*EMPTY*/                                          { $$ = EMPTY; }
2494            ;
2495
2496 /* change me to select, update, etc. some day */
2497 event:  SELECT                          { $$ = make_str("select"); }
2498                 | UPDATE                        { $$ = make_str("update"); }
2499                 | DELETE_P                      { $$ = make_str("delete"); }
2500                 | INSERT                        { $$ = make_str("insert"); }
2501                  ;
2502
2503 opt_instead:  INSTEAD           { $$ = make_str("instead"); }
2504                 | ALSO          { $$ = make_str("also"); }
2505                 | /*EMPTY*/                     { $$ = EMPTY; }
2506                 ;
2507
2508 DropRuleStmt:  DROP RULE name ON qualified_name opt_drop_behavior
2509                 { $$ = cat_str(5, make_str("drop rule"), $3, make_str("on"), $5, $6);}
2510                 ;
2511
2512 /*****************************************************************************
2513  *
2514  *              QUERY:
2515  *                              NOTIFY <qualified_name> can appear both in rule bodies and
2516  *                              as a query-level command
2517  *
2518  *****************************************************************************/
2519
2520 NotifyStmt:  NOTIFY qualified_name
2521                 { $$ = cat2_str(make_str("notify"), $2); }
2522                 ;
2523
2524 ListenStmt:  LISTEN qualified_name
2525                 { $$ = cat2_str(make_str("listen"), $2); }
2526                 ;
2527
2528 UnlistenStmt:  UNLISTEN qualified_name
2529                         { $$ = cat2_str(make_str("unlisten"), $2); }
2530                 | UNLISTEN '*'
2531                         { $$ = make_str("unlisten *"); }
2532                 ;
2533
2534
2535 /*****************************************************************************
2536  *
2537  *                              Transactions:
2538  *
2539  *        BEGIN / COMMIT / ROLLBACK
2540  *              (also older versions END / ABORT)
2541  *
2542  *****************************************************************************/
2543 TransactionStmt:  ABORT_P opt_transaction               { $$ = make_str("rollback"); }
2544                 | BEGIN_P opt_transaction transaction_mode_list_or_empty { $$ = cat2_str(make_str("begin transaction"), $3); }
2545                 | START TRANSACTION transaction_mode_list_or_empty       { $$ = cat2_str(make_str("start transaction"), $3); }
2546                 | COMMIT opt_transaction                { $$ = make_str("commit"); }
2547                 | END_P opt_transaction         { $$ = make_str("commit"); }
2548                 | ROLLBACK opt_transaction              { $$ = make_str("rollback"); }
2549                 ;
2550
2551 opt_transaction: WORK                   { $$ = EMPTY; }
2552                 | TRANSACTION   { $$ = EMPTY; }
2553                 | /*EMPTY*/             { $$ = EMPTY; }
2554                 ;
2555
2556 transaction_mode_list:
2557         ISOLATION LEVEL iso_level
2558         { $$ = cat2_str(make_str("isolation level"), $3); }
2559         | transaction_access_mode
2560         { $$ = $1; }
2561         | ISOLATION LEVEL iso_level transaction_access_mode
2562         { $$ = cat_str(3, make_str("isolation level"), $3, $4); }
2563         | transaction_access_mode ISOLATION LEVEL iso_level
2564         { $$ = cat_str(3, $1, make_str("isolation level"), $4); }
2565         ;
2566          
2567 transaction_mode_list_or_empty:
2568         transaction_mode_list   { $$ = $1; }
2569         | /* EMPTY */           { $$ = EMPTY; }
2570         ;
2571
2572 transaction_access_mode:
2573         READ ONLY       { $$ = make_str("read only"); }
2574         | READ WRITE    { $$ = make_str("read write"); }
2575         ;
2576         
2577 /*****************************************************************************
2578  *
2579  *              QUERY:
2580  *                              define view <viewname> '('target-list ')' [where <quals> ]
2581  *
2582  *****************************************************************************/
2583
2584 ViewStmt:  CREATE opt_or_replace VIEW qualified_name opt_column_list AS SelectStmt
2585                         { $$ = cat_str(7, make_str("create"), $2, make_str("view"), $4, $5, make_str("as"), $7); }
2586                 ;
2587
2588
2589 /*****************************************************************************
2590  *
2591  *              QUERY:
2592  *                              load make_str("filename")
2593  *
2594  *****************************************************************************/
2595
2596 LoadStmt:  LOAD file_name
2597                         { $$ = cat2_str(make_str("load"), $2); }
2598                 ;
2599
2600
2601 /*****************************************************************************
2602  *
2603  *              CREATE DATABASE
2604  *
2605  *
2606  *****************************************************************************/
2607
2608 CreatedbStmt:  CREATE DATABASE database_name WITH createdb_opt_list
2609                         { $$ = cat_str(4, make_str("create database"), $3, make_str("with"), $5); }
2610                 | CREATE DATABASE database_name
2611                         { $$ = cat2_str(make_str("create database"), $3); }
2612                 ;
2613
2614 createdb_opt_list:      createdb_opt_item
2615                         { $$ = $1; }
2616                 | createdb_opt_list createdb_opt_item
2617                         { $$ = cat2_str($1, $2); }
2618                 ;
2619
2620 createdb_opt_item:      TABLESPACE opt_equal name
2621                         { $$ = cat_str(3,make_str("tablespace"), $2, $3); }
2622                 | TABLESPACE opt_equal DEFAULT
2623                         { $$ = cat_str(3, make_str("tablespace"), $2, make_str("default")); }
2624                 | LOCATION opt_equal StringConst
2625                         { $$ = cat_str(3,make_str("location"), $2, $3); }
2626                 | LOCATION opt_equal DEFAULT
2627                         { $$ = cat_str(3, make_str("location"), $2, make_str("default")); }
2628                 | TEMPLATE opt_equal name
2629                         { $$ = cat_str(3, make_str("template"), $2, $3); }
2630                 | TEMPLATE opt_equal DEFAULT
2631                         { $$ = cat_str(3, make_str("template"), $2, make_str("default")); }
2632                 | ENCODING opt_equal PosIntStringConst
2633                         { $$ = cat_str(3, make_str("encoding"), $2, $3); }
2634                 | ENCODING opt_equal DEFAULT
2635                         { $$ = cat_str(3, make_str("encoding"), $2, make_str("default")); }
2636                 | OWNER opt_equal name
2637                         { $$ = cat_str(3, make_str("owner"), $2, $3); }
2638                 | OWNER opt_equal DEFAULT
2639                         { $$ = cat_str(3, make_str("owner"), $2, make_str("default")); }
2640                 ;
2641
2642 opt_equal: '='                                  { $$ = make_str("="); }
2643                 | /* EMPTY */                   { $$ = EMPTY; }
2644                 ;
2645
2646
2647 /*****************************************************************************
2648  *
2649  *                              ALTER DATABASE
2650  *
2651  *
2652  *****************************************************************************/
2653
2654 AlterDatabaseSetStmt: ALTER DATABASE database_name SET set_rest
2655                         { $$ = cat_str(4, make_str("alter database"), $3, make_str("set"), $5); }
2656                 | ALTER DATABASE database_name VariableResetStmt
2657                         { $$ = cat_str(3, make_str("alter database"), $3, $4); }
2658                 ;
2659
2660 /*****************************************************************************
2661  *
2662  *              DROP DATABASE
2663  *
2664  *
2665  *****************************************************************************/
2666
2667 DropdbStmt: DROP DATABASE database_name
2668                         { $$ = cat2_str(make_str("drop database"), $3); }
2669                 ;
2670
2671
2672 /*****************************************************************************
2673  *
2674  * Manipulate a domain
2675  *
2676  *****************************************************************************/
2677
2678 CreateDomainStmt:  CREATE DOMAIN_P any_name opt_as Typename ColQualList
2679                         {
2680                                 $$ = cat_str(55555, make_str("create domain"), $3, $4, $5, $6);
2681                         }
2682                 ;
2683
2684 AlterDomainStmt:
2685         ALTER DOMAIN_P any_name alter_column_default
2686                 { $$ = cat_str(3, make_str("alter domain"), $3, $4); }
2687         | ALTER DOMAIN_P any_name DROP NOT NULL_P
2688                 { $$ = cat_str(3, make_str("alter domain"), $3, make_str("drop not null")); }
2689         | ALTER DOMAIN_P any_name SET NOT NULL_P
2690                 { $$ = cat_str(3, make_str("alter domain"), $3, make_str("set not null")); }
2691         | ALTER DOMAIN_P any_name ADD TableConstraint
2692                 { $$ = cat_str(4, make_str("alter domain"), $3, make_str("add"), $5); }
2693         | ALTER DOMAIN_P any_name DROP CONSTRAINT name opt_drop_behavior
2694                 { $$ = cat_str(5, make_str("alter domain"), $3, make_str("drop constraint"), $6, $7); }
2695         ;
2696         
2697 opt_as: AS      {$$ = make_str("as"); }
2698         | /* EMPTY */   {$$ = EMPTY; }
2699         ;
2700
2701 CreateConversionStmt:
2702                        CREATE opt_default CONVERSION_P any_name FOR StringConst
2703                        TO StringConst FROM any_name
2704                        { $$ = cat_str(10, make_str("create"), $2, make_str("conversion"), $4, make_str("for"), $6, make_str("to"), $8, make_str("from"), $10); }
2705                        ;
2706
2707 /*****************************************************************************
2708  *
2709  *              QUERY:
2710  *                             cluster <index_name> on <qualified_name>
2711  *                             cluster <qualified_name>
2712  *                             cluster
2713  *
2714  *****************************************************************************/
2715
2716 ClusterStmt:  CLUSTER index_name ON qualified_name
2717                         { $$ = cat_str(4, make_str("cluster"), $2, make_str("on"), $4); }
2718         | CLUSTER qualified_name
2719                         { $$ = cat2_str(make_str("cluster"), $2); }
2720         | CLUSTER
2721                         { $$ = make_str("cluster"); }
2722         ;
2723
2724
2725 /*****************************************************************************
2726  *
2727  *              QUERY:
2728  *                              vacuum
2729  *                              analyze
2730  *
2731  *****************************************************************************/
2732
2733 VacuumStmt:  VACUUM opt_full opt_freeze opt_verbose
2734                         { $$ = cat_str(4, make_str("vacuum"), $2, $3, $4); }
2735                 | VACUUM opt_full opt_freeze opt_verbose qualified_name
2736                         { $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5); }
2737                 | VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
2738                         { $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5); }
2739                 ;
2740
2741 AnalyzeStmt:  analyze_keyword opt_verbose
2742                         { $$ = cat_str(2, $1, $2); }
2743                 | analyze_keyword opt_verbose qualified_name opt_name_list
2744                         { $$ = cat_str(4, $1, $2, $3, $4); }
2745                 ;
2746
2747 analyze_keyword:  ANALYZE               { $$ = make_str("analyze"); }
2748                 | ANALYSE                               { $$ = make_str("analyse"); }
2749                 ;
2750
2751 opt_verbose:  VERBOSE                   { $$ = make_str("verbose"); }
2752                 | /*EMPTY*/                             { $$ = EMPTY; }
2753                 ;
2754
2755 opt_full:  FULL                                 { $$ = make_str("full"); }
2756                 | /*EMPTY*/                             { $$ = EMPTY; }
2757                 ;
2758
2759 opt_freeze:  FREEZE                             { $$ = make_str("freeze"); }
2760                 | /*EMPTY*/                             { $$ = EMPTY; }
2761                 ;
2762
2763 opt_name_list:  '(' name_list ')'
2764                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2765                 | /*EMPTY*/
2766                         { $$ = EMPTY; }
2767                 ;
2768
2769
2770 /*****************************************************************************
2771  *
2772  *              QUERY:
2773  *                              EXPLAIN query
2774  *
2775  *****************************************************************************/
2776
2777 ExplainStmt:  EXPLAIN opt_analyze opt_verbose ExplainableStmt
2778                         { $$ = cat_str(4, make_str("explain"), $2, $3, $4); }
2779                 ;
2780
2781 ExplainableStmt:
2782                 SelectStmt
2783                 | InsertStmt
2784                 | UpdateStmt
2785                 | DeleteStmt
2786                 | DeclareCursorStmt
2787                 /* | ExecuteStmt */
2788                 ;                                                                                               
2789 opt_analyze:
2790         analyze_keyword                 { $$ = $1; }
2791         | /* EMPTY */                   { $$ = EMPTY; }
2792         ;
2793
2794 /*
2795
2796 conflicts with ecpg
2797
2798 PrepareStmt: PREPARE name prep_type_clause AS PreparableStmt
2799                 { $$ = cat_str(5, make_str("prepare"), $2, $3, make_str("as"), $5); }
2800                 ;
2801
2802 PreparableStmt:
2803                        SelectStmt
2804                        | InsertStmt
2805                        | UpdateStmt
2806                        | DeleteStmt
2807                ;
2808
2809 prep_type_clause: '(' prep_type_list ')'        { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2810                         | /* EMPTY * /          { $$ = EMPTY; }
2811                         ;
2812
2813 prep_type_list: Typename                { $$ = $1; }
2814         | prep_type_list ',' Typename   { $$ = cat_str(3, $1, make_str(","), $3); }
2815         ;
2816
2817 ExecuteStmt: EXECUTE name execute_param_clause
2818                 { $$ = cat_str(3, make_str("execute"), $2, $3); }
2819                 | CREATE OptTemp TABLE qualified_name OptCreateAs AS EXECUTE name execute_param_clause
2820                 { $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, $5, make_str("as execute"), $8, $9); }
2821                 
2822                 ;
2823
2824 execute_param_clause: '(' expr_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2825                         | /* EMPTY * /          { $$ = EMPTY; }
2826                         ;
2827
2828 DeallocateStmt: DEALLOCATE name         { $$ = cat2_str(make_str("deallocate"), $2); }
2829         | DEALLOCATE PREPARE name       { $$ = cat2_str(make_str("deallocate prepare"), $3); }
2830         ;
2831 */
2832
2833 /*****************************************************************************
2834  *
2835  *              QUERY:
2836  *                              INSERT STATEMENTS
2837  *
2838  *****************************************************************************/
2839
2840 InsertStmt:  INSERT INTO qualified_name insert_rest
2841                         { $$ = cat_str(3, make_str("insert into"), $3, $4); }
2842                 ;
2843
2844 insert_rest:  VALUES '(' insert_target_list ')'
2845                         { $$ = cat_str(3, make_str("values("), $3, make_str(")")); }
2846                 | DEFAULT VALUES
2847                         { $$ = make_str("default values"); }
2848                 | SelectStmt
2849                         { $$ = $1; }
2850                 | '(' insert_column_list ')' VALUES '(' insert_target_list ')'
2851                         { $$ = cat_str(5, make_str("("), $2, make_str(") values ("), $6, make_str(")")); }
2852                 | '(' insert_column_list ')' SelectStmt
2853                         { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
2854                 ;
2855
2856 insert_column_list: insert_column_list ',' insert_column_item
2857                         { $$ = cat_str(3, $1, make_str(","), $3); }
2858                 | insert_column_item
2859                         { $$ = $1; }
2860                 ;
2861
2862 insert_column_item:  ColId opt_indirection
2863                         { $$ = cat2_str($1, $2); }
2864                 ;
2865
2866
2867 /*****************************************************************************
2868  *
2869  *              QUERY:
2870  *                              DELETE STATEMENTS
2871  *
2872  *****************************************************************************/
2873
2874 DeleteStmt:  DELETE_P FROM relation_expr where_clause
2875                         { $$ = cat_str(3, make_str("delete from"), $3, $4); }
2876                 ;
2877
2878 LockStmt:  LOCK_P opt_table qualified_name_list opt_lock opt_nowait
2879                         { $$ = cat_str(5, make_str("lock"), $2, $3, $4, $5); }
2880                 ;
2881
2882 opt_lock:  IN_P lock_type MODE
2883                         { $$ = cat_str(3, make_str("in"), $2, make_str("mode")); }
2884                 | /*EMPTY*/
2885                         { $$ = EMPTY;}
2886                 ;
2887
2888 lock_type:      ACCESS SHARE            { $$ = make_str("access share"); }
2889                 | ROW SHARE                             { $$ = make_str("access share"); }
2890                 | ROW EXCLUSIVE                 { $$ = make_str("row exclusive"); }
2891                 | SHARE UPDATE EXCLUSIVE { $$ = make_str("share update exclusive"); }
2892                 | SHARE                                 { $$ = make_str("share"); }
2893                 | SHARE ROW EXCLUSIVE   { $$ = make_str("share row exclusive"); }
2894                 | EXCLUSIVE                             { $$ = make_str("exclusive"); }
2895                 | ACCESS EXCLUSIVE              { $$ = make_str("access exclusive"); }
2896                 ;
2897
2898 opt_nowait:    NOWAIT                   { $$ = make_str("nowait"); }
2899                 | /* EMPTY */           { $$ = EMPTY; }
2900                 ;
2901
2902 /*****************************************************************************
2903  *
2904  *              QUERY:
2905  *                              UpdateStmt (UPDATE)
2906  *
2907  *****************************************************************************/
2908
2909 UpdateStmt:  UPDATE relation_expr
2910                                 SET update_target_list
2911                                 from_clause
2912                                 where_clause
2913                         {$$ = cat_str(6, make_str("update"), $2, make_str("set"), $4, $5, $6); }
2914                 ;
2915
2916
2917 /*****************************************************************************
2918  *
2919  *              QUERY:
2920  *                              CURSOR STATEMENTS
2921  *
2922  *****************************************************************************/
2923 DeclareCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
2924                 {
2925                         struct cursor *ptr, *this;
2926
2927                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
2928                         {
2929                                 if (strcmp($2, ptr->name) == 0)
2930                                         /* re-definition is a bug */
2931                                         mmerror(PARSE_ERROR, ET_ERROR, "cursor %s already defined", $2);
2932                         }
2933
2934                         this = (struct cursor *) mm_alloc(sizeof(struct cursor));
2935
2936                         /* initial definition */
2937                         this->next = cur;
2938                         this->name = $2;
2939                         this->connection = connection;
2940                         this->opened = false;
2941                         this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
2942                         this->argsinsert = argsinsert;
2943                         this->argsresult = argsresult;
2944                         argsinsert = argsresult = NULL;
2945                         cur = this;
2946
2947                         if (INFORMIX_MODE)
2948                                 $$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), mm_strdup(this->command), make_str("*/"));
2949                         else
2950                                 $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
2951                 }
2952                 ;
2953
2954 cursor_options:  /* EMPTY */            { $$ = EMPTY; }
2955         | cursor_options BINARY         { $$ = cat2_str($1, make_str("binary")); }
2956         | cursor_options INSENSITIVE    { $$ = cat2_str($1, make_str("insensitive")); }
2957         | cursor_options SCROLL         { $$ = cat2_str($1, make_str("scroll")); }
2958         | cursor_options NO SCROLL      { $$ = cat2_str($1, make_str("no scroll")); }
2959         ;
2960
2961 opt_hold:       /* EMPTY */             { if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
2962                                                 $$ = make_str("with hold");
2963                                           else
2964                                                  $$ = EMPTY; }
2965         | WITH HOLD                     { $$ = make_str("with hold"); }
2966         | WITHOUT HOLD                  { $$ = make_str("without hold"); }
2967         ;
2968         
2969 /*****************************************************************************
2970  *
2971  *              QUERY:
2972  *                              SELECT STATEMENTS
2973  *
2974  *****************************************************************************/
2975
2976 SelectStmt: select_no_parens            %prec UMINUS
2977                         { $$ = $1; }
2978                 |       select_with_parens              %prec UMINUS
2979                         { $$ = $1; }
2980                 ;
2981
2982 select_with_parens: '(' select_no_parens ')'
2983                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2984                 | '(' select_with_parens ')'
2985                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2986                 ;
2987
2988 select_no_parens:          simple_select
2989                         { $$ = $1; }
2990                 | select_clause sort_clause
2991                         { $$ = cat2_str($1, $2); }
2992                 | select_clause opt_sort_clause for_update_clause opt_select_limit
2993                         { $$ = cat_str(4, $1, $2, $3, $4); }
2994                 | select_clause opt_sort_clause select_limit opt_for_update_clause
2995                         { $$ = cat_str(4, $1, $2, $3, $4); }
2996                 ;
2997
2998 select_clause: simple_select            { $$ = $1; }
2999                 | select_with_parens            { $$ = $1; }
3000                 ;
3001
3002 simple_select:  SELECT opt_distinct target_list
3003                                         into_clause from_clause where_clause
3004                                         group_clause having_clause
3005                         { $$ = cat_str(8, make_str("select"), $2, $3, $4, $5, $6, $7, $8); }
3006                 | select_clause UNION opt_all select_clause
3007                         { $$ = cat_str(4, $1, make_str("union"), $3, $4); }
3008                 | select_clause INTERSECT opt_all select_clause
3009                         { $$ = cat_str(4, $1, make_str("intersect"), $3, $4); }
3010                 | select_clause EXCEPT opt_all select_clause
3011                         { $$ = cat_str(4, $1, make_str("except"), $3, $4); }
3012                 ;
3013
3014 into_clause:  INTO OptTempTableName
3015                 {
3016                         FoundInto = 1;
3017                         $$= cat2_str(make_str("into"), $2);
3018                 }
3019                 | ecpg_into                     { $$ = EMPTY; }
3020                 | /*EMPTY*/                     { $$ = EMPTY; }
3021                 ;
3022
3023 /*
3024  * Redundancy here is needed to avoid shift/reduce conflicts,
3025  * since TEMP is not a reserved word.  See also OptTemp.
3026  *
3027  * The result is a cons cell (not a true list!) containing
3028  * a boolean and a table name.
3029  */
3030 OptTempTableName:  TEMPORARY opt_table qualified_name
3031                         { $$ = cat_str(3, make_str("temporary"), $2, $3); }
3032                 | TEMP opt_table qualified_name
3033                         { $$ = cat_str(3, make_str("temp"), $2, $3); }
3034                 | LOCAL TEMPORARY opt_table qualified_name
3035                         { $$ = cat_str(3, make_str("local temporary"), $3, $4); }
3036                 | LOCAL TEMP opt_table qualified_name
3037                         { $$ = cat_str(3, make_str("local temp"), $3, $4); }
3038                 | GLOBAL TEMPORARY opt_table qualified_name
3039                         { $$ = cat_str(3, make_str("global temporary"), $3, $4); }
3040                 | GLOBAL TEMP opt_table qualified_name
3041                         { $$ = cat_str(3, make_str("global temp"), $3, $4); }
3042                 | TABLE qualified_name
3043                         { $$ = cat2_str(make_str("table"), $2); }
3044                 | qualified_name
3045                         { $$ = $1; }
3046                 ;
3047
3048 opt_table:      TABLE                           { $$ = make_str("table"); }
3049                 | /*EMPTY*/                             { $$ = EMPTY; }
3050                 ;
3051
3052 opt_all:  ALL                                   { $$ = make_str("all"); }
3053                 | /*EMPTY*/                             { $$ = EMPTY; }
3054                 ;
3055
3056 opt_distinct:  DISTINCT
3057                         { $$ = make_str("distinct"); }
3058                 | DISTINCT ON '(' expr_list ')'
3059                         { $$ = cat_str(3, make_str("distinct on ("), $4, make_str(")")); }
3060                 | ALL
3061                         { $$ = make_str("all"); }
3062                 | /*EMPTY*/
3063                         { $$ = EMPTY; }
3064                 ;
3065
3066 opt_sort_clause:        sort_clause     { $$ = $1; }
3067                 | /* EMPTY */           { $$ = EMPTY; }
3068                 ;
3069
3070 sort_clause:  ORDER BY sortby_list
3071                         { $$ = cat2_str(make_str("order by"), $3); }
3072                 ;
3073
3074 sortby_list:  sortby                                    { $$ = $1; }
3075                 | sortby_list ',' sortby                { $$ = cat_str(3, $1, make_str(","), $3); }
3076                 ;
3077
3078 sortby: a_expr USING qual_all_Op
3079                         { $$ = cat_str(3, $1, make_str("using"), $3); }
3080                 | a_expr ASC
3081                         { $$ = cat2_str($1, make_str("asc")); }
3082                 | a_expr DESC
3083                         { $$ = cat2_str($1, make_str("desc")); }
3084                 | a_expr
3085                         { $$ = $1; }
3086                 ;
3087
3088 select_limit:   LIMIT select_limit_value OFFSET select_offset_value
3089                    { $$ = cat_str(4, make_str("limit"), $2, make_str("offset"), $4); }
3090                 | OFFSET select_offset_value LIMIT select_limit_value
3091                    { $$ = cat_str(4, make_str("offset"), $2, make_str("limit"), $4); }
3092                 | LIMIT select_limit_value
3093                    { $$ = cat2_str(make_str("limit"), $2); }
3094                 | OFFSET select_offset_value
3095                    { $$ = cat2_str(make_str("offset"), $2); }
3096                 | LIMIT select_limit_value ',' select_offset_value
3097                    { mmerror(PARSE_ERROR, ET_WARNING, "No longer supported LIMIT #,# syntax passed to backend."); }
3098                 ;
3099
3100 opt_select_limit:       select_limit    { $$ = $1; }
3101                 | /*EMPTY*/                                     { $$ = EMPTY; }
3102                 ;
3103
3104 select_limit_value: a_expr      { $$ = $1; }
3105                 | ALL           { $$ = make_str("all"); }
3106                 ;
3107
3108 select_offset_value: a_expr { $$ = $1; }        
3109                 ;
3110
3111 /*
3112  *      jimmy bell-style recursive queries aren't supported in the
3113  *      current system.
3114  *
3115  *      ...however, recursive addattr and rename supported.  make special
3116  *      cases for these.
3117  */
3118 group_clause:  GROUP_P BY expr_list
3119                         { $$ = cat2_str(make_str("group by"), $3); }
3120                 | /*EMPTY*/
3121                         { $$ = EMPTY; }
3122                 ;
3123
3124 having_clause:  HAVING a_expr
3125                         { $$ = cat2_str(make_str("having"), $2); }
3126                 | /*EMPTY*/
3127                         { $$ = EMPTY; }
3128                 ;
3129
3130 for_update_clause:      FOR UPDATE update_list
3131                         { $$ = make_str("for update"); }
3132                 | FOR READ ONLY
3133                         { $$ = make_str("for read only"); }
3134                 ;
3135
3136 opt_for_update_clause: for_update_clause        { $$ = $1; }
3137                 | /* EMPTY */                                           { $$ = EMPTY; }
3138                 ;
3139
3140 update_list:  OF name_list              { $$ = cat2_str(make_str("of"), $2); }
3141                 | /* EMPTY */                   { $$ = EMPTY; }
3142                 ;
3143
3144 /*****************************************************************************
3145  *
3146  *      clauses common to all Optimizable Stmts:
3147  *              from_clause - allow list of both JOIN expressions and table names
3148  *              where_clause    - qualifications for joins or restrictions
3149  *
3150  *****************************************************************************/
3151
3152 from_clause:    FROM from_list          { $$ = cat2_str(make_str("from"), $2); }
3153                 | /* EMPTY */                           { $$ = EMPTY; }
3154                 ;
3155
3156 from_list:      from_list ',' table_ref { $$ = cat_str(3, $1, make_str(","), $3); }
3157                 | table_ref                                     { $$ = $1; }
3158                 ;
3159
3160 /*
3161  * table_ref is where an alias clause can be attached.  Note we cannot make
3162  * alias_clause have an empty production because that causes parse conflicts
3163  * between table_ref := '(' joined_table ')' alias_clause
3164  * and joined_table := '(' joined_table ')'.  So, we must have the
3165  * redundant-looking productions here instead.
3166  */
3167 table_ref:      relation_expr
3168                         { $$ = $1; }
3169                 | relation_expr alias_clause
3170                         { $$= cat2_str($1, $2); }
3171                 | func_table
3172                         { $$ = $1; }
3173                 | func_table alias_clause
3174                         { $$= cat2_str($1, $2); }
3175                 | func_table AS '(' TableFuncElementList ')'
3176                         { $$=cat_str(4, $1, make_str("as ("), $4, make_str(")")); }
3177                 | func_table AS ColId '(' TableFuncElementList ')'
3178                         { $$=cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")"));}
3179                 | func_table ColId '(' TableFuncElementList ')'
3180                         { $$=cat_str(5, $1, $2, make_str("("), $4, make_str(")")); }
3181                 | select_with_parens
3182                         {mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias");}
3183                 | select_with_parens alias_clause
3184                         { $$=cat2_str($1, $2); }
3185                 | joined_table
3186                         { $$ = $1; }
3187                 | '(' joined_table ')' alias_clause
3188                         { $$=cat_str(4, make_str("("), $2, make_str(")"), $4); }
3189                 ;
3190
3191 /*
3192  * It may seem silly to separate joined_table from table_ref, but there is
3193  * method in SQL92's madness: if you don't do it this way you get reduce-
3194  * reduce conflicts, because it's not clear to the parser generator whether
3195  * to expect alias_clause after ')' or not.  For the same reason we must
3196  * treat 'JOIN' and 'join_type JOIN' separately, rather than allowing
3197  * join_type to expand to empty; if we try it, the parser generator can't
3198  * figure out when to reduce an empty join_type right after table_ref.
3199  *
3200  * Note that a CROSS JOIN is the same as an unqualified
3201  * INNER JOIN, and an INNER JOIN/ON has the same shape
3202  * but a qualification expression to limit membership.
3203  * A NATURAL JOIN implicitly matches column names between
3204  * tables and the shape is determined by which columns are
3205  * in common. We'll collect columns during the later transformations.
3206  */
3207
3208 joined_table:  '(' joined_table ')'
3209                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3210                 | table_ref CROSS JOIN table_ref
3211                         { $$ = cat_str(3, $1, make_str("cross join"), $4); }
3212                 | table_ref UNIONJOIN table_ref
3213                         { $$ = cat_str(3, $1, make_str("unionjoin"), $3); }
3214                 | table_ref join_type JOIN table_ref join_qual
3215                         { $$ = cat_str(5, $1, $2, make_str("join"), $4, $5); }
3216                 | table_ref JOIN table_ref join_qual
3217                         { $$ = cat_str(4, $1, make_str("join"), $3, $4); }
3218                 | table_ref NATURAL join_type JOIN table_ref
3219                         { $$ = cat_str(5, $1, make_str("natural"), $3, make_str("join"), $5); }
3220                 | table_ref NATURAL JOIN table_ref
3221                         { $$ = cat_str(3, $1, make_str("natural join"), $4); }
3222                 ;
3223
3224 alias_clause:  AS ColId '(' name_list ')'
3225                         { $$ = cat_str(5, make_str("as"), $2, make_str("("), $4, make_str(")")); }
3226                 | AS ColId
3227                         { $$ = cat2_str(make_str("as"), $2); }
3228                 | ColId '(' name_list ')'
3229                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
3230                 | ColId
3231                         { $$ = $1; }
3232                 ;
3233
3234 join_type:      FULL join_outer         { $$ = cat2_str(make_str("full"), $2); }
3235                 | LEFT join_outer               { $$ = cat2_str(make_str("left"), $2); }
3236                 | RIGHT join_outer              { $$ = cat2_str(make_str("right"), $2); }
3237                 | INNER_P                               { $$ = make_str("inner"); }
3238                 ;
3239
3240 /* OUTER is just noise... */
3241 join_outer:  OUTER_P                    { $$ = make_str("outer"); }
3242                 | /*EMPTY*/                             { $$ = EMPTY;  /* no qualifiers */ }
3243                 ;
3244
3245 /* JOIN qualification clauses
3246  * Possibilities are:
3247  *      USING ( column list ) allows only unqualified column names,
3248  *                                                which must match between tables.
3249  *      ON expr allows more general qualifications.
3250  */
3251
3252 join_qual:      USING '(' name_list ')'
3253                         { $$ = cat_str(3, make_str("using ("), $3, make_str(")")); }
3254                 | ON a_expr
3255                         { $$ = cat2_str(make_str("on"), $2); }
3256                 ;
3257
3258 relation_expr:  qualified_name
3259                         { /* normal relations */ $$ = $1; }
3260                 | qualified_name '*'
3261                         { /* inheritance query */ $$ = cat2_str($1, make_str("*")); }
3262                 | ONLY qualified_name
3263                         { /* inheritance query */ $$ = cat2_str(make_str("only "), $2); }
3264                 | ONLY '(' qualified_name ')'
3265                         { /* inheritance query */ $$ = cat_str(3, make_str("only ("), $3, make_str(")")); }
3266                 ;
3267
3268 func_table:  func_name '(' ')'
3269                 { $$ = cat2_str($1, make_str("()")); }
3270         | func_name '(' expr_list ')'
3271                 { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
3272         ;
3273
3274 where_clause:  WHERE a_expr             { $$ = cat2_str(make_str("where"), $2); }
3275                 | /*EMPTY*/                             { $$ = EMPTY;  /* no qualifiers */ }
3276                 ;
3277
3278 TableFuncElementList: TableFuncElement
3279                         { $$ = $1; }
3280                 | TableFuncElementList ',' TableFuncElement
3281                         { $$ = cat_str(3, $1, make_str(","), $3); }
3282                 ;
3283
3284 TableFuncElement:       ColId Typename  { $$ = cat2_str($1, $2); }
3285                         ;
3286
3287 /*****************************************************************************
3288  *
3289  *      Type syntax
3290  *              SQL92 introduces a large amount of type-specific syntax.
3291  *              Define individual clauses to handle these cases, and use
3292  *               the generic case to handle regular type-extensible Postgres syntax.
3293  *              - thomas 1997-10-10
3294  *
3295  *****************************************************************************/
3296
3297 Typename:  SimpleTypename opt_array_bounds
3298                         { $$ = cat2_str($1, $2.str); }
3299                 | SETOF SimpleTypename opt_array_bounds
3300                         { $$ = cat_str(3, make_str("setof"), $2, $3); }
3301                 | SimpleTypename ARRAY '[' PosIntConst ']'
3302                         { $$ = cat_str(4, $1, make_str("array ["), $4, make_str("]")); }
3303                 | SETOF SimpleTypename ARRAY '[' PosIntConst ']'
3304                         { $$ = cat_str(5, make_str("setof"), $2, make_str("array ["), $5, make_str("]")); }
3305                 ;
3306
3307
3308 opt_array_bounds:  '[' ']' opt_array_bounds
3309                 {
3310                         $$.index1 = make_str("0");
3311                         $$.index2 = $3.index1;
3312                         $$.str = cat2_str(make_str("[]"), $3.str);
3313                 }
3314                 | '[' Iresult ']' opt_array_bounds
3315                 {
3316                         $$.index1 = strdup($2);
3317                         $$.index2 = $4.index1;
3318                         $$.str = cat_str(4, make_str("["), $2, make_str("]"), $4.str);
3319                 }
3320                 | /* EMPTY */
3321                 {
3322                         $$.index1 = make_str("-1");
3323                         $$.index2 = make_str("-1");
3324                         $$.str= EMPTY;
3325                 }
3326                 ;
3327
3328 Iresult:        PosIntConst             { $$ = $1; }
3329                 | '(' Iresult ')'       { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3330                 | Iresult '+' Iresult   { $$ = cat_str(3, $1, make_str("+"), $3); }
3331                 | Iresult '-' Iresult   { $$ = cat_str(3, $1, make_str("-"), $3); }
3332                 | Iresult '*' Iresult   { $$ = cat_str(3, $1, make_str("*"), $3); }
3333                 | Iresult '/' Iresult   { $$ = cat_str(3, $1, make_str("/"), $3); }
3334                 | Iresult '%' Iresult   { $$ = cat_str(3, $1, make_str("%"), $3); }
3335                 | Sconst                { $$ = $1; }
3336                 | ColId                 { $$ = $1; }
3337                 ;
3338
3339 SimpleTypename:  GenericType            { $$ = $1; }
3340                 | ConstDatetime         { $$ = $1; }
3341                 | Numeric               { $$ = $1; }
3342                 | Bit                   { $$ = $1; }
3343                 | Character             { $$ = $1; }
3344                 | ConstInterval opt_interval
3345                         { $$ = cat2_str($1, $2); }
3346                 | ConstInterval '(' PosIntConst ')' opt_interval
3347                         { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
3348                 | type_name attrs
3349                         { $$ = cat2_str($1, $2);}
3350                 ;
3351
3352 ConstTypename:  GenericType             { $$ = $1; }
3353                 | ConstDatetime         { $$ = $1; }
3354                 | Numeric               { $$ = $1; }
3355                 | ConstBit              { $$ = $1; }
3356                 | ConstCharacter        { $$ = $1; }
3357                 ;
3358
3359 GenericType:  type_name                 { $$ = $1; }
3360                 ;
3361
3362 /* SQL92 numeric data types
3363  * Check FLOAT() precision limits assuming IEEE floating types.
3364  * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30
3365  * - thomas 1997-09-18
3366  */
3367 Numeric:  INT_P
3368                         { $$ = make_str("int"); }
3369                 | INTEGER
3370                         { $$ = make_str("integer"); }
3371                 | SMALLINT
3372                         { $$ = make_str("smallint"); }
3373                 | BIGINT
3374                         { $$ = make_str("bigint"); }
3375                 | REAL
3376                         { $$ = make_str("real"); }
3377                 | FLOAT_P opt_float
3378                         { $$ = cat2_str(make_str("float"), $2); }
3379                 | DOUBLE_P PRECISION
3380                         { $$ = make_str("double precision"); }
3381                 | DECIMAL_P opt_decimal
3382                         { $$ = cat2_str(make_str("decimal"), $2); }
3383                 | DEC opt_decimal
3384                         { $$ = cat2_str(make_str("dec"), $2); }
3385                 | NUMERIC opt_numeric
3386                         { $$ = cat2_str(make_str("numeric"), $2); }
3387                 | BOOLEAN_P
3388                         { $$ = make_str("boolean"); }
3389                 ;
3390
3391 opt_float:      '(' PosIntConst ')'
3392                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3393                 | /*EMPTY*/
3394                         { $$ = EMPTY; }
3395                 ;
3396
3397 opt_numeric:  '(' PosIntConst ',' PosIntConst ')'
3398                         { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
3399                 | '(' PosIntConst ')'
3400                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3401                 | /*EMPTY*/
3402                         { $$ = EMPTY; }
3403                 ;
3404
3405 opt_decimal:  '(' PosIntConst ',' PosIntConst ')'
3406                         { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
3407                 | '(' PosIntConst ')'
3408                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3409                 | /*EMPTY*/
3410                         { $$ = EMPTY; }
3411                 ;
3412
3413 /*
3414  * SQL92 bit-field data types
3415  * The following implements BIT() and BIT VARYING().
3416  */
3417
3418 Bit:    BitWithLength           { $$ = $1; }
3419         | BitWithoutLength      { $$ = $1; }
3420         ;
3421
3422 ConstBit:       BitWithLength   { $$ = $1; }
3423                 | BitWithoutLength      { $$ = $1; }
3424                 ;
3425
3426 BitWithLength:  BIT opt_varying '(' PosIntConst ')'
3427                         { $$ = cat_str(5, make_str("bit"), $2, make_str("("), $4, make_str(")")); }
3428                 ;
3429
3430 BitWithoutLength: BIT opt_varying
3431                         { $$ = cat2_str(make_str("bit"), $2); }
3432                 ;
3433
3434 /*
3435  * SQL92 character data types
3436  * The following implements CHAR() and VARCHAR().
3437  *                                                              - ay 6/95
3438  */
3439 Character:      CharacterWithLength             { $$ = $1; }
3440                 | CharacterWithoutLength        { $$ = $1; }
3441                 ;
3442
3443 ConstCharacter: CharacterWithLength     { $$ = $1; }
3444                 | CharacterWithoutLength      { $$ = $1; }
3445                 ;
3446
3447 CharacterWithLength: character '(' PosIntConst ')' opt_charset
3448                         { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
3449                 ;
3450
3451 CharacterWithoutLength: character opt_charset
3452                         { $$ = cat2_str($1, $2); }
3453                 ;
3454
3455 character:      CHARACTER opt_varying
3456                         { $$ = cat2_str(make_str("character"), $2); }
3457                 | CHAR_P opt_varying
3458                         { $$ = cat2_str(make_str("char"), $2); }
3459                 | VARCHAR
3460                         { $$ = make_str("varchar"); }
3461                 | NATIONAL CHARACTER opt_varying
3462                         { $$ = cat2_str(make_str("national character"), $3); }
3463                 | NATIONAL CHAR_P opt_varying
3464                         { $$ = cat2_str(make_str("national char"), $3); }
3465                 | NCHAR opt_varying
3466                         { $$ = cat2_str(make_str("nchar"), $2); }
3467                 ;
3468
3469 opt_varying:  VARYING
3470                         { $$ = make_str("varying"); }
3471                 | /*EMPTY*/
3472                         { $$ = EMPTY; }
3473                 ;
3474
3475 opt_charset:  CHARACTER SET ColId
3476                         { $$ = cat2_str(make_str("character set"), $3); }
3477                 | /*EMPTY*/
3478                         { $$ = EMPTY; }
3479                 ;
3480
3481 ConstDatetime:  TIMESTAMP '(' PosIntConst ')' opt_timezone
3482                         { $$ = cat_str(4, make_str("timestamp("), $3, make_str(")"), $5); }
3483                 | TIMESTAMP opt_timezone
3484                         { $$ = cat2_str(make_str("timestamp"), $2); }
3485                 | TIME '(' PosIntConst ')' opt_timezone
3486                         { $$ = cat_str(4, make_str("time("), $3, make_str(")"), $5); }
3487                 | TIME opt_timezone
3488                         { $$ = cat2_str(make_str("time"), $2); }
3489                 ;
3490
3491 ConstInterval:  INTERVAL
3492                         { $$ = make_str("interval"); }
3493                 ;
3494
3495 opt_timezone:  WITH TIME ZONE
3496                         { $$ = make_str("with time zone"); }
3497                 | WITHOUT TIME ZONE
3498                         { $$ = make_str("without time zone"); }
3499                 | /*EMPTY*/
3500                         { $$ = EMPTY; }
3501                 ;
3502
3503 opt_interval:  YEAR_P                   { $$ = make_str("year"); }
3504                 | MONTH_P                               { $$ = make_str("month"); }
3505                 | DAY_P                                 { $$ = make_str("day"); }
3506                 | HOUR_P                                { $$ = make_str("hour"); }
3507                 | MINUTE_P                              { $$ = make_str("minute"); }
3508                 | SECOND_P                              { $$ = make_str("second"); }
3509                 | YEAR_P TO MONTH_P             { $$ = make_str("year to month"); }
3510                 | DAY_P TO HOUR_P               { $$ = make_str("day to hour"); }
3511                 | DAY_P TO MINUTE_P             { $$ = make_str("day to minute"); }
3512                 | DAY_P TO SECOND_P             { $$ = make_str("day to second"); }
3513                 | HOUR_P TO MINUTE_P    { $$ = make_str("hour to minute"); }
3514                 | MINUTE_P TO SECOND_P  { $$ = make_str("minute to second"); }
3515                 | HOUR_P TO SECOND_P    { $$ = make_str("hour to second"); }
3516                 | /*EMPTY*/                             { $$ = EMPTY; }
3517                 ;
3518
3519
3520 /*****************************************************************************
3521  *
3522  *      expression grammar
3523  *
3524  *****************************************************************************/
3525                 
3526 /* General expressions
3527  * This is the heart of the expression syntax.
3528  *
3529  * We have two expression types: a_expr is the unrestricted kind, and
3530  * b_expr is a subset that must be used in some places to avoid shift/reduce
3531  * conflicts.  For example, we can't do BETWEEN as "BETWEEN a_expr AND a_expr"
3532  * because that use of AND conflicts with AND as a boolean operator.  So,
3533  * b_expr is used in BETWEEN and we remove boolean keywords from b_expr.
3534  *
3535  * Note that '(' a_expr ')' is a b_expr, so an unrestricted expression can
3536  * always be used by surrounding it with parens.
3537  *
3538  * c_expr is all the productions that are common to a_expr and b_expr;
3539  * it's factored out just to eliminate redundant coding.
3540  */
3541
3542 a_expr:  c_expr
3543                         { $$ = $1; }
3544                 | a_expr TYPECAST Typename
3545                         { $$ = cat_str(3, $1, make_str("::"), $3); }
3546                 | a_expr AT TIME ZONE c_expr
3547                         { $$ = cat_str(3, $1, make_str("at time zone"), $5); }
3548                 /*
3549                  * These operators must be called out explicitly in order to make use
3550                  * of yacc/bison's automatic operator-precedence handling.  All other
3551                  * operator names are handled by the generic productions using "Op",
3552                  * below; and all those operators will have the same precedence.
3553                  *
3554                  * If you add more explicitly-known operators, be sure to add them
3555                  * also to b_expr and to the MathOp list above.
3556                  */
3557                 | '+' a_expr %prec UMINUS
3558                         { $$ = cat2_str(make_str("+"), $2); }
3559                 | '-' a_expr %prec UMINUS
3560                         { $$ = cat2_str(make_str("-"), $2); }
3561                 | '%' a_expr
3562                         { $$ = cat2_str(make_str("%"), $2); }
3563                 | '^' a_expr
3564                         { $$ = cat2_str(make_str("^"), $2); }
3565                 | a_expr '%'
3566                         { $$ = cat2_str($1, make_str("%")); }
3567                 | a_expr '^'
3568                         { $$ = cat2_str($1, make_str("^")); }
3569                 | a_expr '+' a_expr
3570                         { $$ = cat_str(3, $1, make_str("+"), $3); }
3571                 | a_expr '-' a_expr
3572                         { $$ = cat_str(3, $1, make_str("-"), $3); }
3573                 | a_expr '*' a_expr
3574                         { $$ = cat_str(3, $1, make_str("*"), $3); }
3575                 | a_expr '/' a_expr
3576                         { $$ = cat_str(3, $1, make_str("/"), $3); }
3577                 | a_expr '%' a_expr
3578                         { $$ = cat_str(3, $1, make_str("%"), $3); }
3579                 | a_expr '^' a_expr
3580                         { $$ = cat_str(3, $1, make_str("^"), $3); }
3581                 | a_expr '<' a_expr
3582                         { $$ = cat_str(3, $1, make_str("<"), $3); }
3583                 | a_expr '>' a_expr
3584                         { $$ = cat_str(3, $1, make_str(">"), $3); }
3585                 | a_expr '=' a_expr
3586                         { $$ = cat_str(3, $1, make_str("="), $3); }
3587                 | a_expr qual_Op a_expr         %prec Op
3588                         { $$ = cat_str(3, $1, $2, $3); }
3589                 | qual_Op a_expr                %prec Op
3590                         { $$ = cat2_str($1, $2); }
3591                 | a_expr qual_Op                %prec POSTFIXOP
3592                         { $$ = cat2_str($1, $2); }
3593                 | a_expr AND a_expr
3594                         { $$ = cat_str(3, $1, make_str("and"), $3); }
3595                 | a_expr OR a_expr
3596                         { $$ = cat_str(3, $1, make_str("or"), $3); }
3597                 | NOT a_expr
3598                         { $$ = cat2_str(make_str("not"), $2); }
3599                 | a_expr LIKE a_expr
3600                         { $$ = cat_str(3, $1, make_str("like"), $3); }
3601                 | a_expr LIKE a_expr ESCAPE a_expr
3602                         { $$ = cat_str(5, $1, make_str("like"), $3, make_str("escape"), $5); }
3603                 | a_expr NOT LIKE a_expr
3604                         { $$ = cat_str(3, $1, make_str("not like"), $4); }
3605                 | a_expr NOT LIKE a_expr ESCAPE a_expr
3606                         { $$ = cat_str(5, $1, make_str("not like"), $4, make_str("escape"), $6); }
3607                 | a_expr ILIKE a_expr
3608                         { $$ = cat_str(3, $1, make_str("ilike"), $3); }
3609                 | a_expr ILIKE a_expr ESCAPE a_expr
3610                         { $$ = cat_str(5, $1, make_str("ilike"), $3, make_str("escape"), $5); }
3611                 | a_expr NOT ILIKE a_expr
3612                         { $$ = cat_str(3, $1, make_str("not ilike"), $4); }
3613                 | a_expr NOT ILIKE a_expr ESCAPE a_expr
3614                         { $$ = cat_str(5, $1, make_str("not ilike"), $4, make_str("escape"), $6); }
3615                 | a_expr SIMILAR TO a_expr      %prec SIMILAR
3616                         { $$ = cat_str(3, $1, make_str("similar to"), $4); }
3617                 | a_expr SIMILAR TO a_expr ESCAPE a_expr
3618                         { $$ = cat_str(5, $1, make_str("similar to"), $4, make_str("escape"), $6); }
3619                 | a_expr NOT SIMILAR TO a_expr  %prec SIMILAR
3620                         { $$ = cat_str(3, $1, make_str("not similar to"), $5); }
3621                 | a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
3622                         { $$ = cat_str(5, $1, make_str("not similar to"), $5, make_str("escape"), $7); }
3623                 | a_expr ISNULL
3624                         { $$ = cat2_str($1, make_str("isnull")); }
3625                 | a_expr IS NULL_P
3626                         { $$ = cat2_str($1, make_str("is null")); }
3627                 | a_expr NOTNULL
3628                         { $$ = cat2_str($1, make_str("notnull")); }
3629                 | a_expr IS NOT NULL_P
3630                         { $$ = cat2_str($1, make_str("is not null")); }
3631                 /* IS TRUE, IS FALSE, etc used to be function calls
3632                  *      but let's make them expressions to allow the optimizer
3633                  *      a chance to eliminate them if a_expr is a constant string.
3634                  * - thomas 1997-12-22
3635                  *
3636                  *      Created BooleanTest Node type, and changed handling
3637                  *      for NULL inputs
3638                  * - jec 2001-06-18
3639                  */
3640                 | a_expr IS TRUE_P
3641                         { $$ = cat2_str($1, make_str("is true")); }
3642                 | a_expr IS NOT TRUE_P
3643                         { $$ = cat2_str($1, make_str("is not true")); }
3644                 | a_expr IS FALSE_P
3645                         { $$ = cat2_str($1, make_str("is false")); }
3646                 | a_expr IS NOT FALSE_P
3647                         { $$ = cat2_str($1, make_str("is not false")); }
3648                 | a_expr IS UNKNOWN
3649                         { $$ = cat2_str($1, make_str("is unknown")); }
3650                 | a_expr IS NOT UNKNOWN
3651                         { $$ = cat2_str($1, make_str("is not unknown")); }
3652                 | a_expr IS DISTINCT FROM a_expr %prec IS
3653                         { $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
3654                 | a_expr IS OF '(' type_list ')' %prec IS
3655                         { $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
3656                 | a_expr IS NOT OF '(' type_list ')' %prec IS
3657                         { $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
3658                 | a_expr BETWEEN b_expr AND b_expr      %prec BETWEEN
3659                         { $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5); }
3660                 | a_expr NOT BETWEEN b_expr AND b_expr  %prec BETWEEN
3661                         { $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6); }
3662                 | a_expr IN_P in_expr
3663                         { $$ = cat_str(3, $1, make_str("in"), $3); }
3664                 | a_expr NOT IN_P in_expr
3665                         { $$ = cat_str(3, $1, make_str("not in"), $4); }
3666                 | a_expr subquery_Op sub_type select_with_parens %prec Op
3667                         { $$ = cat_str(4, $1, $2, $3, $4); }
3668                 | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
3669                         { $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")")); }
3670                 | UNIQUE select_with_parens %prec Op
3671                         { $$ = cat2_str(make_str("unique"), $2); }
3672                 ;
3673
3674 /* Restricted expressions
3675  *
3676  * b_expr is a subset of the complete expression syntax
3677  *
3678  * Presently, AND, NOT, IS and IN are the a_expr keywords that would
3679  * cause trouble in the places where b_expr is used.  For simplicity, we
3680  * just eliminate all the boolean-keyword-operator productions from b_expr.
3681  */
3682 b_expr:  c_expr
3683                         { $$ = $1; }
3684                 | b_expr TYPECAST Typename
3685                         { $$ = cat_str(3, $1, make_str("::"), $3); }
3686                 | '-' b_expr %prec UMINUS
3687                         { $$ = cat2_str(make_str("-"), $2); }
3688                 | '%' b_expr
3689                         { $$ = cat2_str(make_str("%"), $2); }
3690                 | '^' b_expr
3691                         { $$ = cat2_str(make_str("^"), $2); }
3692                 | b_expr '%'
3693                         { $$ = cat2_str($1, make_str("%")); }
3694                 | b_expr '^'
3695                         { $$ = cat2_str($1, make_str("^")); }
3696                 | b_expr '+' b_expr
3697                         { $$ = cat_str(3, $1, make_str("+"), $3); }
3698                 | b_expr '-' b_expr
3699                         { $$ = cat_str(3, $1, make_str("-"), $3); }
3700                 | b_expr '*' b_expr
3701                         { $$ = cat_str(3, $1, make_str("*"), $3); }
3702                 | b_expr '/' b_expr
3703                         { $$ = cat_str(3, $1, make_str("/"), $3); }
3704                 | b_expr '%' b_expr
3705                         { $$ = cat_str(3, $1, make_str("%"), $3); }
3706                 | b_expr '^' b_expr
3707                         { $$ = cat_str(3, $1, make_str("^"), $3); }
3708                 | b_expr '<' b_expr
3709                         { $$ = cat_str(3, $1, make_str("<"), $3); }
3710                 | b_expr '>' b_expr
3711                         { $$ = cat_str(3, $1, make_str(">"), $3); }
3712                 | b_expr '=' b_expr
3713                         { $$ = cat_str(3, $1, make_str("="), $3); }
3714                 | b_expr Op b_expr
3715                         { $$ = cat_str(3, $1, $2, $3); }
3716                 | qual_Op b_expr                %prec Op
3717                         { $$ = cat2_str($1, $2); }
3718                 | b_expr qual_Op                %prec POSTFIXOP
3719                         { $$ = cat2_str($1, $2); }
3720                 | b_expr IS DISTINCT FROM b_expr %prec IS
3721                         { $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
3722                 | b_expr IS OF '(' b_expr ')' %prec IS
3723                         { $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
3724                 | b_expr IS NOT OF '(' b_expr ')' %prec IS
3725                         { $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
3726                 ;
3727
3728 /*
3729  * Productions that can be used in both a_expr and b_expr.
3730  *
3731  * Note: productions that refer recursively to a_expr or b_expr mostly
3732  * cannot appear here.  However, it's OK to refer to a_exprs that occur
3733  * inside parentheses, such as function arguments; that cannot introduce
3734  * ambiguity to the b_expr syntax.
3735  */
3736 c_expr: columnref
3737                         { $$ = $1;      }
3738                 | AexprConst
3739                         { $$ = $1;      }
3740                 | PARAM opt_indirection
3741                         { $$ = cat2_str(make_str("param"), $2); }
3742                 | '(' a_expr ')' opt_indirection
3743                         { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
3744                 | case_expr
3745                         { $$ = $1; }
3746                 | func_name '(' ')'
3747                         { $$ = cat2_str($1, make_str("()"));    }
3748                 | func_name '(' expr_list ')'
3749                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));        }
3750                 | func_name '(' ALL expr_list ')'
3751                         { $$ = cat_str(4, $1, make_str("( all"), $4, make_str(")"));    }
3752                 | func_name '(' DISTINCT expr_list ')'
3753                         { $$ = cat_str(4, $1, make_str("( distinct"), $4, make_str(")"));  }
3754                 | func_name '(' '*' ')'
3755                         { $$ = cat2_str($1, make_str("(*)")); }
3756                 | CURRENT_DATE
3757                         { $$ = make_str("current_date"); }
3758                 | CURRENT_TIME opt_empty_parentheses
3759                         { $$ = cat2_str(make_str("current_time"), $2); }
3760                 | CURRENT_TIME '(' PosIntConst ')'
3761                         { $$ = make_str("current_time"); }
3762                 | CURRENT_TIMESTAMP opt_empty_parentheses
3763                         { $$ = cat2_str(make_str("current_timestamp"), $2); }
3764                 | CURRENT_TIMESTAMP '(' PosIntConst ')'
3765                         { $$ = make_str("current_timestamp"); }
3766                 | CURRENT_USER opt_empty_parentheses
3767                         { $$ = cat2_str(make_str("current_user"), $2); }
3768                 | SESSION_USER opt_empty_parentheses
3769                         { $$ = cat2_str(make_str("session_user"), $2); }
3770                 | USER opt_empty_parentheses
3771                         { $$ = cat2_str(make_str("user"), $2); }
3772                 | CAST '(' a_expr AS Typename ')'
3773                         { $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); }
3774                 | EXTRACT '(' extract_list ')'
3775                         { $$ = cat_str(3, make_str("extract("), $3, make_str(")")); }
3776                 | OVERLAY '(' overlay_list ')'
3777                         { $$ = cat_str(3, make_str("overlay("), $3, make_str(")")); }
3778                 | POSITION '(' position_list ')'
3779                         { $$ = cat_str(3, make_str("position("), $3, make_str(")")); }
3780                 | SUBSTRING '(' substr_list ')'
3781                         { $$ = cat_str(3, make_str("substring("), $3, make_str(")")); }
3782                 | TREAT '(' a_expr AS Typename ')'
3783                         { $$ = cat_str(5, make_str("treat("), $3, make_str("as"), $5, make_str(")")); }
3784                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3785                 | TRIM '(' BOTH trim_list ')'
3786                         { $$ = cat_str(3, make_str("trim(both"), $4, make_str(")")); }
3787                 | TRIM '(' LEADING trim_list ')'
3788                         { $$ = cat_str(3, make_str("trim(leading"), $4, make_str(")")); }
3789                 | TRIM '(' TRAILING trim_list ')'
3790                         { $$ = cat_str(3, make_str("trim(trailing"), $4, make_str(")")); }
3791                 | TRIM '(' trim_list ')'
3792                         { $$ = cat_str(3, make_str("trim("), $3, make_str(")")); }
3793                 | CONVERT '(' a_expr USING any_name ')'
3794                         { $$ = cat_str(5, make_str("convert("), $3, make_str("using"), $5, make_str(")"));}
3795                 | CONVERT '(' expr_list ')'
3796                         { $$ = cat_str(3, make_str("convert("), $3, make_str(")")); }
3797                 | select_with_parens    %prec UMINUS
3798                         { $$ = $1; }
3799                 | EXISTS select_with_parens
3800                         { $$ = cat2_str(make_str("exists"), $2); }
3801                 | ARRAY select_with_parens
3802                         { $$ = cat2_str(make_str("array"), $2); }
3803                 | ARRAY array_expr
3804                         { $$ = cat2_str(make_str("array"), $2); }
3805                 | row
3806                         { $$ = $1; }
3807                 ;
3808
3809 row: ROW '(' expr_list ')'
3810                 { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
3811         | ROW '(' ')'
3812                 { $$ = make_str("row()"); }
3813         | '(' expr_list ',' a_expr ')'
3814                 { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
3815         ;
3816
3817 sub_type:  ANY          { $$ = make_str("ANY"); }
3818         | SOME          { $$ = make_str("SOME"); }
3819         | ALL           { $$ = make_str("ALL"); }
3820         ;
3821
3822 all_Op:  Op                             { $$ = $1; }
3823         | MathOp                        { $$ = $1; }
3824         ;
3825
3826 MathOp: '+'                             { $$ = make_str("+"); }
3827                 | '-'                   { $$ = make_str("-"); }
3828                 | '*'                   { $$ = make_str("*"); }
3829                 | '%'                   { $$ = make_str("%"); }
3830                 | '^'                   { $$ = make_str("^"); }
3831                 | '/'                   { $$ = make_str("/"); }
3832                 | '<'                   { $$ = make_str("<"); }
3833                 | '>'                   { $$ = make_str(">"); }
3834                 | '='                   { $$ = make_str("="); }
3835                 ;
3836
3837 qual_Op:  Op                            { $$ = $1; }
3838                 | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
3839                 ;
3840
3841 qual_all_Op:  all_Op                            { $$ = $1; }
3842                 | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
3843                 ;
3844
3845 subquery_Op:  all_Op                            { $$ = $1; }
3846                 | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
3847                 | LIKE                          { $$ = make_str("like"); }
3848                 | NOT LIKE                      { $$ = make_str("not like"); }
3849                 | ILIKE                         { $$ = make_str("ilike"); }
3850                 | NOT ILIKE                     { $$ = make_str("not ilike"); }
3851                 ;
3852
3853 expr_list:      a_expr
3854                         { $$ = $1; }
3855                 | expr_list ',' a_expr
3856                         { $$ = cat_str(3, $1, make_str(","), $3); }
3857                 ;
3858
3859 extract_list:  extract_arg FROM a_expr
3860                         { $$ = cat_str(3, $1, make_str("from"), $3); }
3861                 | /* EMPTY */
3862                         { $$ = EMPTY; }
3863                 ;
3864
3865 type_list:      type_list ',' Typename
3866                         { $$ = cat_str(3, $1, ',', $3); }
3867                 | Typename
3868                         { $$ = $1; }
3869                 ;
3870
3871 array_expr_list: array_expr                             { $$ = $1; }
3872                 | array_expr_list ',' array_expr        { $$ = cat_str(3, $1, make_str(","), $3); }
3873                 ;
3874                 
3875
3876 array_expr: '[' expr_list ']'                   { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
3877                 | '[' array_expr_list ']'       { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
3878                 ;
3879 /* Allow delimited string SCONST in extract_arg as an SQL extension.
3880  * - thomas 2001-04-12
3881  */
3882
3883 extract_arg:  ident                             { $$ = $1; }
3884                 | YEAR_P                                { $$ = make_str("year"); }
3885                 | MONTH_P                               { $$ = make_str("month"); }
3886                 | DAY_P                                 { $$ = make_str("day"); }
3887                 | HOUR_P                                { $$ = make_str("hour"); }
3888                 | MINUTE_P                              { $$ = make_str("minute"); }
3889                 | SECOND_P                              { $$ = make_str("second"); }
3890                 | StringConst                   { $$ = $1; }
3891                 ;
3892
3893 overlay_list:
3894                 a_expr overlay_placing substr_from substr_for
3895                         { $$ = cat_str(4, $1, 42, $3, $4); }
3896                 | a_expr overlay_placing substr_from
3897                         { $$ = cat_str(3, $1, $2, $3); }
3898                 ;
3899
3900 overlay_placing:
3901                         PLACING a_expr          { $$ = cat2_str(make_str("placing"), $2); }
3902                         ;
3903
3904 /* position_list uses b_expr not a_expr to avoid conflict with general IN */
3905 position_list:  b_expr IN_P b_expr
3906                         { $$ = cat_str(3, $1, make_str("in"), $3); }
3907                 | /* EMPTY */
3908                         { $$ = EMPTY; }
3909                 ;
3910
3911 substr_list:  a_expr substr_from substr_for
3912                         { $$ = cat_str(3, $1, $2, $3); }
3913                 | a_expr substr_for substr_from
3914                         { $$ = cat_str(3, $1, $2, $3); }
3915                 | a_expr substr_from
3916                         { $$ = cat2_str($1, $2); }
3917                 | a_expr substr_for
3918                         { $$ = cat2_str($1, $2); }
3919                 | expr_list
3920                         { $$ = $1; }
3921                 | /* EMPTY */
3922                         { $$ = EMPTY; }
3923                 ;
3924
3925 substr_from:  FROM a_expr
3926                         { $$ = cat2_str(make_str("from"), $2); }
3927                 ;
3928
3929 substr_for:  FOR a_expr
3930                         { $$ = cat2_str(make_str("for"), $2); }
3931                 ;
3932
3933 trim_list:      a_expr FROM expr_list
3934                         { $$ = cat_str(3, $1, make_str("from"), $3); }
3935                 | FROM expr_list
3936                         { $$ = cat2_str(make_str("from"), $2); }
3937                 | expr_list
3938                         { $$ = $1; }
3939                 ;
3940
3941 in_expr:  select_with_parens
3942                         { $$ = $1; }
3943                 | '(' expr_list ')'
3944                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3945                 ;
3946
3947 /* Case clause
3948  * Define SQL92-style case clause.
3949  * Allow all four forms described in the standard:
3950  * - Full specification
3951  *      CASE WHEN a = b THEN c ... ELSE d END
3952  * - Implicit argument
3953  *      CASE a WHEN b THEN c ... ELSE d END
3954  * - Conditional NULL
3955  *      NULLIF(x,y)
3956  *      same as CASE WHEN x = y THEN NULL ELSE x END
3957  * - Conditional substitution from list, use first non-null argument
3958  *      COALESCE(a,b,...)
3959  * same as CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ... END
3960  * - thomas 1998-11-09
3961  */
3962 case_expr:      CASE case_arg when_clause_list case_default END_P
3963                         { $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); }
3964                 | NULLIF '(' a_expr ',' a_expr ')'
3965                         { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); }
3966                 | COALESCE '(' expr_list ')'
3967                         { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); }
3968                 ;
3969
3970 when_clause_list:  when_clause_list when_clause
3971                         { $$ = cat2_str($1, $2); }
3972                 | when_clause
3973                         { $$ = $1; }
3974                 ;
3975
3976 when_clause:  WHEN a_expr THEN a_expr
3977                         { $$ = cat_str(4, make_str("when"), $2, make_str("then"), $4); }
3978                 ;
3979
3980 case_default:  ELSE a_expr
3981                         { $$ = cat2_str(make_str("else"), $2); }
3982                 | /*EMPTY*/
3983                         { $$ = EMPTY; }
3984                 ;
3985
3986 case_arg:  a_expr                       { $$ = $1; }
3987                 | /*EMPTY*/             { $$ = EMPTY; }
3988                 ;
3989
3990 columnref: relation_name                { $$ = $1; }
3991         | relation_name indirection     { $$ = cat2_str($1, $2); }
3992         ;
3993
3994 indirection_el:
3995         '.' attr_name                   { $$ = cat2_str(make_str("."), $2); }
3996         | '.' '*'                       { $$ = make_str(".*"); }
3997         | '[' a_expr ']'                { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
3998         | '[' a_expr ':' a_expr ']'     { $$ = cat_str(5, make_str("["), $2, make_str(":"), $4, make_str("]")); }
3999         ;
4000
4001 indirection:    indirection_el          { $$ = $1; }
4002         | indirection indirection_el    { $$ = cat2_str($1, $2); }
4003         ;
4004
4005 opt_indirection:
4006         /*EMPTY*/                               { $$ = EMPTY; }
4007         | opt_indirection indirection_el        { $$ = cat2_str($1, $2);} 
4008         ;
4009         
4010 opt_empty_parentheses: '(' ')'  { $$ = make_str("()"); }
4011                 | /*EMPTY*/                             { $$ = EMPTY; }
4012                 ;
4013
4014
4015 /*****************************************************************************
4016  *
4017  *      target lists for SELECT, UPDATE, INSERT
4018  *
4019  *****************************************************************************/
4020
4021 target_list:  target_list ',' target_el
4022                         { $$ = cat_str(3, $1, make_str(","), $3);  }
4023                 | target_el
4024                         { $$ = $1;      }
4025                 ;
4026
4027 /* AS is not optional because shift/red conflict with unary ops */
4028 target_el:      a_expr AS ColLabel
4029                         { $$ = cat_str(3, $1, make_str("as"), $3); }
4030                 | a_expr
4031                         { $$ = $1; }
4032                 | '*'
4033                         { $$ = make_str("*"); }
4034                 ;
4035
4036 /* Target list as found in UPDATE table SET ... */
4037 update_target_list:  update_target_list ',' update_target_el
4038                         { $$ = cat_str(3, $1, make_str(","),$3);        }
4039                 | '(' inf_col_list ')' '=' '(' inf_val_list ')'
4040                         {
4041                                 struct inf_compat_col *ptrc;
4042                                 struct inf_compat_val *ptrv;
4043                                 char *cols = make_str( "(" );
4044                                 char *vals = make_str( "(" );
4045                                 
4046                                 for (ptrc = informix_col, ptrv = informix_val; ptrc != NULL && ptrv != NULL; ptrc = ptrc->next, ptrv = ptrv->next)
4047                                 {
4048                                         if ( ptrc->next != NULL )
4049                                         {
4050                                                 cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(",") );
4051                                         }
4052                                         else
4053                                         {
4054                                                 cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(")") );
4055                                         }
4056                                         if (ptrv->next != NULL )
4057                                                 vals = cat_str(3, vals, ptrv->val, make_str("," ) );
4058                                         else
4059                                                 vals = cat_str( 3, vals, ptrv->val, make_str(")") );
4060                                 }
4061                                 $$ = cat_str( 3, cols, make_str("="), vals );
4062                         }
4063                 | update_target_el
4064                         { $$ = $1;      }
4065                 ;
4066
4067 inf_col_list: ColId opt_indirection
4068                 {
4069                         struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col));
4070                         
4071                         ptr->name = $1;
4072                         ptr->indirection = $2;
4073                         ptr->next = NULL;
4074                         informix_col = ptr;
4075                 }
4076                 | ColId opt_indirection ',' inf_col_list
4077                 {
4078                         struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col));
4079                 
4080                         ptr->name = $1;
4081                         ptr->indirection = $2;
4082                         ptr->next = informix_col;
4083                         informix_col = ptr;
4084                 }
4085                 ;
4086                 
4087 inf_val_list: a_expr
4088                 {
4089                         struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val));
4090                         
4091                         ptr->val = $1;
4092                         ptr->next = NULL;
4093                         informix_val = ptr;
4094                 }
4095                 | a_expr ',' inf_val_list
4096                 {
4097                         struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val));
4098                 
4099                         ptr->val = $1;
4100                         ptr->next = informix_val;
4101                         informix_val = ptr;
4102                 }
4103                 ;
4104
4105 update_target_el:  ColId opt_indirection '=' a_expr
4106                         { $$ = cat_str(4, $1, $2, make_str("="), $4); }
4107                 | ColId opt_indirection '=' DEFAULT
4108                         { $$ = cat_str(3, $1, $2, make_str("= default")); }
4109                 ;
4110
4111 insert_target_list:  insert_target_list ',' insert_target_el
4112                                 {       $$ = cat_str(3, $1, make_str(","), $3);  }
4113                 | insert_target_el
4114                                 {       $$ = $1;  }
4115                 ;
4116
4117 insert_target_el:  a_expr       { $$ = $1;  }
4118                 | DEFAULT       { $$ = make_str("default"); }
4119                 ;
4120
4121
4122 /*****************************************************************************
4123  *
4124  *         Names and constants
4125  *
4126  *****************************************************************************/
4127
4128 relation_name:  SpecialRuleRelation     { $$ = $1; }
4129                 | ColId                 { $$ = $1; }
4130                 ;
4131
4132 qualified_name_list:  qualified_name
4133                                 { $$ = $1; }
4134                 | qualified_name_list ',' qualified_name
4135                                 { $$ = cat_str(3, $1, make_str(","), $3); }
4136                 ;
4137
4138 qualified_name: relation_name
4139                 { $$ = $1; }
4140                 | relation_name attrs
4141                 { $$ = cat2_str($1, $2); }
4142                 ;
4143
4144 name_list:  name
4145                         { $$ = $1; }
4146                 | name_list ',' name
4147                         { $$ = cat_str(3, $1, make_str(","), $3); }
4148                 ;
4149
4150
4151 name:                           ColId                   { $$ = $1; };
4152 database_name:                  ColId                   { $$ = $1; };
4153 access_method:                  ColId                   { $$ = $1; };
4154 attr_name:                              ColId                   { $$ = $1; };
4155 index_name:                             ColId                   { $$ = $1; };
4156
4157 file_name:                              StringConst             { $$ = $1; };
4158
4159 func_name: function_name
4160                         { $$ = $1; }
4161                 | relation_name indirection
4162                         { $$ = cat2_str($1, $2); }
4163                 ;
4164
4165
4166 /* Constants
4167  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
4168  */
4169 AexprConst:  PosAllConst
4170                         { $$ = $1; }
4171                 | ConstTypename StringConst
4172                         { $$ = cat2_str($1, $2); }
4173                 | ConstInterval StringConst opt_interval
4174                         { $$ = cat_str(3, $1, $2, $3); }
4175                 | ConstInterval  '(' PosIntConst ')' StringConst opt_interval
4176                         { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
4177                 | TRUE_P
4178                         { $$ = make_str("true"); }
4179                 | FALSE_P
4180                         { $$ = make_str("false"); }
4181                 | NULL_P
4182                         { $$ = make_str("null"); }
4183                 | civarind
4184                         { $$ = $1; }
4185                 ;
4186
4187 Iconst:  ICONST                         { $$ = make_name();};
4188 Fconst:  FCONST                         { $$ = make_name();};
4189 Bconst:  BCONST                         { $$ = make_name();};
4190 Xconst:  XCONST                         { $$ = make_name();};
4191 Sconst:  SCONST
4192                 {
4193                         $$ = (char *)mm_alloc(strlen($1) + 3);
4194                         $$[0]='\'';
4195                                         strcpy($$+1, $1);
4196                         $$[strlen($1)+2]='\0';
4197                         $$[strlen($1)+1]='\'';
4198                         free($1);
4199                 }
4200                 ;
4201
4202 PosIntConst:    Iconst          { $$ = $1; }
4203                 | civar         { $$ = $1; }
4204                 ;
4205
4206 IntConst:       PosIntConst             { $$ = $1; }
4207                 | '-' PosIntConst       { $$ = cat2_str(make_str("-"), $2); }
4208                 ;
4209
4210 IntConstVar:    Iconst  
4211                 {
4212                         char *length = mm_alloc(32);
4213
4214                         sprintf(length, "%d", (int) strlen($1));
4215                         new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0);
4216                         $$ = $1;
4217                 }
4218                 | cvariable     { $$ = $1; }
4219                 ;
4220
4221 AllConstVar:    Fconst
4222                 {
4223                         char *length = mm_alloc(32);
4224                         
4225                         sprintf(length, "%d", (int) strlen($1));
4226                         new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0);
4227                         $$ = $1;
4228                 }
4229                 | IntConstVar           { $$ = $1; }
4230                 | '-' Fconst
4231                 {
4232                         char *length = mm_alloc(32);
4233                         char *var = cat2_str(make_str("-"), $2);
4234                         
4235                         sprintf(length, "%d", (int) strlen(var));
4236                         new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
4237                         $$ = var;
4238                 }
4239                 | '-' Iconst
4240                 {
4241                         char *length = mm_alloc(32);
4242                         char *var = cat2_str(make_str("-"), $2);
4243                         
4244                         sprintf(length, "%d", (int) strlen(var));
4245                         new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
4246                         $$ = var;
4247                 }
4248                 | Sconst                
4249                 {
4250                         char *length = mm_alloc(32);
4251                         char *var = $1 + 1;
4252                         
4253                         var[strlen(var) - 1] = '\0';
4254                         sprintf(length, "%d", (int) strlen(var));
4255                         new_variable(var, ECPGmake_simple_type(ECPGt_const, length), 0);
4256                         $$ = var;
4257                 }
4258                 ;
4259
4260 StringConst:    Sconst          { $$ = $1; }
4261                 | civar         { $$ = $1; }
4262                 ;
4263
4264 PosIntStringConst:      Iconst  { $$ = $1; }
4265                 | Sconst        { $$ = $1; } 
4266                 | civar         { $$ = $1; }
4267                 ;
4268
4269 NumConst:       Fconst                  { $$ = $1; }
4270                 | Iconst                { $$ = $1; }
4271                 | '-' Fconst            { $$ = cat2_str(make_str("-"), $2); }
4272                 | '-' Iconst            { $$ = cat2_str(make_str("-"), $2); } 
4273                 | civar                 { $$ = $1; }
4274                 ;
4275
4276 AllConst:       Sconst                  { $$ = $1; }
4277                 | NumConst              { $$ = $1; }
4278                 ;
4279
4280 PosAllConst:    Sconst          { $$ = $1; }
4281                 | Fconst        { $$ = $1; }
4282                 | Iconst        { $$ = $1; }
4283                 | Bconst        { $$ = $1; }
4284                 | Xconst        { $$ = $1; }
4285                 | civar         { $$ = $1; }
4286                 ;
4287
4288 UserId:  ColId                          { $$ = $1;};
4289
4290 SpecialRuleRelation:  OLD
4291                 {
4292                         if (!QueryIsRule)
4293                                 mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query");
4294
4295                         $$ = make_str("old");
4296                 }
4297                 | NEW
4298                 {
4299                         if (!QueryIsRule)
4300                                 mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query");
4301
4302                         $$ = make_str("new");
4303                 }
4304                 ;
4305
4306 /*
4307  * and now special embedded SQL stuff
4308  */
4309
4310 /*
4311  * the exec sql connect statement: connect to the given database
4312  */
4313 ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
4314                         { $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); }
4315                 | SQL_CONNECT TO DEFAULT
4316                         { $$ = make_str("NULL,NULL,NULL,\"DEFAULT\""); }
4317                   /* also allow ORACLE syntax */
4318                 | SQL_CONNECT ora_user
4319                         { $$ = cat_str(3, make_str("NULL,"), $2, make_str(",NULL")); }
4320                 | DATABASE connection_target
4321                         { $$ = cat2_str($2, make_str(",NULL,NULL,NULL")); }
4322                 ;
4323
4324 connection_target: database_name opt_server opt_port
4325                 {
4326                         /* old style: dbname[@server][:port] */
4327                         if (strlen($2) > 0 && *($2) != '@')
4328                                 mmerror(PARSE_ERROR, ET_ERROR, "Expected '@', found '%s'", $2);
4329
4330                         $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
4331                 }
4332                 |  db_prefix ':' server opt_port '/' database_name opt_options
4333                 {
4334                         /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
4335                         if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
4336                                 mmerror(PARSE_ERROR, ET_ERROR, "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported");
4337
4338                         if (strncmp($3, "//", strlen("//")) != 0)
4339                                 mmerror(PARSE_ERROR, ET_ERROR, "Expected '://', found '%s'", $3);
4340
4341                         if (strncmp($1, "unix", strlen("unix")) == 0 &&
4342                                 strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
4343                                 strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
4344                                 mmerror(PARSE_ERROR, ET_ERROR, "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//"));
4345
4346                         $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),    $7, make_str("\"")));
4347                 }
4348                 | Sconst
4349                 {
4350                         if ($1[0] == '\"')
4351                                 $$ = $1;
4352                         else
4353                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
4354                 }
4355                 | char_variable
4356                 {
4357                         $$ = $1;
4358                 }
4359                 ;
4360
4361 db_prefix: ident cvariable
4362                 {
4363                         if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
4364                                 mmerror(PARSE_ERROR, ET_ERROR, "Expected 'postgresql', found '%s'", $2);
4365
4366                         if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
4367                                 mmerror(PARSE_ERROR, ET_ERROR, "Illegal connection type %s", $1);
4368
4369                         $$ = make3_str($1, make_str(":"), $2);
4370                 }
4371                 ;
4372
4373 server: Op server_name
4374                 {
4375                         if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
4376                                 mmerror(PARSE_ERROR, ET_ERROR, "Expected '@' or '://', found '%s'", $1);
4377
4378                         $$ = make2_str($1, $2);
4379                 }
4380                 ;
4381
4382 opt_server: server                      { $$ = $1; }
4383                 | /*EMPTY*/                     { $$ = EMPTY; }
4384                 ;
4385
4386 server_name: ColId                                      { $$ = $1; }
4387                 | ColId '.' server_name         { $$ = make3_str($1, make_str("."), $3); }
4388                 | IP                                            { $$ = make_name(); }
4389                 ;
4390
4391 opt_port: ':' PosIntConst       { $$ = make2_str(make_str(":"), $2); }
4392                 | /*EMPTY*/                     { $$ = EMPTY; }
4393                 ;
4394
4395 opt_connection_name: AS connection_target { $$ = $2; }
4396                 | /*EMPTY*/                     { $$ = make_str("NULL"); }
4397                 ;
4398
4399 opt_user: USER ora_user         { $$ = $2; }
4400                 | /*EMPTY*/                     { $$ = make_str("NULL,NULL"); }
4401                 ;
4402
4403 ora_user: user_name
4404                         { $$ = cat2_str($1, make_str(", NULL")); }
4405                 | user_name '/' user_name
4406                         { $$ = cat_str(3, $1, make_str(","), $3); }
4407                 | user_name SQL_IDENTIFIED BY user_name
4408                         { $$ = cat_str(3, $1, make_str(","), $4); }
4409                 | user_name USING user_name
4410                         { $$ = cat_str(3, $1, make_str(","), $3); }
4411                 ;
4412
4413 user_name: UserId
4414                 {
4415                         if ($1[0] == '\"')
4416                                 $$ = $1;
4417                         else
4418                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
4419                 }
4420                 | StringConst
4421                 {
4422                         if ($1[0] == '\"')
4423                                 $$ = $1;
4424                         else if (strcmp($1, " ?") == 0) /* variable */
4425                         {
4426                                 enum ECPGttype type = argsinsert->variable->type->type;
4427
4428                                 /* if array see what's inside */
4429                                 if (type == ECPGt_array)
4430                                         type = argsinsert->variable->type->u.element->type;
4431
4432                                 /* handle varchars */
4433                                 if (type == ECPGt_varchar)
4434                                         $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
4435                                 else
4436                                         $$ = mm_strdup(argsinsert->variable->name);
4437                         }
4438                         else
4439                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
4440                 }
4441                 ;
4442
4443 char_variable: cvariable
4444                 {
4445                         /* check if we have a string variable */
4446                         struct variable *p = find_variable($1);
4447                         enum ECPGttype type = p->type->type;
4448
4449                         /* If we have just one character this is not a string */
4450                         if (atol(p->type->size) == 1)
4451                                         mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
4452                         else
4453                         {
4454                                 /* if array see what's inside */
4455                                 if (type == ECPGt_array)
4456                                         type = p->type->u.element->type;
4457
4458                                 switch (type)
4459                                 {
4460                                         case ECPGt_char:
4461                                         case ECPGt_unsigned_char:
4462                                                 $$ = $1;
4463                                                 break;
4464                                         case ECPGt_varchar:
4465                                                 $$ = make2_str($1, make_str(".arr"));
4466                                                 break;
4467                                         default:
4468                                                 mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
4469                                                 break;
4470                                 }
4471                         }
4472                 }
4473                 ;
4474
4475 opt_options: Op ColId
4476                 {
4477                         if (strlen($1) == 0)
4478                                 mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
4479
4480                         if (strcmp($1, "?") != 0)
4481                                 mmerror(PARSE_ERROR, ET_ERROR, "unrecognised token '%s'", $1);
4482
4483                         $$ = make2_str(make_str("?"), $2);
4484                 }
4485                 | /*EMPTY*/     { $$ = EMPTY; }
4486                 ;
4487
4488 /*
4489  * Declare a prepared cursor. The syntax is different from the standard
4490  * declare statement, so we create a new rule.
4491  */
4492 ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
4493                 {
4494                         struct cursor *ptr, *this;
4495                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
4496
4497                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
4498                         {
4499                                 if (strcmp($2, ptr->name) == 0)
4500                                         /* re-definition is a bug */
4501                                         mmerror(PARSE_ERROR, ET_ERROR, "cursor %s already defined", $2);
4502                         }
4503
4504                         this = (struct cursor *) mm_alloc(sizeof(struct cursor));
4505
4506                         /* initial definition */
4507                         this->next = cur;
4508                         this->name = $2;
4509                         this->connection = connection;
4510                         this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for ?"));
4511                         this->argsresult = NULL;
4512
4513                         thisquery->type = &ecpg_query;
4514                         thisquery->brace_level = 0;
4515                         thisquery->next = NULL;
4516                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement()") + strlen($7));
4517                         sprintf(thisquery->name, "ECPGprepared_statement(%s)", $7);
4518
4519                         this->argsinsert = NULL;
4520                         add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
4521
4522                         cur = this;
4523
4524                         $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
4525                 }
4526                 ;
4527
4528 /*
4529  * the exec sql deallocate prepare command to deallocate a previously
4530  * prepared statement
4531  */
4532 ECPGDeallocate: DEALLOCATE PREPARE prepared_name
4533                         { $$ = $3; }
4534                 | DEALLOCATE prepared_name
4535                         { $$ = $2; }
4536                 ;
4537
4538 /* 
4539  * variable decalartion outside exec sql declare block
4540  */
4541 ECPGVarDeclaration: single_vt_declaration;
4542
4543 single_vt_declaration: type_declaration         { $$ = $1; }
4544                 | single_var_declaration        { $$ = $1; }
4545                 ;
4546         
4547 single_var_declaration: storage_declaration 
4548                 var_type
4549                 {
4550                         actual_type[struct_level].type_enum = $2.type_enum;
4551                         actual_type[struct_level].type_dimension = $2.type_dimension;
4552                         actual_type[struct_level].type_index = $2.type_index;
4553                         actual_type[struct_level].type_sizeof = $2.type_sizeof;
4554
4555                         actual_startline[struct_level] = hashline_number();
4556                 }
4557                 variable_list ';'
4558                 {
4559                         $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
4560                 }
4561                 | var_type
4562                 {
4563                         actual_type[struct_level].type_enum = $1.type_enum;
4564                         actual_type[struct_level].type_dimension = $1.type_dimension;
4565                         actual_type[struct_level].type_index = $1.type_index;
4566                         actual_type[struct_level].type_sizeof = $1.type_sizeof;
4567
4568                         actual_startline[struct_level] = hashline_number();
4569                 }
4570                 variable_list ';'
4571                 {
4572                         $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
4573                 }
4574                 | struct_union_type_with_symbol ';'
4575                 {
4576                         $$ = cat2_str($1, make_str(";"));
4577                 }
4578                 ;
4579
4580 precision:      NumConst        { $$ = $1; };
4581
4582 opt_scale:      ',' NumConst    { $$ = $2; }
4583                 | /* EMPTY */   { $$ = EMPTY; }
4584                 ;
4585
4586 ecpg_interval:  opt_interval    { $$ = $1; }
4587                 | YEAR_P TO MINUTE_P    { $$ = make_str("year to minute"); }
4588                 | YEAR_P TO SECOND_P    { $$ = make_str("year to second"); }
4589                 | DAY_P TO DAY_P        { $$ = make_str("day to day"); }
4590                 | MONTH_P TO MONTH_P    { $$ = make_str("month to month"); }
4591                 ;
4592
4593 /*
4594  * variable declaration inside exec sql declare block
4595  */
4596 ECPGDeclaration: sql_startdeclare
4597                 { fputs("/* exec sql begin declare section */", yyout); }
4598                 var_type_declarations sql_enddeclare
4599                 {
4600                         fprintf(yyout, "%s/* exec sql end declare section */", $3);
4601                         free($3);
4602                         output_line_number();
4603                 }
4604                 ;
4605
4606 sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
4607
4608 sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
4609
4610 var_type_declarations:  /*EMPTY*/                       { $$ = EMPTY; }
4611                 | vt_declarations                       { $$ = $1; }
4612                 ;
4613
4614 vt_declarations:  var_declaration                       { $$ = $1; }
4615                 | type_declaration                      { $$ = $1; }
4616                 | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
4617                 | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
4618                 ;
4619
4620 variable_declarations:  var_declaration                         { $$ = $1; }
4621                 | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
4622                 ;
4623
4624 type_declaration: S_TYPEDEF
4625         {
4626                 /* reset this variable so we see if there was */
4627                 /* an initializer specified */
4628                 initializer = 0;
4629         }
4630         var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
4631         {
4632                 /* add entry to list */
4633                 struct typedefs *ptr, *this;
4634                 char * dimension = $6.index1;
4635                 char * length = $6.index2;
4636
4637                 if (($3.type_enum == ECPGt_struct ||
4638                      $3.type_enum == ECPGt_union) &&
4639                     initializer == 1)
4640                 {
4641                         mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command");
4642
4643                 }
4644                 else
4645                 {
4646                         for (ptr = types; ptr != NULL; ptr = ptr->next)
4647                         {
4648                                 if (strcmp($5, ptr->name) == 0)
4649                                         /* re-definition is a bug */
4650                                         mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", $5);
4651                         }
4652                         adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0, true);
4653
4654                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
4655
4656                         /* initial definition */
4657                         this->next = types;
4658                         this->name = $5;
4659                         this->brace_level = braces_open;
4660                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
4661                         this->type->type_enum = $3.type_enum;
4662                         this->type->type_str = mm_strdup($5);
4663                         this->type->type_dimension = dimension; /* dimension of array */
4664                         this->type->type_index = length;    /* length of string */
4665                         this->type->type_sizeof = ECPGstruct_sizeof;
4666                         this->struct_member_list = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ?
4667                                 struct_member_list[struct_level] : NULL;
4668
4669                         if ($3.type_enum != ECPGt_varchar &&
4670                             $3.type_enum != ECPGt_char &&
4671                             $3.type_enum != ECPGt_unsigned_char &&
4672                             atoi(this->type->type_index) >= 0)
4673                                 mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
4674
4675                         types = this;
4676                 }
4677
4678                 fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4?"*":"", $5, $6.str);
4679                 output_line_number();
4680                 $$ = make_str("");
4681         };
4682
4683 var_declaration: storage_declaration
4684                 var_type
4685                 {
4686                         actual_type[struct_level].type_enum = $2.type_enum;
4687                         actual_type[struct_level].type_dimension = $2.type_dimension;
4688                         actual_type[struct_level].type_index = $2.type_index;
4689                         actual_type[struct_level].type_sizeof = $2.type_sizeof;
4690
4691                         actual_startline[struct_level] = hashline_number();
4692                 }
4693                 variable_list ';'
4694                 {
4695                         $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
4696                 }
4697                 | var_type
4698                 {
4699                         actual_type[struct_level].type_enum = $1.type_enum;
4700                         actual_type[struct_level].type_dimension = $1.type_dimension;
4701                         actual_type[struct_level].type_index = $1.type_index;
4702                         actual_type[struct_level].type_sizeof = $1.type_sizeof;
4703                         
4704                         actual_startline[struct_level] = hashline_number();
4705                 }
4706                 variable_list ';'
4707                 {
4708                         $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
4709                 }
4710                 | struct_union_type_with_symbol ';'
4711                 {
4712                         $$ = cat2_str($1, make_str(";"));
4713                 }
4714                 ;
4715
4716 storage_declaration: storage_clause storage_modifier
4717                 {
4718                         $$ = cat2_str ($1, $2);
4719                 }
4720                 | storage_clause
4721                 {
4722                         $$ = $1;
4723                 }
4724                 | storage_modifier
4725                 {
4726                         $$ = $1;
4727                 }
4728                 ;
4729
4730 storage_clause : S_EXTERN               { $$ = make_str("extern"); }
4731                 | S_STATIC              { $$ = make_str("static"); }
4732                 | S_REGISTER            { $$ = make_str("register"); }
4733                 | S_AUTO                { $$ = make_str("auto"); }
4734                 ;
4735
4736 storage_modifier : S_CONST              { $$ = make_str("const"); }
4737                 | S_VOLATILE            { $$ = make_str("volatile"); }
4738                 ;
4739
4740 var_type:       simple_type
4741                 {
4742                         $$.type_enum = $1;
4743                         $$.type_str = mm_strdup(ECPGtype_name($1));
4744                         $$.type_dimension = make_str("-1");
4745                         $$.type_index = make_str("-1");
4746                         $$.type_sizeof = NULL;
4747                 }
4748                 | struct_union_type
4749                 {
4750                         $$.type_str = $1;
4751                         $$.type_dimension = make_str("-1");
4752                         $$.type_index = make_str("-1");
4753
4754                         if (strncmp($1, "struct", sizeof("struct")-1) == 0)
4755                         {
4756                                 $$.type_enum = ECPGt_struct;
4757                                 $$.type_sizeof = ECPGstruct_sizeof;
4758                         }
4759                         else
4760                         {
4761                                 $$.type_enum = ECPGt_union;
4762                                 $$.type_sizeof = NULL;
4763                         }
4764                 }
4765                 | enum_type
4766                 {
4767                         $$.type_str = $1;
4768                         $$.type_enum = ECPGt_int;
4769                         $$.type_dimension = make_str("-1");
4770                         $$.type_index = make_str("-1");
4771                         $$.type_sizeof = NULL;
4772                 }
4773                 | ECPGColLabelCommon '(' precision opt_scale ')'
4774                 {
4775                         if (strcmp($1, "numeric") == 0)
4776                         {
4777                                 $$.type_enum = ECPGt_numeric;
4778                                 $$.type_str = make_str("numeric");
4779                         }
4780                         else if (strcmp($1, "decimal") == 0)
4781                         {
4782                                 $$.type_enum = ECPGt_decimal;
4783                                 $$.type_str = make_str("decimal");
4784                         }
4785                         else
4786                         {
4787                                 mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument");
4788                                 $$.type_enum = ECPGt_numeric;
4789                                 $$.type_str = make_str("numeric");
4790                         }
4791                         
4792                         $$.type_dimension = make_str("-1");
4793                         $$.type_index = make_str("-1");
4794                         $$.type_sizeof = NULL;
4795                 }
4796                 | ECPGColLabelCommon ecpg_interval
4797                 {
4798                         if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
4799                                 mmerror (PARSE_ERROR, ET_ERROR, "Interval specification not allowed here ");
4800                         
4801                         /*
4802                          * Check for type names that the SQL grammar treats as
4803                          * unreserved keywords
4804                          */
4805                         if (strcmp($1, "varchar") == 0)
4806                         {
4807                                 $$.type_enum = ECPGt_varchar;
4808                                 $$.type_str = EMPTY; /*make_str("varchar");*/
4809                                 $$.type_dimension = make_str("-1");
4810                                 $$.type_index = make_str("-1");
4811                                 $$.type_sizeof = NULL;
4812                         }
4813                         else if (strcmp($1, "float") == 0)
4814                         {
4815                                 $$.type_enum = ECPGt_float;
4816                                 $$.type_str = make_str("float");
4817                                 $$.type_dimension = make_str("-1");
4818                                 $$.type_index = make_str("-1");
4819                                 $$.type_sizeof = NULL;
4820                         }
4821                         else if (strcmp($1, "double") == 0)
4822                         {
4823                                 $$.type_enum = ECPGt_double;
4824                                 $$.type_str = make_str("double");
4825                                 $$.type_dimension = make_str("-1");
4826                                 $$.type_index = make_str("-1");
4827                                 $$.type_sizeof = NULL;
4828                         }
4829                         else if (strcmp($1, "numeric") == 0)
4830                         {
4831                                 $$.type_enum = ECPGt_numeric;
4832                                 $$.type_str = make_str("numeric");
4833                                 $$.type_dimension = make_str("-1");
4834                                 $$.type_index = make_str("-1");
4835                                 $$.type_sizeof = NULL;
4836                         }
4837                         else if (strcmp($1, "decimal") == 0)
4838                         {
4839                                 $$.type_enum = ECPGt_decimal;
4840                                 $$.type_str = make_str("decimal");
4841                                 $$.type_dimension = make_str("-1");
4842                                 $$.type_index = make_str("-1");
4843                                 $$.type_sizeof = NULL;
4844                         }
4845                         else if (strcmp($1, "date") == 0)
4846                         {
4847                                 $$.type_enum = ECPGt_date;
4848                                 $$.type_str = make_str("date");
4849                                 $$.type_dimension = make_str("-1");
4850                                 $$.type_index = make_str("-1");
4851                                 $$.type_sizeof = NULL;
4852                         }
4853                         else if (strcmp($1, "timestamp") == 0)
4854                         {
4855                                 $$.type_enum = ECPGt_timestamp;
4856                                 $$.type_str = make_str("timestamp");
4857                                 $$.type_dimension = make_str("-1");
4858                                 $$.type_index = make_str("-1");
4859                                 $$.type_sizeof = NULL;
4860                         }
4861                         else if (strcmp($1, "interval") == 0)
4862                         {
4863                                 $$.type_enum = ECPGt_interval;
4864                                 $$.type_str = make_str("interval");
4865                                 $$.type_dimension = make_str("-1");
4866                                 $$.type_index = make_str("-1");
4867                                 $$.type_sizeof = NULL;
4868                         }
4869                         else if (strcmp($1, "datetime") == 0)
4870                         {
4871                                 $$.type_enum = ECPGt_timestamp;
4872                                 $$.type_str = make_str("timestamp");
4873                                 $$.type_dimension = make_str("-1");
4874                                 $$.type_index = make_str("-1");
4875                                 $$.type_sizeof = NULL;
4876                         }
4877                         else
4878                         {
4879                                 /* this is for typedef'ed types */
4880                                 struct typedefs *this = get_typedef($1);
4881
4882                                 $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
4883                                 $$.type_enum = this->type->type_enum;
4884                                 $$.type_dimension = this->type->type_dimension;
4885                                 $$.type_index = this->type->type_index;
4886                                 $$.type_sizeof = this->type->type_sizeof;
4887                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
4888                         }
4889                 }
4890                 | s_struct_union_symbol
4891                 {
4892                         /* this is for named structs/unions */
4893                         char *name;
4894                         struct typedefs *this;
4895                         bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
4896
4897                         name = cat2_str($1.su, $1.symbol);
4898                         /* Do we have a forward definition? */
4899                         if (!forward)
4900                         {
4901                                 /* No */
4902                                 
4903                                 this = get_typedef(name);
4904                                 $$.type_str = mm_strdup(this->name);
4905                                 $$.type_enum = this->type->type_enum;
4906                                 $$.type_dimension = this->type->type_dimension;
4907                                 $$.type_index = this->type->type_index;
4908                                 $$.type_sizeof = this->type->type_sizeof;
4909                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
4910                                 free(name);
4911                         }
4912                         else
4913                         {
4914                                 $$.type_str = name;
4915                                 $$.type_enum = ECPGt_long;
4916                                 $$.type_dimension = make_str("-1");
4917                                 $$.type_index = make_str("-1");
4918                                 $$.type_sizeof = make_str("");
4919                                 struct_member_list[struct_level] = NULL;
4920                         }
4921                 }
4922                 ;
4923
4924 enum_type: SQL_ENUM symbol enum_definition
4925                         { $$ = cat_str(3, make_str("enum"), $2, $3); }
4926                 | SQL_ENUM enum_definition
4927                         { $$ = cat2_str(make_str("enum"), $2); }
4928                 | SQL_ENUM symbol
4929                         { $$ = cat2_str(make_str("enum"), $2); }
4930                 ;
4931
4932 enum_definition: '{' c_list '}'
4933                         { $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
4934
4935 struct_union_type_with_symbol: s_struct_union_symbol
4936                 {
4937                         struct_member_list[struct_level++] = NULL;
4938                         if (struct_level >= STRUCT_DEPTH)
4939                                  mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
4940                         forward_name = mm_strdup($1.symbol);
4941                 } 
4942                 '{' variable_declarations '}'
4943                 {
4944                         struct typedefs *ptr, *this;
4945                         struct this_type su_type;
4946                         
4947                         ECPGfree_struct_member(struct_member_list[struct_level]);
4948                         struct_member_list[struct_level] = NULL;
4949                         struct_level--;
4950                         if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
4951                                 su_type.type_enum = ECPGt_struct;
4952                         else
4953                                 su_type.type_enum = ECPGt_union;
4954                         su_type.type_str = cat2_str($1.su, $1.symbol);
4955                         free(forward_name);
4956                         forward_name = NULL;
4957                         
4958                         /* This is essantially a typedef but needs the keyword struct/union as well.
4959                          * So we create the typedef for each struct definition with symbol */
4960                         for (ptr = types; ptr != NULL; ptr = ptr->next)
4961                         {
4962                                 if (strcmp(su_type.type_str, ptr->name) == 0)
4963                                         /* re-definition is a bug */
4964                                         mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", su_type.type_str);
4965                         }
4966
4967                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
4968
4969                         /* initial definition */
4970                         this->next = types;
4971                         this->name = mm_strdup(su_type.type_str);
4972                         this->brace_level = braces_open;
4973                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
4974                         this->type->type_enum = su_type.type_enum;
4975                         this->type->type_str = mm_strdup(su_type.type_str);
4976                         this->type->type_dimension = make_str("-1"); /* dimension of array */
4977                         this->type->type_index = make_str("-1");    /* length of string */
4978                         this->type->type_sizeof = ECPGstruct_sizeof;
4979                         this->struct_member_list = struct_member_list[struct_level];
4980
4981                         types = this;
4982                         $$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}"));
4983                 }
4984                 ;
4985
4986 struct_union_type: struct_union_type_with_symbol        { $$ = $1; }
4987                 | s_struct_union
4988                 {
4989                         struct_member_list[struct_level++] = NULL;
4990                         if (struct_level >= STRUCT_DEPTH)
4991                                  mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
4992                 }
4993                 '{' variable_declarations '}'
4994                 {
4995                         ECPGfree_struct_member(struct_member_list[struct_level]);
4996                         struct_member_list[struct_level] = NULL;
4997                         struct_level--;
4998                         $$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
4999                 }
5000                 ;
5001
5002 s_struct_union_symbol: SQL_STRUCT symbol
5003                 {
5004                         $$.su = make_str("struct");
5005                         $$.symbol = $2;
5006                         ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")")); 
5007                 }
5008                 | UNION symbol
5009                 {
5010                         $$.su = make_str("union");
5011                         $$.symbol = $2;
5012                 }
5013                 ;
5014
5015 s_struct_union: SQL_STRUCT      
5016                 {
5017                         ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */
5018                         $$ = make_str("struct");
5019                 }
5020                 | UNION         { $$ = make_str("union"); }
5021                 ;
5022
5023 simple_type: unsigned_type                                      { $$=$1; }
5024                 |       opt_signed signed_type                  { $$=$2; }
5025                 ;
5026
5027 unsigned_type: SQL_UNSIGNED SQL_SHORT           { $$ = ECPGt_unsigned_short; }
5028                 | SQL_UNSIGNED SQL_SHORT INT_P  { $$ = ECPGt_unsigned_short; }
5029                 | SQL_UNSIGNED                                          { $$ = ECPGt_unsigned_int; }
5030                 | SQL_UNSIGNED INT_P                            { $$ = ECPGt_unsigned_int; }
5031                 | SQL_UNSIGNED SQL_LONG                         { $$ = ECPGt_unsigned_long; }
5032                 | SQL_UNSIGNED SQL_LONG INT_P           { $$ = ECPGt_unsigned_long; }
5033                 | SQL_UNSIGNED SQL_LONG SQL_LONG
5034                 {
5035 #ifdef HAVE_LONG_LONG_INT_64
5036                         $$ = ECPGt_unsigned_long_long;
5037 #else
5038                         $$ = ECPGt_unsigned_long;
5039 #endif
5040                 }
5041                 | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
5042                 {
5043 #ifdef HAVE_LONG_LONG_INT_64
5044                         $$ = ECPGt_unsigned_long_long;
5045 #else
5046                         $$ = ECPGt_unsigned_long;
5047 #endif
5048                 }
5049                 | SQL_UNSIGNED CHAR_P                   { $$ = ECPGt_unsigned_char; }
5050                 ;
5051
5052 signed_type: SQL_SHORT                          { $$ = ECPGt_short; }
5053                 | SQL_SHORT INT_P                       { $$ = ECPGt_short; }
5054                 | INT_P                                 { $$ = ECPGt_int; }
5055                 | SQL_LONG                                      { $$ = ECPGt_long; }
5056                 | SQL_LONG INT_P                        { $$ = ECPGt_long; }
5057                 | SQL_LONG SQL_LONG
5058                 {
5059 #ifdef HAVE_LONG_LONG_INT_64
5060                         $$ = ECPGt_long_long;
5061 #else
5062                         $$ = ECPGt_long;
5063 #endif
5064                 }
5065                 | SQL_LONG SQL_LONG INT_P
5066                 {
5067 #ifdef HAVE_LONG_LONG_INT_64
5068                         $$ = ECPGt_long_long;
5069 #else
5070                         $$ = ECPGt_long;
5071 #endif
5072                 }
5073                 | SQL_BOOL                                      { $$ = ECPGt_bool; }
5074                 | CHAR_P                                        { $$ = ECPGt_char; }
5075                 | DOUBLE_P                                      { $$ = ECPGt_double; }
5076                 ;
5077
5078 opt_signed: SQL_SIGNED
5079                 |       /* EMPTY */
5080                 ;
5081
5082 variable_list: variable
5083                         { $$ = $1; }
5084                 | variable_list ',' variable
5085                         { $$ = cat_str(3, $1, make_str(","), $3); }
5086                 ;
5087
5088 variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer
5089                 {
5090                         struct ECPGtype * type;
5091                         char *dimension = $3.index1; /* dimension of array */
5092                         char *length = $3.index2;    /* length of string */
5093                         char dim[14L];
5094
5095                         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);
5096
5097                         switch (actual_type[struct_level].type_enum)
5098                         {
5099                                 case ECPGt_struct:
5100                                 case ECPGt_union:
5101                                         if (atoi(dimension) < 0)
5102                                                 type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
5103                                         else
5104                                                 type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof), dimension);
5105
5106                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
5107                                         break;
5108
5109                                 case ECPGt_varchar:
5110                                         if (atoi(dimension) < 0)
5111                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
5112                                         else
5113                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
5114
5115                                         if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
5116                                                         *dim = '\0';
5117                                         else    
5118                                                         sprintf(dim, "[%s]", dimension);
5119                                         if (strcmp(length, "0") == 0)
5120                                                 mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
5121
5122                                         if (strcmp(dimension, "0") == 0)
5123                                                 $$ = 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);
5124                                         else
5125                                                 $$ = 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);
5126                                         break;
5127
5128                                 case ECPGt_char:
5129                                 case ECPGt_unsigned_char:
5130                                         if (atoi(dimension) == -1)
5131                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
5132                                         else
5133                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
5134
5135                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
5136                                         break;
5137
5138                                 default:
5139                                         if (atoi(dimension) < 0)
5140                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"));
5141                                         else
5142                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1")), dimension);
5143
5144                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
5145                                         break;
5146                         }
5147
5148                         if (struct_level == 0)
5149                                 new_variable($2, type, braces_open);
5150                         else
5151                                 ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
5152
5153                         free($2);
5154                 }
5155                 ;
5156
5157 opt_initializer: /*EMPTY*/
5158                         { $$ = EMPTY; }
5159                 | '=' c_term
5160                 {
5161                         initializer = 1;
5162                         $$ = cat2_str(make_str("="), $2);
5163                 }
5164                 ;
5165
5166 opt_pointer: /*EMPTY*/                          { $$ = EMPTY; }
5167                 | '*'                                           { $$ = make_str("*"); }
5168                 | '*' '*'                                       { $$ = make_str("**"); }
5169                 ;
5170
5171 /*
5172  * We try to simulate the correct DECLARE syntax here so we get dynamic SQL
5173  */
5174 ECPGDeclare: DECLARE STATEMENT ident
5175                 {
5176                         /* this is only supported for compatibility */
5177                         $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
5178                 }
5179                 ;
5180 /*
5181  * the exec sql disconnect statement: disconnect from the given database
5182  */
5183 ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
5184                 ;
5185
5186 dis_name: connection_object                             { $$ = $1; }
5187                 | SQL_CURRENT                                           { $$ = make_str("\"CURRENT\""); }
5188                 | ALL                                                   { $$ = make_str("\"ALL\""); }
5189                 | /*EMPTY*/                                             { $$ = make_str("\"CURRENT\""); }
5190                 ;
5191
5192 connection_object: connection_target    { $$ = $1; }
5193                 | DEFAULT                                               { $$ = make_str("\"DEFAULT\""); }
5194                 ;
5195
5196 /*
5197  * execute a given string as sql command
5198  */
5199 ECPGExecute : EXECUTE IMMEDIATE execstring
5200                 {
5201                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
5202
5203                         thisquery->type = &ecpg_query;
5204                         thisquery->brace_level = 0;
5205                         thisquery->next = NULL;
5206                         thisquery->name = $3;
5207
5208                         add_variable_to_head(&argsinsert, thisquery, &no_indicator);
5209
5210                         $$ = make_str("?");
5211                 }
5212                 | EXECUTE prepared_name
5213                 {
5214                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
5215
5216                         thisquery->type = &ecpg_query;
5217                         thisquery->brace_level = 0;
5218                         thisquery->next = NULL;
5219                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement()") + strlen($2));
5220                         sprintf(thisquery->name, "ECPGprepared_statement(%s)", $2);
5221
5222                         add_variable_to_head(&argsinsert, thisquery, &no_indicator);
5223                 }
5224                 execute_rest
5225                 {
5226                         $$ = make_str("?");
5227                 }
5228                 ;
5229
5230 execute_rest:   ecpg_using ecpg_into    { $$ = EMPTY; }
5231                 | ecpg_into ecpg_using  { $$ = EMPTY; }
5232                 | ecpg_using            { $$ = EMPTY; }
5233                 | ecpg_into             { $$ = EMPTY; }
5234                 | /* EMPTY */           { $$ = EMPTY; }
5235                 ;
5236
5237 execstring: char_variable
5238                         { $$ = $1; }
5239                 |       CSTRING
5240                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5241                 ;
5242
5243 prepared_name: name             { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5244                 | char_variable { $$ = $1; }
5245                 ;
5246
5247 /*
5248  * the exec sql free command to deallocate a previously
5249  * prepared statement
5250  */
5251 ECPGFree:       SQL_FREE name   { $$ = $2; };
5252
5253 /*
5254  * open is an open cursor, at the moment this has to be removed
5255  */
5256 ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
5257
5258 opt_ecpg_using: /*EMPTY*/               { $$ = EMPTY; }
5259                 | ecpg_using            { $$ = $1; }
5260                 ;
5261
5262 ecpg_using:     USING using_list        { $$ = EMPTY; }
5263                 | using_descriptor      { $$ = $1; }
5264                 ;
5265
5266 using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
5267                 {
5268                         add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
5269                         $$ = EMPTY;
5270                 }
5271                 ;
5272
5273 into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
5274                 {
5275                         add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
5276                         $$ = EMPTY;
5277                 }
5278                 ;
5279                 
5280 opt_sql: /*EMPTY*/ | SQL_SQL;
5281
5282 ecpg_into: INTO into_list               { $$ = EMPTY; }
5283                 | into_descriptor       { $$ = $1; }
5284                 ;
5285                 
5286 using_list: UsingConst | UsingConst ',' using_list;
5287
5288 UsingConst: AllConst
5289                 {
5290                         if ($1[1] != '?') /* found a constant */
5291                         {
5292                                 char *length = mm_alloc(32);
5293
5294                                 sprintf(length, "%d", (int) strlen($1));
5295                                 add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0), &no_indicator);
5296                         }
5297                 }
5298                 | civarind { $$ = EMPTY; }
5299                 ;
5300
5301 /*
5302  * As long as the prepare statement is not supported by the backend, we will
5303  * try to simulate it here so we get dynamic SQL
5304  *
5305  * It is supported now but not usable yet by ecpg.
5306  */
5307 ECPGPrepare: PREPARE prepared_name FROM execstring
5308                         { $$ = cat_str(3, $2, make_str(","), $4); }
5309                 ;
5310 /* 
5311  * We accept descibe but do nothing with it so far.
5312  */
5313 ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor 
5314         {
5315                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n");
5316                 $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(\"\")") + strlen($3));
5317                 sprintf($$, "1, ECPGprepared_statement(\"%s\")", $3);
5318         }
5319         | SQL_DESCRIBE opt_output name using_descriptor
5320         {
5321                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n");
5322                 $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(\"\")") + strlen($3));
5323                 sprintf($$, "0, ECPGprepared_statement(\"%s\")", $3);
5324         }
5325         | SQL_DESCRIBE opt_output name into_descriptor
5326         {
5327                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n");
5328                 $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(\"\")") + strlen($3));
5329                 sprintf($$, "0, ECPGprepared_statement(\"%s\")", $3);
5330         }
5331         ;
5332
5333 opt_output:     SQL_OUTPUT      { $$ = make_str("output"); }
5334         |       /* EMPTY */     { $$ = EMPTY; }
5335         ;
5336         
5337 /*
5338  * dynamic SQL: descriptor based access
5339  *      originall written by Christof Petig <christof.petig@wtal.de>
5340  *                      and Peter Eisentraut <peter.eisentraut@credativ.de>
5341  */
5342
5343 /*
5344  * allocate a descriptor
5345  */
5346 ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
5347                {
5348                        add_descriptor($3,connection);
5349                        $$ = $3;
5350                };
5351
5352  
5353 /*
5354  * deallocate a descriptor
5355  */
5356 ECPGDeallocateDescr:    DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
5357                 {
5358                         drop_descriptor($3,connection);
5359                         $$ = $3;
5360                 }
5361                 ;
5362
5363 /*
5364  * manipulate a descriptor header
5365  */
5366
5367 ECPGGetDescriptorHeader: GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
5368                         {  $$ = $3; }
5369                 ;
5370
5371 ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
5372                 | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
5373                 ;
5374
5375 ECPGGetDescHeaderItem: cvariable '=' desc_header_item
5376                         { push_assignment($1, $3); }
5377                 ;
5378
5379
5380 ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
5381                         { $$ = $3; }
5382                 ;
5383
5384 ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
5385                 | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
5386                 ;
5387
5388 ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
5389                 {
5390                         push_assignment($3, $1);
5391                 }
5392                 ;
5393
5394
5395 desc_header_item:       SQL_COUNT                       { $$ = ECPGd_count; }
5396                 ;
5397
5398 /*
5399  * manipulate a descriptor
5400  */
5401
5402 ECPGGetDescriptor:      GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE IntConstVar ECPGGetDescItems
5403                         {  $$.str = $5; $$.name = $3; }
5404                 ;
5405
5406 ECPGGetDescItems: ECPGGetDescItem
5407                 | ECPGGetDescItems ',' ECPGGetDescItem
5408                 ;
5409
5410 ECPGGetDescItem: cvariable '=' descriptor_item  { push_assignment($1, $3); };
5411
5412
5413 ECPGSetDescriptor:      SET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE IntConstVar ECPGSetDescItems
5414                         {  $$.str = $5; $$.name = $3; }
5415                 ;
5416
5417 ECPGSetDescItems: ECPGSetDescItem
5418                 | ECPGSetDescItems ',' ECPGSetDescItem
5419                 ;
5420
5421 ECPGSetDescItem: descriptor_item '=' AllConstVar
5422                 {
5423                         push_assignment($3, $1);
5424                 }
5425                 ;
5426
5427
5428 descriptor_item:        SQL_CARDINALITY                 { $$ = ECPGd_cardinality; }
5429                 | SQL_DATA                              { $$ = ECPGd_data; }
5430                 | SQL_DATETIME_INTERVAL_CODE            { $$ = ECPGd_di_code; }
5431                 | SQL_DATETIME_INTERVAL_PRECISION       { $$ = ECPGd_di_precision; }
5432                 | SQL_INDICATOR                         { $$ = ECPGd_indicator; }
5433                 | SQL_KEY_MEMBER                        { $$ = ECPGd_key_member; }
5434                 | SQL_LENGTH                            { $$ = ECPGd_length; }
5435                 | SQL_NAME                              { $$ = ECPGd_name; }
5436                 | SQL_NULLABLE                          { $$ = ECPGd_nullable; }
5437                 | SQL_OCTET_LENGTH                      { $$ = ECPGd_octet; }
5438                 | PRECISION                             { $$ = ECPGd_precision; }
5439                 | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
5440                 | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
5441                 | SQL_SCALE                             { $$ = ECPGd_scale; }
5442                 | TYPE_P                                { $$ = ECPGd_type; }
5443                 ;
5444
5445
5446 /*
5447  * for compatibility with ORACLE we will also allow the keyword RELEASE
5448  * after a transaction statement to disconnect from the database.
5449  */
5450
5451 ECPGRelease: TransactionStmt SQL_RELEASE
5452                 {
5453                         if (strcmp($1, "begin") == 0)
5454                                                         mmerror(PARSE_ERROR, ET_ERROR, "RELEASE does not make sense when beginning a transaction");
5455
5456                         fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");",
5457                                         connection ? connection : "NULL", $1);
5458                         whenever_action(0);
5459                         fprintf(yyout, "ECPGdisconnect(__LINE__, %s);",
5460                                         connection ? connection : "\"CURRENT\"");
5461                         whenever_action(0);
5462                         free($1);
5463                 }
5464                 ;
5465
5466 /*
5467  * set/reset the automatic transaction mode, this needs a differnet handling
5468  * as the other set commands
5469  */
5470 ECPGSetAutocommit:      SET SQL_AUTOCOMMIT '=' on_off   { $$ = $4; }
5471                 |  SET SQL_AUTOCOMMIT TO on_off   { $$ = $4; }
5472                 ;
5473
5474 on_off: ON                              { $$ = make_str("on"); }
5475                 | OFF                   { $$ = make_str("off"); }
5476                 ;
5477
5478 /*
5479  * set the actual connection, this needs a differnet handling as the other
5480  * set commands
5481  */
5482 ECPGSetConnection:      SET SQL_CONNECTION TO connection_object { $$ = $4; }
5483                 | SET SQL_CONNECTION '=' connection_object { $$ = $4; }
5484                 | SET SQL_CONNECTION  connection_object { $$ = $3; }
5485                 ;
5486
5487 /*
5488  * define a new type for embedded SQL
5489  */
5490 ECPGTypedef: TYPE_P
5491                 {
5492                         /* reset this variable so we see if there was */
5493                         /* an initializer specified */
5494                         initializer = 0;
5495                 }
5496                 ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
5497                 {
5498                         /* add entry to list */
5499                         struct typedefs *ptr, *this;
5500                         char *dimension = $6.index1;
5501                         char *length = $6.index2;
5502
5503                         if (($5.type_enum == ECPGt_struct ||
5504                                  $5.type_enum == ECPGt_union) &&
5505                                 initializer == 1)
5506                                 mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL TYPE command");
5507                         else
5508                         {
5509                                 for (ptr = types; ptr != NULL; ptr = ptr->next)
5510                                 {
5511                                         if (strcmp($3, ptr->name) == 0)
5512                                                 /* re-definition is a bug */
5513                                                 mmerror(PARSE_ERROR, ET_ERROR, "Type %s already defined", $3);
5514                                 }
5515
5516                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
5517
5518                                 this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
5519
5520                                 /* initial definition */
5521                                 this->next = types;
5522                                 this->name = $3;
5523                                 this->brace_level = braces_open;
5524                                 this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
5525                                 this->type->type_enum = $5.type_enum;
5526                                 this->type->type_str = mm_strdup($3);
5527                                 this->type->type_dimension = dimension; /* dimension of array */
5528                                 this->type->type_index = length;        /* length of string */
5529                                 this->type->type_sizeof = ECPGstruct_sizeof;
5530                                 this->struct_member_list = ($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) ?
5531                                         struct_member_list[struct_level] : NULL;
5532
5533                                 if ($5.type_enum != ECPGt_varchar &&
5534                                         $5.type_enum != ECPGt_char &&
5535                                         $5.type_enum != ECPGt_unsigned_char &&
5536                                         atoi(this->type->type_index) >= 0)
5537                                         mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
5538
5539                                 types = this;
5540                         }
5541
5542                         if (auto_create_c == false)
5543                                 $$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
5544                         else
5545                                 $$ = cat_str(6, make_str("typedef "), mm_strdup($5.type_str), *$7?make_str("*"):make_str(""), mm_strdup($6.str), mm_strdup($3), make_str(";"));
5546                 }
5547                 ;
5548
5549 opt_reference: SQL_REFERENCE            { $$ = make_str("reference"); }
5550                 | /*EMPTY*/                                     { $$ = EMPTY; }
5551                 ;
5552
5553 /*
5554  * define the type of one variable for embedded SQL
5555  */
5556 ECPGVar: SQL_VAR
5557                 {
5558                         /* reset this variable so we see if there was */
5559                         /* an initializer specified */
5560                         initializer = 0;
5561                 }
5562                 ColLabel IS var_type opt_array_bounds opt_reference
5563                 {
5564                         struct variable *p = find_variable($3);
5565                         char *dimension = $6.index1;
5566                         char *length = $6.index2;
5567                         struct ECPGtype * type;
5568
5569                         if (($5.type_enum == ECPGt_struct ||
5570                                  $5.type_enum == ECPGt_union) &&
5571                                 initializer == 1)
5572                                 mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
5573                         else
5574                         {
5575                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
5576
5577                                 switch ($5.type_enum)
5578                                 {
5579                                         case ECPGt_struct:
5580                                         case ECPGt_union:
5581                                                 if (atoi(dimension) < 0)
5582                                                         type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
5583                                                 else
5584                                                         type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
5585                                                 break;
5586
5587                                         case ECPGt_varchar:
5588                                                 if (atoi(dimension) == -1)
5589                                                         type = ECPGmake_simple_type($5.type_enum, length);
5590                                                 else
5591                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension);
5592                                                 break;
5593
5594                                         case ECPGt_char:
5595                                         case ECPGt_unsigned_char:
5596                                                 if (atoi(dimension) == -1)
5597                                                         type = ECPGmake_simple_type($5.type_enum, length);
5598                                                 else
5599                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension);
5600                                                 break;
5601
5602                                         default:
5603                                                 if (atoi(length) >= 0)
5604                                                         mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
5605
5606                                                 if (atoi(dimension) < 0)
5607                                                         type = ECPGmake_simple_type($5.type_enum, make_str("1"));
5608                                                 else
5609                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1")), dimension);
5610                                                 break;
5611                                 }
5612
5613                                 ECPGfree_type(p->type);
5614                                 p->type = type;
5615                         }
5616
5617                         $$ = cat_str(7, make_str("/* exec sql var"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
5618                 }
5619                 ;
5620
5621 /*
5622  * whenever statement: decide what to do in case of error/no data found
5623  * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
5624  */
5625 ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
5626                 {
5627                         when_error.code = $<action>3.code;
5628                         when_error.command = $<action>3.command;
5629                         $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */\n"));
5630                 }
5631                 | SQL_WHENEVER NOT SQL_FOUND action
5632                 {
5633                         when_nf.code = $<action>4.code;
5634                         when_nf.command = $<action>4.command;
5635                         $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */\n"));
5636                 }
5637                 | SQL_WHENEVER SQL_SQLWARNING action
5638                 {
5639                         when_warn.code = $<action>3.code;
5640                         when_warn.command = $<action>3.command;
5641                         $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */\n"));
5642                 }
5643                 ;
5644
5645 action : SQL_CONTINUE
5646                 {
5647                         $<action>$.code = W_NOTHING;
5648                         $<action>$.command = NULL;
5649                         $<action>$.str = make_str("continue");
5650                 }
5651                 | SQL_SQLPRINT
5652                 {
5653                         $<action>$.code = W_SQLPRINT;
5654                         $<action>$.command = NULL;
5655                         $<action>$.str = make_str("sqlprint");
5656                 }
5657                 | SQL_STOP
5658                 {
5659                         $<action>$.code = W_STOP;
5660                         $<action>$.command = NULL;
5661                         $<action>$.str = make_str("stop");
5662                 }
5663                 | SQL_GOTO name
5664                 {
5665                         $<action>$.code = W_GOTO;
5666                         $<action>$.command = strdup($2);
5667                         $<action>$.str = cat2_str(make_str("goto "), $2);
5668                 }
5669                 | SQL_GO TO name
5670                 {
5671                         $<action>$.code = W_GOTO;
5672                         $<action>$.command = strdup($3);
5673                         $<action>$.str = cat2_str(make_str("goto "), $3);
5674                 }
5675                 | DO name '(' c_args ')'
5676                 {
5677                         $<action>$.code = W_DO;
5678                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
5679                         $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
5680                 }
5681                 | DO SQL_BREAK
5682                 {
5683                         $<action>$.code = W_BREAK;
5684                         $<action>$.command = NULL;
5685                         $<action>$.str = make_str("break");
5686                 }
5687                 | SQL_CALL name '(' c_args ')'
5688                 {
5689                         $<action>$.code = W_DO;
5690                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
5691                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
5692                 }
5693                 | SQL_CALL name 
5694                 {
5695                         $<action>$.code = W_DO;
5696                         $<action>$.command = cat_str(3, $2, make_str("("), make_str(")"));
5697                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
5698                 }
5699                 ;
5700
5701 /* some other stuff for ecpg */
5702
5703 /* additional unreserved keywords */
5704 ECPGKeywords: ECPGKeywords_vanames      { $$ = $1; }
5705                 | ECPGKeywords_rest     { $$ = $1; }
5706                 ;
5707
5708 ECPGKeywords_vanames:  SQL_BREAK                { $$ = make_str("break"); }
5709                 | SQL_CALL                      { $$ = make_str("call"); }
5710                 | SQL_CARDINALITY               { $$ = make_str("cardinality"); }
5711                 | SQL_CONTINUE                  { $$ = make_str("continue"); }
5712                 | SQL_COUNT                     { $$ = make_str("count"); }
5713                 | SQL_DATA                      { $$ = make_str("data"); }
5714                 | SQL_DATETIME_INTERVAL_CODE    { $$ = make_str("datetime_interval_code"); }
5715                 | SQL_DATETIME_INTERVAL_PRECISION       { $$ = make_str("datetime_interval_precision"); }
5716                 | SQL_FOUND                     { $$ = make_str("found"); }
5717                 | SQL_GO                        { $$ = make_str("go"); }
5718                 | SQL_GOTO                      { $$ = make_str("goto"); }
5719                 | SQL_IDENTIFIED                { $$ = make_str("identified"); }
5720                 | SQL_INDICATOR                 { $$ = make_str("indicator"); }
5721                 | SQL_KEY_MEMBER                { $$ = make_str("key_member"); }
5722                 | SQL_LENGTH                    { $$ = make_str("length"); }
5723                 | SQL_NAME                      { $$ = make_str("name"); }
5724                 | SQL_NULLABLE                  { $$ = make_str("nullable"); }
5725                 | SQL_OCTET_LENGTH              { $$ = make_str("octet_length"); }
5726                 | SQL_RELEASE                   { $$ = make_str("release"); }
5727                 | SQL_RETURNED_LENGTH           { $$ = make_str("returned_length"); }
5728                 | SQL_RETURNED_OCTET_LENGTH     { $$ = make_str("returned_octet_length"); }
5729                 | SQL_SCALE                     { $$ = make_str("scale"); }
5730                 | SQL_SECTION                   { $$ = make_str("section"); }
5731                 | SQL_SQLERROR                  { $$ = make_str("sqlerror"); }
5732                 | SQL_SQLPRINT                  { $$ = make_str("sqlprint"); }
5733                 | SQL_SQLWARNING                { $$ = make_str("sqlwarning"); }
5734                 | SQL_STOP                      { $$ = make_str("stop"); }
5735                 ;
5736                 
5737 ECPGKeywords_rest:  SQL_CONNECT                 { $$ = make_str("connect"); }
5738                 | SQL_DESCRIBE                  { $$ = make_str("describe"); }
5739                 | SQL_DISCONNECT                { $$ = make_str("disconnect"); }
5740                 | SQL_OPEN                      { $$ = make_str("open"); }
5741                 | SQL_VAR                       { $$ = make_str("var"); }
5742                 | SQL_WHENEVER                  { $$ = make_str("whenever"); }
5743                 ;
5744
5745 /* additional keywords that can be SQL type names (but not ECPGColLabels) */
5746 ECPGTypeName:  SQL_BOOL                         { $$ = make_str("bool"); }
5747                 | SQL_LONG                      { $$ = make_str("long"); }
5748                 | SQL_OUTPUT                    { $$ = make_str("output"); }
5749                 | SQL_SHORT                     { $$ = make_str("short"); }
5750                 | SQL_STRUCT                    { $$ = make_str("struct"); }
5751                 | SQL_SIGNED                    { $$ = make_str("signed"); }
5752                 | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
5753                 ;
5754
5755 symbol: ColLabel                                { $$ = $1; }
5756                 ;
5757
5758 /*
5759  * Name classification hierarchy.
5760  *
5761  * IDENT is the lexeme returned by the lexer for identifiers that match
5762  * no known keyword.  In most cases, we can accept certain keywords as
5763  * names, not only IDENTs.      We prefer to accept as many such keywords
5764  * as possible to minimize the impact of "reserved words" on programmers.
5765  * So, we divide names into several possible classes.  The classification
5766  * is chosen in part to make keywords acceptable as names wherever possible.
5767  */
5768
5769 /* Column identifier --- names that can be column, table, etc names.
5770  */
5771 ColId:  ident                                           { $$ = $1; }
5772                 | unreserved_keyword                    { $$ = $1; }
5773                 | col_name_keyword                      { $$ = $1; }
5774                 | ECPGKeywords                          { $$ = $1; }
5775                 | ECPGCKeywords                         { $$ = $1; }
5776                 | CHAR_P                                { $$ = make_str("char"); }
5777                 ;
5778
5779 /* Type identifier --- names that can be type names.
5780  */
5781 type_name:      ident                                   { $$ = $1; }
5782                 | unreserved_keyword                    { $$ = $1; }
5783                 | ECPGKeywords                          { $$ = $1; }
5784                 | ECPGTypeName                          { $$ = $1; }
5785                 | ECPGCKeywords                         { $$ = $1; }
5786                 ;
5787
5788 /* Function identifier --- names that can be function names.
5789  */
5790 function_name:  ident                                   { $$ = $1; }
5791                 | unreserved_keyword                    { $$ = $1; }
5792                 | func_name_keyword                     { $$ = $1; }
5793                 | ECPGKeywords                          { $$ = $1; }
5794                 | ECPGCKeywords                         { $$ = $1; }
5795                 ;
5796
5797 /* Column label --- allowed labels in "AS" clauses.
5798  * This presently includes *all* Postgres keywords.
5799  */
5800 ColLabel:  ECPGColLabel                         { $$ = $1; }
5801                 | ECPGTypeName                  { $$ = $1; }
5802                 | CHAR_P                        { $$ = make_str("char"); }
5803                 | INPUT_P                       { $$ = make_str("input"); }
5804                 | INT_P                         { $$ = make_str("int"); }
5805                 | UNION                         { $$ = make_str("union"); }
5806                 | TO                            { $$ = make_str("to"); }
5807                 | ECPGCKeywords                 { $$ = $1; }
5808                 | ECPGunreserved_interval       { $$ = $1; }
5809                 ;
5810
5811 ECPGColLabelCommon:  ident                              { $$ = $1; }
5812                 | col_name_keyword                      { $$ = $1; }
5813                 | func_name_keyword                     { $$ = $1; }
5814                 | ECPGKeywords_vanames                  { $$ = $1; }
5815                 ;
5816                 
5817 ECPGColLabel:  ECPGColLabelCommon                       { $$ = $1; }
5818                 | reserved_keyword                      { $$ = $1; }
5819                 | ECPGunreserved                        { $$ = $1; }
5820                 | ECPGKeywords_rest                     { $$ = $1; }
5821                 ;
5822
5823 ECPGCKeywords: S_AUTO                   { $$ = make_str("auto"); }
5824                 | S_CONST               { $$ = make_str("const"); }
5825                 | S_EXTERN              { $$ = make_str("extern"); }
5826                 | S_REGISTER            { $$ = make_str("register"); }
5827                 | S_STATIC              { $$ = make_str("static"); }
5828                 | S_TYPEDEF             { $$ = make_str("typedef"); }
5829                 | S_VOLATILE            { $$ = make_str("volatile"); }
5830                 ;
5831         
5832 /*
5833  * Keyword classification lists.  Generally, every keyword present in
5834  * the Postgres grammar should appear in exactly one of these lists.
5835  *
5836  * Put a new keyword into the first list that it can go into without causing
5837  * shift or reduce conflicts.  The earlier lists define "less reserved"
5838  * categories of keywords.
5839  */
5840
5841 /* "Unreserved" keywords --- available for use as any kind of name.
5842  */
5843 /* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel
5844    to enable C variables to get names from ECPGColLabel:
5845    DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P
5846  */
5847 unreserved_keyword: ECPGunreserved_interval | ECPGunreserved;
5848
5849 ECPGunreserved_interval: DAY_P                          { $$ = make_str("day"); }
5850                 | HOUR_P                        { $$ = make_str("hour"); }
5851                 | MINUTE_P                      { $$ = make_str("minute"); }
5852                 | MONTH_P                       { $$ = make_str("month"); }
5853                 | SECOND_P                      { $$ = make_str("second"); }
5854                 | YEAR_P                        { $$ = make_str("year"); }
5855                 ;
5856                 
5857 ECPGunreserved:   ABORT_P                       { $$ = make_str("abort"); }
5858                 | ABSOLUTE_P                    { $$ = make_str("absolute"); }
5859                 | ACCESS                        { $$ = make_str("access"); }
5860                 | ACTION                        { $$ = make_str("action"); }
5861                 | ADD                           { $$ = make_str("add"); }
5862                 | AFTER                         { $$ = make_str("after"); }
5863                 | AGGREGATE                     { $$ = make_str("aggregate"); }
5864                 | ALSO                          { $$ = make_str("also"); }
5865                 | ALTER                         { $$ = make_str("alter"); }
5866                 | ASSERTION                     { $$ = make_str("assertion"); }
5867                 | ASSIGNMENT                    { $$ = make_str("assignment"); }
5868                 | AT                            { $$ = make_str("at"); }
5869                 | BACKWARD                      { $$ = make_str("backward"); }
5870                 | BEFORE                        { $$ = make_str("before"); }
5871                 | BEGIN_P                       { $$ = make_str("begin"); }
5872                 | BY                            { $$ = make_str("by"); }
5873                 | CACHE                         { $$ = make_str("cache"); }
5874                 | CASCADE                       { $$ = make_str("cascade"); }
5875                 | CHAIN                         { $$ = make_str("chain"); }
5876                 | CHARACTERISTICS               { $$ = make_str("characteristics"); }
5877                 | CHECKPOINT                    { $$ = make_str("checkpoint"); }
5878                 | CLASS                         { $$ = make_str("class"); }
5879                 | CLOSE                         { $$ = make_str("close"); }
5880                 | CLUSTER                       { $$ = make_str("cluster"); }
5881                 | COMMENT                       { $$ = make_str("comment"); }
5882                 | COMMIT                        { $$ = make_str("commit"); }
5883                 | COMMITTED                     { $$ = make_str("committed"); }
5884                 | CONSTRAINTS                   { $$ = make_str("constraints"); }
5885                 | CONVERSION_P                  { $$ = make_str("conversion"); }
5886                 | COPY                          { $$ = make_str("copy"); }
5887                 | CREATEDB                      { $$ = make_str("createdb"); }
5888                 | CREATEUSER                    { $$ = make_str("createuser"); }
5889                 | CSV                           { $$ = make_str("csv"); }
5890                 | CURSOR                        { $$ = make_str("cursor"); }
5891                 | CYCLE                         { $$ = make_str("cycle"); }
5892                 | DATABASE                      { $$ = make_str("database"); }
5893 /*              | DAY_P                         { $$ = make_str("day"); }*/
5894                 | DEALLOCATE                    { $$ = make_str("deallocate"); }
5895                 | DECLARE                       { $$ = make_str("declare"); }
5896                 | DEFAULTS                      { $$ = make_str("defaults"); }
5897                 | DEFERRED                      { $$ = make_str("deferred"); }
5898                 | DELETE_P                      { $$ = make_str("delete"); }
5899                 | DELIMITER                     { $$ = make_str("delimiter"); }
5900                 | DELIMITERS                    { $$ = make_str("delimiters"); }
5901                 | DOMAIN_P                      { $$ = make_str("domain"); }
5902                 | DOUBLE_P                      { $$ = make_str("double"); }
5903                 | DROP                          { $$ = make_str("drop"); }
5904                 | EACH                          { $$ = make_str("each"); }
5905                 | ENCODING                      { $$ = make_str("encoding"); }
5906                 | ENCRYPTED                     { $$ = make_str("encrypted"); }
5907                 | ESCAPE                        { $$ = make_str("escape"); }
5908                 | EXCLUDING                     { $$ = make_str("excluding"); }
5909                 | EXCLUSIVE                     { $$ = make_str("exclusive"); }
5910                 | EXECUTE                       { $$ = make_str("execute"); }
5911                 | EXPLAIN                       { $$ = make_str("explain"); }
5912                 | FETCH                         { $$ = make_str("fetch"); }
5913                 | FIRST_P                       { $$ = make_str("first"); }
5914                 | FORCE                         { $$ = make_str("force"); }
5915                 | FORWARD                       { $$ = make_str("forward"); }
5916                 | FUNCTION                      { $$ = make_str("function"); }
5917                 | GLOBAL                        { $$ = make_str("global"); }
5918                 | HANDLER                       { $$ = make_str("handler"); }
5919                 | HOLD                          { $$ = make_str("hold"); }
5920 /*              | HOUR_P                        { $$ = make_str("hour"); }*/
5921                 | IMMEDIATE                     { $$ = make_str("immediate"); }
5922                 | IMMUTABLE                     { $$ = make_str("immutable"); }
5923                 | IMPLICIT_P                    { $$ = make_str("implicit"); }
5924                 | INCLUDING                     { $$ = make_str("including"); }
5925                 | INCREMENT                     { $$ = make_str("increment"); }
5926                 | INDEX                         { $$ = make_str("index"); }
5927                 | INHERITS                      { $$ = make_str("inherits"); }
5928                 | INSENSITIVE                   { $$ = make_str("insensitive"); }
5929                 | INSERT                        { $$ = make_str("insert"); }
5930                 | INSTEAD                       { $$ = make_str("instead"); }
5931                 | ISOLATION                     { $$ = make_str("isolation"); }
5932                 | KEY                           { $$ = make_str("key"); }
5933                 | LANCOMPILER                   { $$ = make_str("lancompiler"); }
5934                 | LANGUAGE                      { $$ = make_str("language"); }
5935                 | LARGE_P                       { $$ = make_str("large"); }
5936                 | LAST_P                        { $$ = make_str("last"); }
5937                 | LEVEL                         { $$ = make_str("level"); }
5938                 | LISTEN                        { $$ = make_str("listen"); }
5939                 | LOAD                          { $$ = make_str("load"); }
5940                 | LOCAL                         { $$ = make_str("local"); }
5941                 | LOCATION                      { $$ = make_str("location"); }
5942                 | LOCK_P                        { $$ = make_str("lock"); }
5943                 | MATCH                         { $$ = make_str("match"); }
5944                 | MAXVALUE                      { $$ = make_str("maxvalue"); }
5945 /*              | MINUTE_P                      { $$ = make_str("minute"); }*/
5946                 | MINVALUE                      { $$ = make_str("minvalue"); }
5947                 | MODE                          { $$ = make_str("mode"); }
5948 /*              | MONTH_P                       { $$ = make_str("month"); }*/
5949                 | MOVE                          { $$ = make_str("move"); }
5950                 | NAMES                         { $$ = make_str("names"); }
5951                 | NEXT                          { $$ = make_str("next"); }
5952                 | NO                            { $$ = make_str("no"); }
5953                 | NOCREATEDB                    { $$ = make_str("nocreatedb"); }
5954                 | NOCREATEUSER                  { $$ = make_str("nocreateuser"); }
5955                 | NOTHING                       { $$ = make_str("nothing"); }
5956                 | NOTIFY                        { $$ = make_str("notify"); }
5957                 | OBJECT_P                      { $$ = make_str("object"); }
5958                 | OF                            { $$ = make_str("of"); }
5959                 | OIDS                          { $$ = make_str("oids"); }
5960                 | OPERATOR                      { $$ = make_str("operator"); }
5961                 | OPTION                        { $$ = make_str("option"); }
5962                 | OWNER                         { $$ = make_str("owner"); }
5963                 | PARTIAL                       { $$ = make_str("partial"); }
5964                 | PASSWORD                      { $$ = make_str("password"); }
5965                 | PREPARE                       { $$ = make_str("prepare"); }
5966                 | PRESERVE                      { $$ = make_str("preserver"); }
5967                 | PRIOR                         { $$ = make_str("prior"); }
5968                 | PRIVILEGES                    { $$ = make_str("privileges"); }
5969                 | PROCEDURAL                    { $$ = make_str("procedural"); }
5970                 | PROCEDURE                     { $$ = make_str("procedure"); }
5971                 | QUOTE                         { $$ = make_str("quote"); }
5972                 | READ                          { $$ = make_str("read"); }
5973                 | RECHECK                       { $$ = make_str("recheck"); }
5974                 | REINDEX                       { $$ = make_str("reindex"); }
5975                 | RELATIVE_P                    { $$ = make_str("relative"); }
5976                 | RENAME                        { $$ = make_str("rename"); }
5977                 | REPEATABLE                    { $$ = make_str("repeatable"); }
5978                 | REPLACE                       { $$ = make_str("replace"); }
5979                 | RESET                         { $$ = make_str("reset"); }
5980                 | RESTART                       { $$ = make_str("restart"); }
5981                 | RESTRICT                      { $$ = make_str("restrict"); }
5982                 | RETURNS                       { $$ = make_str("returns"); }
5983                 | REVOKE                        { $$ = make_str("revoke"); }
5984                 | ROLLBACK                      { $$ = make_str("rollback"); }
5985                 | ROWS                          { $$ = make_str("rows"); }
5986                 | RULE                          { $$ = make_str("rule"); }
5987                 | SCHEMA                        { $$ = make_str("schema"); }
5988                 | SCROLL                        { $$ = make_str("scroll"); }
5989 /*              | SECOND_P                      { $$ = make_str("second"); }*/
5990                 | SEQUENCE                      { $$ = make_str("sequence"); }
5991                 | SERIALIZABLE                  { $$ = make_str("serializable"); }
5992                 | SESSION                       { $$ = make_str("session"); }
5993                 | SET                           { $$ = make_str("set"); }
5994                 | SHARE                         { $$ = make_str("share"); }
5995                 | SHOW                          { $$ = make_str("show"); }
5996                 | SIMPLE                        { $$ = make_str("simple"); }
5997                 | STABLE                        { $$ = make_str("stable"); }
5998                 | START                         { $$ = make_str("start"); }
5999                 | STATEMENT                     { $$ = make_str("statement"); }
6000                 | STATISTICS                    { $$ = make_str("statistics"); }
6001                 | STDIN                         { $$ = make_str("stdin"); }
6002                 | STDOUT                        { $$ = make_str("stdout"); }
6003                 | STORAGE                       { $$ = make_str("storage"); }
6004                 | STRICT_P                      { $$ = make_str("strict"); }
6005                 | SYSID                         { $$ = make_str("sysid"); }
6006                 | TABLESPACE                    { $$ = make_str("tablespace"); }
6007                 | TEMP                          { $$ = make_str("temp"); }
6008                 | TEMPLATE                      { $$ = make_str("template"); }
6009                 | TEMPORARY                     { $$ = make_str("temporary"); }
6010                 | TOAST                         { $$ = make_str("toast"); }
6011                 | TRANSACTION                   { $$ = make_str("transaction"); }
6012                 | TRIGGER                       { $$ = make_str("trigger"); }
6013                 | TRUNCATE                      { $$ = make_str("truncate"); }
6014                 | TRUSTED                       { $$ = make_str("trusted"); }
6015                 | TYPE_P                        { $$ = make_str("type"); }
6016                 | UNCOMMITTED                   { $$ = make_str("uncommitted"); }
6017                 | UNENCRYPTED                   { $$ = make_str("unencrypted"); }
6018                 | UNKNOWN                       { $$ = make_str("unknown"); }
6019                 | UNLISTEN                      { $$ = make_str("unlisten"); }
6020                 | UNTIL                         { $$ = make_str("until"); }
6021                 | UPDATE                        { $$ = make_str("update"); }
6022                 | USAGE                         { $$ = make_str("usage"); }
6023                 | VACUUM                        { $$ = make_str("vacuum"); }
6024                 | VALID                         { $$ = make_str("valid"); }
6025                 | VALUES                        { $$ = make_str("values"); }
6026                 | VARYING                       { $$ = make_str("varying"); }
6027                 | VIEW                          { $$ = make_str("view"); }
6028                 | WITH                          { $$ = make_str("with"); }
6029                 | WITHOUT                       { $$ = make_str("without"); }
6030                 | WORK                          { $$ = make_str("work"); }
6031                 | WRITE                         { $$ = make_str("write"); }
6032 /*              | YEAR_P                        { $$ = make_str("year"); }*/
6033                 | ZONE                          { $$ = make_str("zone"); }
6034                 ;
6035
6036 /* Column identifier --- keywords that can be column, table, etc names.
6037  *
6038  * Many of these keywords will in fact be recognized as type or function
6039  * names too; but they have special productions for the purpose, and so
6040  * can't be treated as "generic" type or function names.
6041  *
6042  * The type names appearing here are not usable as function names
6043  * because they can be followed by '(' in typename productions, which
6044  * looks too much like a function call for an LR(1) parser.
6045  */
6046 col_name_keyword:
6047                 BIGINT                  { $$ = make_str("bigint");}
6048                 | BIT                   { $$ = make_str("bit"); }
6049 /* CHAR must be excluded from ECPGColLabel because of conflict with UNSIGNED
6050                 | CHAR_P                { $$ = make_str("char"); }
6051  */
6052                 | CHARACTER             { $$ = make_str("character"); }
6053                 | COALESCE              { $$ = make_str("coalesce"); }
6054                 | CONVERT               { $$ = make_str("convert"); }
6055                 | DEC                   { $$ = make_str("dec"); }
6056                 | DECIMAL_P             { $$ = make_str("decimal"); }
6057                 | EXISTS                { $$ = make_str("exists"); }
6058                 | EXTRACT               { $$ = make_str("extract"); }
6059                 | FLOAT_P               { $$ = make_str("float"); }
6060                 | INOUT                 { $$ = make_str("inout"); }
6061 /* INT must be excluded from ECPGColLabel because of conflict
6062                 | INT_P                 { $$ = make_str("int"); }
6063  */
6064                 | INTEGER               { $$ = make_str("integer"); }
6065                 | INTERVAL              { $$ = make_str("interval"); }
6066                 | NATIONAL              { $$ = make_str("national"); }
6067                 | NCHAR                 { $$ = make_str("nchar"); }
6068                 | NONE                  { $$ = make_str("none"); }
6069                 | NULLIF                { $$ = make_str("nullif"); }
6070                 | NUMERIC               { $$ = make_str("numeric"); }
6071                 | OUT_P                 { $$ = make_str("out"); }
6072                 | OVERLAY               { $$ = make_str("overlay"); }
6073                 | POSITION              { $$ = make_str("position"); }
6074                 | PRECISION             { $$ = make_str("precision"); }
6075                 | REAL                  { $$ = make_str("real"); }
6076                 | ROW                   { $$ = make_str("row"); }
6077                 | SETOF                 { $$ = make_str("setof"); }
6078                 | SMALLINT              { $$ = make_str("smallint"); }
6079                 | SUBSTRING             { $$ = make_str("substring"); }
6080                 | TIME                  { $$ = make_str("time"); }
6081                 | TIMESTAMP             { $$ = make_str("timestamp"); }
6082                 | TREAT                 { $$ = make_str("treat"); }
6083                 | TRIM                  { $$ = make_str("trim"); }
6084                 | VARCHAR               { $$ = make_str("varchar"); }
6085                 ;
6086
6087 /* Function identifier --- keywords that can be function names.
6088  *
6089  * Most of these are keywords that are used as operators in expressions;
6090  * in general such keywords can't be column names because they would be
6091  * ambiguous with variables, but they are unambiguous as function identifiers.
6092  *
6093  * Do not include POSITION, SUBSTRING, etc here since they have explicit
6094  * productions in a_expr to support the goofy SQL9x argument syntax.
6095  *      - thomas 2000-11-28
6096  */
6097 func_name_keyword:
6098                   AUTHORIZATION         { $$ = make_str("authorization"); }
6099                 | BETWEEN               { $$ = make_str("between"); }
6100                 | BINARY                { $$ = make_str("binary"); }
6101                 | CROSS                 { $$ = make_str("cross"); }
6102                 | FREEZE                { $$ = make_str("freeze"); }
6103                 | FULL                  { $$ = make_str("full"); }
6104                 | ILIKE                 { $$ = make_str("ilike"); }
6105                 | INNER_P               { $$ = make_str("inner"); }
6106                 | IS                    { $$ = make_str("is"); }
6107                 | ISNULL                { $$ = make_str("isnull"); }
6108                 | JOIN                  { $$ = make_str("join"); }
6109                 | LEFT                  { $$ = make_str("left"); }
6110                 | LIKE                  { $$ = make_str("like"); }
6111                 | NATURAL               { $$ = make_str("natural"); }
6112                 | NOTNULL               { $$ = make_str("notnull"); }
6113                 | OUTER_P               { $$ = make_str("outer"); }
6114                 | OVERLAPS              { $$ = make_str("overlaps"); }
6115                 | RIGHT                 { $$ = make_str("right"); }
6116                 | SIMILAR               { $$ = make_str("similar"); }
6117                 | VERBOSE               { $$ = make_str("verbose"); }
6118                 ;
6119
6120 /* Reserved keyword --- these keywords are usable only as a ColLabel.
6121  *
6122  * Keywords appear here if they could not be distinguished from variable,
6123  * type, or function names in some contexts.  Don't put things here unless
6124  * forced to.
6125  */
6126 reserved_keyword:
6127                   ALL                           { $$ = make_str("all"); }
6128                 | ANALYSE                       { $$ = make_str("analyse"); } /* British */
6129                 | ANALYZE                       { $$ = make_str("analyze"); }
6130                 | AND                           { $$ = make_str("and"); }
6131                 | ANY                           { $$ = make_str("any"); }
6132                 | ARRAY                         { $$ = make_str("array"); }
6133                 | AS                            { $$ = make_str("as"); }
6134                 | ASC                           { $$ = make_str("asc"); }
6135                 | BOTH                          { $$ = make_str("both"); }
6136                 | CASE                          { $$ = make_str("case"); }
6137                 | CAST                          { $$ = make_str("cast"); }
6138                 | CHECK                         { $$ = make_str("check"); }
6139                 | COLLATE                       { $$ = make_str("collate"); }
6140                 | COLUMN                        { $$ = make_str("column"); }
6141                 | CONSTRAINT                    { $$ = make_str("constraint"); }
6142                 | CREATE                        { $$ = make_str("create"); }
6143                 | CURRENT_DATE                  { $$ = make_str("current_date"); }
6144                 | CURRENT_TIME                  { $$ = make_str("current_time"); }
6145                 | CURRENT_TIMESTAMP             { $$ = make_str("current_timestamp"); }
6146                 | CURRENT_USER                  { $$ = make_str("current_user"); }
6147                 | DEFAULT                       { $$ = make_str("default"); }
6148                 | DEFERRABLE                    { $$ = make_str("deferrable"); }
6149                 | DESC                          { $$ = make_str("desc"); }
6150                 | DISTINCT                      { $$ = make_str("distinct"); }
6151                 | DO                            { $$ = make_str("do"); }
6152                 | ELSE                          { $$ = make_str("else"); }
6153                 | END_P                         { $$ = make_str("end"); }
6154                 | EXCEPT                        { $$ = make_str("except"); }
6155                 | FALSE_P                       { $$ = make_str("false"); }
6156                 | FOR                           { $$ = make_str("for"); }
6157                 | FOREIGN                       { $$ = make_str("foreign"); }
6158                 | FROM                          { $$ = make_str("from"); }
6159                 | GRANT                         { $$ = make_str("grant"); }
6160                 | GROUP_P                       { $$ = make_str("group"); }
6161                 | HAVING                        { $$ = make_str("having"); }
6162                 | IN_P                          { $$ = make_str("in"); }
6163                 | INITIALLY                     { $$ = make_str("initially"); }
6164                 | INTERSECT                     { $$ = make_str("intersect"); }
6165                 | INTO                          { $$ = make_str("into"); }
6166                 | LEADING                       { $$ = make_str("leading"); }
6167                 | LIMIT                         { $$ = make_str("limit"); }
6168                 | NEW                           { $$ = make_str("new"); }
6169                 | NOT                           { $$ = make_str("not"); }
6170                 | NOWAIT                        { $$ = make_str("nowait"); }
6171                 | NULL_P                        { $$ = make_str("null"); }
6172                 | OFF                           { $$ = make_str("off"); }
6173                 | OFFSET                        { $$ = make_str("offset"); }
6174                 | OLD                           { $$ = make_str("old"); }
6175                 | ON                            { $$ = make_str("on"); }
6176                 | ONLY                          { $$ = make_str("only"); }
6177                 | OR                            { $$ = make_str("or"); }
6178                 | ORDER                         { $$ = make_str("order"); }
6179                 | PRIMARY                       { $$ = make_str("primary"); }
6180                 | REFERENCES                    { $$ = make_str("references"); }
6181                 | SELECT                        { $$ = make_str("select"); }
6182                 | SESSION_USER                  { $$ = make_str("session_user"); }
6183                 | SOME                          { $$ = make_str("some"); }
6184                 | TABLE                         { $$ = make_str("table"); }
6185                 | THEN                          { $$ = make_str("then"); }
6186 /* TO must be excluded from ECPGColLabel because of a conflict in variable name parsing
6187                 | TO                            { $$ = make_str("to"); }
6188  */
6189                 | TRAILING                      { $$ = make_str("trailing"); }
6190                 | TRUE_P                        { $$ = make_str("true"); }
6191 /* UNION must be excluded from ECPGColLabel because of conflict with s_union
6192                 | UNION                         { $$ = make_str("union"); }
6193  */
6194                 | UNIQUE                        { $$ = make_str("unique"); }
6195                 | USER                          { $$ = make_str("user"); }
6196                 | USING                         { $$ = make_str("using"); }
6197                 | WHEN                          { $$ = make_str("when"); }
6198                 | WHERE                         { $$ = make_str("where"); }
6199                 ;
6200
6201
6202 into_list : coutputvariable | into_list ',' coutputvariable
6203                 ;
6204
6205 ecpgstart: SQL_START    { reset_variables(); }
6206                 ;
6207
6208 c_args: /*EMPTY*/               { $$ = EMPTY; }
6209                 | c_list                { $$ = $1; }
6210                 ;
6211
6212 coutputvariable: cvariable indicator
6213                         { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
6214                 | cvariable
6215                         { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
6216                 ;
6217
6218
6219 civarind: cvariable indicator
6220                 {
6221                         if (find_variable($2)->type->type == ECPGt_array)
6222                                 mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
6223
6224                         add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
6225                         $$ = create_questionmarks($1, false);
6226                 }
6227                 ;
6228
6229 civar: cvariable
6230                         {
6231                                 add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
6232                                 $$ = create_questionmarks($1, false);
6233                         }
6234                 ;
6235
6236 indicator: cvariable                            { check_indicator((find_variable($1))->type); $$ = $1; }
6237                 | SQL_INDICATOR cvariable       { check_indicator((find_variable($2))->type); $$ = $2; }
6238                 | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
6239                 ;
6240
6241 cvariable:      CVARIABLE 
6242                 {
6243                         /* As long as multidimensional arrays are not implemented we have to check for those here */
6244                         char *ptr = $1;
6245                         int brace_open=0, brace = false;
6246                         
6247                         for (; *ptr; ptr++)
6248                         {
6249                                 switch (*ptr)
6250                                 {
6251                                         case '[':       if (brace)
6252                                                         {
6253                                                                 mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support for simple data types");
6254                                                         }
6255                                                         brace_open++;
6256                                                         break;
6257                                         case ']':       brace_open--;
6258                                                         if (brace_open == 0) brace = true;
6259                                                         break;
6260                                         case '\t':
6261                                         case ' ':       break;
6262                                         default:        if (brace_open == 0) brace = false;
6263                                                         break;
6264                                 }
6265                         }
6266
6267                         $$ = $1;
6268                 }
6269                 ;
6270 ident: IDENT                                    { $$ = $1; }
6271                 | CSTRING                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
6272                 ;
6273
6274 quoted_ident_stringvar: name
6275                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
6276                 | char_variable
6277                         { $$ = make3_str(make_str("("), $1, make_str(")")); }
6278                 ;
6279
6280 /*
6281  * C stuff
6282  */
6283
6284 c_stuff_item: c_anything                        { $$ = $1; }
6285                 | '(' ')'                       { $$ = make_str("()"); }
6286                 | '(' c_stuff ')'
6287                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
6288                 ;
6289
6290 c_stuff: c_stuff_item   { $$ = $1; }
6291                 | c_stuff c_stuff_item
6292                         { $$ = cat2_str($1, $2); }
6293                 ;
6294
6295 c_list: c_term                          { $$ = $1; }
6296                 | c_list ',' c_term     { $$ = cat_str(3, $1, make_str(","), $3); }
6297                 ;
6298
6299 c_term:  c_stuff                        { $$ = $1; }
6300                 | '{' c_list '}'        { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
6301                 ;
6302
6303 c_thing:        c_anything      { $$ = $1; }
6304                 |       '('     { $$ = make_str("("); }
6305                 |       ')'     { $$ = make_str(")"); }
6306                 |       ','     { $$ = make_str(","); }
6307                 |       ';'     { $$ = make_str(";"); }
6308                 ;
6309
6310 c_anything:  IDENT                              { $$ = $1; }
6311                 | CSTRING                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
6312                 | Iconst                        { $$ = $1; }
6313                 | Fconst                        { $$ = $1; }
6314                 | Sconst                        { $$ = $1; }
6315                 | '*'                           { $$ = make_str("*"); }
6316                 | '+'                           { $$ = make_str("+"); }
6317                 | '-'                           { $$ = make_str("-"); }
6318                 | '/'                           { $$ = make_str("/"); }
6319                 | '%'                           { $$ = make_str("%"); }
6320                 | NULL_P                        { $$ = make_str("NULL"); }
6321                 | S_ADD                         { $$ = make_str("+="); }
6322                 | S_AND                         { $$ = make_str("&&"); }
6323                 | S_ANYTHING                    { $$ = make_name(); }
6324                 | S_AUTO                        { $$ = make_str("auto"); }
6325                 | S_CONST                       { $$ = make_str("const"); }
6326                 | S_DEC                         { $$ = make_str("--"); }
6327                 | S_DIV                         { $$ = make_str("/="); }
6328                 | S_DOTPOINT                    { $$ = make_str(".*"); }
6329                 | S_EQUAL                       { $$ = make_str("=="); }
6330                 | S_EXTERN                      { $$ = make_str("extern"); }
6331                 | S_INC                         { $$ = make_str("++"); }
6332                 | S_LSHIFT                      { $$ = make_str("<<"); }
6333                 | S_MEMBER                      { $$ = make_str("->"); }
6334                 | S_MEMPOINT                    { $$ = make_str("->*"); }
6335                 | S_MOD                         { $$ = make_str("%="); }
6336                 | S_MUL                         { $$ = make_str("*="); }
6337                 | S_NEQUAL                      { $$ = make_str("!="); }
6338                 | S_OR                          { $$ = make_str("||"); }
6339                 | S_REGISTER                    { $$ = make_str("register"); }
6340                 | S_RSHIFT                      { $$ = make_str(">>"); }
6341                 | S_STATIC                      { $$ = make_str("static"); }
6342                 | S_SUB                         { $$ = make_str("-="); }
6343                 | S_TYPEDEF                     { $$ = make_str("typedef"); }
6344                 | S_VOLATILE                    { $$ = make_str("volatile"); }
6345                 | SQL_BOOL                      { $$ = make_str("bool"); }
6346                 | SQL_ENUM                      { $$ = make_str("enum"); }
6347                 | HOUR_P                        { $$ = make_str("hour"); }
6348                 | INT_P                         { $$ = make_str("int"); }
6349                 | SQL_LONG                      { $$ = make_str("long"); }
6350                 | MINUTE_P                      { $$ = make_str("minute"); }
6351                 | MONTH_P                       { $$ = make_str("month"); }
6352                 | SECOND_P                      { $$ = make_str("second"); }
6353                 | SQL_SHORT                     { $$ = make_str("short"); }
6354                 | SQL_SIGNED                    { $$ = make_str("signed"); }
6355                 | SQL_STRUCT                    { $$ = make_str("struct"); }
6356                 | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
6357                 | YEAR_P                        { $$ = make_str("year"); }
6358                 | CHAR_P                        { $$ = make_str("char"); }
6359                 | FLOAT_P                       { $$ = make_str("float"); }
6360                 | TO                            { $$ = make_str("to"); }
6361                 | UNION                         { $$ = make_str("union"); }
6362                 | VARCHAR                       { $$ = make_str("varchar"); }
6363                 | '['                           { $$ = make_str("["); }
6364                 | ']'                           { $$ = make_str("]"); }
6365                 | '='                           { $$ = make_str("="); }
6366                 ;
6367
6368 %%
6369
6370 void yyerror( char * error)
6371 {
6372         char buf[1024];
6373
6374         snprintf(buf,sizeof buf,"%s at or near \"%s\"", error, token_start ? token_start : yytext);
6375         buf[sizeof(buf)-1]=0;
6376         mmerror(PARSE_ERROR, ET_ERROR, buf);
6377 }
6378
6379 #include "pgc.c"