From 38201e21d0849a469e165085e4d12ac0969f5018 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" <scrappy@hub.org> Date: Tue, 10 Feb 1998 16:44:17 +0000 Subject: [PATCH] Erk, the whole directory structure changed on us here... --- src/interfaces/ecpg/include/Makefile | 16 + src/interfaces/ecpg/include/Makefile.in | 15 + .../ecpg/{src => }/include/ecpglib.h | 2 +- .../ecpg/{src => }/include/ecpgtype.h | 2 +- src/interfaces/ecpg/{src => }/include/sqlca.h | 0 src/interfaces/ecpg/{src => }/lib/Makefile | 16 +- src/interfaces/ecpg/{src => }/lib/Makefile.in | 16 +- src/interfaces/ecpg/lib/ecpglib.c | 648 ++++++++++++++++++ src/interfaces/ecpg/{src => }/lib/typename.c | 1 + .../ecpg/{src => }/preproc/Makefile | 26 +- src/interfaces/ecpg/preproc/Makefile.in | 32 + src/interfaces/ecpg/{src => }/preproc/ecpg.c | 22 +- src/interfaces/ecpg/{src => }/preproc/pgc.l | 12 +- .../ecpg/{src => }/preproc/preproc.y | 38 +- src/interfaces/ecpg/{src => }/preproc/type.c | 29 +- src/interfaces/ecpg/{src => }/preproc/type.h | 0 src/interfaces/ecpg/preproc/y.tab.h | 39 ++ src/interfaces/ecpg/src/include/Makefile | 16 - src/interfaces/ecpg/src/include/Makefile.in | 15 - src/interfaces/ecpg/src/lib/ecpglib.c | 609 ---------------- src/interfaces/ecpg/src/preproc/Makefile.in | 36 - src/interfaces/ecpg/src/preproc/ecpg.in | 31 - src/interfaces/ecpg/src/test/Makefile | 6 - src/interfaces/ecpg/src/test/test2 | Bin 71167 -> 0 bytes src/interfaces/ecpg/src/test/test2.c | 0 src/interfaces/ecpg/src/test/test2.qc | 0 src/interfaces/ecpg/test/Makefile | 14 + src/interfaces/ecpg/{src => }/test/Ptest1.c | 0 src/interfaces/ecpg/test/perftest.pgc | 72 ++ src/interfaces/ecpg/{src => }/test/test1.c | 0 src/interfaces/ecpg/test/test2.pgc | 50 ++ 31 files changed, 985 insertions(+), 778 deletions(-) create mode 100644 src/interfaces/ecpg/include/Makefile create mode 100644 src/interfaces/ecpg/include/Makefile.in rename src/interfaces/ecpg/{src => }/include/ecpglib.h (94%) rename src/interfaces/ecpg/{src => }/include/ecpgtype.h (98%) rename src/interfaces/ecpg/{src => }/include/sqlca.h (100%) rename src/interfaces/ecpg/{src => }/lib/Makefile (61%) rename src/interfaces/ecpg/{src => }/lib/Makefile.in (64%) create mode 100644 src/interfaces/ecpg/lib/ecpglib.c rename src/interfaces/ecpg/{src => }/lib/typename.c (94%) rename src/interfaces/ecpg/{src => }/preproc/Makefile (51%) create mode 100644 src/interfaces/ecpg/preproc/Makefile.in rename src/interfaces/ecpg/{src => }/preproc/ecpg.c (84%) rename src/interfaces/ecpg/{src => }/preproc/pgc.l (94%) rename src/interfaces/ecpg/{src => }/preproc/preproc.y (90%) rename src/interfaces/ecpg/{src => }/preproc/type.c (87%) rename src/interfaces/ecpg/{src => }/preproc/type.h (100%) create mode 100644 src/interfaces/ecpg/preproc/y.tab.h delete mode 100644 src/interfaces/ecpg/src/include/Makefile delete mode 100644 src/interfaces/ecpg/src/include/Makefile.in delete mode 100644 src/interfaces/ecpg/src/lib/ecpglib.c delete mode 100644 src/interfaces/ecpg/src/preproc/Makefile.in delete mode 100644 src/interfaces/ecpg/src/preproc/ecpg.in delete mode 100644 src/interfaces/ecpg/src/test/Makefile delete mode 100755 src/interfaces/ecpg/src/test/test2 delete mode 100644 src/interfaces/ecpg/src/test/test2.c delete mode 100644 src/interfaces/ecpg/src/test/test2.qc create mode 100644 src/interfaces/ecpg/test/Makefile rename src/interfaces/ecpg/{src => }/test/Ptest1.c (100%) create mode 100644 src/interfaces/ecpg/test/perftest.pgc rename src/interfaces/ecpg/{src => }/test/test1.c (100%) create mode 100644 src/interfaces/ecpg/test/test2.pgc diff --git a/src/interfaces/ecpg/include/Makefile b/src/interfaces/ecpg/include/Makefile new file mode 100644 index 00000000000..08bc9df7f2d --- /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 00000000000..2f5c63ab078 --- /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 b880182e0bd..1fb35f8dfee 100644 --- a/src/interfaces/ecpg/src/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -1,6 +1,6 @@ #include <c.h> -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 cc56b78cbb3..496c934f4f4 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 d227f6df364..e3722e8aec1 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 07d126bd5c6..7ed351ab7a9 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 00000000000..80e9b0fd9c4 --- /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 <meskes@debian.org> + on Feb. 5th, 1998 */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> +#include <string.h> + +#include <ecpgtype.h> +#include <ecpglib.h> +#include <sqlca.h> +#include <libpq-fe.h> +#include <libpq/pqcomm.h> + +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 c1789572057..55756037b30 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 9a53fb1b432..8cc8b7cb3aa 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 00000000000..f3cb049e8c3 --- /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 a7d96072af9..08f4a395250 100644 --- a/src/interfaces/ecpg/src/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -8,10 +8,9 @@ #include <strings.h> 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 857561df9c5..7ab3c5764f2 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; } <SQL>{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 f53c9a56133..b5a30c0d196 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 <tagname> S_VARCHAR S_VARCHAR2 %token <tagname> S_EXTERN S_STATIC %token <tagname> S_UNSIGNED S_SIGNED -%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE +%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL %token <tagname> '[' ']' ';' ',' %type <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 { $<type_enum>$ = ECPGt_char; } | S_LONG { $<type_enum>$ = ECPGt_long; } | S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; } | S_FLOAT { $<type_enum>$ = ECPGt_float; } - | S_DOUBLE { $<type_enum>$ = ECPGt_double; }; + | S_DOUBLE { $<type_enum>$ = ECPGt_double; } + | S_BOOL { $<type_enum>$ = 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 { $<indexsize>$ = 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 a54cbd801db..e3ee2f003ab 100644 --- a/src/interfaces/ecpg/src/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -1,6 +1,5 @@ #include <stdio.h> #include <string.h> -#include <stdlib.h> #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 00000000000..b2fadd683bf --- /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 3b001abaaf0..00000000000 --- 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 80e0451e2b5..00000000000 --- 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 d2c078e2d01..00000000000 --- 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 <meskes@debian.org> - on Feb. 5th, 1998 */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdarg.h> -#include <string.h> - -#include <ecpgtype.h> -#include <ecpglib.h> -#include <sqlca.h> -#include <libpq-fe.h> -#include <libpq/pqcomm.h> - -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 2dca1341245..00000000000 --- 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 b032cada7fd..00000000000 --- 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 219fb54e4f8..00000000000 --- 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 34b86808cd05b730a8ddb891f02891ac9a37d383..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71167 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 G{Qm<6Q&;W) diff --git a/src/interfaces/ecpg/src/test/test2.c b/src/interfaces/ecpg/src/test/test2.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/interfaces/ecpg/src/test/test2.qc b/src/interfaces/ecpg/src/test/test2.qc deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile new file mode 100644 index 00000000000..0ec008964e5 --- /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 00000000000..9fb63fe6fad --- /dev/null +++ b/src/interfaces/ecpg/test/perftest.pgc @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <sys/time.h> +#include <unistd.h> + +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 00000000000..5e944950876 --- /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); +} -- GitLab