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