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