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