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