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