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