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