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