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