diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index a8f3335447b26810a722c503bebbf165d5643f19..5828ef8a81b90f8b309469b0dba84cfd662b731c 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -149,3 +149,43 @@ Mon Apr 27 14:26:55 CEST 1998 and :foo.bar as variables. - Set version to 2.2.0 +Tue Apr 28 14:48:41 CEST 1998 + + - Put operator "->" back into parser. Note that :foo->bar means the + C term, but :foo ->bar means the operator "->". + +Tue Apr 28 15:49:07 CEST 1998 + + - Added exec sql disconnect command. + - Allow varchar in C to be written in uppercase too. + - Added whenever option "do break;" + +Wed Apr 29 09:17:53 CEST 1998 + + - Corrected parsing of C comments. + - Also allow C++ style comments. + - Make sure not found is only checked after commands that could + return it. + - Added error codes, see ecpgerror.h for details. + - Added "exec sql <TransactionStmt> release" as disconnect statement + for compatibility issues. + +Thu Apr 30 10:42:10 CEST 1998 + + - Added a -t option to disable automatic transaction start. + - Added sqlerrd[] to sqlca struct. + - Give back number of tuples affect in sqlca.sqlerrd[2]. + +Thu Apr 30 13:36:02 CEST 1998 + + - Make the return code different in case of different errors. + +Wed May 6 11:42:48 CEST 1998 + + - Free memory if possible + - Some bugfixes for bugs I found while changing the memory + allocation code + - Now able to fill complete array with one call (see test1.pgc for + an example) + - Set version to 2.3.0 + - Set library version to 2.1 diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO index 68d3808aed46beee89d7deb8c870643c5e33327a..3787f100ed5dab9269eb1d4d933c9d01c6c1d7be 100644 --- a/src/interfaces/ecpg/TODO +++ b/src/interfaces/ecpg/TODO @@ -1,55 +1,14 @@ -This list is still from Linus. MM - -The variables should be static. - -There should be different error numbers for the different errors instead of -just -1 for them all. - -Missing library functions to_date et al. - -Oracle has array operations that enhances speed. When implementing it in -ecpg it is done for compatibility reasons only. For them to improve speed -would require a lot more insight in the postgres internal mechanisms than I -possess. - -As well as complex types like records and arrays, typedefs would be a good -thing to take care of. - -To set up a database you need a few scripts with table definitions and other -configuration parameters. If you have these scripts for an old database you -would like to just apply them to get a postgres database that works in the -same way. The functionality could be accomplished with some conversion -scripts. Speed will never be accomplished in this way. To do this you need a -bigger insight in the database construction and the use of the database than -could be realised in a script. - -Now comes my list (MM): - -The return code is alway -1 in case of an error. You cannot see which error -occured by examining the return code. - ecpg does not understand enum datatypes. -There is no exec sql prepare statement. - The complete structure definition has to be listed inside the declare -section for ecpg to be able to understand it. +section of the structure variable for ecpg to be able to understand it. -There is no way yet to fill a complete array with one call except arrays of -[unsigned] char which are considered strings. +Variable type bool has to be checked. I never used it so far. ecpg cannot use pointer variables except [unsigned] char * -give back the number of tuples affected via sqlca +There is no exec sql type statement which is the SQL version of a typedef. -exec sql disconnect {current|default|all|connectionname|connection_hostvar}; - oder <disconnect statement> ::= - DISCONNECT <disconnect object> - - <disconnect object> ::= - <connection object> - | ALL - | CURRENT - commit release|commit work release auch disconnect +There is no exec sql prepare statement. -It is not neccessary to check for "not found" after all commands. +There is no SQLSTATE diff --git a/src/interfaces/ecpg/include/Makefile b/src/interfaces/ecpg/include/Makefile index caa13a8d9162c69d4e97c1a012fec985c5934f53..836fba3ed77f52205ac9c51a8b868a73becd0855 100644 --- a/src/interfaces/ecpg/include/Makefile +++ b/src/interfaces/ecpg/include/Makefile @@ -6,11 +6,13 @@ all clean:: @echo Nothing to be done. install:: + $(INSTALL) $(INSTLOPTS) ecpgerrno.h $(DESTDIR)$(HEADERDIR) $(INSTALL) $(INSTLOPTS) ecpglib.h $(DESTDIR)$(HEADERDIR) $(INSTALL) $(INSTLOPTS) ecpgtype.h $(DESTDIR)$(HEADERDIR) $(INSTALL) $(INSTLOPTS) sqlca.h $(DESTDIR)$(HEADERDIR) uninstall:: + rm -f $(DESTDIR)$(HEADERDIR)/ecpgerrno.h rm -f $(DESTDIR)$(HEADERDIR)/ecpglib.h rm -f $(DESTDIR)$(HEADERDIR)/ecpgtype.h rm -f $(DESTDIR)$(HEADERDIR)/sqlca.h diff --git a/src/interfaces/ecpg/include/ecpgerrno.h b/src/interfaces/ecpg/include/ecpgerrno.h new file mode 100644 index 0000000000000000000000000000000000000000..1be718216d794ad5ea3f3292e82ed4393e04a05a --- /dev/null +++ b/src/interfaces/ecpg/include/ecpgerrno.h @@ -0,0 +1,22 @@ +#ifndef _ECPG_ERROR_H +#define _ECPG_ERROR_H + +/* This is a list of all error codes the embedded SQL program can return */ +#define ECPG_NO_ERROR 0 +#define ECPG_NOT_FOUND 100 + +#define ECPG_PGSQL -1 +#define ECPG_UNSUPPORTED -2 +#define ECPG_TOO_MANY_ARGUMENTS -3 +#define ECPG_TOO_FEW_ARGUMENTS -4 +#define ECPG_TRANS -5 +#define ECPG_TOO_MANY_MATCHES -6 +#define ECPG_INT_FORMAT -7 +#define ECPG_UINT_FORMAT -8 +#define ECPG_FLOAT_FORMAT -9 +#define ECPG_CONVERT_BOOL -10 +#define ECPG_EMPTY -11 +#define ECPG_CONNECT -12 +#define ECPG_DISCONNECT -13 + +#endif /* !_ECPG_ERROR_H */ diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index b828763fa36940cfdecb169da8a1db41f1e03517..9a5c2732d8ff5208b7768d8e9d8004f5022f0b5b 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -5,11 +5,11 @@ extern "C" { #endif void ECPGdebug(int, FILE *); -bool ECPGconnect(const char *dbname); +bool ECPGconnect(const char *); bool ECPGdo(int, char *,...); bool ECPGtrans(int, const char *); bool ECPGfinish(void); -bool ECPGstatus(void); +bool ECPGdisconnect(const char *); void ECPGlog(const char *format,...); @@ -39,3 +39,5 @@ void sqlprint(void); #ifdef __cplusplus } #endif + +#include <ecpgerrno.h> diff --git a/src/interfaces/ecpg/include/sqlca.h b/src/interfaces/ecpg/include/sqlca.h index e493e46bb5d62c783c3561d2bdaa47dac40e30a5..7e99484d5aed054b45e8302e9219098eef6207b5 100644 --- a/src/interfaces/ecpg/include/sqlca.h +++ b/src/interfaces/ecpg/include/sqlca.h @@ -10,10 +10,11 @@ struct sqlca int sqlcode; struct { - int sqlerrml; + int sqlerrml; char sqlerrmc[1000]; } sqlerrm; -} sqlca; + long sqlerrd[6]; +} sqlca; #endif diff --git a/src/interfaces/ecpg/lib/Makefile.in b/src/interfaces/ecpg/lib/Makefile.in index 037d7f8d327466541db85320c56eb680e85b8dba..0fb1d6f0261900c91286bd948495c2c436f97812 100644 --- a/src/interfaces/ecpg/lib/Makefile.in +++ b/src/interfaces/ecpg/lib/Makefile.in @@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq SO_MAJOR_VERSION=2 -SO_MINOR_VERSION=0 +SO_MINOR_VERSION=1 PORTNAME=@PORTNAME@ diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c index 815f4bff0bc719290ac393292107880770b7b3be..4f40a2e1020c4b565f5894e520470429b990d57c 100644 --- a/src/interfaces/ecpg/lib/ecpglib.c +++ b/src/interfaces/ecpg/lib/ecpglib.c @@ -24,6 +24,8 @@ #include <ecpglib.h> #include <sqlca.h> +extern int no_auto_trans; + static PGconn *simple_connection = NULL; static int simple_debug = 0; static FILE *debugstream = NULL; @@ -80,6 +82,11 @@ ECPGdo(int lineno, char *query,...) PGresult *results; PGnotify *notify; enum ECPGttype type; + void *value = NULL, *ind_value; + long varcharsize, ind_varcharsize; + long arrsize, ind_arrsize; + long offset, ind_offset; + enum ECPGttype ind_type; va_start(ap, query); @@ -96,12 +103,6 @@ ECPGdo(int lineno, char *query,...) */ while (type != ECPGt_EOIT) { - void *value = NULL, *ind_value; - long varcharsize, ind_varcharsize; - long size, ind_size; - long arrsize, ind_arrsize; - enum ECPGttype ind_type; - char *newcopy; char *mallocedval = NULL; char *tobeinserted = NULL; @@ -116,13 +117,13 @@ ECPGdo(int lineno, char *query,...) value = va_arg(ap, void *); varcharsize = va_arg(ap, long); - size = va_arg(ap, long); arrsize = va_arg(ap, long); + offset = va_arg(ap, long); ind_type = va_arg(ap, enum ECPGttype); ind_value = va_arg(ap, void *); ind_varcharsize = va_arg(ap, long); - ind_size = va_arg(ap, long); ind_arrsize = va_arg(ap, long); + ind_offset = va_arg(ap, long); buff[0] = '\0'; @@ -211,7 +212,6 @@ ECPGdo(int lineno, char *query,...) break; case ECPGt_varchar: - case ECPGt_varchar2: { struct ECPGgeneric_varchar *var = (struct ECPGgeneric_varchar *) value; @@ -233,7 +233,7 @@ ECPGdo(int lineno, char *query,...) default: /* Not implemented yet */ - register_error(-1, "Unsupported type %s on line %d.", + register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", ECPGtype_name(type), lineno); return false; break; @@ -257,7 +257,7 @@ ECPGdo(int lineno, char *query,...) * We have an argument but we dont have the matched up string * in the string */ - register_error(-1, "Too many arguments line %d.", lineno); + register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno); return false; } else @@ -293,17 +293,17 @@ ECPGdo(int lineno, char *query,...) /* Check if there are unmatched things left. */ if (strstr(copiedquery, ";;") != NULL) { - register_error(-1, "Too few arguments line %d.", lineno); + register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno); return false; } /* Now the request is built. */ - if (committed) + if (committed && !no_auto_trans) { if ((results = PQexec(simple_connection, "begin transaction")) == NULL) { - register_error(-1, "Error starting transaction line %d.", lineno); + register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno); return false; } PQclear(results); @@ -318,15 +318,15 @@ ECPGdo(int lineno, char *query,...) { ECPGlog("ECPGdo line %d: error: %s", lineno, PQerrorMessage(simple_connection)); - register_error(-1, "Postgres error: %s line %d.", + register_error(ECPG_PGSQL, "Postgres error: %s line %d.", PQerrorMessage(simple_connection), lineno); } else + { + sqlca.sqlerrd[2] = 0; switch (PQresultStatus(results)) { - int m, - n, - x; + int nfields, ntuples, act_tuple, act_field; case PGRES_TUPLES_OK: @@ -336,306 +336,308 @@ ECPGdo(int lineno, char *query,...) * !! */ - m = PQnfields(results); - n = PQntuples(results); - - if (n < 1) + nfields = PQnfields(results); + sqlca.sqlerrd[2] = ntuples = PQntuples(results); + status = true; + + if (ntuples < 1) { ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n", - lineno, n); - register_error(1, "Data not found line %d.", lineno); + lineno, ntuples); + register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno); + status = false; break; } - if (n > 1) - { - ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n", - lineno, n); - register_error(-1, "To many matches line %d.", lineno); - break; - } - - status = true; - - for (x = 0; x < m && status; x++) - { - void *value = NULL, *ind_value; - long varcharsize, ind_varcharsize; - long size, ind_size; - long arrsize, ind_arrsize; - enum ECPGttype ind_type; - - char *pval = PQgetvalue(results, 0, x); - - /* - * long int * res_int; char ** res_charstar; char * - * res_char; int res_len; - */ - char *scan_length; - - ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : ""); - - /* Now the pval is a pointer to the value. */ - /* We will have to decode the value */ - type = va_arg(ap, enum ECPGttype); - value = va_arg(ap, void *); - varcharsize = va_arg(ap, long); - size = va_arg(ap, long); - arrsize = va_arg(ap, long); - ind_type = va_arg(ap, enum ECPGttype); - ind_value = va_arg(ap, void *); - ind_varcharsize = va_arg(ap, long); - ind_size = va_arg(ap, long); - ind_arrsize = va_arg(ap, long); - - /* check for null value and set indicator accordingly */ - switch (ind_type) - { - case ECPGt_short: - case ECPGt_unsigned_short: - *(short *) ind_value = -PQgetisnull(results, 0, x); - break; - case ECPGt_int: - case ECPGt_unsigned_int: - *(int *) ind_value = -PQgetisnull(results, 0, x); - break; - case ECPGt_long: - case ECPGt_unsigned_long: - *(long *) ind_value = -PQgetisnull(results, 0, x); - break; - default: - break; - } - - switch (type) - { - long res; - unsigned long ures; - double dres; - - case ECPGt_short: - case ECPGt_int: - case ECPGt_long: - if (pval) - { - res = strtol(pval, &scan_length, 10); - if (*scan_length != '\0') /* Garbage left */ - { - register_error(-1, "Not correctly formatted int type: %s line %d.", - pval, lineno); - status = false; - res = 0L; - } - } - else - res = 0L; - - /* Again?! Yes */ - switch (type) - { - case ECPGt_short: - *(short *) value = (short) res; - break; - case ECPGt_int: - *(int *) value = (int) res; - break; - case ECPGt_long: - *(long *) value = res; - break; - default: - /* Cannot happen */ - break; - } - break; - - case ECPGt_unsigned_short: - case ECPGt_unsigned_int: - case ECPGt_unsigned_long: - if (pval) - { - ures = strtoul(pval, &scan_length, 10); - if (*scan_length != '\0') /* Garbage left */ - { - register_error(-1, "Not correctly formatted unsigned type: %s line %d.", - pval, lineno); - status = false; - ures = 0L; - } - } - else - ures = 0L; - - /* Again?! Yes */ - switch (type) - { - case ECPGt_unsigned_short: - *(unsigned short *) value = (unsigned short) ures; - break; - case ECPGt_unsigned_int: - *(unsigned int *) value = (unsigned int) ures; - break; - case ECPGt_unsigned_long: - *(unsigned long *) value = ures; - break; - default: - /* Cannot happen */ - break; - } - break; - - - case ECPGt_float: - case ECPGt_double: - if (pval) - { - dres = strtod(pval, &scan_length); - if (*scan_length != '\0') /* Garbage left */ - { - register_error(-1, "Not correctly formatted floating point type: %s line %d.", - pval, lineno); - status = false; - dres = 0.0; - } - } - else - dres = 0.0; - - /* Again?! Yes */ - switch (type) - { - case ECPGt_float: - *(float *) value = dres; - break; - case ECPGt_double: - *(double *) value = dres; - break; - default: - /* Cannot happen */ - break; - } - break; - - case ECPGt_bool: - if (pval) - { - if (pval[0] == 'f' && pval[1] == '\0') - { - *(char *) value = false; - break; - } - else if (pval[0] == 't' && pval[1] == '\0') - { - *(char *) value = true; - break; - } - } - - register_error(-1, "Unable to convert %s to bool on line %d.", - (pval ? pval : "NULL"), - lineno); - return false; - break; - - case ECPGt_char: - case ECPGt_unsigned_char: - { - if (varcharsize == 0) - { - /* char* */ - strncpy((char *) value, pval, strlen(pval)); - ((char *) value)[strlen(pval)] = '\0'; - } - else - { - strncpy((char *) value, pval, varcharsize); - if (varcharsize < strlen(pval)) - { - /* truncation */ - switch (ind_type) - { - case ECPGt_short: - case ECPGt_unsigned_short: - *(short *) ind_value = varcharsize; - break; - case ECPGt_int: - case ECPGt_unsigned_int: - *(int *) ind_value = varcharsize; - break; - case ECPGt_long: - case ECPGt_unsigned_long: - *(long *) ind_value = varcharsize; - break; - default: - break; - } - } - } - } - break; - - case ECPGt_varchar: - { - struct ECPGgeneric_varchar *var = - (struct ECPGgeneric_varchar *) value; - - strncpy(var->arr, pval, varcharsize); - var->len = strlen(pval); - if (var->len > varcharsize) - { - /* truncation */ - switch (ind_type) - { - case ECPGt_short: - case ECPGt_unsigned_short: - *(short *) ind_value = varcharsize; - break; - case ECPGt_int: - case ECPGt_unsigned_int: - *(int *) ind_value = varcharsize; - break; - case ECPGt_long: - case ECPGt_unsigned_long: - *(long *) ind_value = varcharsize; - break; - default: - break; - } - - var->len = varcharsize; - } - } - break; - - case ECPGt_EORT: - ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno); - register_error(-1, "Too few arguments line %d.", lineno); - status = false; - break; - - default: - register_error(-1, "Unsupported type %s on line %d.", - ECPGtype_name(type), lineno); - return false; - break; - } + for (act_field = 0; act_field < nfields && status; act_field++) + { + char *pval; + char *scan_length; + + type = va_arg(ap, enum ECPGttype); + value = va_arg(ap, void *); + varcharsize = va_arg(ap, long); + arrsize = va_arg(ap, long); + offset = va_arg(ap, long); + ind_type = va_arg(ap, enum ECPGttype); + ind_value = va_arg(ap, void *); + ind_varcharsize = va_arg(ap, long); + ind_arrsize = va_arg(ap, long); + ind_offset = va_arg(ap, long); + + /* if we don't have enough space, we cannot read all tuples */ + if ((arrsize > 0 && ntuples > arrsize) || (ind_arrsize > 0 && ntuples > ind_arrsize)) + { + ECPGlog("ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d\n", + lineno, ntuples, arrsize); + register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", lineno); + status = false; + break; + } + for (act_tuple = 0; act_tuple < ntuples; act_tuple++) + { + pval = PQgetvalue(results, act_tuple, act_field); + + ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : ""); + + /* Now the pval is a pointer to the value. */ + /* We will have to decode the value */ + + /* check for null value and set indicator accordingly */ + switch (ind_type) + { + case ECPGt_short: + case ECPGt_unsigned_short: + ((short *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); + break; + case ECPGt_int: + case ECPGt_unsigned_int: + ((int *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); + break; + case ECPGt_long: + case ECPGt_unsigned_long: + ((long *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); + break; + default: + break; + } + + switch (type) + { + long res; + unsigned long ures; + double dres; + + case ECPGt_short: + case ECPGt_int: + case ECPGt_long: + if (pval) + { + res = strtol(pval, &scan_length, 10); + if (*scan_length != '\0') /* Garbage left */ + { + register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.", + pval, lineno); + status = false; + res = 0L; + } + } + else + res = 0L; + + /* Again?! Yes */ + switch (type) + { + case ECPGt_short: + ((short *) value)[act_tuple] = (short) res; + break; + case ECPGt_int: + ((int *) value)[act_tuple] = (int) res; + break; + case ECPGt_long: + ((long *) value)[act_tuple] = res; + break; + default: + /* Cannot happen */ + break; + } + break; + + case ECPGt_unsigned_short: + case ECPGt_unsigned_int: + case ECPGt_unsigned_long: + if (pval) + { + ures = strtoul(pval, &scan_length, 10); + if (*scan_length != '\0') /* Garbage left */ + { + register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.", + pval, lineno); + status = false; + ures = 0L; + } + } + else + ures = 0L; + + /* Again?! Yes */ + switch (type) + { + case ECPGt_unsigned_short: + ((unsigned short *) value)[act_tuple] = (unsigned short) ures; + break; + case ECPGt_unsigned_int: + ((unsigned int *) value)[act_tuple] = (unsigned int) ures; + break; + case ECPGt_unsigned_long: + ((unsigned long *) value)[act_tuple] = ures; + break; + default: + /* Cannot happen */ + break; + } + break; + + + case ECPGt_float: + case ECPGt_double: + if (pval) + { + dres = strtod(pval, &scan_length); + if (*scan_length != '\0') /* Garbage left */ + { + register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.", + pval, lineno); + status = false; + dres = 0.0; + } + } + else + dres = 0.0; + + /* Again?! Yes */ + switch (type) + { + case ECPGt_float: + ((float *) value)[act_tuple] = dres; + break; + case ECPGt_double: + ((double *) value)[act_tuple] = dres; + break; + default: + /* Cannot happen */ + break; + } + break; + + case ECPGt_bool: + if (pval) + { + if (pval[0] == 'f' && pval[1] == '\0') + { + ((char *) value)[act_tuple] = false; + break; + } + else if (pval[0] == 't' && pval[1] == '\0') + { + ((char *) value)[act_tuple] = true; + break; + } + } + + register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.", + (pval ? pval : "NULL"), + lineno); + status = false; + break; + + case ECPGt_char: + case ECPGt_unsigned_char: + { + if (varcharsize == 0) + { + /* char* */ + strncpy(((char **) value)[act_tuple], pval, strlen(pval)); + (((char **) value)[act_tuple])[strlen(pval)] = '\0'; + } + else + { + strncpy((char *) (value + offset * act_tuple), pval, varcharsize); + if (varcharsize < strlen(pval)) + { + /* truncation */ + switch (ind_type) + { + case ECPGt_short: + case ECPGt_unsigned_short: + ((short *) ind_value)[act_tuple] = varcharsize; + break; + case ECPGt_int: + case ECPGt_unsigned_int: + ((int *) ind_value)[act_tuple] = varcharsize; + break; + case ECPGt_long: + case ECPGt_unsigned_long: + ((long *) ind_value)[act_tuple] = varcharsize; + break; + default: + break; + } + } + } + } + break; + + case ECPGt_varchar: + { + struct ECPGgeneric_varchar *var = + (struct ECPGgeneric_varchar *) (value + offset * act_tuple); + + if (varcharsize == 0) + strncpy(var->arr, pval, strlen(pval)); + else + strncpy(var->arr, pval, varcharsize); + + var->len = strlen(pval); + if (varcharsize > 0 && var->len > varcharsize) + { + /* truncation */ + switch (ind_type) + { + case ECPGt_short: + case ECPGt_unsigned_short: + ((short *) ind_value)[act_tuple] = varcharsize; + break; + case ECPGt_int: + case ECPGt_unsigned_int: + ((int *) ind_value)[act_tuple] = varcharsize; + break; + case ECPGt_long: + case ECPGt_unsigned_long: + ((long *) ind_value)[act_tuple] = varcharsize; + break; + default: + break; + } + + var->len = varcharsize; + } + } + break; + + case ECPGt_EORT: + ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno); + register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno); + status = false; + break; + + default: + register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.", + ECPGtype_name(type), lineno); + status = false; + break; + } + } } type = va_arg(ap, enum ECPGttype); if (status && type != ECPGt_EORT) { - register_error(-1, "Too many arguments line %d.", lineno); - return false; + register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno); + status = false; } PQclear(results); break; case PGRES_EMPTY_QUERY: /* do nothing */ - register_error(-1, "Empty query line %d.", lineno); + register_error(ECPG_EMPTY, "Empty query line %d.", lineno); break; case PGRES_COMMAND_OK: status = true; + sqlca.sqlerrd[2] = atol(PQcmdTuples(results)); + ECPGlog("TEST: %s\n", PQcmdTuples(results)); ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results)); break; case PGRES_NONFATAL_ERROR: @@ -643,8 +645,9 @@ ECPGdo(int lineno, char *query,...) case PGRES_BAD_RESPONSE: ECPGlog("ECPGdo line %d: Error: %s", lineno, PQerrorMessage(simple_connection)); - register_error(-1, "Error: %s line %d.", + register_error(ECPG_PGSQL, "Error: %s line %d.", PQerrorMessage(simple_connection), lineno); + status = false; break; case PGRES_COPY_OUT: ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno); @@ -657,9 +660,11 @@ ECPGdo(int lineno, char *query,...) default: ECPGlog("ECPGdo line %d: Got something else, postgres error.\n", lineno); - register_error(-1, "Postgres error line %d.", lineno); + register_error(ECPG_PGSQL, "Postgres error line %d.", lineno); + status = false; break; } + } /* check for asynchronous returns */ notify = PQnotifies(simple_connection); @@ -683,11 +688,12 @@ ECPGtrans(int lineno, const char * transaction) ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction); if ((res = PQexec(simple_connection, transaction)) == NULL) { - register_error(-1, "Error in transaction processing line %d.", lineno); + register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno); return (FALSE); } PQclear(res); - committed = 1; + if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0) + committed = 1; return (TRUE); } @@ -716,21 +722,25 @@ ECPGconnect(const char *dbname) if (PQstatus(simple_connection) == CONNECTION_BAD) { ECPGfinish(); - ECPGlog("ECPGconnect: could not open database %s\n", dbname); - register_error(-1, "ECPGconnect: could not open database %s.", dbname); + ECPGlog("connect: could not open database %s\n", dbname); + register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname); return false; } return true; } - bool -ECPGstatus(void) +ECPGdisconnect(const char *dbname) { - return PQstatus(simple_connection) != CONNECTION_BAD; + if (strlen(dbname) > 0 && strcmp(PQdb(simple_connection), dbname) != 0) + { + ECPGlog("disconnect: not connected to database %s\n", dbname); + register_error(ECPG_DISCONNECT, "disconnect: not connected to database %s.", dbname); + return false; + } + return ECPGfinish(); } - bool ECPGfinish(void) { diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 4fcfd5b669f9c9bcda5089326543098a7718f2ea..5cb3861c22a5b3a58334fa82c0180327a2757fd9 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -2,7 +2,7 @@ SRCDIR= ../../.. include $(SRCDIR)/Makefile.global MAJOR_VERSION=2 -MINOR_VERSION=2 +MINOR_VERSION=3 PATCHLEVEL=0 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c index d50de7bd6e7d2c20ec9f5ded16c6985b48602a6e..cf93a241f921a9c59e2dd6b079ec902c8599f392 100644 --- a/src/interfaces/ecpg/preproc/c_keywords.c +++ b/src/interfaces/ecpg/preproc/c_keywords.c @@ -21,6 +21,7 @@ */ static ScanKeyword ScanKeywords[] = { /* name value */ + {"VARCHAR", S_VARCHAR}, {"auto", S_AUTO}, {"bool", S_BOOL}, {"char", S_CHAR}, diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 853088d4acf4dcaca8eddc638f93fa6be6139366..825b292a5436cfd8ebab1487a95c812490f56c1c 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -22,12 +22,13 @@ extern char *optarg; #include "extern.h" struct _include_path *include_paths; - +static int no_auto_trans = 0; + static void usage(char *progname) { fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); - fprintf(stderr, "Usage: %s: [-v] [-I include path] [ -o output file name] file1 [file2] ...\n", progname); + fprintf(stderr, "Usage: %s: [-v] [-t] [-I include path] [ -o output file name] file1 [file2] ...\n", progname); } static void @@ -51,7 +52,7 @@ main(int argc, char *const argv[]) add_include_path("/usr/local/include"); add_include_path("."); - while ((c = getopt(argc, argv, "vo:I:")) != EOF) + while ((c = getopt(argc, argv, "vo:I:t")) != EOF) { switch (c) { @@ -65,23 +66,26 @@ main(int argc, char *const argv[]) case 'I': add_include_path(optarg); break; + case 't': + no_auto_trans = 1; + break; case 'v': fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); fprintf(stderr, "exec sql include ... search starts here:\n"); for (ip = include_paths; ip != NULL; ip = ip->next) fprintf(stderr, " %s\n", ip->path); fprintf(stderr, "End of search list.\n"); - return (0); + return (OK); default: usage(argv[0]); - return (1); + return (ILLEGAL_OPTION); } } if (optind >= argc) /* no files specified */ { usage(argv[0]); - return(1); + return(ILLEGAL_OPTION); } else { @@ -151,8 +155,8 @@ main(int argc, char *const argv[]) cur = NULL; - /* we need two includes */ - fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/*These two include files are added by the preprocessor */\n#include <ecpgtype.h>\n#include <ecpglib.h>\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); + /* we need two includes and a constant */ + fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/*These two include files are added by the preprocessor */\n#include <ecpgtype.h>\n#include <ecpglib.h>\n\nconst int no_auto_trans = %d;\n\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL, no_auto_trans); /* and parse the source */ yyparse(); @@ -169,5 +173,5 @@ main(int argc, char *const argv[]) free(input_filename); } } - return (0); + return (OK); } diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c index 8047ddad8d8fc136daa152f096d724ad20479799..3badb9399741263e095c235905725b42225a8943 100644 --- a/src/interfaces/ecpg/preproc/ecpg_keywords.c +++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c @@ -21,15 +21,18 @@ */ static ScanKeyword ScanKeywords[] = { /* name value */ + {"break", SQL_BREAK}, {"call", SQL_CALL}, {"connect", SQL_CONNECT}, {"continue", SQL_CONTINUE}, + {"disconnect", SQL_DISCONNECT}, {"found", SQL_FOUND}, {"go", SQL_GO}, {"goto", SQL_GOTO}, {"immediate", SQL_IMMEDIATE}, {"indicator", SQL_INDICATOR}, {"open", SQL_OPEN}, + {"release", SQL_RELEASE}, {"section", SQL_SECTION}, {"sqlerror", SQL_SQLERROR}, {"sqlprint", SQL_SQLPRINT}, diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 7b59e14cd5cefe19dab425ee5c8ec4e154124dda..6faa36be883a988b3870d9d0d25a36ebc0ce7eeb 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -43,3 +43,11 @@ extern void *mm_alloc(size_t), *mm_realloc(void *, size_t); ScanKeyword * ScanECPGKeywordLookup(char *); ScanKeyword * ScanCKeywordLookup(char *); extern void yyerror(char *); + +/* return codes */ + +#define OK 0 +#define NO_INCLUDE_FILE 1 +#define PARSE_ERROR 2 +#define OUT_OF_MEMORY 3 +#define ILLEGAL_OPTION 4 diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index ed7b37478c3d4ab47b5a202c30a59fbcbe222305..146938bf7df963d74774426a8c92d7087ac895d1 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -39,6 +39,7 @@ int debugging = 0; extern YYSTYPE yylval; int llen; char literal[MAX_PARSE_BUFFER]; +int before_comment; struct _yy_buffer { YY_BUFFER_STATE buffer; long lineno; @@ -153,7 +154,7 @@ space [ \t\n\f] other . /* some stuff needed for ecpg */ -ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/ +ccomment "//".*\n exec [eE][xX][eE][cC] include [iI][nN][cC][lL][uU][dD][eE] sql [sS][qQ][lL] @@ -174,12 +175,18 @@ sql [sS][qQ][lL] %% <SQL>{comment} { /* ignore */ } -<SQL>{xcline} { /* ignore */ } +{xcline} { /* ignore */ } -<xc>{xcstar} | -<SQL>{xcstart} { BEGIN(xc); } +<xc>{xcstar} { /* ignore */ } +{xcstart} { + fprintf(stderr,"ys = %d %d\n", YYSTATE, before_comment); + before_comment = YYSTATE; + BEGIN(xc); + fprintf(stderr,"ys = %d %d\n", YYSTATE, +before_comment); + } -<xc>{xcstop} { BEGIN(SQL); } +<xc>{xcstop} { fprintf(stderr,"ys = %d %d\n", YYSTATE, before_comment);BEGIN(before_comment); } <xc>{xcinside} { /* ignore */ } @@ -306,7 +313,6 @@ sql [sS][qQ][lL] return (yytext[0]); } <SQL>{self} { return (yytext[0]); } -<SQL>"->" { return S_STRUCTPOINTER; } <SQL>{operator}/-[\.0-9] { yylval.str = strdup((char*)yytext); return (Op); @@ -402,7 +408,7 @@ sql [sS][qQ][lL] return (FCONST); } -<SQL>:{identifier} { +<SQL>:{identifier}(("->"|\.){identifier})* { yylval.str = strdup((char*)yytext+1); return(CVARIABLE); } @@ -436,6 +442,7 @@ sql [sS][qQ][lL] <SQL>{other} { return (yytext[0]); } <C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; } +<C>{ccomment} { /* ignore */ } <C>{identifier} { ScanKeyword *keyword; @@ -501,7 +508,7 @@ sql [sS][qQ][lL] if (!yyin) { fprintf(stderr, "Error: Cannot open include file %s in line %d\n", yytext, yylineno); - exit(1); + exit(NO_INCLUDE_FILE); } input_filename = strdup(inc_file); diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 021988cf52b4b852239c8b779c2dfbb229d98362..b4fa4f2e38c5d6f401db3c60521b406ffc7a2b46 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -8,17 +8,19 @@ #include "type.h" #include "extern.h" +#define STRUCT_DEPTH 128 + /* * Variables containing simple states. */ static int struct_level = 0; static char errortext[128]; static int QueryIsRule = 0; -static enum ECPGttype actual_type[128]; -static char *actual_storage[128]; +static enum ECPGttype actual_type[STRUCT_DEPTH]; +static char *actual_storage[STRUCT_DEPTH]; /* temporarily store struct members while creating the data structure */ -struct ECPGstruct_member *struct_member_list[128] = { NULL }; +struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL }; /* keep a list of cursors */ struct cursor *cur = NULL; @@ -56,22 +58,24 @@ print_action(struct when *w) break; case W_STOP: fprintf(yyout, "exit (1);"); break; + case W_BREAK: fprintf(yyout, "break;"); + break; default: fprintf(yyout, "{/* %d not implemented yet */}", w->code); break; } } static void -whenever_action() +whenever_action(int mode) { - if (when_nf.code != W_NOTHING) + if (mode == 1 && when_nf.code != W_NOTHING) { - fprintf(yyout, "\nif (SQLCODE > 0) "); + fprintf(yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) "); print_action(&when_nf); } if (when_error.code != W_NOTHING) { - fprintf(yyout, "\nif (SQLCODE < 0) "); + fprintf(yyout, "\nif (sqlca.sqlcode < 0) "); print_action(&when_error); } output_line_number(); @@ -127,8 +131,6 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members) { case ECPGt_struct: return(new_variable(name, ECPGmake_struct_type(members->typ->u.members))); - case ECPGt_varchar: - return(new_variable(name, ECPGmake_varchar_type(members->typ->typ, members->typ->size))); default: return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size))); } @@ -311,39 +313,55 @@ check_indicator(struct ECPGtype *var) } static char * -cat2_str(const char *str1, const char *str2) +make1_str(const char *str) +{ + char * res_str = (char *)mm_alloc(strlen(str) + 1); + + strcpy(res_str, str); + return (res_str); +} + +static char * +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); return(res_str); } static char * -make2_str(const char *str1, const char *str2) +cat2_str(char *str1, char *str2) { char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2); strcpy(res_str, str1); strcat(res_str, " "); strcat(res_str, str2); + free(str1); + free(str2); return(res_str); } static char * -cat3_str(const char *str1, const char *str2, const char * str3) +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); } static char * -make3_str(const char *str1, const char *str2, const char * str3) +cat3_str(char *str1, char *str2, char * str3) { char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 3); @@ -352,11 +370,14 @@ make3_str(const char *str1, const char *str2, const char * str3) strcat(res_str, str2); strcat(res_str, " "); strcat(res_str, str3); + free(str1); + free(str2); + free(str3); return(res_str); } static char * -cat4_str(const char *str1, const char *str2, const char *str3, const char *str4) +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); @@ -364,11 +385,15 @@ cat4_str(const char *str1, const char *str2, const char *str3, const char *str4) strcat(res_str, str2); strcat(res_str, str3); strcat(res_str, str4); + free(str1); + free(str2); + free(str3); + free(str4); return(res_str); } static char * -make4_str(const char *str1, const char *str2, const char *str3, const char *str4) +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); @@ -379,11 +404,15 @@ make4_str(const char *str1, const char *str2, const char *str3, const char *str4 strcat(res_str, str3); strcat(res_str, " "); strcat(res_str, str4); + free(str1); + free(str2); + free(str3); + free(str4); return(res_str); } static char * -cat5_str(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5) +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); @@ -392,11 +421,16 @@ cat5_str(const char *str1, const char *str2, const char *str3, const char *str4, strcat(res_str, str3); strcat(res_str, str4); strcat(res_str, str5); + free(str1); + free(str2); + free(str3); + free(str4); + free(str5); return(res_str); } static char * -make5_str(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5) +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); @@ -409,6 +443,11 @@ make5_str(const char *str1, const char *str2, const char *str3, const char *str4 strcat(res_str, str4); strcat(res_str, " "); strcat(res_str, str5); + free(str1); + free(str2); + free(str3); + free(str4); + free(str5); return(res_str); } @@ -423,7 +462,7 @@ make_name(void) } static void -output_statement(const char * stmt) +output_statement(char * stmt, int mode) { int i, j=strlen(stmt); @@ -440,7 +479,8 @@ output_statement(const char * stmt) fputs("ECPGt_EOIT, ", yyout); dump_variables(argsresult); fputs("ECPGt_EORT);", yyout); - whenever_action(); + whenever_action(mode); + free(stmt); } %} @@ -455,8 +495,8 @@ output_statement(const char * stmt) } /* special embedded SQL token */ -%token SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO -%token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN +%token SQL_BREAK SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_DISCONNECT SQL_FOUND SQL_GO SQL_GOTO +%token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN SQL_RELEASE %token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START %token SQL_STOP SQL_WHENEVER @@ -464,7 +504,7 @@ output_statement(const char * stmt) %token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN %token S_FLOAT S_INT %token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT -%token S_STRUCTPOINTER S_UNSIGNED S_VARCHAR +%token S_UNSIGNED S_VARCHAR /* I need this and don't know where it is defined inside the backend */ %token TYPECAST @@ -580,8 +620,8 @@ output_statement(const char * stmt) %type <str> sortby OptUseOp opt_inh_star relation_name_list name_list %type <str> group_clause groupby_list groupby having_clause from_clause %type <str> from_list from_val join_expr join_outer join_spec join_list -%type <str> join_using where_clause relation_expr opt_array_bounds -%type <str> nest_array_bounds opt_column_list insert_rest InsertStmt +%type <str> join_using where_clause relation_expr +%type <str> opt_column_list insert_rest InsertStmt %type <str> columnList DeleteStmt LockStmt UpdateStmt CursorStmt %type <str> NotifyStmt columnElem copy_dirn OptimizableStmt %type <str> copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary @@ -614,15 +654,14 @@ output_statement(const char * stmt) %type <str> indicator ECPGExecute c_expr variable_list dotext %type <str> storage_clause opt_initializer vartext c_anything blockstart %type <str> blockend variable_list variable var_anything sql_anything -%type <str> opt_pointer ecpg_ident cvariable identlist - -%type <str> stmt symbol +%type <str> opt_pointer ecpg_ident cvariable ECPGDisconnect dis_name +%type <str> stmt symbol opt_symbol ECPGRelease execstring %type <type_enum> simple_type type struct_type %type <action> action -%type <index> opt_index +%type <index> opt_array_bounds nest_array_bounds %% prog: statements; @@ -631,68 +670,77 @@ statements: /* empty */ statement: ecpgstart stmt SQL_SEMI | ECPGDeclaration - | c_anything { fputs($1, yyout); } - | blockstart { fputs($1, yyout); } - | blockend { fputs($1, yyout); } - -stmt: AddAttrStmt { output_statement($1); } - | AlterUserStmt { output_statement($1); } - | ClosePortalStmt { output_statement($1); } - | CopyStmt { output_statement($1); } - | CreateStmt { output_statement($1); } - | CreateAsStmt { output_statement($1); } - | CreateSeqStmt { output_statement($1); } - | CreatePLangStmt { output_statement($1); } - | CreateTrigStmt { output_statement($1); } - | CreateUserStmt { output_statement($1); } - | ClusterStmt { output_statement($1); } - | DefineStmt { output_statement($1); } - | DestroyStmt { output_statement($1); } - | DropPLangStmt { output_statement($1); } - | DropTrigStmt { output_statement($1); } - | DropUserStmt { output_statement($1); } - | ExtendStmt { output_statement($1); } - | ExplainStmt { output_statement($1); } - | FetchStmt { output_statement($1); } - | GrantStmt { output_statement($1); } - | IndexStmt { output_statement($1); } - | ListenStmt { output_statement($1); } - | LockStmt { output_statement($1); } - | ProcedureStmt { output_statement($1); } - | RecipeStmt { output_statement($1); } - | RemoveAggrStmt { output_statement($1); } - | RemoveOperStmt { output_statement($1); } - | RemoveFuncStmt { output_statement($1); } - | RemoveStmt { output_statement($1); } - | RenameStmt { output_statement($1); } - | RevokeStmt { output_statement($1); } - | OptimizableStmt { /* already written out */ } - | RuleStmt { output_statement($1); } + | c_anything { fputs($1, yyout); free($1); } + | blockstart { fputs($1, yyout); free($1); } + | blockend { fputs($1, yyout); free($1); } + +stmt: AddAttrStmt { output_statement($1, 0); } + | AlterUserStmt { output_statement($1, 0); } + | ClosePortalStmt { output_statement($1, 0); } + | CopyStmt { output_statement($1, 0); } + | CreateStmt { output_statement($1, 0); } + | CreateAsStmt { 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); } + | 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); } + | GrantStmt { output_statement($1, 0); } + | IndexStmt { output_statement($1, 0); } + | ListenStmt { 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); } + | RemoveStmt { output_statement($1, 0); } + | RenameStmt { output_statement($1, 0); } + | RevokeStmt { output_statement($1, 0); } + | OptimizableStmt { /* output already written */ } + | RuleStmt { output_statement($1, 0); } | TransactionStmt { fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1); - whenever_action(); + whenever_action(0); + free($1); } - | ViewStmt { output_statement($1); } - | LoadStmt { output_statement($1); } - | CreatedbStmt { output_statement($1); } - | DestroydbStmt { output_statement($1); } - | VacuumStmt { output_statement($1); } - | VariableSetStmt { output_statement($1); } - | VariableShowStmt { output_statement($1); } - | VariableResetStmt { output_statement($1); } + | ViewStmt { output_statement($1, 0); } + | LoadStmt { output_statement($1, 0); } + | CreatedbStmt { output_statement($1, 0); } + | DestroydbStmt { output_statement($1, 0); } + | VacuumStmt { output_statement($1, 0); } + | VariableSetStmt { output_statement($1, 0); } + | VariableShowStmt { output_statement($1, 0); } + | VariableResetStmt { output_statement($1, 0); } | ECPGConnect { fprintf(yyout, "ECPGconnect(\"%s\");", $1); - whenever_action(); + whenever_action(0); + free($1); + } + | ECPGDisconnect { + fprintf(yyout, "ECPGdisconnect(\"%s\");", $1); + whenever_action(0); + free($1); } -/* | ECPGDisconnect */ | ECPGExecute { fprintf(yyout, "ECPGdo(__LINE__, %s, ECPGt_EOIT, ECPGt_EORT);", $1); - whenever_action(); + whenever_action(0); + free($1); } - | ECPGOpen { output_statement($1); } + | ECPGOpen { output_statement($1, 0); } + | ECPGRelease { /* output already done */ } | ECPGWhenever { fputs($1, yyout); output_line_number(); + free($1); } /* @@ -709,7 +757,7 @@ stmt: AddAttrStmt { output_statement($1); } CreateUserStmt: CREATE USER UserId user_passwd_clause user_createdb_clause user_createuser_clause user_group_clause user_valid_clause { - $$ = make3_str(make5_str("create user", $3, $4, $5, $6), $7, $8); + $$ = cat3_str(cat5_str(make1_str("create user"), $3, $4, $5, $6), $7, $8); } ; @@ -723,7 +771,7 @@ CreateUserStmt: CREATE USER UserId user_passwd_clause user_createdb_clause AlterUserStmt: ALTER USER UserId user_passwd_clause user_createdb_clause user_createuser_clause user_group_clause user_valid_clause { - $$ = make3_str(make5_str("alter user", $3, $4, $5, $6), $7, $8); + $$ = cat3_str(cat5_str(make1_str("alter user"), $3, $4, $5, $6), $7, $8); } ; @@ -736,39 +784,39 @@ AlterUserStmt: ALTER USER UserId user_passwd_clause user_createdb_clause DropUserStmt: DROP USER UserId { - $$ = make2_str("drop user", $3); + $$ = cat2_str(make1_str("drop user"), $3); } ; -user_passwd_clause: WITH PASSWORD UserId { $$ = make2_str("with password", $3); } - | /*EMPTY*/ { $$ = ""; } +user_passwd_clause: WITH PASSWORD UserId { $$ = cat2_str(make1_str("with password") , $3); } + | /*EMPTY*/ { $$ = make1_str(""); } ; user_createdb_clause: CREATEDB { - $$ = "createdb"; + $$ = make1_str("createdb"); } | NOCREATEDB { - $$ = "nocreatedb"; + $$ = make1_str("nocreatedb"); } - | /*EMPTY*/ { $$ = ""; } + | /*EMPTY*/ { $$ = make1_str(""); } ; user_createuser_clause: CREATEUSER { - $$ = "createuser"; + $$ = make1_str("createuser"); } | NOCREATEUSER { - $$ = "nocreateuser"; + $$ = make1_str("nocreateuser"); } | /*EMPTY*/ { $$ = NULL; } ; user_group_list: user_group_list ',' UserId { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } | UserId { @@ -776,12 +824,12 @@ user_group_list: user_group_list ',' UserId } ; -user_group_clause: IN GROUP user_group_list { $$ = make2_str("in group", $3); } - | /*EMPTY*/ { $$ = ""; } +user_group_clause: IN GROUP user_group_list { $$ = cat2_str(make1_str("in group"), $3); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -user_valid_clause: VALID UNTIL SCONST { $$ = make2_str("valid until", $3);; } - | /*EMPTY*/ { $$ = ""; } +user_valid_clause: VALID UNTIL SCONST { $$ = cat2_str(make1_str("valid until"), $3);; } + | /*EMPTY*/ { $$ = make1_str(""); } ; /***************************************************************************** @@ -795,44 +843,44 @@ user_valid_clause: VALID UNTIL SCONST { $$ = make2_str("valid until", $3);; } VariableSetStmt: SET ColId TO var_value { - $$ = make4_str("set", $2, "to", $4); + $$ = cat4_str(make1_str("set"), $2, make1_str("to"), $4); } | SET ColId '=' var_value { - $$ = make4_str("set", $2, "=", $4); + $$ = cat4_str(make1_str("set"), $2, make1_str("="), $4); } | SET TIME ZONE zone_value { - $$ = make2_str("set time zone", $4); + $$ = cat2_str(make1_str("set time zone"), $4); } ; var_value: Sconst { $$ = $1; } - | DEFAULT { $$ = "default"; } + | DEFAULT { $$ = make1_str("default"); } ; zone_value: Sconst { $$ = $1; } - | DEFAULT { $$ = "default"; } - | LOCAL { $$ = "local"; } + | DEFAULT { $$ = make1_str("default"); } + | LOCAL { $$ = make1_str("local"); } ; VariableShowStmt: SHOW ColId { - $$ = make2_str("show", $2); + $$ = cat2_str(make1_str("show"), $2); } | SHOW TIME ZONE { - $$ = "show time zone"; + $$ = make1_str("show time zone"); } ; VariableResetStmt: RESET ColId { - $$ = make2_str("reset", $2); + $$ = cat2_str(make1_str("reset"), $2); } | RESET TIME ZONE { - $$ = "reset time zone"; + $$ = make1_str("reset time zone"); } ; @@ -846,17 +894,17 @@ VariableResetStmt: RESET ColId AddAttrStmt: ALTER TABLE relation_name opt_inh_star alter_clause { - $$ = make4_str("alter table", $3, $4, $5); + $$ = cat4_str(make1_str("alter table"), $3, $4, $5); } ; alter_clause: ADD opt_column columnDef { - $$ = make3_str("add", $2, $3); + $$ = cat3_str(make1_str("add"), $2, $3); } | ADD '(' OptTableElementList ')' { - $$ = cat3_str("add(", $3, ")"); + $$ = make3_str(make1_str("add("), $3, make1_str(")")); } | DROP opt_column ColId { yyerror("ALTER TABLE/DROP COLUMN not yet implemented"); } @@ -877,7 +925,7 @@ alter_clause: ADD opt_column columnDef ClosePortalStmt: CLOSE opt_id { - $$ = make2_str("close", $2); + $$ = cat2_str(make1_str("close"), $2); } ; @@ -892,14 +940,14 @@ ClosePortalStmt: CLOSE opt_id CopyStmt: COPY opt_binary relation_name opt_with_copy copy_dirn copy_file_name copy_delimiter { - $$ = make3_str(make5_str("copy", $2, $3, $4, $5), $6, $7); + $$ = cat3_str(cat5_str(make1_str("copy"), $2, $3, $4, $5), $6, $7); } ; copy_dirn: TO - { $$ = "to"; } + { $$ = make1_str("to"); } | FROM - { $$ = "from"; } + { $$ = make1_str("from"); } ; /* @@ -908,23 +956,23 @@ copy_dirn: TO * stdout. We silently correct the "typo". - AY 9/94 */ copy_file_name: Sconst { $$ = $1; } - | STDIN { $$ = "stdin"; } - | STDOUT { $$ = "stdout"; } + | STDIN { $$ = make1_str("stdin"); } + | STDOUT { $$ = make1_str("stdout"); } ; -opt_binary: BINARY { $$ = "binary"; } - | /*EMPTY*/ { $$ = ""; } +opt_binary: BINARY { $$ = make1_str("binary"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_with_copy: WITH OIDS { $$ = "with oids"; } - | /*EMPTY*/ { $$ = ""; } +opt_with_copy: WITH OIDS { $$ = make1_str("with oids"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; /* * the default copy delimiter is tab but the user can configure it */ -copy_delimiter: USING DELIMITERS Sconst { $$ = make2_str("using delimiters", $3); } - | /*EMPTY*/ { $$ = ""; } +copy_delimiter: USING DELIMITERS Sconst { $$ = cat2_str(make1_str("using delimiters"), $3); } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -939,19 +987,19 @@ copy_delimiter: USING DELIMITERS Sconst { $$ = make2_str("using delimiters", $ CreateStmt: CREATE TABLE relation_name '(' OptTableElementList ')' OptInherit OptArchiveType { - $$ = make5_str("create table", $3, cat3_str("(", $5, ")"), $7, $8); + $$ = cat5_str(make1_str("create table"), $3, make3_str(make1_str("("), $5, make1_str(")")), $7, $8); } ; OptTableElementList: OptTableElementList ',' OptTableElement { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } | OptTableElement { $$ = $1; } - | /*EMPTY*/ { $$ = ""; } + | /*EMPTY*/ { $$ = make1_str(""); } ; OptTableElement: columnDef { $$ = $1; } @@ -960,22 +1008,22 @@ OptTableElement: columnDef { $$ = $1; } columnDef: ColId Typename ColQualifier { - $$ = make3_str($1, $2, $3); + $$ = cat3_str($1, $2, $3); } ; ColQualifier: ColQualList { $$ = $1; } - | /*EMPTY*/ { $$ = ""; } + | /*EMPTY*/ { $$ = make1_str(""); } ; -ColQualList: ColQualList ColConstraint { $$ = make2_str($1,$2); } +ColQualList: ColQualList ColConstraint { $$ = cat2_str($1,$2); } | ColConstraint { $$ = $1; } ; ColConstraint: CONSTRAINT name ColConstraintElem { - $$ = make3_str("constraint", $2, $3); + $$ = cat3_str(make1_str("constraint"), $2, $3); } | ColConstraintElem { $$ = $1; } @@ -983,34 +1031,34 @@ ColConstraint: ColConstraintElem: CHECK '(' constraint_expr ')' { - $$ = cat3_str("check(", $3, ")"); + $$ = make3_str(make1_str("check("), $3, make1_str(")")); } | DEFAULT default_expr { - $$ = make2_str("default", $2); + $$ = cat2_str(make1_str("default"), $2); } | NOT NULL_P { - $$ = "not null"; + $$ = make1_str("not null"); } | UNIQUE { - $$ = "unique"; + $$ = make1_str("unique"); } | PRIMARY KEY { - $$ = "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(""); } ; default_list: default_list ',' default_expr { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } | default_expr { @@ -1021,17 +1069,17 @@ default_list: default_list ',' default_expr default_expr: AexprConst { $$ = $1; } | NULL_P - { $$ = "null"; } + { $$ = make1_str("null"); } | '-' default_expr %prec UMINUS - { $$ = make2_str("-", $2); } + { $$ = cat2_str(make1_str("-"), $2); } | default_expr '+' default_expr - { $$ = make3_str($1, "+", $3); } + { $$ = cat3_str($1, make1_str("+"), $3); } | default_expr '-' default_expr - { $$ = make3_str($1, "-", $3); } + { $$ = cat3_str($1, make1_str("-"), $3); } | default_expr '/' default_expr - { $$ = make3_str($1, "/", $3); } + { $$ = cat3_str($1, make1_str("/"), $3); } | default_expr '*' default_expr - { $$ = make3_str($1, "*", $3); } + { $$ = cat3_str($1, make1_str("*"), $3); } | default_expr '=' default_expr { yyerror("boolean expressions not supported in DEFAULT"); } | default_expr '<' default_expr @@ -1040,39 +1088,39 @@ default_expr: AexprConst { yyerror("boolean expressions not supported in DEFAULT"); } /* not possible in embedded sql | ':' default_expr - { $$ = make2_str(":", $2); } + { $$ = cat2_str(make1_str(":"), $2); } */ | ';' default_expr - { $$ = make2_str(";", $2); } + { $$ = cat2_str(make1_str(";"), $2); } | '|' default_expr - { $$ = make2_str("|", $2); } + { $$ = cat2_str(make1_str("|"), $2); } | default_expr TYPECAST Typename - { $$ = make3_str($1, "::", $3); } + { $$ = cat3_str($1, make1_str("::"), $3); } | CAST '(' default_expr AS Typename ')' { - $$ = make3_str(cat2_str("cast(", $3) , "as", cat2_str($5, ")")); + $$ = cat3_str(make2_str(make1_str("cast("), $3) , make1_str("as"), make2_str($5, make1_str(")"))); } | '(' default_expr ')' - { $$ = cat3_str("(", $2, ")"); } + { $$ = make3_str(make1_str("("), $2, make1_str(")")); } | func_name '(' ')' - { $$ = make2_str($1, "()"); } + { $$ = cat2_str($1, make1_str("()")); } | func_name '(' default_list ')' - { $$ = make2_str($1, cat3_str("(", $3, ")")); } + { $$ = 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"); - $$ = make3_str($1, $2, $3); + $$ = cat3_str($1, $2, $3); } | Op default_expr - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | default_expr Op - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } /* XXX - thomas 1997-10-07 v6.2 function-specific code to be changed */ | CURRENT_DATE - { $$ = "current_date"; } + { $$ = make1_str("current_date"); } | CURRENT_TIME - { $$ = "current_time"; } + { $$ = make1_str("current_time"); } | CURRENT_TIME '(' Iconst ')' { if ($3 != 0) @@ -1080,7 +1128,7 @@ default_expr: AexprConst $$ = "current_time"; } | CURRENT_TIMESTAMP - { $$ = "current_timestamp"; } + { $$ = make1_str("current_timestamp"); } | CURRENT_TIMESTAMP '(' Iconst ')' { if ($3 != 0) @@ -1088,7 +1136,7 @@ default_expr: AexprConst $$ = "current_timestamp"; } | CURRENT_USER - { $$ = "current user"; } + { $$ = make1_str("current user"); } ; /* ConstraintElem specifies constraint syntax which is not embedded into @@ -1097,7 +1145,7 @@ default_expr: AexprConst */ TableConstraint: CONSTRAINT name ConstraintElem { - $$ = make3_str("constraint", $2, $3); + $$ = cat3_str(make1_str("constraint"), $2, $3); } | ConstraintElem { $$ = $1; } @@ -1105,15 +1153,15 @@ TableConstraint: CONSTRAINT name ConstraintElem ConstraintElem: CHECK '(' constraint_expr ')' { - $$ = cat3_str("check(", $3, ")"); + $$ = make3_str(make1_str("check("), $3, make1_str(")")); } | UNIQUE '(' columnList ')' { - $$ = cat3_str("unique(", $3, ")"); + $$ = make3_str(make1_str("unique("), $3, make1_str(")")); } | PRIMARY KEY '(' columnList ')' { - $$ = cat3_str("primary key(", $4, ")"); + $$ = make3_str(make1_str("primary key("), $4, make1_str(")")); } | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions { @@ -1124,7 +1172,7 @@ ConstraintElem: CHECK '(' constraint_expr ')' constraint_list: constraint_list ',' constraint_expr { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } | constraint_expr { @@ -1135,129 +1183,128 @@ constraint_list: constraint_list ',' constraint_expr constraint_expr: AexprConst { $$ = $1; } | NULL_P - { $$ = "null"; } + { $$ = make1_str("null"); } | ColId { $$ = $1; } | '-' constraint_expr %prec UMINUS - { $$ = make2_str("-", $2); } + { $$ = cat2_str(make1_str("-"), $2); } | constraint_expr '+' constraint_expr - { $$ = make3_str($1, "+", $3); } + { $$ = cat3_str($1, make1_str("+"), $3); } | constraint_expr '-' constraint_expr - { $$ = make3_str($1, "-", $3); } + { $$ = cat3_str($1, make1_str("-"), $3); } | constraint_expr '/' constraint_expr - { $$ = make3_str($1, "/", $3); } + { $$ = cat3_str($1, make1_str("/"), $3); } | constraint_expr '*' constraint_expr - { $$ = make3_str($1, "*", $3); } + { $$ = cat3_str($1, make1_str("*"), $3); } | constraint_expr '=' constraint_expr - { $$ = make3_str($1, "=", $3); } + { $$ = cat3_str($1, make1_str("="), $3); } | constraint_expr '<' constraint_expr - { $$ = make3_str($1, "<", $3); } + { $$ = cat3_str($1, make1_str("<"), $3); } | constraint_expr '>' constraint_expr - { $$ = make3_str($1, ">", $3); } + { $$ = cat3_str($1, make1_str(">"), $3); } /* this one doesn't work with embedded sql anyway | ':' constraint_expr - { $$ = make2_str(":", $2); } + { $$ = cat2_str(make1_str(":"), $2); } */ | ';' constraint_expr - { $$ = make2_str(";", $2); } + { $$ = cat2_str(make1_str(";"), $2); } | '|' constraint_expr - { $$ = make2_str("|", $2); } + { $$ = cat2_str(make1_str("|"), $2); } | constraint_expr TYPECAST Typename { - $$ = make3_str($1, "::", $3); + $$ = cat3_str($1, make1_str("::"), $3); } | CAST '(' constraint_expr AS Typename ')' { - $$ = make3_str(cat2_str("cast(", $3), "as", cat2_str($5, ")")); + $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")"))); } | '(' constraint_expr ')' - { $$ = cat3_str("(", $2, ")"); } + { $$ = make3_str(make1_str("("), $2, make1_str(")")); } | func_name '(' ')' { - { $$ = make2_str($1, "()"); } + { $$ = cat2_str($1, make1_str("()")); } } | func_name '(' constraint_list ')' { - $$ = make2_str($1, cat3_str("(", $3, -")")); + $$ = cat2_str($1, make3_str(make1_str("("), $3, make1_str(")"))); } | constraint_expr Op constraint_expr - { $$ = make3_str($1, $2, $3); } + { $$ = cat3_str($1, $2, $3); } | constraint_expr LIKE constraint_expr - { $$ = make3_str($1, "like", $3); } + { $$ = cat3_str($1, make1_str("like"), $3); } | constraint_expr AND constraint_expr - { $$ = make3_str($1, "and", $3); } + { $$ = cat3_str($1, make1_str("and"), $3); } | constraint_expr OR constraint_expr - { $$ = make3_str($1, "or", $3); } + { $$ = cat3_str($1, make1_str("or"), $3); } | NOT constraint_expr - { $$ = make2_str("not", $2); } + { $$ = cat2_str(make1_str("not"), $2); } | Op constraint_expr - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | constraint_expr Op - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | constraint_expr ISNULL - { $$ = make2_str($1, "isnull"); } + { $$ = cat2_str($1, make1_str("isnull")); } | constraint_expr IS NULL_P - { $$ = make2_str($1, "is null"); } + { $$ = cat2_str($1, make1_str("is null")); } | constraint_expr NOTNULL - { $$ = make2_str($1, "notnull"); } + { $$ = cat2_str($1, make1_str("notnull")); } | constraint_expr IS NOT NULL_P - { $$ = make2_str($1, "is not null"); } + { $$ = cat2_str($1, make1_str("is not null")); } | constraint_expr IS TRUE_P - { $$ = make2_str($1, "is true"); } + { $$ = cat2_str($1, make1_str("is true")); } | constraint_expr IS FALSE_P - { $$ = make2_str($1, "is false"); } + { $$ = cat2_str($1, make1_str("is false")); } | constraint_expr IS NOT TRUE_P - { $$ = make2_str($1, "is not true"); } + { $$ = cat2_str($1, make1_str("is not true")); } | constraint_expr IS NOT FALSE_P - { $$ = make2_str($1, "is not false"); } + { $$ = cat2_str($1, make1_str("is not false")); } ; -key_match: MATCH FULL { $$ = "match full"; } - | MATCH PARTIAL { $$ = "match partial"; } - | /*EMPTY*/ { $$ = ""; } +key_match: MATCH FULL { $$ = make1_str("match full"); } + | MATCH PARTIAL { $$ = make1_str("match partial"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -key_actions: key_action key_action { $$ = make2_str($1, $2); } +key_actions: key_action key_action { $$ = cat2_str($1, $2); } | key_action { $$ = $1; } - | /*EMPTY*/ { $$ = ""; } + | /*EMPTY*/ { $$ = make1_str(""); } ; -key_action: ON DELETE key_reference { $$ = make2_str("on delete", $3); } - | ON UPDATE key_reference { $$ = make2_str("on update", $3); } +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_reference: NO ACTION { $$ = "no action"; } - | CASCADE { $$ = "cascade"; } - | SET DEFAULT { $$ = "set default"; } - | SET NULL_P { $$ = "set null"; } +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"); } ; -OptInherit: INHERITS '(' relation_name_list ')' { $$ = cat3_str("inherits (", $3, ")"); } - | /*EMPTY*/ { $$ = ""; } +OptInherit: INHERITS '(' relation_name_list ')' { $$ = make3_str(make1_str("inherits ("), $3, make1_str(")")); } + | /*EMPTY*/ { $$ = make1_str(""); } ; /* * "ARCHIVE" keyword was removed in 6.3, but we keep it for now * so people can upgrade with old pg_dump scripts. - momjian 1997-11-20(?) */ -OptArchiveType: ARCHIVE '=' NONE { $$ = "archive = none"; } - | /*EMPTY*/ { $$ = ""; } +OptArchiveType: ARCHIVE '=' NONE { $$ = make1_str("archive = none"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; CreateAsStmt: CREATE TABLE relation_name OptCreateAs AS SubSelect { - $$ = make5_str("create table", $3, $4, "as", $6); + $$ = cat5_str(make1_str("create table"), $3, $4, make1_str("as"), $6); } ; -OptCreateAs: '(' CreateAsList ')' { $$ = cat3_str("(", $2, ")"); } - | /*EMPTY*/ { $$ = ""; } +OptCreateAs: '(' CreateAsList ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -CreateAsList: CreateAsList ',' CreateAsElement { $$ = make3_str($1, ",", $3); } +CreateAsList: CreateAsList ',' CreateAsElement { $$ = cat3_str($1, make1_str(","), $3); } | CreateAsElement { $$ = $1; } ; @@ -1273,38 +1320,38 @@ CreateAsElement: ColId { $$ = $1; } CreateSeqStmt: CREATE SEQUENCE relation_name OptSeqList { - $$ = make3_str("create sequence", $3, $4); + $$ = cat3_str(make1_str("create sequence"), $3, $4); } ; OptSeqList: OptSeqList OptSeqElem - { $$ = make2_str($1, $2); } - | { $$ = ""; } + { $$ = cat2_str($1, $2); } + | { $$ = make1_str(""); } ; OptSeqElem: CACHE IntegerOnly { - $$ = make2_str("cache", $2); + $$ = cat2_str(make1_str("cache"), $2); } | CYCLE { - $$ = "cycle"; + $$ = make1_str("cycle"); } | INCREMENT IntegerOnly { - $$ = make2_str("increment", $2); + $$ = cat2_str(make1_str("increment"), $2); } | MAXVALUE IntegerOnly { - $$ = make2_str("maxvalue", $2); + $$ = cat2_str(make1_str("maxvalue"), $2); } | MINVALUE IntegerOnly { - $$ = make2_str("minvalue", $2); + $$ = cat2_str(make1_str("minvalue"), $2); } | START IntegerOnly { - $$ = make2_str("start", $2); + $$ = cat2_str(make1_str("start"), $2); } ; @@ -1314,7 +1361,7 @@ IntegerOnly: Iconst } | '-' Iconst { - $$ = make2_str("-", $2); + $$ = cat2_str(make1_str("-"), $2); } ; @@ -1329,16 +1376,16 @@ IntegerOnly: Iconst CreatePLangStmt: CREATE PLangTrusted PROCEDURAL LANGUAGE Sconst HANDLER def_name LANCOMPILER Sconst { - $$ = make4_str(make5_str("create", $2, "precedural language", $5, "handler"), $7, "langcompiler", $9); + $$ = cat4_str(cat5_str(make1_str("create"), $2, make1_str("precedural language"), $5, make1_str("handler")), $7, make1_str("langcompiler"), $9); } ; -PLangTrusted: TRUSTED { $$ = "trusted"; } - | { $$ = ""; } +PLangTrusted: TRUSTED { $$ = make1_str("trusted"); } + | { $$ = make1_str(""); } DropPLangStmt: DROP PROCEDURAL LANGUAGE Sconst { - $$ = make2_str("drop procedural language", $4); + $$ = cat2_str(make1_str("drop procedural language"), $4); } ; @@ -1354,12 +1401,12 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON relation_name TriggerForSpec EXECUTE PROCEDURE name '(' TriggerFuncArgs ')' { - $$ = make2_str(make5_str(make5_str("create trigger", $3, $4, $5, "on"), $7, $8, "execute procedure", $11), cat3_str("(", $13, ")")); + $$ = 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(")"))); } ; -TriggerActionTime: BEFORE { $$ = "before"; } - | AFTER { $$ = "after"; } +TriggerActionTime: BEFORE { $$ = make1_str("before"); } + | AFTER { $$ = make1_str("after"); } ; TriggerEvents: TriggerOneEvent @@ -1368,39 +1415,39 @@ TriggerEvents: TriggerOneEvent } | TriggerOneEvent OR TriggerOneEvent { - $$ = make3_str($1, "or", $3); + $$ = cat3_str($1, make1_str("or"), $3); } | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent { - $$ = make5_str($1, "or", $3, "or", $5); + $$ = cat5_str($1, make1_str("or"), $3, make1_str("or"), $5); } ; -TriggerOneEvent: INSERT { $$ = "insert"; } - | DELETE { $$ = "delete"; } - | UPDATE { $$ = "update"; } +TriggerOneEvent: INSERT { $$ = make1_str("insert"); } + | DELETE { $$ = make1_str("delete"); } + | UPDATE { $$ = make1_str("update"); } ; TriggerForSpec: FOR TriggerForOpt TriggerForType { - $$ = make3_str("for", $2, $3); + $$ = cat3_str(make1_str("for"), $2, $3); } ; -TriggerForOpt: EACH { $$ = "each"; } - | /*EMPTY*/ { $$ = ""; } +TriggerForOpt: EACH { $$ = make1_str("each"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -TriggerForType: ROW { $$ = "row"; } - | STATEMENT { $$ = "statement"; } +TriggerForType: ROW { $$ = make1_str("row"); } + | STATEMENT { $$ = make1_str("statement"); } ; TriggerFuncArgs: TriggerFuncArg { $$ = $1 } | TriggerFuncArgs ',' TriggerFuncArg - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } | /*EMPTY*/ - { $$ = ""; } + { $$ = make1_str(""); } ; TriggerFuncArg: Iconst @@ -1417,7 +1464,7 @@ TriggerFuncArg: Iconst DropTrigStmt: DROP TRIGGER name ON relation_name { - $$ = make4_str("drop trigger", $3, "on", $5); + $$ = cat4_str(make1_str("drop trigger"), $3, make1_str("on"), $5); } ; @@ -1430,37 +1477,37 @@ DropTrigStmt: DROP TRIGGER name ON relation_name DefineStmt: CREATE def_type def_rest { - $$ = make3_str("create", $2, $3); + $$ = cat3_str(make1_str("create"), $2, $3); } ; def_rest: def_name definition { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } ; -def_type: OPERATOR { $$ = "operator"; } - | TYPE_P { $$ = "type"; } - | AGGREGATE { $$ = "aggregate"; } +def_type: OPERATOR { $$ = make1_str("operator"); } + | TYPE_P { $$ = make1_str("type"); } + | AGGREGATE { $$ = make1_str("aggregate"); } ; -def_name: PROCEDURE { $$ = "procedure"; } - | JOIN { $$ = "join"; } +def_name: PROCEDURE { $$ = make1_str("procedure"); } + | JOIN { $$ = make1_str("join"); } | ColId { $$ = $1; } | MathOp { $$ = $1; } | Op { $$ = $1; } ; -definition: '(' def_list ')' { $$ = cat3_str("(", $2, ")"); } +definition: '(' def_list ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); } ; def_list: def_elem { $$ = $1; } - | def_list ',' def_elem { $$ = make3_str($1, ",", $3); } + | def_list ',' def_elem { $$ = cat3_str($1, make1_str(","), $3); } ; def_elem: def_name '=' def_arg { - $$ = make3_str($1, "=", $3); + $$ = cat3_str($1, make1_str("="), $3); } | def_name { @@ -1468,7 +1515,7 @@ def_elem: def_name '=' def_arg { } | DEFAULT '=' def_arg { - $$ = make2_str("default =", $3); + $$ = cat2_str(make1_str("default ="), $3); } ; @@ -1478,7 +1525,7 @@ def_arg: ColId { $$ = $1; } | Sconst { $$ = $1; } | SETOF ColId { - $$ = make2_str("setof", $2); + $$ = cat2_str(make1_str("setof"), $2); } ; @@ -1491,11 +1538,11 @@ def_arg: ColId { $$ = $1; } DestroyStmt: DROP TABLE relation_name_list { - $$ = make2_str("drop table", $3); + $$ = cat2_str(make1_str("drop table"), $3); } | DROP SEQUENCE relation_name_list { - $$ = make2_str("drop sequence", $3); + $$ = cat2_str(make1_str("drop sequence"), $3); } ; @@ -1510,29 +1557,29 @@ DestroyStmt: DROP TABLE relation_name_list FetchStmt: FETCH opt_direction fetch_how_many opt_portal_name INTO into_list { - $$ = make4_str("fetch", $2, $3, $4); + $$ = cat4_str(make1_str("fetch"), $2, $3, $4); } | MOVE opt_direction fetch_how_many opt_portal_name { - $$ = make4_str("fetch", $2, $3, $4); + $$ = cat4_str(make1_str("fetch"), $2, $3, $4); } ; -opt_direction: FORWARD { $$ = "forward"; } - | BACKWARD { $$ = "backward"; } - | /*EMPTY*/ { $$ = ""; /* default */ } +opt_direction: FORWARD { $$ = make1_str("forward"); } + | BACKWARD { $$ = make1_str("backward"); } + | /*EMPTY*/ { $$ = make1_str(""); /* default */ } ; fetch_how_many: Iconst { $$ = $1; if (atol($1) <= 0) yyerror("Please specify nonnegative count for fetch"); } - | ALL { $$ = "all"; } - | /*EMPTY*/ { $$ = ""; /*default*/ } + | ALL { $$ = make1_str("all"); } + | /*EMPTY*/ { $$ = make1_str(""); /*default*/ } ; -opt_portal_name: IN name { $$ = make2_str("in", $2); } - | name { $$ = make2_str("in", $1); } - | /*EMPTY*/ { $$ = ""; } +opt_portal_name: IN name { $$ = cat2_str(make1_str("in"), $2); } + | name { $$ = cat2_str(make1_str("in"), $1); } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -1545,17 +1592,17 @@ opt_portal_name: IN name { $$ = make2_str("in", $2); } GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant { - $$ = make2_str(make5_str("grant", $2, "on", $4, "to"), $6); + $$ = cat2_str(cat5_str(make1_str("grant"), $2, make1_str("on"), $4, make1_str("to")), $6); } ; privileges: ALL PRIVILEGES { - $$ = "all privileges"; + $$ = make1_str("all privileges"); } | ALL { - $$ = "all"; + $$ = make1_str("all"); } | operation_commalist { @@ -1569,39 +1616,39 @@ operation_commalist: operation } | operation_commalist ',' operation { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } ; operation: SELECT { - $$ = "select"; + $$ = make1_str("select"); } | INSERT { - $$ = "insert"; + $$ = make1_str("insert"); } | UPDATE { - $$ = "update"; + $$ = make1_str("update"); } | DELETE { - $$ = "delete"; + $$ = make1_str("delete"); } | RULE { - $$ = "rule"; + $$ = make1_str("rule"); } ; grantee: PUBLIC { - $$ = "public"; + $$ = make1_str("public"); } | GROUP ColId { - $$ = make2_str("group", $2); + $$ = cat2_str(make1_str("group"), $2); } | ColId { @@ -1626,7 +1673,7 @@ opt_with_grant: WITH GRANT OPTION RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee { - $$ = make2_str(make5_str("revoke", $2, "on", $4, "from"), $6); + $$ = cat2_str(cat5_str(make1_str("revoke"), $2, make1_str("on"), $4, make1_str("from")), $6); } ; @@ -1647,41 +1694,41 @@ IndexStmt: CREATE index_opt_unique INDEX index_name ON relation_name { /* should check that access_method is valid, etc ... but doesn't */ - $$ = make5_str(make5_str("create", $2, "index", $4, "on"), $6, $7, cat3_str("(", $9, ")"), $11); + $$ = 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); } ; -index_opt_unique: UNIQUE { $$ = "unique"; } - | /*EMPTY*/ { $$ = ""; } +index_opt_unique: UNIQUE { $$ = make1_str("unique"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -access_method_clause: USING access_method { $$ = make2_str("using", $2); } - | /*EMPTY*/ { $$ = ""; } +access_method_clause: USING access_method { $$ = cat2_str(make1_str("using"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); } ; index_params: index_list { $$ = $1; } | func_index { $$ = $1; } ; -index_list: index_list ',' index_elem { $$ = make3_str($1, ",", $3); } +index_list: index_list ',' index_elem { $$ = cat3_str($1, make1_str(","), $3); } | index_elem { $$ = $1; } ; func_index: func_name '(' name_list ')' opt_type opt_class { - $$ = make4_str($1, cat3_str("(", $3, ")"), $5, $6); + $$ = cat4_str($1, make3_str(make1_str("("), $3, ")"), $5, $6); } ; index_elem: attr_name opt_type opt_class { - $$ = make3_str($1, $3, $3); + $$ = cat3_str($1, $2, $3); } ; -opt_type: ':' Typename { $$ = make2_str(":", $2); } - | FOR Typename { $$ = make2_str("for", $2); } - | /*EMPTY*/ { $$ = ""; } +opt_type: ':' Typename { $$ = cat2_str(make1_str(":"), $2); } + | FOR Typename { $$ = cat2_str(make1_str("for"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); } ; /* opt_class "WITH class" conflicts with preceeding opt_type @@ -1691,8 +1738,8 @@ opt_type: ':' Typename { $$ = make2_str(":", $2); } * | WITH class { $$ = $2; } */ opt_class: class { $$ = $1; } - | USING class { $$ = make2_str("using", $2); } - | /*EMPTY*/ { $$ = ""; } + | USING class { $$ = cat2_str(make1_str("using"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); } ; /***************************************************************************** @@ -1704,7 +1751,7 @@ opt_class: class { $$ = $1; } ExtendStmt: EXTEND INDEX index_name where_clause { - $$ = make3_str("extend index", $3, $4); + $$ = cat3_str(make1_str("extend index"), $3, $4); } ; @@ -1718,7 +1765,7 @@ ExtendStmt: EXTEND INDEX index_name where_clause RecipeStmt: EXECUTE RECIPE recipe_name { - $$ = make2_str("execute recipe", $3); + $$ = cat2_str(make1_str("execute recipe"), $3); } ; @@ -1741,30 +1788,30 @@ RecipeStmt: EXECUTE RECIPE recipe_name ProcedureStmt: CREATE FUNCTION func_name func_args RETURNS func_return opt_with AS Sconst LANGUAGE Sconst { - $$ = make2_str(make5_str(make5_str("create function", $3, $4, "returns", $6), $7, "as", $9, "language"), $11); + $$ = 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); } -opt_with: WITH definition { $$ = make2_str("with", $2); } - | /*EMPTY*/ { $$ = ""; } +opt_with: WITH definition { $$ = cat2_str(make1_str("with"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -func_args: '(' func_args_list ')' { $$ = cat3_str("(", $2, ")"); } - | '(' ')' { $$ = "()"; } +func_args: '(' func_args_list ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); } + | '(' ')' { $$ = make1_str("()"); } ; func_args_list: TypeId { $$ = $1; } | func_args_list ',' TypeId - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } ; func_return: set_opt TypeId { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } ; -set_opt: SETOF { $$ = "setof"; } - | /*EMPTY*/ { $$ = ""; } +set_opt: SETOF { $$ = make1_str("setof"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -1787,50 +1834,50 @@ set_opt: SETOF { $$ = "setof"; } RemoveStmt: DROP remove_type name { - $$ = make3_str("drop", $2, $3);; + $$ = cat3_str(make1_str("drop"), $2, $3);; } ; -remove_type: TYPE_P { $$ = "type"; } - | INDEX { $$ = "index"; } - | RULE { $$ = "rule"; } - | VIEW { $$ = "view"; } +remove_type: TYPE_P { $$ = make1_str("type"); } + | INDEX { $$ = make1_str("index"); } + | RULE { $$ = make1_str("rule"); } + | VIEW { $$ = make1_str("view"); } ; RemoveAggrStmt: DROP AGGREGATE name aggr_argtype { - $$ = make3_str("drop aggregate", $3, $4); + $$ = cat3_str(make1_str("drop aggregate"), $3, $4); } ; aggr_argtype: name { $$ = $1; } - | '*' { $$ = "*"; } + | '*' { $$ = make1_str("*"); } ; RemoveFuncStmt: DROP FUNCTION func_name func_args { - $$ = make3_str("drop function", $3, $4); + $$ = cat3_str(make1_str("drop function"), $3, $4); } ; RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')' { - $$ = make3_str("drop operator", $3, cat3_str("(", $5, ")")); + $$ = cat3_str(make1_str("drop operator"), $3, make3_str(make1_str("("), $5, make1_str(")"))); } ; all_Op: Op | MathOp; -MathOp: '+' { $$ = "+"; } - | '-' { $$ = "-"; } - | '*' { $$ = "*"; } - | '/' { $$ = "/"; } - | '<' { $$ = "<"; } - | '>' { $$ = ">"; } - | '=' { $$ = "="; } +MathOp: '+' { $$ = make1_str("+"); } + | '-' { $$ = make1_str("-"); } + | '*' { $$ = make1_str("*"); } + | '/' { $$ = make1_str("/"); } + | '<' { $$ = make1_str("<"); } + | '>' { $$ = make1_str(">"); } + | '=' { $$ = make1_str("="); } ; oper_argtypes: name @@ -1838,11 +1885,11 @@ oper_argtypes: name yyerror("parser: argument type missing (use NONE for unary operators)"); } | name ',' name - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } | NONE ',' name /* left unary */ - { $$ = make2_str("none,", $3); } + { $$ = cat2_str(make1_str("none,"), $3); } | name ',' NONE /* right unary */ - { $$ = make2_str($1, ", none"); } + { $$ = cat2_str($1, make1_str(", none")); } ; @@ -1857,16 +1904,16 @@ oper_argtypes: name RenameStmt: ALTER TABLE relation_name opt_inh_star RENAME opt_column opt_name TO name { - $$ = make4_str(make5_str("alter table", $3, $4, "rename", $6), $7, "to", $9); + $$ = cat4_str(cat5_str(make1_str("alter table"), $3, $4, make1_str("rename"), $6), $7, make1_str("to"), $9); } ; opt_name: name { $$ = $1; } - | /*EMPTY*/ { $$ = ""; } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_column: COLUMN { $$ = "colmunn"; } - | /*EMPTY*/ { $$ = ""; } +opt_column: COLUMN { $$ = make1_str("colmunn"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -1884,13 +1931,13 @@ RuleStmt: CREATE RULE name AS ON event TO event_object where_clause DO opt_instead OptStmtList { - $$ = make2_str(make5_str(make5_str("create rule", $3, "as on", $7, "to"), $9, $10, "do", $12), $13); + $$ = 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); } ; -OptStmtList: NOTHING { $$ = "nothing"; } +OptStmtList: NOTHING { $$ = make1_str("nothing"); } | OptimizableStmt { $$ = $1; } - | '[' OptStmtBlock ']' { $$ = make3_str("[", $2, "]"); } + | '[' OptStmtBlock ']' { $$ = cat3_str(make1_str("["), $2, make1_str("]")); } ; OptStmtBlock: OptStmtMulti @@ -1900,16 +1947,16 @@ OptStmtBlock: OptStmtMulti ; OptStmtMulti: OptStmtMulti OptimizableStmt ';' - { $$ = make3_str($1, $2, ";"); } + { $$ = cat3_str($1, $2, make1_str(";")); } | OptStmtMulti OptimizableStmt - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | OptimizableStmt ';' { $$ = $1; } ; event_object: relation_name '.' attr_name { - $$ = cat3_str($1, ".", $3); + $$ = make3_str($1, make1_str("."), $3); } | relation_name { @@ -1918,14 +1965,14 @@ event_object: relation_name '.' attr_name ; /* change me to select, update, etc. some day */ -event: SELECT { $$ = "select"; } - | UPDATE { $$ = "update"; } - | DELETE { $$ = "delete"; } - | INSERT { $$ = "insert"; } +event: SELECT { $$ = make1_str("select"); } + | UPDATE { $$ = make1_str("update"); } + | DELETE { $$ = make1_str("delete"); } + | INSERT { $$ = make1_str("insert"); } ; -opt_instead: INSTEAD { $$ = "instead"; } - | /*EMPTY*/ { $$ = ""; } +opt_instead: INSTEAD { $$ = make1_str("instead"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -1939,13 +1986,13 @@ opt_instead: INSTEAD { $$ = "instead"; } NotifyStmt: NOTIFY relation_name { - $$ = make2_str("notify", $2); + $$ = cat2_str(make1_str("notify"), $2); } ; ListenStmt: LISTEN relation_name { - $$ = make2_str("listen", $2); + $$ = cat2_str(make1_str("listen"), $2); } ; @@ -1961,15 +2008,15 @@ ListenStmt: LISTEN relation_name * (END) * *****************************************************************************/ -TransactionStmt: ABORT_TRANS TRANSACTION { $$ = "rollback"; } - | BEGIN_TRANS TRANSACTION { $$ = "begin transaction"; } - | BEGIN_TRANS WORK { $$ = "begin transaction"; } - | COMMIT WORK { $$ = "commit"; } - | END_TRANS TRANSACTION { $$ = "commit"; } - | ROLLBACK WORK { $$ = "rollback"; } - | ABORT_TRANS { $$ = "rollback"; } - | COMMIT { $$ = "commit"; } - | ROLLBACK { $$ = "rollback"; } +TransactionStmt: ABORT_TRANS TRANSACTION { $$ = make1_str("rollback"); } + | BEGIN_TRANS TRANSACTION { $$ = make1_str("begin transaction"); } + | BEGIN_TRANS WORK { $$ = make1_str("begin transaction"); } + | COMMIT WORK { $$ = make1_str("commit"); } + | END_TRANS TRANSACTION { $$ = make1_str("commit"); } + | ROLLBACK WORK { $$ = make1_str("rollback"); } + | ABORT_TRANS { $$ = make1_str("rollback"); } + | COMMIT { $$ = make1_str("commit"); } + | ROLLBACK { $$ = make1_str("rollback"); } /***************************************************************************** * @@ -1980,7 +2027,7 @@ TransactionStmt: ABORT_TRANS TRANSACTION { $$ = "rollback"; } ViewStmt: CREATE VIEW name AS SelectStmt { - $$ = make4_str("create view", $3, "as", $5); + $$ = cat4_str(make1_str("create view"), $3, make1_str("as"), $5); } ; @@ -1988,13 +2035,13 @@ ViewStmt: CREATE VIEW name AS SelectStmt /***************************************************************************** * * QUERY: - * load "filename" + * load make1_str("filename") * *****************************************************************************/ LoadStmt: LOAD file_name { - $$ = make2_str("load", $2); + $$ = cat2_str(make1_str("load"), $2); } ; @@ -2008,17 +2055,17 @@ LoadStmt: LOAD file_name CreatedbStmt: CREATE DATABASE database_name opt_database { - $$ = make3_str("create database", $3, $4); + $$ = cat3_str(make1_str("create database"), $3, $4); } ; -opt_database: WITH LOCATION '=' location { $$ = make2_str("with location =", $4); } - | /*EMPTY*/ { $$ = ""; } +opt_database: WITH LOCATION '=' location { $$ = cat2_str(make1_str("with location ="), $4); } + | /*EMPTY*/ { $$ = make1_str(""); } ; location: Sconst { $$ = $1; } - | DEFAULT { $$ = "default"; } - | /*EMPTY*/ { $$ = ""; } + | DEFAULT { $$ = make1_str("default"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; /***************************************************************************** @@ -2030,7 +2077,7 @@ location: Sconst { $$ = $1; } DestroydbStmt: DROP DATABASE database_name { - $$ = make2_str("drop database", $3); + $$ = cat2_str(make1_str("drop database"), $3); } ; @@ -2044,7 +2091,7 @@ DestroydbStmt: DROP DATABASE database_name ClusterStmt: CLUSTER index_name ON relation_name { - $$ = make4_str("cluster", $2, "on", $4); + $$ = cat4_str(make1_str("cluster"), $2, make1_str("on"), $4); } ; @@ -2058,32 +2105,32 @@ ClusterStmt: CLUSTER index_name ON relation_name VacuumStmt: VACUUM opt_verbose opt_analyze { - $$ = make3_str("vacuum", $2, $3); + $$ = cat3_str(make1_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 \"(\""); - $$ = make5_str("vacuum", $2, $3, $4, $5); + $$ = cat5_str(make1_str("vacuum"), $2, $3, $4, $5); } ; -opt_verbose: VERBOSE { $$ = "verbose"; } - | /*EMPTY*/ { $$ = ""; } +opt_verbose: VERBOSE { $$ = make1_str("verbose"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_analyze: ANALYZE { $$ = "analyse"; } - | /*EMPTY*/ { $$ = ""; } +opt_analyze: ANALYZE { $$ = make1_str("analyse"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_va_list: '(' va_list ')' { $$ = cat3_str("(", $2, ")"); } - | /*EMPTY*/ { $$ = ""; } +opt_va_list: '(' va_list ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); } + | /*EMPTY*/ { $$ = make1_str(""); } ; va_list: name { $$=$1; } | va_list ',' name - { $$=make3_str($1, ",", $3); } + { $$=cat3_str($1, make1_str(","), $3); } ; @@ -2096,7 +2143,7 @@ va_list: name ExplainStmt: EXPLAIN opt_verbose OptimizableStmt { - $$ = make3_str("explain", $2, $3); + $$ = cat3_str(make1_str("explain"), $2, $3); } ; @@ -2112,12 +2159,17 @@ ExplainStmt: EXPLAIN opt_verbose OptimizableStmt * * *****************************************************************************/ -OptimizableStmt: SelectStmt { output_statement($1); } - | CursorStmt { fputs($1, yyout); output_line_number(); } - | UpdateStmt { output_statement($1); } - | InsertStmt { output_statement($1); } - | NotifyStmt { output_statement($1); } - | DeleteStmt { output_statement($1); } +OptimizableStmt: SelectStmt { output_statement($1, 1); } + | CursorStmt + { + fputs($1, yyout); + output_line_number(); + free($1); + } + | UpdateStmt { output_statement($1, 0); } + | InsertStmt { output_statement($1, 0); } + | NotifyStmt { output_statement($1, 0); } + | DeleteStmt { output_statement($1, 0); } ; @@ -2130,37 +2182,37 @@ OptimizableStmt: SelectStmt { output_statement($1); } InsertStmt: INSERT INTO relation_name opt_column_list insert_rest { - $$ = make4_str("insert into", $3, $4, $5); + $$ = cat4_str(make1_str("insert into"), $3, $4, $5); } ; insert_rest: VALUES '(' res_target_list2 ')' { - $$ = cat3_str("values(", $3, ")"); + $$ = make3_str(make1_str("values("), $3, make1_str(")")); } | SELECT opt_unique res_target_list2 from_clause where_clause group_clause having_clause union_clause { - $$ = make4_str(make5_str("select", $2, $3, $4, $5), $6, $7, $8); + $$ = cat4_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8); } ; -opt_column_list: '(' columnList ')' { $$ = cat3_str("(", $2, ")"); } - | /*EMPTY*/ { $$ = ""; } +opt_column_list: '(' columnList ')' { $$ = make3_str(make1_str("("), $2, make1_str(")")); } + | /*EMPTY*/ { $$ = make1_str(""); } ; columnList: columnList ',' columnElem - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } | columnElem { $$ = $1; } ; columnElem: ColId opt_indirection { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } ; @@ -2175,7 +2227,7 @@ columnElem: ColId opt_indirection DeleteStmt: DELETE FROM relation_name where_clause { - $$ = make3_str("delete from", $3, $4); + $$ = cat3_str(make1_str("delete from"), $3, $4); } ; @@ -2186,7 +2238,7 @@ DeleteStmt: DELETE FROM relation_name */ LockStmt: LOCK_P opt_table relation_name { - $$ = make3_str("lock", $2, $3); + $$ = cat3_str(make1_str("lock"), $2, $3); } ; @@ -2203,7 +2255,7 @@ UpdateStmt: UPDATE relation_name from_clause where_clause { - $$ = make2_str(make5_str("update", $2, "set", $4, $5), $6); + $$ = cat2_str(cat5_str(make1_str("update"), $2, make1_str("set"), $4, $5), $6); } ; @@ -2222,8 +2274,8 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR { struct cursor *ptr, *this = (struct cursor *) mm_alloc(sizeof(struct cursor)); - this->name = $2; - this->command = make4_str(make5_str(make5_str("declare", $2, $3, "cursor for select", $7), $8, $9, $10, $11), $12, $13, $14); + this->name = strdup($2); + this->command = cat4_str(cat5_str(cat5_str(make1_str("declare"), strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14); this->next = NULL; for (ptr = cur; ptr != NULL; ptr = ptr->next) @@ -2244,7 +2296,7 @@ CursorStmt: DECLARE name opt_binary CURSOR FOR cur = this; } - $$ = make5_str("/* declare cursor\"", $2, "\"statement has been moved to location of open cursor \"", $2, "\"statement. */"); + $$ = cat5_str(make1_str("/* declare cursor\""), $2, make1_str("\"statement has been moved to location of open cursor \""), strdup($2), make1_str("\"statement. */")); } ; @@ -2262,21 +2314,21 @@ SelectStmt: SELECT opt_unique res_target_list2 group_clause having_clause union_clause sort_clause { - $$ = make2_str(make5_str(make5_str("select", $2, $3, $4, $5), $6, $7, $8, $9), $10); + $$ = cat2_str(cat5_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8, $9), $10); } ; union_clause: UNION opt_union select_list { - $$ = make3_str("union", $2, $3); + $$ = cat3_str(make1_str("union"), $2, $3); } | /*EMPTY*/ - { $$ = ""; } + { $$ = make1_str(""); } ; select_list: select_list UNION opt_union SubSelect { - $$ = make4_str($1, "union", $3, $4); + $$ = cat4_str($1, make1_str("union"), $3, $4); } | SubSelect { $$ = $1; } @@ -2286,57 +2338,57 @@ SubSelect: SELECT opt_unique res_target_list2 from_clause where_clause group_clause having_clause { - $$ = make3_str(make5_str("select", $2, $3, $4, $5), $6, $7); + $$ = cat3_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7); } ; -result: INTO opt_table relation_name { $$= make3_str("into", $2, $3); } - | INTO into_list { $$ = ""; } - | /*EMPTY*/ { $$ = ""; } +result: INTO opt_table relation_name { $$= cat3_str(make1_str("into"), $2, $3); } + | INTO into_list { $$ = make1_str(""); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_table: TABLE { $$ = "table"; } - | /*EMPTY*/ { $$ = ""; } +opt_table: TABLE { $$ = make1_str("table"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_union: ALL { $$ = "all"; } - | /*EMPTY*/ { $$ = ""; } +opt_union: ALL { $$ = make1_str("all"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_unique: DISTINCT { $$ = "distinct"; } - | DISTINCT ON ColId { $$ = make2_str("distinct on", $3); } - | ALL { $$ = "all"; } - | /*EMPTY*/ { $$ = ""; } +opt_unique: DISTINCT { $$ = make1_str("distinct"); } + | DISTINCT ON ColId { $$ = cat2_str(make1_str("distinct on"), $3); } + | ALL { $$ = make1_str("all"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -sort_clause: ORDER BY sortby_list { $$ = make2_str("order by", $3); } - | /*EMPTY*/ { $$ = ""; } +sort_clause: ORDER BY sortby_list { $$ = cat2_str(make1_str("order by"), $3); } + | /*EMPTY*/ { $$ = make1_str(""); } ; sortby_list: sortby { $$ = $1; } - | sortby_list ',' sortby { $$ = make3_str($1, ",", $3); } + | sortby_list ',' sortby { $$ = cat3_str($1, make1_str(","), $3); } ; sortby: ColId OptUseOp { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | ColId '.' ColId OptUseOp { - $$ = make2_str(cat3_str($1, ".", $3), $4); + $$ = cat2_str(make3_str($1, make1_str("."), $3), $4); } | Iconst OptUseOp { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } ; -OptUseOp: USING Op { $$ = make2_str("using", $2); } - | USING '<' { $$ = "using <"; } - | USING '>' { $$ = "using >"; } - | ASC { $$ = "asc"; } - | DESC { $$ = "desc"; } - | /*EMPTY*/ { $$ = ""; } +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(""); } ; /* @@ -2346,8 +2398,8 @@ OptUseOp: USING Op { $$ = make2_str("using", $2); } * ...however, recursive addattr and rename supported. make special * cases for these. */ -opt_inh_star: '*' { $$ = "*"; } - | /*EMPTY*/ { $$ = ""; } +opt_inh_star: '*' { $$ = make1_str("*"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; relation_name_list: name_list { $$ = $1; }; @@ -2355,15 +2407,15 @@ relation_name_list: name_list { $$ = $1; }; name_list: name { $$ = $1; } | name_list ',' name - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } ; -group_clause: GROUP BY groupby_list { $$ = make2_str("groub by", $3); } - | /*EMPTY*/ { $$ = ""; } +group_clause: GROUP BY groupby_list { $$ = cat2_str(make1_str("groub by"), $3); } + | /*EMPTY*/ { $$ = make1_str(""); } ; groupby_list: groupby { $$ = $1; } - | groupby_list ',' groupby { $$ = make3_str($1, ",", $3); } + | groupby_list ',' groupby { $$ = cat3_str($1, make1_str(","), $3); } ; groupby: ColId @@ -2372,7 +2424,7 @@ groupby: ColId } | ColId '.' ColId { - $$ = cat3_str($1, ",", $3); + $$ = make3_str($1, make1_str(","), $3); } | Iconst { @@ -2383,9 +2435,9 @@ groupby: ColId having_clause: HAVING a_expr { yyerror("HAVING clause not yet implemented"); -/* $$ = make2_str("having", $2); use this line instead to enable HAVING */ +/* $$ = cat2_str(make1_str("having"), $2); use this line instead to enable HAVING */ } - | /*EMPTY*/ { $$ = ""; } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -2401,12 +2453,12 @@ from_clause: FROM '(' relation_expr join_expr JOIN relation_expr join_spec ')' { yyerror("JOIN not yet implemented"); } - | FROM from_list { $$ = make2_str("from", $2); } - | /*EMPTY*/ { $$ = ""; } + | FROM from_list { $$ = cat2_str(make1_str("from"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); } ; from_list: from_list ',' from_val - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } | from_val CROSS JOIN from_val { yyerror("CROSS JOIN not yet implemented"); } | from_val @@ -2415,11 +2467,11 @@ from_list: from_list ',' from_val from_val: relation_expr AS ColLabel { - $$ = make3_str($1, "as", $3); + $$ = cat3_str($1, make1_str("as"), $3); } | relation_expr ColId { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | relation_expr { @@ -2427,7 +2479,7 @@ from_val: relation_expr AS ColLabel } ; -join_expr: NATURAL join_expr { $$ = make2_str("natural", $2); } +join_expr: NATURAL join_expr { $$ = cat2_str(make1_str("natural"), $2); } | FULL join_outer { yyerror("FULL OUTER JOIN not yet implemented"); } | LEFT join_outer @@ -2444,17 +2496,17 @@ join_expr: NATURAL join_expr { $$ = make2_str("natural", $2); } { yyerror("INNER JOIN not yet implemented"); } ; -join_outer: OUTER_P { $$ = "outer"; } - | /*EMPTY*/ { $$ = ""; /* no qualifiers */ } +join_outer: OUTER_P { $$ = make1_str("outer"); } + | /*EMPTY*/ { $$ = make1_str(""); /* no qualifiers */ } ; -join_spec: ON '(' a_expr ')' { $$ = cat3_str("on (", $3, ")"); } - | USING '(' join_list ')' { $$ = cat3_str("using (", $3, ")"); } - | /*EMPTY*/ { $$ = ""; /* no qualifiers */ } +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 */ } ; join_list: join_using { $$ = $1; } - | join_list ',' join_using { $$ = make3_str($1, ",", $3); } + | join_list ',' join_using { $$ = cat3_str($1, make1_str(","), $3); } ; join_using: ColId @@ -2463,7 +2515,7 @@ join_using: ColId } | ColId '.' ColId { - $$ = cat3_str($1, ".", $3); + $$ = make3_str($1, make1_str("."), $3); } | Iconst { @@ -2471,8 +2523,8 @@ join_using: ColId } ; -where_clause: WHERE a_expr { $$ = make2_str("where", $2); } - | /*EMPTY*/ { $$ = ""; /* no qualifiers */ } +where_clause: WHERE a_expr { $$ = cat2_str(make1_str("where"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); /* no qualifiers */ } ; relation_expr: relation_name @@ -2483,25 +2535,48 @@ relation_expr: relation_name | relation_name '*' %prec '=' { /* inheritance query */ - $$ = make2_str($1, "*"); + $$ = cat2_str($1, make1_str("*")); } opt_array_bounds: '[' ']' nest_array_bounds - { $$ = make2_str("[]", $3); } + { + $$.index1 = 0; + $$.index2 = $3.index1; + $$.str = cat2_str(make1_str("[]"), $3.str); + } | '[' Iconst ']' nest_array_bounds - { $$ = make4_str("[", $2, "]", $4); } + { + $$.index1 = atol($2); + $$.index2 = $4.index1; + $$.str = cat4_str(make1_str("["), $2, make1_str("]"), $4.str); + } | /* EMPTY */ - { $$ = ""; } + { + $$.index1 = -1; + $$.index2 = -1; + $$.str= make1_str(""); + } ; nest_array_bounds: '[' ']' nest_array_bounds - { $$ = make2_str("[]", $3); } + { + $$.index1 = 0; + $$.index2 = $3.index1; + $$.str = cat2_str(make1_str("[]"), $3.str); + } | '[' Iconst ']' nest_array_bounds - { $$ = make4_str("[", $2, "]", $4); } - | /*EMPTY*/ - { $$ = ""; } - ; - + { + $$.index1 = atol($2); + $$.index2 = $4.index1; + $$.str = cat4_str(make1_str("["), $2, make1_str("]"), $4.str); + } + | /* EMPTY */ + { + $$.index1 = -1; + $$.index2 = -1; + $$.str= make1_str(""); + } + ; /***************************************************************************** * @@ -2515,12 +2590,12 @@ nest_array_bounds: '[' ']' nest_array_bounds Typename: Array opt_array_bounds { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2.str); } | Character { $$ = $1; } | SETOF Array { - $$ = make2_str("setof", $2); + $$ = cat2_str(make1_str("setof"), $2); } ; @@ -2536,7 +2611,7 @@ Generic: generic ; generic: ecpg_ident { $$ = $1; } - | TYPE_P { $$ = "type"; } + | TYPE_P { $$ = make1_str("type"); } ; /* SQL92 numeric data types @@ -2547,30 +2622,30 @@ generic: ecpg_ident { $$ = $1; } */ Numeric: FLOAT opt_float { - $$ = make2_str("float", $2); + $$ = cat2_str(make1_str("float"), $2); } | DOUBLE PRECISION { - $$ = "double precision"; + $$ = make1_str("double precision"); } | DECIMAL opt_decimal { - $$ = make2_str("decimal", $2); + $$ = cat2_str(make1_str("decimal"), $2); } | NUMERIC opt_numeric { - $$ = make2_str("numeric", $2); + $$ = cat2_str(make1_str("numeric"), $2); } ; numeric: FLOAT - { $$ = "float"; } + { $$ = make1_str("float"); } | DOUBLE PRECISION - { $$ = "double precision"; } + { $$ = make1_str("double precision"); } | DECIMAL - { $$ = "decimal"; } + { $$ = make1_str("decimal"); } | NUMERIC - { $$ = "numeric"; } + { $$ = make1_str("numeric"); } ; opt_float: '(' Iconst ')' @@ -2579,25 +2654,25 @@ opt_float: '(' Iconst ')' yyerror("precision for FLOAT must be at least 1"); else if (atol($2) >= 16) yyerror("precision for FLOAT must be less than 16"); - $$ = cat3_str("(", $2, ")"); + $$ = make3_str(make1_str("("), $2, make1_str(")")); } | /*EMPTY*/ { - $$ = ""; + $$ = make1_str(""); } ; opt_numeric: '(' Iconst ',' Iconst ')' { if (atol($2) != 9) { - sprintf(errortext, "NUMERIC precision %s must be 9", $2); + sprintf(errortext, make1_str("NUMERIC precision %s must be 9"), $2); yyerror(errortext); } if (atol($4) != 0) { sprintf(errortext, "NUMERIC scale %s must be zero", $4); yyerror(errortext); } - $$ = make3_str(cat2_str("(", $2), ",", cat2_str($4, ")")); + $$ = cat3_str(make2_str(make1_str("("), $2), make1_str(","), make2_str($4, make1_str(")"))); } | '(' Iconst ')' { @@ -2605,11 +2680,11 @@ opt_numeric: '(' Iconst ',' Iconst ')' sprintf("NUMERIC precision %s must be 9",$2); yyerror(errortext); } - $$ = cat3_str("(", $2, ")"); + $$ = make3_str(make1_str("("), $2, make1_str(")")); } | /*EMPTY*/ { - $$ = ""; + $$ = make1_str(""); } ; @@ -2623,7 +2698,7 @@ opt_decimal: '(' Iconst ',' Iconst ')' sprintf(errortext, "DECIMAL scale %s must be zero",$4); yyerror(errortext); } - $$ = make3_str(cat2_str("(", $2), ",", cat2_str($4, ")")); + $$ = cat3_str(make2_str(make1_str("("), $2), make1_str(","), make2_str($4, make1_str(")"))); } | '(' Iconst ')' { @@ -2631,11 +2706,11 @@ opt_decimal: '(' Iconst ',' Iconst ')' sprintf(errortext, "DECIMAL precision %s exceeds implementation limit of 9",$2); yyerror(errortext); } - $$ = cat3_str("(", $2, ")"); + $$ = make3_str(make1_str("("), $2, make1_str(")")); } | /*EMPTY*/ { - $$ = ""; + $$ = make1_str(""); } ; @@ -2664,7 +2739,7 @@ Character: character '(' Iconst ')' yyerror(errortext); } - $$ = make2_str($1, cat3_str("(", $3, ")")); + $$ = cat2_str($1, make3_str(make1_str("("), $3, make1_str(")"))); } | character { @@ -2678,24 +2753,24 @@ character: CHARACTER opt_varying opt_charset opt_collate sprintf(errortext, "COLLATE %s not yet implemented",$4); yyerror(errortext); } - $$ = make4_str("character", $2, $3, $4); + $$ = cat4_str(make1_str("character"), $2, $3, $4); } - | CHAR opt_varying { $$ = make2_str("char", $2); } - | VARCHAR { $$ = "varchar"; } - | NATIONAL CHARACTER opt_varying { $$ = make2_str("national character", $3); } - | NCHAR opt_varying { $$ = make2_str("nchar", $2); } + | 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); } ; -opt_varying: VARYING { $$ = "varying"; } - | /*EMPTY*/ { $$ = ""; } +opt_varying: VARYING { $$ = make1_str("varying"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_charset: CHARACTER SET ColId { $$ = make2_str("character set", $3); } - | /*EMPTY*/ { $$ = ""; } +opt_charset: CHARACTER SET ColId { $$ = cat2_str(make1_str("character set"), $3); } + | /*EMPTY*/ { $$ = make1_str(""); } ; -opt_collate: COLLATE ColId { $$ = make2_str("collate", $2); } - | /*EMPTY*/ { $$ = ""; } +opt_collate: COLLATE ColId { $$ = cat2_str(make1_str("collate"), $2); } + | /*EMPTY*/ { $$ = make1_str(""); } ; Datetime: datetime @@ -2704,38 +2779,38 @@ Datetime: datetime } | TIMESTAMP opt_timezone { - $$ = make2_str("timestamp", $2); + $$ = cat2_str(make1_str("timestamp"), $2); } | TIME { - $$ = "time"; + $$ = make1_str("time"); } | INTERVAL opt_interval { - $$ = make2_str("interval", $2); + $$ = cat2_str(make1_str("interval"), $2); } ; -datetime: YEAR_P { $$ = "year"; } - | MONTH_P { $$ = "month"; } - | DAY_P { $$ = "day"; } - | HOUR_P { $$ = "hour"; } - | MINUTE_P { $$ = "minute"; } - | SECOND_P { $$ = "second"; } +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"); } ; -opt_timezone: WITH TIME ZONE { $$ = "with time zone"; } - | /*EMPTY*/ { $$ = ""; } +opt_timezone: WITH TIME ZONE { $$ = make1_str("with time zone"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; opt_interval: datetime { $$ = $1; } - | YEAR_P TO MONTH_P { $$ = "year to #month"; } - | DAY_P TO HOUR_P { $$ = "day to hour"; } - | DAY_P TO MINUTE_P { $$ = "day to minute"; } - | DAY_P TO SECOND_P { $$ = "day to second"; } - | HOUR_P TO MINUTE_P { $$ = "hour to minute"; } - | HOUR_P TO SECOND_P { $$ = "hour to second"; } - | /*EMPTY*/ { $$ = ""; } + | 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"); } + | HOUR_P TO SECOND_P { $$ = make1_str("hour to second"); } + | /*EMPTY*/ { $$ = make1_str(""); } ; @@ -2749,7 +2824,7 @@ a_expr_or_null: a_expr { $$ = $1; } | NULL_P { - $$ = "null"; + $$ = make1_str("null"); } ; @@ -2759,151 +2834,151 @@ a_expr_or_null: a_expr */ row_expr: '(' row_descriptor ')' IN '(' SubSelect ')' { - $$ = cat5_str("(", $2, ") in (", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(") in ("), $6, make1_str(")")); } | '(' row_descriptor ')' NOT IN '(' SubSelect ')' { - $$ = cat5_str("(", $2, ") not in (", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(") not in ("), $7, make1_str(")")); } | '(' row_descriptor ')' Op '(' SubSelect ')' { - $$ = cat3_str(cat5_str("(", $2, ")", $4, "("), $6, ")"); + $$ = make3_str(make5_str(make1_str("("), $2, make1_str(")"), $4, make1_str("(")), $6, make1_str(")")); } | '(' row_descriptor ')' '+' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")+(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")+("), $6, make1_str(")")); } | '(' row_descriptor ')' '-' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")-(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")-("), $6, make1_str(")")); } | '(' row_descriptor ')' '/' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")/(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")/("), $6, make1_str(")")); } | '(' row_descriptor ')' '*' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")*(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")*("), $6, make1_str(")")); } | '(' row_descriptor ')' '<' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")<(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")<("), $6, make1_str(")")); } | '(' row_descriptor ')' '>' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")>(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")>("), $6, make1_str(")")); } | '(' row_descriptor ')' '=' '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")=(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")=("), $6, make1_str(")")); } | '(' row_descriptor ')' Op ANY '(' SubSelect ')' { - $$ = make3_str(cat3_str("(", $2, ")"), $4, cat3_str("any(", $7, ")")); + $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("any("), $7, make1_str(")"))); } | '(' row_descriptor ')' '+' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")+any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")+any("), $7, make1_str(")")); } | '(' row_descriptor ')' '-' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")-any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")-any("), $7, make1_str(")")); } | '(' row_descriptor ')' '/' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")/any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")/any("), $7, make1_str(")")); } | '(' row_descriptor ')' '*' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")*any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")*any("), $7, make1_str(")")); } | '(' row_descriptor ')' '<' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")<any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")<any("), $7, make1_str(")")); } | '(' row_descriptor ')' '>' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")>any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")>any("), $7, make1_str(")")); } | '(' row_descriptor ')' '=' ANY '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")=any(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")=any("), $7, make1_str(")")); } | '(' row_descriptor ')' Op ALL '(' SubSelect ')' { - $$ = make3_str(cat3_str("(", $2, ")"), $4, cat3_str("all(", $7, ")")); + $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("all("), $7, make1_str(")"))); } | '(' row_descriptor ')' '+' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")+all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")+all("), $7, make1_str(")")); } | '(' row_descriptor ')' '-' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")-all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")-all("), $7, make1_str(")")); } | '(' row_descriptor ')' '/' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")/all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")/all("), $7, make1_str(")")); } | '(' row_descriptor ')' '*' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")*all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")*all("), $7, make1_str(")")); } | '(' row_descriptor ')' '<' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")<all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")<all("), $7, make1_str(")")); } | '(' row_descriptor ')' '>' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")>all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")>all("), $7, make1_str(")")); } | '(' row_descriptor ')' '=' ALL '(' SubSelect ')' { - $$ = cat5_str("(", $2, ")=all(", $7, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")=all("), $7, make1_str(")")); } | '(' row_descriptor ')' Op '(' row_descriptor ')' { - $$ = make3_str(cat3_str("(", $2, ")"), $4, cat3_str("(", $6, ")")); + $$ = cat3_str(make3_str(make1_str("("), $2, make1_str(")")), $4, make3_str(make1_str("("), $6, make1_str(")"))); } | '(' row_descriptor ')' '+' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")+(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")+("), $6, make1_str(")")); } | '(' row_descriptor ')' '-' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")-(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")-("), $6, make1_str(")")); } | '(' row_descriptor ')' '/' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")/(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")/("), $6, make1_str(")")); } | '(' row_descriptor ')' '*' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")*(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")*("), $6, make1_str(")")); } | '(' row_descriptor ')' '<' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")<(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")<("), $6, make1_str(")")); } | '(' row_descriptor ')' '>' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")>(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")>("), $6, make1_str(")")); } | '(' row_descriptor ')' '=' '(' row_descriptor ')' { - $$ = cat5_str("(", $2, ")=(", $6, ")"); + $$ = make5_str(make1_str("("), $2, make1_str(")=("), $6, make1_str(")")); } ; row_descriptor: row_list ',' a_expr { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } ; row_list: row_list ',' a_expr { - $$ = make3_str($1, ",", $3); + $$ = cat3_str($1, make1_str(","), $3); } | a_expr { @@ -2921,7 +2996,7 @@ row_list: row_list ',' a_expr a_expr: attr opt_indirection { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | row_expr { $$ = $1; } @@ -2932,129 +3007,129 @@ a_expr: attr opt_indirection $$ = $1; } | '-' a_expr %prec UMINUS - { $$ = make2_str("-", $2); } + { $$ = cat2_str(make1_str("-"), $2); } | a_expr '+' a_expr - { $$ = make3_str($1, "+", $3); } + { $$ = cat3_str($1, make1_str("+"), $3); } | a_expr '-' a_expr - { $$ = make3_str($1, "-", $3); } + { $$ = cat3_str($1, make1_str("-"), $3); } | a_expr '/' a_expr - { $$ = make3_str($1, "/", $3); } + { $$ = cat3_str($1, make1_str("/"), $3); } | a_expr '*' a_expr - { $$ = make3_str($1, "*", $3); } + { $$ = cat3_str($1, make1_str("*"), $3); } | a_expr '<' a_expr - { $$ = make3_str($1, "<", $3); } + { $$ = cat3_str($1, make1_str("<"), $3); } | a_expr '>' a_expr - { $$ = make3_str($1, ">", $3); } + { $$ = cat3_str($1, make1_str(">"), $3); } | a_expr '=' a_expr - { $$ = make3_str($1, "=", $3); } + { $$ = cat3_str($1, make1_str("="), $3); } /* not possible in embedded sql | ':' a_expr - { $$ = make2_str(":", $2); } + { $$ = cat2_str(make1_str(":"), $2); } */ | ';' a_expr - { $$ = make2_str(";", $2); } + { $$ = cat2_str(make1_str(";"), $2); } | '|' a_expr - { $$ = make2_str("|", $2); } + { $$ = cat2_str(make1_str("|"), $2); } | a_expr TYPECAST Typename { - $$ = make3_str($1, "::", $3); + $$ = cat3_str($1, make1_str("::"), $3); } | CAST '(' a_expr AS Typename ')' { - $$ = make3_str(cat2_str("cast(", $3), "as", cat2_str($5, ")")); + $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")"))); } | '(' a_expr_or_null ')' - { $$ = cat3_str("(", $2, ")"); } + { $$ = make3_str(make1_str("("), $2, make1_str(")")); } | a_expr Op a_expr - { $$ = make3_str($1, $2, $3); } + { $$ = cat3_str($1, $2, $3); } | a_expr LIKE a_expr - { $$ = make3_str($1, "like", $3); } + { $$ = cat3_str($1, make1_str("like"), $3); } | a_expr NOT LIKE a_expr - { $$ = make3_str($1, "not like", $4); } + { $$ = cat3_str($1, make1_str("not like"), $4); } | Op a_expr - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | a_expr Op - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | func_name '(' '*' ')' { - $$ = make2_str($1, "(*)"); + $$ = cat2_str($1, make1_str("(*)")); } | func_name '(' ')' { - $$ = make2_str($1, "()"); + $$ = cat2_str($1, make1_str("()")); } | func_name '(' expr_list ')' { - $$ = cat4_str($1, "(", $3, ")"); + $$ = make4_str($1, make1_str("("), $3, make1_str(")")); } | CURRENT_DATE { - $$ = "current_date"; + $$ = make1_str("current_date"); } | CURRENT_TIME { - $$ = "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); - $$ = "current_time"; + $$ = make1_str("current_time"); } | CURRENT_TIMESTAMP { - $$ = "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); - $$ = "current_timestamp"; + $$ = make1_str("current_timestamp"); } | CURRENT_USER { - $$ = "current_user"; + $$ = make1_str("current_user"); } | EXISTS '(' SubSelect ')' { - $$ = cat3_str("exists(", $3, ")"); + $$ = make3_str(make1_str("exists("), $3, make1_str(")")); } | EXTRACT '(' extract_list ')' { - $$ = cat3_str("extract(", $3, ")"); + $$ = make3_str(make1_str("extract("), $3, make1_str(")")); } | POSITION '(' position_list ')' { - $$ = cat3_str("position(", $3, ")"); + $$ = make3_str(make1_str("position("), $3, make1_str(")")); } | SUBSTRING '(' substr_list ')' { - $$ = cat3_str("substring(", $3, ")"); + $$ = make3_str(make1_str("substring("), $3, make1_str(")")); } /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */ | TRIM '(' BOTH trim_list ')' { - $$ = cat3_str("trim(both", $4, ")"); + $$ = make3_str(make1_str("trim(both"), $4, make1_str(")")); } | TRIM '(' LEADING trim_list ')' { - $$ = cat3_str("trim(leading", $4, ")"); + $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")")); } | TRIM '(' TRAILING trim_list ')' { - $$ = cat3_str("trim(trailing", $4, ")"); + $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")")); } | TRIM '(' trim_list ')' { - $$ = cat3_str("trim(", $3, ")"); + $$ = make3_str(make1_str("trim("), $3, make1_str(")")); } | a_expr ISNULL - { $$ = make2_str($1, "isnull"); } + { $$ = cat2_str($1, make1_str("isnull")); } | a_expr IS NULL_P - { $$ = make2_str($1, "is null"); } + { $$ = cat2_str($1, make1_str("is null")); } | a_expr NOTNULL - { $$ = make2_str($1, "notnull"); } + { $$ = cat2_str($1, make1_str("notnull")); } | a_expr IS NOT NULL_P - { $$ = make2_str($1, "is not null"); } + { $$ = 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. @@ -3062,140 +3137,140 @@ a_expr: attr opt_indirection */ | a_expr IS TRUE_P { - { $$ = make2_str($1, "is true"); } + { $$ = cat2_str($1, make1_str("is true")); } } | a_expr IS NOT FALSE_P { - { $$ = make2_str($1, "is not false"); } + { $$ = cat2_str($1, make1_str("is not false")); } } | a_expr IS FALSE_P { - { $$ = make2_str($1, "is false"); } + { $$ = cat2_str($1, make1_str("is false")); } } | a_expr IS NOT TRUE_P { - { $$ = make2_str($1, "is not true"); } + { $$ = cat2_str($1, make1_str("is not true")); } } | a_expr BETWEEN b_expr AND b_expr { - $$ = make5_str($1, "between", $3, "and", $5); + $$ = cat5_str($1, make1_str("between"), $3, make1_str("and"), $5); } | a_expr NOT BETWEEN b_expr AND b_expr { - $$ = make5_str($1, "not between", $4, "and", $6); + $$ = cat5_str($1, make1_str("not between"), $4, make1_str("and"), $6); } | a_expr IN '(' in_expr ')' { - $$ = cat4_str($1, "in (", $4, ")"); + $$ = make4_str($1, make1_str("in ("), $4, make1_str(")")); } | a_expr NOT IN '(' not_in_expr ')' { - $$ = cat4_str($1, "not in (", $5, ")"); + $$ = make4_str($1, make1_str("not in ("), $5, make1_str(")")); } | a_expr Op '(' SubSelect ')' { - $$ = make3_str($1, $2, cat3_str("(", $4, ")")); + $$ = cat3_str($1, $2, make3_str(make1_str("("), $4, make1_str(")"))); } | a_expr '+' '(' SubSelect ')' { - $$ = cat4_str($1, "+(", $4, ")"); + $$ = make4_str($1, make1_str("+("), $4, make1_str(")")); } | a_expr '-' '(' SubSelect ')' { - $$ = cat4_str($1, "-(", $4, ")"); + $$ = make4_str($1, make1_str("-("), $4, make1_str(")")); } | a_expr '/' '(' SubSelect ')' { - $$ = cat4_str($1, "/(", $4, ")"); + $$ = make4_str($1, make1_str("/("), $4, make1_str(")")); } | a_expr '*' '(' SubSelect ')' { - $$ = cat4_str($1, "*(", $4, ")"); + $$ = make4_str($1, make1_str("*("), $4, make1_str(")")); } | a_expr '<' '(' SubSelect ')' { - $$ = cat4_str($1, "<(", $4, ")"); + $$ = make4_str($1, make1_str("<("), $4, make1_str(")")); } | a_expr '>' '(' SubSelect ')' { - $$ = cat4_str($1, ">(", $4, ")"); + $$ = make4_str($1, make1_str(">("), $4, make1_str(")")); } | a_expr '=' '(' SubSelect ')' { - $$ = cat4_str($1, "=(", $4, ")"); + $$ = make4_str($1, make1_str("=("), $4, make1_str(")")); } | a_expr Op ANY '(' SubSelect ')' { - $$ = make3_str($1, $2, cat3_str("any(", $5, ")")); + $$ = cat3_str($1, $2, make3_str(make1_str("any("), $5, make1_str(")"))); } | a_expr '+' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "+any(", $5, ")"); + $$ = make4_str($1, make1_str("+any("), $5, make1_str(")")); } | a_expr '-' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "-any(", $5, ")"); + $$ = make4_str($1, make1_str("-any("), $5, make1_str(")")); } | a_expr '/' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "/any(", $5, ")"); + $$ = make4_str($1, make1_str("/any("), $5, make1_str(")")); } | a_expr '*' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "*any(", $5, ")"); + $$ = make4_str($1, make1_str("*any("), $5, make1_str(")")); } | a_expr '<' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "<any(", $5, ")"); + $$ = make4_str($1, make1_str("<any("), $5, make1_str(")")); } | a_expr '>' ANY '(' SubSelect ')' { - $$ = cat4_str($1, ">any(", $5, ")"); + $$ = make4_str($1, make1_str(">any("), $5, make1_str(")")); } | a_expr '=' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "=any(", $5, ")"); + $$ = make4_str($1, make1_str("=any("), $5, make1_str(")")); } | a_expr Op ALL '(' SubSelect ')' { - $$ = make3_str($1, $2, cat3_str("all (", $5, ")")); + $$ = cat3_str($1, $2, make3_str(make1_str("all ("), $5, make1_str(")"))); } | a_expr '+' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "+all(", $5, ")"); + $$ = make4_str($1, make1_str("+all("), $5, make1_str(")")); } | a_expr '-' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "-all(", $5, ")"); + $$ = make4_str($1, make1_str("-all("), $5, make1_str(")")); } | a_expr '/' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "/all(", $5, ")"); + $$ = make4_str($1, make1_str("/all("), $5, make1_str(")")); } | a_expr '*' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "*all(", $5, ")"); + $$ = make4_str($1, make1_str("*all("), $5, make1_str(")")); } | a_expr '<' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "<all(", $5, ")"); + $$ = make4_str($1, make1_str("<all("), $5, make1_str(")")); } | a_expr '>' ALL '(' SubSelect ')' { - $$ = cat4_str($1, ">all(", $5, ")"); + $$ = make4_str($1, make1_str(">all("), $5, make1_str(")")); } | a_expr '=' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "=all(", $5, ")"); + $$ = make4_str($1, make1_str("=all("), $5, make1_str(")")); } | a_expr AND a_expr - { $$ = make3_str($1, "and", $3); } + { $$ = cat3_str($1, make1_str("and"), $3); } | a_expr OR a_expr - { $$ = make3_str($1, "or", $3); } + { $$ = cat3_str($1, make1_str("or"), $3); } | NOT a_expr - { $$ = make2_str("not", $2); } + { $$ = cat2_str(make1_str("not"), $2); } | cinputvariable - { $$ = ";;"; } + { $$ = make1_str(";;"); } ; /* @@ -3206,7 +3281,7 @@ a_expr: attr opt_indirection b_expr: attr opt_indirection { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | AexprConst { $$ = $1; } @@ -3215,131 +3290,131 @@ b_expr: attr opt_indirection $$ = $1; } | '-' b_expr %prec UMINUS - { $$ = make2_str("-", $2); } + { $$ = cat2_str(make1_str("-"), $2); } | b_expr '+' b_expr - { $$ = make3_str($1, "+", $3); } + { $$ = cat3_str($1, make1_str("+"), $3); } | b_expr '-' b_expr - { $$ = make3_str($1, "-", $3); } + { $$ = cat3_str($1, make1_str("-"), $3); } | b_expr '/' b_expr - { $$ = make3_str($1, "/", $3); } + { $$ = cat3_str($1, make1_str("/"), $3); } | b_expr '*' b_expr - { $$ = make3_str($1, "*", $3); } + { $$ = cat3_str($1, make1_str("*"), $3); } /* not possible in embedded sql | ':' b_expr - { $$ = make2_str(":", $2); } + { $$ = cat2_str(make1_str(":"), $2); } */ | ';' b_expr - { $$ = make2_str(";", $2); } + { $$ = cat2_str(make1_str(";"), $2); } | '|' b_expr - { $$ = make2_str("|", $2); } + { $$ = cat2_str(make1_str("|"), $2); } | b_expr TYPECAST Typename { - $$ = make3_str($1, "::", $3); + $$ = cat3_str($1, make1_str("::"), $3); } | CAST '(' b_expr AS Typename ')' { - $$ = make3_str(cat2_str("cast(", $3), "as", cat2_str($5, ")")); + $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")"))); } | '(' a_expr ')' - { $$ = cat3_str("(", $2, ")"); } + { $$ = make3_str(make1_str("("), $2, make1_str(")")); } | b_expr Op b_expr - { $$ = make3_str($1, $2, $3); } + { $$ = cat3_str($1, $2, $3); } | Op b_expr - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | b_expr Op - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | func_name '(' ')' { - $$ = make2_str($1, "()"); + $$ = cat2_str($1, make1_str("()")); } | func_name '(' expr_list ')' { - $$ = cat4_str($1, "(", $3, ")"); + $$ = make4_str($1, make1_str("("), $3, make1_str(")")); } | CURRENT_DATE { - $$ = "current_date"; + $$ = make1_str("current_date"); } | CURRENT_TIME { - $$ = "current_time"; + $$ = make1_str("current_time"); } | CURRENT_TIME '(' Iconst ')' { if ($3 != 0) fprintf(stderr,"CURRENT_TIME(%s) precision not implemented; zero used instead", $3); - $$ = "current_time"; + $$ = make1_str("current_time"); } | CURRENT_TIMESTAMP { - $$ = "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); - $$ = "current_timestamp"; + $$ = make1_str("current_timestamp"); } | CURRENT_USER { - $$ = "current_user"; + $$ = make1_str("current_user"); } | POSITION '(' position_list ')' { - $$ = cat3_str("position (", $3, ")"); + $$ = make3_str(make1_str("position ("), $3, make1_str(")")); } | SUBSTRING '(' substr_list ')' { - $$ = cat3_str("substring (", $3, ")"); + $$ = make3_str(make1_str("substring ("), $3, make1_str(")")); } /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */ | TRIM '(' BOTH trim_list ')' { - $$ = cat3_str("trim(both", $4, ")"); + $$ = make3_str(make1_str("trim(both"), $4, make1_str(")")); } | TRIM '(' LEADING trim_list ')' { - $$ = cat3_str("trim(leading", $4, ")"); + $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")")); } | TRIM '(' TRAILING trim_list ')' { - $$ = cat3_str("trim(trailing", $4, ")"); + $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")")); } | TRIM '(' trim_list ')' { - $$ = cat3_str("trim(", $3, ")"); + $$ = make3_str(make1_str("trim("), $3, make1_str(")")); } | civariableonly - { $$ = ";;"; } + { $$ = make1_str(";;"); } ; opt_indirection: '[' c_expr ']' opt_indirection { - $$ = make4_str("[", $2, "]", $4); + $$ = cat4_str(make1_str("["), $2, make1_str("]"), $4); } | '[' c_expr ':' c_expr ']' opt_indirection { - $$ = make2_str(make5_str("[", $2, ":", $4, "]"), $6); + $$ = cat2_str(cat5_str(make1_str("["), $2, make1_str(":"), $4, make1_str("]")), $6); } | /* EMPTY */ - { $$ = ""; } + { $$ = make1_str(""); } ; expr_list: a_expr_or_null { $$ = $1; } | expr_list ',' a_expr_or_null - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } | expr_list USING a_expr - { $$ = make3_str($1, "using", $3); } + { $$ = cat3_str($1, make1_str("using"), $3); } ; extract_list: extract_arg FROM a_expr { - $$ = make3_str($1, "from", $3); + $$ = cat3_str($1, make1_str("from"), $3); } | /* EMPTY */ - { $$ = ""; } + { $$ = make1_str(""); } | cinputvariable - { $$ = ";;"; } + { $$ = make1_str(";;"); } ; /* Add in TIMEZONE_HOUR and TIMEZONE_MINUTE for SQL92 compliance @@ -3351,110 +3426,110 @@ extract_arg: datetime ; position_list: position_expr IN position_expr - { $$ = make3_str($1, "in", $3); } + { $$ = cat3_str($1, make1_str("in"), $3); } | /* EMPTY */ - { $$ = ""; } + { $$ = make1_str(""); } ; position_expr: attr opt_indirection { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | AexprConst { $$ = $1; } | '-' position_expr %prec UMINUS - { $$ = make2_str("-", $2); } + { $$ = cat2_str(make1_str("-"), $2); } | position_expr '+' position_expr - { $$ = make3_str($1, "+", $3); } + { $$ = cat3_str($1, make1_str("+"), $3); } | position_expr '-' position_expr - { $$ = make3_str($1, "-", $3); } + { $$ = cat3_str($1, make1_str("-"), $3); } | position_expr '/' position_expr - { $$ = make3_str($1, "/", $3); } + { $$ = cat3_str($1, make1_str("/"), $3); } | position_expr '*' position_expr - { $$ = make3_str($1, "*", $3); } + { $$ = cat3_str($1, make1_str("*"), $3); } | '|' position_expr - { $$ = make2_str("|", $2); } + { $$ = cat2_str(make1_str("|"), $2); } | position_expr TYPECAST Typename { - $$ = make3_str($1, "::", $3); + $$ = cat3_str($1, make1_str("::"), $3); } | CAST '(' position_expr AS Typename ')' { - $$ = make3_str(cat2_str("cast(", $3), "as", cat2_str($5, ")")); + $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")"))); } | '(' position_expr ')' - { $$ = cat3_str("(", $2, ")"); } + { $$ = make3_str(make1_str("("), $2, make1_str(")")); } | position_expr Op position_expr - { $$ = make3_str($1, $2, $3); } + { $$ = cat3_str($1, $2, $3); } | Op position_expr - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | position_expr Op - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | ColId { $$ = $1; } | func_name '(' ')' { - $$ = make2_str($1, "()"); + $$ = cat2_str($1, make1_str("()")); } | func_name '(' expr_list ')' { - $$ = cat4_str($1, "(", $3, ")"); + $$ = make4_str($1, make1_str("("), $3, make1_str(")")); } | POSITION '(' position_list ')' { - $$ = cat3_str("position(", $3, ")"); + $$ = make3_str(make1_str("position("), $3, make1_str(")")); } | SUBSTRING '(' substr_list ')' { - $$ = cat3_str("substring(", $3, ")"); + $$ = make3_str(make1_str("substring("), $3, make1_str(")")); } /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */ | TRIM '(' BOTH trim_list ')' { - $$ = cat3_str("trim(both", $4, ")"); + $$ = make3_str(make1_str("trim(both"), $4, make1_str(")")); } | TRIM '(' LEADING trim_list ')' { - $$ = cat3_str("trim(leading", $4, ")"); + $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")")); } | TRIM '(' TRAILING trim_list ')' { - $$ = cat3_str("trim(trailing", $4, ")"); + $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")")); } | TRIM '(' trim_list ')' { - $$ = cat3_str("trim(", $3, ")"); + $$ = make3_str(make1_str("trim("), $3, make1_str(")")); } ; substr_list: expr_list substr_from substr_for { - $$ = make3_str($1, $2, $3); + $$ = cat3_str($1, $2, $3); } | /* EMPTY */ - { $$ = ""; } + { $$ = make1_str(""); } ; substr_from: FROM expr_list - { $$ = make2_str("from", $2); } + { $$ = cat2_str(make1_str("from"), $2); } | /* EMPTY */ { - $$ = ""; + $$ = make1_str(""); } ; substr_for: FOR expr_list - { $$ = make2_str("for", $2); } + { $$ = cat2_str(make1_str("for"), $2); } | /* EMPTY */ - { $$ = ""; } + { $$ = make1_str(""); } ; trim_list: a_expr FROM expr_list - { $$ = make3_str($1, "from", $3); } + { $$ = cat3_str($1, make1_str("from"), $3); } | FROM expr_list - { $$ = make2_str("from", $2); } + { $$ = cat2_str(make1_str("from"), $2); } | expr_list { $$ = $1; } ; @@ -3470,7 +3545,7 @@ in_expr: SubSelect in_expr_nodes: AexprConst { $$ = $1; } | in_expr_nodes ',' AexprConst - { $$ = make3_str($1, ",", $3);} + { $$ = cat3_str($1, make1_str(","), $3);} ; not_in_expr: SubSelect @@ -3484,25 +3559,25 @@ not_in_expr: SubSelect not_in_expr_nodes: AexprConst { $$ = $1; } | not_in_expr_nodes ',' AexprConst - { $$ = make3_str($1, ",", $3);} + { $$ = cat3_str($1, make1_str(","), $3);} ; attr: relation_name '.' attrs { - $$ = cat3_str($1, ".", $3); + $$ = make3_str($1, make1_str("."), $3); } | ParamNo '.' attrs { - $$ = cat3_str($1, ".", $3); + $$ = make3_str($1, make1_str("."), $3); } ; attrs: attr_name { $$ = $1; } | attrs '.' attr_name - { $$ = cat3_str($1, ".", $3); } + { $$ = make3_str($1, make1_str("."), $3); } | attrs '.' '*' - { $$ = cat2_str($1, ".*"); } + { $$ = make2_str($1, make1_str(".*")); } ; @@ -3513,23 +3588,23 @@ attrs: attr_name *****************************************************************************/ res_target_list: res_target_list ',' res_target_el - { $$ = make3_str($1, ",",$3); } + { $$ = cat3_str($1, make1_str(","),$3); } | res_target_el { $$ = $1; } - | '*' { $$ = "*"; } + | '*' { $$ = make1_str("*"); } ; res_target_el: ColId opt_indirection '=' a_expr_or_null { - $$ = make4_str($1, $2, "=", $4); + $$ = cat4_str($1, $2, make1_str("="), $4); } | attr opt_indirection { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | relation_name '.' '*' { - $$ = cat2_str($1, ".*"); + $$ = make2_str($1, make1_str(".*")); } ; @@ -3539,7 +3614,7 @@ res_target_el: ColId opt_indirection '=' a_expr_or_null ** and update (uses a subset) */ res_target_list2: res_target_list2 ',' res_target_el2 - { $$ = make3_str($1, ",", $3); } + { $$ = cat3_str($1, make1_str(","), $3); } | res_target_el2 { $$ = $1; } ; @@ -3547,7 +3622,7 @@ res_target_list2: res_target_list2 ',' res_target_el2 /* AS is not optional because shift/red conflict with unary ops */ res_target_el2: a_expr_or_null AS ColLabel { - $$ = make3_str($1, "as", $3); + $$ = cat3_str($1, make1_str("as"), $3); } | a_expr_or_null { @@ -3555,16 +3630,16 @@ res_target_el2: a_expr_or_null AS ColLabel } | relation_name '.' '*' { - $$ = cat2_str($1, ".*"); + $$ = make2_str($1, make1_str(".*")); } | '*' { - $$ = "*"; + $$ = make1_str("*"); } ; opt_id: ColId { $$ = $1; } - | /* EMPTY */ { $$ = ""; } + | /* EMPTY */ { $$ = make1_str(""); } ; relation_name: SpecialRuleRelation @@ -3576,7 +3651,7 @@ relation_name: SpecialRuleRelation /* disallow refs to variable system tables */ if (strcmp(LogRelationName, $1) == 0 || strcmp(VariableRelationName, $1) == 0) { - sprintf(errortext, "%s cannot be accessed by users",$1); + sprintf(errortext, make1_str("%s cannot be accessed by users"),$1); yyerror(errortext); } else @@ -3617,17 +3692,17 @@ AexprConst: Iconst } | Typename Sconst { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | ParamNo { $$ = $1; } | TRUE_P { - $$ = "true"; + $$ = make1_str("true"); } | FALSE_P { - $$ = "false"; + $$ = make1_str("false"); } ; @@ -3673,37 +3748,37 @@ TypeId: ColId */ ColId: ecpg_ident { $$ = $1; } | datetime { $$ = $1; } - | ACTION { $$ = "action"; } - | CACHE { $$ = "cache"; } - | CYCLE { $$ = "cycle"; } - | DATABASE { $$ = "database"; } - | DELIMITERS { $$ = "delimiters"; } - | DOUBLE { $$ = "double"; } - | EACH { $$ = "each"; } - | FUNCTION { $$ = "function"; } - | INCREMENT { $$ = "increment"; } - | INDEX { $$ = "index"; } - | KEY { $$ = "key"; } - | LANGUAGE { $$ = "language"; } - | LOCATION { $$ = "location"; } - | MATCH { $$ = "match"; } - | MAXVALUE { $$ = "maxvalue"; } - | MINVALUE { $$ = "minvalue"; } - | OPERATOR { $$ = "operator"; } - | OPTION { $$ = "option"; } - | PASSWORD { $$ = "password"; } - | PRIVILEGES { $$ = "privileges"; } - | RECIPE { $$ = "recipe"; } - | ROW { $$ = "row"; } - | START { $$ = "start"; } - | STATEMENT { $$ = "statement"; } - | TIME { $$ = "time"; } - | TRIGGER { $$ = "trigger"; } - | TYPE_P { $$ = "type"; } - | USER { $$ = "user"; } - | VALID { $$ = "valid"; } - | VERSION { $$ = "version"; } - | ZONE { $$ = "zone"; } + | ACTION { $$ = make1_str("action"); } + | CACHE { $$ = make1_str("cache"); } + | CYCLE { $$ = make1_str("cycle"); } + | DATABASE { $$ = make1_str("database"); } + | DELIMITERS { $$ = make1_str("delimiters"); } + | DOUBLE { $$ = make1_str("double"); } + | EACH { $$ = make1_str("each"); } + | FUNCTION { $$ = make1_str("function"); } + | INCREMENT { $$ = make1_str("increment"); } + | INDEX { $$ = make1_str("index"); } + | KEY { $$ = make1_str("key"); } + | LANGUAGE { $$ = make1_str("language"); } + | LOCATION { $$ = make1_str("location"); } + | MATCH { $$ = make1_str("match"); } + | MAXVALUE { $$ = make1_str("maxvalue"); } + | MINVALUE { $$ = make1_str("minvalue"); } + | OPERATOR { $$ = make1_str("operator"); } + | OPTION { $$ = make1_str("option"); } + | PASSWORD { $$ = make1_str("password"); } + | PRIVILEGES { $$ = make1_str("privileges"); } + | RECIPE { $$ = make1_str("recipe"); } + | ROW { $$ = make1_str("row"); } + | START { $$ = make1_str("start"); } + | STATEMENT { $$ = make1_str("statement"); } + | TIME { $$ = make1_str("time"); } + | TRIGGER { $$ = make1_str("trigger"); } + | TYPE_P { $$ = make1_str("type"); } + | USER { $$ = make1_str("user"); } + | VALID { $$ = make1_str("valid"); } + | VERSION { $$ = make1_str("version"); } + | ZONE { $$ = make1_str("zone"); } ; /* Column label @@ -3717,33 +3792,33 @@ ColId: ecpg_ident { $$ = $1; } * when used as a full identifier. - thomas 1997-11-06 */ ColLabel: ColId { $$ = $1; } - | ARCHIVE { $$ = "archive"; } - | CLUSTER { $$ = "cluster"; } - | CONSTRAINT { $$ = "constraint"; } - | CROSS { $$ = "cross"; } - | FOREIGN { $$ = "foreign"; } - | GROUP { $$ = "group"; } - | LOAD { $$ = "load"; } - | ORDER { $$ = "order"; } - | POSITION { $$ = "position"; } - | PRECISION { $$ = "precision"; } - | TABLE { $$ = "table"; } - | TRANSACTION { $$ = "transaction"; } - | TRUE_P { $$ = "true"; } - | FALSE_P { $$ = "false"; } + | ARCHIVE { $$ = make1_str("archive"); } + | CLUSTER { $$ = make1_str("cluster"); } + | CONSTRAINT { $$ = make1_str("constraint"); } + | CROSS { $$ = make1_str("cross"); } + | FOREIGN { $$ = make1_str("foreign"); } + | GROUP { $$ = make1_str("group"); } + | LOAD { $$ = make1_str("load"); } + | ORDER { $$ = make1_str("order"); } + | POSITION { $$ = make1_str("position"); } + | PRECISION { $$ = make1_str("precision"); } + | TABLE { $$ = make1_str("table"); } + | TRANSACTION { $$ = make1_str("transaction"); } + | TRUE_P { $$ = make1_str("true"); } + | FALSE_P { $$ = make1_str("false"); } ; SpecialRuleRelation: CURRENT { if (QueryIsRule) - $$ = "current"; + $$ = make1_str("current"); else yyerror("CURRENT used in non-rule query"); } | NEW { if (QueryIsRule) - $$ = "new"; + $$ = make1_str("new"); else yyerror("NEW used in non-rule query"); } @@ -3780,31 +3855,37 @@ declaration: storage_clause type } 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 */ { $$ = "" ; } +storage_clause : S_EXTERN { $$ = make1_str("extern"); } + | S_STATIC { $$ = make1_str("static"); } + | S_SIGNED { $$ = make1_str("signed"); } + | S_CONST { $$ = make1_str("const"); } + | S_REGISTER { $$ = make1_str("register"); } + | S_AUTO { $$ = make1_str("auto"); } + | /* empty */ { $$ = make1_str("") ; } type: simple_type | struct_type struct_type: s_struct '{' variable_declarations '}' { - struct_level--; + ECPGfree_struct_member(struct_member_list[struct_level]); + free(actual_storage[struct_level--]); fputs("} ", yyout); $$ = ECPGt_struct; } -s_struct : S_STRUCT symbol - { - struct_member_list[struct_level] = NULL; - struct_level++; - fprintf(yyout, "struct %s {", $2); +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; } @@ -3827,72 +3908,122 @@ variable_list: variable fputs(";\n ", yyout); } variable -variable: opt_pointer symbol opt_index opt_initializer +variable: opt_pointer symbol opt_array_bounds opt_initializer { - int length = $3.ival; - - /* pointer has to get length 0 */ - if (strlen($1) > 0) - length = 0; + 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: - if (struct_level == 0) - new_variable($2, ECPGmake_struct_type(struct_member_list[struct_level])); - else - ECPGmake_struct_member($2, ECPGmake_struct_type(struct_member_list[struct_level]), &(struct_member_list[struct_level-1])); - - fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4); - - break; - case ECPGt_varchar: - if (strlen($4) != 0) - yyerror("varchar initilization impossible"); - - if (struct_level == 0) - new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length)); - else - ECPGmake_struct_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1])); - - if (length > 0) - fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2); - else - fprintf(yyout, "%s struct varchar_%s { int len; char arr[]; } %s", actual_storage[struct_level], $2, $2); - - break; - - default: - if (struct_level == 0) - new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length)); - else - ECPGmake_struct_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1])); - - fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4); - - break; + /* 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 */ { $$ = ""; } - | '=' vartext { $$ = cat2_str("=", $2); } +opt_initializer: /* empty */ { $$ = make1_str(""); } + | '=' vartext { $$ = make2_str(make1_str("="), $2); } -opt_pointer: /* empty */ { $$ = ""; } - | '*' { $$ = "*"; } - -opt_index: '[' Iconst ']' { - $$.ival = atol($2); - $$.str = cat3_str("[", $2, "]"); - } - | '[' ']' - { - $$.ival = 0; - $$.str = "[]"; - } - | /* empty */ { - $$.ival = 1; - $$.str = ""; - } +opt_pointer: /* empty */ { $$ = make1_str(""); } + | '*' { $$ = make1_str("*"); } /* * the exec sql connect statement: connect to the given database @@ -3913,10 +4044,35 @@ db_name: database_name { $$ = $1; } $$ = $1; } +/* + * the exec sql disconnect statement: disconnect from the given database + */ +ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; } + +dis_name: database_name { $$ = $1; } + | cvariable { /* check if we have a char variable */ + struct variable *p = find_variable($1); + enum ECPGttype typ = p->type->typ; + + /* if array see what's inside */ + if (typ == ECPGt_array) + typ = p->type->u.element->typ; + + if (typ != ECPGt_char && typ != ECPGt_unsigned_char) + yyerror("invalid datatype"); + $$ = $1; + } + | CURRENT { $$ = make1_str(""); } + | DEFAULT { $$ = make1_str(""); } + | ALL { $$ = make1_str(""); } + | /* empty */ { $$ = make1_str(""); } + /* * execute a given string as sql command */ -ECPGExecute : EXECUTE SQL_IMMEDIATE cvariable { $$ = $3; }; +ECPGExecute : EXECUTE SQL_IMMEDIATE execstring { $$ = $3; }; + +execstring: cvariable | CSTRING; /* * open is an open cursor, at the moment this has to be removed @@ -3940,11 +4096,28 @@ ECPGOpen: SQL_OPEN name open_opts { } }; -open_opts: /* empty */ { $$ = ""; } +open_opts: /* empty */ { $$ = make1_str(""); } | USING cvariable { yyerror ("open cursor with variables not implemented yet"); } +/* + * 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 (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); + } + /* * whenever statement: decide what to do in case of error/no data found * according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION @@ -3954,55 +4127,60 @@ open_opts: /* empty */ { $$ = ""; } ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action { when_error.code = $<action>3.code; when_error.command = $<action>3.command; - $$ = make3_str("/* exec sql whenever sqlerror ", $3.str, "; */\n"); + $$ = cat3_str(make1_str("/* exec sql whenever sqlerror "), $3.str, make1_str("; */\n")); } | SQL_WHENEVER NOT SQL_FOUND action { when_nf.code = $<action>4.code; when_nf.command = $<action>4.command; - $$ = make3_str("/* exec sql whenever not found ", $4.str, "; */\n"); + $$ = cat3_str(make1_str("/* exec sql whenever not found "), $4.str, make1_str("; */\n")); } action : SQL_CONTINUE { $<action>$.code = W_NOTHING; $<action>$.command = NULL; - $<action>$.str = "continue"; + $<action>$.str = make1_str("continue"); } | SQL_SQLPRINT { $<action>$.code = W_SQLPRINT; $<action>$.command = NULL; - $<action>$.str = "sqlprint"; + $<action>$.str = make1_str("sqlprint"); } | SQL_STOP { $<action>$.code = W_STOP; $<action>$.command = NULL; - $<action>$.str = "stop"; + $<action>$.str = make1_str("stop"); } | SQL_GOTO name { $<action>$.code = W_GOTO; $<action>$.command = $2; - $<action>$.str = make2_str("goto ", $2); + $<action>$.str = cat2_str(make1_str("goto "), $2); } | SQL_GO TO name { $<action>$.code = W_GOTO; $<action>$.command = $3; - $<action>$.str = make2_str("goto ", $3); + $<action>$.str = cat2_str(make1_str("goto "), $3); } | DO name '(' dotext ')' { $<action>$.code = W_DO; - $<action>$.command = cat4_str($2, "(", $4, ")"); - $<action>$.str = make2_str("do", $<action>$.command); + $<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")")); + $<action>$.str = cat2_str(make1_str("do"), $<action>$.command); +} + | DO SQL_BREAK { + $<action>$.code = W_BREAK; + $<action>$.command = NULL; + $<action>$.str = make1_str("break"); } | SQL_CALL name '(' dotext ')' { $<action>$.code = W_DO; - $<action>$.command = cat4_str($2, "(", $4, ")"); - $<action>$.str = make2_str("call", $<action>$.command); + $<action>$.command = make4_str($2, make1_str("("), $4, make1_str(")")); + $<action>$.str = cat2_str(make1_str("call"), $<action>$.command); } /* some other stuff for ecpg */ c_expr: attr opt_indirection { - $$ = make2_str($1, $2); + $$ = cat2_str($1, $2); } | row_expr { $$ = $1; } @@ -4013,128 +4191,128 @@ c_expr: attr opt_indirection $$ = $1; } | '-' c_expr %prec UMINUS - { $$ = make2_str("-", $2); } + { $$ = cat2_str(make1_str("-"), $2); } | a_expr '+' c_expr - { $$ = make3_str($1, "+", $3); } + { $$ = cat3_str($1, make1_str("+"), $3); } | a_expr '-' c_expr - { $$ = make3_str($1, "-", $3); } + { $$ = cat3_str($1, make1_str("-"), $3); } | a_expr '/' c_expr - { $$ = make3_str($1, "/", $3); } + { $$ = cat3_str($1, make1_str("/"), $3); } | a_expr '*' c_expr - { $$ = make3_str($1, "*", $3); } + { $$ = cat3_str($1, make1_str("*"), $3); } | a_expr '<' c_expr - { $$ = make3_str($1, "<", $3); } + { $$ = cat3_str($1, make1_str("<"), $3); } | a_expr '>' c_expr - { $$ = make3_str($1, ">", $3); } + { $$ = cat3_str($1, make1_str(">"), $3); } | a_expr '=' c_expr - { $$ = make3_str($1, "=", $3); } + { $$ = cat3_str($1, make1_str("="), $3); } /* | ':' c_expr - { $$ = make2_str(":", $2); }*/ + { $$ = cat2_str(make1_str(":"), $2); }*/ | ';' c_expr - { $$ = make2_str(";", $2); } + { $$ = cat2_str(make1_str(";"), $2); } | '|' c_expr - { $$ = make2_str("|", $2); } + { $$ = cat2_str(make1_str("|"), $2); } | a_expr TYPECAST Typename { - $$ = make3_str($1, "::", $3); + $$ = cat3_str($1, make1_str("::"), $3); } | CAST '(' a_expr AS Typename ')' { - $$ = make3_str(cat2_str("cast(", $3), "as", cat2_str($5, ")")); + $$ = cat3_str(make2_str(make1_str("cast("), $3), make1_str("as"), make2_str($5, make1_str(")"))); } | '(' a_expr_or_null ')' - { $$ = cat3_str("(", $2, ")"); } + { $$ = make3_str(make1_str("("), $2, make1_str(")")); } | a_expr Op c_expr - { $$ = make3_str($1, $2, $3); } + { $$ = cat3_str($1, $2, $3); } | a_expr LIKE c_expr - { $$ = make3_str($1, "like", $3); } + { $$ = cat3_str($1, make1_str("like"), $3); } | a_expr NOT LIKE c_expr - { $$ = make3_str($1, "not like", $4); } + { $$ = cat3_str($1, make1_str("not like"), $4); } | Op c_expr - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | a_expr Op - { $$ = make2_str($1, $2); } + { $$ = cat2_str($1, $2); } | func_name '(' '*' ')' { - $$ = make2_str($1, "(*)"); + $$ = cat2_str($1, make1_str("(*)")); } | func_name '(' ')' { - $$ = make2_str($1, "()"); + $$ = cat2_str($1, make1_str("()")); } | func_name '(' expr_list ')' { - $$ = cat4_str($1, "(", $3, ")"); + $$ = make4_str($1, make1_str("("), $3, make1_str(")")); } | CURRENT_DATE { - $$ = "current_date"; + $$ = make1_str("current_date"); } | CURRENT_TIME { - $$ = "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); - $$ = "current_time"; + $$ = make1_str("current_time"); } | CURRENT_TIMESTAMP { - $$ = "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); - $$ = "current_timestamp"; + $$ = make1_str("current_timestamp"); } | CURRENT_USER { - $$ = "current_user"; + $$ = make1_str("current_user"); } | EXISTS '(' SubSelect ')' { - $$ = cat3_str("exists(", $3, ")"); + $$ = make3_str(make1_str("exists("), $3, make1_str(")")); } | EXTRACT '(' extract_list ')' { - $$ = cat3_str("extract(", $3, ")"); + $$ = make3_str(make1_str("extract("), $3, make1_str(")")); } | POSITION '(' position_list ')' { - $$ = cat3_str("position(", $3, ")"); + $$ = make3_str(make1_str("position("), $3, make1_str(")")); } | SUBSTRING '(' substr_list ')' { - $$ = cat3_str("substring(", $3, ")"); + $$ = make3_str(make1_str("substring("), $3, make1_str(")")); } /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */ | TRIM '(' BOTH trim_list ')' { - $$ = cat3_str("trim(both", $4, ")"); + $$ = make3_str(make1_str("trim(both"), $4, make1_str(")")); } | TRIM '(' LEADING trim_list ')' { - $$ = cat3_str("trim(leading", $4, ")"); + $$ = make3_str(make1_str("trim(leading"), $4, make1_str(")")); } | TRIM '(' TRAILING trim_list ')' { - $$ = cat3_str("trim(trailing", $4, ")"); + $$ = make3_str(make1_str("trim(trailing"), $4, make1_str(")")); } | TRIM '(' trim_list ')' { - $$ = cat3_str("trim(", $3, ")"); + $$ = make3_str(make1_str("trim("), $3, make1_str(")")); } | a_expr ISNULL - { $$ = make2_str($1, "isnull"); } + { $$ = cat2_str($1, make1_str("isnull")); } | a_expr IS NULL_P - { $$ = make2_str($1, "is null"); } + { $$ = cat2_str($1, make1_str("is null")); } | a_expr NOTNULL - { $$ = make2_str($1, "notnull"); } + { $$ = cat2_str($1, make1_str("notnull")); } | a_expr IS NOT NULL_P - { $$ = make2_str($1, "is not null"); } + { $$ = 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. @@ -4142,152 +4320,151 @@ c_expr: attr opt_indirection */ | a_expr IS TRUE_P { - { $$ = make2_str($1, "is true"); } + { $$ = cat2_str($1, make1_str("is true")); } } | a_expr IS NOT FALSE_P { - { $$ = make2_str($1, "is not false"); } + { $$ = cat2_str($1, make1_str("is not false")); } } | a_expr IS FALSE_P { - { $$ = make2_str($1, "is false"); } + { $$ = cat2_str($1, make1_str("is false")); } } | a_expr IS NOT TRUE_P { - { $$ = make2_str($1, "is not true"); } + { $$ = cat2_str($1, make1_str("is not true")); } } | a_expr BETWEEN b_expr AND b_expr { - $$ = make5_str($1, "between", $3, "and", $5); + $$ = cat5_str($1, make1_str("between"), $3, make1_str("and"), $5); } | a_expr NOT BETWEEN b_expr AND b_expr { - $$ = make5_str($1, "not between", $4, "and", $6); + $$ = cat5_str($1, make1_str("not between"), $4, make1_str("and"), $6); } | a_expr IN '(' in_expr ')' { - $$ = cat4_str($1, "in (", $4, ")"); + $$ = make4_str($1, make1_str("in ("), $4, make1_str(")")); } | a_expr NOT IN '(' not_in_expr ')' { - $$ = cat4_str($1, "not in (", $5, ")"); + $$ = make4_str($1, make1_str("not in ("), $5, make1_str(")")); } | a_expr Op '(' SubSelect ')' { - $$ = make3_str($1, $2, cat3_str("(", $4, -")")); + $$ = cat3_str($1, $2, make3_str(make1_str("("), $4, make1_str(")"))); } | a_expr '+' '(' SubSelect ')' { - $$ = cat4_str($1, "+(", $4, ")"); + $$ = make4_str($1, make1_str("+("), $4, make1_str(")")); } | a_expr '-' '(' SubSelect ')' { - $$ = cat4_str($1, "-(", $4, ")"); + $$ = make4_str($1, make1_str("-("), $4, make1_str(")")); } | a_expr '/' '(' SubSelect ')' { - $$ = cat4_str($1, "/(", $4, ")"); + $$ = make4_str($1, make1_str("/("), $4, make1_str(")")); } | a_expr '*' '(' SubSelect ')' { - $$ = cat4_str($1, "*(", $4, ")"); + $$ = make4_str($1, make1_str("*("), $4, make1_str(")")); } | a_expr '<' '(' SubSelect ')' { - $$ = cat4_str($1, "<(", $4, ")"); + $$ = make4_str($1, make1_str("<("), $4, make1_str(")")); } | a_expr '>' '(' SubSelect ')' { - $$ = cat4_str($1, ">(", $4, ")"); + $$ = make4_str($1, make1_str(">("), $4, make1_str(")")); } | a_expr '=' '(' SubSelect ')' { - $$ = cat4_str($1, "=(", $4, ")"); + $$ = make4_str($1, make1_str("=("), $4, make1_str(")")); } | a_expr Op ANY '(' SubSelect ')' { - $$ = make3_str($1, $2, cat3_str("any (", $5, ")")); + $$ = cat3_str($1, $2, make3_str(make1_str("any ("), $5, make1_str(")"))); } | a_expr '+' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "+any(", $5, ")"); + $$ = make4_str($1, make1_str("+any("), $5, make1_str(")")); } | a_expr '-' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "-any(", $5, ")"); + $$ = make4_str($1, make1_str("-any("), $5, make1_str(")")); } | a_expr '/' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "/any(", $5, ")"); + $$ = make4_str($1, make1_str("/any("), $5, make1_str(")")); } | a_expr '*' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "*any(", $5, ")"); + $$ = make4_str($1, make1_str("*any("), $5, make1_str(")")); } | a_expr '<' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "<any(", $5, ")"); + $$ = make4_str($1, make1_str("<any("), $5, make1_str(")")); } | a_expr '>' ANY '(' SubSelect ')' { - $$ = cat4_str($1, ">any(", $5, ")"); + $$ = make4_str($1, make1_str(">any("), $5, make1_str(")")); } | a_expr '=' ANY '(' SubSelect ')' { - $$ = cat4_str($1, "=any(", $5, ")"); + $$ = make4_str($1, make1_str("=any("), $5, make1_str(")")); } | a_expr Op ALL '(' SubSelect ')' { - $$ = cat3_str($1, $2, cat3_str("all (", $5, ")")); + $$ = make3_str($1, $2, make3_str(make1_str("all ("), $5, make1_str(")"))); } | a_expr '+' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "+all(", $5, ")"); + $$ = make4_str($1, make1_str("+all("), $5, make1_str(")")); } | a_expr '-' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "-all(", $5, ")"); + $$ = make4_str($1, make1_str("-all("), $5, make1_str(")")); } | a_expr '/' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "/all(", $5, ")"); + $$ = make4_str($1, make1_str("/all("), $5, make1_str(")")); } | a_expr '*' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "*all(", $5, ")"); + $$ = make4_str($1, make1_str("*all("), $5, make1_str(")")); } | a_expr '<' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "<all(", $5, ")"); + $$ = make4_str($1, make1_str("<all("), $5, make1_str(")")); } | a_expr '>' ALL '(' SubSelect ')' { - $$ = cat4_str($1, ">all(", $5, ")"); + $$ = make4_str($1, make1_str(">all("), $5, make1_str(")")); } | a_expr '=' ALL '(' SubSelect ')' { - $$ = cat4_str($1, "=all(", $5, ")"); + $$ = make4_str($1, make1_str("=all("), $5, make1_str(")")); } | a_expr AND c_expr - { $$ = make3_str($1, "and", $3); } + { $$ = cat3_str($1, make1_str("and"), $3); } | a_expr OR c_expr - { $$ = make3_str($1, "or", $3); } + { $$ = cat3_str($1, make1_str("or"), $3); } | NOT c_expr - { $$ = make2_str("not", $2); } + { $$ = cat2_str(make1_str("not"), $2); } | civariableonly - { $$ = ";;"; } + { $$ = make1_str(";;"); } ; into_list : coutputvariable | into_list ',' coutputvariable; ecpgstart: SQL_START { reset_variables();} -dotext: /* empty */ { $$ = ""; } - | dotext sql_anything { $$ = cat2_str($1, $2); } +dotext: /* empty */ { $$ = make1_str(""); } + | dotext sql_anything { $$ = make2_str($1, $2); } vartext: var_anything { $$ = $1; } - | vartext var_anything { $$ = cat2_str($1, $2); } + | vartext var_anything { $$ = make2_str($1, $2); } coutputvariable : cvariable indicator { add_variable(&argsresult, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2)); @@ -4302,20 +4479,14 @@ civariableonly : cvariable name { } cvariable: CVARIABLE { $$ = $1; } - | CVARIABLE '.' identlist { $$ = cat3_str($1, ".", $3); } - | CVARIABLE S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); } - -identlist: IDENT { $$ = $1; } - | IDENT '.' identlist { $$ = cat3_str($1, ".", $3); } - | IDENT S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); } indicator: /* empty */ { $$ = NULL; } - | cvariable { printf("## %s\n", $1); check_indicator((find_variable($1))->type); $$ = $1; } + | cvariable { check_indicator((find_variable($1))->type); $$ = $1; } | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; } | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } ecpg_ident: IDENT { $$ = $1; } - | CSTRING { $$ = cat3_str("\"", $1, "\""); } + | CSTRING { $$ = make3_str(make1_str("\""), $1, make1_str("\"")); } /* * C stuff */ @@ -4325,52 +4496,52 @@ symbol: ecpg_ident { $$ = $1; } c_anything: ecpg_ident { $$ = $1; } | Iconst { $$ = $1; } | FCONST { $$ = make_name(); } - | '*' { $$ = "*"; } - | ';' { $$ = ";"; } - | S_AUTO { $$ = "auto"; } - | S_BOOL { $$ = "bool"; } - | S_CHAR { $$ = "char"; } - | S_CONST { $$ = "const"; } - | S_DOUBLE { $$ = "double"; } - | S_EXTERN { $$ = "extern"; } - | S_FLOAT { $$ = "float"; } - | S_INT { $$ = "int"; } - | S_LONG { $$ = "long"; } - | S_REGISTER { $$ = "register"; } - | S_SHORT { $$ = "short"; } - | S_SIGNED { $$ = "signed"; } - | S_STATIC { $$ = "static"; } - | S_STRUCT { $$ = "struct"; } - | S_UNSIGNED { $$ = "unsigned"; } - | S_VARCHAR { $$ = "varchar"; } + | '*' { $$ = make1_str("*"); } + | ';' { $$ = 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"); } | S_ANYTHING { $$ = make_name(); } - | '[' { $$ = "["; } - | ']' { $$ = "]"; } - | '(' { $$ = "("; } - | ')' { $$ = ")"; } - | '=' { $$ = "="; } - | ',' { $$ = ","; } + | '[' { $$ = make1_str("["); } + | ']' { $$ = make1_str("]"); } + | '(' { $$ = make1_str("("); } + | ')' { $$ = make1_str(")"); } + | '=' { $$ = make1_str("="); } + | ',' { $$ = make1_str(","); } sql_anything: ecpg_ident { $$ = $1; } | Iconst { $$ = $1; } | FCONST { $$ = make_name(); } - | ',' { $$ = ","; } + | ',' { $$ = make1_str(","); } var_anything: ecpg_ident { $$ = $1; } | Iconst { $$ = $1; } | FCONST { $$ = make_name(); } -/*FIXME: | ',' { $$ = ","; }*/ - | '{' { $$ = "{"; } - | '}' { $$ = "}"; } +/*FIXME: | ',' { $$ = make1_str(","); }*/ + | '{' { $$ = make1_str("{"); } + | '}' { $$ = make1_str("}"); } blockstart : '{' { braces_open++; - $$ = "{"; + $$ = make1_str("{"); } blockend : '}' { remove_variables(braces_open--); - $$ = "}"; + $$ = make1_str("}"); } %% @@ -4378,5 +4549,5 @@ blockend : '}' { void yyerror(char * error) { fprintf(stderr, "%s in line %d\n", error, yylineno); - exit(1); + exit(PARSE_ERROR); } diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index b3430991cf69504d43df0c1cb8ce722b050dffbb..cbc7446909e37a12944ba6d6afe3e58c5fe3a6f2 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -14,7 +14,7 @@ mm_alloc(size_t size) if (ptr == NULL) { fprintf(stderr, "Out of memory\n"); - exit(1); + exit(OUT_OF_MEMORY); } return (ptr); @@ -29,15 +29,27 @@ mm_realloc(void *ptr, size_t size) if (ptr == NULL) { fprintf(stderr, "Out of memory\n"); - exit(1); + exit(OUT_OF_MEMORY); } return (ptr); } -/* Constructors - Yes, I mostly write c++-code - */ +/* duplicate memberlist */ +static struct ECPGstruct_member * +struct_member_dup(struct ECPGstruct_member * rm) +{ + struct ECPGstruct_member *new = NULL; + + while (rm) + { + ECPGmake_struct_member(rm->name, rm->typ, &new); + + rm = rm->next; + } + + return(new); +} /* The NAME argument is copied. The type argument is preserved as a pointer. */ struct ECPGstruct_member * @@ -72,22 +84,11 @@ ECPGmake_simple_type(enum ECPGttype typ, long siz) return ne; } -struct ECPGtype * -ECPGmake_varchar_type(enum ECPGttype typ, long siz) -{ - struct ECPGtype *ne = ECPGmake_simple_type(typ, 1); - - ne->size = siz; - - return ne; -} - struct ECPGtype * ECPGmake_array_type(struct ECPGtype * typ, long siz) { struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, siz); - ne->size = siz; ne->u.element = typ; return ne; @@ -98,11 +99,57 @@ ECPGmake_struct_type(struct ECPGstruct_member * rm) { struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1); - ne->u.members = rm; + ne->u.members = struct_member_dup(rm); return ne; } +static const char *get_type(enum ECPGttype typ) +{ + switch (typ) + { + case ECPGt_char: + return("ECPGt_char"); + break; + case ECPGt_unsigned_char: + return("ECPGt_unsigned_char"); + break; + case ECPGt_short: + return("ECPGt_short"); + break; + case ECPGt_unsigned_short: + return("ECPGt_unsigned_short"); + break; + case ECPGt_int: + return("ECPGt_int"); + break; + case ECPGt_unsigned_int: + return("ECPGt_unsigned_int"); + break; + case ECPGt_long: + return("ECPGt_long"); + break; + case ECPGt_unsigned_long: + return("ECPGt_unsigned_int"); + break; + case ECPGt_float: + return("ECPGt_float"); + break; + case ECPGt_double: + return("ECPGt_double"); + break; + case ECPGt_bool: + return("ECPGt_bool"); + break; + case ECPGt_varchar: + return("ECPGt_varchar"); + case ECPGt_NO_INDICATOR: /* no indicator */ + return("ECPGt_NO_INDICATOR"); + break; + default: + abort(); + } +} /* Dump a type. The type is dumped as: @@ -136,41 +183,40 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in ind_name = "no_indicator"; } - if (IS_SIMPLE_TYPE(typ->typ)) - { - ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix); - ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, 0, 0, ind_prefix); - } - else if (typ->typ == ECPGt_array) - { - if (IS_SIMPLE_TYPE(typ->u.element->typ)) - { - ECPGdump_a_simple(o, name, typ->u.element->typ, - typ->u.element->size, typ->size, 0, prefix); - ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ, - ind_typ->u.element->size, ind_typ->size, 0, prefix); - } - else if (typ->u.element->typ == ECPGt_array) - { - abort(); /* Array of array, */ - } - else if (typ->u.element->typ == ECPGt_struct) - { - /* Array of structs. */ - ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix); - } - else - { - abort(); - } - } - else if (typ->typ == ECPGt_struct) - { - ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix); - } - else - { - abort(); + switch(typ->typ) + { + case ECPGt_array: + if (IS_SIMPLE_TYPE(typ->u.element->typ)) + { + ECPGdump_a_simple(o, name, typ->u.element->typ, + typ->u.element->size, typ->size, NULL, prefix); + if (ind_typ == &ecpg_no_indicator) + ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); + else + ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ, + ind_typ->u.element->size, ind_typ->size, NULL, prefix); + } + else if (typ->u.element->typ == ECPGt_array) + { + yyerror("No nested arrays allowed (except strings)"); /* Array of array, */ + } + else if (typ->u.element->typ == ECPGt_struct) + { + /* Array of structs. */ + ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, NULL, prefix, ind_prefix); + } + else + { + yyerror("Internal error: unknown datatype, pleqase inform pgsql-bugs@postgresql.org"); + } + break; + case ECPGt_struct: + ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix); + break; + default: + ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix); + ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); + break; } } @@ -180,86 +226,48 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, long varcharsize, - long arrsiz, + long arrsize, const char *siz, const char *prefix ) { - switch (typ) - { - case ECPGt_char: - if (varcharsize == 0) /* pointer */ - fprintf(o, "\n\tECPGt_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, - siz == NULL ? "sizeof(char)" : siz); - else - fprintf(o, "\n\tECPGt_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, - siz == NULL ? "sizeof(char)" : siz); - break; - case ECPGt_unsigned_char: - if (varcharsize == 0) /* pointer */ - fprintf(o, "\n\tECPGt_unsigned_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, - siz == NULL ? "sizeof(char)" : siz); - else - fprintf(o, "\n\tECPGt_unsigned_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, - siz == NULL ? "sizeof(unsigned char)" : siz); - break; - case ECPGt_short: - fprintf(o, "\n\tECPGt_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(short)" : siz); - break; - case ECPGt_unsigned_short: - fprintf(o, - "\n\tECPGt_unsigned_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(unsigned short)" : siz); - break; - case ECPGt_int: - fprintf(o, "\n\tECPGt_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(int)" : siz); - break; - case ECPGt_unsigned_int: - fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(unsigned int)" : siz); - break; - case ECPGt_long: - fprintf(o, "\n\tECPGt_long,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(long)" : siz); - break; - case ECPGt_unsigned_long: - fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(unsigned int)" : siz); - break; - case ECPGt_float: - fprintf(o, "\n\tECPGt_float,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(float)" : siz); - break; - case ECPGt_double: - fprintf(o, "\n\tECPGt_double,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(double)" : siz); - break; - case ECPGt_bool: - fprintf(o, "\n\tECPGt_bool,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, - siz == NULL ? "sizeof(bool)" : siz); - break; - case ECPGt_varchar: - case ECPGt_varchar2: - if (siz == NULL) - fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,sizeof(struct varchar_%s), ", - prefix ? prefix : "", name, - varcharsize, - arrsiz, name); - else - fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,%s, ", - prefix ? prefix : "", name, - varcharsize, - arrsiz, siz); - break; - case ECPGt_NO_INDICATOR: /* no indicator */ - fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, "); - break; - default: - abort(); + if (typ == ECPGt_NO_INDICATOR) + fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, "); + else + { + char *variable = (char *)mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4); + char *offset = (char *)mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1); + + if (varcharsize == 0 || arrsize >= 0) + sprintf(variable, "(%s%s)", prefix ? prefix : "", name); + else + sprintf(variable, "&(%s%s)", prefix ? prefix : "", name); + + switch (typ) + { + case ECPGt_varchar: + sprintf(offset, "sizeof(struct varchar_%s)", name); + break; + case ECPGt_char: + case ECPGt_unsigned_char: + sprintf(offset, "%ld*sizeof(char)", varcharsize); + break; + default: + sprintf(offset, "sizeof(%s)", ECPGtype_name(typ)); + break; } - + + if (arrsize < 0) + arrsize = 1; + + if (siz == NULL) + fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(typ), variable, varcharsize, arrsize, offset); + else + fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(typ), variable, varcharsize, arrsize, siz); + + free(variable); + free(offset); + } } @@ -302,23 +310,18 @@ ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, } } - -/* Freeing is not really that important. Since we throw away the process - anyway. Lets implement that last! */ - -/* won't work anymore because a list of members may appear in several locations */ -/*void +void ECPGfree_struct_member(struct ECPGstruct_member * rm) { - while (rm) - { - struct ECPGstruct_member *p = rm; - - rm = rm->next; - free(p->name); - free(p); - } -}*/ + while (rm) + { + struct ECPGstruct_member *p = rm; + + rm = rm->next; + free(p->name); + free(p); + } +} void ECPGfree_type(struct ECPGtype * typ) @@ -332,16 +335,18 @@ ECPGfree_type(struct ECPGtype * typ) else if (typ->u.element->typ == ECPGt_array) abort(); /* Array of array, */ else if (typ->u.element->typ == ECPGt_struct) + { /* Array of structs. */ + ECPGfree_struct_member(typ->u.members); free(typ->u.members); - /* ECPGfree_struct_member(typ->u.members);*/ + } else abort(); } else if (typ->typ == ECPGt_struct) { + ECPGfree_struct_member(typ->u.members); free(typ->u.members); - /* ECPGfree_struct_member(typ->u.members);*/ } else { diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 0a6df701fea2124b1b5bb7b9cc8dc6bed3c1c5b2..5895359c2eaf01d1c186c95bb3ad03a69410e3aa 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -77,6 +77,7 @@ struct when struct index { - int ival; - char *str; + int index1; + int index2; + char *str; }; diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index 50768a6541bf6214afc17fbd3a6699f69fa8a32e..8a7f1f69df49273fdbfca3c0a6a076c224422ea2 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,14 +1,18 @@ -all: test2 perftest +all: test1 test2 perftest + +LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt --static + +test1: test1.c +test1.c: test1.pgc + ../preproc/ecpg $? test2: test2.c - gcc -g -I ../include -I ../../libpq -o test2 test2.c -L../lib -lecpg -L../../libpq -lpq -lcrypt --static test2.c: test2.pgc - ../preproc/ecpg test2.pgc + ../preproc/ecpg $? perftest: perftest.c - gcc -g -I ../include -I ../../libpq -o perftest perftest.c -L../lib -lecpg -L../../libpq -lpq -lcrypt --static -perftest.c: perftest.pgc - ../preproc/ecpg perftest.pgc +perftest.c:perftest.pgc + ../preproc/ecpg $? clean: - /bin/rm test2 test2.c perftest perftest.c log + /bin/rm test1 test2 perftest *.c log diff --git a/src/interfaces/ecpg/test/Ptest1.c b/src/interfaces/ecpg/test/Ptest1.c deleted file mode 100644 index 5418e2c1a40ec93b8cf83a63e39a8dc61b3cacfb..0000000000000000000000000000000000000000 --- a/src/interfaces/ecpg/test/Ptest1.c +++ /dev/null @@ -1,77 +0,0 @@ -/* These two include files are added by the preprocessor */ -#include <ecpgtype.h> -#include <ecpglib.h> -/* exec sql begin declare section */ - - /* VARSIZE */ struct varchar_uid -{ - int len; - char arr[200]; -} uid; -struct varchar_name -{ - int len; - char arr[200]; -} name; -short value; - -/* exec sql end declare section */ - - -#include "sqlca.h" - -#define DBCP(x,y) strcpy(x.arr,y);x.len = strlen(x.arr) -#define LENFIX(x) x.len=strlen(x.arr) -#define STRFIX(x) x.arr[x.len]='\0' -#define SQLCODE sqlca.sqlcode - -void -db_error(char *msg) -{ - sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0'; - printf("%s: db error %s\n", msg, sqlca.sqlerrm.sqlerrmc); - exit(1); -} - -int -main() -{ - strcpy(uid.arr, "test/test"); - LENFIX(uid); - - ECPGconnect("kom"); - if (SQLCODE) - db_error("connect"); - - strcpy(name.arr, "opt1"); - LENFIX(name); - - ECPGdo(__LINE__, "declare cur cursor for select name , value from pace_test ", ECPGt_EOIT, ECPGt_EORT); - if (SQLCODE) - db_error("declare"); - - - if (SQLCODE) - db_error("open"); - - while (1) - { - ECPGdo(__LINE__, "fetch in cur ", ECPGt_EOIT, ECPGt_varchar, &name, 200, 0, sizeof(struct varchar_name), ECPGt_short, &value, 0, 0, sizeof(short), ECPGt_EORT); - if (SQLCODE) - break; - STRFIX(name); - printf("%s\t%d\n", name.arr, value); - } - - if (SQLCODE < 0) - db_error("fetch"); - - ECPGdo(__LINE__, "close cur ", ECPGt_EOIT, ECPGt_EORT); - if (SQLCODE) - db_error("close"); - ECPGcommit(__LINE__); - if (SQLCODE) - db_error("commit"); - - return (0); -} diff --git a/src/interfaces/ecpg/test/header_test.h b/src/interfaces/ecpg/test/header_test.h index 2494a61dd746af2d63334a125c5299d0d385db41..cc84aed778fece57a86ce9797e9697d40e4ad840 100644 --- a/src/interfaces/ecpg/test/header_test.h +++ b/src/interfaces/ecpg/test/header_test.h @@ -1,4 +1,4 @@ exec sql include sqlca; -exec sql whenever not found do set_not_found(); +exec sql whenever not found do break; exec sql whenever sqlerror sqlprint; diff --git a/src/interfaces/ecpg/test/mm.sql b/src/interfaces/ecpg/test/mm.sql deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/interfaces/ecpg/test/perftest.pgc b/src/interfaces/ecpg/test/perftest.pgc index 8183bf993681fcce9e39c996b6ef8733d2248884..f56d814dd98fb269d86ac9fc12dcc1c9e835f36f 100644 --- a/src/interfaces/ecpg/test/perftest.pgc +++ b/src/interfaces/ecpg/test/perftest.pgc @@ -121,5 +121,7 @@ exec sql end declare section; exec sql commit; + exec sql disconnect; + return (0); } diff --git a/src/interfaces/ecpg/test/test1.c b/src/interfaces/ecpg/test/test1.c deleted file mode 100644 index f2533d544d9f29630fbd2be3846fdadd4ece4334..0000000000000000000000000000000000000000 --- a/src/interfaces/ecpg/test/test1.c +++ /dev/null @@ -1,72 +0,0 @@ -exec sql begin declare section; -VARCHAR uid[200 /* VARSIZE */ ]; -varchar name[200]; -short value; -exec sql end declare section; - -exec sql include sqlca; - -#define DBCP(x,y) strcpy(x.arr,y);x.len = strlen(x.arr) -#define LENFIX(x) x.len=strlen(x.arr) -#define STRFIX(x) x.arr[x.len]='\0' -#define SQLCODE sqlca.sqlcode - -void -db_error(char *msg) -{ - sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0'; - printf("%s: db error %s\n", msg, sqlca.sqlerrm.sqlerrmc); - exit(1); -} - -int -main() -{ - strcpy(uid.arr, "test/test"); - LENFIX(uid); - - exec sql connect 'kom'; - - if (SQLCODE) - db_error("connect"); - - strcpy(name.arr, "opt1"); - LENFIX(name); - - exec sql declare cur cursor for - select name, - value from pace_test; - - if (SQLCODE) - db_error("declare"); - - exec sql open cur; - - if (SQLCODE) - db_error("open"); - - while (1) - { - exec sql fetch in cur into:name, - : value; - - if (SQLCODE) - break; - STRFIX(name); - printf("%s\t%d\n", name.arr, value); - } - - if (SQLCODE < 0) - db_error("fetch"); - - exec sql close cur; - - if (SQLCODE) - db_error("close"); - exec sql commit; - - if (SQLCODE) - db_error("commit"); - - return (0); -} diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc new file mode 100644 index 0000000000000000000000000000000000000000..3363af07b1ff50b1f08e5453b6fd86774dce07fb --- /dev/null +++ b/src/interfaces/ecpg/test/test1.pgc @@ -0,0 +1,63 @@ +#include <stdio.h> + +exec sql whenever sqlerror sqlprint; + +exec sql include sqlca; + +int +main () +{ +exec sql begin declare section; + int amount[5]; + char name[5][8]; +exec sql end declare section; + char msg[128], command[128]; + FILE *dbgs; + int i,j; + + if ((dbgs = fopen("log", "w")) != NULL) + ECPGdebug(1, dbgs); + + strcpy(msg, "connect"); + exec sql connect mm; + + strcpy(msg, "create"); + exec sql create table test(name char(8), amount int); + + strcpy(msg, "execute insert 1"); + sprintf(command, "insert into test(name, amount) values ('foobar', 1)"); + exec sql execute immediate :command; + + strcpy(msg, "excute insert 2"); + sprintf(command, "insert into test(name, amount) select name, amount+1 from test"); + exec sql execute immediate :command; + + strcpy(msg, "excute insert 3"); + sprintf(command, "insert into test(name, amount) select name, amount+10 from test"); + exec sql execute immediate :command; + + printf("Inserted %d tuples via execute immediate\n", sqlca.sqlerrd[2]); + + strcpy(msg, "commit"); + exec sql commit; + + strcpy(msg, "select"); + exec sql select name, amount into :name, :amount from test; + + for (i=0, j=sqlca.sqlerrd[2]; i<j; i++) + printf("name[%d]=%8.8s, amount[%d]=%d\n", i, name[i], i, amount[i]); + + strcpy(msg, "drop"); + exec sql drop table test; + + strcpy(msg, "commit"); + exec sql commit; + + strcpy(msg, "disconnect"); + exec sql disconnect; + + if (dbgs != NULL) + fclose(dbgs); + + return (0); +} diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc index 87834aaa6b7de4586e94f2cbef7dc6f526d24c25..ed0599cdeaf70ac8c29318bce125f672c3e3638c 100644 --- a/src/interfaces/ecpg/test/test2.pgc +++ b/src/interfaces/ecpg/test/test2.pgc @@ -2,13 +2,6 @@ exec sql include header_test; -static int not_found = 0; -static void -set_not_found(void) -{ - not_found = 1; -} - int main () { @@ -43,10 +36,7 @@ exec sql end declare section; exec sql insert into meskes(name, born, age, married) values ('Michael', 19660117, 32, '19900404'); exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 7); exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4); - - sprintf(command, "insert into meskes(name, born, age) values ('Chris', 19970923, 0)"); - strcpy(msg, "execute"); - exec sql execute immediate :command; + exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0); strcpy(msg, "commit"); exec sql commit; @@ -58,11 +48,10 @@ exec sql end declare section; strcpy(msg, "open"); exec sql open cur; - while (not_found == 0) { + while (1) { strcpy(msg, "fetch"); exec sql fetch cur into :personal:ind_personal, :married:ind_married; - if (not_found == 0) - printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married); + printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married); } strcpy(msg, "close"); @@ -74,6 +63,9 @@ exec sql end declare section; strcpy(msg, "commit"); exec sql commit; + strcpy(msg, "disconnect"); + + exec sql disconnect; if (dbgs != NULL) fclose(dbgs);