/* Copyright comment */
%{
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
+#include <stdarg.h>
+
+#include "postgres.h"
+#include "access/htup.h"
#include "catalog/catname.h"
#include "utils/numeric.h"
+#include "utils/memutils.h"
+#include "storage/bufpage.h"
-#include "type.h"
#include "extern.h"
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
#endif
-#define STRUCT_DEPTH 128
+#define EMPTY make_str("")
/*
* Variables containing simple states.
*/
-static int struct_level = 0;
-static char errortext[128];
-static int QueryIsRule = 0, ForUpdateNotAllowed = 0;
-static enum ECPGttype actual_type[STRUCT_DEPTH];
+int struct_level = 0;
+char errortext[128];
+static char *connection = NULL;
+static char *descriptor_name = NULL;
+static char *descriptor_index= NULL;
+static int QueryIsRule = 0, ForUpdateNotAllowed = 0, FoundInto = 0;
+static int FoundSort = 0;
+static int initializer = 0;
+static struct this_type actual_type[STRUCT_DEPTH];
static char *actual_storage[STRUCT_DEPTH];
+static char *actual_startline[STRUCT_DEPTH];
/* temporarily store struct members while creating the data structure */
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
+struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, {NULL}};
+
+/* variable lookup */
+
+static struct variable * find_variable(char * name);
+static void whenever_action(int mode);
+
+/*
+ * Handle parsing errors and warnings
+ */
+void
+mmerror(enum errortype type, char * error)
+{
+
+ switch(type)
+ {
+ case ET_WARN:
+ fprintf(stderr, "%s:%d: WARNING: %s\n", input_filename, yylineno, error);
+ break;
+ case ET_ERROR:
+ fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error);
+ ret_value = PARSE_ERROR;
+ break;
+ case ET_FATAL:
+ fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error);
+ exit(PARSE_ERROR);
+ }
+}
+
/*
* Handle the filename and line numbering.
*/
char * input_filename = NULL;
-static void
+void
output_line_number()
{
if (input_filename)
fprintf(yyout, "\n#line %d \"%s\"\n", yylineno, input_filename);
}
+static void
+output_simple_statement(char *cmd)
+{
+ fputs(cmd, yyout);
+ output_line_number();
+ free(cmd);
+}
+
+/*
+ * assignment handling function (descriptor)
+ */
+
+static struct assignment *assignments;
+
+static void push_assignment(char *var,char *value)
+{
+ struct assignment *new=(struct assignment *)mm_alloc(sizeof(struct assignment));
+
+ new->next=assignments;
+ new->variable=mm_alloc(strlen(var)+1);
+ strcpy(new->variable,var);
+ new->value=mm_alloc(strlen(value)+1);
+ strcpy(new->value,value);
+ assignments=new;
+}
+
+static void drop_assignments(void)
+{ while (assignments)
+ { struct assignment *old_head=assignments;
+ assignments=old_head->next;
+ free(old_head->variable);
+ free(old_head->value);
+ free(old_head);
+ }
+}
+
+/* XXX: these should be more accurate (consider ECPGdump_a_* ) */
+static void ECPGnumeric_lvalue(FILE *f,char *name)
+{ const struct variable *v=find_variable(name);
+ switch(v->type->typ)
+ { case ECPGt_short:
+ case ECPGt_int:
+ case ECPGt_long:
+ case ECPGt_unsigned_short:
+ case ECPGt_unsigned_int:
+ case ECPGt_unsigned_long:
+ fputs(name,yyout);
+ break;
+ default:
+ snprintf(errortext,sizeof errortext,"variable %s: numeric type needed"
+ ,name);
+ mmerror(ET_ERROR,errortext);
+ break;
+ }
+}
+
+static void ECPGstring_buffer(FILE *f,char *name)
+{ const struct variable *v=find_variable(name);
+ switch(v->type->typ)
+ { case ECPGt_varchar:
+ fprintf(yyout,"%s.arr",name);
+ break;
+
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ fputs(name,yyout);
+ break;
+
+ default:
+ snprintf(errortext,sizeof errortext,"variable %s: character type needed"
+ ,name);
+ mmerror(ET_ERROR,errortext);
+ break;
+ }
+}
+
+static void ECPGstring_length(FILE *f,char *name)
+{ const struct variable *v=find_variable(name);
+ switch(v->type->typ)
+ { case ECPGt_varchar:
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ if (!v->type->size)
+ { snprintf(errortext,sizeof errortext,"zero length char variable %s for assignment",
+ v->name);
+ mmerror(ET_ERROR,errortext);
+ }
+ fprintf(yyout,"%ld",v->type->size);
+ break;
+ default:
+ snprintf(errortext,sizeof errortext,"variable %s: character type needed"
+ ,name);
+ mmerror(ET_ERROR,errortext);
+ break;
+ }
+}
+
+static void ECPGdata_assignment(char *variable,char *index_plus_1)
+{ const struct variable *v=find_variable(variable);
+ fprintf(yyout,"\t\t\tif (!PQgetisnull(ECPGresult,0,(%s)-1))\n",index_plus_1);
+ switch(v->type->typ)
+ { case ECPGt_short:
+ case ECPGt_int: /* use the same conversion as ecpglib does */
+ case ECPGt_long:
+ fprintf(yyout,"\t\t\t\t%s=strtol(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);\n"
+ ,variable,index_plus_1);
+ break;
+ case ECPGt_unsigned_short:
+ case ECPGt_unsigned_int:
+ case ECPGt_unsigned_long:
+ fprintf(yyout,"\t\t\t\t%s=strtoul(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);\n"
+ ,variable,index_plus_1);
+ break;
+ case ECPGt_float:
+ case ECPGt_double:
+ fprintf(yyout,"\t\t\t\t%s=strtod(PQgetvalue(ECPGresult,0,(%s)-1),NULL);\n"
+ ,variable,index_plus_1);
+ break;
+
+ case ECPGt_bool:
+ fprintf(yyout,"\t\t\t\t%s=PQgetvalue(ECPGresult,0,(%s)-1)[0]=='t';\n"
+ ,variable,index_plus_1);
+ break;
+
+ case ECPGt_varchar:
+ fprintf(yyout,"\t\t\t{\tstrncpy(%s.arr,PQgetvalue(ECPGresult,0,(%s)-1),%ld);\n"
+ ,variable,index_plus_1,v->type->size);
+ fprintf(yyout,"\t\t\t\t%s.len=strlen(PQgetvalue(ECPGresult,0,(%s)-1)\n"
+ ,variable,index_plus_1);
+ fprintf(yyout,"\t\t\t\tif (%s.len>%ld) { %s.len=%ld; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }\n"
+ ,variable,v->type->size,variable,v->type->size);
+ fputs("\t\t\t}\n",yyout);
+ break;
+
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ if (!v->type->size)
+ { snprintf(errortext,sizeof errortext,"zero length char variable %s for DATA assignment",
+ v->name);
+ mmerror(ET_ERROR,errortext);
+ }
+ fprintf(yyout,"\t\t\t{\tstrncpy(%s,PQgetvalue(ECPGresult,0,(%s)-1),%ld);\n"
+ ,variable,index_plus_1,v->type->size);
+ fprintf(yyout,"\t\t\t\tif (strlen(PQgetvalue(ECPGresult,0,(%s)-1))>=%ld)\n"
+ "\t\t\t\t{ %s[%ld]=0; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }\n"
+ ,index_plus_1,v->type->size,variable,v->type->size-1);
+ fputs("\t\t\t}\n",yyout);
+ break;
+
+ default:
+ snprintf(errortext,sizeof errortext,"unknown variable type %d for DATA assignment"
+ ,v->type->typ);
+ mmerror(ET_ERROR,errortext);
+ break;
+ }
+}
+
+static void
+output_get_descr_header(char *desc_name)
+{ struct assignment *results;
+ fprintf(yyout,"{\tPGresult *ECPGresult=ECPGresultByDescriptor(%d, \"%s\");\n"
+ ,yylineno,desc_name);
+ fputs("\tif (ECPGresult)\n\t{",yyout);
+ for (results=assignments;results!=NULL;results=results->next)
+ { if (!strcasecmp(results->value,"count"))
+ { fputs("\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fputs("=PQnfields(ECPGresult);\n",yyout);
+ }
+ else
+ { snprintf(errortext,sizeof errortext,"unknown descriptor header item '%s'",results->value);
+ mmerror(ET_WARN,errortext);
+ }
+ }
+ drop_assignments();
+ fputs("}",yyout);
+
+ whenever_action(2|1);
+}
+
+static void
+output_get_descr(char *desc_name)
+{ struct assignment *results;
+ int flags=0;
+ const int DATA_SEEN=1;
+ const int INDICATOR_SEEN=2;
+
+ fprintf(yyout,"{\tPGresult *ECPGresult=ECPGresultByDescriptor(%d, \"%s\");\n"
+ ,yylineno,desc_name);
+ fputs("\tif (ECPGresult)\n\t{",yyout);
+ fprintf(yyout,"\tif (PQntuples(ECPGresult)<1) ECPGraise(%d,ECPG_NOT_FOUND);\n",yylineno);
+ fprintf(yyout,"\t\telse if (%s<1 || %s>PQnfields(ECPGresult))\n"
+ "\t\t\tECPGraise(%d,ECPG_INVALID_DESCRIPTOR_INDEX);\n"
+ ,descriptor_index,descriptor_index,yylineno);
+ fputs("\t\telse\n\t\t{\n",yyout);
+ for (results=assignments;results!=NULL;results=results->next)
+ { if (!strcasecmp(results->value,"type"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=ECPGDynamicType(PQftype(ECPGresult,(%s)-1));\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"datetime_interval_code"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=ECPGDynamicType_DDT(PQftype(ECPGresult,(%s)-1));\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"length"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=PQfmod(ECPGresult,(%s)-1)-VARHDRSZ;\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"octet_length"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=PQfsize(ECPGresult,(%s)-1);\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"returned_length")
+ || !strcasecmp(results->value,"returned_octet_length"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=PQgetlength(ECPGresult,0,(%s)-1);\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"precision"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=PQfmod(ECPGresult,(%s)-1)>>16;\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"scale"))
+ { fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=(PQfmod(ECPGresult,(%s)-1)-VARHDRSZ)&0xffff;\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"nullable"))
+ { mmerror(ET_WARN,"nullable is always 1");
+ fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=1;\n");
+ }
+ else if (!strcasecmp(results->value,"key_member"))
+ { mmerror(ET_WARN,"key_member is always 0");
+ fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=0;\n");
+ }
+ else if (!strcasecmp(results->value,"name"))
+ { fputs("\t\t\tstrncpy(",yyout);
+ ECPGstring_buffer(yyout,results->variable);
+ fprintf(yyout,",PQfname(ECPGresult,(%s)-1),",descriptor_index);
+ ECPGstring_length(yyout,results->variable);
+ fputs(");\n",yyout);
+ }
+ else if (!strcasecmp(results->value,"indicator"))
+ { flags|=INDICATOR_SEEN;
+ fputs("\t\t\t",yyout);
+ ECPGnumeric_lvalue(yyout,results->variable);
+ fprintf(yyout,"=-PQgetisnull(ECPGresult,0,(%s)-1);\n",descriptor_index);
+ }
+ else if (!strcasecmp(results->value,"data"))
+ { flags|=DATA_SEEN;
+ ECPGdata_assignment(results->variable,descriptor_index);
+ }
+ else
+ { snprintf(errortext,sizeof errortext,"unknown descriptor header item '%s'",results->value);
+ mmerror(ET_WARN,errortext);
+ }
+ }
+ if (flags==DATA_SEEN) /* no indicator */
+ { fprintf(yyout,"\t\t\tif (PQgetisnull(ECPGresult,0,(%s)-1))\n"
+ "\t\t\t\tECPGraise(%d,ECPG_MISSING_INDICATOR);\n"
+ ,descriptor_index,yylineno);
+ }
+ drop_assignments();
+ fputs("\t\t}\n\t}\n",yyout);
+
+ whenever_action(2|1);
+}
+
/*
* store the whenever action here
*/
-static struct when when_error, when_nf;
+struct when when_error, when_nf, when_warn;
static void
print_action(struct when *w)
static void
whenever_action(int mode)
{
- if (mode == 1 && when_nf.code != W_NOTHING)
+ if ((mode&1) == 1 && when_nf.code != W_NOTHING)
{
output_line_number();
fprintf(yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) ");
print_action(&when_nf);
}
+ if (when_warn.code != W_NOTHING)
+ {
+ output_line_number();
+ fprintf(yyout, "\nif (sqlca.sqlwarn[0] == 'W') ");
+ print_action(&when_warn);
+ }
if (when_error.code != W_NOTHING)
{
output_line_number();
fprintf(yyout, "\nif (sqlca.sqlcode < 0) ");
print_action(&when_error);
}
+ if ((mode&2) == 2)
+ fputc('}', yyout);
output_line_number();
}
return(p);
}
-static struct variable * find_variable(char * name);
-
static struct variable *
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
{
case ECPGt_array:
return(new_variable(name, ECPGmake_array_type(members->typ->u.element, members->typ->size)));
case ECPGt_struct:
- return(new_variable(name, ECPGmake_struct_type(members->typ->u.members)));
+ case ECPGt_union:
+ return(new_variable(name, ECPGmake_struct_type(members->typ->u.members, members->typ->typ)));
default:
return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size)));
}
*next = '\0';
p = find_variable(name);
- /* restore the name, we will need it later on */
- *next = c;
if (c == '-')
{
+ if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union)
+ {
+ sprintf(errortext, "variable %s is not a pointer", name);
+ mmerror(ET_FATAL, errortext);
+ }
+
+ if (p->type->u.element->typ != ECPGt_struct && p->type->u.element->typ != ECPGt_union)
+ {
+ sprintf(errortext, "variable %s is not a pointer to a structure or a union", name);
+ mmerror(ET_FATAL, errortext);
+ }
+
+ /* restore the name, we will need it later on */
+ *next = c;
next++;
+
return find_struct_member(name, next, p->type->u.element->u.members);
}
- else return find_struct_member(name, next, p->type->u.members);
+ else
+ {
+ if (p->type->typ != ECPGt_struct && p->type->typ != ECPGt_union)
+ {
+ sprintf(errortext, "variable %s is neither a structure nor a union", name);
+ mmerror(ET_FATAL, errortext);
+ }
+
+ /* restore the name, we will need it later on */
+ *next = c;
+
+ return find_struct_member(name, next, p->type->u.members);
+ }
}
static struct variable *
if (p == NULL)
{
sprintf(errortext, "The variable %s is not declared", name);
- yyerror(errortext);
+ mmerror(ET_FATAL, errortext);
}
return(p);
break;
case ECPGt_struct:
+ case ECPGt_union:
for (p = var->u.members; p; p = p->next)
check_indicator(p->typ);
break;
check_indicator(var->u.element);
break;
default:
- yyerror ("indicator variable must be integer type");
+ mmerror(ET_ERROR, "indicator variable must be integer type");
break;
}
}
-static char *
-make1_str(const char *str)
-{
- char * res_str = (char *)mm_alloc(strlen(str) + 1);
+/*
+ * descriptor name lookup
+ */
+
+static struct descriptor *descriptors;
- strcpy(res_str, str);
- return res_str;
+static void add_descriptor(char *name,char *connection)
+{
+ struct descriptor *new=(struct descriptor *)mm_alloc(sizeof(struct descriptor));
+
+ new->next=descriptors;
+ new->name=mm_alloc(strlen(name)+1);
+ strcpy(new->name,name);
+ if (connection)
+ { new->connection=mm_alloc(strlen(connection)+1);
+ strcpy(new->connection,connection);
+ }
+ else new->connection=connection;
+ descriptors=new;
}
-static char *
-make2_str(char *str1, char *str2)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
+static void drop_descriptor(char *name,char *connection)
+{ struct descriptor *i;
+ struct descriptor **lastptr=&descriptors;
+ for (i=descriptors;i;lastptr=&i->next,i=i->next)
+ { if (!strcmp(name,i->name))
+ { if ((!connection && !i->connection)
+ || (connection && i->connection
+ && !strcmp(connection,i->connection)))
+ { *lastptr=i->next;
+ if (i->connection) free(i->connection);
+ free(i->name);
+ free(i);
+ return;
+ }
+ }
+ }
+ snprintf(errortext,sizeof errortext,"unknown descriptor %s",name);
+ mmerror(ET_WARN,errortext);
+}
- strcpy(res_str, str1);
- strcat(res_str, str2);
- free(str1);
- free(str2);
- return(res_str);
+static struct descriptor *lookup_descriptor(char *name,char *connection)
+{ struct descriptor *i;
+ for (i=descriptors;i;i=i->next)
+ { if (!strcmp(name,i->name))
+ { if ((!connection && !i->connection)
+ || (connection && i->connection
+ && !strcmp(connection,i->connection)))
+ { return i;
+ }
+ }
+ }
+ snprintf(errortext,sizeof errortext,"unknown descriptor %s",name);
+ mmerror(ET_WARN,errortext);
+ return NULL;
}
+/*
+ * string concatenation
+ */
+
static char *
cat2_str(char *str1, char *str2)
{
}
static char *
-make3_str(char *str1, char *str2, char * str3)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
-
- strcpy(res_str, str1);
- strcat(res_str, str2);
- strcat(res_str, str3);
- free(str1);
- free(str2);
- free(str3);
- return(res_str);
-}
+cat_str(int count, ...)
+{
+ va_list args;
+ int i;
+ char *res_str;
-static char *
-cat3_str(char *str1, char *str2, char * str3)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 3);
-
- strcpy(res_str, str1);
- strcat(res_str, " ");
- strcat(res_str, str2);
- strcat(res_str, " ");
- strcat(res_str, str3);
- free(str1);
- free(str2);
- free(str3);
- return(res_str);
-}
+ va_start(args, count);
-static char *
-make4_str(char *str1, char *str2, char *str3, char *str4)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + strlen(str4) + 1);
-
- strcpy(res_str, str1);
- strcat(res_str, str2);
- strcat(res_str, str3);
- strcat(res_str, str4);
- free(str1);
- free(str2);
- free(str3);
- free(str4);
- return(res_str);
+ res_str = va_arg(args, char *);
+
+ /* now add all other strings */
+ for (i = 1; i < count; i++)
+ res_str = cat2_str(res_str, va_arg(args, char *));
+
+ va_end(args);
+
+ return(res_str);
}
static char *
-cat4_str(char *str1, char *str2, char *str3, char *str4)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + strlen(str4) + 4);
-
- strcpy(res_str, str1);
- strcat(res_str, " ");
- strcat(res_str, str2);
- strcat(res_str, " ");
- strcat(res_str, str3);
- strcat(res_str, " ");
- strcat(res_str, str4);
- free(str1);
- free(str2);
- free(str3);
- free(str4);
- return(res_str);
+make_str(const char *str)
+{
+ char * res_str = (char *)mm_alloc(strlen(str) + 1);
+
+ strcpy(res_str, str);
+ return res_str;
}
static char *
-make5_str(char *str1, char *str2, char *str3, char *str4, char *str5)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + strlen(str4) + strlen(str5) + 1);
-
- strcpy(res_str, str1);
- strcat(res_str, str2);
- strcat(res_str, str3);
- strcat(res_str, str4);
- strcat(res_str, str5);
+make2_str(char *str1, char *str2)
+{
+ char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
+
+ strcpy(res_str, str1);
+ strcat(res_str, str2);
free(str1);
free(str2);
- free(str3);
- free(str4);
- free(str5);
- return(res_str);
-}
+ return(res_str);
+}
static char *
-cat5_str(char *str1, char *str2, char *str3, char *str4, char *str5)
-{
- char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + strlen(str4) + strlen(str5) + 5);
-
- strcpy(res_str, str1);
- strcat(res_str, " ");
- strcat(res_str, str2);
- strcat(res_str, " ");
+make3_str(char *str1, char *str2, char *str3)
+{
+ char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
+
+ strcpy(res_str, str1);
+ strcat(res_str, str2);
strcat(res_str, str3);
- strcat(res_str, " ");
- strcat(res_str, str4);
- strcat(res_str, " ");
- strcat(res_str, str5);
free(str1);
free(str2);
free(str3);
- free(str4);
- free(str5);
- return(res_str);
-}
+ return(res_str);
+}
static char *
make_name(void)
return(name);
}
+static char *
+hashline_number()
+{
+ if (input_filename)
+ {
+ char* line = mm_alloc(strlen("\n#line %d \"%s\"\n") + 21 + strlen(input_filename));
+ sprintf(line, "\n#line %d \"%s\"\n", yylineno, input_filename);
+
+ return line;
+ }
+
+ return EMPTY;
+}
+
static void
output_statement(char * stmt, int mode)
{
int i, j=strlen(stmt);
- fputs("ECPGdo(__LINE__, \"", yyout);
+ fprintf(yyout, "{ ECPGdo(__LINE__, %s, \"", connection ? connection : "NULL");
/* do this char by char as we have to filter '\"' */
- for (i = 0;i < j; i++)
+ for (i = 0;i < j; i++) {
if (stmt[i] != '\"')
fputc(stmt[i], yyout);
+ else
+ fputs("\\\"", yyout);
+ }
+
fputs("\", ", yyout);
/* dump variables to C file*/
fputs("ECPGt_EOIT, ", yyout);
dump_variables(argsresult, 1);
fputs("ECPGt_EORT);", yyout);
+ mode |= 2;
whenever_action(mode);
free(stmt);
+ if (connection != NULL)
+ free(connection);
}
-%}
-
-%union {
- double dval;
- int ival;
- char * str;
- struct when action;
- struct index index;
- int tagname;
- struct this_type type;
- enum ECPGttype type_enum;
-}
+static void
+output_statement_desc(char * stmt, int mode)
+{
+ int i, j=strlen(stmt);
-/* special embedded SQL token */
-%token SQL_BREAK SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE
-%token SQL_DISCONNECT SQL_FOUND SQL_GO SQL_GOTO
-%token SQL_IDENTIFIED SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN SQL_RELEASE
-%token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
-%token SQL_STOP SQL_WHENEVER
+ fprintf(yyout, "{ ECPGdo_descriptor(__LINE__, %s, \"%s\", \"",
+ connection ? connection : "NULL", descriptor_name);
-/* C token */
-%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN
-%token S_FLOAT S_INT S
-%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
-%token S_UNSIGNED S_VARCHAR
+ /* do this char by char as we have to filter '\"' */
+ for (i = 0;i < j; i++) {
+ if (stmt[i] != '\"')
+ fputc(stmt[i], yyout);
+ else
+ fputs("\\\"", yyout);
+ }
-/* I need this and don't know where it is defined inside the backend */
-%token TYPECAST
+ fputs("\");", yyout);
-/* Keywords (in SQL92 reserved words) */
-%token ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC,
- BEGIN_TRANS, BETWEEN, BOTH, BY,
- CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
- COALESCE, COLLATE, COLUMN, COMMIT,
- CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME,
- CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
- DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
- ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
- FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
- GRANT, GROUP, HAVING, HOUR_P,
- IN, INNER_P, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO, IS,
- ISOLATION, JOIN, KEY, LANGUAGE, LEADING, LEFT, LEVEL, LIKE, LOCAL,
- MATCH, MINUTE_P, MONTH_P, NAMES,
- NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC,
- OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P,
- PARTIAL, POSITION, PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE, PUBLIC,
- READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
- SCROLL, SECOND_P, SELECT, SET, SUBSTRING,
- TABLE, THEN, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE,
- TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
- UNION, UNIQUE, UPDATE, USER, USING,
- VALUES, VARCHAR, VARYING, VIEW,
- WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
+ mode |= 2;
+ whenever_action(mode);
+ free(stmt);
+ if (connection != NULL)
+ free(connection);
+ free(descriptor_name);
+}
-/* Keywords (in SQL3 reserved words) */
-%token TRIGGER
+static struct typedefs *
+get_typedef(char *name)
+{
+ struct typedefs *this;
+
+ for (this = types; this && strcmp(this->name, name); this = this->next);
+ if (!this)
+ {
+ sprintf(errortext, "invalid datatype '%s'", name);
+ mmerror(ET_FATAL, errortext);
+ }
+
+ return(this);
+}
+
+static void
+adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dimension, int type_index, bool pointer)
+{
+ if (type_index >= 0)
+ {
+ if (*length >= 0)
+ mmerror(ET_FATAL, "No multi-dimensional array support");
+
+ *length = type_index;
+ }
+
+ if (type_dimension >= 0)
+ {
+ if (*dimension >= 0 && *length >= 0)
+ mmerror(ET_FATAL, "No multi-dimensional array support");
+
+ if (*dimension >= 0)
+ *length = *dimension;
+
+ *dimension = type_dimension;
+ }
+
+ if (*length >= 0 && *dimension >= 0 && pointer)
+ mmerror(ET_FATAL, "No multi-dimensional array support");
+
+ switch (type_enum)
+ {
+ case ECPGt_struct:
+ case ECPGt_union:
+ /* pointer has to get dimension 0 */
+ if (pointer)
+ {
+ *length = *dimension;
+ *dimension = 0;
+ }
+
+ if (*length >= 0)
+ mmerror(ET_FATAL, "No multi-dimensional array support for structures");
+
+ break;
+ case ECPGt_varchar:
+ /* pointer has to get dimension 0 */
+ if (pointer)
+ *dimension = 0;
+
+ /* one index is the string length */
+ if (*length < 0)
+ {
+ *length = *dimension;
+ *dimension = -1;
+ }
+
+ break;
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ /* pointer has to get length 0 */
+ if (pointer)
+ *length=0;
+
+ /* one index is the string length */
+ if (*length < 0)
+ {
+ *length = (*dimension < 0) ? 1 : *dimension;
+ *dimension = -1;
+ }
+
+ break;
+ default:
+ /* a pointer has dimension = 0 */
+ if (pointer) {
+ *length = *dimension;
+ *dimension = 0;
+ }
+
+ if (*length >= 0)
+ mmerror(ET_FATAL, "No multi-dimensional array support for simple data types");
+
+ break;
+ }
+}
+
+%}
+
+%union {
+ double dval;
+ int ival;
+ char * str;
+ struct when action;
+ struct index index;
+ int tagname;
+ struct this_type type;
+ enum ECPGttype type_enum;
+}
+
+/* special embedded SQL token */
+%token SQL_ALLOCATE SQL_AT SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
+%token SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE
+%token SQL_DEALLOCATE SQL_DESCRIPTOR SQL_DISCONNECT SQL_ENUM
+%token SQL_FOUND SQL_FREE SQL_GET SQL_GO SQL_GOTO
+%token SQL_IDENTIFIED SQL_INDICATOR SQL_INT SQL_LONG
+%token SQL_OFF SQL_OPEN SQL_PREPARE SQL_RELEASE SQL_REFERENCE
+%token SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL
+%token SQL_SQLERROR SQL_SQLPRINT
+%token SQL_SQLWARNING SQL_START SQL_STOP SQL_STRUCT SQL_UNSIGNED
+%token SQL_VALUE SQL_VAR SQL_WHENEVER
+
+/* C token */
+%token S_ANYTHING S_AUTO S_CONST S_EXTERN
+%token S_REGISTER S_STATIC S_VOLATILE
+
+/* I need this and don't know where it is defined inside the backend */
+%token TYPECAST
+
+/* Keywords (in SQL92 reserved words) */
+%token ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC,
+ BEGIN_TRANS, BETWEEN, BOTH, BY,
+ CASCADE, CASE, CAST, CHAR, CHARACTER, CHECK, CLOSE,
+ COALESCE, COLLATE, COLUMN, COMMIT,
+ CONSTRAINT, CONSTRAINTS, CREATE, CROSS, CURRENT, CURRENT_DATE,
+ CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR,
+ DAY_P, DEC, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP,
+ ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
+ FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
+ GLOBAL, GRANT, GROUP, HAVING, HOUR_P,
+ IN, INNER_P, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO, IS,
+ ISOLATION, JOIN, KEY, LANGUAGE, LEADING, LEFT, LEVEL, LIKE, LOCAL,
+ MATCH, MINUTE_P, MONTH_P, NAMES,
+ NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC,
+ OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P,
+ PARTIAL, POSITION, PRECISION, PRIMARY, PRIOR, PRIVILEGES, PROCEDURE, PUBLIC,
+ READ, REFERENCES, RELATIVE, REVOKE, RIGHT, ROLLBACK,
+ SCROLL, SECOND_P, SELECT, SESSION_USER, SET, SUBSTRING,
+ TABLE, TEMP, TEMPORARY, THEN, TIME, TIMESTAMP, TIMEZONE_HOUR,
+ TIMEZONE_MINUTE, TO, TRAILING, TRANSACTION, TRIM, TRUE_P,
+ UNION, UNIQUE, UPDATE, USER, USING,
+ VALUES, VARCHAR, VARYING, VIEW,
+ WHEN, WHERE, WITH, WORK, YEAR_P, ZONE
+
+/* Keywords (in SQL3 reserved words) */
+%token DEFERRABLE, DEFERRED,
+ IMMEDIATE, INITIALLY,
+ PENDANT,
+ RESTRICT,
+ TRIGGER
/* Keywords (in SQL92 non-reserved words) */
-%token TYPE_P
+%token COMMITTED, SERIALIZABLE, TYPE_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
* when some sort of pg_privileges relation is introduced.
* - Todd A. Brandys 1998-01-01?
*/
-%token ABORT_TRANS, AFTER, AGGREGATE, ANALYZE, BACKWARD, BEFORE, BINARY,
- CACHE, CLUSTER, COPY, CREATEDB, CREATEUSER, CYCLE,
- DATABASE, DELIMITERS, DO, EACH, ENCODING, EXPLAIN, EXTEND,
+%token ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYZE,
+ BACKWARD, BEFORE, BINARY,
+ CACHE, CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
+ DATABASE, DELIMITERS, DO,
+ EACH, ENCODING, EXCLUSIVE, EXPLAIN, EXTEND,
FORWARD, FUNCTION, HANDLER,
INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
- LANCOMPILER, LISTEN, UNLISTEN, LOAD, LOCATION, LOCK_P, MAXVALUE, MINVALUE, MOVE,
+ LANCOMPILER, LIMIT, LISTEN, UNLISTEN, LOAD, LOCATION, LOCK_P,
+ MAXVALUE, MINVALUE, MODE, MOVE,
NEW, NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY, NOTNULL,
- OIDS, OPERATOR, PASSWORD, PROCEDURAL,
- RECIPE, RENAME, RESET, RETURNS, ROW, RULE,
- SERIAL, SEQUENCE, SETOF, SHOW, START, STATEMENT, STDIN, STDOUT, TRUSTED,
+ OFFSET, OIDS, OPERATOR, PASSWORD, PROCEDURAL,
+ RENAME, RESET, RETURNS, ROW, RULE,
+ SEQUENCE, SERIAL, SETOF, SHARE, SHOW, START, STATEMENT, STDIN, STDOUT, SYSID
+ TRUNCATE, TRUSTED,
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
/* Special keywords, not in the query language - see the "lex" file */
%nonassoc LIKE
%nonassoc BETWEEN
%nonassoc IN
-%nonassoc Op /* multi-character ops and user-defined operators */
+%left Op /* multi-character ops and user-defined operators */
%nonassoc NOTNULL
%nonassoc ISNULL
+%nonassoc NULL_P
%nonassoc IS
%left '+' '-'
-%left '*' '/'
+%left '*' '/' '%'
+%left '^'
%left '|' /* this is the relation union op, not logical or */
/* Unary Operators */
%right ':'
%right UMINUS
%left '.'
%left '[' ']'
-%nonassoc TYPECAST
+%left TYPECAST
%left UNION INTERSECT EXCEPT
%type <str> Iconst Fconst Sconst TransactionStmt CreateStmt UserId
%type <str> CreateAsElement OptCreateAs CreateAsList CreateAsStmt
-%type <str> OptInherit key_reference key_action
-%type <str> key_match constraint_expr ColLabel SpecialRuleRelation
-%type <str> ColId default_expr ColQualifier columnDef ColQualList
-%type <str> ColConstraint ColConstraintElem default_list NumericOnly FloatOnly
+%type <str> OptInherit key_reference key_action comment_text
+%type <str> key_match ColLabel SpecialRuleRelation ColId columnDef
+%type <str> ColConstraint ColConstraintElem NumericOnly FloatOnly
%type <str> OptTableElementList OptTableElement TableConstraint
-%type <str> ConstraintElem key_actions constraint_list ColPrimaryKey
-%type <str> res_target_list res_target_el res_target_list2
-%type <str> res_target_el2 opt_id relation_name database_name
+%type <str> ConstraintElem key_actions ColPrimaryKey ColQualList
+%type <str> target_list target_el update_target_list alias_clause
+%type <str> update_target_el opt_id relation_name database_name
%type <str> access_method attr_name class index_name name func_name
-%type <str> file_name recipe_name AexprConst ParamNo TypeId
-%type <str> in_expr_nodes not_in_expr_nodes a_expr b_expr
+%type <str> file_name AexprConst ParamNo TypeId c_expr ColQualListWithNull
+%type <str> in_expr_nodes a_expr b_expr TruncateStmt CommentStmt
%type <str> opt_indirection expr_list extract_list extract_arg
-%type <str> position_list position_expr substr_list substr_from
-%type <str> trim_list in_expr substr_for not_in_expr attr attrs
-%type <str> Typename Array Generic Numeric generic opt_float opt_numeric
+%type <str> position_list substr_list substr_from alter_column_action
+%type <str> trim_list in_expr substr_for attr attrs drop_behavior
+%type <str> Typename SimpleTypename Generic Numeric generic opt_float opt_numeric
%type <str> opt_decimal Character character opt_varying opt_charset
%type <str> opt_collate Datetime datetime opt_timezone opt_interval
%type <str> numeric a_expr_or_null row_expr row_descriptor row_list
-%type <str> SelectStmt SubSelect result
-%type <str> opt_table opt_union opt_unique sort_clause sortby_list
+%type <str> SelectStmt SubSelect result OptTemp OptTempType OptTempScope
+%type <str> opt_table opt_all sort_clause sortby_list ColQualifier
%type <str> sortby OptUseOp opt_inh_star relation_name_list name_list
-%type <str> group_clause having_clause from_clause c_list
-%type <str> from_list from_val join_expr join_outer join_spec join_list
-%type <str> join_using where_clause relation_expr row_op sub_type
+%type <str> group_clause having_clause from_clause opt_distinct
+%type <str> join_outer where_clause relation_expr sub_type
%type <str> opt_column_list insert_rest InsertStmt OptimizableStmt
%type <str> columnList DeleteStmt LockStmt UpdateStmt CursorStmt
-%type <str> NotifyStmt columnElem copy_dirn c_expr UnlistenStmt
+%type <str> NotifyStmt columnElem copy_dirn UnlistenStmt copy_null
%type <str> copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
-%type <str> opt_with_copy FetchStmt opt_direction fetch_how_many opt_portal_name
-%type <str> ClosePortalStmt DestroyStmt VacuumStmt opt_verbose
+%type <str> opt_with_copy FetchStmt direction fetch_how_many from_in
+%type <str> ClosePortalStmt DropStmt VacuumStmt opt_verbose
%type <str> opt_analyze opt_va_list va_list ExplainStmt index_params
%type <str> index_list func_index index_elem opt_type opt_class access_method_clause
%type <str> index_opt_unique IndexStmt set_opt func_return def_rest
%type <str> func_args_list func_args opt_with ProcedureStmt def_arg
%type <str> def_elem def_list definition def_name def_type DefineStmt
-%type <str> opt_instead event event_object OptStmtMulti OptStmtBlock
-%type <str> OptStmtList RuleStmt opt_column opt_name oper_argtypes
+%type <str> opt_instead event event_object RuleActionList opt_using
+%type <str> RuleActionStmtOrEmpty RuleActionMulti func_as
+%type <str> RuleStmt opt_column opt_name oper_argtypes sysid_clause
%type <str> MathOp RemoveFuncStmt aggr_argtype for_update_clause
-%type <str> RemoveAggrStmt remove_type RemoveStmt ExtendStmt RecipeStmt
+%type <str> RemoveAggrStmt remove_type RemoveStmt ExtendStmt
%type <str> RemoveOperStmt RenameStmt all_Op user_valid_clause
%type <str> VariableSetStmt var_value zone_value VariableShowStmt
-%type <str> VariableResetStmt AddAttrStmt alter_clause DropUserStmt
+%type <str> VariableResetStmt AlterTableStmt DropUserStmt from_list
%type <str> user_passwd_clause user_createdb_clause opt_trans
-%type <str> user_createuser_clause user_group_list user_group_clause
+%type <str> user_createuser_clause user_list user_group_clause
%type <str> CreateUserStmt AlterUserStmt CreateSeqStmt OptSeqList
%type <str> OptSeqElem TriggerForSpec TriggerForOpt TriggerForType
-%type <str> DropTrigStmt TriggerOneEvent TriggerEvents
+%type <str> DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt
%type <str> TriggerActionTime CreateTrigStmt DropPLangStmt PLangTrusted
%type <str> CreatePLangStmt IntegerOnly TriggerFuncArgs TriggerFuncArg
-%type <str> ViewStmt LoadStmt CreatedbStmt opt_database1 opt_database2 location
-%type <str> DestroydbStmt ClusterStmt grantee RevokeStmt encoding
+%type <str> ViewStmt LoadStmt CreatedbStmt createdb_opt_encoding
+%type <str> createdb_opt_location opt_encoding AlterTableStmt
+%type <str> DropdbStmt ClusterStmt grantee RevokeStmt table_expr
%type <str> GrantStmt privileges operation_commalist operation
-%type <str> cursor_clause opt_cursor opt_readonly opt_of opt_lmode
+%type <str> opt_cursor opt_lmode ConstraintsSetStmt comment_tg
%type <str> case_expr when_clause_list case_default case_arg when_clause
-%type <str> select_w_o_sort
+%type <str> select_clause opt_select_limit select_limit_value
+%type <str> select_offset_value using_expr join_expr
+%type <str> using_list from_expr join_clause join_type
+%type <str> join_qual update_list join_clause join_clause_with_union
+%type <str> opt_level opt_lock lock_type users_in_new_group_clause
+%type <str> OptConstrFromTable comment_op ConstraintAttributeSpec
+%type <str> constraints_set_list constraints_set_namelist comment_fn
+%type <str> constraints_set_mode comment_type comment_cl comment_ag
+%type <str> ConstraintDeferrabilitySpec ConstraintTimeSpec
+%type <str> CreateGroupStmt AlterGroupStmt DropGroupStmt
+%type <str> ColConstraintWithNull ColConstraintElemWithNull
+%type <str> join_expr_with_union
+/***
+#ifdef ENABLE_ORACLE_JOIN_SYNTAX
+%type <str> oracle_list oracle_expr oracle_outer
+#endif
+***/
-%type <str> ECPGWhenever ECPGConnect connection_target ECPGOpen open_opts
-%type <str> indicator ECPGExecute ecpg_expr dotext
-%type <str> storage_clause opt_initializer vartext c_anything blockstart
-%type <str> blockend variable_list variable var_anything do_anything
-%type <str> opt_pointer cvariable ECPGDisconnect dis_name
+%type <str> ECPGWhenever ECPGConnect connection_target ECPGOpen
+%type <str> indicator ECPGExecute ECPGPrepare ecpg_using
+%type <str> storage_clause opt_initializer c_anything blockstart
+%type <str> blockend variable_list variable c_thing c_term
+%type <str> opt_pointer cvariable ECPGDisconnect dis_name storage_modifier
%type <str> stmt symbol opt_symbol ECPGRelease execstring server_name
-%type <str> connection_object opt_server opt_port c_thing
+%type <str> connection_object opt_server opt_port c_stuff opt_reference
%type <str> user_name opt_user char_variable ora_user ident
-%type <str> db_prefix server opt_options opt_connection_name
-%type <str> ECPGSetConnection c_line cpp_line s_enum
-%type <str> enum_type
-
-%type <type_enum> simple_type
+%type <str> db_prefix server opt_options opt_connection_name c_list
+%type <str> ECPGSetConnection cpp_line ECPGTypedef c_args
+%type <str> enum_type civariableonly ECPGCursorStmt ECPGDeallocate
+%type <str> ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
+%type <str> struct_type s_struct declaration declarations variable_declarations
+%type <str> s_struct s_union union_type ECPGSetAutocommit on_off
+%type <str> ECPGAllocateDescr ECPGDeallocateDescr
+%type <str> ECPGGetDescriptor ECPGGetDescriptorHeader
+%type <str> FetchDescriptorStmt
+
+%type <type_enum> simple_type signed_type unsigned_type varchar_type
%type <type> type
%type <action> action
-%type <index> opt_array_bounds nest_array_bounds
+%type <index> opt_array_bounds opt_type_array_bounds
+%type <ival> Iresult
%%
prog: statements;
statements: /* empty */
| statements statement
-statement: ecpgstart stmt SQL_SEMI
+statement: ecpgstart opt_at stmt ';' { connection = NULL; }
+ | ecpgstart stmt ';'
| ECPGDeclaration
| c_thing { fprintf(yyout, "%s", $1); free($1); }
| cpp_line { fprintf(yyout, "%s", $1); free($1); }
| blockstart { fputs($1, yyout); free($1); }
| blockend { fputs($1, yyout); free($1); }
-stmt: AddAttrStmt { output_statement($1, 0); }
+opt_at: SQL_AT connection_target { connection = $2; }
+
+stmt: AlterTableStmt { output_statement($1, 0); }
+ | AlterGroupStmt { output_statement($1, 0); }
| AlterUserStmt { output_statement($1, 0); }
| ClosePortalStmt { output_statement($1, 0); }
+ | CommentStmt { output_statement($1, 0); }
| CopyStmt { output_statement($1, 0); }
| CreateStmt { output_statement($1, 0); }
| CreateAsStmt { output_statement($1, 0); }
+ | CreateGroupStmt { output_statement($1, 0); }
| CreateSeqStmt { output_statement($1, 0); }
| CreatePLangStmt { output_statement($1, 0); }
| CreateTrigStmt { output_statement($1, 0); }
| CreateUserStmt { output_statement($1, 0); }
| ClusterStmt { output_statement($1, 0); }
| DefineStmt { output_statement($1, 0); }
- | DestroyStmt { output_statement($1, 0); }
+ | DropStmt { output_statement($1, 0); }
+ | TruncateStmt { output_statement($1, 0); }
+ | DropGroupStmt { output_statement($1, 0); }
| DropPLangStmt { output_statement($1, 0); }
| DropTrigStmt { output_statement($1, 0); }
| DropUserStmt { output_statement($1, 0); }
| ExtendStmt { output_statement($1, 0); }
| ExplainStmt { output_statement($1, 0); }
| FetchStmt { output_statement($1, 1); }
+ | FetchDescriptorStmt { output_statement_desc($1, 1); }
| GrantStmt { output_statement($1, 0); }
| IndexStmt { output_statement($1, 0); }
| ListenStmt { output_statement($1, 0); }
| UnlistenStmt { output_statement($1, 0); }
| LockStmt { output_statement($1, 0); }
| ProcedureStmt { output_statement($1, 0); }
- | RecipeStmt { output_statement($1, 0); }
| RemoveAggrStmt { output_statement($1, 0); }
| RemoveOperStmt { output_statement($1, 0); }
| RemoveFuncStmt { output_statement($1, 0); }
| RevokeStmt { output_statement($1, 0); }
| OptimizableStmt {
if (strncmp($1, "/* " , sizeof("/* ")-1) == 0)
- {
- fputs($1, yyout);
- free($1);
- }
+ output_simple_statement($1);
else
output_statement($1, 1);
}
| RuleStmt { output_statement($1, 0); }
| TransactionStmt {
- fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1);
- whenever_action(0);
+ fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
+ whenever_action(2);
free($1);
}
| ViewStmt { output_statement($1, 0); }
| LoadStmt { output_statement($1, 0); }
| CreatedbStmt { output_statement($1, 0); }
- | DestroydbStmt { output_statement($1, 0); }
+ | DropdbStmt { output_statement($1, 0); }
| VacuumStmt { output_statement($1, 0); }
| VariableSetStmt { output_statement($1, 0); }
| VariableShowStmt { output_statement($1, 0); }
| VariableResetStmt { output_statement($1, 0); }
+ | ConstraintsSetStmt { output_statement($1, 0); }
+ | ECPGAllocateDescr { fprintf(yyout,"ECPGallocate_desc(__LINE__, \"%s\");",$1);
+ whenever_action(0);
+ free($1);
+ }
| ECPGConnect {
- fprintf(yyout, "no_auto_trans = %d;\n", no_auto_trans);
- fprintf(yyout, "ECPGconnect(__LINE__, %s);", $1);
- whenever_action(0);
+ if (connection)
+ mmerror(ET_ERROR, "no at option for connect statement.\n");
+
+ fprintf(yyout, "{ ECPGconnect(__LINE__, %s, %d);", $1, autocommit);
+ whenever_action(2);
free($1);
}
+ | ECPGCursorStmt {
+ output_simple_statement($1);
+ }
+ | ECPGDeallocate {
+ if (connection)
+ mmerror(ET_ERROR, "no at option for connect statement.\n");
+
+ fputc('{', yyout);
+ fputs($1, yyout);
+ whenever_action(2);
+ free($1);
+ }
+ | ECPGDeallocateDescr { fprintf(yyout,"ECPGdeallocate_desc(__LINE__, \"%s\");",$1);
+ whenever_action(0);
+ free($1);
+ }
+ | ECPGDeclare {
+ output_simple_statement($1);
+ }
| ECPGDisconnect {
- fprintf(yyout, "ECPGdisconnect(__LINE__, \"%s\");", $1);
- whenever_action(0);
+ if (connection)
+ mmerror(ET_ERROR, "no at option for disconnect statement.\n");
+
+ fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"%s\");", $1);
+ whenever_action(2);
free($1);
}
| ECPGExecute {
- fprintf(yyout, "ECPGdo(__LINE__, %s, ECPGt_EOIT, ECPGt_EORT);", $1);
- whenever_action(0);
+ output_statement($1, 0);
+ }
+ | ECPGFree {
+ fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
+
+ whenever_action(2);
free($1);
}
+ | ECPGGetDescriptor {
+ lookup_descriptor($1,connection);
+ output_get_descr($1);
+ }
+ | ECPGGetDescriptorHeader {
+ lookup_descriptor($1,connection);
+ output_get_descr_header($1);
+ }
| ECPGOpen {
struct cursor *ptr;
if (ptr == NULL)
{
sprintf(errortext, "trying to open undeclared cursor %s\n", $1);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command);
+ fprintf(yyout, "{ ECPGdo(__LINE__, %s, \"%s\",", ptr->connection ? ptr->connection : "NULL", ptr->command);
/* dump variables to C file*/
dump_variables(ptr->argsinsert, 0);
+ dump_variables(argsinsert, 0);
fputs("ECPGt_EOIT, ", yyout);
dump_variables(ptr->argsresult, 0);
fputs("ECPGt_EORT);", yyout);
- whenever_action(0);
+ whenever_action(2);
+ free($1);
+ }
+ | ECPGPrepare {
+ if (connection)
+ mmerror(ET_ERROR, "no at option for set connection statement.\n");
+
+ fprintf(yyout, "{ ECPGprepare(__LINE__, %s);", $1);
+ whenever_action(2);
free($1);
}
| ECPGRelease { /* output already done */ }
+ | ECPGSetAutocommit {
+ fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
+ whenever_action(2);
+ free($1);
+ }
| ECPGSetConnection {
- fprintf(yyout, "ECPGsetconn(__LINE__, %s);", $1);
- whenever_action(0);
+ if (connection)
+ mmerror(ET_ERROR, "no at option for set connection statement.\n");
+
+ fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
+ whenever_action(2);
free($1);
}
+ | ECPGTypedef {
+ if (connection)
+ mmerror(ET_ERROR, "no at option for typedef statement.\n");
+
+ output_simple_statement($1);
+ }
+ | ECPGVar {
+ if (connection)
+ mmerror(ET_ERROR, "no at option for var statement.\n");
+
+ output_simple_statement($1);
+ }
| ECPGWhenever {
- fputs($1, yyout);
- output_line_number();
- free($1);
+ if (connection)
+ mmerror(ET_ERROR, "no at option for whenever statement.\n");
+
+ output_simple_statement($1);
}
+ ;
+
/*
* We start with a lot of stuff that's very similar to the backend's parsing
*
*****************************************************************************/
-CreateUserStmt: CREATE USER UserId user_passwd_clause user_createdb_clause
- user_createuser_clause user_group_clause user_valid_clause
+CreateUserStmt: CREATE USER UserId
+ user_createdb_clause user_createuser_clause user_group_clause
+ user_valid_clause
{
- $$ = cat3_str(cat5_str(make1_str("create user"), $3, $4, $5, $6), $7, $8);
+ $$ = cat_str(6, make_str("create user"), $3, $4, $5, $6, $7);
}
+ | CREATE USER UserId WITH sysid_clause user_passwd_clause
+ user_createdb_clause user_createuser_clause user_group_clause
+ user_valid_clause
+ {
+ $$ = cat_str(9, make_str("create user"), $3, make_str("with"), $5, $6, $7, $8, $9, $10);
+ }
;
/*****************************************************************************
*
- * Alter a postresql DBMS user
+ * Alter a postgresql DBMS user
*
*
*****************************************************************************/
-AlterUserStmt: ALTER USER UserId user_passwd_clause user_createdb_clause
- user_createuser_clause user_group_clause user_valid_clause
+AlterUserStmt: ALTER USER UserId user_createdb_clause
+ user_createuser_clause user_valid_clause
+ {
+ $$ = cat_str(5, make_str("alter user"), $3, $4, $5, $6);
+ }
+ | ALTER USER UserId WITH PASSWORD Sconst
+ user_createdb_clause
+ user_createuser_clause user_valid_clause
{
- $$ = cat3_str(cat5_str(make1_str("alter user"), $3, $4, $5, $6), $7, $8);
+ $$ = cat_str(7, make_str("alter user"), $3, make_str("with password"), $6, $7, $8, $9);
}
;
/*****************************************************************************
*
- * Drop a postresql DBMS user
+ * Drop a postgresql DBMS user
*
*
*****************************************************************************/
-DropUserStmt: DROP USER UserId
+DropUserStmt: DROP USER user_list
{
- $$ = cat2_str(make1_str("drop user"), $3);
+ $$ = cat2_str(make_str("drop user"), $3);
}
;
-user_passwd_clause: WITH PASSWORD UserId { $$ = cat2_str(make1_str("with password") , $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+user_passwd_clause: PASSWORD Sconst { $$ = cat2_str(make_str("password") , $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
+sysid_clause: SYSID Iconst { if (atoi($2) <= 0)
+ mmerror(ET_ERROR, "sysid must be positive");
+
+ $$ = cat2_str(make_str("sysid"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
+ ;
+
user_createdb_clause: CREATEDB
{
- $$ = make1_str("createdb");
+ $$ = make_str("createdb");
}
| NOCREATEDB
{
- $$ = make1_str("nocreatedb");
+ $$ = make_str("nocreatedb");
}
- | /*EMPTY*/ { $$ = make1_str(""); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
user_createuser_clause: CREATEUSER
{
- $$ = make1_str("createuser");
+ $$ = make_str("createuser");
}
| NOCREATEUSER
{
- $$ = make1_str("nocreateuser");
+ $$ = make_str("nocreateuser");
}
| /*EMPTY*/ { $$ = NULL; }
;
-user_group_list: user_group_list ',' UserId
+user_list: user_list ',' UserId
{
- $$ = cat3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
| UserId
{
}
;
-user_group_clause: IN GROUP user_group_list { $$ = cat2_str(make1_str("in group"), $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+user_group_clause: IN GROUP user_list
+ {
+ $$ = cat2_str(make_str("in group"), $3);
+ }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-user_valid_clause: VALID UNTIL Sconst { $$ = cat2_str(make1_str("valid until"), $3);; }
- | /*EMPTY*/ { $$ = make1_str(""); }
+user_valid_clause: VALID UNTIL Sconst { $$ = cat2_str(make_str("valid until"), $3); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
+
+/*****************************************************************************
+ *
+ * Create a postgresql group
+ *
+ *
+ ****************************************************************************/
+CreateGroupStmt: CREATE GROUP UserId
+ {
+ $$ = cat2_str(make_str("create group"), $3);
+ }
+ | CREATE GROUP UserId WITH sysid_clause users_in_new_group_clause
+ {
+ $$ = cat_str(5, make_str("create group"), $3, make_str("with"), $5, $6);
+ }
+ ;
+
+users_in_new_group_clause: USER user_list { $$ = cat2_str(make_str("user"), $2); }
+ | /* EMPTY */ { $$ = EMPTY; }
+ ;
+
+
+/*****************************************************************************
+ *
+ * Alter a postgresql group
+ *
+ *
+ *****************************************************************************/
+AlterGroupStmt: ALTER GROUP UserId ADD USER user_list
+ {
+ $$ = cat_str(4, make_str("alter group"), $3, make_str("add user"), $6);
+ }
+ | ALTER GROUP UserId DROP USER user_list
+ {
+ $$ = cat_str(4, make_str("alter group"), $3, make_str("drop user"), $6);
+ }
+ ;
+
+/*****************************************************************************
+ *
+ * Drop a postgresql group
+ *
+ *
+ *****************************************************************************/
+DropGroupStmt: DROP GROUP UserId
+ {
+ $$ = cat2_str(make_str("drop group"), $3);
+ }
+ ;
+
+
/*****************************************************************************
*
* Set PG internal variable
VariableSetStmt: SET ColId TO var_value
{
- $$ = cat4_str(make1_str("set"), $2, make1_str("to"), $4);
+ $$ = cat_str(4, make_str("set"), $2, make_str("to"), $4);
}
| SET ColId '=' var_value
{
- $$ = cat4_str(make1_str("set"), $2, make1_str("="), $4);
+ $$ = cat_str(4, make_str("set"), $2, make_str("="), $4);
}
| SET TIME ZONE zone_value
{
- $$ = cat2_str(make1_str("set time zone"), $4);
- }
- | SET TRANSACTION ISOLATION LEVEL READ ColId
- {
- if (strcasecmp($6, "COMMITTED"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $6);
- yyerror(errortext);
- }
-
- $$ = cat2_str(make1_str("set transaction isolation level read"), $6);
+ $$ = cat2_str(make_str("set time zone"), $4);
}
- | SET TRANSACTION ISOLATION LEVEL ColId
+ | SET TRANSACTION ISOLATION LEVEL opt_level
{
- if (strcasecmp($5, "SERIALIZABLE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $5);
- yyerror(errortext);
- }
-
- $$ = cat2_str(make1_str("set transaction isolation level read"), $5);
+ $$ = cat2_str(make_str("set transaction isolation level"), $5);
}
- | SET NAMES encoding
+ | SET NAMES opt_encoding
{
-#ifdef MB
- $$ = cat2_str(make1_str("set names"), $3);
+#ifdef MULTIBYTE
+ $$ = cat2_str(make_str("set names"), $3);
#else
- yyerror("SET NAMES is not supported");
+ mmerror(ET_ERROR, "SET NAMES is not supported.");
#endif
}
;
+opt_level: READ COMMITTED { $$ = make_str("read committed"); }
+ | SERIALIZABLE { $$ = make_str("serializable"); }
+ ;
+
+
var_value: Sconst { $$ = $1; }
- | DEFAULT { $$ = make1_str("default"); }
+ | DEFAULT { $$ = make_str("default"); }
;
zone_value: Sconst { $$ = $1; }
- | DEFAULT { $$ = make1_str("default"); }
- | LOCAL { $$ = make1_str("local"); }
+ | DEFAULT { $$ = make_str("default"); }
+ | LOCAL { $$ = make_str("local"); }
+ ;
+
+opt_encoding: Sconst { $$ = $1; }
+ | DEFAULT { $$ = make_str("default"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
VariableShowStmt: SHOW ColId
{
- $$ = cat2_str(make1_str("show"), $2);
+ $$ = cat2_str(make_str("show"), $2);
}
| SHOW TIME ZONE
{
- $$ = make1_str("show time zone");
+ $$ = make_str("show time zone");
}
| SHOW TRANSACTION ISOLATION LEVEL
{
- $$ = make1_str("show transaction isolation level");
+ $$ = make_str("show transaction isolation level");
}
;
VariableResetStmt: RESET ColId
{
- $$ = cat2_str(make1_str("reset"), $2);
+ $$ = cat2_str(make_str("reset"), $2);
}
| RESET TIME ZONE
{
- $$ = make1_str("reset time zone");
+ $$ = make_str("reset time zone");
}
| RESET TRANSACTION ISOLATION LEVEL
{
- $$ = make1_str("reset transaction isolation level");
+ $$ = make_str("reset transaction isolation level");
}
;
+ConstraintsSetStmt: SET CONSTRAINTS constraints_set_list constraints_set_mode
+ {
+ $$ = cat_str(3, make_str("set constraints"), $3, $4);
+ }
+ ;
+
+constraints_set_list: ALL
+ {
+ $$ = make_str("all");
+ }
+ | constraints_set_namelist
+ {
+ $$ = $1;
+ }
+ ;
+
+
+constraints_set_namelist: IDENT
+ {
+ $$ = $1;
+ }
+ | constraints_set_namelist ',' IDENT
+ {
+ $$ = cat_str(3, $1, make_str(","), $3);
+ }
+ ;
+
+constraints_set_mode: DEFERRED
+ {
+ $$ = make_str("deferred");
+ }
+ | IMMEDIATE
+ {
+ $$ = make_str("immediate");
+ }
+ ;
/*****************************************************************************
*
* QUERY :
- * addattr ( attr1 = type1 .. attrn = typen ) to <relname> [*]
+ *
+ * ALTER TABLE variations
*
*****************************************************************************/
-AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause
- {
- $$ = cat4_str(make1_str("alter table"), $3, $4, $5);
- }
+AlterTableStmt:
+/* ALTER TABLE <name> ADD [COLUMN] <coldef> */
+ ALTER TABLE relation_name opt_inh_star ADD opt_column columnDef
+ {
+ $$ = cat_str(6, make_str("alter table"), $3, $4, make_str("add"), $6, $7);
+ }
+/* ALTER TABLE <name> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP
+DEFAULT} */
+ | ALTER TABLE relation_name opt_inh_star ALTER opt_column ColId
+ alter_column_action
+ {
+ $$ = cat_str(7, make_str("alter table"), $3, $4, make_str("alter"), $6, $7, $8);
+ }
+/* ALTER TABLE <name> DROP [COLUMN] <name> {RESTRICT|CASCADE} */
+ | ALTER TABLE relation_name opt_inh_star DROP opt_column ColId drop_behavior
+ {
+ $$ = cat_str(7, make_str("alter table"), $3, $4, make_str("drop"), $6, $7, $8);
+ }
+/* ALTER TABLE <name> ADD CONSTRAINT ... */
+ | ALTER TABLE relation_name opt_inh_star ADD TableConstraint
+ {
+ $$ = cat_str(5, make_str("alter table"), $3, $4, make_str("add"), $6);
+ }
+/* ALTER TABLE <name> DROP CONSTRAINT ... */
+ | ALTER TABLE relation_name opt_inh_star DROP CONSTRAINT name drop_behavior
+ {
+ $$ = cat_str(6, make_str("alter table"), $3, $4, make_str("drop constraint"), $7, $8);
+ }
;
-alter_clause: ADD opt_column columnDef
- {
- $$ = cat3_str(make1_str("add"), $2, $3);
- }
- | ADD '(' OptTableElementList ')'
- {
- $$ = make3_str(make1_str("add("), $3, make1_str(")"));
- }
- | DROP opt_column ColId
- { yyerror("ALTER TABLE/DROP COLUMN not yet implemented"); }
- | ALTER opt_column ColId SET DEFAULT default_expr
- { yyerror("ALTER TABLE/ALTER COLUMN/SET DEFAULT not yet implemented"); }
- | ALTER opt_column ColId DROP DEFAULT
- { yyerror("ALTER TABLE/ALTER COLUMN/DROP DEFAULT not yet implemented"); }
- | ADD ConstraintElem
- { yyerror("ALTER TABLE/ADD CONSTRAINT not yet implemented"); }
- ;
+alter_column_action:
+ SET DEFAULT a_expr { $$ = cat2_str(make_str("set default"), $3); }
+ | SET DEFAULT NULL_P { $$ = make_str("set default null"); }
+ | DROP DEFAULT { $$ = make_str("drop default"); }
+ ;
+
+drop_behavior: CASCADE { $$ = make_str("cascade"); }
+ | RESTRICT { $$ = make_str("restrict"); }
+ ;
/*****************************************************************************
*
ClosePortalStmt: CLOSE opt_id
{
- $$ = cat2_str(make1_str("close"), $2);
+ $$ = cat2_str(make_str("close"), $2);
}
;
+opt_id: ColId { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter
+CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter copy_null
{
- $$ = cat3_str(cat5_str(make1_str("copy"), $2, $3, $4, $5), $6, $7);
+ $$ = cat_str(8, make_str("copy"), $2, $3, $4, $5, $6, $7, $8);
}
;
copy_dirn: TO
- { $$ = make1_str("to"); }
+ { $$ = make_str("to"); }
| FROM
- { $$ = make1_str("from"); }
+ { $$ = make_str("from"); }
;
/*
* stdout. We silently correct the "typo". - AY 9/94
*/
copy_file_name: Sconst { $$ = $1; }
- | STDIN { $$ = make1_str("stdin"); }
- | STDOUT { $$ = make1_str("stdout"); }
+ | STDIN { $$ = make_str("stdin"); }
+ | STDOUT { $$ = make_str("stdout"); }
;
-opt_binary: BINARY { $$ = make1_str("binary"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_binary: BINARY { $$ = make_str("binary"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_with_copy: WITH OIDS { $$ = make1_str("with oids"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_with_copy: WITH OIDS { $$ = make_str("with oids"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
/*
* the default copy delimiter is tab but the user can configure it
*/
-copy_delimiter: USING DELIMITERS Sconst { $$ = cat2_str(make1_str("using delimiters"), $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+copy_delimiter: opt_using DELIMITERS Sconst { $$ = cat_str(3, $1, make_str("delimiters"), $3); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
+opt_using: USING { $$ = make_str("using"); }
+ | /* EMPTY */ { $$ = EMPTY; }
+ ;
+copy_null: WITH NULL_P AS Sconst { $$ = cat2_str(make_str("with null as"), $4); }
+ | /* EMPTY */ { $$ = EMPTY; }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')'
+CreateStmt: CREATE OptTemp TABLE relation_name '(' OptTableElementList ')'
OptInherit
{
- $$ = cat4_str(make1_str("create table"), $3, make3_str(make1_str("("), $5, make1_str(")")), $7);
+ $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8);
}
;
+OptTemp: OptTempType { $$ = $1; }
+ | OptTempScope OptTempType { $$ = cat2_str($1,$2); }
+ ;
+
+OptTempType: TEMP { $$ = make_str("temp"); }
+ | TEMPORARY { $$ = make_str("temporary"); }
+ | /* EMPTY */ { $$ = EMPTY; }
+ ;
+
+OptTempScope: GLOBAL
+ {
+ mmerror(ET_ERROR, "GLOBAL TEMPORARY TABLE is not currently supported");
+ $$ = make_str("global");
+ }
+ | LOCAL { $$ = make_str("local"); }
+ ;
+
+
OptTableElementList: OptTableElementList ',' OptTableElement
{
- $$ = cat3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
| OptTableElement
{
$$ = $1;
}
- | /*EMPTY*/ { $$ = make1_str(""); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
OptTableElement: columnDef { $$ = $1; }
columnDef: ColId Typename ColQualifier
{
- $$ = cat3_str($1, $2, $3);
+ $$ = cat_str(3, $1, $2, $3);
}
| ColId SERIAL ColPrimaryKey
{
- $$ = make3_str($1, make1_str(" serial "), $3);
+ $$ = cat_str(3, $1, make_str(" serial "), $3);
}
;
-ColQualifier: ColQualList { $$ = $1; }
- | /*EMPTY*/ { $$ = make1_str(""); }
+ColQualifier: ColQualList { $$ = $1; }
+ | NULL_P ColQualListWithNull { $$ = cat2_str(make_str("null"), $2); }
+ | NULL_P { $$ = make_str("null"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
ColQualList: ColQualList ColConstraint { $$ = cat2_str($1,$2); }
- | ColConstraint { $$ = $1; }
+ | ColConstraint { $$ = $1; }
;
+ColQualListWithNull: ColQualListWithNull ColConstraintWithNull
+ { $$ = cat2_str($1, $2); }
+ | ColConstraintWithNull
+ { $$ = $1; }
ColPrimaryKey: PRIMARY KEY
{
- $$ = make1_str("primary key");
+ $$ = make_str("primary key");
}
| /*EMPTY*/
{
- $$ = make1_str("");
+ $$ = EMPTY;
}
;
ColConstraint:
CONSTRAINT name ColConstraintElem
{
- $$ = cat3_str(make1_str("constraint"), $2, $3);
+ $$ = cat_str(3, make_str("constraint"), $2, $3);
}
| ColConstraintElem
{ $$ = $1; }
;
-/* The column constraint WITH NULL gives a shift/reduce error
- * because it requires yacc to look more than one token ahead to
- * resolve WITH TIME ZONE and WITH NULL.
- * So, leave it out of the syntax for now.
- | WITH NULL_P
- {
- $$ = NULL;
- }
- * - thomas 1998-09-12
- *
- * DEFAULT NULL is already the default for Postgres.
- * Bue define it here and carry it forward into the system
+ColConstraintWithNull:
+ CONSTRAINT name ColConstraintElemWithNull
+ { $$ = cat_str(3, make_str("constraint"), $2, $3); }
+ | ColConstraintElemWithNull
+ { $$ = $1; }
+ ;
+
+/* DEFAULT NULL is already the default for Postgres.
+ * But define it here and carry it forward into the system
* to make it explicit.
* - thomas 1998-09-13
+ *
+ * WITH NULL and NULL are not SQL92-standard syntax elements,
+ * so leave them out. Use DEFAULT NULL to explicitly indicate
+ * that a column may have that value. WITH NULL leads to
+ * shift/reduce conflicts with WITH TIME ZONE anyway.
+ * - thomas 1999-01-08
+ *
+ * DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
+ * conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
+ * or be part of a_expr NOT LIKE or similar constructs).
*/
-ColConstraintElem: CHECK '(' constraint_expr ')'
- {
- $$ = make3_str(make1_str("check("), $3, make1_str(")"));
- }
- | DEFAULT NULL_P
- {
- $$ = make1_str("default null");
- }
- | DEFAULT default_expr
- {
- $$ = cat2_str(make1_str("default"), $2);
- }
- | NOT NULL_P
- {
- $$ = make1_str("not null");
- }
- | UNIQUE
+ColConstraintElem: ColConstraintElemWithNull
+ {
+ $$ = $1;
+ }
+ | NOT NULL_P
+ {
+ $$ = make_str("not null");
+ }
+ | UNIQUE
{
- $$ = make1_str("unique");
+ $$ = make_str("unique");
}
| PRIMARY KEY
{
- $$ = make1_str("primary key");
- }
- | REFERENCES ColId opt_column_list key_match key_actions
- {
- fprintf(stderr, "CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
- $$ = make1_str("");
+ $$ = make_str("primary key");
}
- ;
+ ;
-default_list: default_list ',' default_expr
+
+ColConstraintElemWithNull: CHECK '(' a_expr ')'
{
- $$ = cat3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, make_str("check("), $3, make_str(")"));
}
- | default_expr
+ | DEFAULT NULL_P
{
- $$ = $1;
+ $$ = make_str("default null");
}
- ;
-
-/* The Postgres default column value is NULL.
- * Rather than carrying DEFAULT NULL forward as a clause,
- * let's just have it be a no-op.
- | NULL_P
- { $$ = make1_str("null"); }
- * - thomas 1998-09-13
- */
-
-default_expr: AexprConst
- { $$ = $1; }
- | '-' default_expr %prec UMINUS
- { $$ = cat2_str(make1_str("-"), $2); }
- | default_expr '+' default_expr
- { $$ = cat3_str($1, make1_str("+"), $3); }
- | default_expr '-' default_expr
- { $$ = cat3_str($1, make1_str("-"), $3); }
- | default_expr '/' default_expr
- { $$ = cat3_str($1, make1_str("/"), $3); }
- | default_expr '*' default_expr
- { $$ = cat3_str($1, make1_str("*"), $3); }
- | default_expr '=' default_expr
- { yyerror("boolean expressions not supported in DEFAULT"); }
- | default_expr '<' default_expr
- { yyerror("boolean expressions not supported in DEFAULT"); }
- | default_expr '>' default_expr
- { yyerror("boolean expressions not supported in DEFAULT"); }
-/* not possible in embedded sql
- | ':' default_expr
- { $$ = cat2_str(make1_str(":"), $2); }
-*/
- | ';' default_expr
- { $$ = cat2_str(make1_str(";"), $2); }
- | '|' default_expr
- { $$ = cat2_str(make1_str("|"), $2); }
- | default_expr TYPECAST Typename
- { $$ = cat3_str($1, make1_str("::"), $3); }
- | CAST '(' default_expr AS Typename ')'
- {
- $$ = cat3_str(make2_str(make1_str("cast("), $3) , make1_str("as"), make2_str($5, make1_str(")")));
- }
- | '(' default_expr ')'
- { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | func_name '(' ')'
- { $$ = cat2_str($1, make1_str("()")); }
- | func_name '(' default_list ')'
- { $$ = cat2_str($1, make3_str(make1_str("("), $3, make1_str(")"))); }
- | default_expr Op default_expr
- {
- if (!strcmp("<=", $2) || !strcmp(">=", $2))
- yyerror("boolean expressions not supported in DEFAULT");
- $$ = cat3_str($1, $2, $3);
- }
- | Op default_expr
- { $$ = cat2_str($1, $2); }
- | default_expr Op
- { $$ = cat2_str($1, $2); }
- /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */
- | CURRENT_DATE
- { $$ = make1_str("current_date"); }
- | CURRENT_TIME
- { $$ = make1_str("current_time"); }
- | CURRENT_TIME '(' Iconst ')'
+ | DEFAULT b_expr
{
- if ($3 != 0)
- fprintf(stderr, "CURRENT_TIME(%s) precision not implemented; zero used instead",$3);
- $$ = "current_time";
+ $$ = cat2_str(make_str("default"), $2);
}
- | CURRENT_TIMESTAMP
- { $$ = make1_str("current_timestamp"); }
- | CURRENT_TIMESTAMP '(' Iconst ')'
+ | REFERENCES ColId opt_column_list key_match key_actions
{
- if ($3 != 0)
- fprintf(stderr, "CURRENT_TIMESTAMP(%s) precision not implemented; zero used instead",$3);
- $$ = "current_timestamp";
+ $$ = cat_str(5, make_str("references"), $2, $3, $4, $5);
}
- | CURRENT_USER
- { $$ = make1_str("current_user"); }
- | USER
- { $$ = make1_str("user"); }
;
/* ConstraintElem specifies constraint syntax which is not embedded into
*/
TableConstraint: CONSTRAINT name ConstraintElem
{
- $$ = cat3_str(make1_str("constraint"), $2, $3);
+ $$ = cat_str(3, make_str("constraint"), $2, $3);
}
| ConstraintElem
{ $$ = $1; }
;
-ConstraintElem: CHECK '(' constraint_expr ')'
+ConstraintElem: CHECK '(' a_expr ')'
{
- $$ = make3_str(make1_str("check("), $3, make1_str(")"));
+ $$ = cat_str(3, make_str("check("), $3, make_str(")"));
}
| UNIQUE '(' columnList ')'
{
- $$ = make3_str(make1_str("unique("), $3, make1_str(")"));
+ $$ = cat_str(3, make_str("unique("), $3, make_str(")"));
}
| PRIMARY KEY '(' columnList ')'
{
- $$ = make3_str(make1_str("primary key("), $4, make1_str(")"));
+ $$ = cat_str(3, make_str("primary key("), $4, make_str(")"));
}
| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions
{
- fprintf(stderr, "CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented");
- $$ = "";
- }
- ;
-
-constraint_list: constraint_list ',' constraint_expr
- {
- $$ = cat3_str($1, make1_str(","), $3);
- }
- | constraint_expr
- {
- $$ = $1;
+ $$ = cat_str(7, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10);
}
;
-constraint_expr: AexprConst
- { $$ = $1; }
- | NULL_P
- { $$ = make1_str("null"); }
- | ColId
- {
- $$ = $1;
- }
- | '-' constraint_expr %prec UMINUS
- { $$ = cat2_str(make1_str("-"), $2); }
- | constraint_expr '+' constraint_expr
- { $$ = cat3_str($1, make1_str("+"), $3); }
- | constraint_expr '-' constraint_expr
- { $$ = cat3_str($1, make1_str("-"), $3); }
- | constraint_expr '/' constraint_expr
- { $$ = cat3_str($1, make1_str("/"), $3); }
- | constraint_expr '*' constraint_expr
- { $$ = cat3_str($1, make1_str("*"), $3); }
- | constraint_expr '=' constraint_expr
- { $$ = cat3_str($1, make1_str("="), $3); }
- | constraint_expr '<' constraint_expr
- { $$ = cat3_str($1, make1_str("<"), $3); }
- | constraint_expr '>' constraint_expr
- { $$ = cat3_str($1, make1_str(">"), $3); }
-/* this one doesn't work with embedded sql anyway
- | ':' constraint_expr
- { $$ = cat2_str(make1_str(":"), $2); }
-*/
- | ';' constraint_expr
- { $$ = cat2_str(make1_str(";"), $2); }
- | '|' constraint_expr
- { $$ = cat2_str(make1_str("|"), $2); }
- | constraint_expr TYPECAST Typename
- {
- $$ = cat3_str($1, make1_str("::"), $3);
- }
- | CAST '(' constraint_expr AS Typename ')'
- {
- $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")")));
- }
- | '(' constraint_expr ')'
- { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | func_name '(' ')'
- {
- { $$ = cat2_str($1, make1_str("()")); }
- }
- | func_name '(' constraint_list ')'
- {
- $$ = cat2_str($1, make3_str(make1_str("("), $3, make1_str(")")));
- }
- | constraint_expr Op constraint_expr
- { $$ = cat3_str($1, $2, $3); }
- | constraint_expr LIKE constraint_expr
- { $$ = cat3_str($1, make1_str("like"), $3); }
- | constraint_expr NOT LIKE constraint_expr
- { $$ = cat3_str($1, make1_str("not like"), $4); }
- | constraint_expr AND constraint_expr
- { $$ = cat3_str($1, make1_str("and"), $3); }
- | constraint_expr OR constraint_expr
- { $$ = cat3_str($1, make1_str("or"), $3); }
- | NOT constraint_expr
- { $$ = cat2_str(make1_str("not"), $2); }
- | Op constraint_expr
- { $$ = cat2_str($1, $2); }
- | constraint_expr Op
- { $$ = cat2_str($1, $2); }
- | constraint_expr ISNULL
- { $$ = cat2_str($1, make1_str("isnull")); }
- | constraint_expr IS NULL_P
- { $$ = cat2_str($1, make1_str("is null")); }
- | constraint_expr NOTNULL
- { $$ = cat2_str($1, make1_str("notnull")); }
- | constraint_expr IS NOT NULL_P
- { $$ = cat2_str($1, make1_str("is not null")); }
- | constraint_expr IS TRUE_P
- { $$ = cat2_str($1, make1_str("is true")); }
- | constraint_expr IS FALSE_P
- { $$ = cat2_str($1, make1_str("is false")); }
- | constraint_expr IS NOT TRUE_P
- { $$ = cat2_str($1, make1_str("is not true")); }
- | constraint_expr IS NOT FALSE_P
- { $$ = cat2_str($1, make1_str("is not false")); }
- | constraint_expr IN '(' c_list ')'
- { $$ = cat4_str($1, make1_str("in ("), $4, make1_str(")")); }
- | constraint_expr NOT IN '(' c_list ')'
- { $$ = cat4_str($1, make1_str("not in ("), $5, make1_str(")")); }
- | constraint_expr BETWEEN c_expr AND c_expr
- { $$ = cat5_str($1, make1_str("between"), $3, make1_str("and"), $5); }
- | constraint_expr NOT BETWEEN c_expr AND c_expr
- { $$ = cat5_str($1, make1_str("not between"), $4, make1_str("and"), $6); }
- ;
-c_list: c_list ',' c_expr
- {
- $$ = make3_str($1, make1_str(", "), $3);
- }
- | c_expr
- {
- $$ = $1;
- }
-
-c_expr: AexprConst
- {
- $$ = $1;
- }
-
-key_match: MATCH FULL { $$ = make1_str("match full"); }
- | MATCH PARTIAL { $$ = make1_str("match partial"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+key_match: MATCH FULL
+ {
+ $$ = make_str("match full");
+ }
+ | MATCH PARTIAL
+ {
+ mmerror(ET_WARN, "FOREIGN KEY match type PARTIAL not implemented yet");
+ $$ = make_str("match partial");
+ }
+ | /*EMPTY*/
+ {
+ $$ = EMPTY;
+ }
;
-key_actions: key_action key_action { $$ = cat2_str($1, $2); }
- | key_action { $$ = $1; }
- | /*EMPTY*/ { $$ = make1_str(""); }
+key_actions: key_action key_action { $$ = cat2_str($1, $2); }
+ | key_action { $$ = $1; }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-key_action: ON DELETE key_reference { $$ = cat2_str(make1_str("on delete"), $3); }
- | ON UPDATE key_reference { $$ = cat2_str(make1_str("on update"), $3); }
+key_action: ON DELETE key_reference { $$ = cat2_str(make_str("on delete"), $3); }
+ | ON UPDATE key_reference { $$ = cat2_str(make_str("on update"), $3); }
;
-key_reference: NO ACTION { $$ = make1_str("no action"); }
- | CASCADE { $$ = make1_str("cascade"); }
- | SET DEFAULT { $$ = make1_str("set default"); }
- | SET NULL_P { $$ = make1_str("set null"); }
+key_reference: NO ACTION { $$ = make_str("no action"); }
+ | RESTRICT { $$ = make_str("restrict"); }
+ | CASCADE { $$ = make_str("cascade"); }
+ | SET DEFAULT { $$ = make_str("set default"); }
+ | SET NULL_P { $$ = make_str("set null"); }
;
-OptInherit: INHERITS '(' relation_name_list ')' { $$ = make3_str(make1_str("inherits ("), $3, make1_str(")")); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+OptInherit: INHERITS '(' relation_name_list ')' { $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-CreateAsStmt: CREATE TABLE relation_name OptCreateAs AS SubSelect
+/*
+ * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
+ * SELECT ... INTO.
+ */
+
+CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS SelectStmt
{
- $$ = cat5_str(make1_str("create table"), $3, $4, make1_str("as"), $6);
+ if (FoundInto == 1)
+ mmerror(ET_ERROR, "CREATE TABLE/AS SELECT may not specify INTO");
+
+ $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4, $5, make_str("as"), $7);
}
;
-OptCreateAs: '(' CreateAsList ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+OptCreateAs: '(' CreateAsList ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-CreateAsList: CreateAsList ',' CreateAsElement { $$ = cat3_str($1, make1_str(","), $3); }
+CreateAsList: CreateAsList ',' CreateAsElement { $$ = cat_str(3, $1, make_str(","), $3); }
| CreateAsElement { $$ = $1; }
;
CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList
{
- $$ = cat3_str(make1_str("create sequence"), $3, $4);
+ $$ = cat_str(3, make_str("create sequence"), $3, $4);
}
;
OptSeqList: OptSeqList OptSeqElem
{ $$ = cat2_str($1, $2); }
- | { $$ = make1_str(""); }
+ | { $$ = EMPTY; }
;
OptSeqElem: CACHE IntegerOnly
{
- $$ = cat2_str(make1_str("cache"), $2);
+ $$ = cat2_str(make_str("cache"), $2);
}
| CYCLE
{
- $$ = make1_str("cycle");
+ $$ = make_str("cycle");
}
| INCREMENT IntegerOnly
{
- $$ = cat2_str(make1_str("increment"), $2);
+ $$ = cat2_str(make_str("increment"), $2);
}
| MAXVALUE IntegerOnly
{
- $$ = cat2_str(make1_str("maxvalue"), $2);
+ $$ = cat2_str(make_str("maxvalue"), $2);
}
| MINVALUE IntegerOnly
{
- $$ = cat2_str(make1_str("minvalue"), $2);
+ $$ = cat2_str(make_str("minvalue"), $2);
}
| START IntegerOnly
{
- $$ = cat2_str(make1_str("start"), $2);
+ $$ = cat2_str(make_str("start"), $2);
}
;
}
| '-' Fconst
{
- $$ = cat2_str(make1_str("-"), $2);
+ $$ = cat2_str(make_str("-"), $2);
}
;
}
| '-' Iconst
{
- $$ = cat2_str(make1_str("-"), $2);
+ $$ = cat2_str(make_str("-"), $2);
}
;
CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst
HANDLER def_name LANCOMPILER Sconst
{
- $$ = cat4_str(cat5_str(make1_str("create"), $2, make1_str("precedural language"), $5, make1_str("handler")), $7, make1_str("langcompiler"), $9);
+ $$ = cat_str(8, make_str("create"), $2, make_str("precedural language"), $5, make_str("handler"), $7, make_str("langcompiler"), $9);
}
;
-PLangTrusted: TRUSTED { $$ = make1_str("trusted"); }
- | { $$ = make1_str(""); }
+PLangTrusted: TRUSTED { $$ = make_str("trusted"); }
+ | { $$ = EMPTY; }
DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst
{
- $$ = cat2_str(make1_str("drop procedural language"), $4);
+ $$ = cat2_str(make_str("drop procedural language"), $4);
}
;
relation_name TriggerForSpec EXECUTE PROCEDURE
name '(' TriggerFuncArgs ')'
{
- $$ = cat2_str(cat5_str(cat5_str(make1_str("create trigger"), $3, $4, $5, make1_str("on")), $7, $8, make1_str("execute procedure"), $11), make3_str(make1_str("("), $13, make1_str(")")));
+ $$ = 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(")"));
+ }
+ | CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
+ relation_name OptConstrFromTable
+ ConstraintAttributeSpec
+ FOR EACH ROW EXECUTE PROCEDURE
+ name '(' TriggerFuncArgs ')'
+ {
+ $$ = 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(")"));
}
;
-TriggerActionTime: BEFORE { $$ = make1_str("before"); }
- | AFTER { $$ = make1_str("after"); }
+TriggerActionTime: BEFORE { $$ = make_str("before"); }
+ | AFTER { $$ = make_str("after"); }
;
TriggerEvents: TriggerOneEvent
}
| TriggerOneEvent OR TriggerOneEvent
{
- $$ = cat3_str($1, make1_str("or"), $3);
+ $$ = cat_str(3, $1, make_str("or"), $3);
}
| TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
{
- $$ = cat5_str($1, make1_str("or"), $3, make1_str("or"), $5);
+ $$ = cat_str(5, $1, make_str("or"), $3, make_str("or"), $5);
}
;
-TriggerOneEvent: INSERT { $$ = make1_str("insert"); }
- | DELETE { $$ = make1_str("delete"); }
- | UPDATE { $$ = make1_str("update"); }
+TriggerOneEvent: INSERT { $$ = make_str("insert"); }
+ | DELETE { $$ = make_str("delete"); }
+ | UPDATE { $$ = make_str("update"); }
;
TriggerForSpec: FOR TriggerForOpt TriggerForType
{
- $$ = cat3_str(make1_str("for"), $2, $3);
+ $$ = cat_str(3, make_str("for"), $2, $3);
}
;
-TriggerForOpt: EACH { $$ = make1_str("each"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+TriggerForOpt: EACH { $$ = make_str("each"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-TriggerForType: ROW { $$ = make1_str("row"); }
- | STATEMENT { $$ = make1_str("statement"); }
+TriggerForType: ROW { $$ = make_str("row"); }
+ | STATEMENT { $$ = make_str("statement"); }
;
TriggerFuncArgs: TriggerFuncArg
{ $$ = $1; }
| TriggerFuncArgs ',' TriggerFuncArg
- { $$ = cat3_str($1, make1_str(","), $3); }
+ { $$ = cat_str(3, $1, make_str(","), $3); }
| /*EMPTY*/
- { $$ = make1_str(""); }
+ { $$ = EMPTY; }
;
TriggerFuncArg: Iconst
| ident { $$ = $1; }
;
+OptConstrFromTable: /* Empty */
+ {
+ $$ = EMPTY;
+ }
+ | FROM relation_name
+ {
+ $$ = cat2_str(make_str("from"), $2);
+ }
+ ;
+
+ConstraintAttributeSpec: ConstraintDeferrabilitySpec
+ { $$ = $1; }
+ | ConstraintDeferrabilitySpec ConstraintTimeSpec
+ {
+ if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
+ mmerror(ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
+
+ $$ = cat2_str($1, $2);
+ }
+ | ConstraintTimeSpec
+ { $$ = $1; }
+ | ConstraintTimeSpec ConstraintDeferrabilitySpec
+ {
+ if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
+ mmerror(ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
+
+ $$ = cat2_str($1, $2);
+ }
+ | /* Empty */
+ { $$ = 0; }
+ ;
+
+ConstraintDeferrabilitySpec: NOT DEFERRABLE
+ {
+ $$ = make_str("not deferrable");
+ }
+ | DEFERRABLE
+ {
+ $$ = make_str("deferrable");
+ }
+ ;
+
+ConstraintTimeSpec: INITIALLY IMMEDIATE
+ {
+ $$ = make_str("initially immediate");
+ }
+ | INITIALLY DEFERRED
+ {
+ $$ = make_str("initially deferrable");
+ }
+ ;
+
DropTrigStmt: DROP TRIGGER name ON relation_name
{
- $$ = cat4_str(make1_str("drop trigger"), $3, make1_str("on"), $5);
+ $$ = cat_str(4, make_str("drop trigger"), $3, make_str("on"), $5);
}
;
DefineStmt: CREATE def_type def_rest
{
- $$ = cat3_str(make1_str("create"), $2, $3);
+ $$ = cat_str(3, make_str("create"), $2, $3);
}
;
}
;
-def_type: OPERATOR { $$ = make1_str("operator"); }
- | TYPE_P { $$ = make1_str("type"); }
- | AGGREGATE { $$ = make1_str("aggregate"); }
+def_type: OPERATOR { $$ = make_str("operator"); }
+ | TYPE_P { $$ = make_str("type"); }
+ | AGGREGATE { $$ = make_str("aggregate"); }
;
-def_name: PROCEDURE { $$ = make1_str("procedure"); }
- | JOIN { $$ = make1_str("join"); }
+def_name: PROCEDURE { $$ = make_str("procedure"); }
+ | JOIN { $$ = make_str("join"); }
| ColId { $$ = $1; }
- | MathOp { $$ = $1; }
- | Op { $$ = $1; }
+ | all_Op { $$ = $1; }
;
-definition: '(' def_list ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
+definition: '(' def_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
;
def_list: def_elem { $$ = $1; }
- | def_list ',' def_elem { $$ = cat3_str($1, make1_str(","), $3); }
+ | def_list ',' def_elem { $$ = cat_str(3, $1, make_str(","), $3); }
;
def_elem: def_name '=' def_arg {
- $$ = cat3_str($1, make1_str("="), $3);
+ $$ = cat_str(3, $1, make_str("="), $3);
}
| def_name
{
}
| DEFAULT '=' def_arg
{
- $$ = cat2_str(make1_str("default ="), $3);
+ $$ = cat2_str(make_str("default ="), $3);
}
;
| Sconst { $$ = $1; }
| SETOF ColId
{
- $$ = cat2_str(make1_str("setof"), $2);
+ $$ = cat2_str(make_str("setof"), $2);
}
;
/*****************************************************************************
*
* QUERY:
- * destroy <relname1> [, <relname2> .. <relnameN> ]
+ * drop <relname1> [, <relname2> .. <relnameN> ]
*
*****************************************************************************/
-DestroyStmt: DROP TABLE relation_name_list
+DropStmt: DROP TABLE relation_name_list
{
- $$ = cat2_str(make1_str("drop table"), $3);
+ $$ = cat2_str(make_str("drop table"), $3);
}
| DROP SEQUENCE relation_name_list
{
- $$ = cat2_str(make1_str("drop sequence"), $3);
+ $$ = cat2_str(make_str("drop sequence"), $3);
}
;
-
+/*****************************************************************************
+ *
+ * QUERY:
+ * truncate table relname
+ *
+ *****************************************************************************/
+TruncateStmt: TRUNCATE opt_table relation_name
+ {
+ $$ = cat2_str(make_str("drop table"), $3);
+ }
+ ;
/*****************************************************************************
*
*
*****************************************************************************/
-FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name INTO into_list
+FetchStmt: FETCH direction fetch_how_many from_in name INTO into_list
{
- if (strncmp($2, "relative", strlen("relative")) == 0 && atol($3) == 0L)
- yyerror("FETCH/RELATIVE at current position is not supported");
+ if (strcmp($2, "relative") == 0 && atol($3) == 0L)
+ mmerror(ET_ERROR, "FETCH/RELATIVE at current position is not supported");
- $$ = cat4_str(make1_str("fetch"), $2, $3, $4);
+ $$ = cat_str(5, make_str("fetch"), $2, $3, $4, $5);
+ }
+ | FETCH fetch_how_many from_in name INTO into_list
+ {
+ $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
+ }
+ | FETCH direction from_in name INTO into_list
+ {
+ $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
+ }
+ | FETCH from_in name INTO into_list
+ {
+ $$ = cat_str(3, make_str("fetch"), $2, $3);
+ }
+ | FETCH name INTO into_list
+ {
+ $$ = cat2_str(make_str("fetch"), $2);
+ }
+ | MOVE direction fetch_how_many from_in name
+ {
+ $$ = cat_str(5, make_str("move"), $2, $3, $4, $5);
+ }
+ | MOVE fetch_how_many from_in name
+ {
+ $$ = cat_str(4, make_str("move"), $2, $3, $4);
+ }
+ | MOVE direction from_in name
+ {
+ $$ = cat_str(4, make_str("move"), $2, $3, $4);
+ }
+ | MOVE from_in name
+ {
+ $$ = cat_str(3, make_str("move"), $2, $3);
}
- | MOVE opt_direction fetch_how_many opt_portal_name
+ | MOVE name
{
- $$ = cat4_str(make1_str("fetch"), $2, $3, $4);
+ $$ = cat2_str(make_str("move"), $2);
}
;
-opt_direction: FORWARD { $$ = make1_str("forward"); }
- | BACKWARD { $$ = make1_str("backward"); }
- | RELATIVE { $$ = make1_str("relative"); }
- | ABSOLUTE
- {
- fprintf(stderr, "FETCH/ABSOLUTE not supported, using RELATIVE");
- $$ = make1_str("absolute");
+direction: FORWARD { $$ = make_str("forward"); }
+ | BACKWARD { $$ = make_str("backward"); }
+ | RELATIVE { $$ = make_str("relative"); }
+ | ABSOLUTE {
+ mmerror(ET_WARN, "FETCH/ABSOLUTE not supported, backend will use RELATIVE");
+ $$ = make_str("absolute");
}
- | /*EMPTY*/ { $$ = make1_str(""); /* default */ }
;
fetch_how_many: Iconst { $$ = $1; }
- | '-' Iconst { $$ = make2_str(make1_str("-"), $2); }
- | ALL { $$ = make1_str("all"); }
- | NEXT { $$ = make1_str("next"); }
- | PRIOR { $$ = make1_str("prior"); }
- | /*EMPTY*/ { $$ = make1_str(""); /*default*/ }
+ | '-' Iconst { $$ = cat2_str(make_str("-"), $2); }
+ | ALL { $$ = make_str("all"); }
+ | NEXT { $$ = make_str("next"); }
+ | PRIOR { $$ = make_str("prior"); }
;
-opt_portal_name: IN name { $$ = cat2_str(make1_str("in"), $2); }
- | FROM name { $$ = cat2_str(make1_str("from"), $2); }
-/* | name { $$ = cat2_str(make1_str("in"), $1); */
- | /*EMPTY*/ { $$ = make1_str(""); }
+from_in: IN { $$ = make_str("in"); }
+ | FROM { $$ = make_str("from"); }
+ ;
+
+/*****************************************************************************
+ *
+ * The COMMENT ON statement can take different forms based upon the type of
+ * the object associated with the comment. The form of the statement is:
+ *
+ * COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
+ * <objname> | AGGREGATE <aggname> <aggtype> | FUNCTION
+ * <funcname> (arg1, arg2, ...) | OPERATOR <op>
+ * (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
+ * <relname> ] IS 'text'
+ *
+ *****************************************************************************/
+CommentStmt: COMMENT ON comment_type name IS comment_text
+ {
+ $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6);
+ }
+ | COMMENT ON comment_cl relation_name '.' attr_name IS comment_text
+ {
+ $$ = cat_str(7, make_str("comment on"), $3, $4, make_str("."), $6, make_str("is"), $8);
+ }
+ | COMMENT ON comment_ag name aggr_argtype IS comment_text
+ {
+ $$ = cat_str(6, make_str("comment on"), $3, $4, $5, make_str("is"), $7);
+ }
+ | COMMENT ON comment_fn func_name func_args IS comment_text
+ {
+ $$ = cat_str(6, make_str("comment on"), $3, $4, $5, make_str("is"), $7);
+ }
+ | COMMENT ON comment_op all_Op '(' oper_argtypes ')' IS comment_text
+ {
+ $$ = cat_str(7, make_str("comment on"), $3, $4, make_str("("), $6, make_str(") is"), $9);
+ }
+ | COMMENT ON comment_tg name ON relation_name IS comment_text
+ {
+ $$ = cat_str(7, make_str("comment on"), $3, $4, make_str("on"), $6, make_str("is"), $8);
+ }
+ ;
+
+comment_type: DATABASE { $$ = make_str("database"); }
+ | INDEX { $$ = make_str("idnex"); }
+ | RULE { $$ = make_str("rule"); }
+ | SEQUENCE { $$ = make_str("sequence"); }
+ | TABLE { $$ = make_str("table"); }
+ | TYPE_P { $$ = make_str("type"); }
+ | VIEW { $$ = make_str("view"); }
;
+comment_cl: COLUMN { $$ = make_str("column"); }
+
+comment_ag: AGGREGATE { $$ = make_str("aggregate"); }
+
+comment_fn: FUNCTION { $$ = make_str("function"); }
+
+comment_op: OPERATOR { $$ = make_str("operator"); }
+
+comment_tg: TRIGGER { $$ = make_str("trigger"); }
+
+comment_text: Sconst { $$ = $1; }
+ | NULL_P { $$ = make_str("null"); }
+ ;
/*****************************************************************************
*
GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant
{
- $$ = cat2_str(cat5_str(make1_str("grant"), $2, make1_str("on"), $4, make1_str("to")), $6);
+ $$ = cat_str(7, make_str("grant"), $2, make_str("on"), $4, make_str("to"), $6);
}
;
privileges: ALL PRIVILEGES
{
- $$ = make1_str("all privileges");
+ $$ = make_str("all privileges");
}
| ALL
{
- $$ = make1_str("all");
+ $$ = make_str("all");
}
| operation_commalist
{
}
| operation_commalist ',' operation
{
- $$ = cat3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
;
operation: SELECT
{
- $$ = make1_str("select");
+ $$ = make_str("select");
}
| INSERT
{
- $$ = make1_str("insert");
+ $$ = make_str("insert");
}
| UPDATE
{
- $$ = make1_str("update");
+ $$ = make_str("update");
}
| DELETE
{
- $$ = make1_str("delete");
+ $$ = make_str("delete");
}
| RULE
{
- $$ = make1_str("rule");
+ $$ = make_str("rule");
}
;
grantee: PUBLIC
{
- $$ = make1_str("public");
+ $$ = make_str("public");
}
| GROUP ColId
{
- $$ = cat2_str(make1_str("group"), $2);
+ $$ = cat2_str(make_str("group"), $2);
}
| ColId
{
opt_with_grant: WITH GRANT OPTION
{
- yyerror("WITH GRANT OPTION is not supported. Only relation owners can set privileges");
+ mmerror(ET_ERROR, "WITH GRANT OPTION is not supported. Only relation owners can set privileges");
}
| /*EMPTY*/
;
RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee
{
- $$ = cat2_str(cat5_str(make1_str("revoke"), $2, make1_str("on"), $4, make1_str("from")), $6);
+ $$ = cat_str(7, make_str("revoke"), $2, make_str("on"), $4, make_str("from"), $6);
}
;
{
/* should check that access_method is valid,
etc ... but doesn't */
- $$ = cat5_str(cat5_str(make1_str("create"), $2, make1_str("index"), $4, make1_str("on")), $6, $7, make3_str(make1_str("("), $9, make1_str(")")), $11);
+ $$ = cat_str(11, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11);
}
;
-index_opt_unique: UNIQUE { $$ = make1_str("unique"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+index_opt_unique: UNIQUE { $$ = make_str("unique"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-access_method_clause: USING access_method { $$ = cat2_str(make1_str("using"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+access_method_clause: USING access_method { $$ = cat2_str(make_str("using"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
index_params: index_list { $$ = $1; }
| func_index { $$ = $1; }
;
-index_list: index_list ',' index_elem { $$ = cat3_str($1, make1_str(","), $3); }
+index_list: index_list ',' index_elem { $$ = cat_str(3, $1, make_str(","), $3); }
| index_elem { $$ = $1; }
;
func_index: func_name '(' name_list ')' opt_type opt_class
{
- $$ = cat4_str($1, make3_str(make1_str("("), $3, ")"), $5, $6);
+ $$ = cat_str(6, $1, make_str("("), $3, ")", $5, $6);
}
;
index_elem: attr_name opt_type opt_class
{
- $$ = cat3_str($1, $2, $3);
+ $$ = cat_str(3, $1, $2, $3);
}
;
-opt_type: ':' Typename { $$ = cat2_str(make1_str(":"), $2); }
- | FOR Typename { $$ = cat2_str(make1_str("for"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_type: ':' Typename { $$ = cat2_str(make_str(":"), $2); }
+ | FOR Typename { $$ = cat2_str(make_str("for"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
/* opt_class "WITH class" conflicts with preceeding opt_type
* | WITH class { $$ = $2; }
*/
opt_class: class { $$ = $1; }
- | USING class { $$ = cat2_str(make1_str("using"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+ | USING class { $$ = cat2_str(make_str("using"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
/*****************************************************************************
ExtendStmt: EXTEND INDEX index_name where_clause
{
- $$ = cat3_str(make1_str("extend index"), $3, $4);
+ $$ = cat_str(3, make_str("extend index"), $3, $4);
}
;
* execute recipe <recipeName>
*
*****************************************************************************/
-
+/* NOT USED
RecipeStmt: EXECUTE RECIPE recipe_name
{
- $$ = cat2_str(make1_str("execute recipe"), $3);
+ $$ = cat2_str(make_str("execute recipe"), $3);
}
;
-
+*/
/*****************************************************************************
*
* QUERY:
*****************************************************************************/
ProcedureStmt: CREATE FUNCTION func_name func_args
- RETURNS func_return opt_with AS Sconst LANGUAGE Sconst
+ RETURNS func_return opt_with AS func_as LANGUAGE Sconst
{
- $$ = cat2_str(cat5_str(cat5_str(make1_str("create function"), $3, $4, make1_str("returns"), $6), $7, make1_str("as"), $9, make1_str("language")), $11);
+ $$ = cat_str(10, make_str("create function"), $3, $4, make_str("returns"), $6, $7, make_str("as"), $9, make_str("language"), $11);
}
-opt_with: WITH definition { $$ = cat2_str(make1_str("with"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_with: WITH definition { $$ = cat2_str(make_str("with"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-func_args: '(' func_args_list ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | '(' ')' { $$ = make1_str("()"); }
+func_args: '(' func_args_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ | '(' ')' { $$ = make_str("()"); }
;
func_args_list: TypeId { $$ = $1; }
| func_args_list ',' TypeId
- { $$ = cat3_str($1, make1_str(","), $3); }
+ { $$ = cat_str(3, $1, make_str(","), $3); }
;
+func_as: Sconst { $$ = $1; }
+ | Sconst ',' Sconst { $$ = cat_str(3, $1, make_str(","), $3); }
+
func_return: set_opt TypeId
{
$$ = cat2_str($1, $2);
}
;
-set_opt: SETOF { $$ = make1_str("setof"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+set_opt: SETOF { $$ = make_str("setof"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
RemoveStmt: DROP remove_type name
{
- $$ = cat3_str(make1_str("drop"), $2, $3);;
+ $$ = cat_str(3, make_str("drop"), $2, $3);
}
;
-remove_type: TYPE_P { $$ = make1_str("type"); }
- | INDEX { $$ = make1_str("index"); }
- | RULE { $$ = make1_str("rule"); }
- | VIEW { $$ = make1_str("view"); }
+remove_type: TYPE_P { $$ = make_str("type"); }
+ | INDEX { $$ = make_str("index"); }
+ | RULE { $$ = make_str("rule"); }
+ | VIEW { $$ = make_str("view"); }
;
RemoveAggrStmt: DROP AGGREGATE name aggr_argtype
{
- $$ = cat3_str(make1_str("drop aggregate"), $3, $4);
+ $$ = cat_str(3, make_str("drop aggregate"), $3, $4);
}
;
aggr_argtype: name { $$ = $1; }
- | '*' { $$ = make1_str("*"); }
+ | '*' { $$ = make_str("*"); }
;
RemoveFuncStmt: DROP FUNCTION func_name func_args
{
- $$ = cat3_str(make1_str("drop function"), $3, $4);
+ $$ = cat_str(3, make_str("drop function"), $3, $4);
}
;
RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')'
{
- $$ = cat3_str(make1_str("drop operator"), $3, make3_str(make1_str("("), $5, make1_str(")")));
+ $$ = cat_str(5, make_str("drop operator"), $3, make_str("("), $5, make_str(")"));
}
;
-all_Op: Op | MathOp;
-
-MathOp: '+' { $$ = make1_str("+"); }
- | '-' { $$ = make1_str("-"); }
- | '*' { $$ = make1_str("*"); }
- | '/' { $$ = make1_str("/"); }
- | '<' { $$ = make1_str("<"); }
- | '>' { $$ = make1_str(">"); }
- | '=' { $$ = make1_str("="); }
- ;
-
oper_argtypes: name
{
- yyerror("parser: argument type missing (use NONE for unary operators)");
+ mmerror(ET_ERROR, "parser: argument type missing (use NONE for unary operators)");
}
| name ',' name
- { $$ = cat3_str($1, make1_str(","), $3); }
+ { $$ = cat_str(3, $1, make_str(","), $3); }
| NONE ',' name /* left unary */
- { $$ = cat2_str(make1_str("none,"), $3); }
+ { $$ = cat2_str(make_str("none,"), $3); }
| name ',' NONE /* right unary */
- { $$ = cat2_str($1, make1_str(", none")); }
+ { $$ = cat2_str($1, make_str(", none")); }
;
RenameStmt: ALTER TABLE relation_name opt_inh_star
RENAME opt_column opt_name TO name
{
- $$ = cat4_str(cat5_str(make1_str("alter table"), $3, $4, make1_str("rename"), $6), $7, make1_str("to"), $9);
+ $$ = cat_str(8, make_str("alter table"), $3, $4, make_str("rename"), $6, $7, make_str("to"), $9);
}
;
opt_name: name { $$ = $1; }
- | /*EMPTY*/ { $$ = make1_str(""); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_column: COLUMN { $$ = make1_str("colmunn"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_column: COLUMN { $$ = make_str("colmunn"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
RuleStmt: CREATE RULE name AS
{ QueryIsRule=1; }
ON event TO event_object where_clause
- DO opt_instead OptStmtList
+ DO opt_instead RuleActionList
{
- $$ = cat2_str(cat5_str(cat5_str(make1_str("create rule"), $3, make1_str("as on"), $7, make1_str("to")), $9, $10, make1_str("do"), $12), $13);
+ $$ = cat_str(10, make_str("create rule"), $3, make_str("as on"), $7, make_str("to"), $9, $10, make_str("do"), $12, $13);
}
;
-OptStmtList: NOTHING { $$ = make1_str("nothing"); }
- | OptimizableStmt { $$ = $1; }
- | '[' OptStmtBlock ']' { $$ = cat3_str(make1_str("["), $2, make1_str("]")); }
-/***S*I*D***/
-/* We comment this out because it produces a shift / reduce conflict
- * with the select_w_o_sort rule */
-/* | '(' OptStmtBlock ')' { $$ = cat3_str(make1_str("("), $2, make1_str(")")); }*/
- ;
+RuleActionList: NOTHING { $$ = make_str("nothing"); }
+ | SelectStmt { $$ = $1; }
+ | RuleActionStmt { $$ = $1; }
+ | '[' RuleActionMulti ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); }
+ | '(' RuleActionMulti ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ ;
-OptStmtBlock: OptStmtMulti
- { $$ = $1; }
- | OptimizableStmt
- { $$ = $1; }
+/* the thrashing around here is to discard "empty" statements... */
+RuleActionMulti: RuleActionMulti ';' RuleActionStmtOrEmpty
+ { $$ = cat_str(3, $1, make_str(";"), $3); }
+ | RuleActionStmtOrEmpty
+ { $$ = cat2_str($1, make_str(";")); }
;
-OptStmtMulti: OptStmtMulti OptimizableStmt ';'
- { $$ = cat3_str($1, $2, make1_str(";")); }
-/***S*I***/
-/* We comment the next rule because it seems to be redundant
- * and produces 16 shift/reduce conflicts with the new SelectStmt rule
- * needed for EXCEPT and INTERSECT. So far I did not notice any
- * violations by removing the rule! */
-/* | OptStmtMulti OptimizableStmt
- { $$ = cat2_str($1, $2); }*/
- | OptimizableStmt ';'
- { $$ = cat2_str($1, make1_str(";")); }
- ;
+RuleActionStmt: InsertStmt
+ | UpdateStmt
+ | DeleteStmt
+ | NotifyStmt
+ ;
+RuleActionStmtOrEmpty: RuleActionStmt { $$ = $1; }
+ | /*EMPTY*/ { $$ = EMPTY; }
+ ;
event_object: relation_name '.' attr_name
{
- $$ = make3_str($1, make1_str("."), $3);
+ $$ = make3_str($1, make_str("."), $3);
}
| relation_name
{
;
/* change me to select, update, etc. some day */
-event: SELECT { $$ = make1_str("select"); }
- | UPDATE { $$ = make1_str("update"); }
- | DELETE { $$ = make1_str("delete"); }
- | INSERT { $$ = make1_str("insert"); }
+event: SELECT { $$ = make_str("select"); }
+ | UPDATE { $$ = make_str("update"); }
+ | DELETE { $$ = make_str("delete"); }
+ | INSERT { $$ = make_str("insert"); }
;
-opt_instead: INSTEAD { $$ = make1_str("instead"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_instead: INSTEAD { $$ = make_str("instead"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
NotifyStmt: NOTIFY relation_name
{
- $$ = cat2_str(make1_str("notify"), $2);
+ $$ = cat2_str(make_str("notify"), $2);
}
;
ListenStmt: LISTEN relation_name
{
- $$ = cat2_str(make1_str("listen"), $2);
+ $$ = cat2_str(make_str("listen"), $2);
}
;
UnlistenStmt: UNLISTEN relation_name
{
- $$ = cat2_str(make1_str("unlisten"), $2);
+ $$ = cat2_str(make_str("unlisten"), $2);
}
| UNLISTEN '*'
{
- $$ = make1_str("unlisten *");
+ $$ = make_str("unlisten *");
}
;
*
* Transactions:
*
- * abort transaction
- * (ABORT)
- * begin transaction
- * (BEGIN)
- * end transaction
- * (END)
+ * BEGIN / COMMIT / ROLLBACK
+ * (also older versions END / ABORT)
*
*****************************************************************************/
-TransactionStmt: ABORT_TRANS opt_trans { $$ = make1_str("rollback"); }
- | BEGIN_TRANS opt_trans { $$ = make1_str("begin transaction"); }
- | COMMIT opt_trans { $$ = make1_str("commit"); }
- | END_TRANS opt_trans { $$ = make1_str("commit"); }
- | ROLLBACK opt_trans { $$ = make1_str("rollback"); }
+TransactionStmt: ABORT_TRANS opt_trans { $$ = make_str("rollback"); }
+ | BEGIN_TRANS opt_trans { $$ = make_str("begin transaction"); }
+ | COMMIT opt_trans { $$ = make_str("commit"); }
+ | END_TRANS opt_trans { $$ = make_str("commit"); }
+ | ROLLBACK opt_trans { $$ = make_str("rollback"); }
opt_trans: WORK { $$ = ""; }
| TRANSACTION { $$ = ""; }
ViewStmt: CREATE VIEW name AS SelectStmt
{
- $$ = cat4_str(make1_str("create view"), $3, make1_str("as"), $5);
+ $$ = cat_str(4, make_str("create view"), $3, make_str("as"), $5);
}
;
/*****************************************************************************
*
* QUERY:
- * load make1_str("filename")
+ * load make_str("filename")
*
*****************************************************************************/
LoadStmt: LOAD file_name
{
- $$ = cat2_str(make1_str("load"), $2);
+ $$ = cat2_str(make_str("load"), $2);
}
;
/*****************************************************************************
*
- * QUERY:
- * createdb dbname
+ * CREATE DATABASE
+ *
*
*****************************************************************************/
-CreatedbStmt: CREATE DATABASE database_name WITH opt_database1 opt_database2
- {
- if (strlen($5) == 0 || strlen($6) == 0)
- yyerror("CREATE DATABASE WITH requires at least an option");
-#ifndef MULTIBYTE
- if (strlen($6) != 0)
- yyerror("WITH ENCODING is not supported");
-#endif
- $$ = cat5_str(make1_str("create database"), $3, make1_str("with"), $5, $6);
- }
+CreatedbStmt: CREATE DATABASE database_name WITH createdb_opt_location createdb_opt_encoding
+ {
+ if (strlen($5) == 0 || strlen($6) == 0)
+ mmerror(ET_ERROR, "CREATE DATABASE WITH requires at least an option");
+
+ $$ = cat_str(5, make_str("create database"), $3, make_str("with"), $5, $6);
+ }
| CREATE DATABASE database_name
- {
- $$ = cat2_str(make1_str("create database"), $3);
- }
+ {
+ $$ = cat2_str(make_str("create database"), $3);
+ }
;
-opt_database1: LOCATION '=' location { $$ = cat2_str(make1_str("location ="), $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+createdb_opt_location: LOCATION '=' Sconst { $$ = cat2_str(make_str("location ="), $3); }
+ | LOCATION '=' DEFAULT { $$ = make_str("location = default"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_database2: ENCODING '=' encoding { $$ = cat2_str(make1_str("encoding ="), $3); }
+createdb_opt_encoding: ENCODING '=' Sconst
+ {
+#ifndef MULTIBYTE
+ mmerror(ET_ERROR, "Multi-byte support is not enabled.");
+#endif
+ $$ = cat2_str(make_str("encoding ="), $3);
+ }
+ | ENCODING '=' Iconst
+ {
+#ifndef MULTIBYTE
+ mmerror(ET_ERROR, "Multi-byte support is not enabled.");
+#endif
+ $$ = cat2_str(make_str("encoding ="), $3);
+ }
+ | ENCODING '=' DEFAULT
+ {
+#ifndef MULTIBYTE
+ mmerror(ET_ERROR, "Multi-byte support is not enabled.");
+#endif
+ $$ = make_str("encoding = default");
+ }
| /*EMPTY*/ { $$ = NULL; }
;
-location: Sconst { $$ = $1; }
- | DEFAULT { $$ = make1_str("default"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
- ;
-
-encoding: Sconst { $$ = $1; }
- | DEFAULT { $$ = make1_str("default"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
- ;
-
/*****************************************************************************
*
- * QUERY:
- * destroydb dbname
+ * DROP DATABASE
+ *
*
*****************************************************************************/
-DestroydbStmt: DROP DATABASE database_name
+DropdbStmt: DROP DATABASE database_name
{
- $$ = cat2_str(make1_str("drop database"), $3);
+ $$ = cat2_str(make_str("drop database"), $3);
}
;
ClusterStmt: CLUSTER index_name ON relation_name
{
- $$ = cat4_str(make1_str("cluster"), $2, make1_str("on"), $4);
+ $$ = cat_str(4, make_str("cluster"), $2, make_str("on"), $4);
}
;
VacuumStmt: VACUUM opt_verbose opt_analyze
{
- $$ = cat3_str(make1_str("vacuum"), $2, $3);
+ $$ = cat_str(3, make_str("vacuum"), $2, $3);
}
| VACUUM opt_verbose opt_analyze relation_name opt_va_list
{
if ( strlen($5) > 0 && strlen($4) == 0 )
- yyerror("parser: syntax error at or near \"(\"");
- $$ = cat5_str(make1_str("vacuum"), $2, $3, $4, $5);
+ mmerror(ET_ERROR, "VACUUM syntax error at or near \"(\"\n\tRelations name must be specified");
+ $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5);
}
;
-opt_verbose: VERBOSE { $$ = make1_str("verbose"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_verbose: VERBOSE { $$ = make_str("verbose"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_analyze: ANALYZE { $$ = make1_str("analyse"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_analyze: ANALYZE { $$ = make_str("analyse"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_va_list: '(' va_list ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_va_list: '(' va_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
va_list: name
{ $$=$1; }
| va_list ',' name
- { $$=cat3_str($1, make1_str(","), $3); }
+ { $$=cat_str(3, $1, make_str(","), $3); }
;
ExplainStmt: EXPLAIN opt_verbose OptimizableStmt
{
- $$ = cat3_str(make1_str("explain"), $2, $3);
+ $$ = cat_str(3, make_str("explain"), $2, $3);
}
;
*
*****************************************************************************/
-/***S*I***/
/* This rule used 'opt_column_list' between 'relation_name' and 'insert_rest'
* originally. When the second rule of 'insert_rest' was changed to use
* the new 'SelectStmt' rule (for INTERSECT and EXCEPT) it produced a shift/red uce
* the same statements without any shift/reduce conflicts */
InsertStmt: INSERT INTO relation_name insert_rest
{
- $$ = cat3_str(make1_str("insert into"), $3, $4);
+ $$ = cat_str(3, make_str("insert into"), $3, $4);
}
;
-insert_rest: VALUES '(' res_target_list2 ')'
+insert_rest: VALUES '(' target_list ')'
{
- $$ = make3_str(make1_str("values("), $3, make1_str(")"));
+ $$ = cat_str(3, make_str("values("), $3, make_str(")"));
}
| DEFAULT VALUES
{
- $$ = make1_str("default values");
+ $$ = make_str("default values");
}
+/* We want the full power of SelectStatements including INTERSECT and EXCEPT
+ * for insertion. However, we can't support sort or limit clauses.
+ */
| SelectStmt
{
- $$ = $1
+ if (FoundSort != 0)
+ mmerror(ET_ERROR, "ORDER BY is not allowed in INSERT/SELECT");
+
+ $$ = $1;
}
- | '(' columnList ')' VALUES '(' res_target_list2 ')'
+ | '(' columnList ')' VALUES '(' target_list ')'
{
- $$ = make5_str(make1_str("("), $2, make1_str(") values ("), $6, make1_str(")"));
+ $$ = cat_str(5, make_str("("), $2, make_str(") values ("), $6, make_str(")"));
}
| '(' columnList ')' SelectStmt
{
- $$ = make4_str(make1_str("("), $2, make1_str(")"), $4);
+ if (FoundSort != 0)
+ mmerror(ET_ERROR, "ORDER BY is not all owed in INSERT/SELECT");
+
+ $$ = cat_str(4, make_str("("), $2, make_str(")"), $4);
}
;
-opt_column_list: '(' columnList ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_column_list: '(' columnList ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
columnList:
columnList ',' columnElem
- { $$ = cat3_str($1, make1_str(","), $3); }
+ { $$ = cat_str(3, $1, make_str(","), $3); }
| columnElem
{ $$ = $1; }
;
DeleteStmt: DELETE FROM relation_name
where_clause
{
- $$ = cat3_str(make1_str("delete from"), $3, $4);
+ $$ = cat_str(3, make_str("delete from"), $3, $4);
}
;
-LockStmt: LOCK_P opt_table relation_name
- {
- $$ = cat3_str(make1_str("lock"), $2, $3);
- }
- | LOCK_P opt_table relation_name IN opt_lmode ROW IDENT IDENT
- {
- if (strcasecmp($8, "MODE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $8);
- yyerror(errortext);
- }
- if ($5 != NULL)
- {
- if (strcasecmp($5, "SHARE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $5);
- yyerror(errortext);
- }
- if (strcasecmp($7, "EXCLUSIVE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $7);
- yyerror(errortext);
- }
- }
- else
- {
- if (strcasecmp($7, "SHARE") && strcasecmp($7, "EXCLUSIVE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $7);
- yyerror(errortext);
- }
- }
-
- $$=cat4_str(cat5_str(make1_str("lock"), $2, $3, make1_str("in"), $5), make1_str("row"), $7, $8);
- }
- | LOCK_P opt_table relation_name IN IDENT IDENT IDENT
- {
- if (strcasecmp($7, "MODE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $7);
- yyerror(errortext);
- }
- if (strcasecmp($5, "ACCESS"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $5);
- yyerror(errortext);
- }
- if (strcasecmp($6, "SHARE") && strcasecmp($6, "EXCLUSIVE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $6);
- yyerror(errortext);
- }
-
- $$=cat3_str(cat5_str(make1_str("lock"), $2, $3, make1_str("in"), $5), $6, $7);
- }
- | LOCK_P opt_table relation_name IN IDENT IDENT
+LockStmt: LOCK_P opt_table relation_name opt_lock
{
- if (strcasecmp($6, "MODE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $6);
- yyerror(errortext);
- }
- if (strcasecmp($5, "SHARE") && strcasecmp($5, "EXCLUSIVE"))
- {
- sprintf(errortext, "syntax error at or near \"%s\"", $5);
- yyerror(errortext);
- }
-
- $$=cat2_str(cat5_str(make1_str("lock"), $2, $3, make1_str("in"), $5), $6);
+ $$ = cat_str(4, make_str("lock"), $2, $3, $4);
}
;
-opt_lmode: IDENT { $$ = $1; }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_lock: IN lock_type MODE { $$ = cat_str(3, make_str("in"), $2, make_str("mode")); }
+ | /*EMPTY*/ { $$ = EMPTY;}
;
+lock_type: SHARE ROW EXCLUSIVE { $$ = make_str("share row exclusive"); }
+ | ROW opt_lmode { $$ = cat2_str(make_str("row"), $2);}
+ | ACCESS opt_lmode { $$ = cat2_str(make_str("access"), $2);}
+ | opt_lmode { $$ = $1; }
+ ;
-
+opt_lmode: SHARE { $$ = make_str("share"); }
+ | EXCLUSIVE { $$ = make_str("exclusive"); }
+ ;
/*****************************************************************************
*
*****************************************************************************/
UpdateStmt: UPDATE relation_name
- SET res_target_list
+ SET update_target_list
from_clause
where_clause
{
- $$ = cat2_str(cat5_str(make1_str("update"), $2, make1_str("set"), $4, $5), $6);
+ $$ = cat_str(6, make_str("update"), $2, make_str("set"), $4, $5, $6);
}
;
* CURSOR STATEMENTS
*
*****************************************************************************/
-CursorStmt: DECLARE name opt_cursor CURSOR FOR SelectStmt cursor_clause
+CursorStmt: DECLARE name opt_cursor CURSOR FOR
+ { ForUpdateNotAllowed = 1; }
+ SelectStmt
{
struct cursor *ptr, *this;
{
if (strcmp($2, ptr->name) == 0)
{
- /* re-definition is a bug*/
+ /* re-definition is a bug */
sprintf(errortext, "cursor %s already defined", $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
}
/* initial definition */
this->next = cur;
this->name = $2;
- this->command = cat2_str(cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for"), $6), $7);
+ this->connection = connection;
+ this->command = cat_str(5, make_str("declare"), mm_strdup($2), $3, make_str("cursor for"), $7);
this->argsinsert = argsinsert;
this->argsresult = argsresult;
argsinsert = argsresult = NULL;
cur = this;
- $$ = cat3_str(make1_str("/*"), mm_strdup(this->command), make1_str("*/"));
+ $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
}
;
-opt_cursor: BINARY { $$ = make1_str("binary"); }
- | INSENSITIVE { $$ = make1_str("insensitive"); }
- | SCROLL { $$ = make1_str("scroll"); }
- | INSENSITIVE SCROLL { $$ = make1_str("insensitive scroll"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
- ;
-
-cursor_clause: FOR opt_readonly { $$ = cat2_str(make1_str("for"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
-
- ;
-
-opt_readonly: READ ONLY { $$ = make1_str("read only"); }
- | UPDATE opt_of
- {
- yyerror("DECLARE/UPDATE not supported; Cursors must be READ ONLY.");
- }
+opt_cursor: BINARY { $$ = make_str("binary"); }
+ | INSENSITIVE { $$ = make_str("insensitive"); }
+ | SCROLL { $$ = make_str("scroll"); }
+ | INSENSITIVE SCROLL { $$ = make_str("insensitive scroll"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_of: OF columnList { $$ = make2_str(make1_str("of"), $2); }
-
/*****************************************************************************
*
* QUERY:
*
*****************************************************************************/
-/***S*I***/
/* The new 'SelectStmt' rule adapted for the optional use of INTERSECT EXCEPT a nd UNION
* accepts the use of '(' and ')' to select an order of set operations.
+ * The rule returns a SelectStmt Node having the set operations attached to
+ * unionClause and intersectClause (NIL if no set operations were present)
*/
-SelectStmt: select_w_o_sort sort_clause for_update_clause
- {
- if (strlen($3) > 0 && ForUpdateNotAllowed != 0)
- yyerror("SELECT FOR UPDATE is not allowed in this context");
- ForUpdateNotAllowed = 0;
- $$ = cat3_str($1, $2, $3);
- }
+SelectStmt: select_clause
+ { FoundSort = 0; }
+ sort_clause for_update_clause opt_select_limit
+ {
+ if (strlen($4) > 0 && ForUpdateNotAllowed != 0)
+ mmerror(ET_ERROR, "FOR UPDATE is not allowed in this context");
+
+ ForUpdateNotAllowed = 0;
+ $$ = cat_str(4, $1, $3, $4, $5);
+ }
-/***S*I***/
/* This rule parses Select statements including UNION INTERSECT and EXCEPT.
* '(' and ')' can be used to specify the order of the operations
* (UNION EXCEPT INTERSECT). Without the use of '(' and ')' we want the
*
* The sort_clause is not handled here!
*/
-select_w_o_sort: '(' select_w_o_sort ')'
+select_clause: '(' select_clause ')'
{
- $$ = make3_str(make1_str("("), $2, make1_str(")"));
+ $$ = cat_str(3, make_str("("), $2, make_str(")"));
}
| SubSelect
{
- $$ = $1;
+ FoundInto = 0;
+ $$ = $1;
}
- | select_w_o_sort EXCEPT select_w_o_sort
+ | select_clause EXCEPT select_clause
{
- $$ = cat3_str($1, make1_str("except"), $3);
+ $$ = cat_str(3, $1, make_str("except"), $3);
ForUpdateNotAllowed = 1;
}
- | select_w_o_sort UNION opt_union select_w_o_sort
+ | select_clause UNION opt_all select_clause
{
- $$ = cat3_str($1, make1_str("union"), $3);
+ $$ = cat_str(4, $1, make_str("union"), $3, $4);
ForUpdateNotAllowed = 1;
}
- | select_w_o_sort INTERSECT opt_union select_w_o_sort
+ | select_clause INTERSECT opt_all select_clause
{
- $$ = cat3_str($1, make1_str("intersect"), $3);
+ $$ = cat_str(3, $1, make_str("intersect"), $3);
ForUpdateNotAllowed = 1;
}
;
-/***S*I***/
-SubSelect: SELECT opt_unique res_target_list2
+SubSelect: SELECT opt_distinct target_list
result from_clause where_clause
group_clause having_clause
{
- $$ = cat4_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8);
if (strlen($7) > 0 || strlen($8) > 0)
ForUpdateNotAllowed = 1;
+ $$ = cat_str(8, make_str("select"), $2, $3, $4, $5, $6, $7, $8);
}
;
-result: INTO opt_table relation_name { $$= cat3_str(make1_str("into"), $2, $3); }
- | INTO into_list { $$ = make1_str(""); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+result: INTO OptTemp opt_table relation_name { FoundInto = 1;
+ $$= cat_str(4, make_str("into"), $2, $3, $4);
+ }
+ | INTO into_list { $$ = EMPTY; }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_table: TABLE { $$ = make1_str("table"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_table: TABLE { $$ = make_str("table"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_union: ALL { $$ = make1_str("all"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_all: ALL { $$ = make_str("all"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_unique: DISTINCT { $$ = make1_str("distinct"); }
- | DISTINCT ON ColId { $$ = cat2_str(make1_str("distinct on"), $3); }
- | ALL { $$ = make1_str("all"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_distinct: DISTINCT { $$ = make_str("distinct"); }
+ | DISTINCT ON '(' expr_list ')' { $$ = cat_str(3, make_str("distinct on ("), $4, make_str(")")); }
+ | ALL { $$ = make_str("all"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-sort_clause: ORDER BY sortby_list { $$ = cat2_str(make1_str("order by"), $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+sort_clause: ORDER BY sortby_list {
+ FoundSort = 1;
+ $$ = cat2_str(make_str("order by"), $3);
+ }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
sortby_list: sortby { $$ = $1; }
- | sortby_list ',' sortby { $$ = cat3_str($1, make1_str(","), $3); }
+ | sortby_list ',' sortby { $$ = cat_str(3, $1, make_str(","), $3); }
;
sortby: a_expr OptUseOp
}
;
-OptUseOp: USING Op { $$ = cat2_str(make1_str("using"), $2); }
- | USING '<' { $$ = make1_str("using <"); }
- | USING '>' { $$ = make1_str("using >"); }
- | ASC { $$ = make1_str("asc"); }
- | DESC { $$ = make1_str("desc"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
- ;
+OptUseOp: USING all_Op { $$ = cat2_str(make_str("using"), $2); }
+ | ASC { $$ = make_str("asc"); }
+ | DESC { $$ = make_str("desc"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
+ ;
+
+opt_select_limit: LIMIT select_limit_value ',' select_offset_value
+ { $$ = cat_str(4, make_str("limit"), $2, make_str(","), $4); }
+ | LIMIT select_limit_value OFFSET select_offset_value
+ { $$ = cat_str(4, make_str("limit"), $2, make_str("offset"), $4); }
+ | LIMIT select_limit_value
+ { $$ = cat2_str(make_str("limit"), $2); }
+ | OFFSET select_offset_value LIMIT select_limit_value
+ { $$ = cat_str(4, make_str("offset"), $2, make_str("limit"), $4); }
+ | OFFSET select_offset_value
+ { $$ = cat2_str(make_str("offset"), $2); }
+ | /* EMPTY */
+ { $$ = EMPTY; }
+ ;
+
+select_limit_value: Iconst { $$ = $1; }
+ | ALL { $$ = make_str("all"); }
+ | PARAM { $$ = make_name(); }
+ ;
+
+select_offset_value: Iconst { $$ = $1; }
+ | PARAM { $$ = make_name(); }
+ ;
/*
* jimmy bell-style recursive queries aren't supported in the
* ...however, recursive addattr and rename supported. make special
* cases for these.
*/
-opt_inh_star: '*' { $$ = make1_str("*"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_inh_star: '*' { $$ = make_str("*"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
relation_name_list: name_list { $$ = $1; };
name_list: name
{ $$ = $1; }
| name_list ',' name
- { $$ = cat3_str($1, make1_str(","), $3); }
+ { $$ = cat_str(3, $1, make_str(","), $3); }
;
-group_clause: GROUP BY expr_list { $$ = cat2_str(make1_str("groub by"), $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+group_clause: GROUP BY expr_list { $$ = cat2_str(make_str("group by"), $3); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
having_clause: HAVING a_expr
{
- $$ = cat2_str(make1_str("having"), $2);
+ $$ = cat2_str(make_str("having"), $2);
}
- | /*EMPTY*/ { $$ = make1_str(""); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-for_update_clause:
- FOR UPDATE
- {
- $$ = make1_str("for update");
- }
- | FOR UPDATE OF va_list
- {
- $$ = cat2_str(make1_str("for update of"), $4);
- }
- | /* EMPTY */
- {
- $$ = make1_str("");
- }
+for_update_clause: FOR UPDATE update_list
+ {
+ $$ = make_str("for update");
+ }
+ | FOR READ ONLY
+ {
+ $$ = make_str("for read only");
+ }
+ | /* EMPTY */
+ {
+ $$ = EMPTY;
+ }
;
+update_list: OF va_list
+ {
+ $$ = cat2_str(make_str("of"), $2);
+ }
+ | /* EMPTY */
+ {
+ $$ = EMPTY;
+ }
+ ;
/*****************************************************************************
*
* clauses common to all Optimizable Stmts:
- * from_clause -
- * where_clause -
+ * from_clause - allow list of both JOIN expressions and table names
+ * where_clause - qualifications for joins or restrictions
*
*****************************************************************************/
-from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')'
- {
- yyerror("JOIN not yet implemented");
- }
- | FROM from_list { $$ = cat2_str(make1_str("from"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+from_clause: FROM from_list { $$ = cat2_str(make_str("from"), $2); }
+/***
+#ifdef ENABLE_ORACLE_JOIN_SYNTAX
+ | FROM oracle_list { $$ = cat2_str(make_str("from"), $2); }
+#endif
+***/
+ | FROM from_expr { $$ = cat2_str(make_str("from"), $2); }
+ | /* EMPTY */ { $$ = EMPTY; }
;
-from_list: from_list ',' from_val
- { $$ = cat3_str($1, make1_str(","), $3); }
- | from_val CROSS JOIN from_val
- { yyerror("CROSS JOIN not yet implemented"); }
- | from_val
- { $$ = $1; }
- ;
+from_list: from_list ',' table_expr { $$ = cat_str(3, $1, make_str(","), $3); }
+ | table_expr { $$ = $1; }
+ ;
-from_val: relation_expr AS ColLabel
- {
- $$ = cat3_str($1, make1_str("as"), $3);
- }
- | relation_expr ColId
- {
- $$ = cat2_str($1, $2);
- }
- | relation_expr
- {
- $$ = $1;
- }
- ;
+/***********
+ * This results in one shift/reduce conflict, presumably due to the trailing "(
+ * - Thomas 1999-09-20
+ *
+#ifdef ENABLE_ORACLE_JOIN_SYNTAX
+oracle_list: oracle_expr { $$ = $1; }
+ ;
-join_expr: NATURAL join_expr { $$ = cat2_str(make1_str("natural"), $2); }
- | FULL join_outer
- { yyerror("FULL OUTER JOIN not yet implemented"); }
- | LEFT join_outer
- { yyerror("LEFT OUTER JOIN not yet implemented"); }
- | RIGHT join_outer
- { yyerror("RIGHT OUTER JOIN not yet implemented"); }
- | OUTER_P
- { yyerror("OUTER JOIN not yet implemented"); }
- | INNER_P
- { yyerror("INNER JOIN not yet implemented"); }
- | UNION
- { yyerror("UNION JOIN not yet implemented"); }
- | /*EMPTY*/
- { yyerror("INNER JOIN not yet implemented"); }
+oracle_expr: ColId ',' ColId oracle_outer
+ {
+ mmerror(ET_ERROR, "Oracle OUTER JOIN not yet supported");
+ $$ = cat_str(3, $1, make_str(","), $3); }
+ }
+ | oracle_outer ColId ',' ColId
+ {
+ mmerror(ET_ERROR, "Oracle OUTER JOIN not yet supported");
+ $$ = cat_str(4, $1, $2, make_str(","), $3); }
+ }
;
-join_outer: OUTER_P { $$ = make1_str("outer"); }
- | /*EMPTY*/ { $$ = make1_str(""); /* no qualifiers */ }
- ;
+oracle_outer: '(' '+' ')' { $$ = make_str("(+)"); }
+ ;
+#endif
+*************/
-join_spec: ON '(' a_expr ')' { $$ = make3_str(make1_str("on ("), $3, make1_str(")")); }
- | USING '(' join_list ')' { $$ = make3_str(make1_str("using ("), $3, make1_str(")")); }
- | /*EMPTY*/ { $$ = make1_str(""); /* no qualifiers */ }
- ;
+from_expr: '(' join_clause_with_union ')' alias_clause
+ { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
+ | join_clause
+ { $$ = $1; }
+ ;
-join_list: join_using { $$ = $1; }
- | join_list ',' join_using { $$ = cat3_str($1, make1_str(","), $3); }
- ;
+table_expr: relation_expr alias_clause
+ {
+ $$ = cat2_str($1, $2);
+ }
+ ;
-join_using: ColId
- {
- $$ = $1;
- }
- | ColId '.' ColId
- {
- $$ = make3_str($1, make1_str("."), $3);
- }
- | Iconst
- {
- $$ = $1;;
- }
+alias_clause: AS ColId '(' name_list ')'
+ { $$ = cat_str(5, make_str("as"), $2, make_str("("), $4, make_str(")")); }
+ | AS ColId
+ { $$ = cat2_str(make_str("as"), $2); }
+ | ColId '(' name_list ')'
+ { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
+ | ColId
+ { $$ = $1; }
+ | /*EMPTY*/
+ { $$ = EMPTY; }
;
-where_clause: WHERE a_expr { $$ = cat2_str(make1_str("where"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); /* no qualifiers */ }
- ;
+/* A UNION JOIN is the same as a FULL OUTER JOIN which *omits*
+ * all result rows which would have matched on an INNER JOIN.
+ * Syntactically, must enclose the UNION JOIN in parens to avoid
+ * conflicts with SELECT/UNION.
+ */
+join_clause: join_clause join_expr
+ { $$ = cat2_str($1, $2); }
+ | table_expr join_expr
+ { $$ = cat2_str($1, $2); }
+ ;
+
+/* This is everything but the left side of a join.
+ * Note that a CROSS JOIN is the same as an unqualified
+ * inner join, so just pass back the right-side table.
+ * A NATURAL JOIN implicitly matches column names between
+ * tables, and the shape is determined by which columns are
+ * in common. We'll collect columns during the later transformations.
+ */
+join_expr: join_type JOIN table_expr join_qual
+ {
+ $$ = cat_str(4, $1, make_str("join"), $3, $4);
+ }
+ | NATURAL join_type JOIN table_expr
+ {
+ $$ = cat_str(4, make_str("natural"), $2, make_str("join"), $4);
+ }
+ | CROSS JOIN table_expr
+ { $$ = cat2_str(make_str("cross join"), $3); }
+ ;
+
+join_clause_with_union: join_clause_with_union join_expr_with_union
+ { $$ = cat2_str($1, $2); }
+ | table_expr join_expr_with_union
+ { $$ = cat2_str($1, $2); }
+ ;
+
+join_expr_with_union: join_expr
+ { $$ = $1; }
+ | UNION JOIN table_expr
+ { $$ = cat2_str(make_str("union join"), $3); }
+ ;
+
+/* OUTER is just noise... */
+join_type: FULL join_outer { $$ = cat2_str(make_str("full"), $2); }
+ | LEFT join_outer { $$ = cat2_str(make_str("left"), $2); }
+ | RIGHT join_outer { $$ = cat2_str(make_str("right"), $2); }
+ | OUTER_P { $$ = make_str("outer"); }
+ | INNER_P { $$ = make_str("inner"); }
+ | /* EMPTY */ { $$ = EMPTY; }
+ ;
+
+join_outer: OUTER_P { $$ = make_str("outer"); }
+ | /*EMPTY*/ { $$ = EMPTY; /* no qualifiers */ }
+ ;
+
+/* JOIN qualification clauses
+ * Possibilities are:
+ * USING ( column list ) allows only unqualified column names,
+ * which must match between tables.
+ * ON expr allows more general qualifications.
+ * - thomas 1999-01-07
+ */
+
+join_qual: USING '(' using_list ')' { $$ = cat_str(3, make_str("using ("), $3, make_str(")")); }
+ | ON a_expr { $$ = cat2_str(make_str("on"), $2); }
+ ;
+
+using_list: using_list ',' using_expr { $$ = cat_str(3, $1, make_str(","), $3); }
+ | using_expr { $$ = $1; }
+ ;
+
+using_expr: ColId
+ {
+ $$ = $1;
+ }
+ ;
+
+where_clause: WHERE a_expr { $$ = cat2_str(make_str("where"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; /* no qualifiers */ }
+ ;
relation_expr: relation_name
{
| relation_name '*' %prec '='
{
/* inheritance query */
- $$ = cat2_str($1, make1_str("*"));
+ $$ = cat2_str($1, make_str("*"));
}
-opt_array_bounds: '[' ']' nest_array_bounds
+opt_array_bounds: '[' ']' opt_array_bounds
{
$$.index1 = 0;
$$.index2 = $3.index1;
- $$.str = cat2_str(make1_str("[]"), $3.str);
+ $$.str = cat2_str(make_str("[]"), $3.str);
}
- | '[' Iconst ']' nest_array_bounds
+ | '[' Iresult ']' opt_array_bounds
{
- $$.index1 = atol($2);
+ char *txt = mm_alloc(20L);
+
+ sprintf (txt, "%d", $2);
+ $$.index1 = $2;
$$.index2 = $4.index1;
- $$.str = cat4_str(make1_str("["), $2, make1_str("]"), $4.str);
+ $$.str = cat_str(4, make_str("["), txt, make_str("]"), $4.str);
}
| /* EMPTY */
{
$$.index1 = -1;
$$.index2 = -1;
- $$.str= make1_str("");
+ $$.str= EMPTY;
}
;
-nest_array_bounds: '[' ']' nest_array_bounds
- {
- $$.index1 = 0;
- $$.index2 = $3.index1;
- $$.str = cat2_str(make1_str("[]"), $3.str);
- }
- | '[' Iconst ']' nest_array_bounds
- {
- $$.index1 = atol($2);
- $$.index2 = $4.index1;
- $$.str = cat4_str(make1_str("["), $2, make1_str("]"), $4.str);
- }
- | /* EMPTY */
- {
- $$.index1 = -1;
- $$.index2 = -1;
- $$.str= make1_str("");
- }
- ;
+Iresult: Iconst { $$ = atol($1); }
+ | '(' Iresult ')' { $$ = $2; }
+ | Iresult '+' Iresult { $$ = $1 + $3; }
+ | Iresult '-' Iresult { $$ = $1 - $3; }
+ | Iresult '*' Iresult { $$ = $1 * $3; }
+ | Iresult '/' Iresult { $$ = $1 / $3; }
+ | Iresult '%' Iresult { $$ = $1 % $3; }
+ ;
+
/*****************************************************************************
*
*
*****************************************************************************/
-Typename: Array opt_array_bounds
+Typename: SimpleTypename opt_array_bounds
{
$$ = cat2_str($1, $2.str);
}
- | Character { $$ = $1; }
- | SETOF Array
+ | SETOF SimpleTypename
{
- $$ = cat2_str(make1_str("setof"), $2);
+ $$ = cat2_str(make_str("setof"), $2);
}
;
-Array: Generic
+SimpleTypename: Generic { $$ = $1; }
| Datetime { $$ = $1; }
| Numeric { $$ = $1; }
+ | Character { $$ = $1; }
;
Generic: generic
;
generic: ident { $$ = $1; }
- | TYPE_P { $$ = make1_str("type"); }
+ | TYPE_P { $$ = make_str("type"); }
+ | SQL_AT { $$ = make_str("at"); }
+ | SQL_AUTOCOMMIT { $$ = make_str("autocommit"); }
+ | SQL_BOOL { $$ = make_str("bool"); }
+ | SQL_BREAK { $$ = make_str("break"); }
+ | SQL_CALL { $$ = make_str("call"); }
+ | SQL_CONNECT { $$ = make_str("connect"); }
+ | SQL_CONNECTION { $$ = make_str("connection"); }
+ | SQL_CONTINUE { $$ = make_str("continue"); }
+ | SQL_DEALLOCATE { $$ = make_str("deallocate"); }
+ | SQL_DISCONNECT { $$ = make_str("disconnect"); }
+ | SQL_FOUND { $$ = make_str("found"); }
+ | SQL_GO { $$ = make_str("go"); }
+ | SQL_GOTO { $$ = make_str("goto"); }
+ | SQL_IDENTIFIED { $$ = make_str("identified"); }
+ | SQL_INDICATOR { $$ = make_str("indicator"); }
+ | SQL_INT { $$ = make_str("int"); }
+ | SQL_LONG { $$ = make_str("long"); }
+ | SQL_OFF { $$ = make_str("off"); }
+ | SQL_OPEN { $$ = make_str("open"); }
+ | SQL_PREPARE { $$ = make_str("prepare"); }
+ | SQL_RELEASE { $$ = make_str("release"); }
+ | SQL_SECTION { $$ = make_str("section"); }
+ | SQL_SHORT { $$ = make_str("short"); }
+ | SQL_SIGNED { $$ = make_str("signed"); }
+ | SQL_SQLERROR { $$ = make_str("sqlerror"); }
+ | SQL_SQLPRINT { $$ = make_str("sqlprint"); }
+ | SQL_SQLWARNING { $$ = make_str("sqlwarning"); }
+ | SQL_STOP { $$ = make_str("stop"); }
+ | SQL_STRUCT { $$ = make_str("struct"); }
+ | SQL_UNSIGNED { $$ = make_str("unsigned"); }
+ | SQL_VAR { $$ = make_str("var"); }
+ | SQL_WHENEVER { $$ = make_str("whenever"); }
;
/* SQL92 numeric data types
*/
Numeric: FLOAT opt_float
{
- $$ = cat2_str(make1_str("float"), $2);
+ $$ = cat2_str(make_str("float"), $2);
}
| DOUBLE PRECISION
{
- $$ = make1_str("double precision");
+ $$ = make_str("double precision");
}
| DECIMAL opt_decimal
{
- $$ = cat2_str(make1_str("decimal"), $2);
+ $$ = cat2_str(make_str("decimal"), $2);
+ }
+ | DEC opt_decimal
+ {
+ $$ = cat2_str(make_str("dec"), $2);
}
| NUMERIC opt_numeric
{
- $$ = cat2_str(make1_str("numeric"), $2);
+ $$ = cat2_str(make_str("numeric"), $2);
}
;
numeric: FLOAT
- { $$ = make1_str("float"); }
+ { $$ = make_str("float"); }
| DOUBLE PRECISION
- { $$ = make1_str("double precision"); }
+ { $$ = make_str("double precision"); }
| DECIMAL
- { $$ = make1_str("decimal"); }
+ { $$ = make_str("decimal"); }
| NUMERIC
- { $$ = make1_str("numeric"); }
+ { $$ = make_str("numeric"); }
;
opt_float: '(' Iconst ')'
{
if (atol($2) < 1)
- yyerror("precision for FLOAT must be at least 1");
+ mmerror(ET_ERROR, "precision for FLOAT must be at least 1");
else if (atol($2) >= 16)
- yyerror("precision for FLOAT must be less than 16");
- $$ = make3_str(make1_str("("), $2, make1_str(")"));
+ mmerror(ET_ERROR, "precision for FLOAT must be less than 16");
+ $$ = cat_str(3, make_str("("), $2, make_str(")"));
}
| /*EMPTY*/
{
- $$ = make1_str("");
+ $$ = EMPTY;
}
;
{
if (atol($2) < 1 || atol($2) > NUMERIC_MAX_PRECISION) {
sprintf(errortext, "NUMERIC precision %s must be between 1 and %d", $2, NUMERIC_MAX_PRECISION);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
if (atol($4) < 0 || atol($4) > atol($2)) {
sprintf(errortext, "NUMERIC scale %s must be between 0 and precision %s", $4, $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = cat3_str(make2_str(make1_str("("), $2), make1_str(","), make2_str($4, make1_str(")")));
+ $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")"));
}
| '(' Iconst ')'
{
if (atol($2) < 1 || atol($2) > NUMERIC_MAX_PRECISION) {
sprintf(errortext, "NUMERIC precision %s must be between 1 and %d", $2, NUMERIC_MAX_PRECISION);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = make3_str(make1_str("("), $2, make1_str(")"));
+ $$ = cat_str(3, make_str("("), $2, make_str(")"));
}
| /*EMPTY*/
{
- $$ = make1_str("");
+ $$ = EMPTY;
}
;
{
if (atol($2) < 1 || atol($2) > NUMERIC_MAX_PRECISION) {
sprintf(errortext, "NUMERIC precision %s must be between 1 and %d", $2, NUMERIC_MAX_PRECISION);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
if (atol($4) < 0 || atol($4) > atol($2)) {
sprintf(errortext, "NUMERIC scale %s must be between 0 and precision %s", $4, $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = cat3_str(make2_str(make1_str("("), $2), make1_str(","), make2_str($4, make1_str(")")));
+ $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")"));
}
| '(' Iconst ')'
{
if (atol($2) < 1 || atol($2) > NUMERIC_MAX_PRECISION) {
sprintf(errortext, "NUMERIC precision %s must be between 1 and %d", $2, NUMERIC_MAX_PRECISION);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = make3_str(make1_str("("), $2, make1_str(")"));
+ $$ = cat_str(3, make_str("("), $2, make_str(")"));
}
| /*EMPTY*/
{
- $$ = make1_str("");
+ $$ = EMPTY;
}
;
-/* SQL92 character data types
+/*
+ * SQL92 character data types
* The following implements CHAR() and VARCHAR().
- * We do it here instead of the 'Generic' production
- * because we don't want to allow arrays of VARCHAR().
- * I haven't thought about whether that will work or not.
* - ay 6/95
*/
Character: character '(' Iconst ')'
{
- if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar")))
- yyerror("internal parsing error; unrecognized character type");
- if (atol($3) < 1) {
- sprintf(errortext, "length for '%s' type must be at least 1",$1);
- yyerror(errortext);
+ if (atol($3) < 1)
+ {
+ sprintf(errortext, "length for type '%s' type must be at least 1",$1);
+ mmerror(ET_ERROR, errortext);
}
- else if (atol($3) > 4096) {
- /* we can store a char() of length up to the size
- * of a page (8KB) - page headers and friends but
- * just to be safe here... - ay 6/95
- * XXX note this hardcoded limit - thomas 1997-07-13
- */
- sprintf(errortext, "length for type '%s' cannot exceed 4096",$1);
- yyerror(errortext);
+ else if (atol($3) > MaxAttrSize)
+ {
+ sprintf(errortext, "length for type '%s' cannot exceed %ld", $1, MaxAttrSize);
+ mmerror(ET_ERROR, errortext);
}
- $$ = cat2_str($1, make3_str(make1_str("("), $3, make1_str(")")));
+ $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));
}
| character
{
character: CHARACTER opt_varying opt_charset opt_collate
{
- if (strlen($4) > 0)
- fprintf(stderr, "COLLATE %s not yet implemented",$4);
+ if (strlen($4) > 0)
+ {
+ sprintf(errortext, "COLLATE %s not yet implemented", $4);
+ mmerror(ET_WARN, errortext);
+ }
- $$ = cat4_str(make1_str("character"), $2, $3, $4);
+ $$ = cat_str(4, make_str("character"), $2, $3, $4);
}
- | CHAR opt_varying { $$ = cat2_str(make1_str("char"), $2); }
- | VARCHAR { $$ = make1_str("varchar"); }
- | NATIONAL CHARACTER opt_varying { $$ = cat2_str(make1_str("national character"), $3); }
- | NCHAR opt_varying { $$ = cat2_str(make1_str("nchar"), $2); }
+ | CHAR opt_varying { $$ = cat2_str(make_str("char"), $2); }
+ | VARCHAR { $$ = make_str("varchar"); }
+ | NATIONAL CHARACTER opt_varying { $$ = cat2_str(make_str("national character"), $3); }
+ | NCHAR opt_varying { $$ = cat2_str(make_str("nchar"), $2); }
;
-opt_varying: VARYING { $$ = make1_str("varying"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_varying: VARYING { $$ = make_str("varying"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_charset: CHARACTER SET ColId { $$ = cat2_str(make1_str("character set"), $3); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_charset: CHARACTER SET ColId { $$ = cat2_str(make_str("character set"), $3); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-opt_collate: COLLATE ColId { $$ = cat2_str(make1_str("collate"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_collate: COLLATE ColId { $$ = cat2_str(make_str("collate"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
Datetime: datetime
}
| TIMESTAMP opt_timezone
{
- $$ = cat2_str(make1_str("timestamp"), $2);
+ $$ = cat2_str(make_str("timestamp"), $2);
}
| TIME
{
- $$ = make1_str("time");
+ $$ = make_str("time");
}
| INTERVAL opt_interval
{
- $$ = cat2_str(make1_str("interval"), $2);
+ $$ = cat2_str(make_str("interval"), $2);
}
;
-datetime: YEAR_P { $$ = make1_str("year"); }
- | MONTH_P { $$ = make1_str("month"); }
- | DAY_P { $$ = make1_str("day"); }
- | HOUR_P { $$ = make1_str("hour"); }
- | MINUTE_P { $$ = make1_str("minute"); }
- | SECOND_P { $$ = make1_str("second"); }
+datetime: YEAR_P { $$ = make_str("year"); }
+ | MONTH_P { $$ = make_str("month"); }
+ | DAY_P { $$ = make_str("day"); }
+ | HOUR_P { $$ = make_str("hour"); }
+ | MINUTE_P { $$ = make_str("minute"); }
+ | SECOND_P { $$ = make_str("second"); }
;
-opt_timezone: WITH TIME ZONE { $$ = make1_str("with time zone"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+opt_timezone: WITH TIME ZONE { $$ = make_str("with time zone"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
opt_interval: datetime { $$ = $1; }
- | YEAR_P TO MONTH_P { $$ = make1_str("year to #month"); }
- | DAY_P TO HOUR_P { $$ = make1_str("day to hour"); }
- | DAY_P TO MINUTE_P { $$ = make1_str("day to minute"); }
- | DAY_P TO SECOND_P { $$ = make1_str("day to second"); }
- | HOUR_P TO MINUTE_P { $$ = make1_str("hour to minute"); }
- | MINUTE_P TO SECOND_P { $$ = make1_str("minute to second"); }
- | HOUR_P TO SECOND_P { $$ = make1_str("hour to second"); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+ | YEAR_P TO MONTH_P { $$ = make_str("year to #month"); }
+ | DAY_P TO HOUR_P { $$ = make_str("day to hour"); }
+ | DAY_P TO MINUTE_P { $$ = make_str("day to minute"); }
+ | DAY_P TO SECOND_P { $$ = make_str("day to second"); }
+ | HOUR_P TO MINUTE_P { $$ = make_str("hour to minute"); }
+ | MINUTE_P TO SECOND_P { $$ = make_str("minute to second"); }
+ | HOUR_P TO SECOND_P { $$ = make_str("hour to second"); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
/*****************************************************************************
*
- * expression grammar, still needs some cleanup
+ * expression grammar
*
*****************************************************************************/
{ $$ = $1; }
| NULL_P
{
- $$ = make1_str("null");
+ $$ = make_str("null");
}
;
/* Expressions using row descriptors
* Define row_descriptor to allow yacc to break the reduce/reduce conflict
* with singleton expressions.
- * Eliminated lots of code by defining row_op and sub_type clauses.
- * However, can not consolidate EXPR_LINK case with others subselects
- * due to shift/reduce conflict with the non-subselect clause (the parser
- * would have to look ahead more than one token to resolve the conflict).
- * - thomas 1998-05-09
*/
row_expr: '(' row_descriptor ')' IN '(' SubSelect ')'
{
- $$ = make5_str(make1_str("("), $2, make1_str(") in ("), $6, make1_str(")"));
+ $$ = cat_str(5, make_str("("), $2, make_str(") in ("), $6, make_str(")"));
}
| '(' row_descriptor ')' NOT IN '(' SubSelect ')'
{
- $$ = make5_str(make1_str("("), $2, make1_str(") not in ("), $7, make1_str(")"));
+ $$ = cat_str(5, make_str("("), $2, make_str(") not in ("), $7, make_str(")"));
}
- | '(' row_descriptor ')' row_op sub_type '(' SubSelect ')'
+ | '(' row_descriptor ')' all_Op sub_type '(' SubSelect ')'
{
- $$ = make4_str(make5_str(make1_str("("), $2, make1_str(")"), $4, $5), make1_str("("), $7, make1_str(")"));
+ $$ = cat_str(8, make_str("("), $2, make_str(")"), $4, $5, make_str("("), $7, make_str(")"));
}
- | '(' row_descriptor ')' row_op '(' SubSelect ')'
+ | '(' row_descriptor ')' all_Op '(' SubSelect ')'
{
- $$ = make3_str(make5_str(make1_str("("), $2, make1_str(")"), $4, make1_str("(")), $6, make1_str(")"));
+ $$ = cat_str(7, make_str("("), $2, make_str(")"), $4, make_str("("), $6, make_str(")"));
}
- | '(' row_descriptor ')' row_op '(' row_descriptor ')'
+ | '(' row_descriptor ')' all_Op '(' row_descriptor ')'
{
- $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("("), $6, make1_str(")")));
+ $$ = cat_str(7, make_str("("), $2, make_str(")"), $4, make_str("("), $6, make_str(")"));
}
;
row_descriptor: row_list ',' a_expr
{
- $$ = cat3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
;
-row_op: Op { $$ = $1; }
- | '<' { $$ = "<"; }
- | '=' { $$ = "="; }
- | '>' { $$ = ">"; }
- | '+' { $$ = "+"; }
- | '-' { $$ = "-"; }
- | '*' { $$ = "*"; }
- | '/' { $$ = "/"; }
- ;
-
-sub_type: ANY { $$ = make1_str("ANY"); }
- | ALL { $$ = make1_str("ALL"); }
+sub_type: ANY { $$ = make_str("ANY"); }
+ | ALL { $$ = make_str("ALL"); }
;
row_list: row_list ',' a_expr
{
- $$ = cat3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
| a_expr
{
}
;
+all_Op: Op | MathOp;
+
+MathOp: '+' { $$ = make_str("+"); }
+ | '-' { $$ = make_str("-"); }
+ | '*' { $$ = make_str("*"); }
+ | '%' { $$ = make_str("%"); }
+ | '^' { $$ = make_str("^"); }
+ | '|' { $$ = make_str("|"); }
+ | '/' { $$ = make_str("/"); }
+ | '<' { $$ = make_str("<"); }
+ | '>' { $$ = make_str(">"); }
+ | '=' { $$ = make_str("="); }
+ ;
+
/* General expressions
* This is the heart of the expression syntax.
- * Note that the BETWEEN clause looks similar to a boolean expression
- * and so we must define b_expr which is almost the same as a_expr
- * but without the boolean expressions.
- * All operations/expressions are allowed in a BETWEEN clause
- * if surrounded by parens.
+ *
+ * We have two expression types: a_expr is the unrestricted kind, and
+ * b_expr is a subset that must be used in some places to avoid shift/reduce
+ * conflicts. For example, we can't do BETWEEN as "BETWEEN a_expr AND a_expr"
+ * because that use of AND conflicts with AND as a boolean operator. So,
+ * b_expr is used in BETWEEN and we remove boolean keywords from b_expr.
+ *
+ * Note that '(' a_expr ')' is a b_expr, so an unrestricted expression can
+ * always be used by surrounding it with parens.
+ *
+ * c_expr is all the productions that are common to a_expr and b_expr;
+ * it's factored out just to eliminate redundant coding.
*/
-a_expr: attr opt_indirection
- {
- $$ = cat2_str($1, $2);
- }
- | row_expr
- { $$ = $1; }
- | AexprConst
- { $$ = $1; }
- | ColId
- {
- $$ = $1;
- }
+a_expr: c_expr
+ { $$ = $1; }
+ | a_expr TYPECAST Typename
+ { $$ = cat_str(3, $1, make_str("::"), $3); }
+ /*
+ * Can't collapse this into prior rule by using a_expr_or_null;
+ * that creates reduce/reduce conflicts. Grumble.
+ */
+ | NULL_P TYPECAST Typename
+ {
+ $$ = cat2_str(make_str("null::"), $3);
+ }
+ /*
+ * These operators must be called out explicitly in order to make use
+ * of yacc/bison's automatic operator-precedence handling. All other
+ * operator names are handled by the generic productions using "Op",
+ * below; and all those operators will have the same precedence.
+ *
+ * If you add more explicitly-known operators, be sure to add them
+ * also to b_expr and to the MathOp list above.
+ */
| '-' a_expr %prec UMINUS
- { $$ = cat2_str(make1_str("-"), $2); }
+ { $$ = cat2_str(make_str("-"), $2); }
+ | '%' a_expr
+ { $$ = cat2_str(make_str("%"), $2); }
+ | '^' a_expr
+ { $$ = cat2_str(make_str("^"), $2); }
+ | '|' a_expr
+ { $$ = cat2_str(make_str("|"), $2); }
+/* not possible in embedded sql | ':' a_expr
+ { $$ = cat2_str(make_str(":"), $2); }
+*/
+ | ';' a_expr
+ { $$ = cat2_str(make_str(";"), $2); }
+ | a_expr '%'
+ { $$ = cat2_str($1, make_str("%")); }
+ | a_expr '^'
+ { $$ = cat2_str($1, make_str("^")); }
+ | a_expr '|'
+ { $$ = cat2_str($1, make_str("|")); }
| a_expr '+' a_expr
- { $$ = cat3_str($1, make1_str("+"), $3); }
+ { $$ = cat_str(3, $1, make_str("+"), $3); }
| a_expr '-' a_expr
- { $$ = cat3_str($1, make1_str("-"), $3); }
- | a_expr '/' a_expr
- { $$ = cat3_str($1, make1_str("/"), $3); }
+ { $$ = cat_str(3, $1, make_str("-"), $3); }
| a_expr '*' a_expr
- { $$ = cat3_str($1, make1_str("*"), $3); }
+ { $$ = cat_str(3, $1, make_str("*"), $3); }
+ | a_expr '/' a_expr
+ { $$ = cat_str(3, $1, make_str("/"), $3); }
+ | a_expr '%' a_expr
+ { $$ = cat_str(3, $1, make_str("%"), $3); }
+ | a_expr '^' a_expr
+ { $$ = cat_str(3, $1, make_str("^"), $3); }
+ | a_expr '|' a_expr
+ { $$ = cat_str(3, $1, make_str("|"), $3); }
| a_expr '<' a_expr
- { $$ = cat3_str($1, make1_str("<"), $3); }
+ { $$ = cat_str(3, $1, make_str("<"), $3); }
| a_expr '>' a_expr
- { $$ = cat3_str($1, make1_str(">"), $3); }
+ { $$ = cat_str(3, $1, make_str(">"), $3); }
+ | a_expr '=' NULL_P
+ { $$ = cat2_str($1, make_str("= NULL")); }
+ /* We allow this for standards-broken SQL products, like MS stuff */
+ | NULL_P '=' a_expr
+ { $$ = cat2_str(make_str("= NULL"), $3); }
| a_expr '=' a_expr
- { $$ = cat3_str($1, make1_str("="), $3); }
-/* not possible in embedded sql | ':' a_expr
- { $$ = cat2_str(make1_str(":"), $2); }
-*/
- | ';' a_expr
- { $$ = cat2_str(make1_str(";"), $2); }
- | '|' a_expr
- { $$ = cat2_str(make1_str("|"), $2); }
- | a_expr TYPECAST Typename
- {
- $$ = cat3_str($1, make1_str("::"), $3);
- }
- | CAST '(' a_expr AS Typename ')'
- {
- $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")")));
- }
- | '(' a_expr_or_null ')'
- { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
+ { $$ = cat_str(3, $1, make_str("="), $3); }
| a_expr Op a_expr
- { $$ = cat3_str($1, $2, $3); }
- | a_expr LIKE a_expr
- { $$ = cat3_str($1, make1_str("like"), $3); }
- | a_expr NOT LIKE a_expr
- { $$ = cat3_str($1, make1_str("not like"), $4); }
+ { $$ = cat_str(3, $1, $2, $3); }
| Op a_expr
{ $$ = cat2_str($1, $2); }
| a_expr Op
{ $$ = cat2_str($1, $2); }
- | func_name '(' '*' ')'
- {
- $$ = cat2_str($1, make1_str("(*)"));
- }
- | func_name '(' ')'
- {
- $$ = cat2_str($1, make1_str("()"));
- }
- | func_name '(' expr_list ')'
- {
- $$ = make4_str($1, make1_str("("), $3, make1_str(")"));
- }
- | CURRENT_DATE
- {
- $$ = make1_str("current_date");
- }
- | CURRENT_TIME
- {
- $$ = make1_str("current_time");
- }
- | CURRENT_TIME '(' Iconst ')'
- {
- if (atol($3) != 0)
- fprintf(stderr,"CURRENT_TIME(%s) precision not implemented; zero used instead", $3);
- $$ = make1_str("current_time");
- }
- | CURRENT_TIMESTAMP
- {
- $$ = make1_str("current_timestamp");
- }
- | CURRENT_TIMESTAMP '(' Iconst ')'
- {
- if (atol($3) != 0)
- fprintf(stderr,"CURRENT_TIMESTAMP(%s) precision not implemented; zero used instead",$3);
- $$ = make1_str("current_timestamp");
- }
- | CURRENT_USER
- {
- $$ = make1_str("current_user");
- }
- | USER
- {
- $$ = make1_str("user");
- }
-
- | EXISTS '(' SubSelect ')'
- {
- $$ = make3_str(make1_str("exists("), $3, make1_str(")"));
- }
- | EXTRACT '(' extract_list ')'
- {
- $$ = make3_str(make1_str("extract("), $3, make1_str(")"));
- }
- | POSITION '(' position_list ')'
- {
- $$ = make3_str(make1_str("position("), $3, make1_str(")"));
- }
- | SUBSTRING '(' substr_list ')'
- {
- $$ = make3_str(make1_str("substring("), $3, make1_str(")"));
- }
- /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
- | TRIM '(' BOTH trim_list ')'
- {
- $$ = make3_str(make1_str("trim(both"), $4, make1_str(")"));
- }
- | TRIM '(' LEADING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")"));
- }
- | TRIM '(' TRAILING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")"));
- }
- | TRIM '(' trim_list ')'
- {
- $$ = make3_str(make1_str("trim("), $3, make1_str(")"));
- }
+ | a_expr AND a_expr
+ { $$ = cat_str(3, $1, make_str("and"), $3); }
+ | a_expr OR a_expr
+ { $$ = cat_str(3, $1, make_str("or"), $3); }
+ | NOT a_expr
+ { $$ = cat2_str(make_str("not"), $2); }
+ | a_expr LIKE a_expr
+ { $$ = cat_str(3, $1, make_str("like"), $3); }
+ | a_expr NOT LIKE a_expr
+ { $$ = cat_str(3, $1, make_str("not like"), $4); }
| a_expr ISNULL
- { $$ = cat2_str($1, make1_str("isnull")); }
+ { $$ = cat2_str($1, make_str("isnull")); }
| a_expr IS NULL_P
- { $$ = cat2_str($1, make1_str("is null")); }
+ { $$ = cat2_str($1, make_str("is null")); }
| a_expr NOTNULL
- { $$ = cat2_str($1, make1_str("notnull")); }
+ { $$ = cat2_str($1, make_str("notnull")); }
| a_expr IS NOT NULL_P
- { $$ = cat2_str($1, make1_str("is not null")); }
+ { $$ = cat2_str($1, make_str("is not null")); }
/* IS TRUE, IS FALSE, etc used to be function calls
* but let's make them expressions to allow the optimizer
* a chance to eliminate them if a_expr is a constant string.
* - thomas 1997-12-22
*/
| a_expr IS TRUE_P
- {
- { $$ = cat2_str($1, make1_str("is true")); }
- }
+ { $$ = cat2_str($1, make_str("is true")); }
| a_expr IS NOT FALSE_P
- {
- { $$ = cat2_str($1, make1_str("is not false")); }
- }
+ { $$ = cat2_str($1, make_str("is not false")); }
| a_expr IS FALSE_P
- {
- { $$ = cat2_str($1, make1_str("is false")); }
- }
+ { $$ = cat2_str($1, make_str("is false")); }
| a_expr IS NOT TRUE_P
- {
- { $$ = cat2_str($1, make1_str("is not true")); }
- }
+ { $$ = cat2_str($1, make_str("is not true")); }
| a_expr BETWEEN b_expr AND b_expr
{
- $$ = cat5_str($1, make1_str("between"), $3, make1_str("and"), $5);
+ $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5);
}
| a_expr NOT BETWEEN b_expr AND b_expr
{
- $$ = cat5_str($1, make1_str("not between"), $4, make1_str("and"), $6);
+ $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6);
}
| a_expr IN '(' in_expr ')'
{
- $$ = make4_str($1, make1_str("in ("), $4, make1_str(")"));
- }
- | a_expr NOT IN '(' not_in_expr ')'
- {
- $$ = make4_str($1, make1_str("not in ("), $5, make1_str(")"));
- }
- | a_expr Op '(' SubSelect ')'
- {
- $$ = cat3_str($1, $2, make3_str(make1_str("("), $4, make1_str(")")));
- }
- | a_expr '+' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("+("), $4, make1_str(")"));
- }
- | a_expr '-' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("-("), $4, make1_str(")"));
- }
- | a_expr '/' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("/("), $4, make1_str(")"));
- }
- | a_expr '*' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("*("), $4, make1_str(")"));
- }
- | a_expr '<' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("<("), $4, make1_str(")"));
- }
- | a_expr '>' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str(">("), $4, make1_str(")"));
- }
- | a_expr '=' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("=("), $4, make1_str(")"));
- }
- | a_expr Op ANY '(' SubSelect ')'
- {
- $$ = cat3_str($1, $2, make3_str(make1_str("any("), $5, make1_str(")")));
- }
- | a_expr '+' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("+any("), $5, make1_str(")"));
- }
- | a_expr '-' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("-any("), $5, make1_str(")"));
- }
- | a_expr '/' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("/any("), $5, make1_str(")"));
- }
- | a_expr '*' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("*any("), $5, make1_str(")"));
+ $$ = cat_str(4, $1, make_str(" in ("), $4, make_str(")"));
}
- | a_expr '<' ANY '(' SubSelect ')'
+ | a_expr NOT IN '(' in_expr ')'
{
- $$ = make4_str($1, make1_str("<any("), $5, make1_str(")"));
+ $$ = cat_str(4, $1, make_str(" not in ("), $5, make_str(")"));
}
- | a_expr '>' ANY '(' SubSelect ')'
+ | a_expr all_Op sub_type '(' SubSelect ')'
{
- $$ = make4_str($1, make1_str(">any("), $5, make1_str(")"));
+ $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")"));
}
- | a_expr '=' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("=any("), $5, make1_str(")"));
- }
- | a_expr Op ALL '(' SubSelect ')'
- {
- $$ = cat3_str($1, $2, make3_str(make1_str("all ("), $5, make1_str(")")));
- }
- | a_expr '+' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("+all("), $5, make1_str(")"));
- }
- | a_expr '-' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("-all("), $5, make1_str(")"));
- }
- | a_expr '/' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("/all("), $5, make1_str(")"));
- }
- | a_expr '*' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("*all("), $5, make1_str(")"));
- }
- | a_expr '<' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("<all("), $5, make1_str(")"));
- }
- | a_expr '>' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str(">all("), $5, make1_str(")"));
- }
- | a_expr '=' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("=all("), $5, make1_str(")"));
- }
- | a_expr AND a_expr
- { $$ = cat3_str($1, make1_str("and"), $3); }
- | a_expr OR a_expr
- { $$ = cat3_str($1, make1_str("or"), $3); }
- | NOT a_expr
- { $$ = cat2_str(make1_str("not"), $2); }
- | case_expr
+ | row_expr
{ $$ = $1; }
| cinputvariable
- { $$ = make1_str(";;"); }
+ { $$ = make_str("?"); }
;
/* Restricted expressions
+ *
* b_expr is a subset of the complete expression syntax
- * defined by a_expr. b_expr is used in BETWEEN clauses
- * to eliminate parser ambiguities stemming from the AND keyword.
+ *
+ * Presently, AND, NOT, IS, IN, and NULL are the a_expr keywords that would
+ * cause trouble in the places where b_expr is used. For simplicity, we
+ * just eliminate all the boolean-keyword-operator productions from b_expr.
*/
-b_expr: attr opt_indirection
+b_expr: c_expr
{
- $$ = cat2_str($1, $2);
+ $$ = $1;
}
- | AexprConst
- { $$ = $1; }
- | ColId
+ | b_expr TYPECAST Typename
{
- $$ = $1;
+ $$ = cat_str(3, $1, make_str("::"), $3);
}
+ | NULL_P TYPECAST Typename
+ {
+ $$ = cat2_str(make_str("null::"), $3);
+ }
| '-' b_expr %prec UMINUS
- { $$ = cat2_str(make1_str("-"), $2); }
+ { $$ = cat2_str(make_str("-"), $2); }
+ | '%' b_expr
+ { $$ = cat2_str(make_str("%"), $2); }
+ | '^' b_expr
+ { $$ = cat2_str(make_str("^"), $2); }
+ | '|' b_expr
+ { $$ = cat2_str(make_str("|"), $2); }
+/* not possible in embedded sql | ':' b_expr
+ { $$ = cat2_str(make_str(":"), $2); }
+*/
+ | ';' b_expr
+ { $$ = cat2_str(make_str(";"), $2); }
+ | b_expr '%'
+ { $$ = cat2_str($1, make_str("%")); }
+ | b_expr '^'
+ { $$ = cat2_str($1, make_str("^")); }
+ | b_expr '|'
+ { $$ = cat2_str($1, make_str("|")); }
| b_expr '+' b_expr
- { $$ = cat3_str($1, make1_str("+"), $3); }
+ { $$ = cat_str(3, $1, make_str("+"), $3); }
| b_expr '-' b_expr
- { $$ = cat3_str($1, make1_str("-"), $3); }
- | b_expr '/' b_expr
- { $$ = cat3_str($1, make1_str("/"), $3); }
+ { $$ = cat_str(3, $1, make_str("-"), $3); }
| b_expr '*' b_expr
- { $$ = cat3_str($1, make1_str("*"), $3); }
-/* not possible in embedded sql | ':' b_expr
- { $$ = cat2_str(make1_str(":"), $2); }
-*/
- | ';' b_expr
- { $$ = cat2_str(make1_str(";"), $2); }
- | '|' b_expr
- { $$ = cat2_str(make1_str("|"), $2); }
- | b_expr TYPECAST Typename
- {
- $$ = cat3_str($1, make1_str("::"), $3);
- }
- | CAST '(' b_expr AS Typename ')'
- {
- $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")")));
- }
- | '(' a_expr ')'
- { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
+ { $$ = cat_str(3, $1, make_str("*"), $3); }
+ | b_expr '/' b_expr
+ { $$ = cat_str(3, $1, make_str("/"), $3); }
+ | b_expr '%' b_expr
+ { $$ = cat_str(3, $1, make_str("%"), $3); }
+ | b_expr '^' b_expr
+ { $$ = cat_str(3, $1, make_str("^"), $3); }
+ | b_expr '|' b_expr
+ { $$ = cat_str(3, $1, make_str("|"), $3); }
+ | b_expr '<' b_expr
+ { $$ = cat_str(3, $1, make_str("<"), $3); }
+ | b_expr '>' b_expr
+ { $$ = cat_str(3, $1, make_str(">"), $3); }
+ | b_expr '=' b_expr
+ { $$ = cat_str(3, $1, make_str("="), $3); }
| b_expr Op b_expr
- { $$ = cat3_str($1, $2, $3); }
+ { $$ = cat_str(3, $1, $2, $3); }
| Op b_expr
{ $$ = cat2_str($1, $2); }
| b_expr Op
{ $$ = cat2_str($1, $2); }
+ | civariableonly
+ { $$ = $1; }
+ ;
+
+/*
+ * Productions that can be used in both a_expr and b_expr.
+ *
+ * Note: productions that refer recursively to a_expr or b_expr mostly
+ * cannot appear here. However, it's OK to refer to a_exprs that occur
+ * inside parentheses, such as function arguments; that cannot introduce
+ * ambiguity to the b_expr syntax.
+ */
+c_expr: attr
+ { $$ = $1; }
+ | ColId opt_indirection
+ { $$ = cat2_str($1, $2); }
+ | AexprConst
+ { $$ = $1; }
+ | '(' a_expr_or_null ')'
+ { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ | CAST '(' a_expr_or_null AS Typename ')'
+ { $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); }
+ | case_expr
+ { $$ = $1; }
| func_name '(' ')'
- {
- $$ = cat2_str($1, make1_str("()"));
- }
+ { $$ = cat2_str($1, make_str("()")); }
| func_name '(' expr_list ')'
- {
- $$ = make4_str($1, make1_str("("), $3, make1_str(")"));
- }
+ { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
+ | func_name '(' DISTINCT expr_list ')'
+ { $$ = cat_str(4, $1, make_str("( distinct"), $4, make_str(")")); }
+ | func_name '(' '*' ')'
+ { $$ = cat2_str($1, make_str("(*)")); }
| CURRENT_DATE
- {
- $$ = make1_str("current_date");
- }
+ { $$ = make_str("current_date"); }
| CURRENT_TIME
- {
- $$ = make1_str("current_time");
- }
+ { $$ = make_str("current_time"); }
| CURRENT_TIME '(' Iconst ')'
{
- if ($3 != 0)
- fprintf(stderr,"CURRENT_TIME(%s) precision not implemented; zero used instead", $3);
- $$ = make1_str("current_time");
+ if (atol($3) != 0)
+ {
+ sprintf(errortext, "CURRENT_TIME(%s) precision not implemented; backend will use zero instead", $3);
+ mmerror(ET_WARN, errortext);
+ }
+
+ $$ = make_str("current_time");
}
| CURRENT_TIMESTAMP
- {
- $$ = make1_str("current_timestamp");
- }
+ { $$ = make_str("current_timestamp"); }
| CURRENT_TIMESTAMP '(' Iconst ')'
{
if (atol($3) != 0)
- fprintf(stderr,"CURRENT_TIMESTAMP(%s) precision not implemented; zero used instead",$3);
- $$ = make1_str("current_timestamp");
+ {
+ sprintf(errortext, "CURRENT_TIMESTAMP(%s) precision not implemented; backend will use zero instead", $3);
+ mmerror(ET_WARN, errortext);
+ }
+
+ $$ = make_str("current_timestamp");
}
| CURRENT_USER
- {
- $$ = make1_str("current_user");
- }
+ { $$ = make_str("current_user"); }
+ | SESSION_USER
+ { $$ = make_str("session_user"); }
| USER
- {
- $$ = make1_str("user");
- }
+ { $$ = make_str("user"); }
+ | EXTRACT '(' extract_list ')'
+ { $$ = cat_str(3, make_str("extract("), $3, make_str(")")); }
| POSITION '(' position_list ')'
- {
- $$ = make3_str(make1_str("position ("), $3, make1_str(")"));
- }
+ { $$ = cat_str(3, make_str("position("), $3, make_str(")")); }
| SUBSTRING '(' substr_list ')'
- {
- $$ = make3_str(make1_str("substring ("), $3, make1_str(")"));
- }
+ { $$ = cat_str(3, make_str("substring("), $3, make_str(")")); }
/* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
| TRIM '(' BOTH trim_list ')'
- {
- $$ = make3_str(make1_str("trim(both"), $4, make1_str(")"));
- }
+ { $$ = cat_str(3, make_str("trim(both"), $4, make_str(")")); }
| TRIM '(' LEADING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")"));
- }
+ { $$ = cat_str(3, make_str("trim(leading"), $4, make_str(")")); }
| TRIM '(' TRAILING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")"));
- }
+ { $$ = cat_str(3, make_str("trim(trailing"), $4, make_str(")")); }
| TRIM '(' trim_list ')'
- {
- $$ = make3_str(make1_str("trim("), $3, make1_str(")"));
- }
- | civariableonly
- { $$ = make1_str(";;"); }
+ { $$ = cat_str(3, make_str("trim("), $3, make_str(")")); }
+ | '(' SubSelect ')'
+ { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+ | EXISTS '(' SubSelect ')'
+ { $$ = cat_str(3, make_str("exists("), $3, make_str(")")); }
;
-
-opt_indirection: '[' ecpg_expr ']' opt_indirection
+/*
+ * This used to use ecpg_expr, but since there is no shift/reduce conflict
+ * anymore, we can remove ecpg_expr. - MM
+ */
+opt_indirection: '[' a_expr ']' opt_indirection
{
- $$ = cat4_str(make1_str("["), $2, make1_str("]"), $4);
+ $$ = cat_str(4, make_str("["), $2, make_str("]"), $4);
}
- | '[' ecpg_expr ':' ecpg_expr ']' opt_indirection
+ | '[' a_expr ':' a_expr ']' opt_indirection
{
- $$ = cat2_str(cat5_str(make1_str("["), $2, make1_str(":"), $4, make1_str("]")), $6);
+ $$ = cat_str(6, make_str("["), $2, make_str(":"), $4, make_str("]"), $6);
}
| /* EMPTY */
- { $$ = make1_str(""); }
+ { $$ = EMPTY; }
;
expr_list: a_expr_or_null
{ $$ = $1; }
| expr_list ',' a_expr_or_null
- { $$ = cat3_str($1, make1_str(","), $3); }
+ { $$ = cat_str(3, $1, make_str(","), $3); }
| expr_list USING a_expr
- { $$ = cat3_str($1, make1_str("using"), $3); }
+ { $$ = cat_str(3, $1, make_str("using"), $3); }
;
extract_list: extract_arg FROM a_expr
{
- $$ = cat3_str($1, make1_str("from"), $3);
+ $$ = cat_str(3, $1, make_str("from"), $3);
}
| /* EMPTY */
- { $$ = make1_str(""); }
+ { $$ = EMPTY; }
| cinputvariable
- { $$ = make1_str(";;"); }
+ { $$ = make_str("?"); }
;
extract_arg: datetime { $$ = $1; }
- | TIMEZONE_HOUR { $$ = make1_str("timezone_hour"); }
- | TIMEZONE_MINUTE { $$ = make1_str("timezone_minute"); }
+ | TIMEZONE_HOUR { $$ = make_str("timezone_hour"); }
+ | TIMEZONE_MINUTE { $$ = make_str("timezone_minute"); }
;
-position_list: position_expr IN position_expr
- { $$ = cat3_str($1, make1_str("in"), $3); }
+/* position_list uses b_expr not a_expr to avoid conflict with general IN */
+position_list: b_expr IN b_expr
+ { $$ = cat_str(3, $1, make_str("in"), $3); }
| /* EMPTY */
- { $$ = make1_str(""); }
- ;
-
-position_expr: attr opt_indirection
- {
- $$ = cat2_str($1, $2);
- }
- | AexprConst
- { $$ = $1; }
- | '-' position_expr %prec UMINUS
- { $$ = cat2_str(make1_str("-"), $2); }
- | position_expr '+' position_expr
- { $$ = cat3_str($1, make1_str("+"), $3); }
- | position_expr '-' position_expr
- { $$ = cat3_str($1, make1_str("-"), $3); }
- | position_expr '/' position_expr
- { $$ = cat3_str($1, make1_str("/"), $3); }
- | position_expr '*' position_expr
- { $$ = cat3_str($1, make1_str("*"), $3); }
- | '|' position_expr
- { $$ = cat2_str(make1_str("|"), $2); }
- | position_expr TYPECAST Typename
- {
- $$ = cat3_str($1, make1_str("::"), $3);
- }
- | CAST '(' position_expr AS Typename ')'
- {
- $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")")));
- }
- | '(' position_expr ')'
- { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
- | position_expr Op position_expr
- { $$ = cat3_str($1, $2, $3); }
- | Op position_expr
- { $$ = cat2_str($1, $2); }
- | position_expr Op
- { $$ = cat2_str($1, $2); }
- | ColId
- {
- $$ = $1;
- }
- | func_name '(' ')'
- {
- $$ = cat2_str($1, make1_str("()"));
- }
- | func_name '(' expr_list ')'
- {
- $$ = make4_str($1, make1_str("("), $3, make1_str(")"));
- }
- | POSITION '(' position_list ')'
- {
- $$ = make3_str(make1_str("position("), $3, make1_str(")"));
- }
- | SUBSTRING '(' substr_list ')'
- {
- $$ = make3_str(make1_str("substring("), $3, make1_str(")"));
- }
- /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
- | TRIM '(' BOTH trim_list ')'
- {
- $$ = make3_str(make1_str("trim(both"), $4, make1_str(")"));
- }
- | TRIM '(' LEADING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")"));
- }
- | TRIM '(' TRAILING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")"));
- }
- | TRIM '(' trim_list ')'
- {
- $$ = make3_str(make1_str("trim("), $3, make1_str(")"));
- }
+ { $$ = EMPTY; }
;
substr_list: expr_list substr_from substr_for
{
- $$ = cat3_str($1, $2, $3);
+ $$ = cat_str(3, $1, $2, $3);
}
| /* EMPTY */
- { $$ = make1_str(""); }
+ { $$ = EMPTY; }
;
substr_from: FROM expr_list
- { $$ = cat2_str(make1_str("from"), $2); }
+ { $$ = cat2_str(make_str("from"), $2); }
| /* EMPTY */
{
- $$ = make1_str("");
+ $$ = EMPTY;
}
;
substr_for: FOR expr_list
- { $$ = cat2_str(make1_str("for"), $2); }
+ { $$ = cat2_str(make_str("for"), $2); }
| /* EMPTY */
- { $$ = make1_str(""); }
+ { $$ = EMPTY; }
;
trim_list: a_expr FROM expr_list
- { $$ = cat3_str($1, make1_str("from"), $3); }
+ { $$ = cat_str(3, $1, make_str("from"), $3); }
| FROM expr_list
- { $$ = cat2_str(make1_str("from"), $2); }
+ { $$ = cat2_str(make_str("from"), $2); }
| expr_list
{ $$ = $1; }
;
{ $$ = $1; }
;
-in_expr_nodes: AexprConst
- { $$ = $1; }
- | in_expr_nodes ',' AexprConst
- { $$ = cat3_str($1, make1_str(","), $3);}
- ;
-
-not_in_expr: SubSelect
- {
- $$ = $1;
- }
- | not_in_expr_nodes
- { $$ = $1; }
- ;
-
-not_in_expr_nodes: AexprConst
+in_expr_nodes: a_expr
{ $$ = $1; }
- | not_in_expr_nodes ',' AexprConst
- { $$ = cat3_str($1, make1_str(","), $3);}
+ | in_expr_nodes ',' a_expr
+ { $$ = cat_str(3, $1, make_str(","), $3);}
;
/* Case clause
* - thomas 1998-11-09
*/
case_expr: CASE case_arg when_clause_list case_default END_TRANS
- { $$ = cat5_str(make1_str("case"), $2, $3, $4, make1_str("end")); }
+ { $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); }
| NULLIF '(' a_expr ',' a_expr ')'
{
- $$ = cat5_str(make1_str("nullif("), $3, make1_str(","), $5, make1_str(")"));
+ $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")"));
- fprintf(stderr, "NULLIF() not yet fully implemented");
+ mmerror(ET_WARN, "NULLIF() not yet fully implemented");
}
| COALESCE '(' expr_list ')'
{
- $$ = cat3_str(make1_str("coalesce("), $3, make1_str(")"));
-
- fprintf(stderr, "COALESCE() not yet fully implemented");
+ $$ = cat_str(3, make_str("coalesce("), $3, make_str(")"));
}
;
when_clause: WHEN a_expr THEN a_expr_or_null
{
- $$ = cat4_str(make1_str("when"), $2, make1_str("then"), $4);
+ $$ = cat_str(4, make_str("when"), $2, make_str("then"), $4);
}
;
-case_default: ELSE a_expr_or_null { $$ = cat2_str(make1_str("else"), $2); }
- | /*EMPTY*/ { $$ = make1_str(""); }
+case_default: ELSE a_expr_or_null { $$ = cat2_str(make_str("else"), $2); }
+ | /*EMPTY*/ { $$ = EMPTY; }
;
-case_arg: attr opt_indirection
- {
- $$ = cat2_str($1, $2);
- }
- | ColId
- {
+case_arg: a_expr {
$$ = $1;
}
| /*EMPTY*/
- { $$ = make1_str(""); }
+ { $$ = EMPTY; }
;
-attr: relation_name '.' attrs
+attr: relation_name '.' attrs opt_indirection
{
- $$ = make3_str($1, make1_str("."), $3);
+ $$ = cat_str(4, $1, make_str("."), $3, $4);
}
- | ParamNo '.' attrs
+ | ParamNo '.' attrs opt_indirection
{
- $$ = make3_str($1, make1_str("."), $3);
+ $$ = cat_str(4, $1, make_str("."), $3, $4);
}
;
attrs: attr_name
{ $$ = $1; }
| attrs '.' attr_name
- { $$ = make3_str($1, make1_str("."), $3); }
+ { $$ = cat_str(3, $1, make_str("."), $3); }
| attrs '.' '*'
- { $$ = make2_str($1, make1_str(".*")); }
+ { $$ = make2_str($1, make_str(".*")); }
;
*
*****************************************************************************/
-res_target_list: res_target_list ',' res_target_el
- { $$ = cat3_str($1, make1_str(","),$3); }
- | res_target_el
- { $$ = $1; }
- | '*' { $$ = make1_str("*"); }
- ;
-
-res_target_el: ColId opt_indirection '=' a_expr_or_null
- {
- $$ = cat4_str($1, $2, make1_str("="), $4);
- }
- | attr opt_indirection
- {
- $$ = cat2_str($1, $2);
- }
- | relation_name '.' '*'
- {
- $$ = make2_str($1, make1_str(".*"));
- }
- ;
-
-/*
-** target list for select.
-** should get rid of the other but is still needed by the defunct select into
-** and update (uses a subset)
-*/
-res_target_list2: res_target_list2 ',' res_target_el2
- { $$ = cat3_str($1, make1_str(","), $3); }
- | res_target_el2
+/* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
+target_list: target_list ',' target_el
+ { $$ = cat_str(3, $1, make_str(","), $3); }
+ | target_el
{ $$ = $1; }
;
/* AS is not optional because shift/red conflict with unary ops */
-res_target_el2: a_expr_or_null AS ColLabel
+target_el: a_expr_or_null AS ColLabel
{
- $$ = cat3_str($1, make1_str("as"), $3);
+ $$ = cat_str(3, $1, make_str("as"), $3);
}
| a_expr_or_null
{
}
| relation_name '.' '*'
{
- $$ = make2_str($1, make1_str(".*"));
+ $$ = make2_str($1, make_str(".*"));
}
| '*'
{
- $$ = make1_str("*");
+ $$ = make_str("*");
}
;
-opt_id: ColId { $$ = $1; }
- | /* EMPTY */ { $$ = make1_str(""); }
+/* Target list as found in UPDATE table SET ... */
+update_target_list: update_target_list ',' update_target_el
+ { $$ = cat_str(3, $1, make_str(","),$3); }
+ | update_target_el
+ { $$ = $1; }
+ | '*' { $$ = make_str("*"); }
+ ;
+
+update_target_el: ColId opt_indirection '=' a_expr_or_null
+ {
+ $$ = cat_str(4, $1, $2, make_str("="), $4);
+ }
;
+/*****************************************************************************
+ *
+ * Names and constants
+ *
+ *****************************************************************************/
+
relation_name: SpecialRuleRelation
{
$$ = $1;
/* disallow refs to variable system tables */
if (strcmp(LogRelationName, $1) == 0
|| strcmp(VariableRelationName, $1) == 0) {
- sprintf(errortext, make1_str("%s cannot be accessed by users"),$1);
- yyerror(errortext);
+ sprintf(errortext, make_str("%s cannot be accessed by users"),$1);
+ mmerror(ET_ERROR, errortext);
}
else
$$ = $1;
func_name: ColId { $$ = $1; };
file_name: Sconst { $$ = $1; };
-recipe_name: ident { $$ = $1; };
+/* NOT USED recipe_name: ident { $$ = $1; };*/
/* Constants
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
{
$$ = $1;
}
- | Typename Sconst
+ /* this rule formerly used Typename, but that causes reduce conf licts
+ * with subscripted column names ...
+ */
+ | SimpleTypename Sconst
{
$$ = cat2_str($1, $2);
}
{ $$ = $1; }
| TRUE_P
{
- $$ = make1_str("true");
+ $$ = make_str("true");
}
| FALSE_P
{
- $$ = make1_str("false");
+ $$ = make_str("false");
}
;
*/
ColId: ident { $$ = $1; }
| datetime { $$ = $1; }
- | ABSOLUTE { $$ = make1_str("absolute"); }
- | ACTION { $$ = make1_str("action"); }
- | AFTER { $$ = make1_str("after"); }
- | AGGREGATE { $$ = make1_str("aggregate"); }
- | BACKWARD { $$ = make1_str("backward"); }
- | BEFORE { $$ = make1_str("before"); }
- | CACHE { $$ = make1_str("cache"); }
- | CREATEDB { $$ = make1_str("createdb"); }
- | CREATEUSER { $$ = make1_str("createuser"); }
- | CYCLE { $$ = make1_str("cycle"); }
- | DATABASE { $$ = make1_str("database"); }
- | DELIMITERS { $$ = make1_str("delimiters"); }
- | DOUBLE { $$ = make1_str("double"); }
- | EACH { $$ = make1_str("each"); }
- | ENCODING { $$ = make1_str("encoding"); }
- | FORWARD { $$ = make1_str("forward"); }
- | FUNCTION { $$ = make1_str("function"); }
- | HANDLER { $$ = make1_str("handler"); }
- | INCREMENT { $$ = make1_str("increment"); }
- | INDEX { $$ = make1_str("index"); }
- | INHERITS { $$ = make1_str("inherits"); }
- | INSENSITIVE { $$ = make1_str("insensitive"); }
- | INSTEAD { $$ = make1_str("instead"); }
- | ISNULL { $$ = make1_str("isnull"); }
- | KEY { $$ = make1_str("key"); }
- | LANGUAGE { $$ = make1_str("language"); }
- | LANCOMPILER { $$ = make1_str("lancompiler"); }
- | LOCATION { $$ = make1_str("location"); }
- | MATCH { $$ = make1_str("match"); }
- | MAXVALUE { $$ = make1_str("maxvalue"); }
- | MINVALUE { $$ = make1_str("minvalue"); }
- | NEXT { $$ = make1_str("next"); }
- | NOCREATEDB { $$ = make1_str("nocreatedb"); }
- | NOCREATEUSER { $$ = make1_str("nocreateuser"); }
- | NOTHING { $$ = make1_str("nothing"); }
- | NOTNULL { $$ = make1_str("notnull"); }
- | OF { $$ = make1_str("of"); }
- | OIDS { $$ = make1_str("oids"); }
- | ONLY { $$ = make1_str("only"); }
- | OPERATOR { $$ = make1_str("operator"); }
- | OPTION { $$ = make1_str("option"); }
- | PASSWORD { $$ = make1_str("password"); }
- | PRIOR { $$ = make1_str("prior"); }
- | PRIVILEGES { $$ = make1_str("privileges"); }
- | PROCEDURAL { $$ = make1_str("procedural"); }
- | READ { $$ = make1_str("read"); }
- | RECIPE { $$ = make1_str("recipe"); }
- | RELATIVE { $$ = make1_str("relative"); }
- | RENAME { $$ = make1_str("rename"); }
- | RETURNS { $$ = make1_str("returns"); }
- | ROW { $$ = make1_str("row"); }
- | RULE { $$ = make1_str("rule"); }
- | SCROLL { $$ = make1_str("scroll"); }
- | SEQUENCE { $$ = make1_str("sequence"); }
- | SERIAL { $$ = make1_str("serial"); }
- | START { $$ = make1_str("start"); }
- | STATEMENT { $$ = make1_str("statement"); }
- | STDIN { $$ = make1_str("stdin"); }
- | STDOUT { $$ = make1_str("stdout"); }
- | TIME { $$ = make1_str("time"); }
- | TIMESTAMP { $$ = make1_str("timestamp"); }
- | TIMEZONE_HOUR { $$ = make1_str("timezone_hour"); }
- | TIMEZONE_MINUTE { $$ = make1_str("timezone_minute"); }
- | TRIGGER { $$ = make1_str("trigger"); }
- | TRUSTED { $$ = make1_str("trusted"); }
- | TYPE_P { $$ = make1_str("type"); }
- | VALID { $$ = make1_str("valid"); }
- | VERSION { $$ = make1_str("version"); }
- | ZONE { $$ = make1_str("zone"); }
+ | ABSOLUTE { $$ = make_str("absolute"); }
+ | ACCESS { $$ = make_str("access"); }
+ | ACTION { $$ = make_str("action"); }
+ | AFTER { $$ = make_str("after"); }
+ | AGGREGATE { $$ = make_str("aggregate"); }
+ | BACKWARD { $$ = make_str("backward"); }
+ | BEFORE { $$ = make_str("before"); }
+ | CACHE { $$ = make_str("cache"); }
+ | COMMENT { $$ = make_str("comment"); }
+ | COMMITTED { $$ = make_str("committed"); }
+ | CONSTRAINTS { $$ = make_str("constraints"); }
+ | CREATEDB { $$ = make_str("createdb"); }
+ | CREATEUSER { $$ = make_str("createuser"); }
+ | CYCLE { $$ = make_str("cycle"); }
+ | DATABASE { $$ = make_str("database"); }
+ | DEFERRABLE { $$ = make_str("deferrable"); }
+ | DEFERRED { $$ = make_str("deferred"); }
+ | DELIMITERS { $$ = make_str("delimiters"); }
+ | DOUBLE { $$ = make_str("double"); }
+ | EACH { $$ = make_str("each"); }
+ | ENCODING { $$ = make_str("encoding"); }
+ | EXCLUSIVE { $$ = make_str("exclusive"); }
+ | FORWARD { $$ = make_str("forward"); }
+ | FUNCTION { $$ = make_str("function"); }
+ | HANDLER { $$ = make_str("handler"); }
+ | IMMEDIATE { $$ = make_str("immediate"); }
+ | INCREMENT { $$ = make_str("increment"); }
+ | INDEX { $$ = make_str("index"); }
+ | INHERITS { $$ = make_str("inherits"); }
+ | INITIALLY { $$ = make_str("initially"); }
+ | INSENSITIVE { $$ = make_str("insensitive"); }
+ | INSTEAD { $$ = make_str("instead"); }
+ | ISNULL { $$ = make_str("isnull"); }
+ | ISOLATION { $$ = make_str("isolation"); }
+ | KEY { $$ = make_str("key"); }
+ | LANGUAGE { $$ = make_str("language"); }
+ | LANCOMPILER { $$ = make_str("lancompiler"); }
+ | LEVEL { $$ = make_str("level"); }
+ | LOCATION { $$ = make_str("location"); }
+ | MATCH { $$ = make_str("match"); }
+ | MAXVALUE { $$ = make_str("maxvalue"); }
+ | MINVALUE { $$ = make_str("minvalue"); }
+ | MODE { $$ = make_str("mode"); }
+ | NEXT { $$ = make_str("next"); }
+ | NOCREATEDB { $$ = make_str("nocreatedb"); }
+ | NOCREATEUSER { $$ = make_str("nocreateuser"); }
+ | NOTHING { $$ = make_str("nothing"); }
+ | NOTNULL { $$ = make_str("notnull"); }
+ | OF { $$ = make_str("of"); }
+ | OIDS { $$ = make_str("oids"); }
+ | ONLY { $$ = make_str("only"); }
+ | OPERATOR { $$ = make_str("operator"); }
+ | OPTION { $$ = make_str("option"); }
+ | PASSWORD { $$ = make_str("password"); }
+ | PENDANT { $$ = make_str("pendant"); }
+ | PRIOR { $$ = make_str("prior"); }
+ | PRIVILEGES { $$ = make_str("privileges"); }
+ | PROCEDURAL { $$ = make_str("procedural"); }
+ | READ { $$ = make_str("read"); }
+ | RELATIVE { $$ = make_str("relative"); }
+ | RENAME { $$ = make_str("rename"); }
+ | RESTRICT { $$ = make_str("restrict"); }
+ | RETURNS { $$ = make_str("returns"); }
+ | ROW { $$ = make_str("row"); }
+ | RULE { $$ = make_str("rule"); }
+ | SCROLL { $$ = make_str("scroll"); }
+ | SEQUENCE { $$ = make_str("sequence"); }
+ | SERIAL { $$ = make_str("serial"); }
+ | SERIALIZABLE { $$ = make_str("serializable"); }
+ | SHARE { $$ = make_str("share"); }
+ | START { $$ = make_str("start"); }
+ | STATEMENT { $$ = make_str("statement"); }
+ | STDIN { $$ = make_str("stdin"); }
+ | STDOUT { $$ = make_str("stdout"); }
+ | SYSID { $$ = make_str("sysid"); }
+ | TIME { $$ = make_str("time"); }
+ | TIMESTAMP { $$ = make_str("timestamp"); }
+ | TIMEZONE_HOUR { $$ = make_str("timezone_hour"); }
+ | TIMEZONE_MINUTE { $$ = make_str("timezone_minute"); }
+ | TRIGGER { $$ = make_str("trigger"); }
+ | TRUNCATE { $$ = make_str("truncate"); }
+ | TRUSTED { $$ = make_str("trusted"); }
+ | TYPE_P { $$ = make_str("type"); }
+ | VALID { $$ = make_str("valid"); }
+ | VERSION { $$ = make_str("version"); }
+ | ZONE { $$ = make_str("zone"); }
+ | SQL_AT { $$ = make_str("at"); }
+ | SQL_BOOL { $$ = make_str("bool"); }
+ | SQL_BREAK { $$ = make_str("break"); }
+ | SQL_CALL { $$ = make_str("call"); }
+ | SQL_CONNECT { $$ = make_str("connect"); }
+ | SQL_CONTINUE { $$ = make_str("continue"); }
+ | SQL_DEALLOCATE { $$ = make_str("deallocate"); }
+ | SQL_DISCONNECT { $$ = make_str("disconnect"); }
+ | SQL_FOUND { $$ = make_str("found"); }
+ | SQL_GO { $$ = make_str("go"); }
+ | SQL_GOTO { $$ = make_str("goto"); }
+ | SQL_IDENTIFIED { $$ = make_str("identified"); }
+ | SQL_INDICATOR { $$ = make_str("indicator"); }
+ | SQL_INT { $$ = make_str("int"); }
+ | SQL_LONG { $$ = make_str("long"); }
+ | SQL_OFF { $$ = make_str("off"); }
+ | SQL_OPEN { $$ = make_str("open"); }
+ | SQL_PREPARE { $$ = make_str("prepare"); }
+ | SQL_RELEASE { $$ = make_str("release"); }
+ | SQL_SECTION { $$ = make_str("section"); }
+ | SQL_SHORT { $$ = make_str("short"); }
+ | SQL_SIGNED { $$ = make_str("signed"); }
+ | SQL_SQLERROR { $$ = make_str("sqlerror"); }
+ | SQL_SQLPRINT { $$ = make_str("sqlprint"); }
+ | SQL_SQLWARNING { $$ = make_str("sqlwarning"); }
+ | SQL_STOP { $$ = make_str("stop"); }
+ | SQL_STRUCT { $$ = make_str("struct"); }
+ | SQL_UNSIGNED { $$ = make_str("unsigned"); }
+ | SQL_VAR { $$ = make_str("var"); }
+ | SQL_WHENEVER { $$ = make_str("whenever"); }
;
/* Column label
* Allowed labels in "AS" clauses.
* rather than in ColId if there was a shift/reduce conflict
* when used as a full identifier. - thomas 1997-11-06
*/
-ColLabel: ColId { $$ = $1; }
- | ABORT_TRANS { $$ = make1_str("abort"); }
- | ANALYZE { $$ = make1_str("analyze"); }
- | BINARY { $$ = make1_str("binary"); }
- | CASE { $$ = make1_str("case"); }
- | CLUSTER { $$ = make1_str("cluster"); }
- | COALESCE { $$ = make1_str("coalesce"); }
- | CONSTRAINT { $$ = make1_str("constraint"); }
- | COPY { $$ = make1_str("copy"); }
- | CROSS { $$ = make1_str("cross"); }
- | CURRENT { $$ = make1_str("current"); }
- | DO { $$ = make1_str("do"); }
- | ELSE { $$ = make1_str("else"); }
- | END_TRANS { $$ = make1_str("end"); }
- | EXPLAIN { $$ = make1_str("explain"); }
- | EXTEND { $$ = make1_str("extend"); }
- | FALSE_P { $$ = make1_str("false"); }
- | FOREIGN { $$ = make1_str("foreign"); }
- | GROUP { $$ = make1_str("group"); }
- | LISTEN { $$ = make1_str("listen"); }
- | LOAD { $$ = make1_str("load"); }
- | LOCK_P { $$ = make1_str("lock"); }
- | MOVE { $$ = make1_str("move"); }
- | NEW { $$ = make1_str("new"); }
- | NONE { $$ = make1_str("none"); }
- | NULLIF { $$ = make1_str("nullif"); }
- | ORDER { $$ = make1_str("order"); }
- | POSITION { $$ = make1_str("position"); }
- | PRECISION { $$ = make1_str("precision"); }
- | RESET { $$ = make1_str("reset"); }
- | SETOF { $$ = make1_str("setof"); }
- | SHOW { $$ = make1_str("show"); }
- | TABLE { $$ = make1_str("table"); }
- | THEN { $$ = make1_str("then"); }
- | TRANSACTION { $$ = make1_str("transaction"); }
- | TRUE_P { $$ = make1_str("true"); }
- | VACUUM { $$ = make1_str("vacuum"); }
- | VERBOSE { $$ = make1_str("verbose"); }
- | WHEN { $$ = make1_str("when"); }
+ColLabel: ColId { $$ = $1; }
+ | ABORT_TRANS { $$ = make_str("abort"); }
+ | ANALYZE { $$ = make_str("analyze"); }
+ | BINARY { $$ = make_str("binary"); }
+ | CASE { $$ = make_str("case"); }
+ | CLUSTER { $$ = make_str("cluster"); }
+ | COALESCE { $$ = make_str("coalesce"); }
+ | CONSTRAINT { $$ = make_str("constraint"); }
+ | COPY { $$ = make_str("copy"); }
+ | CURRENT { $$ = make_str("current"); }
+ | CURRENT_USER { $$ = make_str("current_user"); }
+ | DEC { $$ = make_str("dec"); }
+ | DECIMAL { $$ = make_str("decimal"); }
+ | DO { $$ = make_str("do"); }
+ | ELSE { $$ = make_str("else"); }
+ | END_TRANS { $$ = make_str("end"); }
+ | EXPLAIN { $$ = make_str("explain"); }
+ | EXTEND { $$ = make_str("extend"); }
+ | FALSE_P { $$ = make_str("false"); }
+ | FLOAT { $$ = make_str("float"); }
+ | FOREIGN { $$ = make_str("foreign"); }
+ | GLOBAL { $$ = make_str("global"); }
+ | GROUP { $$ = make_str("group"); }
+ | LISTEN { $$ = make_str("listen"); }
+ | LOAD { $$ = make_str("load"); }
+ | LOCK_P { $$ = make_str("lock"); }
+ | MOVE { $$ = make_str("move"); }
+ | NEW { $$ = make_str("new"); }
+ | NONE { $$ = make_str("none"); }
+ | NULLIF { $$ = make_str("nullif"); }
+ | NUMERIC { $$ = make_str("numeric"); }
+ | ORDER { $$ = make_str("order"); }
+ | POSITION { $$ = make_str("position"); }
+ | PRECISION { $$ = make_str("precision"); }
+ | RESET { $$ = make_str("reset"); }
+ | SESSION_USER { $$ = make_str("session_user"); }
+ | SETOF { $$ = make_str("setof"); }
+ | SHOW { $$ = make_str("show"); }
+ | TABLE { $$ = make_str("table"); }
+ | THEN { $$ = make_str("then"); }
+ | TRANSACTION { $$ = make_str("transaction"); }
+ | TRUE_P { $$ = make_str("true"); }
+ | USER { $$ = make_str("user"); }
+ | VACUUM { $$ = make_str("vacuum"); }
+ | VERBOSE { $$ = make_str("verbose"); }
+ | WHEN { $$ = make_str("when"); }
;
SpecialRuleRelation: CURRENT
{
if (QueryIsRule)
- $$ = make1_str("current");
+ $$ = make_str("current");
else
- yyerror("CURRENT used in non-rule query");
+ mmerror(ET_ERROR, "CURRENT used in non-rule query");
}
| NEW
{
if (QueryIsRule)
- $$ = make1_str("new");
+ $$ = make_str("new");
else
- yyerror("NEW used in non-rule query");
+ mmerror(ET_ERROR, "NEW used in non-rule query");
}
;
* and now special embedded SQL stuff
*/
-/*
- * variable declaration inside the exec sql declare block
- */
-ECPGDeclaration: sql_startdeclare variable_declarations sql_enddeclare {}
-
-sql_startdeclare : ecpgstart BEGIN_TRANS DECLARE SQL_SECTION SQL_SEMI {
- fputs("/* exec sql begin declare section */\n", yyout);
- output_line_number();
- }
-
-sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION SQL_SEMI {
- fputs("/* exec sql end declare section */\n", yyout);
- output_line_number();
-}
-
-variable_declarations: /* empty */
- | declaration variable_declarations;
-
-declaration: storage_clause type
- {
- actual_storage[struct_level] = $1;
- actual_type[struct_level] = $2.type_enum;
- if ($2.type_enum != ECPGt_varchar && $2.type_enum != ECPGt_struct)
- fprintf(yyout, "%s %s", $1, $2.type_str);
- free($2.type_str);
- }
- variable_list ';' { fputc(';', yyout); }
-
-storage_clause : S_EXTERN { $$ = "extern"; }
- | S_STATIC { $$ = "static"; }
- | S_SIGNED { $$ = "signed"; }
- | S_CONST { $$ = "const"; }
- | S_REGISTER { $$ = "register"; }
- | S_AUTO { $$ = "auto"; }
- | /* empty */ { $$ = ""; }
-
-type: simple_type
- {
- $$.type_enum = $1;
- $$.type_str = mm_strdup(ECPGtype_name($1));
- }
- | struct_type
- {
- $$.type_enum = ECPGt_struct;
- $$.type_str = make1_str("");
- }
- | enum_type
- {
- $$.type_str = $1;
- $$.type_enum = ECPGt_int;
- }
-
-enum_type: s_enum '{' c_line '}'
- {
- $$ = cat4_str($1, make1_str("{"), $3, make1_str("}"));
- }
-
-s_enum: S_ENUM opt_symbol { $$ = cat2_str(make1_str("enum"), $2); }
-
-struct_type: s_struct '{' variable_declarations '}'
- {
- ECPGfree_struct_member(struct_member_list[struct_level]);
- free(actual_storage[struct_level--]);
- fputs("} ", yyout);
- }
-
-s_struct : S_STRUCT opt_symbol
- {
- struct_member_list[struct_level++] = NULL;
- if (struct_level >= STRUCT_DEPTH)
- yyerror("Too many levels in nested structure definition");
- fprintf(yyout, "struct %s {", $2);
- free($2);
- }
-
-opt_symbol: /* empty */ { $$ = make1_str(""); }
- | symbol { $$ = $1; }
-
-simple_type: S_SHORT { $$ = ECPGt_short; }
- | S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; }
- | S_INT { $$ = ECPGt_int; }
- | S_UNSIGNED S_INT { $$ = ECPGt_unsigned_int; }
- | S_LONG { $$ = ECPGt_long; }
- | S_UNSIGNED S_LONG { $$ = ECPGt_unsigned_long; }
- | S_FLOAT { $$ = ECPGt_float; }
- | S_DOUBLE { $$ = ECPGt_double; }
- | S_BOOL { $$ = ECPGt_bool; };
- | S_CHAR { $$ = ECPGt_char; }
- | S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; }
- | S_VARCHAR { $$ = ECPGt_varchar; }
-
-variable_list: variable
- | variable_list ','
- {
- if (actual_type[struct_level] != ECPGt_varchar)
- fputs(", ", yyout);
- else
- fputs(";\n ", yyout);
- } variable
-
-variable: opt_pointer symbol opt_array_bounds opt_initializer
- {
- struct ECPGtype * type;
- int dimension = $3.index1; /* dimension of array */
- int length = $3.index2; /* lenght of string */
- char dim[14L];
-
- switch (actual_type[struct_level])
- {
- case ECPGt_struct:
- /* pointer has to get dimension 0 */
- if (strlen($1) > 0)
- {
- length = dimension;
- dimension = 0;
- }
-
- if (length >= 0)
- yyerror("No multi-dimensional array support for structures");
-
- if (dimension == 1 || dimension < 0)
- type = ECPGmake_struct_type(struct_member_list[struct_level]);
- else
- type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level]), dimension);
-
- fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
- break;
- case ECPGt_varchar:
- /* pointer has to get length 0 */
- if (strlen($1) > 0)
- length=0;
-
- /* one index is the string length */
- if (length < 0)
- {
- length = dimension;
- dimension = 1;
- }
-
- if (dimension == 1)
- type = ECPGmake_simple_type(actual_type[struct_level], length);
- else
- type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level], length), dimension);
-
- switch(dimension)
- {
- case 0:
- strcpy(dim, "[]");
- break;
- case 1:
- *dim = '\0';
- break;
- default:
- sprintf(dim, "[%d]", dimension);
- break;
- }
- if (length > 0)
- fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s%s", actual_storage[struct_level], $2, length, $2, dim);
- else
- fprintf(yyout, "%s struct varchar_%s { int len; char *arr; } %s%s", actual_storage[struct_level], $2, $2, dim);
- break;
- case ECPGt_char:
- case ECPGt_unsigned_char:
- /* pointer has to get length 0 */
- if (strlen($1) > 0)
- length=0;
-
- /* one index is the string length */
- if (length < 0)
- {
- length = (dimension < 0) ? 1 : dimension;
- dimension = 1;
- }
-
- if (dimension == 1)
- type = ECPGmake_simple_type(actual_type[struct_level], length);
- else
- type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level], length), dimension);
-
- fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
- break;
- default:
- /* a pointer has dimension = 0 */
- if (strlen($1) > 0) {
- length = dimension;
- dimension = 0;
- }
-
- if (length >= 0)
- yyerror("No multi-dimensional array support for simple data types");
-
- if (dimension == 1 || dimension < 0)
- type = ECPGmake_simple_type(actual_type[struct_level], 1);
- else
- type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level], 1), dimension);
-
- fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
- break;
- }
-
- if (struct_level == 0)
- new_variable($2, type);
- else
- ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
-
- free($1);
- free($2);
- free($3.str);
- free($4);
- }
-
-opt_initializer: /* empty */ { $$ = make1_str(""); }
- | '=' vartext { $$ = make2_str(make1_str("="), $2); }
-
-opt_pointer: /* empty */ { $$ = make1_str(""); }
- | '*' { $$ = make1_str("*"); }
-
/*
* the exec sql connect statement: connect to the given database
*/
ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
{
- $$ = make5_str($3, make1_str(","), $5, make1_str(","), $4);
+ $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4);
}
| SQL_CONNECT TO DEFAULT
{
- $$ = make1_str("NULL,NULL,NULL,\"DEFAULT\"");
+ $$ = make_str("NULL,NULL,NULL,\"DEFAULT\"");
}
/* also allow ORACLE syntax */
| SQL_CONNECT ora_user
{
- $$ = make3_str(make1_str("NULL,"), $2, make1_str(",NULL"));
+ $$ = cat_str(3, make_str("NULL,"), $2, make_str(",NULL"));
}
connection_target: database_name opt_server opt_port
if (strlen($2) > 0 && *($2) != '@')
{
sprintf(errortext, "parse error at or near '%s'", $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = make5_str(make1_str("\""), $1, $2, $3, make1_str("\""));
+ $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
}
| db_prefix server opt_port '/' database_name opt_options
{
/* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
- if (strncmp($2, "://", 3) != 0)
+ if (strncmp($2, "://", strlen("://")) != 0)
{
sprintf(errortext, "parse error at or near '%s'", $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- if (strncmp($1, "unix", 4) == 0 && strncmp($2 + 3, "localhost", 9) != 0)
+ if (strncmp($1, "unix", strlen("unix")) == 0 && strncmp($2 + strlen("://"), "localhost", strlen("localhost")) != 0)
{
sprintf(errortext, "unix domain sockets only work on 'localhost' but not on '%9.9s'", $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- if (strncmp($1, "unix", 4) != 0 && strncmp($1, "tcp", 3) != 0)
+ if (strncmp($1, "unix", strlen("unix")) != 0 && strncmp($1, "tcp", strlen("tcp")) != 0)
{
sprintf(errortext, "only protocols 'tcp' and 'unix' are supported");
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = make4_str(make5_str(make1_str("\""), $1, $2, $3, make1_str("/")), $5, $6, make1_str("\""));
+ $$ = make2_str(make3_str(make_str("\""), $1, $2), make3_str(make3_str($3, make_str("/"), $5), $6, make_str("\"")));
}
| char_variable
{
if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
{
sprintf(errortext, "parse error at or near '%s'", $2);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
{
sprintf(errortext, "Illegal connection type %s", $1);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = make3_str($1, make1_str(":"), $2);
+ $$ = make3_str( $1, make_str(":"), $2);
}
server: Op server_name
if (strcmp($1, "@") != 0 && strcmp($1, "://") != 0)
{
sprintf(errortext, "parse error at or near '%s'", $1);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
$$ = make2_str($1, $2);
}
opt_server: server { $$ = $1; }
- | /* empty */ { $$ = make1_str(""); }
+ | /* empty */ { $$ = EMPTY; }
server_name: ColId { $$ = $1; }
- | ColId '.' server_name { $$ = make3_str($1, make1_str("."), $3); }
+ | ColId '.' server_name { $$ = make3_str($1, make_str("."), $3); }
-opt_port: ':' Iconst { $$ = make2_str(make1_str(":"), $2); }
- | /* empty */ { $$ = make1_str(""); }
+opt_port: ':' Iconst { $$ = make2_str(make_str(":"), $2); }
+ | /* empty */ { $$ = EMPTY; }
opt_connection_name: AS connection_target { $$ = $2; }
- | /* empty */ { $$ = make1_str("NULL"); }
+ | /* empty */ { $$ = make_str("NULL"); }
opt_user: USER ora_user { $$ = $2; }
- | /* empty */ { $$ = make1_str("NULL,NULL"); }
+ | /* empty */ { $$ = make_str("NULL,NULL"); }
ora_user: user_name
{
- $$ = make2_str($1, make1_str(",NULL"));
+ $$ = cat2_str($1, make_str(", NULL"));
}
- | user_name '/' ColId
+ | user_name '/' user_name
{
- $$ = make3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
| user_name SQL_IDENTIFIED BY user_name
{
- $$ = make3_str($1, make1_str(","), $4);
+ $$ = cat_str(3, $1, make_str(","), $4);
}
| user_name USING user_name
{
- $$ = make3_str($1, make1_str(","), $3);
+ $$ = cat_str(3, $1, make_str(","), $3);
}
user_name: UserId { if ($1[0] == '\"')
$$ = $1;
else
- $$ = make3_str(make1_str("\""), $1, make1_str("\""));
+ $$ = make3_str(make_str("\""), $1, make_str("\""));
}
| char_variable { $$ = $1; }
- | SCONST { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
+ | SCONST { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
char_variable: cvariable
{ /* check if we have a char variable */
$$ = $1;
break;
case ECPGt_varchar:
- $$ = make2_str($1, make1_str(".arr"));
+ $$ = make2_str($1, make_str(".arr"));
break;
default:
- yyerror("invalid datatype");
+ mmerror(ET_ERROR, "invalid datatype");
break;
}
}
opt_options: Op ColId
{
if (strlen($1) == 0)
- yyerror("parse error");
+ mmerror(ET_ERROR, "parse error");
if (strcmp($1, "?") != 0)
{
sprintf(errortext, "parse error at or near %s", $1);
- yyerror(errortext);
+ mmerror(ET_ERROR, errortext);
}
- $$ = make2_str(make1_str("?"), $2);
+ $$ = make2_str(make_str("?"), $2);
}
- | /* empty */ { $$ = make1_str(""); }
+ | /* empty */ { $$ = EMPTY; }
/*
- * the exec sql disconnect statement: disconnect from the given database
+ * Declare a prepared cursor. The syntax is different from the standard
+ * declare statement, so we create a new rule.
*/
-ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
+ECPGCursorStmt: DECLARE name opt_cursor CURSOR FOR ident
+ {
+ struct cursor *ptr, *this;
+ struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
-dis_name: connection_object { $$ = $1; }
- | CURRENT { $$ = make1_str("CURRENT"); }
- | ALL { $$ = make1_str("ALL"); }
- | /* empty */ { $$ = make1_str("CURRENT"); }
+ for (ptr = cur; ptr != NULL; ptr = ptr->next)
+ {
+ if (strcmp($2, ptr->name) == 0)
+ {
+ /* re-definition is a bug */
+ sprintf(errortext, "cursor %s already defined", $2);
+ mmerror(ET_ERROR, errortext);
+ }
+ }
-connection_object: connection_target { $$ = $1; }
- | DEFAULT { $$ = make1_str("DEFAULT"); }
+ this = (struct cursor *) mm_alloc(sizeof(struct cursor));
-/*
- * execute a given string as sql command
- */
-ECPGExecute : EXECUTE SQL_IMMEDIATE execstring { $$ = $3; };
+ /* initial definition */
+ this->next = cur;
+ this->name = $2;
+ this->connection = connection;
+ this->command = cat_str(4, make_str("declare"), mm_strdup($2), $3, make_str("cursor for ?"));
+ this->argsresult = NULL;
-execstring: cvariable |
- CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); };
+ thisquery->type = &ecpg_query;
+ thisquery->brace_level = 0;
+ thisquery->next = NULL;
+ thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($6));
+ sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $6);
-/*
- * open is an open cursor, at the moment this has to be removed
- */
-ECPGOpen: SQL_OPEN name open_opts {
- $$ = $2;
-};
+ this->argsinsert = NULL;
+ add_variable(&(this->argsinsert), thisquery, &no_indicator);
-open_opts: /* empty */ { $$ = make1_str(""); }
- | USING cvariable {
- yyerror ("open cursor with variables not implemented yet");
+ cur = this;
+
+ $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
}
+ ;
/*
- * for compatibility with ORACLE we will also allow the keyword RELEASE
- * after a transaction statement to disconnect from the database.
+ * the exec sql deallocate prepare command to deallocate a previously
+ * prepared statement
*/
+ECPGDeallocate: SQL_DEALLOCATE SQL_PREPARE ident { $$ = cat_str(3, make_str("ECPGdeallocate(__LINE__, \""), $3, make_str("\");")); }
-ECPGRelease: TransactionStmt SQL_RELEASE
+/*
+ * variable declaration inside the exec sql declare block
+ */
+ECPGDeclaration: sql_startdeclare
{
- if (strncmp($1, "begin", 5) == 0)
- yyerror("RELEASE does not make sense when beginning a transaction");
-
- fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1);
- whenever_action(0);
- fprintf(yyout, "ECPGdisconnect(\"\");");
- whenever_action(0);
- free($1);
+ fputs("/* exec sql begin declare section */", yyout);
}
+ variable_declarations sql_enddeclare
+ {
+ fprintf(yyout, "%s/* exec sql end declare section */", $3);
+ free($3);
+ output_line_number();
+ }
+
+sql_startdeclare : ecpgstart BEGIN_TRANS DECLARE SQL_SECTION ';' {}
+
+sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION ';' {}
+
+variable_declarations: /* empty */ { $$ = EMPTY; }
+ | declarations { $$ = $1; }
+
+declarations: declaration { $$ = $1; }
+ | declarations declaration { $$ = cat2_str($1, $2); }
+
+declaration: storage_clause storage_modifier
+ {
+ actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
+ actual_startline[struct_level] = hashline_number();
+ }
+ type
+ {
+ actual_type[struct_level].type_enum = $4.type_enum;
+ actual_type[struct_level].type_dimension = $4.type_dimension;
+ actual_type[struct_level].type_index = $4.type_index;
+
+ /* we do not need the string "varchar" for output */
+ /* so replace it with an empty string */
+ if ($4.type_enum == ECPGt_varchar)
+ {
+ free($4.type_str);
+ $4.type_str=EMPTY;
+ }
+ }
+ variable_list ';'
+ {
+ $$ = cat_str(6, actual_startline[struct_level], $1, $2, $4.type_str, $6, make_str(";\n"));
+ }
+
+storage_clause : S_EXTERN { $$ = make_str("extern"); }
+ | S_STATIC { $$ = make_str("static"); }
+ | S_REGISTER { $$ = make_str("register"); }
+ | S_AUTO { $$ = make_str("auto"); }
+ | /* empty */ { $$ = EMPTY; }
+
+storage_modifier : S_CONST { $$ = make_str("const"); }
+ | S_VOLATILE { $$ = make_str("volatile"); }
+ | /* empty */ { $$ = EMPTY; }
+
+type: simple_type
+ {
+ $$.type_enum = $1;
+ $$.type_str = mm_strdup(ECPGtype_name($1));
+ $$.type_dimension = -1;
+ $$.type_index = -1;
+ }
+ | varchar_type
+ {
+ $$.type_enum = ECPGt_varchar;
+ $$.type_str = make_str("varchar");;
+ $$.type_dimension = -1;
+ $$.type_index = -1;
+ }
+ | struct_type
+ {
+ $$.type_enum = ECPGt_struct;
+ $$.type_str = $1;
+ $$.type_dimension = -1;
+ $$.type_index = -1;
+ }
+ | union_type
+ {
+ $$.type_enum = ECPGt_union;
+ $$.type_str = $1;
+ $$.type_dimension = -1;
+ $$.type_index = -1;
+ }
+ | enum_type
+ {
+ $$.type_str = $1;
+ $$.type_enum = ECPGt_int;
+ $$.type_dimension = -1;
+ $$.type_index = -1;
+ }
+ | symbol
+ {
+ /* this is for typedef'ed types */
+ struct typedefs *this = get_typedef($1);
+
+ $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
+ $$.type_enum = this->type->type_enum;
+ $$.type_dimension = this->type->type_dimension;
+ $$.type_index = this->type->type_index;
+ struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+ }
+
+enum_type: SQL_ENUM opt_symbol enum_definition
+ {
+ $$ = cat_str(3, make_str("enum"), $2, $3);
+ }
+ | SQL_ENUM symbol
+ {
+ $$ = cat2_str(make_str("enum"), $2);
+ }
+
+enum_definition: '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
+
+struct_type: s_struct '{' variable_declarations '}'
+ {
+ ECPGfree_struct_member(struct_member_list[struct_level]);
+ free(actual_storage[struct_level--]);
+ $$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
+ }
+
+union_type: s_union '{' variable_declarations '}'
+ {
+ ECPGfree_struct_member(struct_member_list[struct_level]);
+ free(actual_storage[struct_level--]);
+ $$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
+ }
+
+s_struct: SQL_STRUCT opt_symbol
+ {
+ struct_member_list[struct_level++] = NULL;
+ if (struct_level >= STRUCT_DEPTH)
+ mmerror(ET_ERROR, "Too many levels in nested structure definition");
+
+ /* reset this variable so we see if there was */
+ /* an initializer specified */
+ initializer = 0;
+
+ $$ = cat2_str(make_str("struct"), $2);
+ }
+
+s_union: UNION opt_symbol
+ {
+ struct_member_list[struct_level++] = NULL;
+ if (struct_level >= STRUCT_DEPTH)
+ mmerror(ET_ERROR, "Too many levels in nested structure definition");
+
+ /* reset this variable so we see if there was */
+ /* an initializer specified */
+ initializer = 0;
+
+ $$ = cat2_str(make_str("union"), $2);
+ }
+
+opt_symbol: /* empty */ { $$ = EMPTY; }
+ | symbol { $$ = $1; }
+
+simple_type: unsigned_type { $$=$1; }
+ | opt_signed signed_type { $$=$2; }
+ ;
+
+unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; }
+ | SQL_UNSIGNED SQL_SHORT SQL_INT { $$ = ECPGt_unsigned_short; }
+ | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; }
+ | SQL_UNSIGNED SQL_INT { $$ = ECPGt_unsigned_int; }
+ | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; }
+ | SQL_UNSIGNED SQL_LONG SQL_INT { $$ = ECPGt_unsigned_long; }
+ | SQL_UNSIGNED CHAR { $$ = ECPGt_unsigned_char; }
+ ;
+
+signed_type: SQL_SHORT { $$ = ECPGt_short; }
+ | SQL_SHORT SQL_INT { $$ = ECPGt_short; }
+ | SQL_INT { $$ = ECPGt_int; }
+ | SQL_LONG { $$ = ECPGt_long; }
+ | SQL_LONG SQL_INT { $$ = ECPGt_long; }
+ | SQL_BOOL { $$ = ECPGt_bool; };
+ | FLOAT { $$ = ECPGt_float; }
+ | DOUBLE { $$ = ECPGt_double; }
+ | CHAR { $$ = ECPGt_char; }
+ ;
+
+opt_signed: SQL_SIGNED
+ | /* EMPTY */
+ ;
+
+varchar_type: VARCHAR { $$ = ECPGt_varchar; }
+
+variable_list: variable
+ {
+ $$ = $1;
+ }
+ | variable_list ',' variable
+ {
+ $$ = cat_str(3, $1, make_str(","), $3);
+ }
+
+variable: opt_pointer symbol opt_array_bounds opt_initializer
+ {
+ struct ECPGtype * type;
+ int dimension = $3.index1; /* dimension of array */
+ int length = $3.index2; /* lenght of string */
+ char dim[14L], ascii_len[12];
+
+ adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1));
+
+ switch (actual_type[struct_level].type_enum)
+ {
+ case ECPGt_struct:
+ case ECPGt_union:
+ if (dimension < 0)
+ type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum);
+ else
+ type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum), dimension);
+
+ $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
+ break;
+ case ECPGt_varchar:
+ if (dimension == -1)
+ type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
+ else
+ type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
+
+ switch(dimension)
+ {
+ case 0:
+ case -1:
+ case 1:
+ *dim = '\0';
+ break;
+ default:
+ sprintf(dim, "[%d]", dimension);
+ break;
+ }
+ sprintf(ascii_len, "%d", length);
+
+ if (length == 0)
+ mmerror(ET_ERROR, "pointer to varchar are not implemented");
+
+ if (dimension == 0)
+ $$ = 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);
+ else
+ $$ = 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);
+
+ break;
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ if (dimension == -1)
+ type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
+ else
+ type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
+
+ $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
+ break;
+ default:
+ if (dimension < 0)
+ type = ECPGmake_simple_type(actual_type[struct_level].type_enum, 1);
+ else
+ type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, 1), dimension);
+
+ $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
+ break;
+ }
+
+ if (struct_level == 0)
+ new_variable($2, type);
+ else
+ ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
+
+ free($2);
+ }
+
+opt_initializer: /* empty */ { $$ = EMPTY; }
+ | '=' c_term {
+ initializer = 1;
+ $$ = cat2_str(make_str("="), $2);
+ }
+
+opt_pointer: /* empty */ { $$ = EMPTY; }
+ | '*' { $$ = make_str("*"); }
+
+/*
+ * As long as the prepare statement is not supported by the backend, we will
+ * try to simulate it here so we get dynamic SQL
+ */
+ECPGDeclare: DECLARE STATEMENT ident
+ {
+ /* this is only supported for compatibility */
+ $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
+ }
+/*
+ * the exec sql disconnect statement: disconnect from the given database
+ */
+ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
+
+dis_name: connection_object { $$ = $1; }
+ | CURRENT { $$ = make_str("CURRENT"); }
+ | ALL { $$ = make_str("ALL"); }
+ | /* empty */ { $$ = make_str("CURRENT"); }
+
+connection_object: connection_target { $$ = $1; }
+ | DEFAULT { $$ = make_str("DEFAULT"); }
+
+/*
+ * execute a given string as sql command
+ */
+ECPGExecute : EXECUTE IMMEDIATE execstring
+ {
+ struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
+
+ thisquery->type = &ecpg_query;
+ thisquery->brace_level = 0;
+ thisquery->next = NULL;
+ thisquery->name = $3;
+
+ add_variable(&argsinsert, thisquery, &no_indicator);
+
+ $$ = make_str("?");
+ }
+ | EXECUTE ident
+ {
+ struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
+
+ thisquery->type = &ecpg_query;
+ thisquery->brace_level = 0;
+ thisquery->next = NULL;
+ thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($2));
+ sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $2);
+
+ add_variable(&argsinsert, thisquery, &no_indicator);
+ } ecpg_using
+ {
+ $$ = make_str("?");
+ }
+
+execstring: char_variable |
+ CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); };
+
+/*
+ * the exec sql free command to deallocate a previously
+ * prepared statement
+ */
+ECPGFree: SQL_FREE ident { $$ = $2; }
+
+/*
+ * open is an open cursor, at the moment this has to be removed
+ */
+ECPGOpen: SQL_OPEN name ecpg_using {
+ $$ = $2;
+};
+
+ecpg_using: /* empty */ { $$ = EMPTY; }
+ | USING variablelist {
+ /* mmerror ("open cursor with variables not implemented yet"); */
+ $$ = EMPTY;
+ }
+
+variablelist: cinputvariable | cinputvariable ',' variablelist
+
+/*
+ * As long as the prepare statement is not supported by the backend, we will
+ * try to simulate it here so we get dynamic SQL
+ */
+ECPGPrepare: SQL_PREPARE ident FROM execstring
+ {
+ $$ = cat2_str(make3_str(make_str("\""), $2, make_str("\",")), $4);
+ }
+
+/*
+ * dynamic SQL: descriptor based access
+ * written by Christof Petig <christof.petig@wtal.de>
+ */
+
+/*
+ * deallocate a descriptor
+ */
+ECPGDeallocateDescr: SQL_DEALLOCATE SQL_DESCRIPTOR ident
+{ drop_descriptor($3,connection);
+ $$ = $3;
+}
+
+/*
+ * allocate a descriptor
+ */
+ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR ident
+{ add_descriptor($3,connection);
+ $$ = $3;
+}
+
+/*
+ * read from descriptor
+ */
+
+ECPGGetDescHeaderItem: cvariable '=' ident {
+ push_assignment($1,$3);
+}
+
+ECPGGetDescItem: cvariable '=' ident {
+ push_assignment($1,$3);
+}
+ | cvariable '=' TYPE_P {
+ push_assignment($1,"type");
+}
+ | cvariable '=' PRECISION {
+ push_assignment($1,"precision");
+}
+ | cvariable '=' SQL_INDICATOR {
+ push_assignment($1,"indicator");
+}
+
+ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
+ | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem;
+
+ECPGGetDescItems: ECPGGetDescItem
+ | ECPGGetDescItems ',' ECPGGetDescItem;
+
+ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR ident ECPGGetDescHeaderItems
+{ $$ = $3; }
+
+ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR ident SQL_VALUE cvariable ECPGGetDescItems
+{ $$ = $3; descriptor_index=$5; }
+ | SQL_GET SQL_DESCRIPTOR ident SQL_VALUE Iconst ECPGGetDescItems
+{ $$ = $3; descriptor_index=$5; }
+
+/*
+ * fetch [ in | from ] <portalname> into sql descriptor <name>
+ */
+
+FetchDescriptorStmt: FETCH from_in name INTO SQL_SQL SQL_DESCRIPTOR ident
+ {
+ $$ = cat_str(3, make_str("fetch"), $2, $3);
+ descriptor_name=$7;
+ }
+ | FETCH name INTO SQL_SQL SQL_DESCRIPTOR ident
+ {
+ $$ = cat2_str(make_str("fetch"), $2);
+ descriptor_name=$6;
+ }
+ ;
+
+/*
+ * for compatibility with ORACLE we will also allow the keyword RELEASE
+ * after a transaction statement to disconnect from the database.
+ */
+
+ECPGRelease: TransactionStmt SQL_RELEASE
+ {
+ if (strcmp($1, "begin") == 0)
+ mmerror(ET_ERROR, "RELEASE does not make sense when beginning a transaction");
+
+ fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");",
+ connection ? connection : "NULL", $1);
+ whenever_action(0);
+ fprintf(yyout, "ECPGdisconnect(__LINE__, \"\");");
+ whenever_action(0);
+ free($1);
+ }
+
+/*
+ * set/reset the automatic transaction mode, this needs a differnet handling
+ * as the other set commands
+ */
+ECPGSetAutocommit: SET SQL_AUTOCOMMIT to_equal on_off
+ {
+ $$ = $4;
+ }
+
+on_off: ON { $$ = make_str("on"); }
+ | SQL_OFF { $$ = make_str("off"); }
+
+to_equal: TO | '=';
/*
* set the actual connection, this needs a differnet handling as the other
* set commands
*/
-ECPGSetConnection: SET SQL_CONNECTION connection_object
+ECPGSetConnection: SET SQL_CONNECTION to_equal connection_object
{
- $$ = $3;
+ $$ = $4;
}
+
/*
- * whenever statement: decide what to do in case of error/no data found
- * according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION
- * and SQLWARNING
+ * define a new type for embedded SQL
+ */
+ECPGTypedef: TYPE_P symbol IS type opt_type_array_bounds opt_reference
+ {
+ /* add entry to list */
+ struct typedefs *ptr, *this;
+ int dimension = $5.index1;
+ int length = $5.index2;
+
+ if (($4.type_enum == ECPGt_struct ||
+ $4.type_enum == ECPGt_union) &&
+ initializer == 1)
+ mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+
+ for (ptr = types; ptr != NULL; ptr = ptr->next)
+ {
+ if (strcmp($2, ptr->name) == 0)
+ {
+ /* re-definition is a bug */
+ sprintf(errortext, "Type %s already defined", $2);
+ mmerror(ET_ERROR, errortext);
+ }
+ }
+
+ adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6));
+
+ this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
+
+ /* initial definition */
+ this->next = types;
+ this->name = $2;
+ this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+ this->type->type_enum = $4.type_enum;
+ this->type->type_str = mm_strdup($2);
+ this->type->type_dimension = dimension; /* dimension of array */
+ this->type->type_index = length; /* lenght of string */
+ this->struct_member_list = ($4.type_enum == ECPGt_struct || $4.type_enum == ECPGt_union) ?
+ struct_member_list[struct_level] : NULL;
+
+ if ($4.type_enum != ECPGt_varchar &&
+ $4.type_enum != ECPGt_char &&
+ $4.type_enum != ECPGt_unsigned_char &&
+ this->type->type_index >= 0)
+ mmerror(ET_ERROR, "No multi-dimensional array support for simple data types");
+
+ types = this;
+
+ $$ = 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("*/"));
+ }
+
+opt_type_array_bounds: '[' ']' opt_type_array_bounds
+ {
+ $$.index1 = 0;
+ $$.index2 = $3.index1;
+ $$.str = cat2_str(make_str("[]"), $3.str);
+ }
+ | '(' ')' opt_type_array_bounds
+ {
+ $$.index1 = 0;
+ $$.index2 = $3.index1;
+ $$.str = cat2_str(make_str("[]"), $3.str);
+ }
+ | '[' Iresult ']' opt_type_array_bounds
+ {
+ char *txt = mm_alloc(20L);
+
+ sprintf (txt, "%d", $2);
+ $$.index1 = $2;
+ $$.index2 = $4.index1;
+ $$.str = cat_str(4, make_str("["), txt, make_str("]"), $4.str);
+ }
+ | '(' Iresult ')' opt_type_array_bounds
+ {
+ char *txt = mm_alloc(20L);
+
+ sprintf (txt, "%d", $2);
+ $$.index1 = $2;
+ $$.index2 = $4.index1;
+ $$.str = cat_str(4, make_str("["), txt, make_str("]"), $4.str);
+ }
+ | /* EMPTY */
+ {
+ $$.index1 = -1;
+ $$.index2 = -1;
+ $$.str= EMPTY;
+ }
+ ;
+
+opt_reference: SQL_REFERENCE { $$ = make_str("reference"); }
+ | /* empty */ { $$ = EMPTY; }
+/*
+ * define the type of one variable for embedded SQL
+ */
+ECPGVar: SQL_VAR symbol IS type opt_type_array_bounds opt_reference
+ {
+ struct variable *p = find_variable($2);
+ int dimension = $5.index1;
+ int length = $5.index2;
+ struct ECPGtype * type;
+
+ if (($4.type_enum == ECPGt_struct ||
+ $4.type_enum == ECPGt_union) &&
+ initializer == 1)
+ mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
+
+ adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6));
+
+ switch ($4.type_enum)
+ {
+ case ECPGt_struct:
+ case ECPGt_union:
+ if (dimension < 0)
+ type = ECPGmake_struct_type(struct_member_list[struct_level], $4.type_enum);
+ else
+ type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $4.type_enum), dimension);
+ break;
+ case ECPGt_varchar:
+ if (dimension == -1)
+ type = ECPGmake_simple_type($4.type_enum, length);
+ else
+ type = ECPGmake_array_type(ECPGmake_simple_type($4.type_enum, length), dimension);
+
+ break;
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ if (dimension == -1)
+ type = ECPGmake_simple_type($4.type_enum, length);
+ else
+ type = ECPGmake_array_type(ECPGmake_simple_type($4.type_enum, length), dimension);
+
+ break;
+ default:
+ if (length >= 0)
+ mmerror(ET_ERROR, "No multi-dimensional array support for simple data types");
+
+ if (dimension < 0)
+ type = ECPGmake_simple_type($4.type_enum, 1);
+ else
+ type = ECPGmake_array_type(ECPGmake_simple_type($4.type_enum, 1), dimension);
+
+ break;
+ }
+
+ ECPGfree_type(p->type);
+ p->type = type;
+
+ $$ = 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("*/"));
+ }
+
+/*
+ * whenever statement: decide what to do in case of error/no data found
+ * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
*/
ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action {
when_error.code = $<action>3.code;
when_error.command = $<action>3.command;
- $$ = cat3_str(make1_str("/* exec sql whenever sqlerror "), $3.str, make1_str("; */\n"));
+ $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */\n"));
}
| SQL_WHENEVER NOT SQL_FOUND action {
when_nf.code = $<action>4.code;
when_nf.command = $<action>4.command;
- $$ = cat3_str(make1_str("/* exec sql whenever not found "), $4.str, make1_str("; */\n"));
+ $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */\n"));
+}
+ | SQL_WHENEVER SQL_SQLWARNING action {
+ when_warn.code = $<action>3.code;
+ when_warn.command = $<action>3.command;
+ $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */\n"));
}
action : SQL_CONTINUE {
$<action>$.code = W_NOTHING;
$<action>$.command = NULL;
- $<action>$.str = make1_str("continue");
+ $<action>$.str = make_str("continue");
}
| SQL_SQLPRINT {
$<action>$.code = W_SQLPRINT;
$<action>$.command = NULL;
- $<action>$.str = make1_str("sqlprint");
+ $<action>$.str = make_str("sqlprint");
}
| SQL_STOP {
$<action>$.code = W_STOP;
$<action>$.command = NULL;
- $<action>$.str = make1_str("stop");
+ $<action>$.str = make_str("stop");
}
| SQL_GOTO name {
$<action>$.code = W_GOTO;
- $<action>$.command = $2;
- $<action>$.str = cat2_str(make1_str("goto "), $2);
+ $<action>$.command = strdup($2);
+ $<action>$.str = cat2_str(make_str("goto "), $2);
}
| SQL_GO TO name {
$<action>$.code = W_GOTO;
- $<action>$.command = $3;
- $<action>$.str = cat2_str(make1_str("goto "), $3);
+ $<action>$.command = strdup($3);
+ $<action>$.str = cat2_str(make_str("goto "), $3);
}
- | DO name '(' dotext ')' {
+ | DO name '(' c_args ')' {
$<action>$.code = W_DO;
- $<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")"));
- $<action>$.str = cat2_str(make1_str("do"), mm_strdup($<action>$.command));
+ $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
+ $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
}
| DO SQL_BREAK {
$<action>$.code = W_BREAK;
$<action>$.command = NULL;
- $<action>$.str = make1_str("break");
+ $<action>$.str = make_str("break");
}
- | SQL_CALL name '(' dotext ')' {
+ | SQL_CALL name '(' c_args ')' {
$<action>$.code = W_DO;
- $<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")"));
- $<action>$.str = cat2_str(make1_str("call"), mm_strdup($<action>$.command));
+ $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
+ $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
}
/* some other stuff for ecpg */
-
-ecpg_expr: attr opt_indirection
- {
- $$ = cat2_str($1, $2);
- }
- | row_expr
- { $$ = $1; }
- | AexprConst
- { $$ = $1; }
- | ColId
- {
- $$ = $1;
- }
+/*
+ * no longer used
+ecpg_expr: c_expr
+ { $$ = $1; }
+ | a_expr TYPECAST Typename
+ { $$ = cat_str(3, $1, make_str("::"), $3); }
| '-' ecpg_expr %prec UMINUS
- { $$ = cat2_str(make1_str("-"), $2); }
+ { $$ = cat2_str(make_str("-"), $2); }
+ | '%' ecpg_expr
+ { $$ = cat2_str(make_str("%"), $2); }
+ | '^' ecpg_expr
+ { $$ = cat2_str(make_str("^"), $2); }
+ | '|' ecpg_expr
+ { $$ = cat2_str(make_str("|"), $2); }
+ | ';' a_expr
+ { $$ = cat2_str(make_str(";"), $2); }
+ | a_expr '%'
+ { $$ = cat2_str($1, make_str("%")); }
+ | a_expr '^'
+ { $$ = cat2_str($1, make_str("^")); }
+ | a_expr '|'
+ { $$ = cat2_str($1, make_str("|")); }
| a_expr '+' ecpg_expr
- { $$ = cat3_str($1, make1_str("+"), $3); }
+ { $$ = cat_str(3, $1, make_str("+"), $3); }
| a_expr '-' ecpg_expr
- { $$ = cat3_str($1, make1_str("-"), $3); }
- | a_expr '/' ecpg_expr
- { $$ = cat3_str($1, make1_str("/"), $3); }
+ { $$ = cat_str(3, $1, make_str("-"), $3); }
| a_expr '*' ecpg_expr
- { $$ = cat3_str($1, make1_str("*"), $3); }
+ { $$ = cat_str(3, $1, make_str("*"), $3); }
+ | a_expr '/' ecpg_expr
+ { $$ = cat_str(3, $1, make_str("/"), $3); }
+ | a_expr '%' ecpg_expr
+ { $$ = cat_str(3, $1, make_str("%"), $3); }
+ | a_expr '^' ecpg_expr
+ { $$ = cat_str(3, $1, make_str("^"), $3); }
+ | a_expr '|' ecpg_expr
+ { $$ = cat_str(3, $1, make_str("|"), $3); }
| a_expr '<' ecpg_expr
- { $$ = cat3_str($1, make1_str("<"), $3); }
+ { $$ = cat_str(3, $1, make_str("<"), $3); }
| a_expr '>' ecpg_expr
- { $$ = cat3_str($1, make1_str(">"), $3); }
+ { $$ = cat_str(3, $1, make_str(">"), $3); }
+ | a_expr '=' NULL_P
+ { $$ = cat2_str($1, make_str("= NULL")); }
+ | NULL_P '=' ecpg_expr
+ { $$ = cat2_str(make_str("= NULL"), $3); }
| a_expr '=' ecpg_expr
- { $$ = cat3_str($1, make1_str("="), $3); }
- /* | ':' ecpg_expr
- { $$ = cat2_str(make1_str(":"), $2); }*/
- | ';' ecpg_expr
- { $$ = cat2_str(make1_str(";"), $2); }
- | '|' ecpg_expr
- { $$ = cat2_str(make1_str("|"), $2); }
- | a_expr TYPECAST Typename
- {
- $$ = cat3_str($1, make1_str("::"), $3);
- }
- | CAST '(' a_expr AS Typename ')'
- {
- $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")")));
- }
- | '(' a_expr_or_null ')'
- { $$ = make3_str(make1_str("("), $2, make1_str(")")); }
+ { $$ = cat_str(3, $1, make_str("="), $3); }
| a_expr Op ecpg_expr
- { $$ = cat3_str($1, $2, $3); }
- | a_expr LIKE ecpg_expr
- { $$ = cat3_str($1, make1_str("like"), $3); }
- | a_expr NOT LIKE ecpg_expr
- { $$ = cat3_str($1, make1_str("not like"), $4); }
+ { $$ = cat_str(3, $1, make_str("="), $3); }
| Op ecpg_expr
{ $$ = cat2_str($1, $2); }
| a_expr Op
{ $$ = cat2_str($1, $2); }
- | func_name '(' '*' ')'
- {
- $$ = cat2_str($1, make1_str("(*)"));
- }
- | func_name '(' ')'
- {
- $$ = cat2_str($1, make1_str("()"));
- }
- | func_name '(' expr_list ')'
- {
- $$ = make4_str($1, make1_str("("), $3, make1_str(")"));
- }
- | CURRENT_DATE
- {
- $$ = make1_str("current_date");
- }
- | CURRENT_TIME
- {
- $$ = make1_str("current_time");
- }
- | CURRENT_TIME '(' Iconst ')'
- {
- if (atol($3) != 0)
- fprintf(stderr,"CURRENT_TIME(%s) precision not implemented; zero used instead", $3);
- $$ = make1_str("current_time");
- }
- | CURRENT_TIMESTAMP
- {
- $$ = make1_str("current_timestamp");
- }
- | CURRENT_TIMESTAMP '(' Iconst ')'
- {
- if (atol($3) != 0)
- fprintf(stderr,"CURRENT_TIMESTAMP(%s) precision not implemented; zero used instead",$3);
- $$ = make1_str("current_timestamp");
- }
- | CURRENT_USER
- {
- $$ = make1_str("current_user");
- }
- | EXISTS '(' SubSelect ')'
- {
- $$ = make3_str(make1_str("exists("), $3, make1_str(")"));
- }
- | EXTRACT '(' extract_list ')'
- {
- $$ = make3_str(make1_str("extract("), $3, make1_str(")"));
- }
- | POSITION '(' position_list ')'
- {
- $$ = make3_str(make1_str("position("), $3, make1_str(")"));
- }
- | SUBSTRING '(' substr_list ')'
- {
- $$ = make3_str(make1_str("substring("), $3, make1_str(")"));
- }
- /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
- | TRIM '(' BOTH trim_list ')'
- {
- $$ = make3_str(make1_str("trim(both"), $4, make1_str(")"));
- }
- | TRIM '(' LEADING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")"));
- }
- | TRIM '(' TRAILING trim_list ')'
- {
- $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")"));
- }
- | TRIM '(' trim_list ')'
- {
- $$ = make3_str(make1_str("trim("), $3, make1_str(")"));
- }
+ | a_expr AND ecpg_expr
+ { $$ = cat_str(3, $1, make_str("and"), $3); }
+ | a_expr OR ecpg_expr
+ { $$ = cat_str(3, $1, make_str("or"), $3); }
+ | NOT ecpg_expr
+ { $$ = cat2_str(make_str("not"), $2); }
+ | a_expr LIKE ecpg_expr
+ { $$ = cat_str(3, $1, make_str("like"), $3); }
+ | a_expr NOT LIKE ecpg_expr
+ { $$ = cat_str(3, $1, make_str("not like"), $4); }
| a_expr ISNULL
- { $$ = cat2_str($1, make1_str("isnull")); }
+ { $$ = cat2_str($1, make_str("isnull")); }
| a_expr IS NULL_P
- { $$ = cat2_str($1, make1_str("is null")); }
+ { $$ = cat2_str($1, make_str("is null")); }
| a_expr NOTNULL
- { $$ = cat2_str($1, make1_str("notnull")); }
+ { $$ = cat2_str($1, make_str("notnull")); }
| a_expr IS NOT NULL_P
- { $$ = cat2_str($1, make1_str("is not null")); }
- /* IS TRUE, IS FALSE, etc used to be function calls
- * but let's make them expressions to allow the optimizer
- * a chance to eliminate them if a_expr is a constant string.
- * - thomas 1997-12-22
- */
+ { $$ = cat2_str($1, make_str("is not null")); }
| a_expr IS TRUE_P
- {
- { $$ = cat2_str($1, make1_str("is true")); }
- }
+ { $$ = cat2_str($1, make_str("is true")); }
| a_expr IS NOT FALSE_P
- {
- { $$ = cat2_str($1, make1_str("is not false")); }
- }
+ { $$ = cat2_str($1, make_str("is not false")); }
| a_expr IS FALSE_P
- {
- { $$ = cat2_str($1, make1_str("is false")); }
- }
+ { $$ = cat2_str($1, make_str("is false")); }
| a_expr IS NOT TRUE_P
- {
- { $$ = cat2_str($1, make1_str("is not true")); }
- }
+ { $$ = cat2_str($1, make_str("is not true")); }
| a_expr BETWEEN b_expr AND b_expr
{
- $$ = cat5_str($1, make1_str("between"), $3, make1_str("and"), $5);
+ $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5);
}
| a_expr NOT BETWEEN b_expr AND b_expr
{
- $$ = cat5_str($1, make1_str("not between"), $4, make1_str("and"), $6);
+ $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6);
}
| a_expr IN '(' in_expr ')'
{
- $$ = make4_str($1, make1_str("in ("), $4, make1_str(")"));
- }
- | a_expr NOT IN '(' not_in_expr ')'
- {
- $$ = make4_str($1, make1_str("not in ("), $5, make1_str(")"));
- }
- | a_expr Op '(' SubSelect ')'
- {
- $$ = cat3_str($1, $2, make3_str(make1_str("("), $4, make1_str(")")));
- }
- | a_expr '+' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("+("), $4, make1_str(")"));
- }
- | a_expr '-' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("-("), $4, make1_str(")"));
- }
- | a_expr '/' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("/("), $4, make1_str(")"));
- }
- | a_expr '*' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("*("), $4, make1_str(")"));
- }
- | a_expr '<' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("<("), $4, make1_str(")"));
- }
- | a_expr '>' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str(">("), $4, make1_str(")"));
- }
- | a_expr '=' '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("=("), $4, make1_str(")"));
- }
- | a_expr Op ANY '(' SubSelect ')'
- {
- $$ = cat3_str($1, $2, make3_str(make1_str("any ("), $5, make1_str(")")));
- }
- | a_expr '+' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("+any("), $5, make1_str(")"));
- }
- | a_expr '-' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("-any("), $5, make1_str(")"));
- }
- | a_expr '/' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("/any("), $5, make1_str(")"));
- }
- | a_expr '*' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("*any("), $5, make1_str(")"));
- }
- | a_expr '<' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("<any("), $5, make1_str(")"));
- }
- | a_expr '>' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str(">any("), $5, make1_str(")"));
- }
- | a_expr '=' ANY '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("=any("), $5, make1_str(")"));
- }
- | a_expr Op ALL '(' SubSelect ')'
- {
- $$ = make3_str($1, $2, make3_str(make1_str("all ("), $5, make1_str(")")));
+ $$ = cat_str(4, $1, make_str(" in ("), $4, make_str(")"));
}
- | a_expr '+' ALL '(' SubSelect ')'
+ | a_expr NOT IN '(' in_expr ')'
{
- $$ = make4_str($1, make1_str("+all("), $5, make1_str(")"));
+ $$ = cat_str(4, $1, make_str(" not in ("), $5, make_str(")"));
}
- | a_expr '-' ALL '(' SubSelect ')'
+ | a_expr all_Op sub_type '(' SubSelect ')'
{
- $$ = make4_str($1, make1_str("-all("), $5, make1_str(")"));
+ $$ = cat_str(4, $1, $2, $3, cat_str(3, make_str("("), $5, make_str(")")));
}
- | a_expr '/' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("/all("), $5, make1_str(")"));
- }
- | a_expr '*' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("*all("), $5, make1_str(")"));
- }
- | a_expr '<' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("<all("), $5, make1_str(")"));
- }
- | a_expr '>' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str(">all("), $5, make1_str(")"));
- }
- | a_expr '=' ALL '(' SubSelect ')'
- {
- $$ = make4_str($1, make1_str("=all("), $5, make1_str(")"));
- }
- | a_expr AND ecpg_expr
- { $$ = cat3_str($1, make1_str("and"), $3); }
- | a_expr OR ecpg_expr
- { $$ = cat3_str($1, make1_str("or"), $3); }
- | NOT ecpg_expr
- { $$ = cat2_str(make1_str("not"), $2); }
+ | row_expr
+ { $$ = $1; }
| civariableonly
- { $$ = make1_str(";;"); }
+ { $$ = $1; }
;
+*/
into_list : coutputvariable | into_list ',' coutputvariable;
ecpgstart: SQL_START { reset_variables();}
-dotext: /* empty */ { $$ = make1_str(""); }
- | dotext do_anything { $$ = make2_str($1, $2); }
-
-vartext: var_anything { $$ = $1; }
- | vartext var_anything { $$ = make2_str($1, $2); }
+c_args: /* empty */ { $$ = EMPTY; }
+ | c_list { $$ = $1; }
coutputvariable : cvariable indicator {
add_variable(&argsresult, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2));
civariableonly : cvariable {
add_variable(&argsinsert, find_variable($1), &no_indicator);
+ $$ = make_str("?");
}
cvariable: CVARIABLE { $$ = $1; }
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
ident: IDENT { $$ = $1; }
- | CSTRING { $$ = $1; }
+ | CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); };
+
/*
* C stuff
*/
cpp_line: CPP_LINE { $$ = $1; }
-c_line: c_anything { $$ = $1; }
- | c_line c_anything
- {
- $$ = make2_str($1, $2);
- }
+c_stuff: c_anything { $$ = $1; }
+ | c_stuff c_anything
+ {
+ $$ = cat2_str($1, $2);
+ }
+ | c_stuff '(' c_stuff ')'
+ {
+ $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));
+ }
+
+c_list: c_term { $$ = $1; }
+ | c_list ',' c_term { $$ = cat_str(3, $1, make_str(","), $3); }
-c_thing: c_anything | ';' { $$ = make1_str(";"); }
+c_term: c_stuff { $$ = $1; }
+ | '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
+
+c_thing: c_anything { $$ = $1; }
+ | '(' { $$ = make_str("("); }
+ | ')' { $$ = make_str(")"); }
+ | ',' { $$ = make_str(","); }
+ | ';' { $$ = make_str(";"); }
c_anything: IDENT { $$ = $1; }
- | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
+ | CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
| Iconst { $$ = $1; }
| Fconst { $$ = $1; }
- | '*' { $$ = make1_str("*"); }
- | S_AUTO { $$ = make1_str("auto"); }
- | S_BOOL { $$ = make1_str("bool"); }
- | S_CHAR { $$ = make1_str("char"); }
- | S_CONST { $$ = make1_str("const"); }
- | S_DOUBLE { $$ = make1_str("double"); }
- | S_EXTERN { $$ = make1_str("extern"); }
- | S_FLOAT { $$ = make1_str("float"); }
- | S_INT { $$ = make1_str("int"); }
- | S_LONG { $$ = make1_str("long"); }
- | S_REGISTER { $$ = make1_str("register"); }
- | S_SHORT { $$ = make1_str("short"); }
- | S_SIGNED { $$ = make1_str("signed"); }
- | S_STATIC { $$ = make1_str("static"); }
- | S_STRUCT { $$ = make1_str("struct"); }
- | S_UNSIGNED { $$ = make1_str("unsigned"); }
- | S_VARCHAR { $$ = make1_str("varchar"); }
+ | '*' { $$ = make_str("*"); }
+ | '+' { $$ = make_str("+"); }
+ | '-' { $$ = make_str("-"); }
+ | '/' { $$ = make_str("/"); }
+ | '%' { $$ = make_str("%"); }
| S_ANYTHING { $$ = make_name(); }
- | '[' { $$ = make1_str("["); }
- | ']' { $$ = make1_str("]"); }
- | '(' { $$ = make1_str("("); }
- | ')' { $$ = make1_str(")"); }
- | '=' { $$ = make1_str("="); }
- | ',' { $$ = make1_str(","); }
-
-do_anything: IDENT { $$ = $1; }
- | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\""));}
- | Iconst { $$ = $1; }
- | Fconst { $$ = $1; }
- | ',' { $$ = make1_str(","); }
-
-var_anything: IDENT { $$ = $1; }
- | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); }
- | Iconst { $$ = $1; }
- | Fconst { $$ = $1; }
- | '{' c_line '}' { $$ = make3_str(make1_str("{"), $2, make1_str("}")); }
+ | S_AUTO { $$ = make_str("auto"); }
+ | S_CONST { $$ = make_str("const"); }
+ | S_EXTERN { $$ = make_str("extern"); }
+ | S_REGISTER { $$ = make_str("register"); }
+ | S_STATIC { $$ = make_str("static"); }
+ | SQL_BOOL { $$ = make_str("bool"); }
+ | SQL_ENUM { $$ = make_str("enum"); }
+ | SQL_INT { $$ = make_str("int"); }
+ | SQL_LONG { $$ = make_str("long"); }
+ | SQL_SHORT { $$ = make_str("short"); }
+ | SQL_SIGNED { $$ = make_str("signed"); }
+ | SQL_STRUCT { $$ = make_str("struct"); }
+ | SQL_UNSIGNED { $$ = make_str("unsigned"); }
+ | CHAR { $$ = make_str("char"); }
+ | DOUBLE { $$ = make_str("double"); }
+ | FLOAT { $$ = make_str("float"); }
+ | UNION { $$ = make_str("union"); }
+ | VARCHAR { $$ = make_str("varchar"); }
+ | '[' { $$ = make_str("["); }
+ | ']' { $$ = make_str("]"); }
+/* | '(' { $$ = make_str("("); }
+ | ')' { $$ = make_str(")"); }*/
+ | '=' { $$ = make_str("="); }
blockstart : '{' {
braces_open++;
- $$ = make1_str("{");
+ $$ = make_str("{");
}
blockend : '}' {
remove_variables(braces_open--);
- $$ = make1_str("}");
+ $$ = make_str("}");
}
%%
void yyerror(char * error)
{
- fprintf(stderr, "%s:%d: %s\n", input_filename, yylineno, error);
- exit(PARSE_ERROR);
+ mmerror(ET_ERROR, error);
}