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