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