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