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