diff --git a/src/interfaces/ecpg/include/Makefile b/src/interfaces/ecpg/include/Makefile new file mode 100644 index 0000000000..08bc9df7f2 --- /dev/null +++ b/src/interfaces/ecpg/include/Makefile @@ -0,0 +1,16 @@ +# Generated automatically from Makefile.in by configure. +SRCDIR= ../../.. +include $(SRCDIR)/Makefile.global + +all clean:: + @echo Nothing to be done. + +install:: + install ecpglib.h $(HEADERDIR) + install ecpgtype.h $(HEADERDIR) + install sqlca.h $(HEADERDIR) + +uninstall:: + rm -f $(HEADERDIR)/ecpglib.h + rm -f $(HEADERDIR)/ecpgtype.h + rm -f $(HEADERDIR)/sqlca.h diff --git a/src/interfaces/ecpg/include/Makefile.in b/src/interfaces/ecpg/include/Makefile.in new file mode 100644 index 0000000000..2f5c63ab07 --- /dev/null +++ b/src/interfaces/ecpg/include/Makefile.in @@ -0,0 +1,15 @@ +SRCDIR= ../../.. +include $(SRCDIR)/Makefile.global + +all clean:: + @echo Nothing to be done. + +install:: + install ecpglib.h $(HEADERDIR) + install ecpgtype.h $(HEADERDIR) + install sqlca.h $(HEADERDIR) + +uninstall:: + rm -f $(HEADERDIR)/ecpglib.h + rm -f $(HEADERDIR)/ecpgtype.h + rm -f $(HEADERDIR)/sqlca.h diff --git a/src/interfaces/ecpg/src/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h similarity index 94% rename from src/interfaces/ecpg/src/include/ecpglib.h rename to src/interfaces/ecpg/include/ecpglib.h index b880182e0b..1fb35f8dfe 100644 --- a/src/interfaces/ecpg/src/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -1,6 +1,6 @@ #include -void ECPGdebug(int); +void ECPGdebug(int, FILE *); bool ECPGconnect(const char * dbname); bool ECPGdo(int, char *, ...); bool ECPGcommit(int); diff --git a/src/interfaces/ecpg/src/include/ecpgtype.h b/src/interfaces/ecpg/include/ecpgtype.h similarity index 98% rename from src/interfaces/ecpg/src/include/ecpgtype.h rename to src/interfaces/ecpg/include/ecpgtype.h index cc56b78cbb..496c934f4f 100644 --- a/src/interfaces/ecpg/src/include/ecpgtype.h +++ b/src/interfaces/ecpg/include/ecpgtype.h @@ -32,13 +32,13 @@ enum ECPGttype { ECPGt_char = 1, ECPGt_unsigned_char, ECPGt_short, ECPGt_unsigned_short, ECPGt_int, ECPGt_unsigned_int, ECPGt_long, ECPGt_unsigned_long, + ECPGt_bool, ECPGt_float, ECPGt_double, ECPGt_varchar, ECPGt_varchar2, ECPGt_array, ECPGt_record, ECPGt_EOIT, /* End of insert types. */ ECPGt_EORT /* End of result types. */ - }; #define IS_SIMPLE_TYPE(type) ((type) >= ECPGt_char && (type) <= ECPGt_varchar2) diff --git a/src/interfaces/ecpg/src/include/sqlca.h b/src/interfaces/ecpg/include/sqlca.h similarity index 100% rename from src/interfaces/ecpg/src/include/sqlca.h rename to src/interfaces/ecpg/include/sqlca.h diff --git a/src/interfaces/ecpg/src/lib/Makefile b/src/interfaces/ecpg/lib/Makefile similarity index 61% rename from src/interfaces/ecpg/src/lib/Makefile rename to src/interfaces/ecpg/lib/Makefile index d227f6df36..e3722e8aec 100644 --- a/src/interfaces/ecpg/src/lib/Makefile +++ b/src/interfaces/ecpg/lib/Makefile @@ -1,19 +1,21 @@ # Generated automatically from Makefile.in by configure. -TOPDIR=/home/meskes/data/computer/databases/postgres/pgsql/src/interfaces/ecpg/../.. -PQ_INCLUDE=-I$(TOPDIR)/include -I$(TOPDIR)/interfaces/libpq -POSTGRES_LIB=$(POSTGRESTOP)/lib +SRCDIR= ../../.. +include $(SRCDIR)/Makefile.global + +PQ_INCLUDE=-I$(SRCDIR)/include -I$(SRCDIR)/interfaces/libpq all: lib lib: libecpg.a -clean:: +clean: rm -f *.o *.a core a.out *~ -install:: libecpg.a - install -m644 libecpg.a $(POSTGRES_LIB) +install: libecpg.a + install -m 644 libecpg.a $(LIBDIR) + uninstall:: - rm -f $(POSTGRES_LIB)/libecpg.a + rm -f $(LIBDIR)/libecpg.a # Rules that do something libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o) diff --git a/src/interfaces/ecpg/src/lib/Makefile.in b/src/interfaces/ecpg/lib/Makefile.in similarity index 64% rename from src/interfaces/ecpg/src/lib/Makefile.in rename to src/interfaces/ecpg/lib/Makefile.in index 07d126bd5c..7ed351ab7a 100644 --- a/src/interfaces/ecpg/src/lib/Makefile.in +++ b/src/interfaces/ecpg/lib/Makefile.in @@ -1,18 +1,20 @@ -TOPDIR=@TOPSRC@ -PQ_INCLUDE=-I$(TOPDIR)/include -I$(TOPDIR)/interfaces/libpq -POSTGRES_LIB=$(POSTGRESTOP)/lib +SRCDIR= ../../.. +include $(SRCDIR)/Makefile.global + +PQ_INCLUDE=-I$(SRCDIR)/include -I$(SRCDIR)/interfaces/libpq all: lib lib: libecpg.a -clean:: +clean: rm -f *.o *.a core a.out *~ -install:: libecpg.a - install -m644 libecpg.a $(POSTGRES_LIB) +install: libecpg.a + install -m 644 libecpg.a $(LIBDIR) + uninstall:: - rm -f $(POSTGRES_LIB)/libecpg.a + rm -f $(LIBDIR)/libecpg.a # Rules that do something libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o) diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c new file mode 100644 index 0000000000..80e9b0fd9c --- /dev/null +++ b/src/interfaces/ecpg/lib/ecpglib.c @@ -0,0 +1,648 @@ +/* Copyright comment */ +/* + * The aim is to get a simpler inteface to the database routines. + * All the tidieous messing around with tuples is supposed to be hidden + * by this function. + */ +/* Author: Linus Tolke + (actually most if the code is "borrowed" from the distribution and just + slightly modified) + */ + +/* Taken over as part of PostgreSQL by Michael Meskes + on Feb. 5th, 1998 */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static PGconn *simple_connection; +static int simple_debug = 0; +static FILE *debugstream = NULL; +static int committed = true; + +static void +register_error(int code, char *fmt,...) +{ + va_list args; + + sqlca.sqlcode = code; + va_start(args, fmt); + vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args); + va_end(args); + sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); +} + +/* This function returns a newly malloced string that has the ' and \ + in the argument quoted with \. + */ +static +char * +quote_postgres(char *arg) +{ + char *res = (char *) malloc(2 * strlen(arg) + 1); + int i, + ri; + + for (i = 0, ri = 0; arg[i]; i++, ri++) + { + switch (arg[i]) + { + case '\'': + case '\\': + res[ri++] = '\\'; + default: + ; + } + + res[ri] = arg[i]; + } + res[ri] = '\0'; + + return res; +} + + +bool +ECPGdo(int lineno, char *query,...) +{ + va_list ap; + bool status = false; + char *copiedquery; + PGresult *results; + PGnotify *notify; + enum ECPGttype type; + + va_start(ap, query); + + sqlca.sqlcode = 0; + copiedquery = strdup(query); + + type = va_arg(ap, enum ECPGttype); + + /* + * Now, if the type is one of the fill in types then we take the argument + * and enter that in the string at the first %s position. Then if there + * are any more fill in types we fill in at the next and so on. + */ + while (type != ECPGt_EOIT) + { + void *value = NULL; + short varcharsize; + short size; + short arrsize; + + char *newcopy; + char *mallocedval = NULL; + char *tobeinserted = NULL; + char *p; + char buff[20]; + + /* Some special treatment is needed for records since we want their + contents to arrive in a comma-separated list on insert (I think). */ + + value = va_arg(ap, void *); + varcharsize = va_arg(ap, short); + size = va_arg(ap, short); + arrsize = va_arg(ap, short); + + switch (type) + { + case ECPGt_char: + case ECPGt_short: + case ECPGt_int: + sprintf(buff, "%d", *(int *) value); + tobeinserted = buff; + break; + + case ECPGt_unsigned_char: + case ECPGt_unsigned_short: + case ECPGt_unsigned_int: + sprintf(buff, "%d", *(unsigned int *) value); + tobeinserted = buff; + break; + + case ECPGt_long: + sprintf(buff, "%ld", *(long *) value); + tobeinserted = buff; + break; + + case ECPGt_unsigned_long: + sprintf(buff, "%ld", *(unsigned long *) value); + tobeinserted = buff; + break; + + case ECPGt_float: + sprintf(buff, "%.14g", *(float *) value); + tobeinserted = buff; + break; + + case ECPGt_double: + sprintf(buff, "%.14g", *(double *) value); + tobeinserted = buff; + break; + + case ECPGt_bool: + sprintf(buff, "'%c'", (*(char *) value ? 't' : 'f')); + tobeinserted = buff; + break; + + case ECPGt_varchar: + case ECPGt_varchar2: + { + struct ECPGgeneric_varchar *var = + (struct ECPGgeneric_varchar *) value; + + newcopy = (char *) malloc(var->len + 1); + strncpy(newcopy, var->arr, var->len); + newcopy[var->len] = '\0'; + + mallocedval = (char *) malloc(2 * strlen(newcopy) + 3); + strcpy(mallocedval, "'"); + strcat(mallocedval, quote_postgres(newcopy)); + strcat(mallocedval, "'"); + + free(newcopy); + + tobeinserted = mallocedval; + } + break; + + default: + /* Not implemented yet */ + register_error(-1, "Unsupported type %s on line %d.", + ECPGtype_name(type), lineno); + return false; + break; + } + + /* Now tobeinserted points to an area that is to be inserted at + the first %s + */ + newcopy = (char *) malloc(strlen(copiedquery) + + strlen(tobeinserted) + + 1); + strcpy(newcopy, copiedquery); + if ((p = strstr(newcopy, ";;")) == NULL) + { + /* We have an argument but we dont have the matched up string + in the string + */ + register_error(-1, "Too many arguments line %d.", lineno); + return false; + } + else + { + strcpy(p, tobeinserted); + /* The strange thing in the second argument is the rest of the + string from the old string */ + strcat(newcopy, + copiedquery + + (p - newcopy) + + 2 /* Length of ;; */ ); + } + + /* Now everything is safely copied to the newcopy. Lets free the + oldcopy and let the copiedquery get the value from the newcopy. + */ + if (mallocedval != NULL) + { + free(mallocedval); + mallocedval = NULL; + } + + free(copiedquery); + copiedquery = newcopy; + + type = va_arg(ap, enum ECPGttype); + } + + /* Check if there are unmatched things left. */ + if (strstr(copiedquery, ";;") != NULL) + { + register_error(-1, "Too few arguments line %d.", lineno); + return false; + } + + /* Now then request is built. */ + + if (committed) + { + if ((results = PQexec(simple_connection, "begin")) == NULL) + { + register_error(-1, "Error starting transaction line %d.", lineno); + return false; + } + PQclear(results); + committed = 0; + } + + ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery); + results = PQexec(simple_connection, copiedquery); + free(copiedquery); + + if (results == NULL) + { + ECPGlog("ECPGdo line %d: error: %s", lineno, + PQerrorMessage(simple_connection)); + register_error(-1, "Postgres error: %s line %d.", + PQerrorMessage(simple_connection), lineno); + } + else + switch (PQresultStatus(results)) + { + int m, + n, + x; + + case PGRES_TUPLES_OK: + /* XXX Cheap Hack. For now, we see only the last group + * of tuples. This is clearly not the right + * way to do things !! + */ + + m = PQnfields(results); + n = PQntuples(results); + + if (n < 1) + { + ECPGlog("ECPGdo lineno %d: Incorrect number of matches: %d\n", + lineno, n); + register_error(1, "Data not found line %d.", lineno); + 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; + short varcharsize; + short size; + short arrsize; + + 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 : ""); + + /* No 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, short); + size = va_arg(ap, short); + arrsize = va_arg(ap, short); + + switch (type) + { + long res; + unsigned long ures; + double dres; + + case ECPGt_char: + 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_char: + *(char *) value = (char) res; + break; + 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_char: + 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_char: + *(unsigned char *) value = (unsigned char) ures; + break; + 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_varchar: + { + struct ECPGgeneric_varchar *var = + (struct ECPGgeneric_varchar *) value; + + strncpy(var->arr, pval, varcharsize); + var->len = strlen(pval); + if (var->len > varcharsize) + 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; + } + } + + type = va_arg(ap, enum ECPGttype); + + if (status && type != ECPGt_EORT) + { + register_error(-1, "Too many arguments line %d.", lineno); + return false; + } + + PQclear(results); + break; + case PGRES_EMPTY_QUERY: + /* do nothing */ + register_error(-1, "Empty query line %d.", lineno); + break; + case PGRES_COMMAND_OK: + status = true; + ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results)); + break; + case PGRES_NONFATAL_ERROR: + case PGRES_FATAL_ERROR: + case PGRES_BAD_RESPONSE: + ECPGlog("ECPGdo line %d: Error: %s", + lineno, PQerrorMessage(simple_connection)); + register_error(-1, "Error: %s line %d.", + PQerrorMessage(simple_connection), lineno); + break; + case PGRES_COPY_OUT: + ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno); + PQendcopy(results->conn); + break; + case PGRES_COPY_IN: + ECPGlog("ECPGdo line %d: Got PGRES_COPY_IN ... tossing.\n", lineno); + PQendcopy(results->conn); + break; + default: + ECPGlog("ECPGdo line %d: Got something else, postgres error.\n", + lineno); + register_error(-1, "Postgres error line %d.", lineno); + break; + } + + /* check for asynchronous returns */ + notify = PQnotifies(simple_connection); + if (notify) + { + ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n", + lineno, notify->relname, notify->be_pid); + free(notify); + } + + va_end(ap); + return status; +} + + +bool +ECPGcommit(int lineno) +{ + PGresult *res; + + ECPGlog("ECPGcommit line %d\n", lineno); + if ((res = PQexec(simple_connection, "end")) == NULL) + { + register_error(-1, "Error committing line %d.", lineno); + return (FALSE); + } + PQclear(res); + committed = 1; + return (TRUE); +} + +bool +ECPGrollback(int lineno) +{ + PGresult *res; + + ECPGlog("ECPGrollback line %d\n", lineno); + if ((res = PQexec(simple_connection, "abort")) == NULL) + { + register_error(-1, "Error rolling back line %d.", lineno); + return (FALSE); + } + PQclear(res); + committed = 1; + return (TRUE); +} + + + +bool +ECPGsetdb(PGconn *newcon) +{ + ECPGfinish(); + simple_connection = newcon; + return true; +} + +bool +ECPGconnect(const char *dbname) +{ + char *name = strdup(dbname); + + ECPGlog("ECPGconnect: opening database %s\n", name); + + sqlca.sqlcode = 0; + + ECPGsetdb(PQsetdb(NULL, NULL, NULL, NULL, name)); + + free(name); + name = NULL; + + 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); + return false; + } + return true; +} + + +bool +ECPGstatus() +{ + return PQstatus(simple_connection) != CONNECTION_BAD; +} + + +bool +ECPGfinish() +{ + if (simple_connection != NULL) + { + ECPGlog("ECPGfinish: finishing.\n"); + PQfinish(simple_connection); + } + else + ECPGlog("ECPGfinish: called an extra time.\n"); + return true; +} + +void +ECPGdebug(int n, FILE *dbgs) +{ + simple_debug = n; + debugstream = dbgs; + ECPGlog("ECPGdebug: set to %d\n", simple_debug); +} + +void +ECPGlog(const char *format,...) +{ + va_list ap; + + if (simple_debug) + { + char *f = (char *) malloc(strlen(format) + 100); + + sprintf(f, "[%d]: %s", getpid(), format); + + va_start(ap, format); + vfprintf(debugstream, f, ap); + va_end(ap); + + free(f); + } +} diff --git a/src/interfaces/ecpg/src/lib/typename.c b/src/interfaces/ecpg/lib/typename.c similarity index 94% rename from src/interfaces/ecpg/src/lib/typename.c rename to src/interfaces/ecpg/lib/typename.c index c178957205..55756037b3 100644 --- a/src/interfaces/ecpg/src/lib/typename.c +++ b/src/interfaces/ecpg/lib/typename.c @@ -17,6 +17,7 @@ ECPGtype_name(enum ECPGttype typ) case ECPGt_unsigned_long: return "unsigned long"; case ECPGt_float: return "float"; case ECPGt_double: return "double"; + case ECPGt_bool: return "bool"; default: abort(); } diff --git a/src/interfaces/ecpg/src/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile similarity index 51% rename from src/interfaces/ecpg/src/preproc/Makefile rename to src/interfaces/ecpg/preproc/Makefile index 9a53fb1b43..8cc8b7cb3a 100644 --- a/src/interfaces/ecpg/src/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -1,36 +1,32 @@ # Generated automatically from Makefile.in by configure. -POSTGRESTOP=@POSTGRESERVER@ -POSTGRES_BIN=$(POSTGRESTOP)/bin -POSTGRES_LIB=$(POSTGRESTOP)/lib +SRCDIR= ../../.. +include $(SRCDIR)/Makefile.global CC=gcc LEX=flex LEXLIB=-lfl -YACC=bison -y - +YACC=/usr/bin/bison +YFLAGS=-y -d CFLAGS=-I../include -O2 -g -Wall all:: ecpg -clean:: - rm -f *.o core a.out ecpg y.tab.h y.tab.c *~ +clean: + rm -f *.o core a.out ecpg preproc.tab.h y.tab.c *~ -install:: all - install -c -d -m755 $(POSTGRES_LIB)/ecpg - install -c -m555 preproc $(POSTGRES_LIB)/ecpg - install -c -m555 ecpg $(POSTGRES_BIN) +install: all + install -c -m 755 ecpg $(BINDIR) -uninstall:: - rm -f $(POSTGRES_BIN)/ecpg - rm -f $(POSTGRES_LIB)/ecpg/preproc +uninstall: + rm -f $(BINDIR)/ecpg # Rule that really do something. ecpg: y.tab.o pgc.o type.o ecpg.o $(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB) y.tab.h y.tab.c: preproc.y - $(YACC) -d $< + $(YACC) $(YFLAGS) $< y.tab.o : y.tab.h ../include/ecpgtype.h type.o : ../include/ecpgtype.h diff --git a/src/interfaces/ecpg/preproc/Makefile.in b/src/interfaces/ecpg/preproc/Makefile.in new file mode 100644 index 0000000000..f3cb049e8c --- /dev/null +++ b/src/interfaces/ecpg/preproc/Makefile.in @@ -0,0 +1,32 @@ +SRCDIR= ../../.. +include $(SRCDIR)/Makefile.global + +CC=@CC@ +LEX=@LEX@ +LEXLIB=@LEXLIB@ +YACC=@YACC@ +YFLAGS=@YFLAGS@ + +CFLAGS=-I../include -O2 -g -Wall + +all:: ecpg + +clean: + rm -f *.o core a.out ecpg preproc.tab.h y.tab.c *~ + +install: all + install -c -m 755 ecpg $(BINDIR) + +uninstall: + rm -f $(BINDIR)/ecpg + +# Rule that really do something. +ecpg: y.tab.o pgc.o type.o ecpg.o + $(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB) + +y.tab.h y.tab.c: preproc.y + $(YACC) $(YFLAGS) $< + +y.tab.o : y.tab.h ../include/ecpgtype.h +type.o : ../include/ecpgtype.h +pgc.o : ../include/ecpgtype.h diff --git a/src/interfaces/ecpg/src/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c similarity index 84% rename from src/interfaces/ecpg/src/preproc/ecpg.c rename to src/interfaces/ecpg/preproc/ecpg.c index a7d96072af..08f4a39525 100644 --- a/src/interfaces/ecpg/src/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -8,10 +8,9 @@ #include extern void lex_init(void); -extern FILE *yyin, - *yyout; - -int yyparse(void); +extern FILE *yyin, *yyout; +extern char * input_filename; +extern int yyparse(void); static void usage(char *progname) @@ -22,7 +21,8 @@ usage(char *progname) int main(int argc, char *const argv[]) { - char c, out_option = 0; + char c, + out_option = 0; int fnr; while ((c = getopt(argc, argv, "o:")) != EOF) @@ -58,7 +58,8 @@ main(int argc, char *const argv[]) ptr2ext = strrchr(filename, '.'); /* no extension or extension not equal .pgc */ - if (ptr2ext == NULL || strcmp(ptr2ext, ".pgc") != 0) { + if (ptr2ext == NULL || strcmp(ptr2ext, ".pgc") != 0) + { ptr2ext = filename + strlen(filename); ptr2ext[0] = '.'; } @@ -67,17 +68,18 @@ main(int argc, char *const argv[]) ptr2ext[1] = 'c'; ptr2ext[2] = '\0'; - if (out_option == 0) /* calculate the output name */ + if (out_option == 0) /* calculate the output name */ { yyout = fopen(filename, "w"); - if (yyout == NULL) { + if (yyout == NULL) + { perror(filename); free(filename); continue; } } - yyin = fopen(argv[fnr], "r"); + yyin = fopen(input_filename = argv[fnr], "r"); if (yyin == NULL) { perror(argv[fnr]); @@ -95,7 +97,7 @@ main(int argc, char *const argv[]) fclose(yyin); if (out_option == 0) - fclose (yyout); + fclose(yyout); } free(filename); diff --git a/src/interfaces/ecpg/src/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l similarity index 94% rename from src/interfaces/ecpg/src/preproc/pgc.l rename to src/interfaces/ecpg/preproc/pgc.l index 857561df9c..7ab3c5764f 100644 --- a/src/interfaces/ecpg/src/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -3,8 +3,11 @@ #include "type.h" #include "y.tab.h" -#define dbg(arg) fprintf(stderr, "DEBUG: %s\n", #arg); +extern int debugging; + +#define dbg(arg) if (debugging) fprintf(stderr, "DEBUG, %d: %s\n", yylineno, #arg); %} +%option yylineno %s C SQL ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/ ws ([ \t\n][ \t\n]*|{ccomment})* @@ -53,7 +56,8 @@ int { dbg(S_INT); return S_INT; } char { dbg(S_CHAR); return S_CHAR; } float { dbg(S_FLOAT); return S_FLOAT; } double { dbg(S_DOUBLE); return S_DOUBLE; } - +bool { dbg(S_BOOL); return S_BOOL; } + {string} { dbg(SQL_STRING); return SQL_STRING; } {ws} ; {symbol} { dbg(S_SYMBOL); return S_SYMBOL; } @@ -100,12 +104,12 @@ double { dbg(S_DOUBLE); return S_DOUBLE; } . { dbg(.); return S_ANYTHING; } %% void -lex_init() +lex_init(void) { BEGIN C; } -int yywrap() +int yywrap(void) { return 1; } diff --git a/src/interfaces/ecpg/src/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y similarity index 90% rename from src/interfaces/ecpg/src/preproc/preproc.y rename to src/interfaces/ecpg/preproc/preproc.y index f53c9a5613..b5a30c0d19 100644 --- a/src/interfaces/ecpg/src/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -8,8 +8,26 @@ void yyerror(char *); extern FILE * yyout; extern char * yytext; +extern int yylineno; extern int yyleng; +/* + * Variables containing simple states. + */ +int debugging = 0; + +/* + * Handle the filename and line numbering. + */ +char * input_filename = NULL; + +void +output_line_number() +{ + if (input_filename) + fprintf(yyout, "\n#line %d \"%s\"\n", yylineno, input_filename); +} + /* * Handling of the variables. */ @@ -144,7 +162,7 @@ dump_variables(struct arguments * list) %token S_VARCHAR S_VARCHAR2 %token S_EXTERN S_STATIC %token S_UNSIGNED S_SIGNED -%token S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE +%token S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL %token '[' ']' ';' ',' %type type type_detailed varchar_type simple_type array_type @@ -175,10 +193,12 @@ sqldeclaration : sql_startdeclare sql_enddeclare; sql_startdeclare : SQL_START SQL_BEGIN SQL_DECLARE SQL_SECTION SQL_SEMI { - printf("/* exec sql begin declare section */\n"); + fprintf(yyout, "/* exec sql begin declare section */\n"); + output_line_number(); }; sql_enddeclare : SQL_START SQL_END SQL_DECLARE SQL_SECTION SQL_SEMI { - printf("/* exec sql end declare section */\n"); + fprintf(yyout,"/* exec sql end declare section */\n"); + output_line_number(); }; variable_declarations : /* empty */ @@ -235,7 +255,8 @@ simple_tag : S_CHAR { $$ = ECPGt_char; } | S_LONG { $$ = ECPGt_long; } | S_UNSIGNED S_LONG { $$ = ECPGt_unsigned_long; } | S_FLOAT { $$ = ECPGt_float; } - | S_DOUBLE { $$ = ECPGt_double; }; + | S_DOUBLE { $$ = ECPGt_double; } + | S_BOOL { $$ = ECPGt_bool; }; maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); } | S_STATIC { fwrite(yytext, yyleng, 1, yyout); } @@ -248,17 +269,17 @@ index : '[' length ']' { length : S_LENGTH { $$ = atoi(yytext); } sqlinclude : SQL_START SQL_INCLUDE { fprintf(yyout, "#include \""); } - filename SQL_SEMI { fprintf(yyout, ".h\""); }; + filename SQL_SEMI { fprintf(yyout, ".h\""); output_line_number(); }; filename : cthing | filename cthing; sqlconnect : SQL_START SQL_CONNECT { fprintf(yyout, "ECPGconnect(\""); } SQL_STRING { fwrite(yytext + 1, yyleng - 2, 1, yyout); } - SQL_SEMI { fprintf(yyout, "\");"); }; + SQL_SEMI { fprintf(yyout, "\");"); output_line_number(); }; /* Open is an open cursor. Removed. */ -sqlopen : SQL_START SQL_OPEN sqlgarbage SQL_SEMI { }; +sqlopen : SQL_START SQL_OPEN sqlgarbage SQL_SEMI { output_line_number(); }; sqlgarbage : /* Empty */ | sqlgarbage sqlanything; @@ -266,9 +287,11 @@ sqlgarbage : /* Empty */ sqlcommit : SQL_START SQL_COMMIT SQL_SEMI { fprintf(yyout, "ECPGcommit(__LINE__);"); + output_line_number(); }; sqlrollback : SQL_START SQL_ROLLBACK SQL_SEMI { fprintf(yyout, "ECPGrollback(__LINE__);"); + output_line_number(); }; sqlstatement : SQL_START { /* Reset stack */ @@ -283,6 +306,7 @@ sqlstatement : SQL_START { /* Reset stack */ fprintf(yyout, "ECPGt_EOIT, "); dump_variables(argsresult); fprintf(yyout, "ECPGt_EORT );"); + output_line_number(); }; sqlstatement_words : sqlstatement_word diff --git a/src/interfaces/ecpg/src/preproc/type.c b/src/interfaces/ecpg/preproc/type.c similarity index 87% rename from src/interfaces/ecpg/src/preproc/type.c rename to src/interfaces/ecpg/preproc/type.c index a54cbd801d..e3ee2f003a 100644 --- a/src/interfaces/ecpg/src/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -1,6 +1,5 @@ #include #include -#include #include "type.h" @@ -134,55 +133,59 @@ ECPGdump_a_simple(FILE * o, const char * name, enum ECPGttype typ, switch (typ) { case ECPGt_char: - fprintf(o, "ECPGt_char,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_char,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(char)" : siz); break; case ECPGt_unsigned_char: - fprintf(o, "ECPGt_unsigned_char,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_unsigned_char,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(unsigned char)" : siz); break; case ECPGt_short: - fprintf(o, "ECPGt_short,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_short,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(short)" : siz); break; case ECPGt_unsigned_short: fprintf(o, - "ECPGt_unsigned_short,&%s,0,%d,%s, ", name, arrsiz, + "\n\tECPGt_unsigned_short,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(unsigned short)" : siz); break; case ECPGt_int: - fprintf(o, "ECPGt_int,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_int,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(int)" : siz); break; case ECPGt_unsigned_int: - fprintf(o, "ECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(unsigned int)" : siz); break; case ECPGt_long: - fprintf(o, "ECPGt_long,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_long,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(long)" : siz); break; case ECPGt_unsigned_long: - fprintf(o, "ECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_unsigned_int,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(unsigned int)" : siz); break; case ECPGt_float: - fprintf(o, "ECPGt_float,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_float,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(float)" : siz); break; case ECPGt_double: - fprintf(o, "ECPGt_double,&%s,0,%d,%s, ", name, arrsiz, + fprintf(o, "\n\tECPGt_double,&%s,0,%d,%s, ", name, arrsiz, siz == NULL ? "sizeof(double)" : siz); break; + case ECPGt_bool: + fprintf(o, "\n\tECPGt_bool,&%s,0,%d,%s, ", name, arrsiz, + siz == NULL ? "sizeof(bool)" : siz); + break; case ECPGt_varchar: case ECPGt_varchar2: if (siz == NULL) - fprintf(o, "ECPGt_varchar,&%s,%d,%d,sizeof(struct varchar_%s), ", + fprintf(o, "\n\tECPGt_varchar,&%s,%d,%d,sizeof(struct varchar_%s), ", name, varcharsize, arrsiz, name); else - fprintf(o, "ECPGt_varchar,&%s,%d,%d,%s, ", + fprintf(o, "\n\tECPGt_varchar,&%s,%d,%d,%s, ", name, varcharsize, arrsiz, siz); diff --git a/src/interfaces/ecpg/src/preproc/type.h b/src/interfaces/ecpg/preproc/type.h similarity index 100% rename from src/interfaces/ecpg/src/preproc/type.h rename to src/interfaces/ecpg/preproc/type.h diff --git a/src/interfaces/ecpg/preproc/y.tab.h b/src/interfaces/ecpg/preproc/y.tab.h new file mode 100644 index 0000000000..b2fadd683b --- /dev/null +++ b/src/interfaces/ecpg/preproc/y.tab.h @@ -0,0 +1,39 @@ +typedef union { + int tagname; + struct ECPGtemp_type type; + char * symbolname; + int indexsize; + enum ECPGttype type_enum; +} YYSTYPE; +#define SQL_START 258 +#define SQL_SEMI 259 +#define SQL_STRING 260 +#define SQL_INTO 261 +#define SQL_BEGIN 262 +#define SQL_END 263 +#define SQL_DECLARE 264 +#define SQL_SECTION 265 +#define SQL_INCLUDE 266 +#define SQL_CONNECT 267 +#define SQL_OPEN 268 +#define SQL_COMMIT 269 +#define SQL_ROLLBACK 270 +#define S_SYMBOL 271 +#define S_LENGTH 272 +#define S_ANYTHING 273 +#define S_VARCHAR 274 +#define S_VARCHAR2 275 +#define S_EXTERN 276 +#define S_STATIC 277 +#define S_UNSIGNED 278 +#define S_SIGNED 279 +#define S_LONG 280 +#define S_SHORT 281 +#define S_INT 282 +#define S_CHAR 283 +#define S_FLOAT 284 +#define S_DOUBLE 285 +#define S_BOOL 286 + + +extern YYSTYPE yylval; diff --git a/src/interfaces/ecpg/src/include/Makefile b/src/interfaces/ecpg/src/include/Makefile deleted file mode 100644 index 3b001abaaf..0000000000 --- a/src/interfaces/ecpg/src/include/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Generated automatically from Makefile.in by configure. -POSTGRESTOP=@POSTGRESERVER@ -POSTGRES_INCLUDE=$(POSTGRESTOP)/include - -all clean:: - @echo Nothing to be done. - -install:: - install ecpglib.h $(POSTGRES_INCLUDE) - install ecpgtype.h $(POSTGRES_INCLUDE) - install sqlca.h $(POSTGRES_INCLUDE) - -uninstall:: - rm -f $(POSTGRES_INCLUDE)/ecpglib.h - rm -f $(POSTGRES_INCLUDE)/ecpgtype.h - rm -f $(POSTGRES_INCLUDE)/sqlca.h diff --git a/src/interfaces/ecpg/src/include/Makefile.in b/src/interfaces/ecpg/src/include/Makefile.in deleted file mode 100644 index 80e0451e2b..0000000000 --- a/src/interfaces/ecpg/src/include/Makefile.in +++ /dev/null @@ -1,15 +0,0 @@ -POSTGRESTOP=@POSTGRESERVER@ -POSTGRES_INCLUDE=$(POSTGRESTOP)/include - -all clean:: - @echo Nothing to be done. - -install:: - install ecpglib.h $(POSTGRES_INCLUDE) - install ecpgtype.h $(POSTGRES_INCLUDE) - install sqlca.h $(POSTGRES_INCLUDE) - -uninstall:: - rm -f $(POSTGRES_INCLUDE)/ecpglib.h - rm -f $(POSTGRES_INCLUDE)/ecpgtype.h - rm -f $(POSTGRES_INCLUDE)/sqlca.h diff --git a/src/interfaces/ecpg/src/lib/ecpglib.c b/src/interfaces/ecpg/src/lib/ecpglib.c deleted file mode 100644 index d2c078e2d0..0000000000 --- a/src/interfaces/ecpg/src/lib/ecpglib.c +++ /dev/null @@ -1,609 +0,0 @@ -/* Copyright comment */ -/* - * The aim is to get a simpler inteface to the database routines. - * All the tidieous messing around with tuples is supposed to be hidden - * by this function. - */ -/* Author: Linus Tolke - (actually most if the code is "borrowed" from the distribution and just - slightly modified) - */ - -/* Taken over as part of PostgreSQL by Michael Meskes - on Feb. 5th, 1998 */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static PGconn * simple_connection; -static int simple_debug = 0; -static int committed = true; - -static void -register_error(int code, char *fmt, ...) -{ - va_list args; - - sqlca.sqlcode = code; - va_start (args, fmt); - vsprintf (sqlca.sqlerrm.sqlerrmc, fmt, args); - va_end (args); - sqlca.sqlerrm.sqlerrml = strlen (sqlca.sqlerrm.sqlerrmc); -} - -/* This function returns a newly malloced string that has the ' and \ - in the argument quoted with \. - */ -static -char * -quote_postgres(char * arg) -{ - char * res = (char *)malloc(2 * strlen(arg) + 1); - int i, ri; - - for (i = 0, ri = 0; arg[i]; i++, ri++) - { - switch (arg[i]) - { - case '\'': - case '\\': - res[ri++] = '\\'; - default: - ; - } - - res[ri] = arg[i]; - } - res[ri] = '\0'; - - return res; -} - - -bool -ECPGdo(int lineno, char * query, ...) -{ - va_list ap; - bool status = false; - char * copiedquery; - PGresult * results; - PGnotify * notify; - enum ECPGttype type; - - va_start(ap, query); - - sqlca.sqlcode = 0; - copiedquery = strdup(query); - - type = va_arg(ap, enum ECPGttype); - - /* - * Now, if the type is one of the fill in types then we take the argument - * and enter that in the string at the first %s position. Then if there - * are any more fill in types we fill in at the next and so on. - */ - while (type != ECPGt_EOIT) - { - void * value = NULL; - short varcharsize; - short size; - short arrsize; - - char * newcopy; - char * mallocedval = NULL; - char * tobeinserted = NULL; - char * p; - char buff[20]; - - /* Some special treatment is needed for records since we want their - contents to arrive in a comma-separated list on insert (I think). */ - - value = va_arg(ap, void *); - varcharsize = va_arg(ap, short); - size = va_arg(ap, short); - arrsize = va_arg(ap, short); - - switch (type) { - case ECPGt_char: - case ECPGt_short: - case ECPGt_int: - sprintf(buff, "%d", *(int*)value); - tobeinserted = buff; - break; - - case ECPGt_unsigned_char: - case ECPGt_unsigned_short: - case ECPGt_unsigned_int: - sprintf(buff, "%d", *(unsigned int*)value); - tobeinserted = buff; - break; - - case ECPGt_long: - sprintf(buff, "%ld", *(long*)value); - tobeinserted = buff; - break; - - case ECPGt_unsigned_long: - sprintf(buff, "%ld", *(unsigned long*)value); - tobeinserted = buff; - break; - - case ECPGt_float: - sprintf(buff, "%.14g", *(float*)value); - tobeinserted = buff; - break; - - case ECPGt_double: - sprintf(buff, "%.14g", *(double*)value); - tobeinserted = buff; - break; - - case ECPGt_varchar: - case ECPGt_varchar2: - { - struct ECPGgeneric_varchar * var = - (struct ECPGgeneric_varchar*)value; - - newcopy = (char *)malloc(var->len + 1); - strncpy(newcopy, var->arr, var->len); - newcopy[var->len] = '\0'; - - mallocedval = (char *)malloc(2 * strlen(newcopy) + 3); - strcpy(mallocedval, "'"); - strcat(mallocedval, quote_postgres(newcopy)); - strcat(mallocedval, "'"); - - free(newcopy); - - tobeinserted = mallocedval; - } - break; - - default: - /* Not implemented yet */ - register_error(-1, "Unsupported type %s on line %d.", - ECPGtype_name(type), lineno); - return false; - break; - } - - /* Now tobeinserted points to an area that is to be inserted at - the first %s - */ - newcopy = (char *)malloc(strlen(copiedquery) - + strlen(tobeinserted) - + 1); - strcpy(newcopy, copiedquery); - if ((p = strstr(newcopy, ";;")) == NULL) - { - /* We have an argument but we dont have the matched up string - in the string - */ - register_error(-1, "Too many arguments line %d.", lineno); - return false; - } - else - { - strcpy(p, tobeinserted); - /* The strange thing in the second argument is the rest of the - string from the old string */ - strcat(newcopy, - copiedquery - + ( p - newcopy ) - + 2 /* Length of ;; */); - } - - /* Now everything is safely copied to the newcopy. Lets free the - oldcopy and let the copiedquery get the value from the newcopy. - */ - if (mallocedval != NULL) - { - free(mallocedval); - mallocedval = NULL; - } - - free(copiedquery); - copiedquery = newcopy; - - type = va_arg(ap, enum ECPGttype); - } - - /* Check if there are unmatched things left. */ - if (strstr(copiedquery, ";;") != NULL) - { - register_error(-1, "Too few arguments line %d.", lineno); - return false; - } - - /* Now then request is built. */ - - if (committed) - { - if ((results = PQexec (simple_connection, "begin")) == NULL) { - register_error(-1, "Error starting transaction line %d.", lineno); - return false; - } - PQclear (results); - committed = 0; - } - - ECPGlog("ECPGdo line %d: QUERY: %s\n", lineno, copiedquery); - results = PQexec(simple_connection, copiedquery); - free(copiedquery); - - if (results == NULL) - { - ECPGlog("ECPGdo line %d: error: %s", lineno, - PQerrorMessage(simple_connection)); - register_error(-1, "Postgres error: %s line %d.", - PQerrorMessage(simple_connection), lineno); - } - else switch(PQresultStatus(results)) - { - int m,n,x; - - case PGRES_TUPLES_OK: - /* XXX Cheap Hack. For now, we see only the last group - * of tuples. This is clearly not the right - * way to do things !! - */ - - m = PQnfields(results); - n = PQntuples(results); - - if (n < 1) - { - ECPGlog("ECPGdo lineno %d: Incorrect number of matches: %d\n", - lineno, n); - register_error(1, "Data not found line %d.", lineno); - 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; - short varcharsize; - short size; - short arrsize; - - 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 : ""); - - /* No 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, short); - size = va_arg(ap, short); - arrsize = va_arg(ap, short); - - switch (type) - { - long res; - unsigned long ures; - double dres; - - case ECPGt_char: - 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_char: - *(char *)value = (char)res; - break; - 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_char: - 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_char: - *(unsigned char *)value = (unsigned char)ures; - break; - 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 = (float)res; - break; - case ECPGt_double: - *(double *)value = res; - break; - default: - /* Cannot happen */ - 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) - 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; - } - } - - type = va_arg(ap, enum ECPGttype); - - if (status && type != ECPGt_EORT) - { - register_error(-1, "Too many arguments line %d.", lineno); - return false; - } - - PQclear(results); - break; - case PGRES_EMPTY_QUERY: - /* do nothing */ - register_error(-1, "Empty query line %d.", lineno); - break; - case PGRES_COMMAND_OK: - status = true; - ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results)); - break; - case PGRES_NONFATAL_ERROR: - case PGRES_FATAL_ERROR: - case PGRES_BAD_RESPONSE: - ECPGlog("ECPGdo line %d: Error: %s", - lineno, PQerrorMessage(simple_connection)); - register_error(-1, "Error: %s line %d.", - PQerrorMessage(simple_connection), lineno); - break; - case PGRES_COPY_OUT: - ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno); - PQendcopy(results->conn); - break; - case PGRES_COPY_IN: - ECPGlog("ECPGdo line %d: Got PGRES_COPY_IN ... tossing.\n", lineno); - PQendcopy(results->conn); - break; - default: - ECPGlog("ECPGdo line %d: Got something else, postgres error.\n", - lineno); - register_error(-1, "Postgres error line %d.", lineno); - break; - } - - /* check for asynchronous returns */ - notify = PQnotifies(simple_connection); - if (notify) { - ECPGlog("ECPGdo line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n", - lineno, notify->relname, notify->be_pid); - free(notify); - } - - va_end(ap); - return status; -} - - -bool -ECPGcommit(int lineno) -{ - PGresult *res; - - ECPGlog("ECPGcommit line %d\n", lineno); - if ((res = PQexec (simple_connection, "end")) == NULL) { - register_error(-1, "Error committing line %d.", lineno); - return (FALSE); - } - PQclear (res); - committed = 1; - return (TRUE); -} - -bool -ECPGrollback(int lineno) -{ - PGresult *res; - - ECPGlog("ECPGrollback line %d\n", lineno); - if ((res = PQexec (simple_connection, "abort")) == NULL) { - register_error(-1, "Error rolling back line %d.", lineno); - return (FALSE); - } - PQclear (res); - committed = 1; - return(TRUE); -} - - - -bool -ECPGsetdb(PGconn * newcon) -{ - ECPGfinish(); - simple_connection = newcon; - return true; -} - -bool -ECPGconnect(const char * dbname) -{ - char * name = strdup(dbname); - ECPGlog("ECPGconnect: opening database %s\n", name); - - sqlca.sqlcode = 0; - - ECPGsetdb(PQsetdb(NULL, NULL, NULL, NULL, name)); - - free(name); - name = NULL; - - 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); - return false; - } - return true; -} - - -bool -ECPGstatus() -{ - return PQstatus(simple_connection) != CONNECTION_BAD; -} - - -bool -ECPGfinish() -{ - if (simple_connection != NULL) - { - ECPGlog("ECPGfinish: finishing.\n"); - PQfinish(simple_connection); - } - else - ECPGlog("ECPGfinish: called an extra time.\n"); - return true; -} - -void -ECPGdebug(int n) -{ - simple_debug = n; - ECPGlog("ECPGdebug: set to %d\n", simple_debug); -} - -void -ECPGlog(const char * format, ...) -{ - va_list ap; - if (simple_debug) - { - char * f = (char *) malloc(strlen(format) + 100); - - sprintf(f, "[%d]: %s", getpid(), format); - - va_start(ap, format); - vfprintf(stderr, f, ap); - va_end(ap); - - free(f); - } -} diff --git a/src/interfaces/ecpg/src/preproc/Makefile.in b/src/interfaces/ecpg/src/preproc/Makefile.in deleted file mode 100644 index 2dca134124..0000000000 --- a/src/interfaces/ecpg/src/preproc/Makefile.in +++ /dev/null @@ -1,36 +0,0 @@ -POSTGRESTOP=@POSTGRESERVER@ -POSTGRES_BIN=$(POSTGRESTOP)/bin -POSTGRES_LIB=$(POSTGRESTOP)/lib - -CC=@CC@ -LEX=@LEX@ -LEXLIB=@LEXLIB@ -YACC=@YACC@ - - -CFLAGS=-I../include -O2 -g -Wall - -all:: ecpg - -clean:: - rm -f *.o core a.out ecpg y.tab.h y.tab.c *~ - -install:: all - install -c -d -m755 $(POSTGRES_LIB)/ecpg - install -c -m555 preproc $(POSTGRES_LIB)/ecpg - install -c -m555 ecpg $(POSTGRES_BIN) - -uninstall:: - rm -f $(POSTGRES_BIN)/ecpg - rm -f $(POSTGRES_LIB)/ecpg/preproc - -# Rule that really do something. -ecpg: y.tab.o pgc.o type.o ecpg.o - $(CC) -g -O2 -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o -L../lib -lecpg $(LEXLIB) - -y.tab.h y.tab.c: preproc.y - $(YACC) -d $< - -y.tab.o : y.tab.h ../include/ecpgtype.h -type.o : ../include/ecpgtype.h -pgc.o : ../include/ecpgtype.h diff --git a/src/interfaces/ecpg/src/preproc/ecpg.in b/src/interfaces/ecpg/src/preproc/ecpg.in deleted file mode 100644 index b032cada7f..0000000000 --- a/src/interfaces/ecpg/src/preproc/ecpg.in +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -INFILE= -OUTFILE= - -for arg -do - case "$arg" in - iname=*) - INFILE=`expr substr $arg 7 1000` - ;; - oname=*) - OUTFILE=`expr substr $arg 7 1000` - ;; - *) - echo Wrong argument $arg - exit 1; - ;; - esac -done - -if [ -n "$INFILE" -a -n "$OUTFILE" ] -then - exec @POSTGRESERVER@/lib/ecpg/preproc < $INFILE > $OUTFILE -else - echo Missing arguments. - echo usage: $0 iname=file oname=outfile - exit 1; -fi - -exit 0; diff --git a/src/interfaces/ecpg/src/test/Makefile b/src/interfaces/ecpg/src/test/Makefile deleted file mode 100644 index 219fb54e4f..0000000000 --- a/src/interfaces/ecpg/src/test/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -test2: test2.c - gcc -g -I ../include -I ../../../libpq -o test2 test2.c ../lib/libecpg.a ../../../libpq/libpq.a -lcrypt -test2.c: test2.pgc - ../preproc/ecpg test2.pgc -clean: - /bin/rm test2 test2.c diff --git a/src/interfaces/ecpg/src/test/test2 b/src/interfaces/ecpg/src/test/test2 deleted file mode 100755 index 34b86808cd..0000000000 Binary files a/src/interfaces/ecpg/src/test/test2 and /dev/null differ diff --git a/src/interfaces/ecpg/src/test/test2.c b/src/interfaces/ecpg/src/test/test2.c deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/interfaces/ecpg/src/test/test2.qc b/src/interfaces/ecpg/src/test/test2.qc deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile new file mode 100644 index 0000000000..0ec008964e --- /dev/null +++ b/src/interfaces/ecpg/test/Makefile @@ -0,0 +1,14 @@ +all: test2 perftest + +test2: test2.c + gcc -g -I ../include -I ../../../libpq -o test2 test2.c ../lib/libecpg.a ../../../libpq/libpq.a -lcrypt +test2.c: test2.pgc + ../preproc/ecpg test2.pgc + +perftest: perftest.c + gcc -g -I ../include -I ../../../libpq -o perftest perftest.c ../lib/libecpg.a ../../../libpq/libpq.a -lcrypt +perftest.c: perftest.pgc + ../preproc/ecpg perftest.pgc + +clean: + /bin/rm test2 test2.c perftest perftest.c diff --git a/src/interfaces/ecpg/src/test/Ptest1.c b/src/interfaces/ecpg/test/Ptest1.c similarity index 100% rename from src/interfaces/ecpg/src/test/Ptest1.c rename to src/interfaces/ecpg/test/Ptest1.c diff --git a/src/interfaces/ecpg/test/perftest.pgc b/src/interfaces/ecpg/test/perftest.pgc new file mode 100644 index 0000000000..9fb63fe6fa --- /dev/null +++ b/src/interfaces/ecpg/test/perftest.pgc @@ -0,0 +1,72 @@ +#include +#include +#include + +exec sql include sqlca; + +#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 () +{ +exec sql begin declare section; + long i; +exec sql end declare section; + struct timeval tvs, tve; + + gettimeofday(&tvs, NULL); + + exec sql connect 'mm'; + if (SQLCODE) + db_error ("connect"); + + exec sql create table perftest(number int4, ascii char16); + if (SQLCODE) + db_error ("create t"); + + exec sql create unique index number on perftest(number); + if (SQLCODE) + db_error ("create i"); + + for (i = 0;i < 1407; i++) + { + exec sql begin declare section; + char text[16]; + exec sql end declare section; + + sprintf(text, "%ld", i); + exec sql insert into perftest(number, ascii) values (:i, :text); + if (SQLCODE) + db_error ("insert"); + + exec sql commit; + if (SQLCODE) + db_error ("commit"); + } + + exec sql drop index number; + if (SQLCODE) + db_error ("drop i"); + + exec sql drop table perftest; + if (SQLCODE) + db_error ("drop t"); + + exec sql commit; + if (SQLCODE) + db_error ("commit"); + + gettimeofday(&tve, NULL); + + printf("I needed %ld seconds and %ld microseconds for this test\n", tve.tv_sec - tvs.tv_sec, tve.tv_usec - tvs.tv_usec); + + return (0); +} diff --git a/src/interfaces/ecpg/src/test/test1.c b/src/interfaces/ecpg/test/test1.c similarity index 100% rename from src/interfaces/ecpg/src/test/test1.c rename to src/interfaces/ecpg/test/test1.c diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc new file mode 100644 index 0000000000..5e94495087 --- /dev/null +++ b/src/interfaces/ecpg/test/test2.pgc @@ -0,0 +1,50 @@ +exec sql include sqlca; + +#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 () +{ +exec sql begin declare section; + varchar text[8]; + int count; + double control; +exec sql end declare section; + + exec sql connect 'mm'; + if (SQLCODE) + db_error ("connect"); + + exec sql declare cur cursor for + select text, control, count from test; + if (SQLCODE) db_error ("declare"); + + exec sql open cur; + if (SQLCODE) + db_error ("open"); + + while (1) { + exec sql fetch in cur into :text, :control, :count; + if (SQLCODE) + break; + printf ("%8.8s %d %f\n", text.arr, count, control); + } + + 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); +}