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