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