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