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