]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/preproc.y
6c6006c175ecc22c1b1c320587fcbaba380dd75a
[postgresql] / src / interfaces / ecpg / preproc / preproc.y
1 /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.242 2003/06/29 09:25:19 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 */             { $$ = EMPTY; }
2710         | WITH HOLD                     { $$ = make_str("with hold"); }
2711         | WITHOUT HOLD                  { $$ = make_str("without hold"); }
2712         ;
2713         
2714 /*****************************************************************************
2715  *
2716  *              QUERY:
2717  *                              SELECT STATEMENTS
2718  *
2719  *****************************************************************************/
2720
2721 SelectStmt: select_no_parens            %prec UMINUS
2722                         { $$ = $1; }
2723                 |       select_with_parens              %prec UMINUS
2724                         { $$ = $1; }
2725                 ;
2726
2727 select_with_parens: '(' select_no_parens ')'
2728                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2729                 | '(' select_with_parens ')'
2730                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2731                 ;
2732
2733 select_no_parens:          simple_select
2734                         { $$ = $1; }
2735                 | select_clause sort_clause
2736                         { $$ = cat2_str($1, $2); }
2737                 | select_clause opt_sort_clause for_update_clause opt_select_limit
2738                         { $$ = cat_str(4, $1, $2, $3, $4); }
2739                 | select_clause opt_sort_clause select_limit opt_for_update_clause
2740                         { $$ = cat_str(4, $1, $2, $3, $4); }
2741                 ;
2742
2743 select_clause: simple_select            { $$ = $1; }
2744                 | select_with_parens            { $$ = $1; }
2745                 ;
2746
2747 simple_select:  SELECT opt_distinct target_list
2748                                         into_clause from_clause where_clause
2749                                         group_clause having_clause
2750                         { $$ = cat_str(8, make_str("select"), $2, $3, $4, $5, $6, $7, $8); }
2751                 | select_clause UNION opt_all select_clause
2752                         { $$ = cat_str(4, $1, make_str("union"), $3, $4); }
2753                 | select_clause INTERSECT opt_all select_clause
2754                         { $$ = cat_str(4, $1, make_str("intersect"), $3, $4); }
2755                 | select_clause EXCEPT opt_all select_clause
2756                         { $$ = cat_str(4, $1, make_str("except"), $3, $4); }
2757                 ;
2758
2759 into_clause:  INTO OptTempTableName
2760                 {
2761                         FoundInto = 1;
2762                         $$= cat2_str(make_str("into"), $2);
2763                 }
2764                 | ecpg_into_using               { $$ = EMPTY; }
2765                 | /*EMPTY*/                     { $$ = EMPTY; }
2766                 ;
2767
2768 /*
2769  * Redundancy here is needed to avoid shift/reduce conflicts,
2770  * since TEMP is not a reserved word.  See also OptTemp.
2771  *
2772  * The result is a cons cell (not a true list!) containing
2773  * a boolean and a table name.
2774  */
2775 OptTempTableName:  TEMPORARY opt_table qualified_name
2776                         { $$ = cat_str(3, make_str("temporary"), $2, $3); }
2777                 | TEMP opt_table qualified_name
2778                         { $$ = cat_str(3, make_str("temp"), $2, $3); }
2779                 | LOCAL TEMPORARY opt_table qualified_name
2780                         { $$ = cat_str(3, make_str("local temporary"), $3, $4); }
2781                 | LOCAL TEMP opt_table qualified_name
2782                         { $$ = cat_str(3, make_str("local temp"), $3, $4); }
2783                 | GLOBAL TEMPORARY opt_table qualified_name
2784                         { $$ = cat_str(3, make_str("global temporary"), $3, $4); }
2785                 | GLOBAL TEMP opt_table qualified_name
2786                         { $$ = cat_str(3, make_str("global temp"), $3, $4); }
2787                 | TABLE qualified_name
2788                         { $$ = cat2_str(make_str("table"), $2); }
2789                 | qualified_name
2790                         { $$ = $1; }
2791                 ;
2792
2793 opt_table:      TABLE                           { $$ = make_str("table"); }
2794                 | /*EMPTY*/                             { $$ = EMPTY; }
2795                 ;
2796
2797 opt_all:  ALL                                   { $$ = make_str("all"); }
2798                 | /*EMPTY*/                             { $$ = EMPTY; }
2799                 ;
2800
2801 opt_distinct:  DISTINCT
2802                         { $$ = make_str("distinct"); }
2803                 | DISTINCT ON '(' expr_list ')'
2804                         { $$ = cat_str(3, make_str("distinct on ("), $4, make_str(")")); }
2805                 | ALL
2806                         { $$ = make_str("all"); }
2807                 | /*EMPTY*/
2808                         { $$ = EMPTY; }
2809                 ;
2810
2811 opt_sort_clause:        sort_clause     { $$ = $1; }
2812                 | /* EMPTY */           { $$ = EMPTY; }
2813                 ;
2814
2815 sort_clause:  ORDER BY sortby_list
2816                         { $$ = cat2_str(make_str("order by"), $3); }
2817                 ;
2818
2819 sortby_list:  sortby                                    { $$ = $1; }
2820                 | sortby_list ',' sortby                { $$ = cat_str(3, $1, make_str(","), $3); }
2821                 ;
2822
2823 sortby: a_expr OptUseOp
2824                         { $$ = cat2_str($1, $2); }
2825                 ;
2826
2827 OptUseOp:  USING all_Op         { $$ = cat2_str(make_str("using"), $2); }
2828                 | ASC                           { $$ = make_str("asc"); }
2829                 | DESC                          { $$ = make_str("desc"); }
2830                 | /*EMPTY*/                     { $$ = EMPTY; }
2831                 ;
2832
2833 select_limit:   LIMIT select_limit_value OFFSET select_offset_value
2834                    { $$ = cat_str(4, make_str("limit"), $2, make_str("offset"), $4); }
2835                 | OFFSET select_offset_value LIMIT select_limit_value
2836                    { $$ = cat_str(4, make_str("offset"), $2, make_str("limit"), $4); }
2837                 | LIMIT select_limit_value
2838                    { $$ = cat2_str(make_str("limit"), $2); }
2839                 | OFFSET select_offset_value
2840                    { $$ = cat2_str(make_str("offset"), $2); }
2841                 | LIMIT select_limit_value ',' select_offset_value
2842                    { mmerror(PARSE_ERROR, ET_WARNING, "No longer supported LIMIT #,# syntax passed to backend."); }
2843                 ;
2844
2845 opt_select_limit:       select_limit    { $$ = $1; }
2846                 | /*EMPTY*/                                     { $$ = EMPTY; }
2847                 ;
2848
2849 select_limit_value: PosIntConst
2850                 {
2851                         if (atoi($1) < 0)
2852                                 mmerror(PARSE_ERROR, ET_ERROR, "LIMIT must not be negative");
2853                         $$ = $1;
2854                 }
2855                 | ALL   { $$ = make_str("all"); }
2856                 | PARAM { $$ = make_name(); }
2857                 ;
2858
2859 select_offset_value:    PosIntConst
2860                 {
2861                         if (atoi($1) < 0)
2862                                 mmerror(PARSE_ERROR, ET_ERROR, "OFFSET must not be negative");
2863                         $$ = $1;
2864                 }
2865                 | PARAM { $$ = make_name(); }
2866                 ;
2867
2868 /*
2869  *      jimmy bell-style recursive queries aren't supported in the
2870  *      current system.
2871  *
2872  *      ...however, recursive addattr and rename supported.  make special
2873  *      cases for these.
2874  */
2875 group_clause:  GROUP_P BY expr_list
2876                         { $$ = cat2_str(make_str("group by"), $3); }
2877                 | /*EMPTY*/
2878                         { $$ = EMPTY; }
2879                 ;
2880
2881 having_clause:  HAVING a_expr
2882                         { $$ = cat2_str(make_str("having"), $2); }
2883                 | /*EMPTY*/
2884                         { $$ = EMPTY; }
2885                 ;
2886
2887 for_update_clause:      FOR UPDATE update_list
2888                         { $$ = make_str("for update"); }
2889                 | FOR READ ONLY
2890                         { $$ = make_str("for read only"); }
2891                 ;
2892
2893 opt_for_update_clause: for_update_clause        { $$ = $1; }
2894                 | /* EMPTY */                                           { $$ = EMPTY; }
2895                 ;
2896
2897 update_list:  OF name_list              { $$ = cat2_str(make_str("of"), $2); }
2898                 | /* EMPTY */                   { $$ = EMPTY; }
2899                 ;
2900
2901 /*****************************************************************************
2902  *
2903  *      clauses common to all Optimizable Stmts:
2904  *              from_clause - allow list of both JOIN expressions and table names
2905  *              where_clause    - qualifications for joins or restrictions
2906  *
2907  *****************************************************************************/
2908
2909 from_clause:    FROM from_list          { $$ = cat2_str(make_str("from"), $2); }
2910                 | /* EMPTY */                           { $$ = EMPTY; }
2911                 ;
2912
2913 from_list:      from_list ',' table_ref { $$ = cat_str(3, $1, make_str(","), $3); }
2914                 | table_ref                                     { $$ = $1; }
2915                 ;
2916
2917 /*
2918  * table_ref is where an alias clause can be attached.  Note we cannot make
2919  * alias_clause have an empty production because that causes parse conflicts
2920  * between table_ref := '(' joined_table ')' alias_clause
2921  * and joined_table := '(' joined_table ')'.  So, we must have the
2922  * redundant-looking productions here instead.
2923  */
2924 table_ref:      relation_expr
2925                         { $$ = $1; }
2926                 | relation_expr alias_clause
2927                         { $$= cat2_str($1, $2); }
2928                 | func_table
2929                         { $$ = $1; }
2930                 | func_table alias_clause
2931                         { $$= cat2_str($1, $2); }
2932                 | func_table AS '(' TableFuncElementList ')'
2933                         { $$=cat_str(4, $1, make_str("as ("), $4, make_str(")")); }
2934                 | func_table AS ColId '(' TableFuncElementList ')'
2935                         { $$=cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")")); }
2936                 | func_table ColId '(' TableFuncElementList ')'
2937                         { $$=cat_str(5, $1, $2, make_str("("), $4, make_str(")")); }
2938                 | select_with_parens
2939                         {mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias");}
2940                 | select_with_parens alias_clause
2941                         { $$=cat2_str($1, $2); }
2942                 | joined_table
2943                         { $$ = $1; }
2944                 | '(' joined_table ')' alias_clause
2945                         { $$=cat_str(4, make_str("("), $2, make_str(")"), $4); }
2946                 ;
2947
2948 /*
2949  * It may seem silly to separate joined_table from table_ref, but there is
2950  * method in SQL92's madness: if you don't do it this way you get reduce-
2951  * reduce conflicts, because it's not clear to the parser generator whether
2952  * to expect alias_clause after ')' or not.  For the same reason we must
2953  * treat 'JOIN' and 'join_type JOIN' separately, rather than allowing
2954  * join_type to expand to empty; if we try it, the parser generator can't
2955  * figure out when to reduce an empty join_type right after table_ref.
2956  *
2957  * Note that a CROSS JOIN is the same as an unqualified
2958  * INNER JOIN, and an INNER JOIN/ON has the same shape
2959  * but a qualification expression to limit membership.
2960  * A NATURAL JOIN implicitly matches column names between
2961  * tables and the shape is determined by which columns are
2962  * in common. We'll collect columns during the later transformations.
2963  */
2964
2965 joined_table:  '(' joined_table ')'
2966                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2967                 | table_ref CROSS JOIN table_ref
2968                         { $$ = cat_str(3, $1, make_str("cross join"), $4); }
2969                 | table_ref UNIONJOIN table_ref
2970                         { $$ = cat_str(3, $1, make_str("unionjoin"), $3); }
2971                 | table_ref join_type JOIN table_ref join_qual
2972                         { $$ = cat_str(5, $1, $2, make_str("join"), $4, $5); }
2973                 | table_ref JOIN table_ref join_qual
2974                         { $$ = cat_str(4, $1, make_str("join"), $3, $4); }
2975                 | table_ref NATURAL join_type JOIN table_ref
2976                         { $$ = cat_str(5, $1, make_str("natural"), $3, make_str("join"), $5); }
2977                 | table_ref NATURAL JOIN table_ref
2978                         { $$ = cat_str(3, $1, make_str("natural join"), $4); }
2979                 ;
2980
2981 alias_clause:  AS ColId '(' name_list ')'
2982                         { $$ = cat_str(5, make_str("as"), $2, make_str("("), $4, make_str(")")); }
2983                 | AS ColId
2984                         { $$ = cat2_str(make_str("as"), $2); }
2985                 | ColId '(' name_list ')'
2986                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
2987                 | ColId
2988                         { $$ = $1; }
2989                 ;
2990
2991 join_type:      FULL join_outer         { $$ = cat2_str(make_str("full"), $2); }
2992                 | LEFT join_outer               { $$ = cat2_str(make_str("left"), $2); }
2993                 | RIGHT join_outer              { $$ = cat2_str(make_str("right"), $2); }
2994                 | INNER_P                               { $$ = make_str("inner"); }
2995                 ;
2996
2997 /* OUTER is just noise... */
2998 join_outer:  OUTER_P                    { $$ = make_str("outer"); }
2999                 | /*EMPTY*/                             { $$ = EMPTY;  /* no qualifiers */ }
3000                 ;
3001
3002 /* JOIN qualification clauses
3003  * Possibilities are:
3004  *      USING ( column list ) allows only unqualified column names,
3005  *                                                which must match between tables.
3006  *      ON expr allows more general qualifications.
3007  */
3008
3009 join_qual:      USING '(' name_list ')'
3010                         { $$ = cat_str(3, make_str("using ("), $3, make_str(")")); }
3011                 | ON a_expr
3012                         { $$ = cat2_str(make_str("on"), $2); }
3013                 ;
3014
3015 relation_expr:  qualified_name
3016                         { /* normal relations */ $$ = $1; }
3017                 | qualified_name '*'
3018                         { /* inheritance query */ $$ = cat2_str($1, make_str("*")); }
3019                 | ONLY qualified_name
3020                         { /* inheritance query */ $$ = cat2_str(make_str("only "), $2); }
3021                 | ONLY '(' qualified_name ')'
3022                         { /* inheritance query */ $$ = cat_str(3, make_str("only ("), $3, make_str(")")); }
3023                 ;
3024
3025 func_table:  func_name '(' ')'
3026                 { $$ = cat2_str($1, make_str("()")); }
3027         | func_name '(' expr_list ')'
3028                 { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
3029         ;
3030
3031 where_clause:  WHERE a_expr             { $$ = cat2_str(make_str("where"), $2); }
3032                 | /*EMPTY*/                             { $$ = EMPTY;  /* no qualifiers */ }
3033                 ;
3034
3035 TableFuncElementList: TableFuncElement
3036                         { $$ = $1; }
3037                 | TableFuncElementList ',' TableFuncElement
3038                         { $$ = cat_str(3, $1, ',', $3); }
3039                 ;
3040
3041 TableFuncElement:       ColId Typename  { $$ = cat2_str($1, $2); }
3042                         ;
3043
3044 /*****************************************************************************
3045  *
3046  *      Type syntax
3047  *              SQL92 introduces a large amount of type-specific syntax.
3048  *              Define individual clauses to handle these cases, and use
3049  *               the generic case to handle regular type-extensible Postgres syntax.
3050  *              - thomas 1997-10-10
3051  *
3052  *****************************************************************************/
3053
3054 Typename:  SimpleTypename opt_array_bounds
3055                         { $$ = cat2_str($1, $2.str); }
3056                 | SETOF SimpleTypename opt_array_bounds
3057                         { $$ = cat_str(3, make_str("setof"), $2, $3); }
3058                 | SimpleTypename ARRAY '[' PosIntConst ']'
3059                         { $$ = cat_str(4, $1, make_str("array ["), $4, make_str("]")); }
3060                 | SETOF SimpleTypename ARRAY '[' PosIntConst ']'
3061                         { $$ = cat_str(5, make_str("setof"), $2, make_str("array ["), $5, make_str("]")); }
3062                 ;
3063
3064
3065 opt_array_bounds:  '[' ']' opt_array_bounds
3066                 {
3067                         $$.index1 = make_str("0");
3068                         $$.index2 = $3.index1;
3069                         $$.str = cat2_str(make_str("[]"), $3.str);
3070                 }
3071                 | '[' Iresult ']' opt_array_bounds
3072                 {
3073                         $$.index1 = strdup($2);
3074                         $$.index2 = $4.index1;
3075                         $$.str = cat_str(4, make_str("["), $2, make_str("]"), $4.str);
3076                 }
3077                 | /* EMPTY */
3078                 {
3079                         $$.index1 = make_str("-1");
3080                         $$.index2 = make_str("-1");
3081                         $$.str= EMPTY;
3082                 }
3083                 ;
3084
3085 Iresult:        PosIntConst             { $$ = $1; }
3086                 | '(' Iresult ')'       { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3087                 | Iresult '+' Iresult   { $$ = cat_str(3, $1, make_str("+"), $3); }
3088                 | Iresult '-' Iresult   { $$ = cat_str(3, $1, make_str("-"), $3); }
3089                 | Iresult '*' Iresult   { $$ = cat_str(3, $1, make_str("*"), $3); }
3090                 | Iresult '/' Iresult   { $$ = cat_str(3, $1, make_str("/"), $3); }
3091                 | Iresult '%' Iresult   { $$ = cat_str(3, $1, make_str("%"), $3); }
3092                 | Sconst                { $$ = $1; }
3093                 | ColId                 { $$ = $1; }
3094                 ;
3095
3096 SimpleTypename:  GenericType            { $$ = $1; }
3097                 | ConstDatetime         { $$ = $1; }
3098                 | Numeric               { $$ = $1; }
3099                 | Bit                   { $$ = $1; }
3100                 | Character             { $$ = $1; }
3101                 | ConstInterval opt_interval
3102                         { $$ = cat2_str($1, $2); }
3103                 | ConstInterval '(' PosIntConst ')' opt_interval
3104                         { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
3105                 | type_name attrs
3106                         { $$ = cat2_str($1, $2);}
3107                 ;
3108
3109 ConstTypename:  GenericType             { $$ = $1; }
3110                 | ConstDatetime         { $$ = $1; }
3111                 | Numeric               { $$ = $1; }
3112                 | ConstBit              { $$ = $1; }
3113                 | ConstCharacter        { $$ = $1; }
3114                 ;
3115
3116 GenericType:  type_name                 { $$ = $1; }
3117                 ;
3118
3119 /* SQL92 numeric data types
3120  * Check FLOAT() precision limits assuming IEEE floating types.
3121  * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30
3122  * - thomas 1997-09-18
3123  */
3124 Numeric:  INT_P
3125                         { $$ = make_str("int"); }
3126                 | INTEGER
3127                         { $$ = make_str("integer"); }
3128                 | SMALLINT
3129                         { $$ = make_str("smallint"); }
3130                 | BIGINT
3131                         { $$ = make_str("bigint"); }
3132                 | REAL
3133                         { $$ = make_str("real"); }
3134                 | FLOAT_P opt_float
3135                         { $$ = cat2_str(make_str("float"), $2); }
3136                 | DOUBLE_P PRECISION
3137                         { $$ = make_str("double precision"); }
3138                 | DECIMAL_P opt_decimal
3139                         { $$ = cat2_str(make_str("decimal"), $2); }
3140                 | DEC opt_decimal
3141                         { $$ = cat2_str(make_str("dec"), $2); }
3142                 | NUMERIC opt_numeric
3143                         { $$ = cat2_str(make_str("numeric"), $2); }
3144                 | BOOLEAN_P
3145                         { $$ = make_str("boolean"); }
3146                 ;
3147
3148 opt_float:      '(' PosIntConst ')'
3149                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3150                 | /*EMPTY*/
3151                         { $$ = EMPTY; }
3152                 ;
3153
3154 opt_numeric:  '(' PosIntConst ',' PosIntConst ')'
3155                         { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
3156                 | '(' PosIntConst ')'
3157                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3158                 | /*EMPTY*/
3159                         { $$ = EMPTY; }
3160                 ;
3161
3162 opt_decimal:  '(' PosIntConst ',' PosIntConst ')'
3163                         { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
3164                 | '(' PosIntConst ')'
3165                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3166                 | /*EMPTY*/
3167                         { $$ = EMPTY; }
3168                 ;
3169
3170 /*
3171  * SQL92 bit-field data types
3172  * The following implements BIT() and BIT VARYING().
3173  */
3174
3175 Bit:    BitWithLength           { $$ = $1; }
3176         | BitWithoutLength      { $$ = $1; }
3177         ;
3178
3179 ConstBit:       BitWithLength   { $$ = $1; }
3180                 | BitWithoutLength      { $$ = $1; }
3181                 ;
3182
3183 BitWithLength:  BIT opt_varying '(' PosIntConst ')'
3184                         { $$ = cat_str(5, make_str("bit"), $2, make_str("("), $4, make_str(")")); }
3185                 ;
3186
3187 BitWithoutLength: BIT opt_varying
3188                         { $$ = cat2_str(make_str("bit"), $2); }
3189                 ;
3190
3191 /*
3192  * SQL92 character data types
3193  * The following implements CHAR() and VARCHAR().
3194  *                                                              - ay 6/95
3195  */
3196 Character:      CharacterWithLength             { $$ = $1; }
3197                 | CharacterWithoutLength        { $$ = $1; }
3198                 ;
3199
3200 ConstCharacter: CharacterWithLength     { $$ = $1; }
3201                 | CharacterWithoutLength      { $$ = $1; }
3202                 ;
3203
3204 CharacterWithLength: character '(' PosIntConst ')' opt_charset
3205                         { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
3206                 ;
3207
3208 CharacterWithoutLength: character opt_charset
3209                         { $$ = cat2_str($1, $2); }
3210                 ;
3211
3212 character:      CHARACTER opt_varying
3213                         { $$ = cat2_str(make_str("character"), $2); }
3214                 | CHAR_P opt_varying
3215                         { $$ = cat2_str(make_str("char"), $2); }
3216                 | VARCHAR
3217                         { $$ = make_str("varchar"); }
3218                 | NATIONAL CHARACTER opt_varying
3219                         { $$ = cat2_str(make_str("national character"), $3); }
3220                 | NATIONAL CHAR_P opt_varying
3221                         { $$ = cat2_str(make_str("national char"), $3); }
3222                 | NCHAR opt_varying
3223                         { $$ = cat2_str(make_str("nchar"), $2); }
3224                 ;
3225
3226 opt_varying:  VARYING
3227                         { $$ = make_str("varying"); }
3228                 | /*EMPTY*/
3229                         { $$ = EMPTY; }
3230                 ;
3231
3232 opt_charset:  CHARACTER SET ColId
3233                         { $$ = cat2_str(make_str("character set"), $3); }
3234                 | /*EMPTY*/
3235                         { $$ = EMPTY; }
3236                 ;
3237
3238 opt_collate:  COLLATE ColId
3239                         { $$ = cat2_str(make_str("collate"), $2); }
3240                 | /*EMPTY*/
3241                         { $$ = EMPTY; }
3242                 ;
3243
3244 ConstDatetime:  TIMESTAMP '(' PosIntConst ')' opt_timezone
3245                         { $$ = cat_str(4, make_str("timestamp("), $3, make_str(")"), $5); }
3246                 | TIMESTAMP opt_timezone
3247                         { $$ = cat2_str(make_str("timestamp"), $2); }
3248                 | TIME '(' PosIntConst ')' opt_timezone
3249                         { $$ = cat_str(4, make_str("time("), $3, make_str(")"), $5); }
3250                 | TIME opt_timezone
3251                         { $$ = cat2_str(make_str("time"), $2); }
3252                 ;
3253
3254 ConstInterval:  INTERVAL
3255                         { $$ = make_str("interval"); }
3256                 ;
3257
3258 opt_timezone:  WITH TIME ZONE
3259                         { $$ = make_str("with time zone"); }
3260                 | WITHOUT TIME ZONE
3261                         { $$ = make_str("without time zone"); }
3262                 | /*EMPTY*/
3263                         { $$ = EMPTY; }
3264                 ;
3265
3266 opt_interval:  YEAR_P                   { $$ = make_str("year"); }
3267                 | MONTH_P                               { $$ = make_str("month"); }
3268                 | DAY_P                                 { $$ = make_str("day"); }
3269                 | HOUR_P                                { $$ = make_str("hour"); }
3270                 | MINUTE_P                              { $$ = make_str("minute"); }
3271                 | SECOND_P                              { $$ = make_str("second"); }
3272                 | YEAR_P TO MONTH_P             { $$ = make_str("year to month"); }
3273                 | DAY_P TO HOUR_P               { $$ = make_str("day to hour"); }
3274                 | DAY_P TO MINUTE_P             { $$ = make_str("day to minute"); }
3275                 | DAY_P TO SECOND_P             { $$ = make_str("day to second"); }
3276                 | HOUR_P TO MINUTE_P    { $$ = make_str("hour to minute"); }
3277                 | MINUTE_P TO SECOND_P  { $$ = make_str("minute to second"); }
3278                 | HOUR_P TO SECOND_P    { $$ = make_str("hour to second"); }
3279                 | /*EMPTY*/                             { $$ = EMPTY; }
3280                 ;
3281
3282
3283 /*****************************************************************************
3284  *
3285  *      expression grammar
3286  *
3287  *****************************************************************************/
3288
3289 /* Expressions using row descriptors
3290  * Define row_descriptor to allow yacc to break the reduce/reduce conflict
3291  *      with singleton expressions.
3292  */
3293 r_expr: row IN_P select_with_parens
3294                         { $$ = cat_str(3, $1, make_str("in"), $3); }
3295                 | row NOT IN_P select_with_parens
3296                         { $$ = cat_str(3, $1, make_str("not in"), $4); }
3297                 | row qual_all_Op sub_type select_with_parens %prec Op
3298                         { $$ = cat_str(4, $1, $2, $3, $4); }
3299                 | row qual_all_Op select_with_parens %prec Op
3300                         { $$ = cat_str(3, $1, $2, $3); }
3301                 | row qual_all_Op row %prec Op
3302                         { $$ = cat_str(3, $1, $2, $3); }
3303                 | row IS NULL_P
3304                         { $$ = cat2_str($1, make_str("is null")); }
3305                 | row IS NOT NULL_P
3306                         { $$ = cat2_str($1, make_str("is not null")); }
3307                 | row OVERLAPS row
3308                         { $$ = cat_str(3, $1, make_str("overlaps"), $3); }
3309                 | row IS DISTINCT FROM row %prec IS
3310                         { $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
3311                 ;
3312
3313 row: ROW '(' row_descriptor ')'
3314                 { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
3315         | ROW '(' a_expr ')'
3316                 { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
3317         | ROW '(' ')'
3318                 { $$ = make_str("row()"); }
3319         | '(' row_descriptor ')'
3320                 { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3321         ;
3322
3323 row_descriptor:  expr_list ',' a_expr
3324                         { $$ = cat_str(3, $1, make_str(","), $3); }
3325                 ;
3326
3327 sub_type:  ANY                                  { $$ = make_str("ANY"); }
3328                 | SOME                                  { $$ = make_str("SOME"); }
3329                 | ALL                                   { $$ = make_str("ALL"); }
3330                           ;
3331
3332 all_Op:  Op                             { $$ = $1; }
3333         | MathOp                        { $$ = $1; }
3334         ;
3335
3336 MathOp: '+'                             { $$ = make_str("+"); }
3337                 | '-'                   { $$ = make_str("-"); }
3338                 | '*'                   { $$ = make_str("*"); }
3339                 | '%'                   { $$ = make_str("%"); }
3340                 | '^'                   { $$ = make_str("^"); }
3341                 | '/'                   { $$ = make_str("/"); }
3342                 | '<'                   { $$ = make_str("<"); }
3343                 | '>'                   { $$ = make_str(">"); }
3344                 | '='                   { $$ = make_str("="); }
3345                 ;
3346
3347 qual_Op:  Op                            { $$ = $1; }
3348                 | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
3349                 ;
3350
3351 qual_all_Op:  all_Op                            { $$ = $1; }
3352                 | OPERATOR '(' any_operator ')' { $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
3353                 ;
3354
3355 /* General expressions
3356  * This is the heart of the expression syntax.
3357  *
3358  * We have two expression types: a_expr is the unrestricted kind, and
3359  * b_expr is a subset that must be used in some places to avoid shift/reduce
3360  * conflicts.  For example, we can't do BETWEEN as "BETWEEN a_expr AND a_expr"
3361  * because that use of AND conflicts with AND as a boolean operator.  So,
3362  * b_expr is used in BETWEEN and we remove boolean keywords from b_expr.
3363  *
3364  * Note that '(' a_expr ')' is a b_expr, so an unrestricted expression can
3365  * always be used by surrounding it with parens.
3366  *
3367  * c_expr is all the productions that are common to a_expr and b_expr;
3368  * it's factored out just to eliminate redundant coding.
3369  */
3370
3371 a_expr:  c_expr
3372                         { $$ = $1; }
3373                 | a_expr TYPECAST Typename
3374                         { $$ = cat_str(3, $1, make_str("::"), $3); }
3375                 | a_expr AT TIME ZONE c_expr
3376                         { $$ = cat_str(3, $1, make_str("at time zone"), $5); }
3377                 /*
3378                  * These operators must be called out explicitly in order to make use
3379                  * of yacc/bison's automatic operator-precedence handling.  All other
3380                  * operator names are handled by the generic productions using "Op",
3381                  * below; and all those operators will have the same precedence.
3382                  *
3383                  * If you add more explicitly-known operators, be sure to add them
3384                  * also to b_expr and to the MathOp list above.
3385                  */
3386                 | '+' a_expr %prec UMINUS
3387                         { $$ = cat2_str(make_str("+"), $2); }
3388                 | '-' a_expr %prec UMINUS
3389                         { $$ = cat2_str(make_str("-"), $2); }
3390                 | '%' a_expr
3391                         { $$ = cat2_str(make_str("%"), $2); }
3392                 | '^' a_expr
3393                         { $$ = cat2_str(make_str("^"), $2); }
3394                 | a_expr '%'
3395                         { $$ = cat2_str($1, make_str("%")); }
3396                 | a_expr '^'
3397                         { $$ = cat2_str($1, make_str("^")); }
3398                 | a_expr '+' a_expr
3399                         { $$ = cat_str(3, $1, make_str("+"), $3); }
3400                 | a_expr '-' a_expr
3401                         { $$ = cat_str(3, $1, make_str("-"), $3); }
3402                 | a_expr '*' a_expr
3403                         { $$ = cat_str(3, $1, make_str("*"), $3); }
3404                 | a_expr '/' a_expr
3405                         { $$ = cat_str(3, $1, make_str("/"), $3); }
3406                 | a_expr '%' a_expr
3407                         { $$ = cat_str(3, $1, make_str("%"), $3); }
3408                 | a_expr '^' a_expr
3409                         { $$ = cat_str(3, $1, make_str("^"), $3); }
3410                 | a_expr '<' a_expr
3411                         { $$ = cat_str(3, $1, make_str("<"), $3); }
3412                 | a_expr '>' a_expr
3413                         { $$ = cat_str(3, $1, make_str(">"), $3); }
3414                 | a_expr '=' a_expr
3415                         { $$ = cat_str(3, $1, make_str("="), $3); }
3416                 | a_expr qual_Op a_expr         %prec Op
3417                         { $$ = cat_str(3, $1, $2, $3); }
3418                 | qual_Op a_expr                %prec Op
3419                         { $$ = cat2_str($1, $2); }
3420                 | a_expr qual_Op                %prec POSTFIXOP
3421                         { $$ = cat2_str($1, $2); }
3422                 | a_expr AND a_expr
3423                         { $$ = cat_str(3, $1, make_str("and"), $3); }
3424                 | a_expr OR a_expr
3425                         { $$ = cat_str(3, $1, make_str("or"), $3); }
3426                 | NOT a_expr
3427                         { $$ = cat2_str(make_str("not"), $2); }
3428                 | a_expr LIKE a_expr
3429                         { $$ = cat_str(3, $1, make_str("like"), $3); }
3430                 | a_expr LIKE a_expr ESCAPE a_expr
3431                         { $$ = cat_str(5, $1, make_str("like"), $3, make_str("escape"), $5); }
3432                 | a_expr NOT LIKE a_expr
3433                         { $$ = cat_str(3, $1, make_str("not like"), $4); }
3434                 | a_expr NOT LIKE a_expr ESCAPE a_expr
3435                         { $$ = cat_str(5, $1, make_str("not like"), $4, make_str("escape"), $6); }
3436                 | a_expr ILIKE a_expr
3437                         { $$ = cat_str(3, $1, make_str("ilike"), $3); }
3438                 | a_expr ILIKE a_expr ESCAPE a_expr
3439                         { $$ = cat_str(5, $1, make_str("ilike"), $3, make_str("escape"), $5); }
3440                 | a_expr NOT ILIKE a_expr
3441                         { $$ = cat_str(3, $1, make_str("not ilike"), $4); }
3442                 | a_expr NOT ILIKE a_expr ESCAPE a_expr
3443                         { $$ = cat_str(5, $1, make_str("not ilike"), $4, make_str("escape"), $6); }
3444                 | a_expr SIMILAR TO a_expr      %prec SIMILAR
3445                         { $$ = cat_str(3, $1, make_str("similar to"), $4); }
3446                 | a_expr SIMILAR TO a_expr ESCAPE a_expr
3447                         { $$ = cat_str(5, $1, make_str("similar to"), $4, make_str("escape"), $6); }
3448                 | a_expr NOT SIMILAR TO a_expr  %prec SIMILAR
3449                         { $$ = cat_str(3, $1, make_str("not similar to"), $5); }
3450                 | a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
3451                         { $$ = cat_str(5, $1, make_str("not similar to"), $5, make_str("escape"), $7); }
3452                 | a_expr ISNULL
3453                         { $$ = cat2_str($1, make_str("isnull")); }
3454                 | a_expr IS NULL_P
3455                         { $$ = cat2_str($1, make_str("is null")); }
3456                 | a_expr NOTNULL
3457                         { $$ = cat2_str($1, make_str("notnull")); }
3458                 | a_expr IS NOT NULL_P
3459                         { $$ = cat2_str($1, make_str("is not null")); }
3460                 /* IS TRUE, IS FALSE, etc used to be function calls
3461                  *      but let's make them expressions to allow the optimizer
3462                  *      a chance to eliminate them if a_expr is a constant string.
3463                  * - thomas 1997-12-22
3464                  *
3465                  *      Created BooleanTest Node type, and changed handling
3466                  *      for NULL inputs
3467                  * - jec 2001-06-18
3468                  */
3469                 | a_expr IS TRUE_P
3470                         { $$ = cat2_str($1, make_str("is true")); }
3471                 | a_expr IS NOT TRUE_P
3472                         { $$ = cat2_str($1, make_str("is not true")); }
3473                 | a_expr IS FALSE_P
3474                         { $$ = cat2_str($1, make_str("is false")); }
3475                 | a_expr IS NOT FALSE_P
3476                         { $$ = cat2_str($1, make_str("is not false")); }
3477                 | a_expr IS UNKNOWN
3478                         { $$ = cat2_str($1, make_str("is unknown")); }
3479                 | a_expr IS NOT UNKNOWN
3480                         { $$ = cat2_str($1, make_str("is not unknown")); }
3481                 | a_expr IS DISTINCT FROM a_expr %prec IS
3482                         { $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
3483                 | a_expr IS OF '(' type_list ')' %prec IS
3484                         { $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
3485                 | a_expr IS NOT OF '(' type_list ')' %prec IS
3486                         { $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
3487                 | a_expr BETWEEN b_expr AND b_expr      %prec BETWEEN
3488                         { $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5); }
3489                 | a_expr NOT BETWEEN b_expr AND b_expr  %prec BETWEEN
3490                         { $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6); }
3491                 | a_expr IN_P in_expr
3492                         { $$ = cat_str(3, $1, make_str("in"), $3); }
3493                 | a_expr NOT IN_P in_expr
3494                         { $$ = cat_str(3, $1, make_str("not in"), $4); }
3495                 | a_expr qual_all_Op sub_type select_with_parens %prec Op
3496                         { $$ = cat_str(4, $1, $2, $3, $4); }
3497                 | a_expr qual_all_Op sub_type '(' a_expr ')' %prec Op
3498                         { $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")")); }
3499                 | UNIQUE select_with_parens %prec Op
3500                         { $$ = cat2_str(make_str("unique"), $2); }
3501                 | r_expr
3502                         { $$ = $1; }
3503                 ;
3504
3505 /* Restricted expressions
3506  *
3507  * b_expr is a subset of the complete expression syntax
3508  *
3509  * Presently, AND, NOT, IS and IN are the a_expr keywords that would
3510  * cause trouble in the places where b_expr is used.  For simplicity, we
3511  * just eliminate all the boolean-keyword-operator productions from b_expr.
3512  */
3513 b_expr:  c_expr
3514                         { $$ = $1; }
3515                 | b_expr TYPECAST Typename
3516                         { $$ = cat_str(3, $1, make_str("::"), $3); }
3517                 | '-' b_expr %prec UMINUS
3518                         { $$ = cat2_str(make_str("-"), $2); }
3519                 | '%' b_expr
3520                         { $$ = cat2_str(make_str("%"), $2); }
3521                 | '^' b_expr
3522                         { $$ = cat2_str(make_str("^"), $2); }
3523                 | b_expr '%'
3524                         { $$ = cat2_str($1, make_str("%")); }
3525                 | b_expr '^'
3526                         { $$ = cat2_str($1, make_str("^")); }
3527                 | b_expr '+' b_expr
3528                         { $$ = cat_str(3, $1, make_str("+"), $3); }
3529                 | b_expr '-' b_expr
3530                         { $$ = cat_str(3, $1, make_str("-"), $3); }
3531                 | b_expr '*' b_expr
3532                         { $$ = cat_str(3, $1, make_str("*"), $3); }
3533                 | b_expr '/' b_expr
3534                         { $$ = cat_str(3, $1, make_str("/"), $3); }
3535                 | b_expr '%' b_expr
3536                         { $$ = cat_str(3, $1, make_str("%"), $3); }
3537                 | b_expr '^' b_expr
3538                         { $$ = cat_str(3, $1, make_str("^"), $3); }
3539                 | b_expr '<' b_expr
3540                         { $$ = cat_str(3, $1, make_str("<"), $3); }
3541                 | b_expr '>' b_expr
3542                         { $$ = cat_str(3, $1, make_str(">"), $3); }
3543                 | b_expr '=' b_expr
3544                         { $$ = cat_str(3, $1, make_str("="), $3); }
3545                 | b_expr Op b_expr
3546                         { $$ = cat_str(3, $1, $2, $3); }
3547                 | qual_Op b_expr                %prec Op
3548                         { $$ = cat2_str($1, $2); }
3549                 | b_expr qual_Op                %prec POSTFIXOP
3550                         { $$ = cat2_str($1, $2); }
3551                 | b_expr IS DISTINCT FROM b_expr %prec IS
3552                         { $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
3553                 | b_expr IS OF '(' b_expr ')' %prec IS
3554                         { $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
3555                 | b_expr IS NOT OF '(' b_expr ')' %prec IS
3556                         { $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
3557                 ;
3558
3559 /*
3560  * Productions that can be used in both a_expr and b_expr.
3561  *
3562  * Note: productions that refer recursively to a_expr or b_expr mostly
3563  * cannot appear here.  However, it's OK to refer to a_exprs that occur
3564  * inside parentheses, such as function arguments; that cannot introduce
3565  * ambiguity to the b_expr syntax.
3566  */
3567 c_expr: columnref
3568                         { $$ = $1;      }
3569                 | AexprConst
3570                         { $$ = $1;      }
3571                 | PARAM attrs opt_indirection
3572                         { $$ = cat_str(3, make_str("param"), $2, $3); }
3573                 | '(' a_expr ')' attrs opt_indirection
3574                         { $$ = cat_str(5, make_str("("), $2, make_str(")"), $4, $5); }
3575                 | '(' a_expr ')' opt_indirection
3576                         { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
3577                 | case_expr
3578                         { $$ = $1; }
3579                 | func_name '(' ')'
3580                         { $$ = cat2_str($1, make_str("()"));    }
3581                 | func_name '(' expr_list ')'
3582                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));        }
3583                 | func_name '(' ALL expr_list ')'
3584                         { $$ = cat_str(4, $1, make_str("( all"), $4, make_str(")"));    }
3585                 | func_name '(' DISTINCT expr_list ')'
3586                         { $$ = cat_str(4, $1, make_str("( distinct"), $4, make_str(")"));  }
3587                 | func_name '(' '*' ')'
3588                         { $$ = cat2_str($1, make_str("(*)")); }
3589                 | CURRENT_DATE
3590                         { $$ = make_str("current_date"); }
3591                 | CURRENT_TIME opt_empty_parentheses
3592                         { $$ = cat2_str(make_str("current_time"), $2); }
3593                 | CURRENT_TIME '(' PosIntConst ')'
3594                         { $$ = make_str("current_time"); }
3595                 | CURRENT_TIMESTAMP opt_empty_parentheses
3596                         { $$ = cat2_str(make_str("current_timestamp"), $2); }
3597                 | CURRENT_TIMESTAMP '(' PosIntConst ')'
3598                         { $$ = make_str("current_timestamp"); }
3599                 | CURRENT_USER opt_empty_parentheses
3600                         { $$ = cat2_str(make_str("current_user"), $2); }
3601                 | SESSION_USER opt_empty_parentheses
3602                         { $$ = cat2_str(make_str("session_user"), $2); }
3603                 | USER opt_empty_parentheses
3604                         { $$ = cat2_str(make_str("user"), $2); }
3605                 | CAST '(' a_expr AS Typename ')'
3606                         { $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); }
3607                 | EXTRACT '(' extract_list ')'
3608                         { $$ = cat_str(3, make_str("extract("), $3, make_str(")")); }
3609                 | OVERLAY '(' overlay_list ')'
3610                         { $$ = cat_str(3, make_str("overlay("), $3, make_str(")")); }
3611                 | POSITION '(' position_list ')'
3612                         { $$ = cat_str(3, make_str("position("), $3, make_str(")")); }
3613                 | SUBSTRING '(' substr_list ')'
3614                         { $$ = cat_str(3, make_str("substring("), $3, make_str(")")); }
3615                 | TREAT '(' a_expr AS Typename ')'
3616                         { $$ = cat_str(5, make_str("treat("), $3, make_str("as"), $5, make_str(")")); }
3617                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3618                 | TRIM '(' BOTH trim_list ')'
3619                         { $$ = cat_str(3, make_str("trim(both"), $4, make_str(")")); }
3620                 | TRIM '(' LEADING trim_list ')'
3621                         { $$ = cat_str(3, make_str("trim(leading"), $4, make_str(")")); }
3622                 | TRIM '(' TRAILING trim_list ')'
3623                         { $$ = cat_str(3, make_str("trim(trailing"), $4, make_str(")")); }
3624                 | TRIM '(' trim_list ')'
3625                         { $$ = cat_str(3, make_str("trim("), $3, make_str(")")); }
3626                 | CONVERT '(' a_expr USING any_name ')'
3627                         { $$ = cat_str(5, make_str("convert("), $3, make_str("using"), $5, make_str(")"));}
3628                 | CONVERT '(' expr_list ')'
3629                         { $$ = cat_str(3, make_str("convert("), $3, make_str(")")); }
3630                 | select_with_parens    %prec UMINUS
3631                         { $$ = $1; }
3632                 | EXISTS select_with_parens
3633                         { $$ = cat2_str(make_str("exists"), $2); }
3634                 | ARRAY select_with_parens
3635                         { $$ = cat2_str(make_str("array"), $2); }
3636                 | ARRAY array_expr
3637                         { $$ = cat2_str(make_str("array"), $2); }
3638                 ;
3639 /*
3640  * This used to use ecpg_expr, but since there is no shift/reduce conflict
3641  * anymore, we can remove ecpg_expr. - MM
3642  */
3643 opt_indirection:  '[' a_expr ']' opt_indirection
3644                         { $$ = cat_str(4, make_str("["), $2, make_str("]"), $4); }
3645                 | '[' a_expr ':' a_expr ']' opt_indirection
3646                         { $$ = cat_str(6, make_str("["), $2, make_str(":"), $4, make_str("]"), $6); }
3647                 | /* EMPTY */
3648                         { $$ = EMPTY; }
3649                 ;
3650
3651 expr_list:      a_expr
3652                         { $$ = $1; }
3653                 | expr_list ',' a_expr
3654                         { $$ = cat_str(3, $1, make_str(","), $3); }
3655                 ;
3656
3657 extract_list:  extract_arg FROM a_expr
3658                         { $$ = cat_str(3, $1, make_str("from"), $3); }
3659                 | /* EMPTY */
3660                         { $$ = EMPTY; }
3661                 ;
3662
3663 type_list:      type_list ',' Typename
3664                         { $$ = cat_str(3, $1, ',', $3); }
3665                 | Typename
3666                         { $$ = $1; }
3667                 ;
3668
3669 array_expr_list: array_expr                             { $$ = $1; }
3670                 | array_expr_list ',' array_expr        { $$ = cat_str(3, $1, make_str(","), $3); }
3671                 ;
3672                 
3673
3674 array_expr: '[' expr_list ']'                   { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
3675                 | '[' array_expr_list ']'       { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
3676                 ;
3677 /* Allow delimited string SCONST in extract_arg as an SQL extension.
3678  * - thomas 2001-04-12
3679  */
3680
3681 extract_arg:  ident                             { $$ = $1; }
3682                 | YEAR_P                                { $$ = make_str("year"); }
3683                 | MONTH_P                               { $$ = make_str("month"); }
3684                 | DAY_P                                 { $$ = make_str("day"); }
3685                 | HOUR_P                                { $$ = make_str("hour"); }
3686                 | MINUTE_P                              { $$ = make_str("minute"); }
3687                 | SECOND_P                              { $$ = make_str("second"); }
3688                 | StringConst                   { $$ = $1; }
3689                 ;
3690
3691 overlay_list:
3692                 a_expr overlay_placing substr_from substr_for
3693                         { $$ = cat_str(4, $1, 42, $3, $4); }
3694                 | a_expr overlay_placing substr_from
3695                         { $$ = cat_str(3, $1, $2, $3); }
3696                 ;
3697
3698 overlay_placing:
3699                         PLACING a_expr          { $$ = cat2_str(make_str("placing"), $2); }
3700                         ;
3701
3702 /* position_list uses b_expr not a_expr to avoid conflict with general IN */
3703 position_list:  b_expr IN_P b_expr
3704                         { $$ = cat_str(3, $1, make_str("in"), $3); }
3705                 | /* EMPTY */
3706                         { $$ = EMPTY; }
3707                 ;
3708
3709 substr_list:  a_expr substr_from substr_for
3710                         { $$ = cat_str(3, $1, $2, $3); }
3711                 | a_expr substr_for substr_from
3712                         { $$ = cat_str(3, $1, $2, $3); }
3713                 | a_expr substr_from
3714                         { $$ = cat2_str($1, $2); }
3715                 | a_expr substr_for
3716                         { $$ = cat2_str($1, $2); }
3717                 | expr_list
3718                         { $$ = $1; }
3719                 | /* EMPTY */
3720                         { $$ = EMPTY; }
3721                 ;
3722
3723 substr_from:  FROM a_expr
3724                         { $$ = cat2_str(make_str("from"), $2); }
3725                 ;
3726
3727 substr_for:  FOR a_expr
3728                         { $$ = cat2_str(make_str("for"), $2); }
3729                 ;
3730
3731 trim_list:      a_expr FROM expr_list
3732                         { $$ = cat_str(3, $1, make_str("from"), $3); }
3733                 | FROM expr_list
3734                         { $$ = cat2_str(make_str("from"), $2); }
3735                 | expr_list
3736                         { $$ = $1; }
3737                 ;
3738
3739 in_expr:  select_with_parens
3740                         { $$ = $1; }
3741                 | '(' expr_list ')'
3742                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3743                 ;
3744
3745 /* Case clause
3746  * Define SQL92-style case clause.
3747  * Allow all four forms described in the standard:
3748  * - Full specification
3749  *      CASE WHEN a = b THEN c ... ELSE d END
3750  * - Implicit argument
3751  *      CASE a WHEN b THEN c ... ELSE d END
3752  * - Conditional NULL
3753  *      NULLIF(x,y)
3754  *      same as CASE WHEN x = y THEN NULL ELSE x END
3755  * - Conditional substitution from list, use first non-null argument
3756  *      COALESCE(a,b,...)
3757  * same as CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ... END
3758  * - thomas 1998-11-09
3759  */
3760 case_expr:      CASE case_arg when_clause_list case_default END_P
3761                         { $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); }
3762                 | NULLIF '(' a_expr ',' a_expr ')'
3763                         { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); }
3764                 | COALESCE '(' expr_list ')'
3765                         { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); }
3766                 ;
3767
3768 when_clause_list:  when_clause_list when_clause
3769                         { $$ = cat2_str($1, $2); }
3770                 | when_clause
3771                         { $$ = $1; }
3772                 ;
3773
3774 when_clause:  WHEN a_expr THEN a_expr
3775                         { $$ = cat_str(4, make_str("when"), $2, make_str("then"), $4); }
3776                 ;
3777
3778 case_default:  ELSE a_expr
3779                         { $$ = cat2_str(make_str("else"), $2); }
3780                 | /*EMPTY*/
3781                         { $$ = EMPTY; }
3782                 ;
3783
3784 case_arg:  a_expr                       { $$ = $1; }
3785                 | /*EMPTY*/                     { $$ = EMPTY; }
3786                 ;
3787
3788 columnref: relation_name opt_indirection
3789                 { $$ = cat2_str($1, $2); }
3790         | dotted_name opt_indirection
3791                 { $$ = cat2_str($1, $2); }
3792         ;
3793
3794 dotted_name: relation_name attrs
3795                         { $$ = cat2_str($1, $2); }
3796                 ;
3797
3798 attrs: '.' attr_name
3799                         { $$ = cat2_str(make_str("."), $2); }
3800                 | '.' '*'
3801                         { $$ = make_str(".*"); }
3802                 | '.' attr_name attrs
3803                         { $$ = cat_str(3, make_str("."), $2, $3); }
3804                 ;
3805
3806 opt_empty_parentheses: '(' ')'  { $$ = make_str("()"); }
3807                 | /*EMPTY*/                             { $$ = EMPTY; }
3808                 ;
3809
3810
3811 /*****************************************************************************
3812  *
3813  *      target lists
3814  *
3815  *****************************************************************************/
3816
3817 /* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
3818 target_list:  target_list ',' target_el
3819                         { $$ = cat_str(3, $1, make_str(","), $3);  }
3820                 | target_el
3821                         { $$ = $1;      }
3822                 ;
3823
3824 /* AS is not optional because shift/red conflict with unary ops */
3825 target_el:      a_expr AS ColLabel
3826                         { $$ = cat_str(3, $1, make_str("as"), $3); }
3827                 | a_expr
3828                         { $$ = $1; }
3829                 | '*'
3830                         { $$ = make_str("*"); }
3831                 ;
3832
3833 /* Target list as found in UPDATE table SET ... */
3834 update_target_list:  update_target_list ',' update_target_el
3835                         { $$ = cat_str(3, $1, make_str(","),$3);        }
3836                 | '(' inf_col_list ')' '=' '(' inf_val_list ')'
3837                         {
3838                                 struct inf_compat_col *ptrc;
3839                                 struct inf_compat_val *ptrv;
3840                                 char *cols = make_str( "(" );
3841                                 char *vals = make_str( "(" );
3842                                 
3843                                 for (ptrc = informix_col, ptrv = informix_val; ptrc != NULL && ptrv != NULL; ptrc = ptrc->next, ptrv = ptrv->next)
3844                                 {
3845                                         if ( ptrc->next != NULL )
3846                                         {
3847                                                 cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(",") );
3848                                         }
3849                                         else
3850                                         {
3851                                                 cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(")") );
3852                                         }
3853                                         if (ptrv->next != NULL )
3854                                                 vals = cat_str(3, vals, ptrv->val, make_str("," ) );
3855                                         else
3856                                                 vals = cat_str( 3, vals, ptrv->val, make_str(")") );
3857                                 }
3858                                 $$ = cat_str( 3, cols, make_str("="), vals );
3859                         }
3860                 | update_target_el
3861                         { $$ = $1;      }
3862                 ;
3863
3864 inf_col_list: ColId opt_indirection
3865                 {
3866                         struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col));
3867                         
3868                         ptr->name = $1;
3869                         ptr->indirection = $2;
3870                         ptr->next = NULL;
3871                         informix_col = ptr;
3872                 }
3873                 | ColId opt_indirection ',' inf_col_list
3874                 {
3875                         struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col));
3876                 
3877                         ptr->name = $1;
3878                         ptr->indirection = $2;
3879                         ptr->next = informix_col;
3880                         informix_col = ptr;
3881                 }
3882                 ;
3883                 
3884 inf_val_list: a_expr
3885                 {
3886                         struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val));
3887                         
3888                         ptr->val = $1;
3889                         ptr->next = NULL;
3890                         informix_val = ptr;
3891                 }
3892                 | a_expr ',' inf_val_list
3893                 {
3894                         struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val));
3895                 
3896                         ptr->val = $1;
3897                         ptr->next = informix_val;
3898                         informix_val = ptr;
3899                 }
3900                 ;
3901
3902 update_target_el:  ColId opt_indirection '=' a_expr
3903                         { $$ = cat_str(4, $1, $2, make_str("="), $4); }
3904                 | ColId opt_indirection '=' DEFAULT
3905                         { $$ = cat_str(3, $1, $2, make_str("= default")); }
3906                 ;
3907
3908 insert_target_list:  insert_target_list ',' insert_target_el
3909                                 {       $$ = cat_str(3, $1, make_str(","), $3);  }
3910                 | insert_target_el
3911                                 {       $$ = $1;  }
3912                 ;
3913
3914 insert_target_el:  target_el    {       $$ = $1;  }
3915                 | DEFAULT       {       $$ = make_str("default"); }
3916                 ;
3917
3918
3919 /*****************************************************************************
3920  *
3921  *         Names and constants
3922  *
3923  *****************************************************************************/
3924
3925 relation_name:  SpecialRuleRelation     { $$ = $1; }
3926                 | ColId                 { $$ = $1; }
3927                 ;
3928
3929 qualified_name_list:  qualified_name
3930                                 { $$ = $1; }
3931                 | qualified_name_list ',' qualified_name
3932                                 { $$ = cat_str(3, $1, make_str(","), $3); }
3933                 ;
3934
3935 qualified_name: relation_name
3936                 { $$ = $1; }
3937                 | dotted_name
3938                 { $$ = $1; }
3939                 ;
3940
3941 name_list:  name
3942                         { $$ = $1; }
3943                 | name_list ',' name
3944                         { $$ = cat_str(3, $1, make_str(","), $3); }
3945                 ;
3946
3947
3948 name:                           ColId                   { $$ = $1; };
3949 database_name:                  ColId                   { $$ = $1; };
3950 access_method:                  ColId                   { $$ = $1; };
3951 attr_name:                              ColId                   { $$ = $1; };
3952 index_name:                             ColId                   { $$ = $1; };
3953
3954 file_name:                              StringConst             { $$ = $1; };
3955
3956 /* func_name will soon return a List ... but not yet */
3957 /*
3958 func_name: function_name
3959                         { $$ = makeList1(makeString($1)); }
3960                 | dotted_name
3961                         { $$ = $1; }
3962                 ;
3963 */
3964 func_name: function_name
3965                         { $$ = $1; }
3966                 | dotted_name
3967                         { $$ = $1; }
3968                 ;
3969
3970
3971 /* Constants
3972  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3973  */
3974 AexprConst:  PosAllConst
3975                         { $$ = $1; }
3976                 | ConstTypename StringConst
3977                         { $$ = cat2_str($1, $2); }
3978                 | ConstInterval StringConst opt_interval
3979                         { $$ = cat_str(3, $1, $2, $3); }
3980                 | ConstInterval  '(' PosIntConst ')' StringConst opt_interval
3981                         { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
3982                 | PARAM opt_indirection
3983                         { $$ = cat2_str(make_str("param"), $2); }
3984                 | TRUE_P
3985                         { $$ = make_str("true"); }
3986                 | FALSE_P
3987                         { $$ = make_str("false"); }
3988                 | NULL_P
3989                         { $$ = make_str("null"); }
3990                 | civarind
3991                         { $$ = $1; }
3992                 ;
3993
3994 Iconst:  ICONST                         { $$ = make_name();};
3995 Fconst:  FCONST                         { $$ = make_name();};
3996 Bconst:  BCONST                         { $$ = make_name();};
3997 Xconst:  XCONST                         { $$ = make_name();};
3998 Sconst:  SCONST
3999                 {
4000                         $$ = (char *)mm_alloc(strlen($1) + 3);
4001                         $$[0]='\'';
4002                                         strcpy($$+1, $1);
4003                         $$[strlen($1)+2]='\0';
4004                         $$[strlen($1)+1]='\'';
4005                         free($1);
4006                 }
4007                 ;
4008
4009 PosIntConst:    Iconst          { $$ = $1; }
4010                 | civar         { $$ = $1; }
4011                 ;
4012
4013 IntConst:       PosIntConst             { $$ = $1; }
4014                 | '-' PosIntConst       { $$ = cat2_str(make_str("-"), $2); }
4015                 ;
4016
4017 StringConst:    Sconst          { $$ = $1; }
4018                 | civar         { $$ = $1; }
4019                 ;
4020
4021 PosIntStringConst:      Iconst  { $$ = $1; }
4022                 | Sconst        { $$ = $1; } 
4023                 | civar         { $$ = $1; }
4024                 ;
4025
4026 NumConst:       Fconst                  { $$ = $1; }
4027                 | Iconst                { $$ = $1; }
4028                 | '-' Fconst            { $$ = cat2_str(make_str("-"), $2); }
4029                 | '-' Iconst            { $$ = cat2_str(make_str("-"), $2); } 
4030                 | civar                 { $$ = $1; }
4031                 ;
4032
4033 AllConst:       Sconst                  { $$ = $1; }
4034                 | NumConst              { $$ = $1; }
4035                 ;
4036
4037 PosAllConst:    Sconst          { $$ = $1; }
4038                 | Fconst        { $$ = $1; }
4039                 | Iconst        { $$ = $1; }
4040                 | Bconst        { $$ = $1; }
4041                 | Xconst        { $$ = $1; }
4042                 | civar         { $$ = $1; }
4043                 ;
4044
4045 UserId:  ColId                          { $$ = $1;};
4046
4047 SpecialRuleRelation:  OLD
4048                 {
4049                         if (!QueryIsRule)
4050                                 mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query");
4051
4052                         $$ = make_str("old");
4053                 }
4054                 | NEW
4055                 {
4056                         if (!QueryIsRule)
4057                                 mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query");
4058
4059                         $$ = make_str("new");
4060                 }
4061                 ;
4062
4063 /*
4064  * and now special embedded SQL stuff
4065  */
4066
4067 /*
4068  * the exec sql connect statement: connect to the given database
4069  */
4070 ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
4071                         { $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); }
4072                 | SQL_CONNECT TO DEFAULT
4073                         { $$ = make_str("NULL,NULL,NULL,\"DEFAULT\""); }
4074                   /* also allow ORACLE syntax */
4075                 | SQL_CONNECT ora_user
4076                         { $$ = cat_str(3, make_str("NULL,"), $2, make_str(",NULL")); }
4077                 | DATABASE connection_target
4078                         { $$ = cat2_str($2, make_str(",NULL,NULL,NULL")); }
4079                 ;
4080
4081 connection_target: database_name opt_server opt_port
4082                 {
4083                         /* old style: dbname[@server][:port] */
4084                         if (strlen($2) > 0 && *($2) != '@')
4085                         {
4086                                 snprintf(errortext, sizeof(errortext),
4087                                                  "Expected '@', found '%s'", $2);
4088                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4089                         }
4090
4091                         $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
4092                 }
4093                 |  db_prefix ':' server opt_port '/' database_name opt_options
4094                 {
4095                         /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
4096                         if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
4097                         {
4098                                 snprintf(errortext, sizeof(errortext), "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported");
4099                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4100                         }
4101
4102                         if (strncmp($3, "//", strlen("//")) != 0)
4103                         {
4104                                 snprintf(errortext, sizeof(errortext), "Expected '://', found '%s'", $3);
4105                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4106                         }
4107
4108                         if (strncmp($1, "unix", strlen("unix")) == 0 &&
4109                                 strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
4110                                 strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
4111                         {
4112                                 snprintf(errortext, sizeof(errortext), "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//"));
4113                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4114                         }
4115
4116                         $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),    $7, make_str("\"")));
4117                 }
4118                 | StringConst
4119                 {
4120                         if ($1[0] == '\"')
4121                                 $$ = $1;
4122                         else if (strcmp($1, " ?") == 0) /* variable */
4123                         {
4124                                 enum ECPGttype type = argsinsert->variable->type->type;
4125
4126                                 /* if array see what's inside */
4127                                 if (type == ECPGt_array)
4128                                         type = argsinsert->variable->type->u.element->type;
4129
4130                                 /* handle varchars */
4131                                 if (type == ECPGt_varchar)
4132                                         $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
4133                                 else
4134                                         $$ = mm_strdup(argsinsert->variable->name);
4135                         }
4136                         else
4137                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
4138                 }
4139                 ;
4140
4141 db_prefix: ident CVARIABLE
4142                 {
4143                         if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
4144                         {
4145                                 snprintf(errortext, sizeof(errortext), "Expected 'postgresql', found '%s'", $2);
4146                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4147                         }
4148
4149                         if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
4150                         {
4151                                 snprintf(errortext, sizeof(errortext), "Illegal connection type %s", $1);
4152                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4153                         }
4154
4155                         $$ = make3_str($1, make_str(":"), $2);
4156                 }
4157                 ;
4158
4159 server: Op server_name
4160                 {
4161                         if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
4162                         {
4163                                 snprintf(errortext, sizeof(errortext), "Expected '@' or '://', found '%s'", $1);
4164                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4165                         }
4166
4167                         $$ = make2_str($1, $2);
4168                 }
4169                 ;
4170
4171 opt_server: server                      { $$ = $1; }
4172                 | /*EMPTY*/                     { $$ = EMPTY; }
4173                 ;
4174
4175 server_name: ColId                                      { $$ = $1; }
4176                 | ColId '.' server_name         { $$ = make3_str($1, make_str("."), $3); }
4177                 | IP                                            { $$ = make_name(); }
4178                 ;
4179
4180 opt_port: ':' PosIntConst       { $$ = make2_str(make_str(":"), $2); }
4181                 | /*EMPTY*/                     { $$ = EMPTY; }
4182                 ;
4183
4184 opt_connection_name: AS connection_target { $$ = $2; }
4185                 | /*EMPTY*/                     { $$ = make_str("NULL"); }
4186                 ;
4187
4188 opt_user: USER ora_user         { $$ = $2; }
4189                 | /*EMPTY*/                     { $$ = make_str("NULL,NULL"); }
4190                 ;
4191
4192 ora_user: user_name
4193                         { $$ = cat2_str($1, make_str(", NULL")); }
4194                 | user_name '/' user_name
4195                         { $$ = cat_str(3, $1, make_str(","), $3); }
4196                 | user_name SQL_IDENTIFIED BY user_name
4197                         { $$ = cat_str(3, $1, make_str(","), $4); }
4198                 | user_name USING user_name
4199                         { $$ = cat_str(3, $1, make_str(","), $3); }
4200                 ;
4201
4202 user_name: UserId
4203                 {
4204                         if ($1[0] == '\"')
4205                                 $$ = $1;
4206                         else
4207                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
4208                 }
4209                 | StringConst
4210                 {
4211                         if ($1[0] == '\"')
4212                                 $$ = $1;
4213                         else if (strcmp($1, "?") == 0) /* variable */
4214                         {
4215                                 enum ECPGttype type = argsinsert->variable->type->type;
4216
4217                                 /* if array see what's inside */
4218                                 if (type == ECPGt_array)
4219                                         type = argsinsert->variable->type->u.element->type;
4220
4221                                 /* handle varchars */
4222                                 if (type == ECPGt_varchar)
4223                                         $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
4224                                 else
4225                                         $$ = mm_strdup(argsinsert->variable->name);
4226                         }
4227                         else
4228                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
4229                 }
4230                 ;
4231
4232 char_variable: CVARIABLE
4233                 {
4234                         /* check if we have a char variable */
4235                         struct variable *p = find_variable($1);
4236                         enum ECPGttype type = p->type->type;
4237
4238                         /* if array see what's inside */
4239                         if (type == ECPGt_array)
4240                                 type = p->type->u.element->type;
4241
4242                         switch (type)
4243                         {
4244                                 case ECPGt_char:
4245                                 case ECPGt_unsigned_char:
4246                                         $$ = $1;
4247                                         break;
4248                                 case ECPGt_varchar:
4249                                         $$ = make2_str($1, make_str(".arr"));
4250                                         break;
4251                                 default:
4252                                         mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
4253                                         break;
4254                         }
4255                 }
4256                 ;
4257
4258 opt_options: Op ColId
4259                 {
4260                         if (strlen($1) == 0)
4261                                 mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
4262
4263                         if (strcmp($1, "?") != 0)
4264                         {
4265                                 snprintf(errortext, sizeof(errortext), "unrecognised token '%s'", $1);
4266                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4267                         }
4268
4269                         $$ = make2_str(make_str("?"), $2);
4270                 }
4271                 | /*EMPTY*/     { $$ = EMPTY; }
4272                 ;
4273
4274 /*
4275  * Declare a prepared cursor. The syntax is different from the standard
4276  * declare statement, so we create a new rule.
4277  */
4278 ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR ident
4279                 {
4280                         struct cursor *ptr, *this;
4281                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
4282
4283                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
4284                         {
4285                                 if (strcmp($2, ptr->name) == 0)
4286                                 {
4287                                                 /* re-definition is a bug */
4288                                         snprintf(errortext, sizeof(errortext), "cursor %s already defined", $2);
4289                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
4290                                 }
4291                         }
4292
4293                         this = (struct cursor *) mm_alloc(sizeof(struct cursor));
4294
4295                         /* initial definition */
4296                         this->next = cur;
4297                         this->name = $2;
4298                         this->connection = connection;
4299                         this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for ?"));
4300                         this->argsresult = NULL;
4301
4302                         thisquery->type = &ecpg_query;
4303                         thisquery->brace_level = 0;
4304                         thisquery->next = NULL;
4305                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($7));
4306                         sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $7);
4307
4308                         this->argsinsert = NULL;
4309                         add_variable(&(this->argsinsert), thisquery, &no_indicator);
4310
4311                         cur = this;
4312
4313                         $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
4314                 }
4315                 ;
4316
4317 /*
4318  * the exec sql deallocate prepare command to deallocate a previously
4319  * prepared statement
4320  */
4321 ECPGDeallocate: DEALLOCATE PREPARE ident
4322                         { $$ = $3; }
4323                 | DEALLOCATE ident
4324                         { $$ = $2; }
4325                 ;
4326
4327 /* 
4328  * variable decalartion outside exec sql declare block
4329  */
4330 ECPGVarDeclaration: single_vt_declaration;
4331
4332 single_vt_declaration: type_declaration         { $$ = $1; }
4333                 | single_var_declaration        { $$ = $1; }
4334                 ;
4335         
4336 single_var_declaration: storage_declaration 
4337                 single_vt_type
4338                 {
4339                         actual_type[struct_level].type_enum = $2.type_enum;
4340                         actual_type[struct_level].type_dimension = $2.type_dimension;
4341                         actual_type[struct_level].type_index = $2.type_index;
4342                         actual_type[struct_level].type_sizeof = $2.type_sizeof;
4343                 }
4344                 variable_list ';'
4345                 {
4346                         $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
4347                 }
4348                 | single_vt_type
4349                 {
4350                         actual_type[struct_level].type_enum = $1.type_enum;
4351                         actual_type[struct_level].type_dimension = $1.type_dimension;
4352                         actual_type[struct_level].type_index = $1.type_index;
4353                         actual_type[struct_level].type_sizeof = $1.type_sizeof;
4354                         actual_storage[struct_level] = EMPTY;
4355
4356                         actual_startline[struct_level] = hashline_number();
4357                 }
4358                 variable_list ';'
4359                 {
4360                         $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
4361                 }
4362                 | struct_union_type_with_symbol ';'
4363                 {
4364                         /* this is essantially a typedef but needs the keyword struct/union as well */
4365                         struct typedefs *ptr, *this;
4366                         
4367                         for (ptr = types; ptr != NULL; ptr = ptr->next)
4368                         {
4369                                 if (strcmp($1.type_str, ptr->name) == 0)
4370                                 {
4371                                         /* re-definition is a bug */
4372                                         snprintf(errortext, sizeof(errortext), "Type %s already defined", $1.type_str);
4373                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
4374                                 }
4375                         }
4376
4377                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
4378
4379                         /* initial definition */
4380                         this->next = types;
4381                         this->name = $1.type_str;
4382                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
4383                         this->type->type_enum = $1.type_enum;
4384                         this->type->type_str = mm_strdup($1.type_str);
4385                         this->type->type_dimension = make_str("-1"); /* dimension of array */
4386                         this->type->type_index = make_str("-1");    /* length of string */
4387                         this->type->type_sizeof = ECPGstruct_sizeof;
4388                         this->struct_member_list = struct_member_list[struct_level];
4389
4390                         types = this;
4391                         $$ = cat2_str($1.type_sizeof, make_str(";"));
4392                 }
4393                 ;
4394
4395 precision:      NumConst        { $$ = $1; };
4396
4397 opt_scale:      ',' NumConst    { $$ = $2; }
4398                 | /* EMPTY */   { $$ = EMPTY; }
4399                 ;
4400
4401 ecpg_interval:  opt_interval    { $$ = $1; }
4402                 | YEAR_P TO MINUTE_P    { $$ = make_str("year to minute"); }
4403                 | YEAR_P TO SECOND_P    { $$ = make_str("year to second"); }
4404                 | DAY_P TO DAY_P        { $$ = make_str("day to day"); }
4405                 | MONTH_P TO MONTH_P    { $$ = make_str("month to month"); }
4406                 ;
4407
4408 single_vt_type: common_type
4409                 | DOUBLE_P
4410                 {
4411                         $$.type_enum = ECPGt_double;
4412                         $$.type_str = make_str("double");
4413                         $$.type_dimension = make_str("-1");
4414                         $$.type_index = make_str("-1");
4415                         $$.type_sizeof = NULL;
4416                 }
4417                 | ECPGColLabelCommon ecpg_interval
4418                 {
4419                         if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
4420                                 mmerror (PARSE_ERROR, ET_ERROR, "Interval specification not allowed here ");
4421                         
4422                         /*
4423                          * Check for type names that the SQL grammar treats as
4424                          * unreserved keywords
4425                          */
4426                         if (strcmp($1, "varchar") == 0)
4427                         {
4428                                 $$.type_enum = ECPGt_varchar;
4429                                 $$.type_str = EMPTY;
4430                                 $$.type_dimension = make_str("-1");
4431                                 $$.type_index = make_str("-1");
4432                                 $$.type_sizeof = NULL;
4433                         }
4434                         else if (strcmp($1, "float") == 0)
4435                         {
4436                                 $$.type_enum = ECPGt_float;
4437                                 $$.type_str = make_str("float");
4438                                 $$.type_dimension = make_str("-1");
4439                                 $$.type_index = make_str("-1");
4440                                 $$.type_sizeof = NULL;
4441                         }
4442                         else if (strcmp($1, "numeric") == 0)
4443                         {
4444                                 $$.type_enum = ECPGt_numeric;
4445                                 $$.type_str = make_str("Numeric");
4446                                 $$.type_dimension = make_str("-1");
4447                                 $$.type_index = make_str("-1");
4448                                 $$.type_sizeof = NULL;
4449                         }
4450                         else if (strcmp($1, "decimal") == 0)
4451                         {
4452                                 $$.type_enum = ECPGt_numeric;
4453                                 $$.type_str = make_str("Numeric");
4454                                 $$.type_dimension = make_str("-1");
4455                                 $$.type_index = make_str("-1");
4456                                 $$.type_sizeof = NULL;
4457                         }
4458                         else if (strcmp($1, "date") == 0)
4459                         {
4460                                 $$.type_enum = ECPGt_date;
4461                                 $$.type_str = make_str("Date");
4462                                 $$.type_dimension = make_str("-1");
4463                                 $$.type_index = make_str("-1");
4464                                 $$.type_sizeof = NULL;
4465                         }
4466                         else if (strcmp($1, "timestamp") == 0)
4467                         {
4468                                 $$.type_enum = ECPGt_timestamp;
4469                                 $$.type_str = make_str("Timestamp");
4470                                 $$.type_dimension = make_str("-1");
4471                                 $$.type_index = make_str("-1");
4472                                 $$.type_sizeof = NULL;
4473                         }
4474                         else if (strcmp($1, "datetime") == 0)
4475                         {
4476                                 $$.type_enum = ECPGt_timestamp;
4477                                 $$.type_str = make_str("Timestamp");
4478                                 $$.type_dimension = make_str("-1");
4479                                 $$.type_index = make_str("-1");
4480                                 $$.type_sizeof = NULL;
4481                         }
4482                         else if (strcmp($1, "interval") == 0)
4483                         {
4484                                 $$.type_enum = ECPGt_interval;
4485                                 $$.type_str = make_str("Interval");
4486                                 $$.type_dimension = make_str("-1");
4487                                 $$.type_index = make_str("-1");
4488                                 $$.type_sizeof = NULL;
4489                         }
4490                         else
4491                         {
4492                                 /* this is for typedef'ed types */
4493                                 struct typedefs *this = get_typedef($1);
4494
4495                                 $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
4496                                 $$.type_enum = this->type->type_enum;
4497                                 $$.type_dimension = this->type->type_dimension;
4498                                 $$.type_index = this->type->type_index;
4499                                 $$.type_sizeof = this->type->type_sizeof;
4500                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
4501                         }
4502                 }
4503                 | s_struct_union_symbol
4504                 {
4505                         /* this is for named structs/unions */
4506                         char *name;
4507                         struct typedefs *this;
4508                         bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
4509
4510                         name = cat2_str($1.su, $1.symbol);
4511                         /* Do we have a forward definition? */
4512                         if (!forward)
4513                         {
4514                                 /* No */
4515                                 
4516                                 this = get_typedef(name);
4517                                 $$.type_str = mm_strdup(this->name);
4518                                 $$.type_enum = this->type->type_enum;
4519                                 $$.type_dimension = this->type->type_dimension;
4520                                 $$.type_index = this->type->type_index;
4521                                 $$.type_sizeof = this->type->type_sizeof;
4522                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
4523                                 free(name);
4524                         }
4525                         else
4526                         {
4527                                 $$.type_str = name;
4528                                 $$.type_enum = ECPGt_long;
4529                                 $$.type_dimension = make_str("-1");
4530                                 $$.type_index = make_str("-1");
4531                                 $$.type_sizeof = make_str("");
4532                                 struct_member_list[struct_level] = NULL;
4533                         }
4534                 }
4535                 ;
4536
4537 /*
4538  * variable declaration inside exec sql declare block
4539  */
4540 ECPGDeclaration: sql_startdeclare
4541                 { fputs("/* exec sql begin declare section */", yyout); }
4542                 var_type_declarations sql_enddeclare
4543                 {
4544                         fprintf(yyout, "%s/* exec sql end declare section */", $3);
4545                         free($3);
4546                         output_line_number();
4547                 }
4548                 ;
4549
4550 sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
4551
4552 sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
4553
4554 var_type_declarations:  /*EMPTY*/                       { $$ = EMPTY; }
4555                 | vt_declarations                       { $$ = $1; }
4556                 ;
4557
4558 vt_declarations:  var_declaration                       { $$ = $1; }
4559                 | type_declaration                      { $$ = $1; }
4560                 | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
4561                 | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
4562                 ;
4563
4564 variable_declarations:  var_declaration                         { $$ = $1; }
4565                 | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
4566                 ;
4567
4568 type_declaration: S_TYPEDEF
4569         {
4570                 /* reset this variable so we see if there was */
4571                 /* an initializer specified */
4572                 initializer = 0;
4573         }
4574         var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
4575         {
4576                 /* add entry to list */
4577                 struct typedefs *ptr, *this;
4578                 char * dimension = $6.index1;
4579                 char * length = $6.index2;
4580
4581                 if (($3.type_enum == ECPGt_struct ||
4582                      $3.type_enum == ECPGt_union) &&
4583                     initializer == 1)
4584                 {
4585                         mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command");
4586
4587                 }
4588                 else
4589                 {
4590                         for (ptr = types; ptr != NULL; ptr = ptr->next)
4591                         {
4592                                 if (strcmp($5, ptr->name) == 0)
4593                                 {
4594                                         /* re-definition is a bug */
4595                                         snprintf(errortext, sizeof(errortext), "Type %s already defined", $5);
4596                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
4597                                 }
4598                         }
4599
4600                         adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0);
4601
4602                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
4603
4604                         /* initial definition */
4605                         this->next = types;
4606                         this->name = $5;
4607                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
4608                         this->type->type_enum = $3.type_enum;
4609                         this->type->type_str = mm_strdup($5);
4610                         this->type->type_dimension = dimension; /* dimension of array */
4611                         this->type->type_index = length;    /* length of string */
4612                         this->type->type_sizeof = ECPGstruct_sizeof;
4613                         this->struct_member_list = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ?
4614                                 struct_member_list[struct_level] : NULL;
4615
4616                         if ($3.type_enum != ECPGt_varchar &&
4617                             $3.type_enum != ECPGt_char &&
4618                             $3.type_enum != ECPGt_unsigned_char &&
4619                             atoi(this->type->type_index) >= 0)
4620                                 mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
4621
4622                         types = this;
4623                 }
4624
4625                 fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4?"*":"", $5, $6.str);
4626                 output_line_number();
4627                 $$ = make_str("");
4628         };
4629
4630 var_declaration: storage_declaration
4631                 var_type
4632                 {
4633                         actual_type[struct_level].type_enum = $2.type_enum;
4634                         actual_type[struct_level].type_dimension = $2.type_dimension;
4635                         actual_type[struct_level].type_index = $2.type_index;
4636                         actual_type[struct_level].type_sizeof = $2.type_sizeof;
4637                 }
4638                 variable_list ';'
4639                 {
4640                         $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
4641                 }
4642                 | var_type
4643                 {
4644                         actual_type[struct_level].type_enum = $1.type_enum;
4645                         actual_type[struct_level].type_dimension = $1.type_dimension;
4646                         actual_type[struct_level].type_index = $1.type_index;
4647                         actual_type[struct_level].type_sizeof = $1.type_sizeof;
4648                         actual_storage[struct_level] = EMPTY;
4649                         
4650                         actual_startline[struct_level] = hashline_number();
4651                 }
4652                 variable_list ';'
4653                 {
4654                         $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
4655                 }
4656                 | struct_union_type_with_symbol ';'
4657                 {
4658                         /* this is essantially a typedef but needs the keyword struct/union as well */
4659                         struct typedefs *ptr, *this;
4660                         
4661                         for (ptr = types; ptr != NULL; ptr = ptr->next)
4662                         {
4663                                 if (strcmp($1.type_str, ptr->name) == 0)
4664                                 {
4665                                         /* re-definition is a bug */
4666                                         snprintf(errortext, sizeof(errortext), "Type %s already defined", $1.type_str);
4667                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
4668                                 }
4669                         }
4670
4671                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
4672
4673                         /* initial definition */
4674                         this->next = types;
4675                         this->name = $1.type_str;
4676                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
4677                         this->type->type_enum = $1.type_enum;
4678                         this->type->type_str = mm_strdup($1.type_str);
4679                         this->type->type_dimension = make_str("-1"); /* dimension of array */
4680                         this->type->type_index = make_str("-1");    /* length of string */
4681                         this->type->type_sizeof = ECPGstruct_sizeof;
4682                         this->struct_member_list = struct_member_list[struct_level];
4683
4684                         types = this;
4685                         $$ = cat2_str($1.type_sizeof, make_str(";"));
4686                 }
4687                 ;
4688
4689 storage_declaration: storage_clause storage_modifier
4690                 {
4691                         actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
4692                         actual_startline[struct_level] = hashline_number();
4693                 }
4694                 | storage_clause
4695                 {
4696                         actual_storage[struct_level] = mm_strdup($1);
4697                         actual_startline[struct_level] = hashline_number();
4698                 }
4699                 | storage_modifier
4700                 {
4701                         actual_storage[struct_level] = mm_strdup($1);
4702                         actual_startline[struct_level] = hashline_number();
4703                 }
4704                 ;
4705
4706 storage_clause : S_EXTERN               { $$ = make_str("extern"); }
4707                 | S_STATIC              { $$ = make_str("static"); }
4708                 | S_REGISTER            { $$ = make_str("register"); }
4709                 | S_AUTO                { $$ = make_str("auto"); }
4710                 ;
4711
4712 storage_modifier : S_CONST              { $$ = make_str("const"); }
4713                 | S_VOLATILE            { $$ = make_str("volatile"); }
4714                 ;
4715
4716 common_type: simple_type
4717                 {
4718                         $$.type_enum = $1;
4719                         $$.type_str = mm_strdup(ECPGtype_name($1));
4720                         $$.type_dimension = make_str("-1");
4721                         $$.type_index = make_str("-1");
4722                         $$.type_sizeof = NULL;
4723                 }
4724                 | struct_union_type
4725                 {
4726                         $$.type_str = $1;
4727                         $$.type_dimension = make_str("-1");
4728                         $$.type_index = make_str("-1");
4729
4730                         if (strncmp($1, "struct", sizeof("struct")-1) == 0)
4731                         {
4732                                 $$.type_enum = ECPGt_struct;
4733                                 $$.type_sizeof = ECPGstruct_sizeof;
4734                         }
4735                         else
4736                         {
4737                                 $$.type_enum = ECPGt_union;
4738                                 $$.type_sizeof = NULL;
4739                         }
4740                 }
4741                 | enum_type
4742                 {
4743                         $$.type_str = $1;
4744                         $$.type_enum = ECPGt_int;
4745                         $$.type_dimension = make_str("-1");
4746                         $$.type_index = make_str("-1");
4747                         $$.type_sizeof = NULL;
4748                 }
4749                 | ECPGColLabelCommon '(' precision opt_scale ')'
4750                 {
4751                         if (strcmp($1, "numeric") != 0 && strcmp($1, "decimal") != 0)
4752                                 mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument");
4753                         
4754                         $$.type_enum = ECPGt_numeric;
4755                         $$.type_str = make_str("Numeric");
4756                         $$.type_dimension = make_str("-1");
4757                         $$.type_index = make_str("-1");
4758                         $$.type_sizeof = NULL;
4759                 }
4760                 ;
4761
4762 var_type:       common_type
4763                 | ECPGColLabel ecpg_interval
4764                 {
4765                         if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
4766                                 mmerror (PARSE_ERROR, ET_ERROR, "Interval specification not allowed here ");
4767                         
4768                         /*
4769                          * Check for type names that the SQL grammar treats as
4770                          * unreserved keywords
4771                          */
4772                         if (strcmp($1, "varchar") == 0)
4773                         {
4774                                 $$.type_enum = ECPGt_varchar;
4775                                 $$.type_str = EMPTY; /*make_str("varchar");*/
4776                                 $$.type_dimension = make_str("-1");
4777                                 $$.type_index = make_str("-1");
4778                                 $$.type_sizeof = NULL;
4779                         }
4780                         else if (strcmp($1, "float") == 0)
4781                         {
4782                                 $$.type_enum = ECPGt_float;
4783                                 $$.type_str = make_str("float");
4784                                 $$.type_dimension = make_str("-1");
4785                                 $$.type_index = make_str("-1");
4786                                 $$.type_sizeof = NULL;
4787                         }
4788                         else if (strcmp($1, "double") == 0)
4789                         {
4790                                 $$.type_enum = ECPGt_double;
4791                                 $$.type_str = make_str("double");
4792                                 $$.type_dimension = make_str("-1");
4793                                 $$.type_index = make_str("-1");
4794                                 $$.type_sizeof = NULL;
4795                         }
4796                         else if (strcmp($1, "numeric") == 0)
4797                         {
4798                                 $$.type_enum = ECPGt_numeric;
4799                                 $$.type_str = make_str("Numeric");
4800                                 $$.type_dimension = make_str("-1");
4801                                 $$.type_index = make_str("-1");
4802                                 $$.type_sizeof = NULL;
4803                         }
4804                         else if (strcmp($1, "decimal") == 0)
4805                         {
4806                                 $$.type_enum = ECPGt_numeric;
4807                                 $$.type_str = make_str("Numeric");
4808                                 $$.type_dimension = make_str("-1");
4809                                 $$.type_index = make_str("-1");
4810                                 $$.type_sizeof = NULL;
4811                         }
4812                         else if (strcmp($1, "date") == 0)
4813                         {
4814                                 $$.type_enum = ECPGt_date;
4815                                 $$.type_str = make_str("Date");
4816                                 $$.type_dimension = make_str("-1");
4817                                 $$.type_index = make_str("-1");
4818                                 $$.type_sizeof = NULL;
4819                         }
4820                         else if (strcmp($1, "timestamp") == 0)
4821                         {
4822                                 $$.type_enum = ECPGt_timestamp;
4823                                 $$.type_str = make_str("Timestamp");
4824                                 $$.type_dimension = make_str("-1");
4825                                 $$.type_index = make_str("-1");
4826                                 $$.type_sizeof = NULL;
4827                         }
4828                         else if (strcmp($1, "interval") == 0)
4829                         {
4830                                 $$.type_enum = ECPGt_interval;
4831                                 $$.type_str = make_str("Interval");
4832                                 $$.type_dimension = make_str("-1");
4833                                 $$.type_index = make_str("-1");
4834                                 $$.type_sizeof = NULL;
4835                         }
4836                         else if (strcmp($1, "datetime") == 0)
4837                         {
4838                                 $$.type_enum = ECPGt_timestamp;
4839                                 $$.type_str = make_str("Timestamp");
4840                                 $$.type_dimension = make_str("-1");
4841                                 $$.type_index = make_str("-1");
4842                                 $$.type_sizeof = NULL;
4843                         }
4844                         else
4845                         {
4846                                 /* this is for typedef'ed types */
4847                                 struct typedefs *this = get_typedef($1);
4848
4849                                 $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
4850                                 $$.type_enum = this->type->type_enum;
4851                                 $$.type_dimension = this->type->type_dimension;
4852                                 $$.type_index = this->type->type_index;
4853                                 $$.type_sizeof = this->type->type_sizeof;
4854                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
4855                         }
4856                 }
4857                 | s_struct_union_symbol
4858                 {
4859                         /* this is for named structs/unions */
4860                         char *name;
4861                         struct typedefs *this;
4862                         bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
4863
4864                         name = cat2_str($1.su, $1.symbol);
4865                         /* Do we have a forward definition? */
4866                         if (!forward)
4867                         {
4868                                 /* No */
4869                                 
4870                                 this = get_typedef(name);
4871                                 $$.type_str = mm_strdup(this->name);
4872                                 $$.type_enum = this->type->type_enum;
4873                                 $$.type_dimension = this->type->type_dimension;
4874                                 $$.type_index = this->type->type_index;
4875                                 $$.type_sizeof = this->type->type_sizeof;
4876                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
4877                                 free(name);
4878                         }
4879                         else
4880                         {
4881                                 $$.type_str = name;
4882                                 $$.type_enum = ECPGt_long;
4883                                 $$.type_dimension = make_str("-1");
4884                                 $$.type_index = make_str("-1");
4885                                 $$.type_sizeof = make_str("");
4886                                 struct_member_list[struct_level] = NULL;
4887                         }
4888                 }
4889                 ;
4890
4891 enum_type: SQL_ENUM symbol enum_definition
4892                         { $$ = cat_str(3, make_str("enum"), $2, $3); }
4893                 | SQL_ENUM enum_definition
4894                         { $$ = cat2_str(make_str("enum"), $2); }
4895                 | SQL_ENUM symbol
4896                         { $$ = cat2_str(make_str("enum"), $2); }
4897                 ;
4898
4899 enum_definition: '{' c_list '}'
4900                         { $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
4901
4902 struct_union_type_with_symbol: s_struct_union_symbol
4903                 {
4904                         struct_member_list[struct_level++] = NULL;
4905                         if (struct_level >= STRUCT_DEPTH)
4906                                  mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
4907                         forward_name = mm_strdup($1.symbol);
4908                 } 
4909                 '{' variable_declarations '}'
4910                 {
4911                         ECPGfree_struct_member(struct_member_list[struct_level]);
4912                         struct_member_list[struct_level] = NULL;
4913                         free(actual_storage[struct_level--]);
4914                         if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
4915                                 $$.type_enum = ECPGt_struct;
4916                         else
4917                                 $$.type_enum = ECPGt_union;
4918                         $$.type_str = cat2_str($1.su, $1.symbol);
4919                         $$.type_sizeof = cat_str(4, mm_strdup($$.type_str), make_str("{"), $4, make_str("}"));
4920                         free(forward_name);
4921                         forward_name = NULL;
4922                 }
4923                 ;
4924
4925 struct_union_type: struct_union_type_with_symbol        { $$ = $1.type_sizeof; }
4926                 | s_struct_union
4927                 {
4928                         struct_member_list[struct_level++] = NULL;
4929                         if (struct_level >= STRUCT_DEPTH)
4930                                  mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
4931                 }
4932                 '{' variable_declarations '}'
4933                 {
4934                         ECPGfree_struct_member(struct_member_list[struct_level]);
4935                         struct_member_list[struct_level] = NULL;
4936                         free(actual_storage[struct_level--]);
4937                         $$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
4938                 }
4939                 ;
4940
4941 s_struct_union_symbol: SQL_STRUCT symbol
4942                 {
4943                         $$.su = make_str("struct");
4944                         $$.symbol = $2;
4945                         ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")")); 
4946                 }
4947                 | UNION symbol
4948                 {
4949                         $$.su = make_str("union");
4950                         $$.symbol = $2;
4951                 }
4952                 ;
4953
4954 s_struct_union: SQL_STRUCT      
4955                 {
4956                         ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */
4957                         $$ = make_str("struct");
4958                 }
4959                 | UNION         { $$ = make_str("union"); }
4960                 ;
4961
4962 simple_type: unsigned_type                                      { $$=$1; }
4963                 |       opt_signed signed_type                  { $$=$2; }
4964                 ;
4965
4966 unsigned_type: SQL_UNSIGNED SQL_SHORT           { $$ = ECPGt_unsigned_short; }
4967                 | SQL_UNSIGNED SQL_SHORT INT_P  { $$ = ECPGt_unsigned_short; }
4968                 | SQL_UNSIGNED                                          { $$ = ECPGt_unsigned_int; }
4969                 | SQL_UNSIGNED INT_P                            { $$ = ECPGt_unsigned_int; }
4970                 | SQL_UNSIGNED SQL_LONG                         { $$ = ECPGt_unsigned_long; }
4971                 | SQL_UNSIGNED SQL_LONG INT_P           { $$ = ECPGt_unsigned_long; }
4972                 | SQL_UNSIGNED SQL_LONG SQL_LONG
4973                 {
4974 #ifdef HAVE_LONG_LONG_INT_64
4975                         $$ = ECPGt_unsigned_long_long;
4976 #else
4977                         $$ = ECPGt_unsigned_long;
4978 #endif
4979                 }
4980                 | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
4981                 {
4982 #ifdef HAVE_LONG_LONG_INT_64
4983                         $$ = ECPGt_unsigned_long_long;
4984 #else
4985                         $$ = ECPGt_unsigned_long;
4986 #endif
4987                 }
4988                 | SQL_UNSIGNED CHAR_P                   { $$ = ECPGt_unsigned_char; }
4989                 ;
4990
4991 signed_type: SQL_SHORT                          { $$ = ECPGt_short; }
4992                 | SQL_SHORT INT_P                       { $$ = ECPGt_short; }
4993                 | INT_P                                 { $$ = ECPGt_int; }
4994                 | SQL_LONG                                      { $$ = ECPGt_long; }
4995                 | SQL_LONG INT_P                        { $$ = ECPGt_long; }
4996                 | SQL_LONG SQL_LONG
4997                 {
4998 #ifdef HAVE_LONG_LONG_INT_64
4999                         $$ = ECPGt_long_long;
5000 #else
5001                         $$ = ECPGt_long;
5002 #endif
5003                 }
5004                 | SQL_LONG SQL_LONG INT_P
5005                 {
5006 #ifdef HAVE_LONG_LONG_INT_64
5007                         $$ = ECPGt_long_long;
5008 #else
5009                         $$ = ECPGt_long;
5010 #endif
5011                 }
5012                 | SQL_BOOL                                      { $$ = ECPGt_bool; }
5013                 | CHAR_P                                        { $$ = ECPGt_char; }
5014                 ;
5015
5016 opt_signed: SQL_SIGNED
5017                 |       /* EMPTY */
5018                 ;
5019
5020 variable_list: variable
5021                         { $$ = $1; }
5022                 | variable_list ',' variable
5023                         { $$ = cat_str(3, $1, make_str(","), $3); }
5024                 ;
5025
5026 variable: opt_pointer ECPGColLabelCommon opt_array_bounds opt_initializer
5027                 {
5028                         struct ECPGtype * type;
5029                         char *dimension = $3.index1; /* dimension of array */
5030                         char *length = $3.index2;    /* length of string */
5031                         char dim[14L];
5032
5033                         adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1));
5034
5035                         switch (actual_type[struct_level].type_enum)
5036                         {
5037                                 case ECPGt_struct:
5038                                 case ECPGt_union:
5039                                         if (atoi(dimension) < 0)
5040                                                 type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
5041                                         else
5042                                                 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);
5043
5044                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
5045                                         break;
5046
5047                                 case ECPGt_varchar:
5048                                         if (atoi(dimension) < 0)
5049                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
5050                                         else
5051                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
5052
5053                                         if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
5054                                                         *dim = '\0';
5055                                         else    
5056                                                         sprintf(dim, "[%s]", dimension);
5057                                         if (strcmp(length, "0") == 0)
5058                                                 mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
5059
5060                                         if (strcmp(dimension, "0") == 0)
5061                                                 $$ = 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);
5062                                         else
5063                                            $$ = 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);
5064                                         break;
5065
5066                                 case ECPGt_char:
5067                                 case ECPGt_unsigned_char:
5068                                         if (atoi(dimension) == -1)
5069                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
5070                                         else
5071                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
5072
5073                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
5074                                         break;
5075
5076                                 default:
5077                                         if (atoi(dimension) < 0)
5078                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"));
5079                                         else
5080                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1")), dimension);
5081
5082                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
5083                                         break;
5084                         }
5085
5086                         if (struct_level == 0)
5087                                 new_variable($2, type, braces_open);
5088                         else
5089                                 ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
5090
5091                         free($2);
5092                 }
5093                 ;
5094
5095 opt_initializer: /*EMPTY*/
5096                         { $$ = EMPTY; }
5097                 | '=' c_term
5098                 {
5099                         initializer = 1;
5100                         $$ = cat2_str(make_str("="), $2);
5101                 }
5102                 ;
5103
5104 opt_pointer: /*EMPTY*/                          { $$ = EMPTY; }
5105                 | '*'                                           { $$ = make_str("*"); }
5106                 | '*' '*'                                       { $$ = make_str("**"); }
5107                 ;
5108
5109 /*
5110  * As long as the prepare statement is not supported by the backend, we will
5111  * try to simulate it here so we get dynamic SQL
5112  */
5113 ECPGDeclare: DECLARE STATEMENT ident
5114                 {
5115                         /* this is only supported for compatibility */
5116                         $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
5117                 }
5118                 ;
5119 /*
5120  * the exec sql disconnect statement: disconnect from the given database
5121  */
5122 ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
5123                 ;
5124
5125 dis_name: connection_object                             { $$ = $1; }
5126                 | SQL_CURRENT                                           { $$ = make_str("\"CURRENT\""); }
5127                 | ALL                                                   { $$ = make_str("\"ALL\""); }
5128                 | /*EMPTY*/                                             { $$ = make_str("\"CURRENT\""); }
5129                 ;
5130
5131 connection_object: connection_target    { $$ = $1; }
5132                 | DEFAULT                                               { $$ = make_str("\"DEFAULT\""); }
5133                 ;
5134
5135 /*
5136  * execute a given string as sql command
5137  */
5138 ECPGExecute : EXECUTE IMMEDIATE execstring
5139                 {
5140                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
5141
5142                         thisquery->type = &ecpg_query;
5143                         thisquery->brace_level = 0;
5144                         thisquery->next = NULL;
5145                         thisquery->name = $3;
5146
5147                         add_variable(&argsinsert, thisquery, &no_indicator);
5148
5149                         $$ = make_str("?");
5150                 }
5151                 | EXECUTE name
5152                 {
5153                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
5154
5155                         thisquery->type = &ecpg_query;
5156                         thisquery->brace_level = 0;
5157                         thisquery->next = NULL;
5158                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($2));
5159                         sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $2);
5160
5161                         add_variable(&argsinsert, thisquery, &no_indicator);
5162                 }
5163                 execute_rest
5164                 {
5165                         $$ = make_str("?");
5166                 }
5167                 ;
5168
5169 execute_rest:   ecpg_using ecpg_into    { $$ = EMPTY; }
5170                 | ecpg_into ecpg_using  { $$ = EMPTY; }
5171                 | ecpg_using            { $$ = EMPTY; }
5172                 | ecpg_into             { $$ = EMPTY; }
5173                 | /* EMPTY */           { $$ = EMPTY; }
5174                 ;
5175
5176 execstring: char_variable
5177                         { $$ = $1; }
5178                 |       CSTRING
5179                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5180                 ;
5181
5182 /*
5183  * the exec sql free command to deallocate a previously
5184  * prepared statement
5185  */
5186 ECPGFree:       SQL_FREE name   { $$ = $2; };
5187
5188 /*
5189  * open is an open cursor, at the moment this has to be removed
5190  */
5191 ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
5192
5193 opt_ecpg_using: /*EMPTY*/               { $$ = EMPTY; }
5194                 | ecpg_using            { $$ = $1; }
5195                 ;
5196
5197 ecpg_using:     USING using_list        { $$ = EMPTY; }
5198                 ;
5199
5200 using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
5201                 {
5202                         add_variable(&argsresult, descriptor_variable($4,0), &no_indicator);
5203                         $$ = EMPTY;
5204                 }
5205                 ;
5206
5207 into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
5208                 {
5209                         add_variable(&argsresult, descriptor_variable($4,0), &no_indicator);
5210                         $$ = EMPTY;
5211                 }
5212                 ;
5213                 
5214 opt_sql: /*EMPTY*/ | SQL_SQL;
5215
5216 ecpg_into_using: ecpg_into              { $$ = EMPTY; }
5217                 | using_descriptor      { $$ = $1; }
5218                 ;
5219
5220 ecpg_into: INTO into_list               { $$ = EMPTY; }
5221                 | into_descriptor       { $$ = $1; }
5222                 ;
5223                 
5224 using_list: UsingConst | UsingConst ',' using_list;
5225
5226 UsingConst: AllConst
5227                 {
5228                         if ($1[1] != '?') /* found a constant */
5229                         {
5230                                 char *length = mm_alloc(sizeof("INT_MAX")+1);
5231
5232                                 sprintf(length, "%d", strlen($1));
5233                                 add_variable(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0), &no_indicator);
5234                         }
5235                 }
5236                 ;
5237
5238 /*
5239  * As long as the prepare statement is not supported by the backend, we will
5240  * try to simulate it here so we get dynamic SQL
5241  *
5242  * It is supported now but not usable yet by ecpg.
5243  */
5244 ECPGPrepare: PREPARE name FROM execstring
5245                         { $$ = cat2_str(make3_str(make_str("\""), $2, make_str("\",")), $4); }
5246                 ;
5247 /* 
5248  * We accept descibe but do nothing with it so far.
5249  */
5250 ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor 
5251         {
5252                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n");
5253                 $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(\"\")") + strlen($3));
5254                 sprintf($$, "1, ECPGprepared_statement(\"%s\")", $3);
5255         }
5256         | SQL_DESCRIBE opt_output name using_descriptor
5257         {
5258                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n");
5259                 $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(\"\")") + strlen($3));
5260                 sprintf($$, "0, ECPGprepared_statement(\"%s\")", $3);
5261         }
5262         | SQL_DESCRIBE opt_output name into_descriptor
5263         {
5264                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n");
5265                 $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(\"\")") + strlen($3));
5266                 sprintf($$, "0, ECPGprepared_statement(\"%s\")", $3);
5267         }
5268         ;
5269
5270 opt_output:     SQL_OUTPUT      { $$ = make_str("output"); }
5271         |       /* EMPTY */     { $$ = EMPTY; }
5272         ;
5273         
5274 /*
5275  * dynamic SQL: descriptor based access
5276  *      written by Christof Petig <christof.petig@wtal.de>
5277  */
5278
5279 /*
5280  * deallocate a descriptor
5281  */
5282 ECPGDeallocateDescr:    DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
5283                 {
5284                         drop_descriptor($3,connection);
5285                         $$ = $3;
5286                 }
5287                 ;
5288
5289 /*
5290  * allocate a descriptor
5291  */
5292 ECPGAllocateDescr:      SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
5293                 {
5294                         add_descriptor($3,connection);
5295                         $$ = $3;
5296                 };
5297
5298 /*
5299  * read from descriptor
5300  */
5301
5302 ECPGGetDescHeaderItem: CVARIABLE '=' desc_header_item
5303                         { push_assignment($1, $3); }
5304                 ;
5305
5306 desc_header_item:       SQL_COUNT                       { $$ = ECPGd_count; }
5307                 ;
5308
5309 ECPGGetDescItem: CVARIABLE '=' descriptor_item  { push_assignment($1, $3); };
5310
5311 descriptor_item:        SQL_CARDINALITY         { $$ = ECPGd_cardinality; }
5312                 | SQL_DATA                                              { $$ = ECPGd_data; }
5313                 | SQL_DATETIME_INTERVAL_CODE    { $$ = ECPGd_di_code; }
5314                 | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; }
5315                 | SQL_INDICATOR                                 { $$ = ECPGd_indicator; }
5316                 | SQL_KEY_MEMBER                                { $$ = ECPGd_key_member; }
5317                 | SQL_LENGTH                                    { $$ = ECPGd_length; }
5318                 | SQL_NAME                                              { $$ = ECPGd_name; }
5319                 | SQL_NULLABLE                                  { $$ = ECPGd_nullable; }
5320                 | SQL_OCTET_LENGTH                              { $$ = ECPGd_octet; }
5321                 | PRECISION                                             { $$ = ECPGd_precision; }
5322                 | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
5323                 | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
5324                 | SQL_SCALE                                             { $$ = ECPGd_scale; }
5325                 | TYPE_P                                                { $$ = ECPGd_type; }
5326                 ;
5327
5328 ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
5329                 | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
5330                 ;
5331
5332 ECPGGetDescItems: ECPGGetDescItem
5333                 | ECPGGetDescItems ',' ECPGGetDescItem
5334                 ;
5335
5336 ECPGGetDescriptorHeader:        GET SQL_DESCRIPTOR quoted_ident_stringvar
5337                                                                 ECPGGetDescHeaderItems
5338                         {  $$ = $3; }
5339                 ;
5340
5341 ECPGGetDescriptor:      GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE CVARIABLE ECPGGetDescItems
5342                         {  $$.str = $5; $$.name = $3; }
5343                 |       GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE Iconst ECPGGetDescItems
5344                         {  $$.str = $5; $$.name = $3; }
5345                 ;
5346
5347 /*
5348  * for compatibility with ORACLE we will also allow the keyword RELEASE
5349  * after a transaction statement to disconnect from the database.
5350  */
5351
5352 ECPGRelease: TransactionStmt SQL_RELEASE
5353                 {
5354                         if (strcmp($1, "begin") == 0)
5355                                                         mmerror(PARSE_ERROR, ET_ERROR, "RELEASE does not make sense when beginning a transaction");
5356
5357                         fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");",
5358                                         connection ? connection : "NULL", $1);
5359                         whenever_action(0);
5360                         fprintf(yyout, "ECPGdisconnect(__LINE__, %s);",
5361                                         connection ? connection : "\"CURRENT\"");
5362                         whenever_action(0);
5363                         free($1);
5364                 }
5365                 ;
5366
5367 /*
5368  * set/reset the automatic transaction mode, this needs a differnet handling
5369  * as the other set commands
5370  */
5371 ECPGSetAutocommit:      SET SQL_AUTOCOMMIT '=' on_off   { $$ = $4; }
5372                 |  SET SQL_AUTOCOMMIT TO on_off   { $$ = $4; }
5373                 ;
5374
5375 on_off: ON                              { $$ = make_str("on"); }
5376                 | OFF                   { $$ = make_str("off"); }
5377                 ;
5378
5379 /*
5380  * set the actual connection, this needs a differnet handling as the other
5381  * set commands
5382  */
5383 ECPGSetConnection:      SET SQL_CONNECTION TO connection_object { $$ = $4; }
5384                 | SET SQL_CONNECTION '=' connection_object { $$ = $4; }
5385                 | SET SQL_CONNECTION  connection_object { $$ = $3; }
5386                 ;
5387
5388 /*
5389  * define a new type for embedded SQL
5390  */
5391 ECPGTypedef: TYPE_P
5392                 {
5393                         /* reset this variable so we see if there was */
5394                         /* an initializer specified */
5395                         initializer = 0;
5396                 }
5397                 ColLabel IS var_type opt_array_bounds opt_reference
5398                 {
5399                         /* add entry to list */
5400                         struct typedefs *ptr, *this;
5401                         char *dimension = $6.index1;
5402                         char *length = $6.index2;
5403
5404                         if (($5.type_enum == ECPGt_struct ||
5405                                  $5.type_enum == ECPGt_union) &&
5406                                 initializer == 1)
5407                                 mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL TYPE command");
5408                         else
5409                         {
5410                                 for (ptr = types; ptr != NULL; ptr = ptr->next)
5411                                 {
5412                                         if (strcmp($3, ptr->name) == 0)
5413                                         {
5414                                                 /* re-definition is a bug */
5415                                                 snprintf(errortext, sizeof(errortext), "Type %s already defined", $3);
5416                                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
5417                                         }
5418                                 }
5419
5420                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0);
5421
5422                                 this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
5423
5424                                 /* initial definition */
5425                                 this->next = types;
5426                                 this->name = $3;
5427                                 this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
5428                                 this->type->type_enum = $5.type_enum;
5429                                 this->type->type_str = mm_strdup($3);
5430                                 this->type->type_dimension = dimension; /* dimension of array */
5431                                 this->type->type_index = length;        /* length of string */
5432                                 this->type->type_sizeof = ECPGstruct_sizeof;
5433                                 this->struct_member_list = ($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) ?
5434                                         struct_member_list[struct_level] : NULL;
5435
5436                                 if ($5.type_enum != ECPGt_varchar &&
5437                                         $5.type_enum != ECPGt_char &&
5438                                         $5.type_enum != ECPGt_unsigned_char &&
5439                                         atoi(this->type->type_index) >= 0)
5440                                         mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
5441
5442                                 types = this;
5443                         }
5444
5445                         if (auto_create_c == false)
5446                                 $$ = 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("*/"));
5447                         else
5448                                 $$ = 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(";"));
5449                 }
5450                 ;
5451
5452 opt_reference: SQL_REFERENCE            { $$ = make_str("reference"); }
5453                 | /*EMPTY*/                                     { $$ = EMPTY; }
5454                 ;
5455
5456 /*
5457  * define the type of one variable for embedded SQL
5458  */
5459 ECPGVar: SQL_VAR
5460                 {
5461                         /* reset this variable so we see if there was */
5462                         /* an initializer specified */
5463                         initializer = 0;
5464                 }
5465                 ColLabel IS var_type opt_array_bounds opt_reference
5466                 {
5467                         struct variable *p = find_variable($3);
5468                         char *dimension = $6.index1;
5469                         char *length = $6.index2;
5470                         struct ECPGtype * type;
5471
5472                         if (($5.type_enum == ECPGt_struct ||
5473                                  $5.type_enum == ECPGt_union) &&
5474                                 initializer == 1)
5475                                 mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
5476                         else
5477                         {
5478                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0);
5479
5480                                 switch ($5.type_enum)
5481                                 {
5482                                         case ECPGt_struct:
5483                                         case ECPGt_union:
5484                                                 if (atoi(dimension) < 0)
5485                                                         type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
5486                                                 else
5487                                                         type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
5488                                                 break;
5489
5490                                         case ECPGt_varchar:
5491                                                 if (atoi(dimension) == -1)
5492                                                         type = ECPGmake_simple_type($5.type_enum, length);
5493                                                 else
5494                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension);
5495                                                 break;
5496
5497                                         case ECPGt_char:
5498                                         case ECPGt_unsigned_char:
5499                                                 if (atoi(dimension) == -1)
5500                                                         type = ECPGmake_simple_type($5.type_enum, length);
5501                                                 else
5502                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension);
5503                                                 break;
5504
5505                                         default:
5506                                                 if (atoi(length) >= 0)
5507                                                         mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types");
5508
5509                                                 if (atoi(dimension) < 0)
5510                                                         type = ECPGmake_simple_type($5.type_enum, make_str("1"));
5511                                                 else
5512                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1")), dimension);
5513                                                 break;
5514                                 }
5515
5516                                 ECPGfree_type(p->type);
5517                                 p->type = type;
5518                         }
5519
5520                         $$ = 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("*/"));
5521                 }
5522                 ;
5523
5524 /*
5525  * whenever statement: decide what to do in case of error/no data found
5526  * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
5527  */
5528 ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
5529                 {
5530                         when_error.code = $<action>3.code;
5531                         when_error.command = $<action>3.command;
5532                         $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */\n"));
5533                 }
5534                 | SQL_WHENEVER NOT SQL_FOUND action
5535                 {
5536                         when_nf.code = $<action>4.code;
5537                         when_nf.command = $<action>4.command;
5538                         $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */\n"));
5539                 }
5540                 | SQL_WHENEVER SQL_SQLWARNING action
5541                 {
5542                         when_warn.code = $<action>3.code;
5543                         when_warn.command = $<action>3.command;
5544                         $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */\n"));
5545                 }
5546                 ;
5547
5548 action : SQL_CONTINUE
5549                 {
5550                         $<action>$.code = W_NOTHING;
5551                         $<action>$.command = NULL;
5552                         $<action>$.str = make_str("continue");
5553                 }
5554                 | SQL_SQLPRINT
5555                 {
5556                         $<action>$.code = W_SQLPRINT;
5557                         $<action>$.command = NULL;
5558                         $<action>$.str = make_str("sqlprint");
5559                 }
5560                 | SQL_STOP
5561                 {
5562                         $<action>$.code = W_STOP;
5563                         $<action>$.command = NULL;
5564                         $<action>$.str = make_str("stop");
5565                 }
5566                 | SQL_GOTO name
5567                 {
5568                         $<action>$.code = W_GOTO;
5569                         $<action>$.command = strdup($2);
5570                         $<action>$.str = cat2_str(make_str("goto "), $2);
5571                 }
5572                 | SQL_GO TO name
5573                 {
5574                         $<action>$.code = W_GOTO;
5575                         $<action>$.command = strdup($3);
5576                         $<action>$.str = cat2_str(make_str("goto "), $3);
5577                 }
5578                 | DO name '(' c_args ')'
5579                 {
5580                         $<action>$.code = W_DO;
5581                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
5582                         $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
5583                 }
5584                 | DO SQL_BREAK
5585                 {
5586                         $<action>$.code = W_BREAK;
5587                         $<action>$.command = NULL;
5588                         $<action>$.str = make_str("break");
5589                 }
5590                 | SQL_CALL name '(' c_args ')'
5591                 {
5592                         $<action>$.code = W_DO;
5593                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
5594                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
5595                 }
5596                 | SQL_CALL name 
5597                 {
5598                         $<action>$.code = W_DO;
5599                         $<action>$.command = cat_str(3, $2, make_str("("), make_str(")"));
5600                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
5601                 }
5602                 ;
5603
5604 /* some other stuff for ecpg */
5605
5606 /* additional unreserved keywords */
5607 ECPGKeywords: ECPGKeywords_vanames      { $$ = $1; }
5608                 | ECPGKeywords_rest     { $$ = $1; }
5609                 ;
5610
5611 ECPGKeywords_vanames:  SQL_BREAK                { $$ = make_str("break"); }
5612                 | SQL_CALL                      { $$ = make_str("call"); }
5613                 | SQL_CARDINALITY               { $$ = make_str("cardinality"); }
5614                 | SQL_CONTINUE                  { $$ = make_str("continue"); }
5615                 | SQL_COUNT                     { $$ = make_str("count"); }
5616                 | SQL_DATA                      { $$ = make_str("data"); }
5617                 | SQL_DATETIME_INTERVAL_CODE    { $$ = make_str("datetime_interval_code"); }
5618                 | SQL_DATETIME_INTERVAL_PRECISION       { $$ = make_str("datetime_interval_precision"); }
5619                 | SQL_FOUND                     { $$ = make_str("found"); }
5620                 | SQL_GO                        { $$ = make_str("go"); }
5621                 | SQL_GOTO                      { $$ = make_str("goto"); }
5622                 | SQL_IDENTIFIED                { $$ = make_str("identified"); }
5623                 | SQL_INDICATOR                 { $$ = make_str("indicator"); }
5624                 | SQL_KEY_MEMBER                { $$ = make_str("key_member"); }
5625                 | SQL_LENGTH                    { $$ = make_str("length"); }
5626                 | SQL_NAME                      { $$ = make_str("name"); }
5627                 | SQL_NULLABLE                  { $$ = make_str("nullable"); }
5628                 | SQL_OCTET_LENGTH              { $$ = make_str("octet_length"); }
5629                 | SQL_RELEASE                   { $$ = make_str("release"); }
5630                 | SQL_RETURNED_LENGTH           { $$ = make_str("returned_length"); }
5631                 | SQL_RETURNED_OCTET_LENGTH     { $$ = make_str("returned_octet_length"); }
5632                 | SQL_SCALE                     { $$ = make_str("scale"); }
5633                 | SQL_SECTION                   { $$ = make_str("section"); }
5634                 | SQL_SQLERROR                  { $$ = make_str("sqlerror"); }
5635                 | SQL_SQLPRINT                  { $$ = make_str("sqlprint"); }
5636                 | SQL_SQLWARNING                { $$ = make_str("sqlwarning"); }
5637                 | SQL_STOP                      { $$ = make_str("stop"); }
5638                 ;
5639                 
5640 ECPGKeywords_rest:  SQL_CONNECT                 { $$ = make_str("connect"); }
5641                 | SQL_DESCRIBE                  { $$ = make_str("describe"); }
5642                 | SQL_DISCONNECT                { $$ = make_str("disconnect"); }
5643                 | SQL_OPEN                      { $$ = make_str("open"); }
5644                 | SQL_VAR                       { $$ = make_str("var"); }
5645                 | SQL_WHENEVER                  { $$ = make_str("whenever"); }
5646                 ;
5647
5648 /* additional keywords that can be SQL type names (but not ECPGColLabels) */
5649 ECPGTypeName:  SQL_BOOL                         { $$ = make_str("bool"); }
5650                 | SQL_LONG                      { $$ = make_str("long"); }
5651                 | SQL_OUTPUT                    { $$ = make_str("output"); }
5652                 | SQL_SHORT                     { $$ = make_str("short"); }
5653                 | SQL_STRUCT                    { $$ = make_str("struct"); }
5654                 | SQL_SIGNED                    { $$ = make_str("signed"); }
5655                 | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
5656                 ;
5657
5658 symbol: ColLabel                                { $$ = $1; }
5659                 ;
5660
5661 /*
5662  * Name classification hierarchy.
5663  *
5664  * IDENT is the lexeme returned by the lexer for identifiers that match
5665  * no known keyword.  In most cases, we can accept certain keywords as
5666  * names, not only IDENTs.      We prefer to accept as many such keywords
5667  * as possible to minimize the impact of "reserved words" on programmers.
5668  * So, we divide names into several possible classes.  The classification
5669  * is chosen in part to make keywords acceptable as names wherever possible.
5670  */
5671
5672 /* Column identifier --- names that can be column, table, etc names.
5673  */
5674 ColId:  ident                                           { $$ = $1; }
5675                 | unreserved_keyword                    { $$ = $1; }
5676                 | col_name_keyword                      { $$ = $1; }
5677                 | ECPGKeywords                          { $$ = $1; }
5678                 | CHAR_P                                { $$ = make_str("char"); }
5679                 ;
5680
5681 /* Type identifier --- names that can be type names.
5682  */
5683 type_name:      ident                                   { $$ = $1; }
5684                 | unreserved_keyword                    { $$ = $1; }
5685                 | ECPGKeywords                          { $$ = $1; }
5686                 | ECPGTypeName                          { $$ = $1; }
5687                 ;
5688
5689 /* Function identifier --- names that can be function names.
5690  */
5691 function_name:  ident                                   { $$ = $1; }
5692                 | unreserved_keyword                    { $$ = $1; }
5693                 | func_name_keyword                     { $$ = $1; }
5694                 | ECPGKeywords                          { $$ = $1; }
5695                 ;
5696
5697 /* Column label --- allowed labels in "AS" clauses.
5698  * This presently includes *all* Postgres keywords.
5699  */
5700 ColLabel:  ECPGColLabel                         { $$ = $1; }
5701                 | ECPGTypeName                  { $$ = $1; }
5702                 | CHAR_P                        { $$ = make_str("char"); }
5703                 | INPUT_P                       { $$ = make_str("input"); }
5704                 | INT_P                         { $$ = make_str("int"); }
5705                 | UNION                         { $$ = make_str("union"); }
5706                 ;
5707
5708 ECPGColLabelCommon:  ident                              { $$ = $1; }
5709                 | col_name_keyword                      { $$ = $1; }
5710                 | func_name_keyword                     { $$ = $1; }
5711                 | ECPGKeywords_vanames                  { $$ = $1; }
5712                 ;
5713                 
5714 ECPGColLabel:  ECPGColLabelCommon                       { $$ = $1; }
5715                 | unreserved_keyword                    { $$ = $1; }
5716                 | reserved_keyword                      { $$ = $1; }
5717                 | ECPGKeywords_rest                     { $$ = $1; }
5718                 ;
5719
5720 /*
5721  * Keyword classification lists.  Generally, every keyword present in
5722  * the Postgres grammar should appear in exactly one of these lists.
5723  *
5724  * Put a new keyword into the first list that it can go into without causing
5725  * shift or reduce conflicts.  The earlier lists define "less reserved"
5726  * categories of keywords.
5727  */
5728
5729 /* "Unreserved" keywords --- available for use as any kind of name.
5730  */
5731 unreserved_keyword:
5732                   ABORT_P                       { $$ = make_str("abort"); }
5733                 | ABSOLUTE_P                    { $$ = make_str("absolute"); }
5734                 | ACCESS                        { $$ = make_str("access"); }
5735                 | ACTION                        { $$ = make_str("action"); }
5736                 | ADD                           { $$ = make_str("add"); }
5737                 | AFTER                         { $$ = make_str("after"); }
5738                 | AGGREGATE                     { $$ = make_str("aggregate"); }
5739                 | ALTER                         { $$ = make_str("alter"); }
5740                 | ASSERTION                     { $$ = make_str("assertion"); }
5741                 | ASSIGNMENT                    { $$ = make_str("assignment"); }
5742                 | AT                            { $$ = make_str("at"); }
5743                 | BACKWARD                      { $$ = make_str("backward"); }
5744                 | BEFORE                        { $$ = make_str("before"); }
5745                 | BEGIN_P                       { $$ = make_str("begin"); }
5746                 | BY                            { $$ = make_str("by"); }
5747                 | CACHE                         { $$ = make_str("cache"); }
5748                 | CASCADE                       { $$ = make_str("cascade"); }
5749                 | CHAIN                         { $$ = make_str("chain"); }
5750                 | CHARACTERISTICS               { $$ = make_str("characteristics"); }
5751                 | CHECKPOINT                    { $$ = make_str("checkpoint"); }
5752                 | CLASS                         { $$ = make_str("class"); }
5753                 | CLOSE                         { $$ = make_str("close"); }
5754                 | CLUSTER                       { $$ = make_str("cluster"); }
5755                 | COMMENT                       { $$ = make_str("comment"); }
5756                 | COMMIT                        { $$ = make_str("commit"); }
5757                 | COMMITTED                     { $$ = make_str("committed"); }
5758                 | CONSTRAINTS                   { $$ = make_str("constraints"); }
5759                 | CONVERSION_P                  { $$ = make_str("conversion"); }
5760                 | COPY                          { $$ = make_str("copy"); }
5761                 | CREATEDB                      { $$ = make_str("createdb"); }
5762                 | CREATEUSER                    { $$ = make_str("createuser"); }
5763                 | CURSOR                        { $$ = make_str("cursor"); }
5764                 | CYCLE                         { $$ = make_str("cycle"); }
5765                 | DATABASE                      { $$ = make_str("database"); }
5766                 | DAY_P                         { $$ = make_str("day"); }
5767                 | DEALLOCATE                    { $$ = make_str("deallocate"); }
5768                 | DECLARE                       { $$ = make_str("declare"); }
5769                 | DEFAULTS                      { $$ = make_str("defaults"); }
5770                 | DEFERRED                      { $$ = make_str("deferred"); }
5771                 | DELETE_P                      { $$ = make_str("delete"); }
5772                 | DELIMITER                     { $$ = make_str("delimiter"); }
5773                 | DELIMITERS                    { $$ = make_str("delimiters"); }
5774                 | DOMAIN_P                      { $$ = make_str("domain"); }
5775                 | DOUBLE_P                      { $$ = make_str("double"); }
5776                 | DROP                          { $$ = make_str("drop"); }
5777                 | EACH                          { $$ = make_str("each"); }
5778                 | ENCODING                      { $$ = make_str("encoding"); }
5779                 | ENCRYPTED                     { $$ = make_str("encrypted"); }
5780                 | ESCAPE                        { $$ = make_str("escape"); }
5781                 | EXCLUDING                     { $$ = make_str("excluding"); }
5782                 | EXCLUSIVE                     { $$ = make_str("exclusive"); }
5783                 | EXECUTE                       { $$ = make_str("execute"); }
5784                 | EXPLAIN                       { $$ = make_str("explain"); }
5785                 | FETCH                         { $$ = make_str("fetch"); }
5786                 | FIRST_P                       { $$ = make_str("first"); }
5787                 | FORCE                         { $$ = make_str("force"); }
5788                 | FORWARD                       { $$ = make_str("forward"); }
5789                 | FUNCTION                      { $$ = make_str("function"); }
5790                 | GLOBAL                        { $$ = make_str("global"); }
5791                 | HANDLER                       { $$ = make_str("handler"); }
5792                 | HOLD                          { $$ = make_str("hold"); }
5793                 | HOUR_P                        { $$ = make_str("hour"); }
5794                 | IMMEDIATE                     { $$ = make_str("immediate"); }
5795                 | IMMUTABLE                     { $$ = make_str("immutable"); }
5796                 | IMPLICIT_P                    { $$ = make_str("implicit"); }
5797                 | INCLUDING                     { $$ = make_str("including"); }
5798                 | INCREMENT                     { $$ = make_str("increment"); }
5799                 | INDEX                         { $$ = make_str("index"); }
5800                 | INHERITS                      { $$ = make_str("inherits"); }
5801                 | INOUT                         { $$ = make_str("inout"); }
5802                 | INSENSITIVE                   { $$ = make_str("insensitive"); }
5803                 | INSERT                        { $$ = make_str("insert"); }
5804                 | INSTEAD                       { $$ = make_str("instead"); }
5805                 | ISOLATION                     { $$ = make_str("isolation"); }
5806                 | KEY                           { $$ = make_str("key"); }
5807                 | LANCOMPILER                   { $$ = make_str("lancompiler"); }
5808                 | LANGUAGE                      { $$ = make_str("language"); }
5809                 | LAST_P                        { $$ = make_str("last"); }
5810                 | LEVEL                         { $$ = make_str("level"); }
5811                 | LISTEN                        { $$ = make_str("listen"); }
5812                 | LOAD                          { $$ = make_str("load"); }
5813                 | LOCAL                         { $$ = make_str("local"); }
5814                 | LOCATION                      { $$ = make_str("location"); }
5815                 | LOCK_P                        { $$ = make_str("lock"); }
5816                 | MATCH                         { $$ = make_str("match"); }
5817                 | MAXVALUE                      { $$ = make_str("maxvalue"); }
5818                 | MINUTE_P                      { $$ = make_str("minute"); }
5819                 | MINVALUE                      { $$ = make_str("minvalue"); }
5820                 | MODE                          { $$ = make_str("mode"); }
5821                 | MONTH_P                       { $$ = make_str("month"); }
5822                 | MOVE                          { $$ = make_str("move"); }
5823                 | NAMES                         { $$ = make_str("names"); }
5824                 | NATIONAL                      { $$ = make_str("national"); }
5825                 | NEXT                          { $$ = make_str("next"); }
5826                 | NO                            { $$ = make_str("no"); }
5827                 | NOCREATEDB                    { $$ = make_str("nocreatedb"); }
5828                 | NOCREATEUSER                  { $$ = make_str("nocreateuser"); }
5829                 | NOTHING                       { $$ = make_str("nothing"); }
5830                 | NOTIFY                        { $$ = make_str("notify"); }
5831                 | OF                            { $$ = make_str("of"); }
5832                 | OIDS                          { $$ = make_str("oids"); }
5833                 | OPERATOR                      { $$ = make_str("operator"); }
5834                 | OPTION                        { $$ = make_str("option"); }
5835                 | OUT_P                         { $$ = make_str("out"); }
5836                 | OWNER                         { $$ = make_str("owner"); }
5837                 | PARTIAL                       { $$ = make_str("partial"); }
5838                 | PASSWORD                      { $$ = make_str("password"); }
5839                 | PATH_P                        { $$ = make_str("path"); }
5840                 | PENDANT                       { $$ = make_str("pendant"); }
5841                 | PRECISION                     { $$ = make_str("precision"); }
5842                 | PREPARE                       { $$ = make_str("prepare"); }
5843                 | PRESERVE                      { $$ = make_str("preserver"); }
5844                 | PRIOR                         { $$ = make_str("prior"); }
5845                 | PRIVILEGES                    { $$ = make_str("privileges"); }
5846                 | PROCEDURAL                    { $$ = make_str("procedural"); }
5847                 | PROCEDURE                     { $$ = make_str("procedure"); }
5848                 | READ                          { $$ = make_str("read"); }
5849                 | RECHECK                       { $$ = make_str("recheck"); }
5850                 | REINDEX                       { $$ = make_str("reindex"); }
5851                 | RELATIVE_P                    { $$ = make_str("relative"); }
5852                 | RENAME                        { $$ = make_str("rename"); }
5853                 | REPLACE                       { $$ = make_str("replace"); }
5854                 | RESET                         { $$ = make_str("reset"); }
5855                 | RESTART                       { $$ = make_str("restart"); }
5856                 | RESTRICT                      { $$ = make_str("restrict"); }
5857                 | RETURNS                       { $$ = make_str("returns"); }
5858                 | REVOKE                        { $$ = make_str("revoke"); }
5859                 | ROLLBACK                      { $$ = make_str("rollback"); }
5860                 | ROWS                          { $$ = make_str("rows"); }
5861                 | RULE                          { $$ = make_str("rule"); }
5862                 | SCHEMA                        { $$ = make_str("schema"); }
5863                 | SCROLL                        { $$ = make_str("scroll"); }
5864                 | SECOND_P                      { $$ = make_str("second"); }
5865                 | SEQUENCE                      { $$ = make_str("sequence"); }
5866                 | SERIALIZABLE                  { $$ = make_str("serializable"); }
5867                 | SESSION                       { $$ = make_str("session"); }
5868                 | SET                           { $$ = make_str("set"); }
5869                 | SHARE                         { $$ = make_str("share"); }
5870                 | SHOW                          { $$ = make_str("show"); }
5871                 | SIMPLE                        { $$ = make_str("simple"); }
5872                 | STABLE                        { $$ = make_str("stable"); }
5873                 | START                         { $$ = make_str("start"); }
5874                 | STATEMENT                     { $$ = make_str("statement"); }
5875                 | STATISTICS                    { $$ = make_str("statistics"); }
5876                 | STDIN                         { $$ = make_str("stdin"); }
5877                 | STDOUT                        { $$ = make_str("stdout"); }
5878                 | STORAGE                       { $$ = make_str("storage"); }
5879                 | STRICT_P                      { $$ = make_str("strict"); }
5880                 | SYSID                         { $$ = make_str("sysid"); }
5881                 | TEMP                          { $$ = make_str("temp"); }
5882                 | TEMPLATE                      { $$ = make_str("template"); }
5883                 | TEMPORARY                     { $$ = make_str("temporary"); }
5884                 | TOAST                         { $$ = make_str("toast"); }
5885                 | TRANSACTION                   { $$ = make_str("transaction"); }
5886                 | TRIGGER                       { $$ = make_str("trigger"); }
5887                 | TRUNCATE                      { $$ = make_str("truncate"); }
5888                 | TRUSTED                       { $$ = make_str("trusted"); }
5889                 | TYPE_P                        { $$ = make_str("type"); }
5890                 | UNENCRYPTED                   { $$ = make_str("unencrypted"); }
5891                 | UNKNOWN                       { $$ = make_str("unknown"); }
5892                 | UNLISTEN                      { $$ = make_str("unlisten"); }
5893                 | UNTIL                         { $$ = make_str("until"); }
5894                 | UPDATE                        { $$ = make_str("update"); }
5895                 | USAGE                         { $$ = make_str("usage"); }
5896                 | VACUUM                        { $$ = make_str("vacuum"); }
5897                 | VALID                         { $$ = make_str("valid"); }
5898                 | VALUES                        { $$ = make_str("values"); }
5899                 | VARYING                       { $$ = make_str("varying"); }
5900                 | VERSION                       { $$ = make_str("version"); }
5901                 | VIEW                          { $$ = make_str("view"); }
5902                 | WITH                          { $$ = make_str("with"); }
5903                 | WITHOUT                       { $$ = make_str("without"); }
5904                 | WORK                          { $$ = make_str("work"); }
5905                 | WRITE                         { $$ = make_str("write"); }
5906                 | YEAR_P                        { $$ = make_str("year"); }
5907                 | ZONE                          { $$ = make_str("zone"); }
5908                 ;
5909
5910 /* Column identifier --- keywords that can be column, table, etc names.
5911  *
5912  * Many of these keywords will in fact be recognized as type or function
5913  * names too; but they have special productions for the purpose, and so
5914  * can't be treated as "generic" type or function names.
5915  *
5916  * The type names appearing here are not usable as function names
5917  * because they can be followed by '(' in typename productions, which
5918  * looks too much like a function call for an LR(1) parser.
5919  */
5920 col_name_keyword:
5921                 BIGINT                  { $$ = make_str("bigint");}
5922                 | BIT                   { $$ = make_str("bit"); }
5923 /* CHAR must be excluded from ECPGColLabel because of conflict with UNSIGNED
5924                 | CHAR_P                { $$ = make_str("char"); }
5925  */
5926                 | CHARACTER             { $$ = make_str("character"); }
5927                 | COALESCE              { $$ = make_str("coalesce"); }
5928                 | CONVERT               { $$ = make_str("convert"); }
5929                 | DEC                   { $$ = make_str("dec"); }
5930                 | DECIMAL_P             { $$ = make_str("decimal"); }
5931                 | EXISTS                { $$ = make_str("exists"); }
5932                 | EXTRACT               { $$ = make_str("extract"); }
5933                 | FLOAT_P               { $$ = make_str("float"); }
5934 /* INT must be excluded from ECPGColLabel because of conflict
5935                 | INT_P                 { $$ = make_str("int"); }
5936  */
5937                 | INTEGER               { $$ = make_str("integer"); }
5938                 | INTERVAL              { $$ = make_str("interval"); }
5939                 | NCHAR                 { $$ = make_str("nchar"); }
5940                 | NONE                  { $$ = make_str("none"); }
5941                 | NULLIF                { $$ = make_str("nullif"); }
5942                 | NUMERIC               { $$ = make_str("numeric"); }
5943                 | POSITION              { $$ = make_str("position"); }
5944                 | REAL                  { $$ = make_str("real"); }
5945                 | ROW                   { $$ = make_str("row"); }
5946                 | SETOF                 { $$ = make_str("setof"); }
5947                 | SMALLINT              { $$ = make_str("smallint"); }
5948                 | SUBSTRING             { $$ = make_str("substring"); }
5949                 | TIME                  { $$ = make_str("time"); }
5950                 | TIMESTAMP             { $$ = make_str("timestamp"); }
5951                 | TREAT                 { $$ = make_str("treat"); }
5952                 | TRIM                  { $$ = make_str("trim"); }
5953                 | VARCHAR               { $$ = make_str("varchar"); }
5954                 ;
5955
5956 /* Function identifier --- keywords that can be function names.
5957  *
5958  * Most of these are keywords that are used as operators in expressions;
5959  * in general such keywords can't be column names because they would be
5960  * ambiguous with variables, but they are unambiguous as function identifiers.
5961  *
5962  * Do not include POSITION, SUBSTRING, etc here since they have explicit
5963  * productions in a_expr to support the goofy SQL9x argument syntax.
5964  *      - thomas 2000-11-28
5965  */
5966 func_name_keyword:
5967                   AUTHORIZATION         { $$ = make_str("authorization"); }
5968                 | BETWEEN               { $$ = make_str("between"); }
5969                 | BINARY                { $$ = make_str("binary"); }
5970                 | CROSS                 { $$ = make_str("cross"); }
5971                 | FREEZE                { $$ = make_str("freeze"); }
5972                 | FULL                  { $$ = make_str("full"); }
5973                 | ILIKE                 { $$ = make_str("ilike"); }
5974                 | IN_P                  { $$ = make_str("in"); }
5975                 | INNER_P               { $$ = make_str("inner"); }
5976                 | IS                    { $$ = make_str("is"); }
5977                 | ISNULL                { $$ = make_str("isnull"); }
5978                 | JOIN                  { $$ = make_str("join"); }
5979                 | LEFT                  { $$ = make_str("left"); }
5980                 | LIKE                  { $$ = make_str("like"); }
5981                 | NATURAL               { $$ = make_str("natural"); }
5982                 | NOTNULL               { $$ = make_str("notnull"); }
5983                 | OUTER_P               { $$ = make_str("outer"); }
5984                 | OVERLAPS              { $$ = make_str("overlaps"); }
5985                 | RIGHT                 { $$ = make_str("right"); }
5986                 | SIMILAR               { $$ = make_str("similar"); }
5987                 | VERBOSE               { $$ = make_str("verbose"); }
5988                 ;
5989
5990 /* Reserved keyword --- these keywords are usable only as a ColLabel.
5991  *
5992  * Keywords appear here if they could not be distinguished from variable,
5993  * type, or function names in some contexts.  Don't put things here unless
5994  * forced to.
5995  */
5996 reserved_keyword:
5997                   ALL                           { $$ = make_str("all"); }
5998                 | ANALYSE                       { $$ = make_str("analyse"); } /* British */
5999                 | ANALYZE                       { $$ = make_str("analyze"); }
6000                 | AND                           { $$ = make_str("and"); }
6001                 | ANY                           { $$ = make_str("any"); }
6002                 | ARRAY                         { $$ = make_str("array"); }
6003                 | AS                            { $$ = make_str("as"); }
6004                 | ASC                           { $$ = make_str("asc"); }
6005                 | BOTH                          { $$ = make_str("both"); }
6006                 | CASE                          { $$ = make_str("case"); }
6007                 | CAST                          { $$ = make_str("cast"); }
6008                 | CHECK                         { $$ = make_str("check"); }
6009                 | COLLATE                       { $$ = make_str("collate"); }
6010                 | COLUMN                        { $$ = make_str("column"); }
6011                 | CONSTRAINT                    { $$ = make_str("constraint"); }
6012                 | CREATE                        { $$ = make_str("create"); }
6013                 | CURRENT_DATE                  { $$ = make_str("current_date"); }
6014                 | CURRENT_TIME                  { $$ = make_str("current_time"); }
6015                 | CURRENT_TIMESTAMP             { $$ = make_str("current_timestamp"); }
6016                 | CURRENT_USER                  { $$ = make_str("current_user"); }
6017                 | DEFAULT                       { $$ = make_str("default"); }
6018                 | DEFERRABLE                    { $$ = make_str("deferrable"); }
6019                 | DESC                          { $$ = make_str("desc"); }
6020                 | DISTINCT                      { $$ = make_str("distinct"); }
6021                 | DO                            { $$ = make_str("do"); }
6022                 | ELSE                          { $$ = make_str("else"); }
6023                 | END_P                         { $$ = make_str("end"); }
6024                 | EXCEPT                        { $$ = make_str("except"); }
6025                 | FALSE_P                       { $$ = make_str("false"); }
6026                 | FOR                           { $$ = make_str("for"); }
6027                 | FOREIGN                       { $$ = make_str("foreign"); }
6028                 | FROM                          { $$ = make_str("from"); }
6029                 | GRANT                         { $$ = make_str("grant"); }
6030                 | GROUP_P                       { $$ = make_str("group"); }
6031                 | HAVING                        { $$ = make_str("having"); }
6032                 | INITIALLY                     { $$ = make_str("initially"); }
6033                 | INTERSECT                     { $$ = make_str("intersect"); }
6034                 | INTO                          { $$ = make_str("into"); }
6035                 | LEADING                       { $$ = make_str("leading"); }
6036                 | LIMIT                         { $$ = make_str("limit"); }
6037                 | NEW                           { $$ = make_str("new"); }
6038                 | NOT                           { $$ = make_str("not"); }
6039                 | NULL_P                        { $$ = make_str("null"); }
6040                 | OFF                           { $$ = make_str("off"); }
6041                 | OFFSET                        { $$ = make_str("offset"); }
6042                 | OLD                           { $$ = make_str("old"); }
6043                 | ON                            { $$ = make_str("on"); }
6044                 | ONLY                          { $$ = make_str("only"); }
6045                 | OR                            { $$ = make_str("or"); }
6046                 | ORDER                         { $$ = make_str("order"); }
6047                 | PRIMARY                       { $$ = make_str("primary"); }
6048                 | REFERENCES                    { $$ = make_str("references"); }
6049                 | SELECT                        { $$ = make_str("select"); }
6050                 | SESSION_USER                  { $$ = make_str("session_user"); }
6051                 | SOME                          { $$ = make_str("some"); }
6052                 | TABLE                         { $$ = make_str("table"); }
6053                 | THEN                          { $$ = make_str("then"); }
6054                 | TO                            { $$ = make_str("to"); }
6055                 | TRAILING                      { $$ = make_str("trailing"); }
6056                 | TRUE_P                        { $$ = make_str("true"); }
6057 /* UNION must be excluded from ECPGColLabel because of conflict with s_union
6058                 | UNION                         { $$ = make_str("union"); }
6059  */
6060                 | UNIQUE                        { $$ = make_str("unique"); }
6061                 | USER                          { $$ = make_str("user"); }
6062                 | USING                         { $$ = make_str("using"); }
6063                 | WHEN                          { $$ = make_str("when"); }
6064                 | WHERE                         { $$ = make_str("where"); }
6065                 ;
6066
6067
6068 into_list : coutputvariable | into_list ',' coutputvariable
6069                 ;
6070
6071 ecpgstart: SQL_START    { reset_variables(); }
6072                 ;
6073
6074 c_args: /*EMPTY*/               { $$ = EMPTY; }
6075                 | c_list                { $$ = $1; }
6076                 ;
6077
6078 coutputvariable: CVARIABLE indicator
6079                         { add_variable(&argsresult, find_variable($1), find_variable($2)); }
6080                 | CVARIABLE
6081                         { add_variable(&argsresult, find_variable($1), &no_indicator); }
6082                 ;
6083
6084
6085 civarind: CVARIABLE indicator
6086                 {
6087                         if (find_variable($2)->type->type == ECPGt_array)
6088                                 mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
6089
6090                         add_variable(&argsinsert, find_variable($1), find_variable($2));
6091                         $$ = create_questionmarks($1, false);
6092                 }
6093                 ;
6094
6095 civar: CVARIABLE
6096                         {
6097                                 add_variable(&argsinsert, find_variable($1), &no_indicator);
6098                                 $$ = create_questionmarks($1, false);
6099                         }
6100                 ;
6101
6102 indicator: CVARIABLE                            { check_indicator((find_variable($1))->type); $$ = $1; }
6103                 | SQL_INDICATOR CVARIABLE       { check_indicator((find_variable($2))->type); $$ = $2; }
6104                 | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
6105                 ;
6106
6107 ident: IDENT                                            { $$ = $1; }
6108                 | CSTRING                                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
6109                 ;
6110
6111 quoted_ident_stringvar: name
6112                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
6113                 | char_variable
6114                         { $$ = make3_str(make_str("("), $1, make_str(")")); }
6115                 ;
6116
6117 /*
6118  * C stuff
6119  */
6120
6121 c_stuff_item: c_anything                        { $$ = $1; }
6122                 | '(' ')'                       { $$ = make_str("()"); }
6123                 | '(' c_stuff ')'
6124                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
6125                 ;
6126
6127 c_stuff: c_stuff_item   { $$ = $1; }
6128                 | c_stuff c_stuff_item
6129                         { $$ = cat2_str($1, $2); }
6130                 ;
6131
6132 c_list: c_term                          { $$ = $1; }
6133                 | c_list ',' c_term     { $$ = cat_str(3, $1, make_str(","), $3); }
6134                 ;
6135
6136 c_term:  c_stuff                        { $$ = $1; }
6137                 | '{' c_list '}'        { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
6138                 ;
6139
6140 c_thing:        c_anything      { $$ = $1; }
6141                 |       '('     { $$ = make_str("("); }
6142                 |       ')'     { $$ = make_str(")"); }
6143                 |       ','     { $$ = make_str(","); }
6144                 |       ';'     { $$ = make_str(";"); }
6145                 ;
6146
6147 c_anything:  IDENT                              { $$ = $1; }
6148                 | CSTRING                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
6149                 | Iconst                        { $$ = $1; }
6150                 | Fconst                        { $$ = $1; }
6151                 | Sconst                        { $$ = $1; }
6152                 | '*'                           { $$ = make_str("*"); }
6153                 | '+'                           { $$ = make_str("+"); }
6154                 | '-'                           { $$ = make_str("-"); }
6155                 | '/'                           { $$ = make_str("/"); }
6156                 | '%'                           { $$ = make_str("%"); }
6157                 | NULL_P                        { $$ = make_str("NULL"); }
6158                 | S_ADD                         { $$ = make_str("+="); }
6159                 | S_AND                         { $$ = make_str("&&"); }
6160                 | S_ANYTHING                    { $$ = make_name(); }
6161                 | S_AUTO                        { $$ = make_str("auto"); }
6162                 | S_CONST                       { $$ = make_str("const"); }
6163                 | S_DEC                         { $$ = make_str("--"); }
6164                 | S_DIV                         { $$ = make_str("/="); }
6165                 | S_DOTPOINT                    { $$ = make_str(".*"); }
6166                 | S_EQUAL                       { $$ = make_str("=="); }
6167                 | S_EXTERN                      { $$ = make_str("extern"); }
6168                 | S_INC                         { $$ = make_str("++"); }
6169                 | S_LSHIFT                      { $$ = make_str("<<"); }
6170                 | S_MEMBER                      { $$ = make_str("->"); }
6171                 | S_MEMPOINT                    { $$ = make_str("->*"); }
6172                 | S_MOD                         { $$ = make_str("%="); }
6173                 | S_MUL                         { $$ = make_str("*="); }
6174                 | S_NEQUAL                      { $$ = make_str("!="); }
6175                 | S_OR                          { $$ = make_str("||"); }
6176                 | S_REGISTER                    { $$ = make_str("register"); }
6177                 | S_RSHIFT                      { $$ = make_str(">>"); }
6178                 | S_STATIC                      { $$ = make_str("static"); }
6179                 | S_SUB                         { $$ = make_str("-="); }
6180                 | S_TYPEDEF                     { $$ = make_str("typedef"); }
6181                 | SQL_BOOL                      { $$ = make_str("bool"); }
6182                 | SQL_ENUM                      { $$ = make_str("enum"); }
6183                 | HOUR_P                        { $$ = make_str("hour"); }
6184                 | INT_P                         { $$ = make_str("int"); }
6185                 | SQL_LONG                      { $$ = make_str("long"); }
6186                 | MINUTE_P                      { $$ = make_str("minute"); }
6187                 | MONTH_P                       { $$ = make_str("month"); }
6188                 | SECOND_P                      { $$ = make_str("second"); }
6189                 | SQL_SHORT                     { $$ = make_str("short"); }
6190                 | SQL_SIGNED                    { $$ = make_str("signed"); }
6191                 | SQL_STRUCT                    { $$ = make_str("struct"); }
6192                 | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
6193                 | YEAR_P                        { $$ = make_str("year"); }
6194                 | CHAR_P                        { $$ = make_str("char"); }
6195                 | FLOAT_P                       { $$ = make_str("float"); }
6196                 | UNION                         { $$ = make_str("union"); }
6197                 | VARCHAR                       { $$ = make_str("varchar"); }
6198                 | '['                           { $$ = make_str("["); }
6199                 | ']'                           { $$ = make_str("]"); }
6200                 | '='                           { $$ = make_str("="); }
6201                 ;
6202
6203 %%
6204
6205 void yyerror( char * error)
6206 {
6207         char buf[1024];
6208
6209         snprintf(buf,sizeof buf,"%s at or near \"%s\"", error, token_start ? token_start : yytext);
6210         buf[sizeof(buf)-1]=0;
6211         mmerror(PARSE_ERROR, ET_ERROR, buf);
6212 }
6213
6214 #include "pgc.c"