]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Erk, the whole directory structure changed on us here...
authorMarc G. Fournier <scrappy@hub.org>
Tue, 10 Feb 1998 16:44:17 +0000 (16:44 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Tue, 10 Feb 1998 16:44:17 +0000 (16:44 +0000)
31 files changed:
src/interfaces/ecpg/include/Makefile [new file with mode: 0644]
src/interfaces/ecpg/include/Makefile.in [new file with mode: 0644]
src/interfaces/ecpg/include/ecpglib.h [moved from src/interfaces/ecpg/src/include/ecpglib.h with 94% similarity]
src/interfaces/ecpg/include/ecpgtype.h [moved from src/interfaces/ecpg/src/include/ecpgtype.h with 98% similarity]
src/interfaces/ecpg/include/sqlca.h [moved from src/interfaces/ecpg/src/include/sqlca.h with 100% similarity]
src/interfaces/ecpg/lib/Makefile [moved from src/interfaces/ecpg/src/lib/Makefile with 61% similarity]
src/interfaces/ecpg/lib/Makefile.in [moved from src/interfaces/ecpg/src/lib/Makefile.in with 64% similarity]
src/interfaces/ecpg/lib/ecpglib.c [new file with mode: 0644]
src/interfaces/ecpg/lib/typename.c [moved from src/interfaces/ecpg/src/lib/typename.c with 94% similarity]
src/interfaces/ecpg/preproc/Makefile [moved from src/interfaces/ecpg/src/preproc/Makefile with 51% similarity]
src/interfaces/ecpg/preproc/Makefile.in [new file with mode: 0644]
src/interfaces/ecpg/preproc/ecpg.c [moved from src/interfaces/ecpg/src/preproc/ecpg.c with 84% similarity]
src/interfaces/ecpg/preproc/pgc.l [moved from src/interfaces/ecpg/src/preproc/pgc.l with 94% similarity]
src/interfaces/ecpg/preproc/preproc.y [moved from src/interfaces/ecpg/src/preproc/preproc.y with 90% similarity]
src/interfaces/ecpg/preproc/type.c [moved from src/interfaces/ecpg/src/preproc/type.c with 87% similarity]
src/interfaces/ecpg/preproc/type.h [moved from src/interfaces/ecpg/src/preproc/type.h with 100% similarity]
src/interfaces/ecpg/preproc/y.tab.h [new file with mode: 0644]
src/interfaces/ecpg/src/include/Makefile [deleted file]
src/interfaces/ecpg/src/include/Makefile.in [deleted file]
src/interfaces/ecpg/src/lib/ecpglib.c [deleted file]
src/interfaces/ecpg/src/preproc/Makefile.in [deleted file]
src/interfaces/ecpg/src/preproc/ecpg.in [deleted file]
src/interfaces/ecpg/src/test/Makefile [deleted file]
src/interfaces/ecpg/src/test/test2 [deleted file]
src/interfaces/ecpg/src/test/test2.c [deleted file]
src/interfaces/ecpg/src/test/test2.qc [deleted file]
src/interfaces/ecpg/test/Makefile [new file with mode: 0644]
src/interfaces/ecpg/test/Ptest1.c [moved from src/interfaces/ecpg/src/test/Ptest1.c with 100% similarity]
src/interfaces/ecpg/test/perftest.pgc [new file with mode: 0644]
src/interfaces/ecpg/test/test1.c [moved from src/interfaces/ecpg/src/test/test1.c with 100% similarity]
src/interfaces/ecpg/test/test2.pgc [new file with mode: 0644]

diff --git a/src/interfaces/ecpg/include/Makefile b/src/interfaces/ecpg/include/Makefile
new file mode 100644 (file)
index 0000000..08bc9df
--- /dev/null
@@ -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 (file)
index 0000000..2f5c63a
--- /dev/null
@@ -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
similarity index 94%
rename from src/interfaces/ecpg/src/include/ecpglib.h
rename to src/interfaces/ecpg/include/ecpglib.h
index b880182e0bdf9771fe323b7fe8e637ef3be80faa..1fb35f8dfee58431311892ee8ad5f9e2d1b5936c 100644 (file)
@@ -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);
similarity index 98%
rename from src/interfaces/ecpg/src/include/ecpgtype.h
rename to src/interfaces/ecpg/include/ecpgtype.h
index cc56b78cbb3d90c505b530722a9bf1dbba21b72d..496c934f4f4cbba98057fabd0858d91eb39e6c02 100644 (file)
 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)
similarity index 61%
rename from src/interfaces/ecpg/src/lib/Makefile
rename to src/interfaces/ecpg/lib/Makefile
index d227f6df3649ff6da64667721cd9b74e24862392..e3722e8aec1b3ec5d3fc155fddb44d300e838946 100644 (file)
@@ -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)
similarity index 64%
rename from src/interfaces/ecpg/src/lib/Makefile.in
rename to src/interfaces/ecpg/lib/Makefile.in
index 07d126bd5c6470cb9bac068f84a0fea7ab8600ea..7ed351ab7a9b2ba601267475c49fdb19f43be15a 100644 (file)
@@ -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 (file)
index 0000000..80e9b0f
--- /dev/null
@@ -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);
+       }
+}
similarity index 94%
rename from src/interfaces/ecpg/src/lib/typename.c
rename to src/interfaces/ecpg/lib/typename.c
index c1789572057c00173ec8602bb2a5fd06bf6fe501..55756037b30d51b8969667b6c9a9e6a0d98f6c50 100644 (file)
@@ -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();
     }
similarity index 51%
rename from src/interfaces/ecpg/src/preproc/Makefile
rename to src/interfaces/ecpg/preproc/Makefile
index 9a53fb1b4322e828b7daf0a7f1b754862dd5a084..8cc8b7cb3aa27e7bf7a75d43c319951ec224e345 100644 (file)
@@ -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 (file)
index 0000000..f3cb049
--- /dev/null
@@ -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
similarity index 84%
rename from src/interfaces/ecpg/src/preproc/ecpg.c
rename to src/interfaces/ecpg/preproc/ecpg.c
index a7d96072af9101709e654b16228e3296924d3d65..08f4a3952505eb6ad8b90cc412badbb836e1c5e4 100644 (file)
@@ -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);
similarity index 94%
rename from src/interfaces/ecpg/src/preproc/pgc.l
rename to src/interfaces/ecpg/preproc/pgc.l
index 857561df9c5d6586fc7054e3171330201e950189..7ab3c5764f20e8ffc6212c5c8e3a4498e6df4e66 100644 (file)
@@ -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;
 }
similarity index 90%
rename from src/interfaces/ecpg/src/preproc/preproc.y
rename to src/interfaces/ecpg/preproc/preproc.y
index f53c9a561333a15aa7ff88f544fc5b83804eccbd..b5a30c0d196b4cf929dd802adc60eedd545c0e27 100644 (file)
@@ -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
similarity index 87%
rename from src/interfaces/ecpg/src/preproc/type.c
rename to src/interfaces/ecpg/preproc/type.c
index a54cbd801db69b90a0307af33c7a4aad5f84845a..e3ee2f003ab303e24a97073358f6b429cf32db39 100644 (file)
@@ -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/preproc/y.tab.h b/src/interfaces/ecpg/preproc/y.tab.h
new file mode 100644 (file)
index 0000000..b2fadd6
--- /dev/null
@@ -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 (file)
index 3b001ab..0000000
+++ /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 (file)
index 80e0451..0000000
+++ /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 (file)
index d2c078e..0000000
+++ /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 (file)
index 2dca134..0000000
+++ /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 (file)
index b032cad..0000000
+++ /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 (file)
index 219fb54..0000000
+++ /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 (executable)
index 34b8680..0000000
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 (file)
index e69de29..0000000
diff --git a/src/interfaces/ecpg/src/test/test2.qc b/src/interfaces/ecpg/src/test/test2.qc
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
new file mode 100644 (file)
index 0000000..0ec0089
--- /dev/null
@@ -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/test/perftest.pgc b/src/interfaces/ecpg/test/perftest.pgc
new file mode 100644 (file)
index 0000000..9fb63fe
--- /dev/null
@@ -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/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc
new file mode 100644 (file)
index 0000000..5e94495
--- /dev/null
@@ -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);
+}