New version of the driver with libpq based comms layer, courtesy of Anoop Kumar of...
authorDave Page <dpage@pgadmin.org>
Wed, 13 Jul 2005 14:23:36 +0000 (14:23 +0000)
committerDave Page <dpage@pgadmin.org>
Wed, 13 Jul 2005 14:23:36 +0000 (14:23 +0000)
44 files changed:
Makefile.am
README.unix
bind.h
columninfo.c
columninfo.h
configure.ac
connection.c
connection.h
convert.c
descriptor.c
dlg_specific.c
dlg_specific.h
drvconn.c
environ.c
execute.c
info.c
info30.c
installer/Make.bat
libpqconnection.h [new file with mode: 0644]
lobj.c
lobj.h
misc.c
multibyte.c
odbcapi.c
odbcapi30.c
odbcapi30w.c
odbcapiw.c
options.c
parse.c
pgapi30.c
pgtypes.c
psqlodbc.c
psqlodbc.h
psqlodbc.rc
qresult.c
qresult.h
readme.txt
results.c
setup.c
socket.c
statement.c
tuplelist.c
version.h
win32.mak

index dff8ccb6dcd785bf1818e647a0169ac6bc1160ce..65069d19b23c8775dbaa79f0ba5797e79290c6e6 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile.am for psqlodbc (PostgreSQL ODBC driver)
 #
-# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.17 2005/03/02 14:37:52 dpage Exp $
+# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.18 2005/07/13 14:23:34 dpage Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -23,7 +23,7 @@ psqlodbc_la_SOURCES = \
 psqlodbc_la_SOURCES += \
    bind.h columninfo.h connection.h convert.h descriptor.h \
    dlg_specific.h environ.h \
-   lobj.h md5.h misc.h multibyte.h pgapifunc.h pgtypes.h \
+   lobj.h libpqconnection.h md5.h misc.h multibyte.h pgapifunc.h pgtypes.h \
    psqlodbc.h qresult.h resource.h socket.h statement.h tuple.h \
    tuplelist.h version.h
 
index 8943e492f10ea67923987626bf5d437894599690..ce974ebd08e97988f90d4aa4ebf255eb07f6f2e9 100644 (file)
@@ -21,6 +21,9 @@ The configure script will accept the following useful options:
 --with-iodbc
 --with-unixodbc
 --with-odbcinst=DIR
+--with-libpq   (build a libpq enabled version of psqlodbc. default = yes)
+--with-pgsql-include=DIR  (Look for postgreSQL include files in DIR if libpq is enabled)
+--with-pgsql=DIR        (look for PostgreSQL libraries and headers in DIR if libpq is enabled)
 --enable-pthreads (thread-safe driver on some platforms)
 --help
 
diff --git a/bind.h b/bind.h
index cd9fb0cda4c684dd7d5262688c1ae8be95781a94..16d08fa613073cfe4c424b35aa13aac7e7e4779c 100644 (file)
--- a/bind.h
+++ b/bind.h
@@ -10,7 +10,9 @@
 #define __BIND_H__
 
 #include "psqlodbc.h"
-
+#ifdef USE_LIBPQ
+#include <libpq-fe.h>
+#endif /* USE_LIBPQ */
 /*
  * BindInfoClass -- stores information about a bound column
  */
index 6897711be384bc600bb5c01bcb9a851e890d24b4..42438cd6fc7f347ce96a49fbdbb2f0d583a7b7f2 100644 (file)
 #include "pgtypes.h"
 #include "columninfo.h"
 
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
 #include "socket.h"
+#endif /* USE_LIBPQ*/
+
 #include <stdlib.h>
 #include <string.h>
 #include "pgapifunc.h"
@@ -51,6 +56,17 @@ CI_Destructor(ColumnInfoClass *self)
 }
 
 
+#ifdef USE_LIBPQ
+
+/* Reading Fields part is already done in the mapping part, skipping it while using Libpq */
+char
+CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
+{
+   return 'T';
+}
+
+#else
+
 /*
  * Read in field descriptions.
  * If self is not null, then also store the information.
@@ -120,6 +136,7 @@ CI_read_fields(ColumnInfoClass *self, ConnectionClass *conn)
    return (SOCK_get_errcode(sock) == 0);
 }
 
+#endif /* USE_LIBPQ */
 
 void
 CI_free_memory(ColumnInfoClass *self)
index 41e9400dceaad9856b9588590f5ccbe3da37b46b..5f9951f2af86fdf6be7eaa9ee99c76a2d79178a1 100644 (file)
@@ -10,7 +10,9 @@
 #define __COLUMNINFO_H__
 
 #include "psqlodbc.h"
-
+#ifdef USE_LIBPQ
+#include <libpq-fe.h>
+#endif /* USE_LIBPQ */
 struct ColumnInfoClass_
 {
    Int2        num_fields;
index 247d070d194801b9037482f3f20b108b8d2f650a..6b0ab8f5b9499276932fa12730f8f1e1654c69ed 100644 (file)
@@ -1,5 +1,5 @@
 # Process this file with autoconf to produce a configure script.
-AC_INIT(psqlodbc, 08.00.0102, [pgsql-odbc@postgresql.org])
+AC_INIT(psqlodbc, 08.01.0001, [pgsql-odbc@postgresql.org])
 AC_PREREQ(2.52)
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([bind.c])
@@ -44,7 +44,6 @@ if test "$with_iodbc" = yes; then
   AC_DEFINE(WITH_IODBC, 1, [Define to 1 to build with iODBC support])
 fi
 
-
 #
 # Default odbc version number (--with-odbcver), default 0x0300
 #
@@ -56,7 +55,6 @@ AC_MSG_RESULT([$with_odbcver])
 AC_DEFINE_UNQUOTED(ODBCVER, [$with_odbcver], [Define to ODBC version (--with-odbcver)])
 
 AC_CHECK_FUNCS(strtoul strtoll)
-AC_CHECK_LIB(socket, socket)
 
 # to implement the thread-safe driver
 PGAC_ARG_BOOL(enable, pthreads, no,
@@ -107,5 +105,99 @@ AC_C_CONST
 AC_TYPE_SIZE_T
 AC_STRUCT_TM
 
+#Decide whether libpq or socket based driver to be built 
+PGAC_ARG_BOOL(with, libpq, yes,
+          [  --with-libpq            build libpq enabled odbc driver(default)],[use_libpq=yes],[use_libpq=no])
+
+#
+#Options for pgsql headers and libraries
+#
+if test "$use_libpq" = "yes"; then
+        AC_MSG_CHECKING(for pgsql include files)
+        AC_ARG_WITH(pgsql-include,
+        [  --with-pgsql-include=DIR  Look for postgreSQL include files in DIR],
+        [if test "$withval" != no; then
+            AC_MSG_RESULT(yes)
+            pgsql_include="$withval"
+        else
+            AC_MSG_RESULT(no)
+            AC_MSG_ERROR([you must specify a directory when using --with-pgsql-include=DIR])
+         fi])
+fi
+
+#
+# Library directories
+#
+if test "$use_libpq" = "yes"; then
+        AC_MSG_CHECKING(for pgsql)
+        AC_ARG_WITH(pgsql,
+        [  --with-pgsql=DIR        look for PostgreSQL libraries and headers in DIR],
+        [if test "$withval" != no
+        then
+            AC_MSG_RESULT(yes)
+            LIBPQ_HOME="$withval"
+        else
+            AC_MSG_RESULT(no)
+        fi], [
+        AC_MSG_RESULT(yes)
+        LIBPQ_HOME="/usr/local/pgsql"
+        if test "$pgsql_include" = ""
+        then
+                if test ! -f "${LIBPQ_HOME}/include/libpq-fe.h"
+                then
+                    LIBPQ_HOME=/usr/local
+                    if test ! -f "${LIBPQ_HOME}/include/libpq-fe.h"
+                    then
+                        LIBPQ_HOME=/usr
+                    fi
+                fi
+                if test -f "/usr/include/libpq-fe.h"
+                then
+                    pgsql_include="/usr/include"
+                else
+                    if test -f "/usr/include/pgsql/libpq-fe.h"
+                    then
+                        pgsql_include="/usr/include/pgsql"
+                    fi
+                fi
+         fi
+   ])
+#
+# Check for libpq libraries and headers
+#
+        if test -n "${LIBPQ_HOME}"
+        then
+            OLD_LDFLAGS="$LDFLAGS"
+            OLD_CPPFLAGS="$CPPFLAGS"
+            LDFLAGS="$LDFLAGS -L${LIBPQ_HOME}/lib"
+            AC_CHECK_LIB(pq, PQexec, [pgsql_cv_libpq=yes], [pgsql_cv_libpq=no])
+
+            if test "$pgsql_include" != ""
+            then
+                CPPFLAGS="$CPPFLAGS -I${pgsql_include}"
+            else
+                CPPFLAGS="$CPPFLAGS -I${LIBPQ_HOME}/include"
+            fi
+            AC_CHECK_HEADER(libpq-fe.h, [pgsql_cv_libpqfe_h=yes], [pgsql_cv_libpqfe_h=no])
+
+            if test "$pgsql_cv_libpq" = "yes" -a "$pgsql_cv_libpqfe_h" = "yes"
+            then
+                AC_MSG_CHECKING(pgsql in ${LIBPQ_HOME})
+                AC_MSG_RESULT(ok)
+            else
+                AC_MSG_CHECKING(pgsql in ${LIBPQ_HOME})
+                AC_MSG_RESULT(failed)
+                LDFLAGS="$OLD_LDFLAGS"
+                CPPFLAGS="$OLD_CPPFLAGS"
+                AC_MSG_ERROR([you must specify a valid pgsql installation with --with-pgsql=DIR])
+            fi
+            LIBS="$LIBS -lpq"
+            CPPFLAGS="$CPPFLAGS -DUSE_LIBPQ"
+
+        fi
+else
+        AC_CHECK_LIB(socket, socket)
+fi
+
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
index deda5808d97703e5abc1dbd740ab592f6092a1f5..01e4ca8a6dfd4a1c0143e41b5d101c54fb59916e 100644 (file)
@@ -14,8 +14,6 @@
  */
 /* Multibyte support   Eiji Tokuya 2001-03-15 */
 
-#include "connection.h"
-
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
@@ -24,7 +22,6 @@
 #endif /* WIN32 */
 
 #include "environ.h"
-#include "socket.h"
 #include "statement.h"
 #include "qresult.h"
 #include "lobj.h"
 
 extern GLOBAL_VALUES globals;
 
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#include "pgtypes.h"
+#include <libpq-fe.h>
+#else
+#include "connection.h"
+#include "socket.h"
+#endif /* USE_LIBPQ */
+
 
 RETCODE        SQL_API
 PGAPI_AllocConnect(
@@ -245,118 +251,6 @@ CC_conninfo_init(ConnInfo *conninfo)
        conninfo->use_server_side_prepare = -1;
        memcpy(&(conninfo->drivers), &globals, sizeof(globals));
 }
-/*
- *     IMPLEMENTATION CONNECTION CLASS
- */
-ConnectionClass *
-CC_Constructor()
-{
-   ConnectionClass *rv;
-
-   rv = (ConnectionClass *) malloc(sizeof(ConnectionClass));
-
-   if (rv != NULL)
-   {
-       rv->henv = NULL;        /* not yet associated with an environment */
-
-       rv->__error_message = NULL;
-       rv->__error_number = 0;
-       rv->errormsg_created = FALSE;
-
-       rv->status = CONN_NOT_CONNECTED;
-       rv->transact_status = CONN_IN_AUTOCOMMIT;       /* autocommit by default */
-
-       CC_conninfo_init(&(rv->connInfo));
-       rv->sock = SOCK_Constructor(rv);
-       if (!rv->sock)
-           return NULL;
-
-       rv->stmts = (StatementClass **) malloc(sizeof(StatementClass *) * STMT_INCREMENT);
-       if (!rv->stmts)
-           return NULL;
-       memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT);
-
-       rv->num_stmts = STMT_INCREMENT;
-       rv->descs = (DescriptorClass **) malloc(sizeof(DescriptorClass *) * STMT_INCREMENT);
-       if (!rv->descs)
-           return NULL;
-       memset(rv->descs, 0, sizeof(DescriptorClass *) * STMT_INCREMENT);
-
-       rv->num_descs = STMT_INCREMENT;
-
-       rv->lobj_type = PG_TYPE_LO_UNDEFINED;
-
-       rv->ntables = 0;
-       rv->col_info = NULL;
-
-       rv->translation_option = 0;
-       rv->translation_handle = NULL;
-       rv->DataSourceToDriver = NULL;
-       rv->DriverToDataSource = NULL;
-       rv->driver_version = ODBCVER;
-       memset(rv->pg_version, 0, sizeof(rv->pg_version));
-       rv->pg_version_number = .0;
-       rv->pg_version_major = 0;
-       rv->pg_version_minor = 0;
-       rv->ms_jet = 0;
-       rv->unicode = 0;
-       rv->result_uncommitted = 0;
-       rv->schema_support = 0;
-       rv->isolation = SQL_TXN_READ_COMMITTED;
-       rv->client_encoding = NULL;
-       rv->server_encoding = NULL;
-       rv->current_schema = NULL;
-       rv->num_discardp = 0;
-       rv->discardp = NULL;
-
-       /* Initialize statement options to defaults */
-       /* Statements under this conn will inherit these options */
-
-       InitializeStatementOptions(&rv->stmtOptions);
-       InitializeARDFields(&rv->ardOptions);
-       InitializeAPDFields(&rv->apdOptions);
-       INIT_CONN_CS(rv);
-   }
-   return rv;
-}
-
-
-char
-CC_Destructor(ConnectionClass *self)
-{
-   mylog("enter CC_Destructor, self=%u\n", self);
-
-   if (self->status == CONN_EXECUTING)
-       return 0;
-
-   CC_cleanup(self);           /* cleanup socket and statements */
-
-   mylog("after CC_Cleanup\n");
-
-   /* Free up statement holders */
-   if (self->stmts)
-   {
-       free(self->stmts);
-       self->stmts = NULL;
-   }
-
-   if (self->descs)
-   {
-       free(self->descs);
-       self->descs = NULL;
-   }
-
-   mylog("after free statement holders\n");
-
-   if (self->__error_message)
-       free(self->__error_message);
-   DELETE_CONN_CS(self);
-   free(self);
-
-   mylog("exit CC_Destructor\n");
-
-   return 1;
-}
 
 
 /* Return how many cursors are opened on this connection */
@@ -462,121 +356,6 @@ CC_abort(ConnectionClass *self)
 }
 
 
-/* This is called by SQLDisconnect also */
-char
-CC_cleanup(ConnectionClass *self)
-{
-   int         i;
-   StatementClass *stmt;
-   DescriptorClass *desc;
-
-   if (self->status == CONN_EXECUTING)
-       return FALSE;
-
-   mylog("in CC_Cleanup, self=%u\n", self);
-
-   /* Cancel an ongoing transaction */
-   /* We are always in the middle of a transaction, */
-   /* even if we are in auto commit. */
-   if (self->sock)
-   {
-       CC_abort(self);
-
-       mylog("after CC_abort\n");
-
-       /* This actually closes the connection to the dbase */
-       SOCK_Destructor(self->sock);
-       self->sock = NULL;
-   }
-
-   mylog("after SOCK destructor\n");
-
-   /* Free all the stmts on this connection */
-   for (i = 0; i < self->num_stmts; i++)
-   {
-       stmt = self->stmts[i];
-       if (stmt)
-       {
-           stmt->hdbc = NULL;  /* prevent any more dbase interactions */
-
-           SC_Destructor(stmt);
-
-           self->stmts[i] = NULL;
-       }
-   }
-
-   /* Free all the descs on this connection */
-   for (i = 0; i < self->num_descs; i++)
-   {
-       desc = self->descs[i];
-       if (desc)
-       {
-           DC_get_conn(desc) = NULL;   /* prevent any more dbase interactions */
-           DC_Destructor(desc);
-           free(desc);
-           self->descs[i] = NULL;
-       }
-   }
-
-   /* Check for translation dll */
-#ifdef WIN32
-   if (self->translation_handle)
-   {
-       FreeLibrary(self->translation_handle);
-       self->translation_handle = NULL;
-   }
-#endif
-
-   self->status = CONN_NOT_CONNECTED;
-   self->transact_status = CONN_IN_AUTOCOMMIT;
-   CC_conninfo_init(&(self->connInfo));
-   if (self->client_encoding)
-   {
-       free(self->client_encoding);
-       self->client_encoding = NULL;
-   }
-   if (self->server_encoding)
-   {
-       free(self->server_encoding);
-       self->server_encoding = NULL;
-   }
-   if (self->current_schema)
-   {
-       free(self->current_schema);
-       self->current_schema = NULL;
-   }
-   /* Free cached table info */
-   if (self->col_info)
-   {
-       for (i = 0; i < self->ntables; i++)
-       {
-           if (self->col_info[i]->result)  /* Free the SQLColumns result structure */
-               QR_Destructor(self->col_info[i]->result);
-
-           if (self->col_info[i]->schema)
-               free(self->col_info[i]->schema);
-           free(self->col_info[i]);
-       }
-       free(self->col_info);
-       self->col_info = NULL;
-   }
-   self->ntables = 0;
-   if (self->num_discardp > 0 && self->discardp)
-   {
-       for (i = 0; i < self->num_discardp; i++)
-           free(self->discardp[i]);
-       self->num_discardp = 0;
-   }
-   if (self->discardp)
-   {
-       free(self->discardp);
-       self->discardp = NULL;
-   }
-
-   mylog("exit CC_Cleanup\n");
-   return TRUE;
-}
-
 
 int
 CC_set_translation(ConnectionClass *self)
@@ -619,1547 +398,2586 @@ CC_set_translation(ConnectionClass *self)
    return TRUE;
 }
 
-static int
-md5_auth_send(ConnectionClass *self, const char *salt)
+
+char
+CC_add_statement(ConnectionClass *self, StatementClass *stmt)
 {
-   char    *pwd1 = NULL, *pwd2 = NULL;
-   ConnInfo   *ci = &(self->connInfo);
-   SocketClass *sock = self->sock;
+   int         i;
 
-   if (!(pwd1 = malloc(MD5_PASSWD_LEN + 1)))
-       return 1;
-   if (!EncryptMD5(ci->password, ci->username, strlen(ci->username), pwd1))
-   {
-       free(pwd1);
-       return 1;
-   } 
-   if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1)))
+   mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt);
+
+   for (i = 0; i < self->num_stmts; i++)
    {
-       free(pwd1);
-       return 1;
-   } 
-   if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2))
-   {
-       free(pwd2);
-       free(pwd1);
-       return 1;
+       if (!self->stmts[i])
+       {
+           stmt->hdbc = self;
+           self->stmts[i] = stmt;
+           return TRUE;
+       }
    }
-   free(pwd1);
-   SOCK_put_int(sock, 4 + strlen(pwd2) + 1, 4);
-   SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1);
-   SOCK_flush_output(sock);
-   free(pwd2);
-   return 0; 
-}
 
-char
-CC_connect(ConnectionClass *self, char password_req, char *salt_para)
-{
-   StartupPacket sp;
-   StartupPacket6_2 sp62;
-   QResultClass *res;
-   SocketClass *sock;
-   ConnInfo   *ci = &(self->connInfo);
-   int         areq = -1;
-   int         beresp;
-   char        msgbuffer[ERROR_MSG_LENGTH];
-   char        salt[5], notice[512];
-   CSTR        func = "CC_connect";
-   char       *encoding;
+   /* no more room -- allocate more memory */
+   self->stmts = (StatementClass **) realloc(self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));
+   if (!self->stmts)
+       return FALSE;
 
-   mylog("%s: entering...\n", func);
+   memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT);
 
-   if (password_req != AUTH_REQ_OK)
+   stmt->hdbc = self;
+   self->stmts[self->num_stmts] = stmt;
 
-       sock = self->sock;      /* already connected, just authenticate */
+   self->num_stmts += STMT_INCREMENT;
 
-   else
-   {
-       qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
-            POSTGRESDRIVERVERSION,
-            ci->drivers.fetch_max,
-            ci->drivers.socket_buffersize,
-            ci->drivers.unknown_sizes,
-            ci->drivers.max_varchar_size,
-            ci->drivers.max_longvarchar_size);
-       qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n",
-            ci->drivers.disable_optimizer,
-            ci->drivers.ksqo,
-            ci->drivers.unique_index,
-            ci->drivers.use_declarefetch);
-       qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d NAMEDATALEN=%d\n",
-            ci->drivers.text_as_longvarchar,
-            ci->drivers.unknowns_as_longvarchar,
-            ci->drivers.bools_as_char,
-            TABLE_NAME_STORAGE_LEN);
+   return TRUE;
+}
 
-       encoding = check_client_encoding(ci->conn_settings);
-       if (encoding && strcmp(encoding, "OTHER"))
-           self->client_encoding = strdup(encoding);
-       else
-       {
-           encoding = check_client_encoding(ci->drivers.conn_settings);
-           if (encoding && strcmp(encoding, "OTHER"))
-               self->client_encoding = strdup(encoding);
-       }
-       if (self->client_encoding)
-           self->ccsc = pg_CS_code(self->client_encoding);
-       qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
-            ci->drivers.extra_systable_prefixes,
-            ci->drivers.conn_settings,
-            encoding ? encoding : "");
 
-       if (self->status != CONN_NOT_CONNECTED)
-       {
-           CC_set_error(self, CONN_OPENDB_ERROR, "Already connected.");
-           return 0;
-       }
+char
+CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
+{
+   int         i;
 
-       if (ci->port[0] == '\0' ||
-#ifdef WIN32
-           ci->server[0] == '\0' ||
-#endif /* WIN32 */
-           ci->database[0] == '\0')
+   if (stmt->status == STMT_EXECUTING)
+       return FALSE;
+   for (i = 0; i < self->num_stmts; i++)
+   {
+       if (self->stmts[i] == stmt)
        {
-           CC_set_error(self, CONN_INIREAD_ERROR, "Missing server name, port, or database name in call to CC_connect.");
-           return 0;
+           self->stmts[i] = NULL;
+           return TRUE;
        }
+   }
 
-       mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s',"
-#ifdef HAVE_UNIX_SOCKETS
-             " uds = '%s',"
-#endif
-             " database = '%s', username = '%s',"
-             " password='%s'\n", ci->dsn, ci->server, ci->port,
-#ifdef HAVE_UNIX_SOCKETS
-             ci->uds,
-#endif
-             ci->database, ci->username, ci->password ? "xxxxx" : "");
+   return FALSE;
+}
 
-another_version_retry:
 
-       /*
-        * If the socket was closed for some reason (like a SQLDisconnect,
-        * but no SQLFreeConnect then create a socket now.
-        */
-       if (!self->sock)
-       {
-           self->sock = SOCK_Constructor(self);
-           if (!self->sock)
-           {
-               CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not open a socket to the server");
-               return 0;
-           }
-       }
+void
+CC_set_error(ConnectionClass *self, int number, const char *message)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_number = number;
+   self->__error_message = message ? strdup(message) : NULL;
+}
 
-       sock = self->sock;
 
-       mylog("connecting to the server socket...\n");
+void
+CC_set_errormsg(ConnectionClass *self, const char *message)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_message = message ? strdup(message) : NULL;
+}
 
-       SOCK_connect_to(sock, (short) atoi(ci->port), ci->server
-#ifdef HAVE_UNIX_SOCKETS
-               , ci->uds
-#endif
-               );
-       if (SOCK_get_errcode(sock) != 0)
-       {
-           mylog("connection to the server socket failed.\n");
-           CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not connect to the server");
-           return 0;
-       }
-       mylog("connection to the server socket succeeded.\n");
 
-       if (PROTOCOL_62(ci))
-       {
-           sock->reverse = TRUE;       /* make put_int and get_int work
-                                        * for 6.2 */
+char
+CC_get_error(ConnectionClass *self, int *number, char **message)
+{
+   int         rv;
+   char *msgcrt;
 
-           memset(&sp62, 0, sizeof(StartupPacket6_2));
-           SOCK_put_int(sock, htonl(4 + sizeof(StartupPacket6_2)), 4);
-           sp62.authtype = htonl(NO_AUTHENTICATION);
-           strncpy(sp62.database, ci->database, PATH_SIZE);
-           strncpy(sp62.user, ci->username, USRNAMEDATALEN);
-           SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2));
-           SOCK_flush_output(sock);
-       }
-       else
-       {
-           memset(&sp, 0, sizeof(StartupPacket));
+   mylog("enter CC_get_error\n");
 
-           mylog("sizeof startup packet = %d\n", sizeof(StartupPacket));
+   /* Create a very informative errormsg if it hasn't been done yet. */
+   if (!self->errormsg_created)
+   {
+       msgcrt = CC_create_errormsg(self);
+       if (self->__error_message)
+           free(self->__error_message);
+       self->__error_message = msgcrt;
+       self->errormsg_created = TRUE;
+   }
 
-           /* Send length of Authentication Block */
-           SOCK_put_int(sock, 4 + sizeof(StartupPacket), 4);
+   if (CC_get_errornumber(self))
+   {
+       *number = CC_get_errornumber(self);
+       *message = CC_get_errormsg(self);
+   }
+   rv = (CC_get_errornumber(self) != 0);
 
-           if (PROTOCOL_63(ci))
-               sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_63);
-           else
-               sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST);
+   self->__error_number = 0;       /* clear the error */
 
-           strncpy(sp.database, ci->database, SM_DATABASE);
-           strncpy(sp.user, ci->username, SM_USER);
+   mylog("exit CC_get_error\n");
 
-           SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket));
-           SOCK_flush_output(sock);
-       }
+   return rv;
+}
 
-       mylog("sent the authentication block.\n");
+static void CC_clear_cursors(ConnectionClass *self, BOOL allcursors)
+{
+   int i;
+   StatementClass  *stmt;
+   QResultClass    *res;
 
-       if (sock->errornumber != 0)
+   for (i = 0; i < self->num_stmts; i++)
+   {
+       stmt = self->stmts[i];
+       if (stmt && (res = SC_get_Result(stmt)) &&
+           res->cursor && res->cursor[0])
        {
-           mylog("couldn't send the authentication block properly.\n");
-           CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Sending the authentication packet failed");
-           return 0;
+       /*
+        * non-holdable cursors are automatically closed
+        * at commit time.
+        * all cursors are automatically closed
+        * at rollback time.
+        */
+           if (res->cursor)
+           {
+               free(res->cursor);
+               res->cursor = NULL;
+           }
        }
-       mylog("sent the authentication block successfully.\n");
    }
+}
 
-
-   mylog("gonna do authentication\n");
+void   CC_on_commit(ConnectionClass *conn)
+{
+   if (CC_is_in_trans(conn))
+   {
+#ifdef DRIVER_CURSOR_IMPLEMENT
+       if (conn->result_uncommitted)
+           ProcessRollback(conn, FALSE);
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+       CC_set_no_trans(conn);
+       CC_set_no_manual_trans(conn);
+   }
+   conn->result_uncommitted = 0;
+   CC_clear_cursors(conn, TRUE);
+   CC_discard_marked_plans(conn);
+}
 
 
-   /*
-    * Now get the authentication request from backend
-    */
+char
+CC_send_settings(ConnectionClass *self)
+{
+   /* char ini_query[MAX_MESSAGE_LEN]; */
+   ConnInfo   *ci = &(self->connInfo);
 
-   if (!PROTOCOL_62(ci))
-   {
-       BOOL        before_64 = PG_VERSION_LT(self, 6.4),
-                   ReadyForQuery = FALSE;
+/* QResultClass *res; */
+   HSTMT       hstmt;
+   StatementClass *stmt;
+   RETCODE     result;
+   char        status = TRUE;
+   char       *cs,
+              *ptr;
+#ifdef HAVE_STRTOK_R
+   char    *last;
+#endif /* HAVE_STRTOK_R */
+   CSTR func = "CC_send_settings";
 
-       do
-       {
-           if (password_req != AUTH_REQ_OK)
-               beresp = 'R';
-           else
-           {
-               beresp = SOCK_get_char(sock);
-               mylog("auth got '%c'\n", beresp);
-           }
 
-           switch (beresp)
-           {
-               case 'E':
+   mylog("%s: entering...\n", func);
 
-                   SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-                   CC_set_error(self, CONN_INVALID_AUTHENTICATION, msgbuffer);
-                   qlog("ERROR from backend during authentication: '%s'\n", msgbuffer);
-                   if (strncmp(msgbuffer, "Unsupported frontend protocol", 29) == 0)
-                   {           /* retry older version */
-                       if (PROTOCOL_63(ci))
-                           strcpy(ci->protocol, PG62);
-                       else
-                           strcpy(ci->protocol, PG63);
-                       SOCK_Destructor(sock);
-                       self->sock = (SocketClass *) 0;
-                       CC_initialize_pg_version(self);
-                       goto another_version_retry;
-                   }
+/*
+ * This function must use the local odbc API functions since the odbc state
+ * has not transitioned to "connected" yet.
+ */
 
-                   return 0;
-               case 'R':
+   result = PGAPI_AllocStmt(self, &hstmt);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+       return FALSE;
+   stmt = (StatementClass *) hstmt;
 
-                   if (password_req != AUTH_REQ_OK)
-                   {
-                       mylog("in 'R' password_req=%s\n", ci->password);
-                       areq = password_req;
-                       if (salt_para)
-                           memcpy(salt, salt_para, sizeof(salt));
-                       password_req = AUTH_REQ_OK;
-                   }
-                   else
-                   {
+   stmt->internal = TRUE;      /* ensure no BEGIN/COMMIT/ABORT stuff */
 
-                       areq = SOCK_get_int(sock, 4);
-                       if (areq == AUTH_REQ_MD5)
-                           SOCK_get_n_char(sock, salt, 4);
-                       else if (areq == AUTH_REQ_CRYPT)
-                           SOCK_get_n_char(sock, salt, 2);
+   /* Set the Datestyle to the format the driver expects it to be in */
+   result = PGAPI_ExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS, 0);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+       status = FALSE;
 
-                       mylog("areq = %d\n", areq);
-                   }
-                   switch (areq)
-                   {
-                       case AUTH_REQ_OK:
-                           break;
+   mylog("%s: result %d, status %d from set DateStyle\n", func, result, status);
 
-                       case AUTH_REQ_KRB4:
-                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 4 authentication not supported");
-                           return 0;
+   /* Disable genetic optimizer based on global flag */
+   if (ci->drivers.disable_optimizer)
+   {
+       result = PGAPI_ExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS, 0);
+       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+           status = FALSE;
 
-                       case AUTH_REQ_KRB5:
-                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 5 authentication not supported");
-                           return 0;
+       mylog("%s: result %d, status %d from set geqo\n", func, result, status);
 
-                       case AUTH_REQ_PASSWORD:
-                           mylog("in AUTH_REQ_PASSWORD\n");
+   }
 
-                           if (ci->password[0] == '\0')
-                           {
-                               CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.");
-                               return -areq;       /* need password */
-                           }
+   /* KSQO (not applicable to 7.1+ - DJP 21/06/2002) */
+   if (ci->drivers.ksqo && PG_VERSION_LT(self, 7.1))
+   {
+       result = PGAPI_ExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS, 0);
+       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+           status = FALSE;
 
-                           mylog("past need password\n");
+       mylog("%s: result %d, status %d from set ksqo\n", func, result, status);
 
-                           SOCK_put_int(sock, 4 + strlen(ci->password) + 1, 4);
-                           SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1);
-                           SOCK_flush_output(sock);
+   }
 
-                           mylog("past flush\n");
-                           break;
+   /* extra_float_digits (applicable since 7.4) */
+   if (PG_VERSION_GT(self, 7.3))
+   {
+       result = PGAPI_ExecDirect(hstmt, "set extra_float_digits to 2", SQL_NTS, 0);
+       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+           status = FALSE;
 
-                       case AUTH_REQ_CRYPT:
-                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Password crypt authentication not supported");
-                           return 0;
-                       case AUTH_REQ_MD5:
-                           mylog("in AUTH_REQ_MD5\n");
-                           if (ci->password[0] == '\0')
-                           {
-                               CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.");
-                               if (salt_para)
-                                   memcpy(salt_para, salt, sizeof(salt));
-                               return -areq; /* need password */
-                           }
-                           if (md5_auth_send(self, salt))
-                           {
-                               CC_set_error(self, CONN_INVALID_AUTHENTICATION, "md5 hashing failed");
-                               return 0;
-                           }
-                           break;
+       mylog("%s: result %d, status %d from set extra_float_digits\n", func, result, status);
 
-                       case AUTH_REQ_SCM_CREDS:
-                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unix socket credential authentication not supported");
-                           return 0;
+   }
 
-                       default:
-                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unknown authentication type");
-                           return 0;
-                   }
-                   break;
-               case 'K':       /* Secret key (6.4 protocol) */
-                   self->be_pid = SOCK_get_int(sock, 4);       /* pid */
-                   self->be_key = SOCK_get_int(sock, 4);       /* key */
+   /* Global settings */
+   if (ci->drivers.conn_settings[0] != '\0')
+   {
+       cs = strdup(ci->drivers.conn_settings);
+#ifdef HAVE_STRTOK_R
+       ptr = strtok_r(cs, ";", &last);
+#else
+       ptr = strtok(cs, ";");
+#endif /* HAVE_STRTOK_R */
+       while (ptr)
+       {
+           result = PGAPI_ExecDirect(hstmt, ptr, SQL_NTS, 0);
+           if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+               status = FALSE;
 
-                   break;
-               case 'Z':       /* Backend is ready for new query (6.4) */
-                   ReadyForQuery = TRUE;
-                   break;
-               case 'N':   /* Notices may come */
-                   while (SOCK_get_string(sock, notice, sizeof(notice) - 1)) ;
-                   break;
-               default:
-                   CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Unexpected protocol character during authentication");
-                   return 0;
-           }
+           mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
 
-           /*
-            * There were no ReadyForQuery responce before 6.4.
-            */
-           if (before_64 && areq == AUTH_REQ_OK)
-               ReadyForQuery = TRUE;
-       } while (!ReadyForQuery);
+#ifdef HAVE_STRTOK_R
+           ptr = strtok_r(NULL, ";", &last);
+#else
+           ptr = strtok(NULL, ";");
+#endif /* HAVE_STRTOK_R */
+       }
+
+       free(cs);
    }
 
+   /* Per Datasource settings */
+   if (ci->conn_settings[0] != '\0')
+   {
+       cs = strdup(ci->conn_settings);
+#ifdef HAVE_STRTOK_R
+       ptr = strtok_r(cs, ";", &last);
+#else
+       ptr = strtok(cs, ";");
+#endif /* HAVE_STRTOK_R */
+       while (ptr)
+       {
+           result = PGAPI_ExecDirect(hstmt, ptr, SQL_NTS, 0);
+           if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+               status = FALSE;
 
-   CC_clear_error(self);       /* clear any password error */
+           mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
 
-   /*
-    * send an empty query in order to find out whether the specified
-    * database really exists on the server machine
-    */
-   mylog("sending an empty query...\n");
+#ifdef HAVE_STRTOK_R
+           ptr = strtok_r(NULL, ";", &last);
+#else
+           ptr = strtok(NULL, ";");
+#endif /* HAVE_STRTOK_R */
+       }
 
-   res = CC_send_query(self, " ", NULL, CLEAR_RESULT_ON_ABORT);
-   if (res == NULL ||
-       (QR_get_status(res) != PGRES_EMPTY_QUERY &&
-        QR_command_nonfatal(res)))
-   {
-       mylog("got no result from the empty query.  (probably database does not exist)\n");
-       CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.");
-       if (res != NULL)
-           QR_Destructor(res);
-       return 0;
+       free(cs);
    }
-   if (res)
-       QR_Destructor(res);
 
-   mylog("empty query seems to be OK.\n");
 
-   CC_set_translation(self);
+   PGAPI_FreeStmt(hstmt, SQL_DROP);
 
-   /*
-    * Send any initial settings
-    */
+   return status;
+}
 
-   /* 
-    * Get the version number first so we can check it before sending options
-    * that are now obsolete. DJP 21/06/2002
-    */
 
-   CC_lookup_pg_version(self);     /* Get PostgreSQL version for
-                          SQLGetInfo use */
-   /*
-    * Since these functions allocate statements, and since the connection
-    * is not established yet, it would violate odbc state transition
-    * rules.  Therefore, these functions call the corresponding local
-    * function instead.
-    */
-   CC_send_settings(self);
-   CC_clear_error(self);           /* clear any error */
-   CC_lookup_lo(self);         /* a hack to get the oid of
-                          our large object oid type */
+/*
+ * This function is just a hack to get the oid of our Large Object oid type.
+ * If a real Large Object oid type is made part of Postgres, this function
+ * will go away and the define 'PG_TYPE_LO' will be updated.
+ */
+void
+CC_lookup_lo(ConnectionClass *self)
+{
+   HSTMT       hstmt;
+   StatementClass *stmt;
+   RETCODE     result;
+   CSTR func = "CC_lookup_lo";
 
-   /*
-    *  Multibyte handling is available ?
-    */
-   if (PG_VERSION_GE(self, 6.4))
+   mylog("%s: entering...\n", func);
+
+/*
+ * This function must use the local odbc API functions since the odbc state
+ * has not transitioned to "connected" yet.
+ */
+   result = PGAPI_AllocStmt(self, &hstmt);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+       return;
+   stmt = (StatementClass *) hstmt;
+
+   result = PGAPI_ExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS, 0);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       CC_lookup_characterset(self);
-       if (CC_get_errornumber(self) != 0)
-           return 0;
-       
-       if (self->unicode)
-       {
-           if (!self->client_encoding ||
-               !stricmp(self->client_encoding, "UNICODE"))
-           {
-               QResultClass    *res;
-               if (PG_VERSION_LT(self, 7.1))
-               {
-                   CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "UTF-8 conversion isn't implemented before 7.1");
-                   return 0;
-               }
-               if (self->client_encoding)
-                   free(self->client_encoding);
-               self->client_encoding = NULL;
-               if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, CLEAR_RESULT_ON_ABORT), res)
-               {
-                   self->client_encoding = strdup("UNICODE");
-                   self->ccsc = pg_CS_code(self->client_encoding);
-                   QR_Destructor(res);
-                   
-               }
-           }
-       }
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return;
    }
-   else if (self->unicode)
+
+   result = PGAPI_Fetch(hstmt);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4");
-       return 0;
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return;
    }
 
-   ci->updatable_cursors = 0;
-#ifdef DRIVER_CURSOR_IMPLEMENT
-   if (!ci->drivers.use_declarefetch &&
-       PG_VERSION_GE(self, 7.0)) /* Tid scan since 7.0 */
-       ci->updatable_cursors = ci->allow_keyset;
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-
-   CC_clear_error(self);       /* clear any initial command errors */
-   self->status = CONN_CONNECTED;
-
-   mylog("%s: returning...\n", func);
-
-   return 1;
-
-}
-
-
-char
-CC_add_statement(ConnectionClass *self, StatementClass *stmt)
-{
-   int         i;
-
-   mylog("CC_add_statement: self=%u, stmt=%u\n", self, stmt);
-
-   for (i = 0; i < self->num_stmts; i++)
+   result = PGAPI_GetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       if (!self->stmts[i])
-       {
-           stmt->hdbc = self;
-           self->stmts[i] = stmt;
-           return TRUE;
-       }
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return;
    }
 
-   /* no more room -- allocate more memory */
-   self->stmts = (StatementClass **) realloc(self->stmts, sizeof(StatementClass *) * (STMT_INCREMENT + self->num_stmts));
-   if (!self->stmts)
-       return FALSE;
-
-   memset(&self->stmts[self->num_stmts], 0, sizeof(StatementClass *) * STMT_INCREMENT);
-
-   stmt->hdbc = self;
-   self->stmts[self->num_stmts] = stmt;
-
-   self->num_stmts += STMT_INCREMENT;
+   mylog("Got the large object oid: %d\n", self->lobj_type);
+   qlog("    [ Large Object oid = %d ]\n", self->lobj_type);
 
-   return TRUE;
+   result = PGAPI_FreeStmt(hstmt, SQL_DROP);
 }
 
 
-char
-CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
+/*
+ * This function initializes the version of PostgreSQL from
+ * connInfo.protocol that we're connected to.
+ * h-inoue 01-2-2001
+ */
+void
+CC_initialize_pg_version(ConnectionClass *self)
 {
-   int         i;
-
-   if (stmt->status == STMT_EXECUTING)
-       return FALSE;
-   for (i = 0; i < self->num_stmts; i++)
+   strcpy(self->pg_version, self->connInfo.protocol);
+   if (PROTOCOL_62(&self->connInfo))
    {
-       if (self->stmts[i] == stmt)
-       {
-           self->stmts[i] = NULL;
-           return TRUE;
-       }
+       self->pg_version_number = (float) 6.2;
+       self->pg_version_major = 6;
+       self->pg_version_minor = 2;
+   }
+   else if (PROTOCOL_63(&self->connInfo))
+   {
+       self->pg_version_number = (float) 6.3;
+       self->pg_version_major = 6;
+       self->pg_version_minor = 3;
+   }
+   else
+   {
+       self->pg_version_number = (float) 6.4;
+       self->pg_version_major = 6;
+       self->pg_version_minor = 4;
    }
-
-   return FALSE;
 }
 
 
 /*
- * Create a more informative error message by concatenating the connection
- * error message with its socket error message.
+ * This function gets the version of PostgreSQL that we're connected to.
+ * This is used to return the correct info in SQLGetInfo
+ * DJP - 25-1-2001
  */
-char *
-CC_create_errormsg(ConnectionClass *self)
+void
+CC_lookup_pg_version(ConnectionClass *self)
 {
-   SocketClass *sock = self->sock;
-   int         pos;
-   char     msg[4096];
+   HSTMT       hstmt;
+   StatementClass *stmt;
+   RETCODE     result;
+   char        szVersion[32];
+   int         major,
+               minor;
+   CSTR        func = "CC_lookup_pg_version";
 
-   mylog("enter CC_create_errormsg\n");
+   mylog("%s: entering...\n", func);
 
-   msg[0] = '\0';
+/*
+ * This function must use the local odbc API functions since the odbc state
+ * has not transitioned to "connected" yet.
+ */
+   result = PGAPI_AllocStmt(self, &hstmt);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+       return;
+   stmt = (StatementClass *) hstmt;
 
-   if (CC_get_errormsg(self))
-       strncpy(msg, CC_get_errormsg(self), sizeof(msg));
+   /* get the server's version if possible  */
+   result = PGAPI_ExecDirect(hstmt, "select version()", SQL_NTS, 0);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   {
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return;
+   }
 
-   mylog("msg = '%s'\n", msg);
+   result = PGAPI_Fetch(hstmt);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   {
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return;
+   }
 
-   if (sock && sock->errormsg && sock->errormsg[0] != '\0')
+   result = PGAPI_GetData(hstmt, 1, SQL_C_CHAR, self->pg_version, MAX_INFO_STRING, NULL);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       pos = strlen(msg);
-       sprintf(&msg[pos], ";\n%s", sock->errormsg);
+       PGAPI_FreeStmt(hstmt, SQL_DROP);
+       return;
    }
 
-   mylog("exit CC_create_errormsg\n");
-   return msg ? strdup(msg) : NULL;
-}
+   /*
+    * Extract the Major and Minor numbers from the string. This assumes
+    * the string starts 'Postgresql X.X'
+    */
+   strcpy(szVersion, "0.0");
+   if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
+   {
+       sprintf(szVersion, "%d.%d", major, minor);
+       self->pg_version_major = major;
+       self->pg_version_minor = minor;
+   }
+   self->pg_version_number = (float) atof(szVersion);
+   if (PG_VERSION_GE(self, 7.3))
+       self->schema_support = 1;
 
+   mylog("Got the PostgreSQL version string: '%s'\n", self->pg_version);
+   mylog("Extracted PostgreSQL version number: '%1.1f'\n", self->pg_version_number);
+   qlog("    [ PostgreSQL version string = '%s' ]\n", self->pg_version);
+   qlog("    [ PostgreSQL version number = '%1.1f' ]\n", self->pg_version_number);
 
-void
-CC_set_error(ConnectionClass *self, int number, const char *message)
-{
-   if (self->__error_message)
-       free(self->__error_message);
-   self->__error_number = number;
-   self->__error_message = message ? strdup(message) : NULL;
+   result = PGAPI_FreeStmt(hstmt, SQL_DROP);
 }
 
-
-void
-CC_set_errormsg(ConnectionClass *self, const char *message)
+int
+CC_get_max_query_len(const ConnectionClass *conn)
 {
-   if (self->__error_message)
-       free(self->__error_message);
-   self->__error_message = message ? strdup(message) : NULL;
-}
-
+   int         value;
 
-char
-CC_get_error(ConnectionClass *self, int *number, char **message)
-{
-   int         rv;
-   char *msgcrt;
-
-   mylog("enter CC_get_error\n");
-
-   /* Create a very informative errormsg if it hasn't been done yet. */
-   if (!self->errormsg_created)
-   {
-       msgcrt = CC_create_errormsg(self);
-       if (self->__error_message)
-           free(self->__error_message);
-       self->__error_message = msgcrt;
-       self->errormsg_created = TRUE;
-   }
-
-   if (CC_get_errornumber(self))
-   {
-       *number = CC_get_errornumber(self);
-       *message = CC_get_errormsg(self);
-   }
-   rv = (CC_get_errornumber(self) != 0);
-
-   self->__error_number = 0;       /* clear the error */
-
-   mylog("exit CC_get_error\n");
-
-   return rv;
+   /* Long Queries in 7.0+ */
+   if (PG_VERSION_GE(conn, 7.0))
+       value = 0 /* MAX_STATEMENT_LEN */ ;
+   /* Prior to 7.0 we used 2*BLCKSZ */
+   else if (PG_VERSION_GE(conn, 6.5))
+       value = (2 * BLCKSZ);
+   else
+       /* Prior to 6.5 we used BLCKSZ */
+       value = BLCKSZ;
+   return value;
 }
 
-static void CC_clear_cursors(ConnectionClass *self, BOOL allcursors)
+/*
+ * This doesn't really return the CURRENT SCHEMA
+ * but there's no alternative.
+ */
+const char *
+CC_get_current_schema(ConnectionClass *conn)
 {
-   int i;
-   StatementClass  *stmt;
-   QResultClass    *res;
-
-   for (i = 0; i < self->num_stmts; i++)
+   if (!conn->current_schema && conn->schema_support)
    {
-       stmt = self->stmts[i];
-       if (stmt && (res = SC_get_Result(stmt)) &&
-           res->cursor && res->cursor[0])
+       QResultClass    *res;
+
+       if (res = CC_send_query(conn, "select current_schema()", NULL, CLEAR_RESULT_ON_ABORT), res)
        {
-       /*
-        * non-holdable cursors are automatically closed
-        * at commit time.
-        * all cursors are automatically closed
-        * at rollback time.
-        */
-           if (res->cursor)
-           {
-               free(res->cursor);
-               res->cursor = NULL;
-           }
+           if (QR_get_num_total_tuples(res) == 1)
+               conn->current_schema = strdup(QR_get_value_backend_row(res, 0, 0));
+           QR_Destructor(res);
        }
    }
+   return (const char *) conn->current_schema;
 }
 
-void   CC_on_commit(ConnectionClass *conn)
+int    CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plan)
 {
-   if (CC_is_in_trans(conn))
-   {
-#ifdef DRIVER_CURSOR_IMPLEMENT
-       if (conn->result_uncommitted)
-           ProcessRollback(conn, FALSE);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-       CC_set_no_trans(conn);
-       CC_set_no_manual_trans(conn);
-   }
-   conn->result_uncommitted = 0;
-   CC_clear_cursors(conn, TRUE);
-   CC_discard_marked_plans(conn);
+   int cnt = conn->num_discardp + 1;
+   char    *pname;
+
+   CC_REALLOC_return_with_error(conn->discardp, char *,
+       (cnt * sizeof(char *)), conn, "Couldn't alloc discardp.", -1) 
+   CC_MALLOC_return_with_error(pname, char, (strlen(plan) + 1),
+       conn, "Couldn't alloc discardp mem.", -1)
+   strcpy(pname, plan);
+   conn->discardp[conn->num_discardp++] = pname; 
+   return 1;
 }
-void   CC_on_abort(ConnectionClass *conn, UDWORD opt)
+int    CC_discard_marked_plans(ConnectionClass *conn)
 {
-   BOOL    set_no_trans = FALSE;
+   int i, cnt;
+   QResultClass *res;
+   char    cmd[32];
 
-   if (0 != (opt & CONN_DEAD))
-       opt |= NO_TRANS;
-   if (CC_is_in_trans(conn))
-   {
-#ifdef DRIVER_CURSOR_IMPLEMENT
-       if (conn->result_uncommitted)
-           ProcessRollback(conn, TRUE);
-#endif /* DRIVER_CURSOR_IMPLEMENT */
-       if (0 != (opt & NO_TRANS))
-       {
-           CC_set_no_trans(conn);
-           CC_set_no_manual_trans(conn);
-           set_no_trans = TRUE;
-       }
-   }
-   CC_clear_cursors(conn, TRUE);
-   if (0 != (opt & CONN_DEAD))
+   if ((cnt = conn->num_discardp) <= 0)
+       return 0;
+   for (i = cnt - 1; i >= 0; i--)
    {
-       conn->status = CONN_DOWN;
-       if (conn->sock)
+       sprintf(cmd, "DEALLOCATE \"%s\"", conn->discardp[i]);
+       res = CC_send_query(conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
+       if (res)
        {
-           SOCK_Destructor(conn->sock);
-           conn->sock = NULL;
+           QR_Destructor(res);
+           free(conn->discardp[i]);
+           conn->num_discardp--;
        }
+       else
+           return -1;
    }
-   else if (set_no_trans)
-       CC_discard_marked_plans(conn);
-   conn->result_uncommitted = 0;
+   return 1;
 }
 
+
+#ifndef USE_LIBPQ
 /*
- * The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
- * the same existing QResultClass (this occurs when the tuple cache is depleted and
- * needs to be re-filled).
- *
- * The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
- * (i.e., C3326857) for SQL select statements.  This cursor is then used in future
- * 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
+ *     IMPLEMENTATION CONNECTION CLASS
  */
-QResultClass *
-CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
+ConnectionClass *
+CC_Constructor()
 {
-   QResultClass *cmdres = NULL,
-              *retres = NULL,
-              *res = NULL;
-   BOOL    clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
-       create_keyset = ((flag & CREATE_KEYSET) != 0),
-       issue_begin = ((flag & GO_INTO_TRANSACTION) != 0 && !CC_is_in_trans(self));
-   char        swallow, *wq, *ptr;
-   int         id;
-   SocketClass *sock = self->sock;
-   int         maxlen,
-               empty_reqs;
-   BOOL        msg_truncated,
-               ReadyToReturn = FALSE,
-               query_completed = FALSE,
-               before_64 = PG_VERSION_LT(self, 6.4),
-               aborted = FALSE,
-               used_passed_result_object = FALSE;
-   UDWORD      abort_opt;
-   int     func_cs_count = 0;
-
-   /* ERROR_MSG_LENGTH is suffcient */
-   char msgbuffer[ERROR_MSG_LENGTH + 1];
-
-   /* QR_set_command() dups this string so doesn't need static */
-   char        cmdbuffer[ERROR_MSG_LENGTH + 1];
+   ConnectionClass *rv;
 
-   mylog("send_query(): conn=%u, query='%s'\n", self, query);
-   qlog("conn=%u, query='%s'\n", self, query);
+   rv = (ConnectionClass *) malloc(sizeof(ConnectionClass));
 
-   if (!self->sock)
+   if (rv != NULL)
    {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query(connection dead)");
-       CC_on_abort(self, NO_TRANS);
-       return NULL;
-   }
+       rv->henv = NULL;        /* not yet associated with an environment */
 
-   /* Indicate that we are sending a query to the backend */
-   maxlen = CC_get_max_query_len(self);
-   if (maxlen > 0 && maxlen < (int) strlen(query) + 1)
-   {
-       CC_set_error(self, CONNECTION_MSG_TOO_LONG, "Query string is too long");
-       return NULL;
-   }
+       rv->__error_message = NULL;
+       rv->__error_number = 0;
+       rv->errormsg_created = FALSE;
 
-   if ((NULL == query) || (query[0] == '\0'))
-       return NULL;
+       rv->status = CONN_NOT_CONNECTED;
+       rv->transact_status = CONN_IN_AUTOCOMMIT;       /* autocommit by default */
 
-   if (SOCK_get_errcode(sock) != 0)
-   {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
-       CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       return NULL;
-   }
+       CC_conninfo_init(&(rv->connInfo));
+       rv->sock = SOCK_Constructor(rv);
+       if (!rv->sock)
+           return NULL;
 
-#define    return DONT_CALL_RETURN_FROM_HERE???
-   ENTER_INNER_CONN_CS(self, func_cs_count);
-   SOCK_put_char(sock, 'Q');
-   if (SOCK_get_errcode(sock) != 0)
-   {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
-       CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       goto cleanup;
-   }
+       rv->stmts = (StatementClass **) malloc(sizeof(StatementClass *) * STMT_INCREMENT);
+       if (!rv->stmts)
+           return NULL;
+       memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT);
 
-   if (issue_begin)
-       SOCK_put_n_char(sock, "BEGIN;", 6);
-   SOCK_put_string(sock, query);
-   SOCK_flush_output(sock);
+       rv->num_stmts = STMT_INCREMENT;
+       rv->descs = (DescriptorClass **) malloc(sizeof(DescriptorClass *) * STMT_INCREMENT);
+       if (!rv->descs)
+           return NULL;
+       memset(rv->descs, 0, sizeof(DescriptorClass *) * STMT_INCREMENT);
 
-   if (SOCK_get_errcode(sock) != 0)
-   {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
-       CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       goto cleanup;
-   }
+       rv->num_descs = STMT_INCREMENT;
 
-   mylog("send_query: done sending query\n");
+       rv->lobj_type = PG_TYPE_LO_UNDEFINED;
 
-   empty_reqs = 0;
-   for (wq = query; isspace((UCHAR) *wq); wq++)
-       ;
-   if (*wq == '\0')
-       empty_reqs = 1;
-   cmdres = qi ? qi->result_in : NULL;
-   if (cmdres)
-       used_passed_result_object = TRUE;
-   else
-   {
-       cmdres = QR_Constructor();
-       if (!cmdres)
-       {
-           CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
+       rv->ntables = 0;
+       rv->col_info = NULL;
+
+       rv->translation_option = 0;
+       rv->translation_handle = NULL;
+       rv->DataSourceToDriver = NULL;
+       rv->DriverToDataSource = NULL;
+       rv->driver_version = ODBCVER;
+       memset(rv->pg_version, 0, sizeof(rv->pg_version));
+       rv->pg_version_number = .0;
+       rv->pg_version_major = 0;
+       rv->pg_version_minor = 0;
+       rv->ms_jet = 0;
+       rv->unicode = 0;
+       rv->result_uncommitted = 0;
+       rv->schema_support = 0;
+       rv->isolation = SQL_TXN_READ_COMMITTED;
+       rv->client_encoding = NULL;
+       rv->server_encoding = NULL;
+       rv->current_schema = NULL;
+       rv->num_discardp = 0;
+       rv->discardp = NULL;
+
+       /* Initialize statement options to defaults */
+       /* Statements under this conn will inherit these options */
+
+       InitializeStatementOptions(&rv->stmtOptions);
+       InitializeARDFields(&rv->ardOptions);
+       InitializeAPDFields(&rv->apdOptions);
+       INIT_CONN_CS(rv);
+   }
+   return rv;
+}
+
+
+char
+CC_Destructor(ConnectionClass *self)
+{
+   mylog("enter CC_Destructor, self=%u\n", self);
+
+   if (self->status == CONN_EXECUTING)
+       return 0;
+
+   CC_cleanup(self);           /* cleanup socket and statements */
+
+   mylog("after CC_Cleanup\n");
+
+   /* Free up statement holders */
+   if (self->stmts)
+   {
+       free(self->stmts);
+       self->stmts = NULL;
+   }
+
+   if (self->descs)
+   {
+       free(self->descs);
+       self->descs = NULL;
+   }
+
+   mylog("after free statement holders\n");
+
+   if (self->__error_message)
+       free(self->__error_message);
+   DELETE_CONN_CS(self);
+   free(self);
+
+   mylog("exit CC_Destructor\n");
+
+   return 1;
+}
+
+
+/* This is called by SQLDisconnect also */
+char
+CC_cleanup(ConnectionClass *self)
+{
+   int         i;
+   StatementClass *stmt;
+   DescriptorClass *desc;
+
+   if (self->status == CONN_EXECUTING)
+       return FALSE;
+
+   mylog("in CC_Cleanup, self=%u\n", self);
+
+   /* Cancel an ongoing transaction */
+   /* We are always in the middle of a transaction, */
+   /* even if we are in auto commit. */
+   if (self->sock)
+   {
+       CC_abort(self);
+
+       mylog("after CC_abort\n");
+
+       /* This actually closes the connection to the dbase */
+       SOCK_Destructor(self->sock);
+       self->sock = NULL;
+   }
+
+   mylog("after SOCK destructor\n");
+
+   /* Free all the stmts on this connection */
+   for (i = 0; i < self->num_stmts; i++)
+   {
+       stmt = self->stmts[i];
+       if (stmt)
+       {
+           stmt->hdbc = NULL;  /* prevent any more dbase interactions */
+
+           SC_Destructor(stmt);
+
+           self->stmts[i] = NULL;
+       }
+   }
+
+   /* Free all the descs on this connection */
+   for (i = 0; i < self->num_descs; i++)
+   {
+       desc = self->descs[i];
+       if (desc)
+       {
+           DC_get_conn(desc) = NULL;   /* prevent any more dbase interactions */
+           DC_Destructor(desc);
+           free(desc);
+           self->descs[i] = NULL;
+       }
+   }
+
+   /* Check for translation dll */
+#ifdef WIN32
+   if (self->translation_handle)
+   {
+       FreeLibrary(self->translation_handle);
+       self->translation_handle = NULL;
+   }
+#endif
+
+   self->status = CONN_NOT_CONNECTED;
+   self->transact_status = CONN_IN_AUTOCOMMIT;
+   CC_conninfo_init(&(self->connInfo));
+   if (self->client_encoding)
+   {
+       free(self->client_encoding);
+       self->client_encoding = NULL;
+   }
+   if (self->server_encoding)
+   {
+       free(self->server_encoding);
+       self->server_encoding = NULL;
+   }
+   if (self->current_schema)
+   {
+       free(self->current_schema);
+       self->current_schema = NULL;
+   }
+   /* Free cached table info */
+   if (self->col_info)
+   {
+       for (i = 0; i < self->ntables; i++)
+       {
+           if (self->col_info[i]->result)  /* Free the SQLColumns result structure */
+               QR_Destructor(self->col_info[i]->result);
+
+           if (self->col_info[i]->schema)
+               free(self->col_info[i]->schema);
+           free(self->col_info[i]);
+       }
+       free(self->col_info);
+       self->col_info = NULL;
+   }
+   self->ntables = 0;
+   if (self->num_discardp > 0 && self->discardp)
+   {
+       for (i = 0; i < self->num_discardp; i++)
+           free(self->discardp[i]);
+       self->num_discardp = 0;
+   }
+   if (self->discardp)
+   {
+       free(self->discardp);
+       self->discardp = NULL;
+   }
+
+   mylog("exit CC_Cleanup\n");
+   return TRUE;
+}
+
+static int
+md5_auth_send(ConnectionClass *self, const char *salt)
+{
+   char    *pwd1 = NULL, *pwd2 = NULL;
+   ConnInfo   *ci = &(self->connInfo);
+   SocketClass *sock = self->sock;
+
+   if (!(pwd1 = malloc(MD5_PASSWD_LEN + 1)))
+       return 1;
+   if (!EncryptMD5(ci->password, ci->username, strlen(ci->username), pwd1))
+   {
+       free(pwd1);
+       return 1;
+   } 
+   if (!(pwd2 = malloc(MD5_PASSWD_LEN + 1)))
+   {
+       free(pwd1);
+       return 1;
+   } 
+   if (!EncryptMD5(pwd1 + strlen("md5"), salt, 4, pwd2))
+   {
+       free(pwd2);
+       free(pwd1);
+       return 1;
+   }
+   free(pwd1);
+   SOCK_put_int(sock, 4 + strlen(pwd2) + 1, 4);
+   SOCK_put_n_char(sock, pwd2, strlen(pwd2) + 1);
+   SOCK_flush_output(sock);
+   free(pwd2);
+   return 0; 
+}
+
+
+char
+CC_connect(ConnectionClass *self, char password_req, char *salt_para)
+{
+   StartupPacket sp;
+   StartupPacket6_2 sp62;
+   QResultClass *res;
+   SocketClass *sock;
+   ConnInfo   *ci = &(self->connInfo);
+   int         areq = -1;
+   int         beresp;
+   char        msgbuffer[ERROR_MSG_LENGTH];
+   char        salt[5], notice[512];
+   CSTR        func = "CC_connect";
+   char       *encoding;
+
+   mylog("%s: entering...\n", func);
+
+   if (password_req != AUTH_REQ_OK)
+
+       sock = self->sock;      /* already connected, just authenticate */
+
+   else
+   {
+       qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
+            POSTGRESDRIVERVERSION,
+            ci->drivers.fetch_max,
+            ci->drivers.socket_buffersize,
+            ci->drivers.unknown_sizes,
+            ci->drivers.max_varchar_size,
+            ci->drivers.max_longvarchar_size);
+       qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n",
+            ci->drivers.disable_optimizer,
+            ci->drivers.ksqo,
+            ci->drivers.unique_index,
+            ci->drivers.use_declarefetch);
+       qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d NAMEDATALEN=%d\n",
+            ci->drivers.text_as_longvarchar,
+            ci->drivers.unknowns_as_longvarchar,
+            ci->drivers.bools_as_char,
+            TABLE_NAME_STORAGE_LEN);
+
+       encoding = check_client_encoding(ci->conn_settings);
+       if (encoding && strcmp(encoding, "OTHER"))
+           self->client_encoding = strdup(encoding);
+       else
+       {
+           encoding = check_client_encoding(ci->drivers.conn_settings);
+           if (encoding && strcmp(encoding, "OTHER"))
+               self->client_encoding = strdup(encoding);
+       }
+       if (self->client_encoding)
+           self->ccsc = pg_CS_code(self->client_encoding);
+       qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
+            ci->drivers.extra_systable_prefixes,
+            ci->drivers.conn_settings,
+            encoding ? encoding : "");
+
+       if (self->status != CONN_NOT_CONNECTED)
+       {
+           CC_set_error(self, CONN_OPENDB_ERROR, "Already connected.");
+           return 0;
+       }
+
+       if (ci->port[0] == '\0' ||
+#ifdef WIN32
+           ci->server[0] == '\0' ||
+#endif /* WIN32 */
+           ci->database[0] == '\0')
+       {
+           CC_set_error(self, CONN_INIREAD_ERROR, "Missing server name, port, or database name in call to CC_connect.");
+           return 0;
+       }
+
+       mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s',"
+#ifdef HAVE_UNIX_SOCKETS
+             " uds = '%s',"
+#endif
+             " database = '%s', username = '%s',"
+             " password='%s'\n", ci->dsn, ci->server, ci->port,
+#ifdef HAVE_UNIX_SOCKETS
+             ci->uds,
+#endif
+             ci->database, ci->username, ci->password ? "xxxxx" : "");
+
+another_version_retry:
+
+       /*
+        * If the socket was closed for some reason (like a SQLDisconnect,
+        * but no SQLFreeConnect then create a socket now.
+        */
+       if (!self->sock)
+       {
+           self->sock = SOCK_Constructor(self);
+           if (!self->sock)
+           {
+               CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not open a socket to the server");
+               return 0;
+           }
+       }
+
+       sock = self->sock;
+
+       mylog("connecting to the server socket...\n");
+
+       SOCK_connect_to(sock, (short) atoi(ci->port), ci->server
+#ifdef HAVE_UNIX_SOCKETS
+               , ci->uds
+#endif
+               );
+       if (SOCK_get_errcode(sock) != 0)
+       {
+           mylog("connection to the server socket failed.\n");
+           CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not connect to the server");
+           return 0;
+       }
+       mylog("connection to the server socket succeeded.\n");
+
+       if (PROTOCOL_62(ci))
+       {
+           sock->reverse = TRUE;       /* make put_int and get_int work
+                                        * for 6.2 */
+
+           memset(&sp62, 0, sizeof(StartupPacket6_2));
+           SOCK_put_int(sock, htonl(4 + sizeof(StartupPacket6_2)), 4);
+           sp62.authtype = htonl(NO_AUTHENTICATION);
+           strncpy(sp62.database, ci->database, PATH_SIZE);
+           strncpy(sp62.user, ci->username, USRNAMEDATALEN);
+           SOCK_put_n_char(sock, (char *) &sp62, sizeof(StartupPacket6_2));
+           SOCK_flush_output(sock);
+       }
+       else
+       {
+           memset(&sp, 0, sizeof(StartupPacket));
+
+           mylog("sizeof startup packet = %d\n", sizeof(StartupPacket));
+
+           /* Send length of Authentication Block */
+           SOCK_put_int(sock, 4 + sizeof(StartupPacket), 4);
+
+           if (PROTOCOL_63(ci))
+               sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_63);
+           else
+               sp.protoVersion = (ProtocolVersion) htonl(PG_PROTOCOL_LATEST);
+
+           strncpy(sp.database, ci->database, SM_DATABASE);
+           strncpy(sp.user, ci->username, SM_USER);
+
+           SOCK_put_n_char(sock, (char *) &sp, sizeof(StartupPacket));
+           SOCK_flush_output(sock);
+       }
+
+       mylog("sent the authentication block.\n");
+
+       if (sock->errornumber != 0)
+       {
+           mylog("couldn't send the authentication block properly.\n");
+           CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Sending the authentication packet failed");
+           return 0;
+       }
+       mylog("sent the authentication block successfully.\n");
+   }
+
+
+   mylog("gonna do authentication\n");
+
+
+   /*
+    * Now get the authentication request from backend
+    */
+
+   if (!PROTOCOL_62(ci))
+   {
+       BOOL        before_64 = PG_VERSION_LT(self, 6.4),
+                   ReadyForQuery = FALSE;
+
+       do
+       {
+           if (password_req != AUTH_REQ_OK)
+               beresp = 'R';
+           else
+           {
+               beresp = SOCK_get_char(sock);
+               mylog("auth got '%c'\n", beresp);
+           }
+
+           switch (beresp)
+           {
+               case 'E':
+
+                   SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+                   CC_set_error(self, CONN_INVALID_AUTHENTICATION, msgbuffer);
+                   qlog("ERROR from backend during authentication: '%s'\n", msgbuffer);
+                   if (strncmp(msgbuffer, "Unsupported frontend protocol", 29) == 0)
+                   {           /* retry older version */
+                       if (PROTOCOL_63(ci))
+                           strcpy(ci->protocol, PG62);
+                       else
+                           strcpy(ci->protocol, PG63);
+                       SOCK_Destructor(sock);
+                       self->sock = (SocketClass *) 0;
+                       CC_initialize_pg_version(self);
+                       goto another_version_retry;
+                   }
+
+                   return 0;
+               case 'R':
+
+                   if (password_req != AUTH_REQ_OK)
+                   {
+                       mylog("in 'R' password_req=%s\n", ci->password);
+                       areq = password_req;
+                       if (salt_para)
+                           memcpy(salt, salt_para, sizeof(salt));
+                       password_req = AUTH_REQ_OK;
+                   }
+                   else
+                   {
+
+                       areq = SOCK_get_int(sock, 4);
+                       if (areq == AUTH_REQ_MD5)
+                           SOCK_get_n_char(sock, salt, 4);
+                       else if (areq == AUTH_REQ_CRYPT)
+                           SOCK_get_n_char(sock, salt, 2);
+
+                       mylog("areq = %d\n", areq);
+                   }
+                   switch (areq)
+                   {
+                       case AUTH_REQ_OK:
+                           break;
+
+                       case AUTH_REQ_KRB4:
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 4 authentication not supported");
+                           return 0;
+
+                       case AUTH_REQ_KRB5:
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 5 authentication not supported");
+                           return 0;
+
+                       case AUTH_REQ_PASSWORD:
+                           mylog("in AUTH_REQ_PASSWORD\n");
+
+                           if (ci->password[0] == '\0')
+                           {
+                               CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.");
+                               return -areq;       /* need password */
+                           }
+
+                           mylog("past need password\n");
+
+                           SOCK_put_int(sock, 4 + strlen(ci->password) + 1, 4);
+                           SOCK_put_n_char(sock, ci->password, strlen(ci->password) + 1);
+                           SOCK_flush_output(sock);
+
+                           mylog("past flush\n");
+                           break;
+
+                       case AUTH_REQ_CRYPT:
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Password crypt authentication not supported");
+                           return 0;
+                       case AUTH_REQ_MD5:
+                           mylog("in AUTH_REQ_MD5\n");
+                           if (ci->password[0] == '\0')
+                           {
+                               CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.");
+                               if (salt_para)
+                                   memcpy(salt_para, salt, sizeof(salt));
+                               return -areq; /* need password */
+                           }
+                           if (md5_auth_send(self, salt))
+                           {
+                               CC_set_error(self, CONN_INVALID_AUTHENTICATION, "md5 hashing failed");
+                               return 0;
+                           }
+                           break;
+
+                       case AUTH_REQ_SCM_CREDS:
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unix socket credential authentication not supported");
+                           return 0;
+
+                       default:
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unknown authentication type");
+                           return 0;
+                   }
+                   break;
+               case 'K':       /* Secret key (6.4 protocol) */
+                   self->be_pid = SOCK_get_int(sock, 4);       /* pid */
+                   self->be_key = SOCK_get_int(sock, 4);       /* key */
+
+                   break;
+               case 'Z':       /* Backend is ready for new query (6.4) */
+                   ReadyForQuery = TRUE;
+                   break;
+               case 'N':   /* Notices may come */
+                   while (SOCK_get_string(sock, notice, sizeof(notice) - 1)) ;
+                   break;
+               default:
+                   CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Unexpected protocol character during authentication");
+                   return 0;
+           }
+
+           /*
+            * There were no ReadyForQuery responce before 6.4.
+            */
+           if (before_64 && areq == AUTH_REQ_OK)
+               ReadyForQuery = TRUE;
+       } while (!ReadyForQuery);
+   }
+
+
+   CC_clear_error(self);       /* clear any password error */
+
+   /*
+    * send an empty query in order to find out whether the specified
+    * database really exists on the server machine
+    */
+   mylog("sending an empty query...\n");
+
+   res = CC_send_query(self, " ", NULL, CLEAR_RESULT_ON_ABORT);
+   if (res == NULL ||
+       (QR_get_status(res) != PGRES_EMPTY_QUERY &&
+        QR_command_nonfatal(res)))
+   {
+       mylog("got no result from the empty query.  (probably database does not exist)\n");
+       CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.");
+       if (res != NULL)
+           QR_Destructor(res);
+       return 0;
+   }
+   if (res)
+       QR_Destructor(res);
+
+   mylog("empty query seems to be OK.\n");
+
+   CC_set_translation(self);
+
+   /*
+    * Send any initial settings
+    */
+
+   /* 
+    * Get the version number first so we can check it before sending options
+    * that are now obsolete. DJP 21/06/2002
+    */
+
+   CC_lookup_pg_version(self);     /* Get PostgreSQL version for
+                          SQLGetInfo use */
+   /*
+    * Since these functions allocate statements, and since the connection
+    * is not established yet, it would violate odbc state transition
+    * rules.  Therefore, these functions call the corresponding local
+    * function instead.
+    */
+   CC_send_settings(self);
+   CC_clear_error(self);           /* clear any error */
+   CC_lookup_lo(self);         /* a hack to get the oid of
+                          our large object oid type */
+
+   /*
+    *  Multibyte handling is available ?
+    */
+   if (PG_VERSION_GE(self, 6.4))
+   {
+       CC_lookup_characterset(self);
+       if (CC_get_errornumber(self) != 0)
+           return 0;
+       
+       if (self->unicode)
+       {
+           if (!self->client_encoding ||
+               !stricmp(self->client_encoding, "UNICODE"))
+           {
+               QResultClass    *res;
+               if (PG_VERSION_LT(self, 7.1))
+               {
+                   CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "UTF-8 conversion isn't implemented before 7.1");
+                   return 0;
+               }
+               if (self->client_encoding)
+                   free(self->client_encoding);
+               self->client_encoding = NULL;
+               if (res = CC_send_query(self, "set client_encoding to 'UTF8'", NULL, CLEAR_RESULT_ON_ABORT), res)
+               {
+                   self->client_encoding = strdup("UNICODE");
+                   self->ccsc = pg_CS_code(self->client_encoding);
+                   QR_Destructor(res);
+                   
+               }
+           }
+       }
+   }
+   else if (self->unicode)
+   {
+       CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4");
+       return 0;
+   }
+
+   ci->updatable_cursors = 0;
+#ifdef DRIVER_CURSOR_IMPLEMENT
+   if (!ci->drivers.use_declarefetch &&
+       PG_VERSION_GE(self, 7.0)) /* Tid scan since 7.0 */
+       ci->updatable_cursors = ci->allow_keyset;
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+
+   CC_clear_error(self);       /* clear any initial command errors */
+   self->status = CONN_CONNECTED;
+
+   mylog("%s: returning...\n", func);
+
+   return 1;
+
+}
+
+
+/*
+ * Create a more informative error message by concatenating the connection
+ * error message with its socket error message.
+ */
+char *
+CC_create_errormsg(ConnectionClass *self)
+{
+   SocketClass *sock = self->sock;
+   int         pos;
+   char     msg[4096];
+
+   mylog("enter CC_create_errormsg\n");
+
+   msg[0] = '\0';
+
+   if (CC_get_errormsg(self))
+       strncpy(msg, CC_get_errormsg(self), sizeof(msg));
+
+   mylog("msg = '%s'\n", msg);
+
+   if (sock && sock->errormsg && sock->errormsg[0] != '\0')
+   {
+       pos = strlen(msg);
+       sprintf(&msg[pos], ";\n%s", sock->errormsg);
+   }
+
+   mylog("exit CC_create_errormsg\n");
+   return msg ? strdup(msg) : NULL;
+}
+
+void   CC_on_abort(ConnectionClass *conn, UDWORD opt)
+{
+   BOOL    set_no_trans = FALSE;
+
+   if (0 != (opt & CONN_DEAD))
+       opt |= NO_TRANS;
+   if (CC_is_in_trans(conn))
+   {
+#ifdef DRIVER_CURSOR_IMPLEMENT
+       if (conn->result_uncommitted)
+           ProcessRollback(conn, TRUE);
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+       if (0 != (opt & NO_TRANS))
+       {
+           CC_set_no_trans(conn);
+           CC_set_no_manual_trans(conn);
+           set_no_trans = TRUE;
+       }
+   }
+   CC_clear_cursors(conn, TRUE);
+   if (0 != (opt & CONN_DEAD))
+   {
+       conn->status = CONN_DOWN;
+       if (conn->sock)
+       {
+           SOCK_Destructor(conn->sock);
+           conn->sock = NULL;
+       }
+   }
+   else if (set_no_trans)
+       CC_discard_marked_plans(conn);
+   conn->result_uncommitted = 0;
+}
+
+/*
+ * The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
+ * the same existing QResultClass (this occurs when the tuple cache is depleted and
+ * needs to be re-filled).
+ *
+ * The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
+ * (i.e., C3326857) for SQL select statements.  This cursor is then used in future
+ * 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
+ */
+QResultClass *
+CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
+{
+   QResultClass *cmdres = NULL,
+              *retres = NULL,
+              *res = NULL;
+   BOOL    clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
+       create_keyset = ((flag & CREATE_KEYSET) != 0),
+       issue_begin = ((flag & GO_INTO_TRANSACTION) != 0 && !CC_is_in_trans(self));
+   char        swallow, *wq, *ptr;
+   int         id;
+   SocketClass *sock = self->sock;
+   int         maxlen,
+               empty_reqs;
+   BOOL        msg_truncated,
+               ReadyToReturn = FALSE,
+               query_completed = FALSE,
+               before_64 = PG_VERSION_LT(self, 6.4),
+               aborted = FALSE,
+               used_passed_result_object = FALSE;
+   UDWORD      abort_opt;
+   int     func_cs_count = 0;
+
+   /* ERROR_MSG_LENGTH is suffcient */
+   char msgbuffer[ERROR_MSG_LENGTH + 1];
+
+   /* QR_set_command() dups this string so doesn't need static */
+   char        cmdbuffer[ERROR_MSG_LENGTH + 1];
+
+   mylog("send_query(): conn=%u, query='%s'\n", self, query);
+   qlog("conn=%u, query='%s'\n", self, query);
+
+   if (!self->sock)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query(connection dead)");
+       CC_on_abort(self, NO_TRANS);
+       return NULL;
+   }
+
+   /* Indicate that we are sending a query to the backend */
+   maxlen = CC_get_max_query_len(self);
+   if (maxlen > 0 && maxlen < (int) strlen(query) + 1)
+   {
+       CC_set_error(self, CONNECTION_MSG_TOO_LONG, "Query string is too long");
+       return NULL;
+   }
+
+   if ((NULL == query) || (query[0] == '\0'))
+       return NULL;
+
+   if (SOCK_get_errcode(sock) != 0)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
+       CC_on_abort(self, NO_TRANS | CONN_DEAD);
+       return NULL;
+   }
+
+#define    return DONT_CALL_RETURN_FROM_HERE???
+   ENTER_INNER_CONN_CS(self, func_cs_count);
+   SOCK_put_char(sock, 'Q');
+   if (SOCK_get_errcode(sock) != 0)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
+       CC_on_abort(self, NO_TRANS | CONN_DEAD);
+       goto cleanup;
+   }
+
+   if (issue_begin)
+       SOCK_put_n_char(sock, "BEGIN;", 6);
+   SOCK_put_string(sock, query);
+   SOCK_flush_output(sock);
+
+   if (SOCK_get_errcode(sock) != 0)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
+       CC_on_abort(self, NO_TRANS | CONN_DEAD);
+       goto cleanup;
+   }
+
+   mylog("send_query: done sending query\n");
+
+   empty_reqs = 0;
+   for (wq = query; isspace((UCHAR) *wq); wq++)
+       ;
+   if (*wq == '\0')
+       empty_reqs = 1;
+   cmdres = qi ? qi->result_in : NULL;
+   if (cmdres)
+       used_passed_result_object = TRUE;
+   else
+   {
+       cmdres = QR_Constructor();
+       if (!cmdres)
+       {
+           CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
            goto cleanup;
        }
    }
-   res = cmdres;
-   while (!ReadyToReturn)
+   res = cmdres;
+   while (!ReadyToReturn)
+   {
+       /* what type of message is coming now ? */
+       id = SOCK_get_char(sock);
+
+       if ((SOCK_get_errcode(sock) != 0) || (id == EOF))
+       {
+           CC_set_error(self, CONNECTION_NO_RESPONSE, "No response from the backend");
+
+           mylog("send_query: 'id' - %s\n", CC_get_errormsg(self));
+           CC_on_abort(self, NO_TRANS | CONN_DEAD);
+           ReadyToReturn = TRUE;
+           retres = NULL;
+           break;
+       }
+
+       mylog("send_query: got id = '%c'\n", id);
+
+       switch (id)
+       {
+           case 'A':           /* Asynchronous Messages are ignored */
+               (void) SOCK_get_int(sock, 4);   /* id of notification */
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+               /* name of the relation the message comes from */
+               break;
+           case 'C':           /* portal query command, no tuples
+                                * returned */
+               /* read in the return message from the backend */
+               SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+               if (SOCK_get_errcode(sock) != 0)
+               {
+                   CC_set_error(self, CONNECTION_NO_RESPONSE, "No response from backend while receiving a portal query command");
+                   mylog("send_query: 'C' - %s\n", CC_get_errormsg(self));
+                   CC_on_abort(self, NO_TRANS | CONN_DEAD);
+                   ReadyToReturn = TRUE;
+                   retres = NULL;
+               }
+               else
+               {
+                   mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
+
+                   if (query_completed)    /* allow for "show" style notices */
+                   {
+                       res->next = QR_Constructor();
+                       res = res->next;
+                   } 
+
+                   mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
+
+                   if (strnicmp(cmdbuffer, "BEGIN", 5) == 0)
+                   {
+                       CC_set_in_trans(self);
+                       if (issue_begin)
+                       {
+                           issue_begin = FALSE;
+                           continue;
+                       }
+                   }
+                   else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
+                       CC_on_commit(self);
+                   else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
+                       CC_on_abort(self, NO_TRANS);
+                   else if (strnicmp(cmdbuffer, "END", 3) == 0)
+                       CC_on_commit(self);
+                   else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
+                       CC_on_abort(self, NO_TRANS);
+                   else
+                   {
+                       trim(cmdbuffer); /* get rid of trailing space */ 
+                       ptr = strrchr(cmdbuffer, ' ');
+                       if (ptr)
+                           res->recent_processed_row_count = atoi(ptr + 1);
+                       else
+                           res->recent_processed_row_count = -1;
+                   }
+
+                   if (QR_command_successful(res))
+                       QR_set_status(res, PGRES_COMMAND_OK);
+                   QR_set_command(res, cmdbuffer);
+                   query_completed = TRUE;
+                   mylog("send_query: returning res = %u\n", res);
+                   if (!before_64)
+                       break;
+
+                   /*
+                    * (Quotation from the original comments) since
+                    * backend may produce more than one result for some
+                    * commands we need to poll until clear so we send an
+                    * empty query, and keep reading out of the pipe until
+                    * an 'I' is received
+                    */
+
+                   if (empty_reqs == 0)
+                   {
+                       SOCK_put_string(sock, "Q ");
+                       SOCK_flush_output(sock);
+                       empty_reqs++;
+                   }
+               }
+               break;
+           case 'Z':           /* Backend is ready for new query (6.4) */
+               if (empty_reqs == 0)
+               {
+                   ReadyToReturn = TRUE;
+                   if (aborted || query_completed)
+                       retres = cmdres;
+                   else
+                       ReadyToReturn = FALSE;
+               }
+               break;
+           case 'N':           /* NOTICE: */
+               msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+               if (QR_command_successful(res))
+                   QR_set_status(res, PGRES_NONFATAL_ERROR);
+               QR_set_notice(res, cmdbuffer);  /* will dup this string */
+               mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
+               qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
+               while (msg_truncated)
+                   msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+
+               continue;       /* dont return a result -- continue
+                                * reading */
+
+           case 'I':           /* The server sends an empty query */
+               /* There is a closing '\0' following the 'I', so we eat it */
+               swallow = SOCK_get_char(sock);
+               if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
+               {
+                   CC_set_errornumber(self, CONNECTION_BACKEND_CRAZY);
+                   QR_set_message(res, "Unexpected protocol character from backend (send_query - I)");
+                   QR_set_status(res, PGRES_FATAL_ERROR);
+                   ReadyToReturn = TRUE;
+                   retres = cmdres;
+                   break;
+               }
+               else
+               {
+                   /* We return the empty query */
+                   QR_set_status(res, PGRES_EMPTY_QUERY);
+               }
+               if (empty_reqs > 0)
+               {
+                   if (--empty_reqs == 0)
+                       query_completed = TRUE;
+               }
+               break;
+           case 'E':
+               msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+
+               /* Remove a newline */
+               if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer) - 1] == '\n')
+                   msgbuffer[strlen(msgbuffer) - 1] = '\0';
+
+
+               mylog("send_query: 'E' - %s\n", msgbuffer);
+               qlog("ERROR from backend during send_query: '%s'\n", msgbuffer);
+
+               /* We should report that an error occured. Zoltan */
+               abort_opt = 0;
+               if (!strncmp(msgbuffer, "FATAL", 5))
+               {
+                   CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_ERROR);
+                   abort_opt = NO_TRANS | CONN_DEAD;
+               }
+               else
+               {
+                   CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);
+                   if (CC_is_in_trans(self))
+                       CC_set_in_error_trans(self);
+               }
+               CC_on_abort(self, abort_opt);
+               QR_set_status(res, PGRES_FATAL_ERROR);
+               QR_set_message(res, msgbuffer);
+               QR_set_aborted(res, TRUE);
+               aborted = TRUE;
+               while (msg_truncated)
+                   msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+
+               query_completed = TRUE;
+               break;
+
+           case 'P':           /* get the Portal name */
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+               break;
+           case 'T':           /* Tuple results start here */
+               if (query_completed)
+               {
+                   res->next = QR_Constructor();
+                   if (!res->next)
+                   {
+                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
+                       ReadyToReturn = TRUE;
+                       retres = NULL;
+                       break;
+                   }
+                   if (create_keyset)
+                       QR_set_haskeyset(res->next);
+                   mylog("send_query: 'T' no result_in: res = %u\n", res->next);
+                   res = res->next;
+
+                   if (qi)
+                       QR_set_cache_size(res, qi->row_size);
+               }
+               if (!used_passed_result_object)
+               {
+                   if (create_keyset)
+                       QR_set_haskeyset(res);
+                   if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
+                   {
+                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
+                       ReadyToReturn = TRUE;
+                       if (PGRES_FATAL_ERROR == QR_get_status(res))
+                           retres = cmdres;
+                       else
+                           retres = NULL;
+                       break;
+                   }
+                   query_completed = TRUE;
+               }
+               else
+               {               /* next fetch, so reuse an existing result */
+
+                   /*
+                    * called from QR_next_tuple and must return
+                    * immediately.
+                    */
+                   ReadyToReturn = TRUE;
+                   if (!QR_fetch_tuples(res, NULL, NULL))
+                   {
+                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
+                       retres = NULL;
+                       break;
+                   }
+                   retres = cmdres;
+               }
+               break;
+           case 'D':           /* Copy in command began successfully */
+               if (query_completed)
+               {
+                   res->next = QR_Constructor();
+                   res = res->next;
+               }
+               QR_set_status(res, PGRES_COPY_IN);
+               ReadyToReturn = TRUE;
+               retres = cmdres;
+               break;
+           case 'B':           /* Copy out command began successfully */
+               if (query_completed)
+               {
+                   res->next = QR_Constructor();
+                   res = res->next;
+               }
+               QR_set_status(res, PGRES_COPY_OUT);
+               ReadyToReturn = TRUE;
+               retres = cmdres;
+               break;
+           default:
+               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_query)");
+               CC_on_abort(self, NO_TRANS | CONN_DEAD);
+
+               mylog("send_query: error - %s\n", CC_get_errormsg(self));
+               ReadyToReturn = TRUE;
+               retres = NULL;
+               break;
+       }
+
+       /*
+        * There were no ReadyForQuery response before 6.4.
+        */
+       if (before_64)
+       {
+           if (empty_reqs == 0 && query_completed)
+               break;
+       }
+   }
+
+cleanup:
+   CLEANUP_FUNC_CONN_CS(func_cs_count, self);
+   /*
+    * Break before being ready to return.
+    */
+   if (!ReadyToReturn)
+       retres = cmdres;
+
+   /*
+    * Cleanup garbage results before returning.
+    */
+   if (cmdres && retres != cmdres && !used_passed_result_object)
+       QR_Destructor(cmdres);
+   /*
+    * Cleanup the aborted result if specified
+    */
+   if (retres)
+   {
+       if (aborted)
+       {
+           if (clear_result_on_abort)
+           {
+               if (!used_passed_result_object)
+               {
+                   QR_Destructor(retres);
+                   retres = NULL;
+               }
+           }
+           if (retres)
+           {
+               /*
+                *  discard results other than errors.
+                */
+               QResultClass    *qres;
+               for (qres = retres; qres->next; qres = retres)
+               {
+                   if (QR_get_aborted(qres))
+                       break;
+                   retres = qres->next;
+                   qres->next = NULL;
+                   QR_Destructor(qres);
+               }
+               /*
+                *  If error message isn't set
+                */
+               if (retres && (!CC_get_errormsg(self) || !CC_get_errormsg(self)[0]))
+                   CC_set_errormsg(self, QR_get_message(retres));
+           }
+       }
+   }
+#undef return
+   return retres;
+}
+
+
+int
+CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
+{
+   char        id,
+               c,
+               done;
+   SocketClass *sock = self->sock;
+
+   /* ERROR_MSG_LENGTH is sufficient */
+   char msgbuffer[ERROR_MSG_LENGTH + 1];
+   int         i;
+
+   mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
+
+   if (!self->sock)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function(connection dead)");
+       CC_on_abort(self, NO_TRANS);
+       return FALSE;
+   }
+
+   if (SOCK_get_errcode(sock) != 0)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function to backend");
+       CC_on_abort(self, NO_TRANS | CONN_DEAD);
+       return FALSE;
+   }
+
+   SOCK_put_string(sock, "F ");
+   if (SOCK_get_errcode(sock) != 0)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function to backend");
+       CC_on_abort(self, NO_TRANS | CONN_DEAD);
+       return FALSE;
+   }
+
+   SOCK_put_int(sock, fnid, 4);
+   SOCK_put_int(sock, nargs, 4);
+
+
+   mylog("send_function: done sending function\n");
+
+   for (i = 0; i < nargs; ++i)
+   {
+       mylog("  arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
+
+       SOCK_put_int(sock, args[i].len, 4);
+       if (args[i].isint)
+           SOCK_put_int(sock, args[i].u.integer, 4);
+       else
+           SOCK_put_n_char(sock, (char *) args[i].u.ptr, args[i].len);
+
+
+   }
+
+   mylog("    done sending args\n");
+
+   SOCK_flush_output(sock);
+   mylog("  after flush output\n");
+
+   done = FALSE;
+   while (!done)
+   {
+       id = SOCK_get_char(sock);
+       mylog("   got id = %c\n", id);
+
+       switch (id)
+       {
+           case 'V':
+               done = TRUE;
+               break;          /* ok */
+
+           case 'N':
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+               mylog("send_function(V): 'N' - %s\n", msgbuffer);
+               /* continue reading */
+               break;
+
+           case 'E':
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+               CC_set_errormsg(self, msgbuffer);
+               if (CC_is_in_trans(self))
+                   CC_set_in_error_trans(self);
+               CC_on_abort(self, 0);
+
+               mylog("send_function(V): 'E' - %s\n", CC_get_errormsg(self));
+               qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
+
+               return FALSE;
+
+           case 'Z':
+               break;
+
+           default:
+               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_function, args)");
+               CC_on_abort(self, NO_TRANS | CONN_DEAD);
+
+               mylog("send_function: error - %s\n", CC_get_errormsg(self));
+               return FALSE;
+       }
+   }
+
+   id = SOCK_get_char(sock);
+   for (;;)
+   {
+       switch (id)
+       {
+           case 'G':           /* function returned properly */
+               mylog("  got G!\n");
+
+               *actual_result_len = SOCK_get_int(sock, 4);
+               mylog("  actual_result_len = %d\n", *actual_result_len);
+
+               if (result_is_int)
+                   *((int *) result_buf) = SOCK_get_int(sock, 4);
+               else
+                   SOCK_get_n_char(sock, (char *) result_buf, *actual_result_len);
+
+               mylog("  after get result\n");
+
+               c = SOCK_get_char(sock);        /* get the last '0' */
+
+               mylog("   after get 0\n");
+
+               return TRUE;
+
+           case 'E':
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+               CC_set_errormsg(self, msgbuffer);
+               CC_on_abort(self, 0);
+               mylog("send_function(G): 'E' - %s\n", CC_get_errormsg(self));
+               qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
+
+               return FALSE;
+
+           case 'N':
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+
+               mylog("send_function(G): 'N' - %s\n", msgbuffer);
+               qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer);
+
+               continue;       /* dont return a result -- continue
+                                * reading */
+
+           case '0':           /* empty result */
+               return TRUE;
+
+           default:
+               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_function, result)");
+               CC_on_abort(self, NO_TRANS | CONN_DEAD);
+
+               mylog("send_function: error - %s\n", CC_get_errormsg(self));
+               return FALSE;
+       }
+   }
+}
+
+void
+CC_log_error(const char *func, const char *desc, const ConnectionClass *self)
+{
+#ifdef PRN_NULLCHECK
+#define nullcheck(a) (a ? a : "(NULL)")
+#endif
+
+   if (self)
+   {
+       qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
+       mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
+       qlog("            ------------------------------------------------------------\n");
+       qlog("            henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
+       qlog("            sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
+
+       qlog("            ---------------- Socket Info -------------------------------\n");
+       if (self->sock)
+       {
+           SocketClass *sock = self->sock;
+
+           qlog("            socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg));
+           qlog("            buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
+           qlog("            buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
+       }
+   }
+   else
+{
+       qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
+       mylog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
+}
+#undef PRN_NULLCHECK
+}
+
+
+int
+CC_send_cancel_request(const ConnectionClass *conn)
+{
+   int         save_errno = SOCK_ERRNO;
+   int         tmpsock = -1;
+   struct
+   {
+       uint32      packetlen;
+       CancelRequestPacket cp;
+   }           crp;
+   BOOL    ret = TRUE;
+
+   /* Check we have an open connection */
+   if (!conn || !conn->sock)
+       return FALSE;
+
+   /*
+    * We need to open a temporary connection to the postmaster. Use the
+    * information saved by connectDB to do this with only kernel calls.
+   */
+   if ((tmpsock = socket(conn->sock->sadr->sa_family, SOCK_STREAM, 0)) < 0)
+   {
+       return FALSE;
+   }
+   if (connect(tmpsock, conn->sock->sadr, conn->sock->sadr_len) < 0)
+   {
+       closesocket(tmpsock);
+       return FALSE;
+   }
+
+   /*
+    * We needn't set nonblocking I/O or NODELAY options here.
+    */
+   crp.packetlen = htonl((uint32) sizeof(crp));
+   crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
+   crp.cp.backendPID = htonl(conn->be_pid);
+   crp.cp.cancelAuthCode = htonl(conn->be_key);
+
+   if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
+   {
+       save_errno = SOCK_ERRNO;
+       ret = FALSE;
+   }
+
+   /* Sent it, done */
+   closesocket(tmpsock);
+   SOCK_ERRNO_SET(save_errno);
+
+   return ret;
+}
+
+#else
+/*
+ * Connection class implementation using libpq.
+ * Memory Allocation for PGconn is handled by libpq.
+ */
+ConnectionClass *
+CC_Constructor()
+{
+   ConnectionClass *rv;
+
+   rv = (ConnectionClass *) malloc(sizeof(ConnectionClass));
+
+   if (rv != NULL)
    {
-       /* what type of message is coming now ? */
-       id = SOCK_get_char(sock);
+       rv->henv = NULL;        /* not yet associated with an environment */
 
-       if ((SOCK_get_errcode(sock) != 0) || (id == EOF))
-       {
-           CC_set_error(self, CONNECTION_NO_RESPONSE, "No response from the backend");
+       rv->__error_message = NULL;
+       rv->__error_number = 0;
+       rv->errormsg_created = FALSE;
 
-           mylog("send_query: 'id' - %s\n", CC_get_errormsg(self));
-           CC_on_abort(self, NO_TRANS | CONN_DEAD);
-           ReadyToReturn = TRUE;
-           retres = NULL;
-           break;
-       }
+       rv->status = CONN_NOT_CONNECTED;
+       rv->transact_status = CONN_IN_AUTOCOMMIT;       /* autocommit by default */
 
-       mylog("send_query: got id = '%c'\n", id);
+       CC_conninfo_init(&(rv->connInfo));
+       rv->stmts = (StatementClass **) malloc(sizeof(StatementClass *) * STMT_INCREMENT);
+       if (!rv->stmts)
+           return NULL;
+       memset(rv->stmts, 0, sizeof(StatementClass *) * STMT_INCREMENT);
 
-       switch (id)
-       {
-           case 'A':           /* Asynchronous Messages are ignored */
-               (void) SOCK_get_int(sock, 4);   /* id of notification */
-               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               /* name of the relation the message comes from */
-               break;
-           case 'C':           /* portal query command, no tuples
-                                * returned */
-               /* read in the return message from the backend */
-               SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-               if (SOCK_get_errcode(sock) != 0)
-               {
-                   CC_set_error(self, CONNECTION_NO_RESPONSE, "No response from backend while receiving a portal query command");
-                   mylog("send_query: 'C' - %s\n", CC_get_errormsg(self));
-                   CC_on_abort(self, NO_TRANS | CONN_DEAD);
-                   ReadyToReturn = TRUE;
-                   retres = NULL;
-               }
-               else
-               {
-                   mylog("send_query: ok - 'C' - %s\n", cmdbuffer);
+       rv->num_stmts = STMT_INCREMENT;
+       rv->descs = (DescriptorClass **) malloc(sizeof(DescriptorClass *) * STMT_INCREMENT);
+       if (!rv->descs)
+           return NULL;
+       memset(rv->descs, 0, sizeof(DescriptorClass *) * STMT_INCREMENT);
 
-                   if (query_completed)    /* allow for "show" style notices */
-                   {
-                       res->next = QR_Constructor();
-                       res = res->next;
-                   } 
+       rv->num_descs = STMT_INCREMENT;
 
-                   mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
+       rv->lobj_type = PG_TYPE_LO_UNDEFINED;
 
-                   if (strnicmp(cmdbuffer, "BEGIN", 5) == 0)
-                   {
-                       CC_set_in_trans(self);
-                       if (issue_begin)
-                       {
-                           issue_begin = FALSE;
-                           continue;
-                       }
-                   }
-                   else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
-                       CC_on_commit(self);
-                   else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
-                       CC_on_abort(self, NO_TRANS);
-                   else if (strnicmp(cmdbuffer, "END", 3) == 0)
-                       CC_on_commit(self);
-                   else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
-                       CC_on_abort(self, NO_TRANS);
-                   else
-                   {
-                       trim(cmdbuffer); /* get rid of trailing space */ 
-                       ptr = strrchr(cmdbuffer, ' ');
-                       if (ptr)
-                           res->recent_processed_row_count = atoi(ptr + 1);
-                       else
-                           res->recent_processed_row_count = -1;
-                   }
+       rv->ntables = 0;
+       rv->col_info = NULL;
 
-                   if (QR_command_successful(res))
-                       QR_set_status(res, PGRES_COMMAND_OK);
-                   QR_set_command(res, cmdbuffer);
-                   query_completed = TRUE;
-                   mylog("send_query: returning res = %u\n", res);
-                   if (!before_64)
-                       break;
+       rv->translation_option = 0;
+       rv->translation_handle = NULL;
+       rv->DataSourceToDriver = NULL;
+       rv->DriverToDataSource = NULL;
+       rv->driver_version = ODBCVER;
+       memset(rv->pg_version, 0, sizeof(rv->pg_version));
+       rv->pg_version_number = .0;
+       rv->pg_version_major = 0;
+       rv->pg_version_minor = 0;
+       rv->ms_jet = 0;
+       rv->unicode = 0;
+       rv->result_uncommitted = 0;
+       rv->schema_support = 0;
+       rv->isolation = SQL_TXN_READ_COMMITTED;
+       rv->client_encoding = NULL;
+       rv->server_encoding = NULL;
+       rv->current_schema = NULL;
+       rv->num_discardp = 0;
+       rv->discardp = NULL;
 
-                   /*
-                    * (Quotation from the original comments) since
-                    * backend may produce more than one result for some
-                    * commands we need to poll until clear so we send an
-                    * empty query, and keep reading out of the pipe until
-                    * an 'I' is received
-                    */
+       /* Initialize statement options to defaults */
+       /* Statements under this conn will inherit these options */
 
-                   if (empty_reqs == 0)
-                   {
-                       SOCK_put_string(sock, "Q ");
-                       SOCK_flush_output(sock);
-                       empty_reqs++;
-                   }
-               }
-               break;
-           case 'Z':           /* Backend is ready for new query (6.4) */
-               if (empty_reqs == 0)
-               {
-                   ReadyToReturn = TRUE;
-                   if (aborted || query_completed)
-                       retres = cmdres;
-                   else
-                       ReadyToReturn = FALSE;
-               }
-               break;
-           case 'N':           /* NOTICE: */
-               msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
-               if (QR_command_successful(res))
-                   QR_set_status(res, PGRES_NONFATAL_ERROR);
-               QR_set_notice(res, cmdbuffer);  /* will dup this string */
-               mylog("~~~ NOTICE: '%s'\n", cmdbuffer);
-               qlog("NOTICE from backend during send_query: '%s'\n", cmdbuffer);
-               while (msg_truncated)
-                   msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+       InitializeStatementOptions(&rv->stmtOptions);
+       InitializeARDFields(&rv->ardOptions);
+       InitializeAPDFields(&rv->apdOptions);
+       INIT_CONN_CS(rv);
+   }
+   return rv;
+}
 
-               continue;       /* dont return a result -- continue
-                                * reading */
 
-           case 'I':           /* The server sends an empty query */
-               /* There is a closing '\0' following the 'I', so we eat it */
-               swallow = SOCK_get_char(sock);
-               if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
-               {
-                   CC_set_errornumber(self, CONNECTION_BACKEND_CRAZY);
-                   QR_set_message(res, "Unexpected protocol character from backend (send_query - I)");
-                   QR_set_status(res, PGRES_FATAL_ERROR);
-                   ReadyToReturn = TRUE;
-                   retres = cmdres;
-                   break;
-               }
-               else
-               {
-                   /* We return the empty query */
-                   QR_set_status(res, PGRES_EMPTY_QUERY);
-               }
-               if (empty_reqs > 0)
-               {
-                   if (--empty_reqs == 0)
-                       query_completed = TRUE;
-               }
-               break;
-           case 'E':
-               msg_truncated = SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+char
+CC_Destructor(ConnectionClass *self)
+{
+   mylog("enter CC_Destructor, self=%u\n", self);
 
-               /* Remove a newline */
-               if (msgbuffer[0] != '\0' && msgbuffer[strlen(msgbuffer) - 1] == '\n')
-                   msgbuffer[strlen(msgbuffer) - 1] = '\0';
+   if (self->status == CONN_EXECUTING)
+       return 0;
 
+   CC_cleanup(self);           /* cleanup libpq connection class and statements */
 
-               mylog("send_query: 'E' - %s\n", msgbuffer);
-               qlog("ERROR from backend during send_query: '%s'\n", msgbuffer);
+   mylog("after CC_Cleanup\n");
 
-               /* We should report that an error occured. Zoltan */
-               abort_opt = 0;
-               if (!strncmp(msgbuffer, "FATAL", 5))
-               {
-                   CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_ERROR);
-                   abort_opt = NO_TRANS | CONN_DEAD;
-               }
-               else
-               {
-                   CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);
-                   if (CC_is_in_trans(self))
-                       CC_set_in_error_trans(self);
-               }
-               CC_on_abort(self, abort_opt);
-               QR_set_status(res, PGRES_FATAL_ERROR);
-               QR_set_message(res, msgbuffer);
-               QR_set_aborted(res, TRUE);
-               aborted = TRUE;
-               while (msg_truncated)
-                   msg_truncated = SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
+   /* Free up statement holders */
+   if (self->stmts)
+   {
+       free(self->stmts);
+       self->stmts = NULL;
+   }
+
+   if (self->descs)
+   {
+       free(self->descs);
+       self->descs = NULL;
+   }
+
+   mylog("after free statement holders\n");
+
+   if (self->__error_message)
+       free(self->__error_message);
+   DELETE_CONN_CS(self);
+   free(self);
 
-               query_completed = TRUE;
-               break;
+   mylog("exit CC_Destructor\n");
 
-           case 'P':           /* get the Portal name */
-               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               break;
-           case 'T':           /* Tuple results start here */
-               if (query_completed)
-               {
-                   res->next = QR_Constructor();
-                   if (!res->next)
-                   {
-                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
-                       ReadyToReturn = TRUE;
-                       retres = NULL;
-                       break;
-                   }
-                   if (create_keyset)
-                       QR_set_haskeyset(res->next);
-                   mylog("send_query: 'T' no result_in: res = %u\n", res->next);
-                   res = res->next;
+   return 1;
+}
 
-                   if (qi)
-                       QR_set_cache_size(res, qi->row_size);
-               }
-               if (!used_passed_result_object)
-               {
-                   if (create_keyset)
-                       QR_set_haskeyset(res);
-                   if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
-                   {
-                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
-                       ReadyToReturn = TRUE;
-                       if (PGRES_FATAL_ERROR == QR_get_status(res))
-                           retres = cmdres;
-                       else
-                           retres = NULL;
-                       break;
-                   }
-                   query_completed = TRUE;
-               }
-               else
-               {               /* next fetch, so reuse an existing result */
+/* This is called by SQLDisconnect also */
+char
+CC_cleanup(ConnectionClass *self)
+{
+   int         i;
+   StatementClass *stmt;
+   DescriptorClass *desc;
 
-                   /*
-                    * called from QR_next_tuple and must return
-                    * immediately.
-                    */
-                   ReadyToReturn = TRUE;
-                   if (!QR_fetch_tuples(res, NULL, NULL))
-                   {
-                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
-                       retres = NULL;
-                       break;
-                   }
-                   retres = cmdres;
-               }
-               break;
-           case 'D':           /* Copy in command began successfully */
-               if (query_completed)
-               {
-                   res->next = QR_Constructor();
-                   res = res->next;
-               }
-               QR_set_status(res, PGRES_COPY_IN);
-               ReadyToReturn = TRUE;
-               retres = cmdres;
-               break;
-           case 'B':           /* Copy out command began successfully */
-               if (query_completed)
-               {
-                   res->next = QR_Constructor();
-                   res = res->next;
-               }
-               QR_set_status(res, PGRES_COPY_OUT);
-               ReadyToReturn = TRUE;
-               retres = cmdres;
-               break;
-           default:
-               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_query)");
-               CC_on_abort(self, NO_TRANS | CONN_DEAD);
+   if (self->status == CONN_EXECUTING)
+       return FALSE;
 
-               mylog("send_query: error - %s\n", CC_get_errormsg(self));
-               ReadyToReturn = TRUE;
-               retres = NULL;
-               break;
-       }
+   mylog("in CC_Cleanup, self=%u\n", self);
 
-       /*
-        * There were no ReadyForQuery response before 6.4.
-        */
-       if (before_64)
-       {
-           if (empty_reqs == 0 && query_completed)
-               break;
-       }
+   /* Cancel an ongoing transaction */
+   /* We are always in the middle of a transaction, */
+   /* even if we are in auto commit. */
+   if (self->pgconn)
+   {
+       CC_abort(self);
+
+       mylog("after CC_abort\n");
+
+       /* This closes the connection to the database */
+       LIBPQ_Destructor(self->pgconn);
+       self->pgconn = NULL;
    }
 
-cleanup:
-   CLEANUP_FUNC_CONN_CS(func_cs_count, self);
-   /*
-    * Break before being ready to return.
-    */
-   if (!ReadyToReturn)
-       retres = cmdres;
+   mylog("after LIBPQ destructor\n");
 
-   /*
-    * Cleanup garbage results before returning.
-    */
-   if (cmdres && retres != cmdres && !used_passed_result_object)
-       QR_Destructor(cmdres);
-   /*
-    * Cleanup the aborted result if specified
-    */
-   if (retres)
+   /* Free all the stmts on this connection */
+   for (i = 0; i < self->num_stmts; i++)
    {
-       if (aborted)
+       stmt = self->stmts[i];
+       if (stmt)
        {
-           if (clear_result_on_abort)
-           {
-               if (!used_passed_result_object)
-               {
-                   QR_Destructor(retres);
-                   retres = NULL;
-               }
-           }
-           if (retres)
-           {
-               /*
-                *  discard results other than errors.
-                */
-               QResultClass    *qres;
-               for (qres = retres; qres->next; qres = retres)
-               {
-                   if (QR_get_aborted(qres))
-                       break;
-                   retres = qres->next;
-                   qres->next = NULL;
-                   QR_Destructor(qres);
-               }
-               /*
-                *  If error message isn't set
-                */
-               if (retres && (!CC_get_errormsg(self) || !CC_get_errormsg(self)[0]))
-                   CC_set_errormsg(self, QR_get_message(retres));
-           }
-       }
-   }
-#undef return
-   return retres;
-}
-
+           stmt->hdbc = NULL;  /* prevent any more dbase interactions */
 
-int
-CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
-{
-   char        id,
-               c,
-               done;
-   SocketClass *sock = self->sock;
+           SC_Destructor(stmt);
 
-   /* ERROR_MSG_LENGTH is sufficient */
-   char msgbuffer[ERROR_MSG_LENGTH + 1];
-   int         i;
+           self->stmts[i] = NULL;
+       }
+   }
 
-   mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
+   /* Free all the descs on this connection */
+   for (i = 0; i < self->num_descs; i++)
+   {
+       desc = self->descs[i];
+       if (desc)
+       {
+           DC_get_conn(desc) = NULL;   /* prevent any more dbase interactions */
+           DC_Destructor(desc);
+           free(desc);
+           self->descs[i] = NULL;
+       }
+   }
 
-   if (!self->sock)
+   /* Check for translation dll */
+#ifdef WIN32
+   if (self->translation_handle)
    {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function(connection dead)");
-       CC_on_abort(self, NO_TRANS);
-       return FALSE;
+       FreeLibrary(self->translation_handle);
+       self->translation_handle = NULL;
    }
+#endif
 
-   if (SOCK_get_errcode(sock) != 0)
+   self->status = CONN_NOT_CONNECTED;
+   self->transact_status = CONN_IN_AUTOCOMMIT;
+   CC_conninfo_init(&(self->connInfo));
+   if (self->client_encoding)
    {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function to backend");
-       CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       return FALSE;
+       free(self->client_encoding);
+       self->client_encoding = NULL;
+   }
+   if (self->server_encoding)
+   {
+       free(self->server_encoding);
+       self->server_encoding = NULL;
+   }
+   if (self->current_schema)
+   {
+       free(self->current_schema);
+       self->current_schema = NULL;
    }
+   /* Free cached table info */
+   if (self->col_info)
+   {
+       for (i = 0; i < self->ntables; i++)
+       {
+           if (self->col_info[i]->result)  /* Free the SQLColumns result structure */
+               QR_Destructor(self->col_info[i]->result);
 
-   SOCK_put_string(sock, "F ");
-   if (SOCK_get_errcode(sock) != 0)
+           if (self->col_info[i]->schema)
+               free(self->col_info[i]->schema);
+           free(self->col_info[i]);
+       }
+       free(self->col_info);
+       self->col_info = NULL;
+   }
+   self->ntables = 0;
+   if (self->num_discardp > 0 && self->discardp)
    {
-       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function to backend");
-       CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       return FALSE;
+       for (i = 0; i < self->num_discardp; i++)
+           free(self->discardp[i]);
+       self->num_discardp = 0;
+   }
+   if (self->discardp)
+   {
+       free(self->discardp);
+       self->discardp = NULL;
    }
 
-   SOCK_put_int(sock, fnid, 4);
-   SOCK_put_int(sock, nargs, 4);
-
-
-   mylog("send_function: done sending function\n");
+   mylog("exit CC_Cleanup\n");
+   return TRUE;
+}
 
-   for (i = 0; i < nargs; ++i)
-   {
-       mylog("  arg[%d]: len = %d, isint = %d, integer = %d, ptr = %u\n", i, args[i].len, args[i].isint, args[i].u.integer, args[i].u.ptr);
 
-       SOCK_put_int(sock, args[i].len, 4);
-       if (args[i].isint)
-           SOCK_put_int(sock, args[i].u.integer, 4);
-       else
-           SOCK_put_n_char(sock, (char *) args[i].u.ptr, args[i].len);
+static void
+exit_nicely(PGconn *conn)
+{
+        PQfinish(conn);
+        exit(1);
+}
 
+char
+CC_connect(ConnectionClass *self, char password_req, char *salt_para)
+{
+   /* ignore salt_para for now */
+   /* QResultClass *res; */
+   PGconn *pgconn;
+   ConnInfo   *ci = &(self->connInfo);
+   int         areq = -1,connect_return;
+   char       *encoding;
+   /* char    *conninfo; */
+   CSTR        func = "CC_connect";
 
-   }
+   mylog("%s: entering...\n", func);
 
-   mylog("    done sending args\n");
+   if (password_req != AUTH_REQ_OK)
 
-   SOCK_flush_output(sock);
-   mylog("  after flush output\n");
+       /* already connected, just authenticate */
+       pgconn = self->pgconn;
 
-   done = FALSE;
-   while (!done)
+   else
    {
-       id = SOCK_get_char(sock);
-       mylog("   got id = %c\n", id);
+       qlog("Global Options: Version='%s', fetch=%d, socket=%d, unknown_sizes=%d, max_varchar_size=%d, max_longvarchar_size=%d\n",
+            POSTGRESDRIVERVERSION,
+            ci->drivers.fetch_max,
+            ci->drivers.socket_buffersize,
+            ci->drivers.unknown_sizes,
+            ci->drivers.max_varchar_size,
+            ci->drivers.max_longvarchar_size);
+       qlog("                disable_optimizer=%d, ksqo=%d, unique_index=%d, use_declarefetch=%d\n",
+            ci->drivers.disable_optimizer,
+            ci->drivers.ksqo,
+            ci->drivers.unique_index,
+            ci->drivers.use_declarefetch);
+       qlog("                text_as_longvarchar=%d, unknowns_as_longvarchar=%d, bools_as_char=%d NAMEDATALEN=%d\n",
+            ci->drivers.text_as_longvarchar,
+            ci->drivers.unknowns_as_longvarchar,
+            ci->drivers.bools_as_char,
+            TABLE_NAME_STORAGE_LEN);
 
-       switch (id)
+       encoding = check_client_encoding(ci->conn_settings);
+       if (encoding && strcmp(encoding, "OTHER"))
+           self->client_encoding = strdup(encoding);
+       else
        {
-           case 'V':
-               done = TRUE;
-               break;          /* ok */
-
-           case 'N':
-               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               mylog("send_function(V): 'N' - %s\n", msgbuffer);
-               /* continue reading */
-               break;
-
-           case 'E':
-               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               CC_set_errormsg(self, msgbuffer);
-               if (CC_is_in_trans(self))
-                   CC_set_in_error_trans(self);
-               CC_on_abort(self, 0);
-
-               mylog("send_function(V): 'E' - %s\n", CC_get_errormsg(self));
-               qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
-
-               return FALSE;
-
-           case 'Z':
-               break;
-
-           default:
-               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_function, args)");
-               CC_on_abort(self, NO_TRANS | CONN_DEAD);
+           encoding = check_client_encoding(ci->drivers.conn_settings);
+           if (encoding && strcmp(encoding, "OTHER"))
+               self->client_encoding = strdup(encoding);
+       }
+       if (self->client_encoding)
+           self->ccsc = pg_CS_code(self->client_encoding);
+       qlog("                extra_systable_prefixes='%s', conn_settings='%s' conn_encoding='%s'\n",
+            ci->drivers.extra_systable_prefixes,
+            ci->drivers.conn_settings,
+            encoding ? encoding : "");
 
-               mylog("send_function: error - %s\n", CC_get_errormsg(self));
-               return FALSE;
+       if (self->status != CONN_NOT_CONNECTED)
+       {
+           CC_set_error(self, CONN_OPENDB_ERROR, "Already connected.");
+           return 0;
        }
-   }
 
-   id = SOCK_get_char(sock);
-   for (;;)
-   {
-       switch (id)
+       if (ci->port[0] == '\0' ||
+#ifdef WIN32
+           ci->server[0] == '\0' ||
+#endif /* WIN32 */
+           ci->database[0] == '\0')
        {
-           case 'G':           /* function returned properly */
-               mylog("  got G!\n");
+           CC_set_error(self, CONN_INIREAD_ERROR, "Missing server name, port, or database name in call to CC_connect.");
+           return 0;
+       }
 
-               *actual_result_len = SOCK_get_int(sock, 4);
-               mylog("  actual_result_len = %d\n", *actual_result_len);
+       mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s',"
+             " database = '%s', username = '%s',"
+             " password='%s'\n", ci->dsn, ci->server, ci->port,
+             ci->database, ci->username, ci->password ? "xxxxx" : "");
 
-               if (result_is_int)
-                   *((int *) result_buf) = SOCK_get_int(sock, 4);
-               else
-                   SOCK_get_n_char(sock, (char *) result_buf, *actual_result_len);
 
-               mylog("  after get result\n");
+       mylog("connecting to the server \n");
 
-               c = SOCK_get_char(sock);        /* get the last '0' */
+       connect_return = LIBPQ_connect(self);
+       if(0 == connect_return)
+       {
+           CC_set_error(self, CONNECTION_COULD_NOT_ESTABLISH, "Could not connect to the server");
+           return 0;
+       }
 
-               mylog("   after get 0\n");
+       mylog("connection to the database succeeded.\n");
 
-               return TRUE;
+   }
 
-           case 'E':
-               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               CC_set_errormsg(self, msgbuffer);
-               CC_on_abort(self, 0);
-               mylog("send_function(G): 'E' - %s\n", CC_get_errormsg(self));
-               qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
+   CC_clear_error(self);       /* clear any password error */
 
-               return FALSE;
+   CC_set_translation(self);
 
-           case 'N':
-               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+   /*
+    * Send any initial settings
+    */
 
-               mylog("send_function(G): 'N' - %s\n", msgbuffer);
-               qlog("NOTICE from backend during send_function: '%s'\n", msgbuffer);
+   /*
+    * Get the version number first so we can check it before sending options
+    * that are now obsolete. DJP 21/06/2002
+    */
 
-               continue;       /* dont return a result -- continue
-                                * reading */
+   CC_lookup_pg_version(self);     /* Get PostgreSQL version for
+                          SQLGetInfo use */
+   /*
+    * Since these functions allocate statements, and since the connection
+    * is not established yet, it would violate odbc state transition
+    * rules.  Therefore, these functions call the corresponding local
+    * function instead.
+    */
+   CC_send_settings(self);
+   CC_clear_error(self);           /* clear any error */
+   CC_lookup_lo(self);         /* a hack to get the oid of
+                          our large object oid type */
 
-           case '0':           /* empty result */
-               return TRUE;
+   /*
+    *  Multibyte handling is available ?
+    */
+   if (PG_VERSION_GE(self, 6.4))
+   {
+       CC_lookup_characterset(self);
+       if (CC_get_errornumber(self) != 0)
+           return 0;
 
-           default:
-               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_function, result)");
-               CC_on_abort(self, NO_TRANS | CONN_DEAD);
+       if (self->unicode)
+       {
+           if (!self->client_encoding ||
+               stricmp(self->client_encoding, "UNICODE"))
+           {
+               QResultClass    *res;
+               if (PG_VERSION_LT(self, 7.1))
+               {
+                   CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "UTF-8 conversion isn't implemented before 7.1");
+                   return 0;
+               }
+               if (self->client_encoding)
+                   free(self->client_encoding);
+               self->client_encoding = NULL;
+               res = LIBPQ_execute_query(self,"set client_encoding to 'UTF8'");
+               if (res)
+               {
+                   self->client_encoding = strdup("UNICODE");
+                   self->ccsc = pg_CS_code(self->client_encoding);
+                   QR_Destructor(res);
 
-               mylog("send_function: error - %s\n", CC_get_errormsg(self));
-               return FALSE;
+               }
+           }
        }
    }
-}
-
-
-char
-CC_send_settings(ConnectionClass *self)
-{
-   /* char ini_query[MAX_MESSAGE_LEN]; */
-   ConnInfo   *ci = &(self->connInfo);
-
-/* QResultClass *res; */
-   HSTMT       hstmt;
-   StatementClass *stmt;
-   RETCODE     result;
-   char        status = TRUE;
-   char       *cs,
-              *ptr;
-#ifdef HAVE_STRTOK_R
-   char    *last;
-#endif /* HAVE_STRTOK_R */
-   CSTR func = "CC_send_settings";
-
-
-   mylog("%s: entering...\n", func);
+   else if (self->unicode)
+   {
+       CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4");
+       return 0;
+   }
 
-/*
- * This function must use the local odbc API functions since the odbc state
- * has not transitioned to "connected" yet.
- */
+   ci->updatable_cursors = 0;
+#ifdef DRIVER_CURSOR_IMPLEMENT
+   if (!ci->drivers.use_declarefetch &&
+       PG_VERSION_GE(self, 7.0)) /* Tid scan since 7.0 */
+       ci->updatable_cursors = ci->allow_keyset;
+#endif /* DRIVER_CURSOR_IMPLEMENT */
 
-   result = PGAPI_AllocStmt(self, &hstmt);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-       return FALSE;
-   stmt = (StatementClass *) hstmt;
+   CC_clear_error(self);       /* clear any initial command errors */
+   self->status = CONN_CONNECTED;
 
-   stmt->internal = TRUE;      /* ensure no BEGIN/COMMIT/ABORT stuff */
+   mylog("%s: returning...\n", func);
 
-   /* Set the Datestyle to the format the driver expects it to be in */
-   result = PGAPI_ExecDirect(hstmt, "set DateStyle to 'ISO'", SQL_NTS, 0);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-       status = FALSE;
+   return 1;
 
-   mylog("%s: result %d, status %d from set DateStyle\n", func, result, status);
+}
 
-   /* Disable genetic optimizer based on global flag */
-   if (ci->drivers.disable_optimizer)
-   {
-       result = PGAPI_ExecDirect(hstmt, "set geqo to 'OFF'", SQL_NTS, 0);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-           status = FALSE;
 
-       mylog("%s: result %d, status %d from set geqo\n", func, result, status);
+/*
+ * Create a more informative error message by concatenating the connection
+ * error message with its libpq error message.
+ */
+char *
+CC_create_errormsg(ConnectionClass *self)
+{
+   PGconn *pgconn = self->pgconn;
+   char     msg[4096];
 
-   }
+   mylog("enter CC_create_errormsg\n");
 
-   /* KSQO (not applicable to 7.1+ - DJP 21/06/2002) */
-   if (ci->drivers.ksqo && PG_VERSION_LT(self, 7.1))
-   {
-       result = PGAPI_ExecDirect(hstmt, "set ksqo to 'ON'", SQL_NTS, 0);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-           status = FALSE;
+   msg[0] = '\0';
 
-       mylog("%s: result %d, status %d from set ksqo\n", func, result, status);
+   if (CC_get_errormsg(self))
+       strncpy(msg, CC_get_errormsg(self), sizeof(msg));
 
-   }
+   mylog("msg = '%s'\n", msg);
 
-   /* extra_float_digits (applicable since 7.4) */
-   if (PG_VERSION_GT(self, 7.3))
-   {
-       result = PGAPI_ExecDirect(hstmt, "set extra_float_digits to 2", SQL_NTS, 0);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-           status = FALSE;
+   mylog("exit CC_create_errormsg\n");
+   return msg ? strdup(msg) : NULL;
+}
 
-       mylog("%s: result %d, status %d from set extra_float_digits\n", func, result, status);
 
-   }
+void   CC_on_abort(ConnectionClass *conn, UDWORD opt)
+{
+   BOOL    set_no_trans = FALSE;
 
-   /* Global settings */
-   if (ci->drivers.conn_settings[0] != '\0')
+   if (0 != (opt & CONN_DEAD))
+       opt |= NO_TRANS;
+   if (CC_is_in_trans(conn))
    {
-       cs = strdup(ci->drivers.conn_settings);
-#ifdef HAVE_STRTOK_R
-       ptr = strtok_r(cs, ";", &last);
-#else
-       ptr = strtok(cs, ";");
-#endif /* HAVE_STRTOK_R */
-       while (ptr)
+#ifdef DRIVER_CURSOR_IMPLEMENT
+       if (conn->result_uncommitted)
+           ProcessRollback(conn, TRUE);
+#endif /* DRIVER_CURSOR_IMPLEMENT */
+       if (0 != (opt & NO_TRANS))
        {
-           result = PGAPI_ExecDirect(hstmt, ptr, SQL_NTS, 0);
-           if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-               status = FALSE;
-
-           mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
-
-#ifdef HAVE_STRTOK_R
-           ptr = strtok_r(NULL, ";", &last);
-#else
-           ptr = strtok(NULL, ";");
-#endif /* HAVE_STRTOK_R */
+           CC_set_no_trans(conn);
+           CC_set_no_manual_trans(conn);
+           set_no_trans = TRUE;
        }
-
-       free(cs);
    }
-
-   /* Per Datasource settings */
-   if (ci->conn_settings[0] != '\0')
+   CC_clear_cursors(conn, TRUE);
+   if (0 != (opt & CONN_DEAD))
    {
-       cs = strdup(ci->conn_settings);
-#ifdef HAVE_STRTOK_R
-       ptr = strtok_r(cs, ";", &last);
-#else
-       ptr = strtok(cs, ";");
-#endif /* HAVE_STRTOK_R */
-       while (ptr)
+       conn->status = CONN_DOWN;
+       if (conn->pgconn)
        {
-           result = PGAPI_ExecDirect(hstmt, ptr, SQL_NTS, 0);
-           if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-               status = FALSE;
-
-           mylog("%s: result %d, status %d from '%s'\n", func, result, status, ptr);
-
-#ifdef HAVE_STRTOK_R
-           ptr = strtok_r(NULL, ";", &last);
-#else
-           ptr = strtok(NULL, ";");
-#endif /* HAVE_STRTOK_R */
+           LIBPQ_Destructor(conn->pgconn);
+           conn->pgconn = NULL;
        }
-
-       free(cs);
    }
-
-
-   PGAPI_FreeStmt(hstmt, SQL_DROP);
-
-   return status;
+   else if (set_no_trans)
+       CC_discard_marked_plans(conn);
+   conn->result_uncommitted = 0;
 }
 
-
 /*
- * This function is just a hack to get the oid of our Large Object oid type.
- * If a real Large Object oid type is made part of Postgres, this function
- * will go away and the define 'PG_TYPE_LO' will be updated.
+ * The "result_in" is only used by QR_next_tuple() to fetch another group of rows into
+ * the same existing QResultClass (this occurs when the tuple cache is depleted and
+ * needs to be re-filled).
+ *
+ * The "cursor" is used by SQLExecute to associate a statement handle as the cursor name
+ * (i.e., C3326857) for SQL select statements.  This cursor is then used in future
+ * 'declare cursor C3326857 for ...' and 'fetch 100 in C3326857' statements.
  */
-void
-CC_lookup_lo(ConnectionClass *self)
+QResultClass *
+CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
 {
-   HSTMT       hstmt;
-   StatementClass *stmt;
-   RETCODE     result;
-   CSTR func = "CC_lookup_lo";
-
-   mylog("%s: entering...\n", func);
+   QResultClass *cmdres = NULL,
+              *retres = NULL,
+              *res ;
+   BOOL    clear_result_on_abort = ((flag & CLEAR_RESULT_ON_ABORT) != 0),
+       create_keyset = ((flag & CREATE_KEYSET) != 0),
+       issue_begin = ((flag & GO_INTO_TRANSACTION) != 0 && !CC_is_in_trans(self));
+   char         *wq;
+   int         id=0;
+   PGconn *pgconn = self->pgconn;
+   int         maxlen,
+               empty_reqs;
+   BOOL        ReadyToReturn = FALSE,
+               query_completed = FALSE,
+               before_64 = PG_VERSION_LT(self, 6.4),
+               aborted = FALSE,
+               used_passed_result_object = FALSE;
+   int     func_cs_count = 0;
 
-/*
- * This function must use the local odbc API functions since the odbc state
- * has not transitioned to "connected" yet.
- */
-   result = PGAPI_AllocStmt(self, &hstmt);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-       return;
-   stmt = (StatementClass *) hstmt;
 
-   result = PGAPI_ExecDirect(hstmt, "select oid from pg_type where typname='" PG_TYPE_LO_NAME "'", SQL_NTS, 0);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-   {
-       PGAPI_FreeStmt(hstmt, SQL_DROP);
-       return;
-   }
+   mylog("send_query(): conn=%u, query='%s'\n", self, query);
+   qlog("conn=%u, query='%s'\n", self, query);
 
-   result = PGAPI_Fetch(hstmt);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   if (!self->pgconn)
    {
-       PGAPI_FreeStmt(hstmt, SQL_DROP);
-       return;
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query(connection dead)");
+       CC_on_abort(self, NO_TRANS);
+       return NULL;
    }
-
-   result = PGAPI_GetData(hstmt, 1, SQL_C_SLONG, &self->lobj_type, sizeof(self->lobj_type), NULL);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   /* Indicate that we are sending a query to the backend */
+   maxlen = CC_get_max_query_len(self);
+   if (maxlen > 0 && maxlen < (int) strlen(query) + 1)
    {
-       PGAPI_FreeStmt(hstmt, SQL_DROP);
-       return;
+       CC_set_error(self, CONNECTION_MSG_TOO_LONG, "Query string is too long");
+       return NULL;
    }
 
-   mylog("Got the large object oid: %d\n", self->lobj_type);
-   qlog("    [ Large Object oid = %d ]\n", self->lobj_type);
+   if ((NULL == query) || (query[0] == '\0'))
+       return NULL;
 
-   result = PGAPI_FreeStmt(hstmt, SQL_DROP);
-}
+#define    return DONT_CALL_RETURN_FROM_HERE???
+   ENTER_INNER_CONN_CS(self, func_cs_count);
 
+   if (issue_begin)
+       res = LIBPQ_execute_query(self,"BEGIN");
+   res = LIBPQ_execute_query(self,query);
 
-/*
- * This function initializes the version of PostgreSQL from
- * connInfo.protocol that we're connected to.
- * h-inoue 01-2-2001
- */
-void
-CC_initialize_pg_version(ConnectionClass *self)
-{
-   strcpy(self->pg_version, self->connInfo.protocol);
-   if (PROTOCOL_62(&self->connInfo))
+   if((!res) || (res->status == PGRES_EMPTY_QUERY) )
    {
-       self->pg_version_number = (float) 6.2;
-       self->pg_version_major = 6;
-       self->pg_version_minor = 2;
+       QR_Destructor(res);
+       goto cleanup;
    }
-   else if (PROTOCOL_63(&self->connInfo))
+   else
    {
-       self->pg_version_number = (float) 6.3;
-       self->pg_version_major = 6;
-       self->pg_version_minor = 3;
+       mylog("send_query: done sending query\n");
+
+       empty_reqs = 0;
+       for (wq = query; isspace((UCHAR) *wq); wq++)
+       ;
+       if (*wq == '\0')
+           empty_reqs = 1;
+       cmdres = qi ? qi->result_in : NULL;
+       if (cmdres)
+           used_passed_result_object = TRUE;
+       if (!used_passed_result_object)
+       {
+           if (create_keyset)
+               QR_set_haskeyset(res->next);
+           if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
+           {
+               CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
+               if (PGRES_FATAL_ERROR == QR_get_status(res))
+                   retres = cmdres;
+               else
+                   retres = NULL;
+           }
+       }
+       else
+       {               /* next fetch, so reuse an existing result */
+           /*
+           * called from QR_next_tuple and must return
+           * immediately.
+           */
+           if (!QR_fetch_tuples(res, NULL, NULL))
+           {
+               CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
+               retres = NULL;
+           }
+           retres = cmdres;
+       }
    }
-   else
+
+cleanup:
+   CLEANUP_FUNC_CONN_CS(func_cs_count, self);
+   /*
+    * Cleanup garbage results before returning.
+    */
+   if (cmdres && retres != cmdres && !used_passed_result_object)
    {
-       self->pg_version_number = (float) 6.4;
-       self->pg_version_major = 6;
-       self->pg_version_minor = 4;
+       QR_Destructor(cmdres);
+   }
+   /*
+    * Cleanup the aborted result if specified
+    */
+   if (retres)
+   {
+       if (aborted)
+       {
+           if (clear_result_on_abort)
+           {
+               if (!used_passed_result_object)
+               {
+                   QR_Destructor(retres);
+                   retres = NULL;
+               }
+           }
+           if (retres)
+           {
+               /*
+                *  discard results other than errors.
+                */
+               QResultClass    *qres;
+               for (qres = retres; qres->next; qres = retres)
+               {
+                   if (QR_get_aborted(qres))
+                       break;
+                   retres = qres->next;
+                   qres->next = NULL;
+                   QR_Destructor(qres);
+               }
+               /*
+                *  If error message isn't set
+                */
+               if (retres && (!CC_get_errormsg(self) || !CC_get_errormsg(self)[0]))
+                   CC_set_errormsg(self, QR_get_message(retres));
+           }
+       }
    }
+#undef return
+   return res;
 }
 
-
-/*
- * This function gets the version of PostgreSQL that we're connected to.
- * This is used to return the correct info in SQLGetInfo
- * DJP - 25-1-2001
- */
-void
-CC_lookup_pg_version(ConnectionClass *self)
+int
+CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *args, int nargs)
 {
-   HSTMT       hstmt;
-   StatementClass *stmt;
-   RETCODE     result;
-   char        szVersion[32];
-   int         major,
-               minor;
-   CSTR        func = "CC_lookup_pg_version";
+   char            done;
+   PGconn *pgconn=self->pgconn;
 
-   mylog("%s: entering...\n", func);
 
-/*
- * This function must use the local odbc API functions since the odbc state
- * has not transitioned to "connected" yet.
- */
-   result = PGAPI_AllocStmt(self, &hstmt);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-       return;
-   stmt = (StatementClass *) hstmt;
+   mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
 
-   /* get the server's version if possible  */
-   result = PGAPI_ExecDirect(hstmt, "select version()", SQL_NTS, 0);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   if (!self->pgconn)
    {
-       PGAPI_FreeStmt(hstmt, SQL_DROP);
-       return;
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function(connection dead)");
+       CC_on_abort(self, NO_TRANS);
+       return FALSE;
    }
 
-   result = PGAPI_Fetch(hstmt);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-   {
-       PGAPI_FreeStmt(hstmt, SQL_DROP);
-       return;
-   }
+   mylog("send_function: done sending function\n");
 
-   result = PGAPI_GetData(hstmt, 1, SQL_C_CHAR, self->pg_version, MAX_INFO_STRING, NULL);
-   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
-   {
-       PGAPI_FreeStmt(hstmt, SQL_DROP);
-       return;
-   }
+   /* Need to implement this */
 
-   /*
-    * Extract the Major and Minor numbers from the string. This assumes
-    * the string starts 'Postgresql X.X'
-    */
-   strcpy(szVersion, "0.0");
-   if (sscanf(self->pg_version, "%*s %d.%d", &major, &minor) >= 2)
-   {
-       sprintf(szVersion, "%d.%d", major, minor);
-       self->pg_version_major = major;
-       self->pg_version_minor = minor;
-   }
-   self->pg_version_number = (float) atof(szVersion);
-   if (PG_VERSION_GE(self, 7.3))
-       self->schema_support = 1;
+   mylog("    done sending args\n");
 
-   mylog("Got the PostgreSQL version string: '%s'\n", self->pg_version);
-   mylog("Extracted PostgreSQL version number: '%1.1f'\n", self->pg_version_number);
-   qlog("    [ PostgreSQL version string = '%s' ]\n", self->pg_version);
-   qlog("    [ PostgreSQL version number = '%1.1f' ]\n", self->pg_version_number);
+   mylog("  after flush output\n");
 
-   result = PGAPI_FreeStmt(hstmt, SQL_DROP);
+   done = FALSE;
+   return TRUE;
 }
 
 
@@ -2176,148 +2994,268 @@ CC_log_error(const char *func, const char *desc, const ConnectionClass *self)
        mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
        qlog("            ------------------------------------------------------------\n");
        qlog("            henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
-       qlog("            sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
-
-       qlog("            ---------------- Socket Info -------------------------------\n");
-       if (self->sock)
-       {
-           SocketClass *sock = self->sock;
-
-           qlog("            socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg));
-           qlog("            buffer_in=%u, buffer_out=%u\n", sock->buffer_in, sock->buffer_out);
-           qlog("            buffer_filled_in=%d, buffer_filled_out=%d, buffer_read_in=%d\n", sock->buffer_filled_in, sock->buffer_filled_out, sock->buffer_read_in);
-       }
    }
    else
-{
+   {
        qlog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
        mylog("INVALID CONNECTION HANDLE ERROR: func=%s, desc='%s'\n", func, desc);
-}
+   }
 #undef PRN_NULLCHECK
 }
 
+
 int
-CC_get_max_query_len(const ConnectionClass *conn)
+CC_send_cancel_request(const ConnectionClass *conn)
 {
-   int         value;
+   int         ret = 0,errbufsize=256;
+   char        errbuf[256];
+   PGcancel    *cancel;
 
-   /* Long Queries in 7.0+ */
-   if (PG_VERSION_GE(conn, 7.0))
-       value = 0 /* MAX_STATEMENT_LEN */ ;
-   /* Prior to 7.0 we used 2*BLCKSZ */
-   else if (PG_VERSION_GE(conn, 6.5))
-       value = (2 * BLCKSZ);
+
+   cancel = PQgetCancel(conn->pgconn);
+   if(!cancel)
+   {
+       PQfreeCancel(cancel);
+       return FALSE;
+   }
+   ret=PQcancel(cancel, errbuf,errbufsize);
+   if(1 == ret)
+       return TRUE;
    else
-       /* Prior to 6.5 we used BLCKSZ */
-       value = BLCKSZ;
-   return value;
+   {
+       PQfreeCancel(cancel);
+       return FALSE;
+   }
+   return ret;
 }
 
-/*
- * This doesn't really return the CURRENT SCHEMA
- * but there's no alternative.
- */
-const char *
-CC_get_current_schema(ConnectionClass *conn)
+
+void
+LIBPQ_Destructor(PGconn *pgconn)
 {
-   if (!conn->current_schema && conn->schema_support)
+   mylog("entering PGCONN_Destructor \n");
+   PQfinish(pgconn);
+   mylog("exiting PGCONN_Destructor \n");
+}
+
+
+int
+LIBPQ_connect(ConnectionClass *self)
+{
+   char *conninfo;
+   mylog("connecting to the database  using %s as the server\n",self->connInfo.server);
+   if(self->connInfo.server != '\0')
    {
-       QResultClass    *res;
+       conninfo = (char *)malloc((sizeof(char) * strlen(" host=") + strlen(self->connInfo.server) + 1));
+       if(!conninfo)
+       {
+           CC_set_error(self, CONN_MEMORY_ALLOCATION_FAILED,"Could not allocate memory for connection string(server)");
+           mylog("could not allocate memory for server \n");
+       }
+       conninfo = strcpy(conninfo," host=");
+       conninfo = strcat(conninfo,self->connInfo.server);
 
-       if (res = CC_send_query(conn, "select current_schema()", NULL, CLEAR_RESULT_ON_ABORT), res)
+   }
+   mylog("the size is %d \n",strlen(conninfo));
+   if(self->connInfo.port[0] != '\0')
+   {
+       size_t size=(sizeof(char) * (strlen(" port=") + strlen(self->connInfo.port) + 1));
+       conninfo = (char *)realloc(conninfo,size+strlen(conninfo));
+       if(!conninfo)
        {
-           if (QR_get_num_total_tuples(res) == 1)
-               conn->current_schema = strdup(QR_get_value_backend_row(res, 0, 0));
-           QR_Destructor(res);
+           CC_set_error(self, CONN_MEMORY_ALLOCATION_FAILED,"Could not allocate memory for connection string(port)");
+           mylog("could not allocate memory for port \n");
        }
+       conninfo = strcat(conninfo," port=");
+       conninfo = strcat(conninfo,self->connInfo.port);
    }
-   return (const char *) conn->current_schema;
-}
 
-int
-CC_send_cancel_request(const ConnectionClass *conn)
-{
-   int         save_errno = SOCK_ERRNO;
-   int         tmpsock = -1;
-   struct
+
+   if(self->connInfo.database[0] != '\0')
    {
-       uint32      packetlen;
-       CancelRequestPacket cp;
-   }           crp;
-   BOOL    ret = TRUE;
+       size_t size= (sizeof(char) * (strlen(" dbname=") + strlen(self->connInfo.database) + 1));
+       conninfo = (char *)realloc(conninfo,size+strlen(conninfo));
+       if(!conninfo)
+       {
+           CC_set_error(self, CONN_MEMORY_ALLOCATION_FAILED,"Could not allocate memory for connection string(database)");
+           mylog("i could not allocate memory for dbname \n");
+       }
+       conninfo = strcat(conninfo," dbname=");
+       conninfo = strcat(conninfo,self->connInfo.database);
+   }
 
-   /* Check we have an open connection */
-   if (!conn || !conn->sock)
-       return FALSE;
 
-   /*
-    * We need to open a temporary connection to the postmaster. Use the
-    * information saved by connectDB to do this with only kernel calls.
-   */
-   if ((tmpsock = socket(conn->sock->sadr->sa_family, SOCK_STREAM, 0)) < 0)
+   if(self->connInfo.username[0] != '\0')
    {
-       return FALSE;
+       size_t size = (sizeof(char) * (strlen(" user=") + strlen(self->connInfo.username) + 1));
+       conninfo = (char *)realloc(conninfo,size+strlen(conninfo));
+       if(!conninfo)
+       {
+           CC_set_error(self, CONN_MEMORY_ALLOCATION_FAILED,"Could not allocate memory for connection string(username)");
+           mylog("i could not allocate memory for username \n");
+       }
+       conninfo = strcat(conninfo," user=");
+       conninfo = strcat(conninfo,self->connInfo.username);
    }
-   if (connect(tmpsock, conn->sock->sadr, conn->sock->sadr_len) < 0)
+
+
+   if(self->connInfo.password[0] != '\0')
    {
-       closesocket(tmpsock);
-       return FALSE;
+       size_t size = (sizeof(char) * (strlen(" password=") + strlen(self->connInfo.password) + 1));
+       conninfo = (char *)realloc(conninfo,size+strlen(conninfo));
+       if(!conninfo)
+       {
+           CC_set_error(self, CONN_MEMORY_ALLOCATION_FAILED,"Could not allocate memory for connection string(password)");
+           mylog("i could not allocate memory for password \n");
+       }
+       conninfo = strcat(conninfo," password=");
+       conninfo = strcat(conninfo,self->connInfo.password);
    }
 
-   /*
-    * We needn't set nonblocking I/O or NODELAY options here.
-    */
-   crp.packetlen = htonl((uint32) sizeof(crp));
-   crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE);
-   crp.cp.backendPID = htonl(conn->be_pid);
-   crp.cp.cancelAuthCode = htonl(conn->be_key);
-
-   if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
+   self->pgconn = PQconnectdb(conninfo);
+   if (PQstatus(self->pgconn) != CONNECTION_OK)
    {
-       save_errno = SOCK_ERRNO;
-       ret = FALSE;
+       CC_set_error(self,CONNECTION_COULD_NOT_ESTABLISH,PQerrorMessage(self->pgconn));
+       mylog("could not establish connection to the database %s \n",PQerrorMessage(self->pgconn));
+       exit_nicely(self->pgconn);
+       free(conninfo);
+       return 0;
    }
+   /* free the conninfo structure */
+   free(conninfo);
+   mylog("connection to the database succeeded.\n");
+   return 1;
+}
 
-   /* Sent it, done */
-   closesocket(tmpsock);
-   SOCK_ERRNO_SET(save_errno);
 
-   return ret;
+QResultClass *
+LIBPQ_execute_query(ConnectionClass *self,char *query)
+{
+   QResultClass *qres;
+   PGresult *pgres;
+   char        *ptr;
+   char        cmdbuffer[ERROR_MSG_LENGTH + 1];
+   strcpy(cmdbuffer,query);
+   mylog("send_query: setting cmdbuffer = '%s'\n", cmdbuffer);
+   pgres = PQexec(self->pgconn,query);
+   qres=QR_Constructor();
+   if(!qres)
+   {
+       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not allocate memory for result set");
+       QR_Destructor(qres);
+   }
+   qres->status = PQresultStatus(pgres);
+   if( (PQresultStatus(pgres) == PGRES_COMMAND_OK) )
+   {
+       mylog("The query was executed successfully and the query did not return any result \n");
+       PQclear(pgres);
+       return qres;
+   }
+   if ( (PQresultStatus(pgres) != PGRES_EMPTY_QUERY) && (PQresultStatus(pgres) != PGRES_TUPLES_OK) )
+    {
+       mylog("inside if loop got no result from the empty query.  (probably database does not exist)\n");
+       CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server");
+        PQclear(pgres);
+       return qres;
+    }
+   if (strnicmp(cmdbuffer, "BEGIN", 5) == 0)
+   {
+       CC_set_in_trans(self);
+   }
+   else if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
+       CC_on_commit(self);
+   else if (strnicmp(cmdbuffer, "ROLLBACK", 8) == 0)
+       CC_on_abort(self, NO_TRANS);
+   else if (strnicmp(cmdbuffer, "END", 3) == 0)
+       CC_on_commit(self);
+   else if (strnicmp(cmdbuffer, "ABORT", 5) == 0)
+       CC_on_abort(self, NO_TRANS);
+   else
+   {
+       trim(cmdbuffer); /* get rid of trailing space */
+       ptr = strrchr(cmdbuffer, ' ');
+       if (ptr)
+           qres->recent_processed_row_count = atoi(ptr + 1);
+       else
+           qres->recent_processed_row_count = -1;
+   }
+   qres=CC_mapping(pgres,qres);
+   QR_set_command(qres, cmdbuffer);
+   return qres;
 }
 
-int    CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plan)
-{
-   int cnt = conn->num_discardp + 1;
-   char    *pname;
+/*
+ * This function populates the manual_tuples of QResultClass using PGresult class.
+ */
 
-   CC_REALLOC_return_with_error(conn->discardp, char *,
-       (cnt * sizeof(char *)), conn, "Couldn't alloc discardp.", -1) 
-   CC_MALLOC_return_with_error(pname, char, (strlen(plan) + 1),
-       conn, "Couldn't alloc discardp mem.", -1)
-   strcpy(pname, plan);
-   conn->discardp[conn->num_discardp++] = pname; 
-   return 1;
-}
-int    CC_discard_marked_plans(ConnectionClass *conn)
+QResultClass *
+CC_mapping(PGresult *pgres,QResultClass *qres)
 {
-   int i, cnt;
-   QResultClass *res;
-   char    cmd[32];
-
-   if ((cnt = conn->num_discardp) <= 0)
-       return 0;
-   for (i = cnt - 1; i >= 0; i--)
-   {
-       sprintf(cmd, "DEALLOCATE \"%s\"", conn->discardp[i]);
-       res = CC_send_query(conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
-       if (res)
+   int i=0,j=0;
+   TupleNode *node, *temp;
+   Oid typid;
+   int atttypmod,typlen;
+   int num_attributes = PQnfields(pgres);
+   int num_tuples = PQntuples(pgres);
+
+   CI_set_num_fields(qres->fields, num_attributes);
+   for(i = 0 ; i < num_attributes ; i++)
+   {
+       typid = PQftype(pgres,i);
+       atttypmod = PQfmod(pgres,i);
+       typlen = PQfsize(pgres,i);
+       if(typlen == -1 || PG_TYPE_VARCHAR == typid)
+           typlen = MAX_VARCHAR_SIZE;
+       switch (typid)
        {
-           QR_Destructor(res);
-           free(conn->discardp[i]);
-           conn->num_discardp--;
+           case PG_TYPE_DATETIME:
+           case PG_TYPE_TIMESTAMP_NO_TMZONE:
+           case PG_TYPE_TIME:
+           case PG_TYPE_TIME_WITH_TMZONE:
+               break;
+           default:
+               atttypmod -= 4;
        }
-       else
-           return -1;
+       if (atttypmod < 0)
+           atttypmod = -1;
+       CI_set_field_info(qres->fields, i, PQfname(pgres,i),
+             typid, (Int2)typlen, atttypmod);
    }
-   return 1;
+   qres->manual_tuples = TL_Constructor(num_attributes);
+   qres->manual_tuples->num_tuples = (Int4)num_tuples;
+   for(i=0;i < num_tuples;i++)
+   {
+           node = (TupleNode *)malloc(sizeof(TupleNode) + (num_attributes ) * sizeof(TupleField));
+           if(!node)
+           {
+               QR_set_status(qres, PGRES_FATAL_ERROR);
+               QR_set_message(qres, "Error could not allocate memory for row.");
+           }
+           if (i==0)
+           {
+               qres->manual_tuples->list_start = qres->manual_tuples->list_end = node;
+               qres->manual_tuples->lastref = node;
+               qres->manual_tuples->last_indexed = 0;
+               qres->manual_tuples->list_end->next = NULL;
+           }
+           else
+           {
+               temp = qres->manual_tuples->list_end;
+               qres->manual_tuples->list_end->next = node;
+               qres->manual_tuples->list_end = node;
+               qres->manual_tuples->list_end->prev = temp;
+               qres->manual_tuples->list_end->next = NULL;
+           }
+           for(j=0;j < num_attributes ;j++)
+           {
+               set_tuplefield_string(&qres->manual_tuples->list_end->tuple[j],PQgetvalue(pgres,i,j));
+           }
+
+   }
+       return qres;
 }
+
+
+#endif /* USE_LIBPQ */
+
+
index 279ff796000e63e0ed71b43d2d4272c721d87a9c..018e256fd36dcb999a7e01cdc11d6a0d6f807257 100644 (file)
@@ -6,6 +6,8 @@
  *
  */
 
+#ifndef USE_LIBPQ
+
 #ifndef __CONNECTION_H__
 #define __CONNECTION_H__
 
@@ -461,3 +463,5 @@ int     CC_discard_marked_plans(ConnectionClass *conn);
 #define    CONN_DEAD       (1L << 1) /* connection is no longer valid */
 
 #endif /* __CONNECTION_H__ */
+
+#endif /* USE_LIBPQ */
index 58c5449e09affa48e3f8c89349ef2a61f2f646ba..c560e8bc195da9cc63f45e28463bf1686ec65fa6 100644 (file)
--- a/convert.c
+++ b/convert.c
 #include "bind.h"
 #include "pgtypes.h"
 #include "lobj.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "pgapifunc.h"
 
 #ifdef __CYGWIN__
@@ -470,9 +476,12 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
    std_time.m = tim->tm_mon + 1;
    std_time.d = tim->tm_mday;
    std_time.y = tim->tm_year + 1900;
-
+   /* Setting the value as NULL when 
+    * PQgetvalue returns a null terminated string.*/
+   value = ((char *) value)[0]?value:NULL;
    mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "<NULL>" : value, cbValueMax);
-
+   
+   
    if (!value)
    {
        /*
@@ -2911,7 +2920,12 @@ ResolveOneParam(QueryBuild *qb)
                }
 
                /* store the oid */
+#ifdef USE_LIBPQ
+               lobj_oid = lo_creat(conn->pgconn, INV_READ | INV_WRITE);
+#else
                lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
+#endif /* USE_LIBPQ */
+
                if (lobj_oid == 0)
                {
                    qb->errornumber = STMT_EXEC_ERROR;
@@ -2920,17 +2934,27 @@ ResolveOneParam(QueryBuild *qb)
                }
 
                /* store the fd */
+#ifdef USE_LIBPQ
+               lobj_fd = lo_open(conn->pgconn, lobj_oid, INV_WRITE);
+#else
                lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);
+#endif /* USE_LIBPQ */
+
                if (lobj_fd < 0)
                {
                    qb->errornumber = STMT_EXEC_ERROR;
                    qb->errormsg = "Couldnt open (in-line) large object for writing.";
                    return SQL_ERROR;
                }
+#ifdef USE_LIBPQ
+           retval = lo_write(conn->pgconn, lobj_fd, buffer, used);
+           lo_close(conn->pgconn, lobj_fd);
 
+#else
                retval = lo_write(conn, lobj_fd, buffer, used);
 
                lo_close(conn, lobj_fd);
+#endif /* USE_LIBPQ */
 
                /* commit transaction if needed */
                if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
@@ -3891,7 +3915,12 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        }
 
        oid = ATOI32U(value);
+#ifdef USE_LIBPQ
+           stmt->lobj_fd = lo_open(conn->pgconn, oid, INV_READ);
+#else
        stmt->lobj_fd = lo_open(conn, oid, INV_READ);
+#endif /* USE_LIBPQ*/
+
        if (stmt->lobj_fd < 0)
        {
            SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for reading.");
@@ -3899,15 +3928,30 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        }
 
        /* Get the size */
+#ifdef USE_LIBPQ
+           retval = lo_lseek(conn->pgconn, stmt->lobj_fd, 0L, SEEK_END);
+#else
        retval = lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_END);
+#endif /* USE_LIBPQ*/
+
        if (retval >= 0)
        {
+#ifdef USE_LIBPQ
+           left = lo_tell(conn->pgconn, stmt->lobj_fd);
+#else
            left = lo_tell(conn, stmt->lobj_fd);
+#endif /* USE_LIBPQ*/
+
            if (gdata)
                gdata->data_left = left;
 
            /* return to beginning */
+#ifdef USE_LIBPQ
+           lo_lseek(conn->pgconn, stmt->lobj_fd, 0L, SEEK_SET);
+#else
            lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET);
+#endif /* USE_LIBPQ*/
+
        }
    }
    mylog("lo data left = %d\n", left);
@@ -3921,10 +3965,20 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        return COPY_GENERAL_ERROR;
    }
 
+#ifdef USE_LIBPQ
+   retval = lo_read(conn->pgconn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax);
+#else
    retval = lo_read(conn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax);
+#endif /* USE_LIBPQ */
+
    if (retval < 0)
    {
+#ifdef USE_LIBPQ
+       lo_close(conn->pgconn, stmt->lobj_fd);
+#else
        lo_close(conn, stmt->lobj_fd);
+#endif /* USE_LIBPQ */
+
 
        /* commit transaction if needed */
        if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
@@ -3957,7 +4011,11 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
 
    if (!gdata || gdata->data_left == 0)
    {
+#ifdef USE_LIBPQ
+       lo_close(conn->pgconn, stmt->lobj_fd);
+#else
        lo_close(conn, stmt->lobj_fd);
+#endif /* USE_LIBPQ */
 
        /* commit transaction if needed */
        if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
index 6e1bd81425dbd4bf5252c6f6c6965db743e739a3..d9a344a1526f0ff53c07e355346fe99c061208b3 100644 (file)
  */
 
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "descriptor.h"
 #include "statement.h"
 
index f79d0e7367de3ba301e0e1053cbb4d962e251ef3..b172c6f7c84ecf5d173e0ea2f7fbf53edec47cde 100644 (file)
@@ -286,10 +286,12 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
    else if (stricmp(attribute, INI_PORT) == 0)
        strcpy(ci->port, value);
 
+#ifndef USE_LIBPQ
 #ifdef HAVE_UNIX_SOCKETS
    else if (stricmp(attribute, INI_UDS) == 0)
        strcpy(ci->uds, value);
 #endif
+#endif /*USE_LIBPQ*/
 
    else if (stricmp(attribute, INI_READONLY) == 0 || stricmp(attribute, "A0") == 0)
        strcpy(ci->onlyread, value);
@@ -497,10 +499,12 @@ getDSNinfo(ConnInfo *ci, char overwrite)
    if (ci->port[0] == '\0' || overwrite)
        SQLGetPrivateProfileString(DSN, INI_PORT, "", ci->port, sizeof(ci->port), ODBC_INI);
 
+#ifndef USE_LIBPQ
 #ifdef HAVE_UNIX_SOCKETS
    if (ci->uds[0] == '\0' || overwrite)
        SQLGetPrivateProfileString(DSN, INI_UDS, "", ci->uds, sizeof(ci->uds), ODBC_INI);
 #endif
+#endif /* USE_LIBPQ */
 
    if (ci->onlyread[0] == '\0' || overwrite)
        SQLGetPrivateProfileString(DSN, INI_READONLY, "", ci->onlyread, sizeof(ci->onlyread), ODBC_INI);
@@ -735,12 +739,14 @@ writeDSNinfo(const ConnInfo *ci)
                                 ci->port,
                                 ODBC_INI);
 
+#ifndef USE_LIBPQ
 #ifdef HAVE_UNIX_SOCKETS
    SQLWritePrivateProfileString(DSN,
                                 INI_UDS,
                                 ci->uds,
                                 ODBC_INI);
 #endif
+#endif /* USE_LIBPQ */
 
    SQLWritePrivateProfileString(DSN,
                                 INI_USER,
index 4097e3aa5071207bd15e226816f6c5de532d1ed4..11a0074ba01fe391b5ded5a58d41e3f5e7daa216 100644 (file)
 #define __DLG_SPECIFIC_H__
 
 #include "psqlodbc.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
 
 #ifdef WIN32
 #include  <windowsx.h>
index 3ea1867d03af7ff629aa2904443db4f197b3a65c..0a97df1511014379d080f36a5d17231fb4f0b59e 100644 (file)
--- a/drvconn.c
+++ b/drvconn.c
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
 
 #ifndef WIN32
 #include <sys/types.h>
index fb12a9521a617cd24351e7467325b5414da35501..4a513f65e6a95829ba29e39f04ceeff542b26f82 100644 (file)
--- a/environ.c
+++ b/environ.c
 
 #include "environ.h"
 
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "dlg_specific.h"
 #include "statement.h"
 #include <stdlib.h>
@@ -156,7 +161,7 @@ ER_ReturnError(PG_ErrorInfo *error,
    /*
     *  Even though an application specifies a larger error message
     *  buffer, the driver manager changes it silently.
-    *  Therefore we divide the error message into ... 
+    *  Therefore we divide the error message into ...
     */
    if (error->recsize < 0)
    {
@@ -174,19 +179,19 @@ ER_ReturnError(PG_ErrorInfo *error,
    }
    stapos = (RecNumber - 1) * error->recsize;
    if (stapos > msglen)
-       return SQL_NO_DATA_FOUND; 
+       return SQL_NO_DATA_FOUND;
    pcblen = wrtlen = msglen - stapos;
    if (pcblen > error->recsize)
        pcblen = error->recsize;
    if (0 == cbErrorMsgMax)
-       wrtlen = 0; 
+       wrtlen = 0;
    else if (wrtlen >= cbErrorMsgMax)
    {
        if (partial_ok)
            wrtlen = cbErrorMsgMax - 1;
        else if (cbErrorMsgMax <= error->recsize)
            wrtlen = 0;
-       else 
+       else
            wrtlen = error->recsize;
    }
    if (wrtlen > pcblen)
@@ -263,7 +268,7 @@ PGAPI_StmtError(    HSTMT hstmt,
    /*
     *  Even though an application specifies a larger error message
     *  buffer, the driver manager changes it silently.
-    *  Therefore we divide the error message into ... 
+    *  Therefore we divide the error message into ...
     */
    if (stmt->error_recsize < 0)
    {
@@ -281,19 +286,19 @@ PGAPI_StmtError(  HSTMT hstmt,
    }
    stapos = (RecNumber - 1) * stmt->error_recsize;
    if (stapos > msglen)
-       return SQL_NO_DATA_FOUND; 
+       return SQL_NO_DATA_FOUND;
    pcblen = wrtlen = msglen - stapos;
    if (pcblen > stmt->error_recsize)
        pcblen = stmt->error_recsize;
    if (0 == cbErrorMsgMax)
-       wrtlen = 0; 
+       wrtlen = 0;
    else if (wrtlen >= cbErrorMsgMax)
    {
        if (partial_ok)
            wrtlen = cbErrorMsgMax - 1;
        else if (cbErrorMsgMax <= stmt->error_recsize)
            wrtlen = 0;
-       else 
+       else
            wrtlen = stmt->error_recsize;
    }
    if (wrtlen > pcblen)
@@ -608,7 +613,7 @@ PGAPI_EnvError(     HENV henv,
    if (!EN_get_error(env, &status, &msg) || NULL == msg)
    {
            mylog("EN_get_error: status = %d, msg = #%s#\n", status, msg);
-       
+
        if (NULL != szSqlState)
            pg_sqlstate_set(env, szSqlState, "00000", "00000");
        if (NULL != pcbErrorMsg)
index fb6d3f00820a2919ace0114e956a935b3c27bd48..93539e78840a29cc7ea52f640e58fed8482cc4b5 100644 (file)
--- a/execute.c
+++ b/execute.c
 #include <string.h>
 
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 #include "qresult.h"
 #include "convert.h"
@@ -226,7 +232,7 @@ RETCODE Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
 
    /*
     *  Dummy exection to get the column info.
-    */ 
+    */
    if (stmt->inaccurate_result && conn->connInfo.disallow_premature)
    {
        BOOL        in_trans = CC_is_in_trans(conn);
@@ -301,7 +307,7 @@ RETCODE Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
        if (res && QR_command_maybe_successful(res))
        {
            QResultClass    *kres;
-       
+
            kres = res->next;
            SC_set_Result(stmt, kres);
            res->next = NULL;
@@ -323,13 +329,13 @@ RETCODE   Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
    {
        switch (retval)
        {
-           case SQL_SUCCESS: 
+           case SQL_SUCCESS:
                ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
                break;
-           case SQL_SUCCESS_WITH_INFO: 
+           case SQL_SUCCESS_WITH_INFO:
                ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
                break;
-           default: 
+           default:
                ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
                break;
        }
@@ -493,9 +499,9 @@ PGAPI_Execute(HSTMT hstmt, UWORD flag)
    }
 
    if (start_row = stmt->exec_start_row, start_row < 0)
-       start_row = 0; 
+       start_row = 0;
    if (end_row = stmt->exec_end_row, end_row < 0)
-       end_row = apdopts->paramset_size - 1; 
+       end_row = apdopts->paramset_size - 1;
    if (stmt->exec_current_row < 0)
        stmt->exec_current_row = start_row;
    ipdopts = SC_get_IPDF(stmt);
@@ -505,7 +511,7 @@ PGAPI_Execute(HSTMT hstmt, UWORD flag)
            *ipdopts->param_processed_ptr = 0;
 
        /*
-        *  Initialize the param_status_ptr 
+        *  Initialize the param_status_ptr
         */
        if (ipdopts->param_status_ptr)
        {
@@ -532,7 +538,7 @@ next_param_row:
        }
    }
    /*
-    *  Initialize the current row status 
+    *  Initialize the current row status
     */
    if (ipdopts->param_status_ptr)
        ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
@@ -553,7 +559,7 @@ next_param_row:
        Int4    current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
 
        /*
-        *  Increment the  number of currently processed rows 
+        *  Increment the  number of currently processed rows
         */
        if (ipdopts->param_processed_ptr)
            (*ipdopts->param_processed_ptr)++;
@@ -866,7 +872,11 @@ PGAPI_ParamData(
    /* close the large object */
    if (estmt->lobj_fd >= 0)
    {
+#ifdef USE_LIBPQ
+       lo_close(estmt->hdbc->pgconn, estmt->lobj_fd);
+#else
        lo_close(estmt->hdbc, estmt->lobj_fd);
+#endif /* USE_LIBPQ */
 
        /* commit transaction if needed */
        if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(estmt->hdbc))
@@ -917,7 +927,7 @@ PGAPI_ParamData(
                if (stmt->execute_delegate)
                {
                    UInt4   offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
-                   UInt4   perrow = apdopts->param_bind_type > 0 ? apdopts->param_bind_type : apdopts->parameters[i].buflen; 
+                   UInt4   perrow = apdopts->param_bind_type > 0 ? apdopts->param_bind_type : apdopts->parameters[i].buflen;
 
                    *prgbValue = apdopts->parameters[i].buffer + offset + estmt->exec_current_row * perrow;
                }
@@ -1056,7 +1066,11 @@ PGAPI_PutData(
            }
 
            /* store the oid */
+#ifdef USE_LIBPQ
+           current_pdata->lobj_oid = lo_creat(conn->pgconn, INV_READ | INV_WRITE);
+#else
            current_pdata->lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
+#endif /* USE_LIBPQ */
            if (current_pdata->lobj_oid == 0)
            {
                SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt create large object.");
@@ -1071,7 +1085,11 @@ PGAPI_PutData(
            /***current_param->EXEC_buffer = (char *) &current_param->lobj_oid;***/
 
            /* store the fd */
+#ifdef USE_LIBPQ
+           estmt->lobj_fd = lo_open(conn->pgconn, current_pdata->lobj_oid, INV_WRITE);
+#else
            estmt->lobj_fd = lo_open(conn, current_pdata->lobj_oid, INV_WRITE);
+#endif /* USE_LIBPQ */
            if (estmt->lobj_fd < 0)
            {
                SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for writing.");
@@ -1079,7 +1097,11 @@ PGAPI_PutData(
                return SQL_ERROR;
            }
 
+#ifdef USE_LIBPQ
+           retval = lo_write(conn->pgconn, estmt->lobj_fd, putbuf, putlen);
+#else
            retval = lo_write(conn, estmt->lobj_fd, putbuf, putlen);
+#endif /* USE_LIBPQ */
            mylog("lo_write: cbValue=%d, wrote %d bytes\n", putlen, retval);
        }
        else
@@ -1104,7 +1126,11 @@ PGAPI_PutData(
        if (current_iparam->PGType == conn->lobj_type)
        {
            /* the large object fd is in EXEC_buffer */
+#ifdef USE_LIBPQ
+           retval = lo_write(conn->pgconn, estmt->lobj_fd, putbuf, putlen);
+#else
            retval = lo_write(conn, estmt->lobj_fd, putbuf, putlen);
+#endif /* USE_LIBPQ */
            mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", putlen, retval);
 
            *current_pdata->EXEC_used += putlen;
diff --git a/info.c b/info.c
index 45712370d7b4b10e6a45c1138af62dfd4102e80d..ff26d0958276e1e1820f73bd57fc8b7b22fe6731 100644 (file)
--- a/info.c
+++ b/info.c
 #include "dlg_specific.h"
 
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 #include "qresult.h"
 #include "bind.h"
@@ -1218,7 +1224,7 @@ PGAPI_Tables(
    char        show_system_tables,
                show_regular_tables,
                show_views,
-               remarks[254]; //Added for holding Table Description, if any.
+               remarks[254]; /*Added for holding Table Description, if any.*/
    char        regular_table,
                view,
                systable;
index 06b0694db7a62902dabaff279750b47c502cccc3..d9b9273911a39f986c016d552e542285c790940e 100644 (file)
--- a/info30.c
+++ b/info30.c
@@ -8,7 +8,12 @@
 
 #include "psqlodbc.h"
 
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "pgapifunc.h"
 
 RETCODE        SQL_API
@@ -183,11 +188,11 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
            len = 4;
            value = SQL_CT_CREATE_TABLE | SQL_CT_COLUMN_CONSTRAINT
                | SQL_CT_COLUMN_DEFAULT;
-           if (PG_VERSION_GE(conn, 6.5)) 
-               value |= SQL_CT_GLOBAL_TEMPORARY; 
-           if (PG_VERSION_GE(conn, 7.0)) 
+           if (PG_VERSION_GE(conn, 6.5))
+               value |= SQL_CT_GLOBAL_TEMPORARY;
+           if (PG_VERSION_GE(conn, 7.0))
                value |= SQL_CT_TABLE_CONSTRAINT
-                   | SQL_CT_CONSTRAINT_NAME_DEFINITION 
+                   | SQL_CT_CONSTRAINT_NAME_DEFINITION
                    | SQL_CT_CONSTRAINT_INITIALLY_DEFERRED
                    | SQL_CT_CONSTRAINT_INITIALLY_IMMEDIATE
                    | SQL_CT_CONSTRAINT_DEFERRABLE;
@@ -296,7 +301,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
            break;
        case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS:
            len = 4;
-           value = SQL_SNVF_BIT_LENGTH | SQL_SNVF_CHAR_LENGTH 
+           value = SQL_SNVF_BIT_LENGTH | SQL_SNVF_CHAR_LENGTH
                | SQL_SNVF_CHARACTER_LENGTH | SQL_SNVF_EXTRACT
                | SQL_SNVF_OCTET_LENGTH | SQL_SNVF_POSITION;
            break;
@@ -315,7 +320,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                    | SQL_SRJO_FULL_OUTER_JOIN | SQL_SRJO_INNER_JOIN
                    | SQL_SRJO_INTERSECT_JOIN | SQL_SRJO_LEFT_OUTER_JOIN
                    | SQL_SRJO_NATURAL_JOIN | SQL_SRJO_RIGHT_OUTER_JOIN
-                   | SQL_SRJO_UNION_JOIN; 
+                   | SQL_SRJO_UNION_JOIN;
            break;
        case SQL_SQL92_REVOKE:
            len = 4;
@@ -369,7 +374,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                  */
                 if (conn->unicode)
                     len = len * WCLEN;
-                
+
        if (rgbInfoValue)
        {
 
@@ -401,7 +406,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
        *pcbInfoValue = len;
 
    mylog("%s: p='%s', len=%d, value=%d, cbMax=%d\n", func, p ? p : "<NULL>", len, value, cbInfoValueMax);
-   
+
    return result;
 }
 
index 22eed5b57539f6e5cf71a88c975a6d23e76f973e..de715ac01e3bfb60925f670fe0439f9a0dea92a5 100644 (file)
@@ -3,7 +3,7 @@
 if NOT "%1"=="" SET VERSION="%1"
 if NOT "%1"=="" GOTO GOT_VERSION
 
-SET VERSION="08.00.0101"
+SET VERSION="08.01.0001"
 echo.
 echo Version not specified - defaulting to %VERSION%
 echo.
diff --git a/libpqconnection.h b/libpqconnection.h
new file mode 100644 (file)
index 0000000..8061ea6
--- /dev/null
@@ -0,0 +1,420 @@
+/* File:           libpqconnection.h
+ *
+ * Description:        See "libpqconnection.c"
+ *
+ * Comments:       See "notice.txt" for copyright and license information.
+ *
+ */
+
+#ifdef USE_LIBPQ
+
+#ifndef __LIBPQCONNECTION_H__
+#define __LIBPQCONNECTION_H__
+
+#include "psqlodbc.h"
+#include <libpq-fe.h>
+#include <stdlib.h>
+#include <string.h>
+#include "descriptor.h"
+
+#if defined (POSIX_MULTITHREAD_SUPPORT)
+#include <pthread.h>
+#endif
+
+#if !defined WIN32 && defined HAVE_SYS_UN_H && !defined HAVE_UNIX_SOCKETS
+#define HAVE_UNIX_SOCKETS
+#endif
+
+/* These errors have general sql error state */
+#define CONNECTION_SERVER_NOT_REACHED          101
+#define CONNECTION_MSG_TOO_LONG                    103
+#define CONNECTION_COULD_NOT_SEND              104
+#define CONNECTION_NO_SUCH_DATABASE                105
+#define CONNECTION_BACKEND_CRAZY               106
+#define CONNECTION_NO_RESPONSE                 107
+#define CONNECTION_SERVER_REPORTED_ERROR       108
+#define CONNECTION_COULD_NOT_RECEIVE           109
+#define CONNECTION_SERVER_REPORTED_WARNING     110
+#define CONNECTION_NEED_PASSWORD               112
+#define CONNECTION_COULD_NOT_ESTABLISH         113
+
+/* These errors correspond to specific SQL states */
+#define CONN_INIREAD_ERROR                     201
+#define CONN_OPENDB_ERROR                      202
+#define CONN_STMT_ALLOC_ERROR                  203
+#define CONN_IN_USE                                204
+#define CONN_UNSUPPORTED_OPTION                    205
+/* Used by SetConnectoption to indicate unsupported options */
+#define CONN_INVALID_ARGUMENT_NO               206
+/* SetConnectOption: corresponds to ODBC--"S1009" */
+#define CONN_TRANSACT_IN_PROGRES               207
+#define CONN_NO_MEMORY_ERROR                   208
+#define CONN_NOT_IMPLEMENTED_ERROR             209
+#define CONN_INVALID_AUTHENTICATION                210
+#define CONN_AUTH_TYPE_UNSUPPORTED             211
+#define CONN_UNABLE_TO_LOAD_DLL                    212
+
+#define CONN_OPTION_VALUE_CHANGED              213
+#define CONN_VALUE_OUT_OF_RANGE                    214
+
+#define CONN_TRUNCATED                         215
+
+
+#define CONN_MEMORY_ALLOCATION_FAILED          301
+#define COULD_NOT_GET_RESULT_BACK              302
+
+/* Conn_status defines */
+#define CONN_IN_AUTOCOMMIT     1L
+#define CONN_IN_TRANSACTION        (1L<<1)
+#define CONN_IN_MANUAL_TRANSACTION (1L<<2)
+#define CONN_IN_ERROR_BEFORE_IDLE  (1L<<3)
+
+/* AutoCommit functions */
+#define CC_set_autocommit_off(x)   (x->transact_status &= ~CONN_IN_AUTOCOMMIT)
+#define CC_set_autocommit_on(x)        (x->transact_status |= CONN_IN_AUTOCOMMIT)
+#define CC_is_in_autocommit(x)     (x->transact_status & CONN_IN_AUTOCOMMIT)
+
+/* Transaction in/not functions */
+#define CC_set_in_trans(x) (x->transact_status |= CONN_IN_TRANSACTION)
+#define CC_set_no_trans(x) (x->transact_status &= ~(CONN_IN_TRANSACTION | CONN_IN_ERROR_BEFORE_IDLE))
+#define CC_is_in_trans(x)  (x->transact_status & CONN_IN_TRANSACTION)
+
+/* Manual transaction in/not functions */
+#define CC_set_in_manual_trans(x) (x->transact_status |= CONN_IN_MANUAL_TRANSACTION)
+#define CC_set_no_manual_trans(x) (x->transact_status &= ~CONN_IN_MANUAL_TRANSACTION)
+#define CC_is_in_manual_trans(x) (x->transact_status & CONN_IN_MANUAL_TRANSACTION)
+
+/* Error waiting for ROLLBACK */
+#define CC_set_in_error_trans(x) (x->transact_status |= CONN_IN_ERROR_BEFORE_IDLE)
+#define CC_set_no_error_trans(x) (x->transact_status &= ~CONN_IN_ERROR_BEFORE_IDLE)
+#define CC_is_in_error_trans(x) (x->transact_status & CONN_IN_ERROR_BEFORE_IDLE)
+
+#define CC_get_errornumber(x)  (x->__error_number)
+#define CC_get_errormsg(x) (x->__error_message)
+#define CC_set_errornumber(x, n)   (x->__error_number = n)
+
+#define CC_MALLOC_return_with_error(t, tp, s, x, m, ret) \
+   { \
+       if (t = malloc(s), NULL == t) \
+       { \
+           CC_set_error(x, CONN_NO_MEMORY_ERROR, m); \
+           return ret; \
+       } \
+   }
+#define CC_REALLOC_return_with_error(t, tp, s, x, m, ret) \
+   { \
+       if (t = (tp *) realloc(t, s), NULL == t) \
+       { \
+           CC_set_error(x, CONN_NO_MEMORY_ERROR, m); \
+           return ret; \
+       } \
+   }
+
+/* For Multi-thread */
+#if defined(WIN_MULTITHREAD_SUPPORT)
+#define INIT_CONN_CS(x)        InitializeCriticalSection(&((x)->cs))
+#define ENTER_CONN_CS(x)   EnterCriticalSection(&((x)->cs))
+#define ENTER_INNER_CONN_CS(x, entered) \
+   { EnterCriticalSection(&((x)->cs)); entered++; }
+#define LEAVE_CONN_CS(x)   LeaveCriticalSection(&((x)->cs))
+#define DELETE_CONN_CS(x)  DeleteCriticalSection(&((x)->cs))
+#elif defined(POSIX_THREADMUTEX_SUPPORT)
+#define INIT_CONN_CS(x)        pthread_mutex_init(&((x)->cs), getMutexAttr())
+#define ENTER_CONN_CS(x)   pthread_mutex_lock(&((x)->cs))
+#define ENTER_INNER_CONN_CS(x, entered) \
+   { \
+       if (getMutexAttr()) \
+       { \
+           if (pthread_mutex_lock(&((x)->cs)) == 0) \
+               entered++; \
+           else \
+               -1; \
+       } \
+       else \
+           0; \
+   }
+#define LEAVE_CONN_CS(x)   pthread_mutex_unlock(&((x)->cs))
+#define DELETE_CONN_CS(x)  pthread_mutex_destroy(&((x)->cs))
+#else
+#define INIT_CONN_CS(x)
+#define ENTER_CONN_CS(x)
+#define ENTER_INNER_CONN_CS(x, entered) (0)
+#define LEAVE_CONN_CS(x)
+#define DELETE_CONN_CS(x)
+#endif /* WIN_MULTITHREAD_SUPPORT */
+
+#define    LEAVE_INNER_CONN_CS(entered, conn) \
+   { \
+       if (entered > 0) \
+       { \
+           LEAVE_CONN_CS(conn); \
+           entered--; \
+       } \
+   }
+#define    CLEANUP_FUNC_CONN_CS(entered, conn) \
+   while (entered > 0) \
+   { \
+       LEAVE_CONN_CS(conn); \
+       entered--; \
+   }
+
+
+#define AUTH_REQ_OK                                0
+#define AUTH_REQ_KRB4                          1
+#define AUTH_REQ_KRB5                          2
+#define AUTH_REQ_PASSWORD                      3
+#define AUTH_REQ_CRYPT                         4
+#define AUTH_REQ_MD5                           5
+#define AUTH_REQ_SCM_CREDS                     6
+
+/* Old 6.2 protocol defines */
+#define NO_AUTHENTICATION                      7
+#define PATH_SIZE                              64
+#define ARGV_SIZE                              64
+#define USRNAMEDATALEN                         16
+
+typedef unsigned int ProtocolVersion;
+
+#define PG_PROTOCOL(major, minor)  (((major) << 16) | (minor))
+#define PG_PROTOCOL_LATEST                         PG_PROTOCOL(2, 0)
+#define PG_PROTOCOL_63                             PG_PROTOCOL(1, 0)
+#define PG_PROTOCOL_62                             PG_PROTOCOL(0, 0)
+
+
+typedef enum
+{
+   CONN_NOT_CONNECTED,         /* Connection has not been established */
+   CONN_CONNECTED,             /* Connection is up and has been
+                                * established */
+   CONN_DOWN,                  /* Connection is broken */
+   CONN_EXECUTING              /* the connection is currently executing a
+                                * statement */
+} CONN_Status;
+
+/* Transferred from pqcomm.h:  */
+
+
+typedef ProtocolVersion MsgType;
+
+/* Structure to hold all the connection attributes for a specific
+   connection (used for both registry and file, DSN and DRIVER) */
+
+typedef struct
+{
+   char        dsn[MEDIUM_REGISTRY_LEN];
+   char        desc[MEDIUM_REGISTRY_LEN];
+   char        drivername[MEDIUM_REGISTRY_LEN];
+   char        server[MEDIUM_REGISTRY_LEN];
+   char        database[MEDIUM_REGISTRY_LEN];
+   char        username[MEDIUM_REGISTRY_LEN];
+   char        password[MEDIUM_REGISTRY_LEN];
+   char        conn_settings[LARGE_REGISTRY_LEN];
+   char        protocol[SMALL_REGISTRY_LEN];
+   char        port[SMALL_REGISTRY_LEN];
+   char        onlyread[SMALL_REGISTRY_LEN];
+   char        fake_oid_index[SMALL_REGISTRY_LEN];
+   char        show_oid_column[SMALL_REGISTRY_LEN];
+   char        row_versioning[SMALL_REGISTRY_LEN];
+   char        show_system_tables[SMALL_REGISTRY_LEN];
+   char        translation_dll[MEDIUM_REGISTRY_LEN];
+   char        translation_option[SMALL_REGISTRY_LEN];
+   char        focus_password;
+   signed char disallow_premature;
+   signed char allow_keyset;
+   signed char updatable_cursors;
+   signed char lf_conversion;
+   signed char true_is_minus1;
+   signed char int8_as;
+   signed char bytea_as_longvarbinary;
+   signed char use_server_side_prepare;
+   signed char lower_case_identifier;
+   GLOBAL_VALUES drivers;      /* moved from driver's option */
+} ConnInfo;
+
+
+/* Macro to determine is the connection using 6.2 protocol? */
+#define PROTOCOL_62(conninfo_)     (strncmp((conninfo_)->protocol, PG62, strlen(PG62)) == 0)
+
+/* Macro to determine is the connection using 6.3 protocol? */
+#define PROTOCOL_63(conninfo_)     (strncmp((conninfo_)->protocol, PG63, strlen(PG63)) == 0)
+
+/*
+ * Macros to compare the server's version with a specified version
+ *     1st parameter: pointer to a ConnectionClass object
+ *     2nd parameter: major version number
+ *     3rd parameter: minor version number
+ */
+#define SERVER_VERSION_GT(conn, major, minor) \
+   ((conn)->pg_version_major > major || \
+   ((conn)->pg_version_major == major && (conn)->pg_version_minor > minor))
+#define SERVER_VERSION_GE(conn, major, minor) \
+   ((conn)->pg_version_major > major || \
+   ((conn)->pg_version_major == major && (conn)->pg_version_minor >= minor))
+#define SERVER_VERSION_EQ(conn, major, minor) \
+   ((conn)->pg_version_major == major && (conn)->pg_version_minor == minor)
+#define SERVER_VERSION_LE(conn, major, minor) (! SERVER_VERSION_GT(conn, major, minor))
+#define SERVER_VERSION_LT(conn, major, minor) (! SERVER_VERSION_GE(conn, major, minor))
+/*#if ! defined(HAVE_CONFIG_H) || defined(HAVE_STRINGIZE)*/
+#define STRING_AFTER_DOT(string)   (strchr(#string, '.') + 1)
+/*#else
+#define STRING_AFTER_DOT(str)  (strchr("str", '.') + 1)
+#endif*/
+/*
+ * Simplified macros to compare the server's version with a
+ *     specified version
+ * Note: Never pass a variable as the second parameter.
+ *       It must be a decimal constant of the form %d.%d .
+ */
+#define PG_VERSION_GT(conn, ver) \
+ (SERVER_VERSION_GT(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
+#define PG_VERSION_GE(conn, ver) \
+ (SERVER_VERSION_GE(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
+#define PG_VERSION_EQ(conn, ver) \
+ (SERVER_VERSION_EQ(conn, (int) ver, atoi(STRING_AFTER_DOT(ver))))
+#define PG_VERSION_LE(conn, ver) (! PG_VERSION_GT(conn, ver))
+#define PG_VERSION_LT(conn, ver) (! PG_VERSION_GE(conn, ver))
+
+/* This is used to store cached table information in the connection */
+struct col_info
+{
+   QResultClass *result;
+   char        *schema;
+   char        name[TABLE_NAME_STORAGE_LEN + 1];
+};
+
+ /* Translation DLL entry points */
+#ifdef WIN32
+#define DLLHANDLE HINSTANCE
+#else
+#define WINAPI CALLBACK
+#define DLLHANDLE void *
+#define HINSTANCE void *
+#endif
+
+typedef BOOL (FAR WINAPI * DataSourceToDriverProc) 
+   (UDWORD,SWORD,PTR,SDWORD,PTR,SDWORD,SDWORD FAR *,UCHAR FAR *,SWORD,SWORD FAR *);
+
+typedef BOOL (FAR WINAPI * DriverToDataSourceProc) 
+   (UDWORD,SWORD,PTR,SDWORD,PTR,SDWORD,SDWORD FAR *,UCHAR FAR *,SWORD,SWORD FAR *);
+
+ /*******  The Connection handle   ************/
+struct ConnectionClass_
+{
+   HENV        henv;           /* environment this connection was created
+                                * on */
+   StatementOptions stmtOptions;
+   ARDFields   ardOptions;
+   APDFields   apdOptions;
+   char       *__error_message;
+   int         __error_number;
+   CONN_Status status;
+   ConnInfo    connInfo;
+   StatementClass **stmts;
+   int         num_stmts;
+   PGconn *pgconn;
+   int         lobj_type;
+   int         ntables;
+   COL_INFO  **col_info;
+   UDWORD      translation_option;
+   HINSTANCE   translation_handle;
+   DataSourceToDriverProc DataSourceToDriver;
+   DriverToDataSourceProc DriverToDataSource;
+   Int2        driver_version; /* prepared for ODBC3.0 */
+   char        transact_status;/* Is a transaction is currently in
+                                * progress */
+   char        errormsg_created;       /* has an informative error msg
+                                        * been created?  */
+   char        pg_version[MAX_INFO_STRING];    /* Version of PostgreSQL
+                                                * we're connected to -
+                                                * DJP 25-1-2001 */
+   float       pg_version_number;
+   Int2        pg_version_major;
+   Int2        pg_version_minor;
+   char        ms_jet;
+   char        unicode;
+   char        result_uncommitted;
+   char        schema_support;
+   char        *client_encoding;
+   char        *server_encoding;
+   int     ccsc;
+   int     be_pid; /* pid returned by backend */
+   int     be_key; /* auth code needed to send cancel */
+   UInt4       isolation;
+   char        *current_schema;
+   int     num_discardp;
+   char        **discardp;
+   int     num_descs;
+   DescriptorClass **descs;
+#if defined(WIN_MULTITHREAD_SUPPORT)
+   CRITICAL_SECTION    cs;
+#elif defined(POSIX_THREADMUTEX_SUPPORT)
+   pthread_mutex_t     cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
+};
+
+
+/* Accessor functions */
+#define CC_get_database(x)                 (x->connInfo.database)
+#define CC_get_server(x)                   (x->connInfo.server)
+#define CC_get_DSN(x)                      (x->connInfo.dsn)
+#define CC_get_username(x)                 (x->connInfo.username)
+#define CC_is_onlyread(x)                  (x->connInfo.onlyread[0] == '1')
+
+/* for CC_DSN_info */
+#define CONN_DONT_OVERWRITE        0
+#define CONN_OVERWRITE         1
+
+
+/* prototypes */
+ConnectionClass *CC_Constructor(void);
+void       CC_conninfo_init(ConnInfo *conninfo);
+char       CC_Destructor(ConnectionClass *self);
+int            CC_cursor_count(ConnectionClass *self);
+char       CC_cleanup(ConnectionClass *self);
+char       CC_begin(ConnectionClass *self);
+char       CC_commit(ConnectionClass *self);
+char       CC_abort(ConnectionClass *self);
+int            CC_set_translation(ConnectionClass *self);
+char       CC_connect(ConnectionClass *self, char password_req, char *salt);
+char       CC_add_statement(ConnectionClass *self, StatementClass *stmt);
+char       CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
+char       CC_add_descriptor(ConnectionClass *self, DescriptorClass *desc);
+char       CC_remove_descriptor(ConnectionClass *self, DescriptorClass *desc);
+void       CC_set_error(ConnectionClass *self, int number, const char *message);
+void       CC_set_errormsg(ConnectionClass *self, const char *message);
+char       CC_get_error(ConnectionClass *self, int *number, char **message);
+QResultClass   *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag);
+void       CC_clear_error(ConnectionClass *self);
+char      *CC_create_errormsg(ConnectionClass *self);
+int        CC_send_function(ConnectionClass *conn, int fnid, void *result_buf, int *actual_result_len, int result_is_int, LO_ARG *argv, int nargs);
+char       CC_send_settings(ConnectionClass *self);
+void       CC_lookup_lo(ConnectionClass *conn);
+void       CC_lookup_pg_version(ConnectionClass *conn);
+void       CC_initialize_pg_version(ConnectionClass *conn);
+void       CC_log_error(const char *func, const char *desc, const ConnectionClass *self);
+int        CC_get_max_query_len(const ConnectionClass *self);
+int        CC_send_cancel_request(const ConnectionClass *conn);
+void       CC_on_commit(ConnectionClass *conn);
+void       CC_on_abort(ConnectionClass *conn, UDWORD opt);
+void       ProcessRollback(ConnectionClass *conn, BOOL undo);
+const char *CC_get_current_schema(ConnectionClass *conn);
+int        CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plannm);
+int        CC_discard_marked_plans(ConnectionClass *conn);
+
+/* Accessor functions*/
+PGconn         *LIBPQ_Constructor();
+void           LIBPQ_Destructor(PGconn *pgconn);
+int            LIBPQ_connect(ConnectionClass *self);
+QResultClass       *LIBPQ_execute_query(ConnectionClass *self,char *query);
+QResultClass       *CC_mapping(PGresult *pgres,QResultClass *qres);
+/* CC_send_query options */
+#define    CLEAR_RESULT_ON_ABORT   1L
+#define    CREATE_KEYSET       (1L << 1) /* create keyset for updatable curosrs */
+#define    GO_INTO_TRANSACTION (1L << 2) /* issue begin in advance */
+/* CC_on_abort options */
+#define    NO_TRANS        1L
+#define    CONN_DEAD       (1L << 1) /* connection is no longer valid */
+
+#endif /* __LIBPQCONNECTION_H__ */
+
+#endif /* USE_LIBPQ */
diff --git a/lobj.c b/lobj.c
index 6b55b82d54e5632edb1b3bcbb2c79728888cb23d..eef659ca2b442c8e83ba3e2ad1224f142c03c9ff 100644 (file)
--- a/lobj.c
+++ b/lobj.c
@@ -12,6 +12,8 @@
  *--------
  */
 
+#ifndef USE_LIBPQ
+
 #include "lobj.h"
 
 #include "connection.h"
@@ -184,3 +186,5 @@ lo_unlink(ConnectionClass *conn, Oid lobjId)
    else
        return retval;
 }
+
+#endif /* USE_LIBPQ */
diff --git a/lobj.h b/lobj.h
index 4d720488a018339c5432c131710d05e8302e5cc9..646274b653666d875892a9437ffeb7d42aa0cf3b 100644 (file)
--- a/lobj.h
+++ b/lobj.h
@@ -35,6 +35,8 @@ struct lo_arg
 #define INV_WRITE                  0x00020000
 #define INV_READ                   0x00040000
 
+#ifndef USE_LIBPQ
+
 Oid            lo_creat(ConnectionClass *conn, int mode);
 int            lo_open(ConnectionClass *conn, int lobjId, int mode);
 int            lo_close(ConnectionClass *conn, int fd);
@@ -44,4 +46,6 @@ int           lo_lseek(ConnectionClass *conn, int fd, int offset, int len);
 int            lo_tell(ConnectionClass *conn, int fd);
 int            lo_unlink(ConnectionClass *conn, Oid lobjId);
 
+#endif /*USE_LIBPQ */
+
 #endif
diff --git a/misc.c b/misc.c
index 4589f19bf5847d3d7cf101c3738990b2e57353cd..35d67567d7f4b95ba4dd905afe96afd68707fbba 100644 (file)
--- a/misc.c
+++ b/misc.c
 #include <process.h>           /* Byron: is this where Windows keeps def.
                                 * of getpid ? */
 #endif
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "multibyte.h"
 
 extern GLOBAL_VALUES globals;
@@ -325,7 +331,7 @@ make_lstring_ifneeded(ConnectionClass *conn, const char *s, int len, BOOL ifallu
                    str = NULL;
                }
                break;
-           } 
+           }
            if (tolower(*ptr) != *ptr)
            {
                if (!str)
index 2a47fd067505178fa99eaefdb2de8d5e6e4e5dcf..a7df17cbe72d3f44eba803cc9c5671259564388f 100644 (file)
@@ -9,7 +9,13 @@
  */
 
 #include "multibyte.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "pgapifunc.h"
 #include "qresult.h"
 #include <string.h>
@@ -194,11 +200,11 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code)
 /* EUC_JP Support */
        case EUC_JP:
            {
-               if (stat < 3 && 
+               if (stat < 3 &&
                    character == 0x8f)  /* JIS X 0212 */
                    stat = 3;
                else
-               if (stat != 2 && 
+               if (stat != 2 &&
                    (character == 0x8e ||
                    character > 0xa0))  /* Half Katakana HighByte & Kanji HighByte */
                    stat = 2;
@@ -280,7 +286,7 @@ pg_mbschr(int csc, const UCHAR *string, unsigned int character)
    int         mb_st = 0;
    const UCHAR *s, *rs = NULL;
 
-   for(s = string; *s ; s++) 
+   for(s = string; *s ; s++)
    {
        mb_st = pg_CS_stat(mb_st, (UCHAR) *s, csc);
        if (mb_st == 0 && (*s == character))
@@ -385,7 +391,7 @@ CC_lookup_characterset(ConnectionClass *self)
        if (stricmp(pg_CS_name(self->ccsc), encstr))
        {
            qlog(" Client encoding = '%s' and %s\n", self->client_encoding, pg_CS_name(self->ccsc));
-           CC_set_error(self, CONN_VALUE_OUT_OF_RANGE, "client encoding mismatch"); 
+           CC_set_error(self, CONN_VALUE_OUT_OF_RANGE, "client encoding mismatch");
        }
    }
    else
@@ -406,15 +412,15 @@ int encoded_nextchar(encoded_str *encstr)
 {
    int chr;
 
-   chr = encstr->encstr[++encstr->pos]; 
+   chr = encstr->encstr[++encstr->pos];
    encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
-   return chr; 
+   return chr;
 }
 int encoded_byte_check(encoded_str *encstr, int abspos)
 {
    int chr;
 
-   chr = encstr->encstr[encstr->pos = abspos]; 
+   chr = encstr->encstr[encstr->pos = abspos];
    encstr->ccst = pg_CS_stat(encstr->ccst, (unsigned int) chr, encstr->ccsc);
-   return chr; 
+   return chr;
 }
index d75048d026861c3d0caaf75d6daeec26c93117f0..025a4b43363554a5a688c9d934730bc04b5f8abc 100644 (file)
--- a/odbcapi.c
+++ b/odbcapi.c
 
 #include "pgapifunc.h"
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 #include "qresult.h"
 
@@ -124,7 +130,7 @@ SQLColumns(HSTMT StatementHandle,
        ret = PGAPI_Columns(StatementHandle, ctName, NameLength1,
                scName, NameLength2, tbName, NameLength3,
                clName, NameLength4, flag);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt = NULL, *newSc = NULL, *newTb = NULL, *newCl = NULL;
@@ -141,7 +147,7 @@ SQLColumns(HSTMT StatementHandle,
        {
            scName = newSc;
            reexec = TRUE;
-       }   
+       }
        if (newTb = make_lstring_ifneeded(conn, TableName, NameLength3, ifallupper))
        {
            tbName = newTb;
@@ -594,7 +600,7 @@ SQLSpecialColumns(HSTMT StatementHandle,
        ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
            NameLength1, scName, NameLength2, tbName, NameLength3,
                            Scope, Nullable);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt =NULL, *newSc = NULL, *newTb = NULL;
@@ -655,7 +661,7 @@ SQLStatistics(HSTMT StatementHandle,
        ret = PGAPI_Statistics(StatementHandle, ctName, NameLength1,
                 scName, NameLength2, tbName, NameLength3,
                 Unique, Reserved);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt =NULL, *newSc = NULL, *newTb = NULL;
@@ -689,7 +695,7 @@ SQLStatistics(HSTMT StatementHandle,
                free(newSc);
            if (newTb)
                free(newTb);
-       }   
+       }
    }
    LEAVE_STMT_CS(stmt);
    return ret;
@@ -716,7 +722,7 @@ SQLTables(HSTMT StatementHandle,
        ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
                scName, NameLength2, tbName, NameLength3,
                        TableType, NameLength4);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt =NULL, *newSc = NULL, *newTb = NULL;
@@ -783,7 +789,7 @@ SQLColumnPrivileges(
        ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
                scName, cbSchemaName, tbName, cbTableName,
                        clName, cbColumnName);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt = NULL, *newSc = NULL, *newTb = NULL, *newCl = NULL;
@@ -904,7 +910,7 @@ SQLForeignKeys(
            pkscName, cbPkSchemaName, pktbName, cbPkTableName,
            fkctName, cbFkCatalogName, fkscName, cbFkSchemaName,
            fktbName, cbFkTableName);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newPkct = NULL, *newPksc = NULL, *newPktb = NULL,
@@ -1059,7 +1065,7 @@ SQLPrimaryKeys(
    else
        ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
            scName, cbSchemaName, tbName, cbTableName);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt = NULL, *newSc = NULL, *newTb = NULL;
@@ -1125,7 +1131,7 @@ SQLProcedureColumns(
        ret = PGAPI_ProcedureColumns(hstmt, ctName, cbCatalogName,
                scName, cbSchemaName, prName, cbProcName,
                    clName, cbColumnName);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt = NULL, *newSc = NULL, *newPr = NULL, *newCl = NULL;
@@ -1196,7 +1202,7 @@ SQLProcedures(
    else
        ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
                     scName, cbSchemaName, prName, cbProcName);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt = NULL, *newSc = NULL, *newPr = NULL;
@@ -1277,7 +1283,7 @@ SQLTablePrivileges(
    else
        ret = PGAPI_TablePrivileges(hstmt, ctName, cbCatalogName,
            scName, cbSchemaName, tbName, cbTableName, 0);
-   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
+   if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt)))
    {
        BOOL    ifallupper = TRUE, reexec = FALSE;
        char *newCt = NULL, *newSc = NULL, *newTb = NULL;
index aceaf8ab8b8ba798f0888f586b6619f92c70e8b8..7029470282b4e36ea6dd0da5b528930f88b696e0 100644 (file)
 #include <string.h>
 
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 #include "pgapifunc.h"
 
@@ -456,7 +462,7 @@ SQLSetEnvAttr(HENV EnvironmentHandle,
                ret = SQL_SUCCESS;
            else
                ret = SQL_SUCCESS_WITH_INFO;
-   
+
            break;
        default:
            env->errornumber = CONN_INVALID_ARGUMENT_NO;
@@ -556,7 +562,7 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
    if (ci->drivers.lie)
        SQL_FUNC_ESET(pfExists, SQL_API_SQLBROWSECONNECT); /* 55 not implmented yet */
    if (ci->drivers.lie)
-       SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implemented yet */ 
+       SQL_FUNC_ESET(pfExists, SQL_API_SQLCOLUMNPRIVILEGES); /* 56 not implemented yet */
    SQL_FUNC_ESET(pfExists, SQL_API_SQLDATASOURCES);    /* 57 */
    if (ci->drivers.lie)
        SQL_FUNC_ESET(pfExists, SQL_API_SQLDESCRIBEPARAM); /* 58 not properly implemented */
@@ -572,7 +578,7 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
    SQL_FUNC_ESET(pfExists, SQL_API_SQLNUMPARAMS);      /* 63 */
    /* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */
    SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS);    /* 65 */
-   SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS);   /* 66 */ 
+   SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS);   /* 66 */
    SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES);     /* 67 */
    SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS);     /* 68 */
    /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); 69 deprecated */
@@ -631,5 +637,5 @@ SQLBulkOperations(HSTMT hstmt, SQLSMALLINT operation)
 #endif /* DRIVER_CURSOR_IMPLEMENT */
    LEAVE_STMT_CS(stmt);
    return ret;
-}  
+}
 
index 5388304fc0054f4197acac5de5cc0720f1f745f9..ac8c05aa60baceec0155bdb9d436d2a8ae2cafba 100644 (file)
 #include <string.h>
 
 #include "pgapifunc.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 
 
@@ -91,7 +97,7 @@ RETCODE SQL_API   SQLSetConnectAttrW(HDBC hdbc,
 /*      new function */
 RETCODE  SQL_API
 SQLSetDescFieldW(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber,
-               SQLSMALLINT FieldIdentifier, PTR Value, 
+               SQLSMALLINT FieldIdentifier, PTR Value,
                SQLINTEGER BufferLength)
 {
    RETCODE ret;
@@ -232,7 +238,7 @@ RETCODE SQL_API SQLColAttributeW(
    SQLUSMALLINT    iCol,
    SQLUSMALLINT    iField,
    SQLPOINTER      pCharAttr,
-   SQLSMALLINT     cbCharAttrMax,  
+   SQLSMALLINT     cbCharAttrMax,
    SQLSMALLINT  *pcbCharAttr,
    SQLPOINTER      pNumAttr)
 {
@@ -245,7 +251,7 @@ RETCODE SQL_API SQLColAttributeW(
    ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
    switch (iField)
-   { 
+   {
        case SQL_DESC_BASE_COLUMN_NAME:
        case SQL_DESC_BASE_TABLE_NAME:
        case SQL_DESC_CATALOG_NAME:
@@ -308,7 +314,7 @@ RETCODE SQL_API SQLGetDiagFieldW(
    mylog("[[SQLGetDiagFieldW]] Handle=(%u,%x) Rec=%d Id=%d\n", fHandleType,
            handle, iRecord, fDiagField);
    switch (fDiagField)
-   { 
+   {
        case SQL_DIAG_DYNAMIC_FUNCTION:
        case SQL_DIAG_CLASS_ORIGIN:
        case SQL_DIAG_CONNECTION_NAME:
index b4270ddc4a3ac9a3e83ee8612a673e4be0eb4343..29658d0f3f8139775d0aba114907e55d0a4f151f 100644 (file)
 #include <string.h>
 
 #include "pgapifunc.h"
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
 #include "statement.h"
 
 RETCODE  SQL_API SQLColumnsW(HSTMT StatementHandle,
@@ -36,7 +40,7 @@ RETCODE  SQL_API SQLColumnsW(HSTMT StatementHandle,
    UInt4   nmlen1, nmlen2, nmlen3, nmlen4;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLColumnsW]");
    conn = SC_get_conn(stmt);
@@ -70,7 +74,7 @@ RETCODE  SQL_API SQLConnectW(HDBC ConnectionHandle,
    char    *svName, *usName, *auth;
    UInt4   nmlen1, nmlen2, nmlen3;
    RETCODE ret;
-   
+
    mylog("[SQLConnectW]");
    ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    ((ConnectionClass *) ConnectionHandle)->unicode = 1;
@@ -202,7 +206,7 @@ RETCODE  SQL_API SQLDescribeColW(HSTMT StatementHandle,
            *NameLength = nmcount;
    }
    LEAVE_STMT_CS((StatementClass *) StatementHandle);
-   free(clName); 
+   free(clName);
    return ret;
 }
 
@@ -236,7 +240,7 @@ RETCODE  SQL_API SQLGetCursorNameW(HSTMT StatementHandle,
    crName = malloc(buflen);
    ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_GetCursorName(StatementHandle, crName, buflen, &clen);
-   if (ret == SQL_SUCCESS) 
+   if (ret == SQL_SUCCESS)
    {
        UInt4   nmcount = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
        if (nmcount > (UInt4) BufferLength)
@@ -329,7 +333,7 @@ RETCODE  SQL_API SQLSpecialColumnsW(HSTMT StatementHandle,
    StatementClass *stmt = (StatementClass *) StatementHandle;
    ConnectionClass *conn;
    BOOL lower_id;
-   
+
    mylog("[SQLSpecialColumnsW]");
    conn = SC_get_conn(stmt);
    lower_id = SC_is_lower_case(stmt, conn);
@@ -435,7 +439,7 @@ RETCODE SQL_API SQLColumnPrivilegesW(
    UInt4   nmlen1, nmlen2, nmlen3, nmlen4;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLColumnPrivilegesW]");
    conn = SC_get_conn(stmt);
@@ -480,7 +484,7 @@ RETCODE SQL_API SQLForeignKeysW(
    UInt4   nmlen1, nmlen2, nmlen3, nmlen4, nmlen5, nmlen6;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLForeignKeysW]");
    conn = SC_get_conn(stmt);
@@ -567,7 +571,7 @@ RETCODE SQL_API SQLPrimaryKeysW(
    UInt4   nmlen1, nmlen2, nmlen3;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLPrimaryKeysW]");
    conn = SC_get_conn(stmt);
@@ -604,7 +608,7 @@ RETCODE SQL_API SQLProcedureColumnsW(
    UInt4   nmlen1, nmlen2, nmlen3, nmlen4;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLProcedureColumnsW]");
    conn = SC_get_conn(stmt);
@@ -643,7 +647,7 @@ RETCODE SQL_API SQLProceduresW(
    UInt4   nmlen1, nmlen2, nmlen3;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLProceduresW]");
    conn = SC_get_conn(stmt);
@@ -678,7 +682,7 @@ RETCODE SQL_API SQLTablePrivilegesW(
    UInt4   nmlen1, nmlen2, nmlen3;
    StatementClass *stmt = (StatementClass *) hstmt;
    ConnectionClass *conn;
-   BOOL    lower_id; 
+   BOOL    lower_id;
 
    mylog("[SQLTablePrivilegesW]");
    conn = SC_get_conn(stmt);
index 7875c639f1f856b46f3794628d3509e7be175975..4679d9bf48b4470d07632db272816b8cd495ca89 100644 (file)
--- a/options.c
+++ b/options.c
 #include <string.h>
 
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 #include "qresult.h"
 #include "pgapifunc.h"
diff --git a/parse.c b/parse.c
index 452e7d0b90d2e51d7e1c021989dbf634d4985f5e..173dbcab4f2fc285a9fdaa2de3a9c27a8ca3c346 100644 (file)
--- a/parse.c
+++ b/parse.c
 #include <ctype.h>
 
 #include "statement.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "qresult.h"
 #include "pgtypes.h"
 #include "pgapifunc.h"
@@ -353,8 +359,6 @@ parse_statement(StatementClass *stmt)
    BOOL        updatable = TRUE;
 
    QResultClass*   resultClass;
-   HSTMT           privStmt;
-   
 
    mylog("%s: entering...\n", func);
 
index 5c07bdb9259b434b66a2011bb42816dc1b8af4bd..f4965c911060acdbdb6f988ca19944a1591b9cc7 100644 (file)
--- a/pgapi30.c
+++ b/pgapi30.c
 #include <string.h>
 
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "statement.h"
 #include "descriptor.h"
 #include "qresult.h"
@@ -68,7 +74,7 @@ PGAPI_GetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
 }
 
 /*
- * Minimal implementation. 
+ * Minimal implementation.
  *
  */
 RETCODE        SQL_API
@@ -102,15 +108,15 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                case SQL_DIAG_MESSAGE_TEXT:
                    ret = PGAPI_EnvError(Handle, RecNumber,
                                    NULL, NULL, DiagInfoPtr,
-                       BufferLength, StringLengthPtr, 0);  
+                       BufferLength, StringLengthPtr, 0);
                    break;
                case SQL_DIAG_NATIVE:
                    ret = PGAPI_EnvError(Handle, RecNumber,
                                    NULL, DiagInfoPtr, NULL,
-                       0, NULL, 0);  
-                   if (StringLengthPtr)  
-                       *StringLengthPtr = sizeof(SQLINTEGER);  
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                       0, NULL, 0);
+                   if (StringLengthPtr)
+                       *StringLengthPtr = sizeof(SQLINTEGER);
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_NUMBER:
@@ -130,9 +136,9 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                    ret = PGAPI_EnvError(Handle, RecNumber,
                                    DiagInfoPtr, NULL, NULL,
                        0, NULL, 0);
-                   if (StringLengthPtr)  
-                       *StringLengthPtr = 5;  
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                   if (StringLengthPtr)
+                       *StringLengthPtr = 5;
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_RETURNCODE: /* driver manager returns */
@@ -166,15 +172,15 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                case SQL_DIAG_MESSAGE_TEXT:
                    ret = PGAPI_ConnectError(Handle, RecNumber,
                                    NULL, NULL, DiagInfoPtr,
-                       BufferLength, StringLengthPtr, 0);  
+                       BufferLength, StringLengthPtr, 0);
                    break;
                case SQL_DIAG_NATIVE:
                    ret = PGAPI_ConnectError(Handle, RecNumber,
                                    NULL, DiagInfoPtr, NULL,
-                       0, NULL, 0);  
-                   if (StringLengthPtr)  
-                       *StringLengthPtr = sizeof(SQLINTEGER);  
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                       0, NULL, 0);
+                   if (StringLengthPtr)
+                       *StringLengthPtr = sizeof(SQLINTEGER);
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_NUMBER:
@@ -189,14 +195,14 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                            *StringLengthPtr = sizeof(SQLINTEGER);
                        ret = SQL_SUCCESS;
                    }
-                   break;  
+                   break;
                case SQL_DIAG_SQLSTATE:
                    ret = PGAPI_ConnectError(Handle, RecNumber,
                                    DiagInfoPtr, NULL, NULL,
                        0, NULL, 0);
-                   if (StringLengthPtr)  
-                       *StringLengthPtr = 5;  
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                   if (StringLengthPtr)
+                       *StringLengthPtr = 5;
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_RETURNCODE: /* driver manager returns */
@@ -230,15 +236,15 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                case SQL_DIAG_MESSAGE_TEXT:
                    ret = PGAPI_StmtError(Handle, RecNumber,
                                    NULL, NULL, DiagInfoPtr,
-                       BufferLength, StringLengthPtr, 0);  
+                       BufferLength, StringLengthPtr, 0);
                    break;
                case SQL_DIAG_NATIVE:
                    ret = PGAPI_StmtError(Handle, RecNumber,
                                    NULL, DiagInfoPtr, NULL,
-                       0, NULL, 0);  
-                   if (StringLengthPtr)  
-                       *StringLengthPtr = sizeof(SQLINTEGER);  
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                       0, NULL, 0);
+                   if (StringLengthPtr)
+                       *StringLengthPtr = sizeof(SQLINTEGER);
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_NUMBER:
@@ -265,9 +271,9 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                    ret = PGAPI_StmtError(Handle, RecNumber,
                                    DiagInfoPtr, NULL, NULL,
                        0, NULL, 0);
-                   if (StringLengthPtr)  
+                   if (StringLengthPtr)
                        *StringLengthPtr = 5;
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_CURSOR_ROW_COUNT:
@@ -279,7 +285,7 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
 
                        if (res && QR_NumResultCols(res) > 0 && !SC_is_fetchcursor(stmt))
                            rc = QR_get_num_total_tuples(res) - res->dl_count;
-                   } 
+                   }
                    *((SQLINTEGER *) DiagInfoPtr) = rc;
                    if (StringLengthPtr)
                        *StringLengthPtr = sizeof(SQLINTEGER);
@@ -309,7 +315,7 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
            }
            break;
        case SQL_HANDLE_DESC:
-           conn = DC_get_conn(((DescriptorClass *) Handle)); 
+           conn = DC_get_conn(((DescriptorClass *) Handle));
            switch (DiagIdentifier)
            {
                case SQL_DIAG_CLASS_ORIGIN:
@@ -333,9 +339,9 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                    ret = PGAPI_DescError(Handle, RecNumber,
                                    DiagInfoPtr, NULL, NULL,
                        0, NULL, 0);
-                   if (StringLengthPtr)  
+                   if (StringLengthPtr)
                        *StringLengthPtr = 5;
-                   if (SQL_SUCCESS_WITH_INFO == ret)  
+                   if (SQL_SUCCESS_WITH_INFO == ret)
                        ret = SQL_SUCCESS;
                    break;
                case SQL_DIAG_RETURNCODE: /* driver manager returns */
@@ -393,7 +399,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
 }
 
 static SQLHDESC
-descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType) 
+descHandleFromStatementHandle(HSTMT StatementHandle, SQLINTEGER descType)
 {
    StatementClass  *stmt = (StatementClass *) StatementHandle;
 
@@ -447,7 +453,7 @@ ARDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
    {
        case SQL_DESC_ARRAY_SIZE:
            opts->size_of_rowset = (SQLUINTEGER) Value;
-           return ret; 
+           return ret;
        case SQL_DESC_ARRAY_STATUS_PTR:
            opts->row_operation_ptr = Value;
            return ret;
@@ -485,7 +491,7 @@ ARDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
                tptr = bookmark->used;
                if (Value != tptr)
                {
-                   DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR"); 
+                   DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR");
                    ret = SQL_ERROR;
                }
                break;
@@ -538,7 +544,7 @@ ARDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            if (Value != tptr)
            {
                ret = SQL_ERROR;
-               DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR"); 
+               DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR");
            }
            break;
        case SQL_DESC_OCTET_LENGTH_PTR:
@@ -559,7 +565,7 @@ ARDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_NUM_PREC_RADIX:
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invalid descriptor identifier"); 
+               "invalid descriptor identifier");
    }
    return ret;
 }
@@ -622,7 +628,7 @@ APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
    {
        case SQL_DESC_ARRAY_SIZE:
            opts->paramset_size = (SQLUINTEGER) Value;
-           return ret; 
+           return ret;
        case SQL_DESC_ARRAY_STATUS_PTR:
            opts->param_operation_ptr = Value;
            return ret;
@@ -634,7 +640,7 @@ APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            return ret;
        case SQL_DESC_COUNT:
            parameter_bindings_set(opts, (SQLUINTEGER) Value, FALSE);
-           return ret; 
+           return ret;
 
        case SQL_DESC_TYPE:
        case SQL_DESC_DATETIME_INTERVAL_CODE:
@@ -648,7 +654,7 @@ APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
                "bad parameter number");
        return SQL_ERROR;
    }
-   para_idx = RecNumber - 1; 
+   para_idx = RecNumber - 1;
    switch (FieldIdentifier)
    {
        case SQL_DESC_TYPE:
@@ -687,7 +693,7 @@ APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            if (Value != opts->parameters[para_idx].used)
            {
                ret = SQL_ERROR;
-               DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR"); 
+               DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR");
            }
            break;
        case SQL_DESC_OCTET_LENGTH:
@@ -708,7 +714,7 @@ APDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_NUM_PREC_RADIX:
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invaid descriptor identifier"); 
+               "invaid descriptor identifier");
    }
    return ret;
 }
@@ -764,7 +770,7 @@ IRDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_UPDATABLE: /* read-only */
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invalid descriptor identifier"); 
+               "invalid descriptor identifier");
    }
    return ret;
 }
@@ -785,7 +791,7 @@ IPDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_ROWS_PROCESSED_PTR:
            ipdopts->param_processed_ptr = (UInt4 *) Value;
            return ret;
-       case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */ 
+       case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */
            if (SQL_UNNAMED !=  (SQLUINTEGER) Value)
            {
                ret = SQL_ERROR;
@@ -846,7 +852,7 @@ IPDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_SCALE:
            ipdopts->parameters[para_idx].decimal_digits = (Int2) ((Int4) Value);
            break;
-       case SQL_DESC_ALLOC_TYPE: /* read-only */ 
+       case SQL_DESC_ALLOC_TYPE: /* read-only */
        case SQL_DESC_CASE_SENSITIVE: /* read-only */
        case SQL_DESC_DATETIME_INTERVAL_PRECISION:
        case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
@@ -864,7 +870,7 @@ IPDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_UNSIGNED: /* read-only */
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invalid descriptor identifier"); 
+               "invalid descriptor identifier");
    }
    return ret;
 }
@@ -929,7 +935,7 @@ ARDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
    {
        case SQL_DESC_ARRAY_SIZE:
            ival = opts->size_of_rowset;
-           break; 
+           break;
        case SQL_DESC_ARRAY_STATUS_PTR:
            rettype = SQL_IS_POINTER;
            ptr = opts->row_operation_ptr;
@@ -1010,7 +1016,7 @@ ARDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_LENGTH:
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invalid descriptor identifier"); 
+               "invalid descriptor identifier");
    }
    switch (rettype)
    {
@@ -1024,7 +1030,7 @@ ARDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            *((void **) Value) = ptr;
            break;
    }
-           
+
    if (StringLength)
        *StringLength = len;
    return ret;
@@ -1049,13 +1055,13 @@ APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_BIND_OFFSET_PTR:
        case SQL_DESC_BIND_TYPE:
        case SQL_DESC_COUNT:
-           break; 
+           break;
        default:if (RecNumber <= 0 || RecNumber > opts->allocated)
            {
                DC_set_error(desc, STMT_BAD_PARAMETER_NUMBER_ERROR,
                    "bad parameter number");
                return SQL_ERROR;
-           } 
+           }
    }
    para_idx = RecNumber - 1;
    switch (FieldIdentifier)
@@ -1063,7 +1069,7 @@ APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_ARRAY_SIZE:
            rettype = SQL_IS_POINTER;
            ival = opts->paramset_size;
-           break; 
+           break;
        case SQL_DESC_ARRAY_STATUS_PTR:
            rettype = SQL_IS_POINTER;
            ptr = opts->param_operation_ptr;
@@ -1125,7 +1131,7 @@ APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            break;
        case SQL_DESC_COUNT:
            ival = opts->allocated;
-           break; 
+           break;
        case SQL_DESC_ALLOC_TYPE: /* read-only */
            if (desc->embedded)
                ival = SQL_DESC_ALLOC_AUTO;
@@ -1145,7 +1151,7 @@ APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_LENGTH:
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-                   "invalid descriptor identifer"); 
+                   "invalid descriptor identifer");
    }
    switch (rettype)
    {
@@ -1159,7 +1165,7 @@ APDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            *((void **) Value) = ptr;
            break;
    }
-           
+
    if (StringLength)
        *StringLength = len;
    return ret;
@@ -1226,10 +1232,10 @@ IRDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_TYPE_NAME: /* read-only */
            rettype = SQL_NTS;
            bCallColAtt = TRUE;
-           break; 
+           break;
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invalid descriptor identifier"); 
+               "invalid descriptor identifier");
    }
    if (bCallColAtt)
    {
@@ -1241,7 +1247,7 @@ IRDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            FieldIdentifier, Value, (SQLSMALLINT) BufferLength,
                &pcbL, &ival);
        len = pcbL;
-   } 
+   }
    switch (rettype)
    {
        case 0:
@@ -1258,7 +1264,7 @@ IRDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            *((void **) Value) = ptr;
            break;
    }
-           
+
    if (StringLength)
        *StringLength = len;
    return ret;
@@ -1280,7 +1286,7 @@ IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_ARRAY_STATUS_PTR:
        case SQL_DESC_ROWS_PROCESSED_PTR:
        case SQL_DESC_COUNT:
-           break; 
+           break;
        default:if (RecNumber <= 0 || RecNumber > ipdopts->allocated)
            {
                DC_set_error(desc, STMT_BAD_PARAMETER_NUMBER_ERROR,
@@ -1334,7 +1340,7 @@ IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            break;
        case SQL_DESC_COUNT:
            ival = ipdopts->allocated;
-           break; 
+           break;
        case SQL_DESC_PARAMETER_TYPE:
            ival = ipdopts->parameters[para_idx].paramType;
            break;
@@ -1359,7 +1365,7 @@ IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            break;
        case SQL_DESC_ALLOC_TYPE: /* read-only */
            ival = SQL_DESC_ALLOC_AUTO;
-           break; 
+           break;
        case SQL_DESC_CASE_SENSITIVE: /* read-only */
        case SQL_DESC_DATETIME_INTERVAL_PRECISION:
        case SQL_DESC_FIXED_PREC_SCALE: /* read-only */
@@ -1376,7 +1382,7 @@ IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
        case SQL_DESC_UNSIGNED: /* read-only */
        default:ret = SQL_ERROR;
            DC_set_error(desc, STMT_INVALID_DESCRIPTOR_IDENTIFIER,
-               "invalid descriptor identifier"); 
+               "invalid descriptor identifier");
    }
    switch (rettype)
    {
@@ -1390,7 +1396,7 @@ IPDGetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            *((void **)Value) = ptr;
            break;
    }
-           
+
    if (StringLength)
        *StringLength = len;
    return ret;
@@ -1463,7 +1469,7 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
        case SQL_ATTR_IMP_ROW_DESC:     /* 10012 */
        case SQL_ATTR_IMP_PARAM_DESC:   /* 10013 */
            len = 4;
-           *((HSTMT *) Value) = descHandleFromStatementHandle(StatementHandle, Attribute); 
+           *((HSTMT *) Value) = descHandleFromStatementHandle(StatementHandle, Attribute);
            break;
 
        case SQL_ATTR_CURSOR_SCROLLABLE:        /* -1 */
@@ -1577,7 +1583,7 @@ PGAPI_GetDescField(SQLHDESC DescriptorHandle,
                    DC_set_errormsg(desc, "can't SQLGetDescField for this parameter number");
                    break;
            }
-       } 
+       }
        DC_log_error(func, "", desc);
    }
    return ret;
@@ -1627,7 +1633,7 @@ PGAPI_SetDescField(SQLHDESC DescriptorHandle,
                    break;
                break;
            }
-       } 
+       }
        DC_log_error(func, "", desc);
    }
    return ret;
@@ -1665,7 +1671,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
            return SQL_ERROR;
 
        case SQL_ATTR_METADATA_ID:      /* 10014 */
-           stmt->options.metadata_id = (SQLUINTEGER) Value; 
+           stmt->options.metadata_id = (SQLUINTEGER) Value;
            break;
        case SQL_ATTR_APP_ROW_DESC:     /* 10010 */
            if (SQL_NULL_HDESC == Value)
@@ -1673,7 +1679,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
                stmt->ard = &(stmt->ardi);
            }
            else
-           { 
+           {
                stmt->ard = (ARDClass *) Value;
            }
            break;
@@ -1683,7 +1689,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
                stmt->apd = &(stmt->apdi);
            }
            else
-           { 
+           {
                stmt->apd = (APDClass *) Value;
            }
            break;
@@ -1732,7 +1738,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
 #ifdef DRIVER_CURSOR_IMPLEMENT
 #define    CALC_BOOKMARK_ADDR(book, offset, bind_size, index) \
    (book->buffer + offset + \
-   (bind_size > 0 ? bind_size : (SQL_C_VARBOOKMARK == book->returntype ? book->buflen : sizeof(UInt4))) * index)       
+   (bind_size > 0 ? bind_size : (SQL_C_VARBOOKMARK == book->returntype ? book->buflen : sizeof(UInt4))) * index)
 
 /* SQL_NEED_DATA callback for PGAPI_BulkOperations */
 typedef struct
@@ -1745,7 +1751,7 @@ typedef struct
    int     idx, processed;
 }  bop_cdata;
 
-static 
+static
 RETCODE    bulk_ope_callback(RETCODE retcode, void *para)
 {
    RETCODE ret = retcode;
@@ -1829,7 +1835,7 @@ PGAPI_BulkOperations(HSTMT hstmt, SQLSMALLINT operationX)
    s.operation = operationX;
    SC_clear_error(s.stmt);
    s.opts = SC_get_ARDF(s.stmt);
-   
+
    s.auto_commit_needed = FALSE;
    if (SQL_FETCH_BY_BOOKMARK != s.operation)
    {
@@ -1849,6 +1855,6 @@ PGAPI_BulkOperations(HSTMT hstmt, SQLSMALLINT operationX)
    s.need_data_callback = FALSE;
    ret = bulk_ope_callback(SQL_SUCCESS, &s);
    return ret;
-}  
+}
 #endif /* DRIVER_CURSOR_IMPLEMENT */
 
index ac9641d5dad15137d867afc012a9643d75047146..aa8dadfd1720bd5db8bd819b45ccb819e28dd534 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
 
 #include "dlg_specific.h"
 #include "statement.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
+
 #include "environ.h"
 #include "qresult.h"
 
index b019e37af244de33244bb1f8e8624c3266512df2..1343270891333f358f87634db0329d01f20d4d4c 100644 (file)
@@ -87,14 +87,16 @@ HINSTANCE NEAR s_hModule;       /* Saved module handle. */
 BOOL       WINAPI
 DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
 {
+#ifndef USE_LIBPQ
    WORD        wVersionRequested;
    WSADATA     wsaData;
+#endif /* USE_LIBPQ */
 
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            s_hModule = hInst;  /* Save for dialog boxes */
-
+#ifndef USE_LIBPQ
            /* Load the WinSock Library */
            wVersionRequested = MAKEWORD(1, 1);
 
@@ -108,7 +110,7 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
                WSACleanup();
                return FALSE;
            }
-
+#endif /* USE_LIBPQ */
            initialize_global_cs();
            getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
            break;
@@ -118,7 +120,9 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
 
        case DLL_PROCESS_DETACH:
            finalize_global_cs();
+#ifndef USE_LIBPQ
            WSACleanup();
+#endif /* USE_LIBPQ*/
            return TRUE;
 
        case DLL_THREAD_DETACH:
index 2c57dbe02fd666c1db8cf0f75e71126af71c9af9..83ad5fea1c94ea73a1a089188b67196393a56214 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.88 2005/02/14 13:07:11 dpage Exp $
+ * $Id: psqlodbc.h,v 1.89 2005/07/13 14:23:35 dpage Exp $
  *
  */
 
@@ -90,9 +90,9 @@ typedef double SDOUBLE;
 
 #endif
 
-
+#ifndef USE_LIBPQ
 typedef UInt4 Oid;
-
+#endif /* USE_LIBPQ */
 
 #ifndef FALSE
 #define FALSE  (BOOL)0
index f584b3fd4807c7202c80b809c046dd07e5acf7dd..f26ad35e18fc127c91438b33cd11f41a0e260025 100644 (file)
@@ -30,7 +30,11 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
 DLG_CONFIG DIALOGEX 65, 43, 359, 219
 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | 
     WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+#ifdef USE_LIBPQ
+CAPTION "PostgreSQL ODBC (libpq) \83Z\83b\83g\83A\83b\83v"
+#else
 CAPTION "PostgreSQL ODBC \83Z\83b\83g\83A\83b\83v"
+#endif
 FONT 9, "\82l\82\83S\83V\83b\83N", 0, 0, 0x1
 BEGIN
     RTEXT           "\83f\81|\83^\83\\81|\83X\96¼:(&N)",IDC_DSNAMETEXT,2,9,63,17,NOT 
@@ -295,8 +299,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 8,0,1,2
- PRODUCTVERSION 8,0,1,2
+ FILEVERSION 8,1,0,1
+ PRODUCTVERSION 8,1,0,1
  FILEFLAGSMASK 0x3L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -311,15 +315,19 @@ BEGIN
     BEGIN
         BLOCK "040904e4"
         BEGIN
+#ifdef USE_LIBPQ
+            VALUE "Comments", "PostgreSQL ODBC driver (libpq based)"
+#else
             VALUE "Comments", "PostgreSQL ODBC driver"
+#endif
             VALUE "CompanyName", "PostgreSQL Global Development Group"
             VALUE "FileDescription", "PostgreSQL Driver"
-            VALUE "FileVersion", "08.00.0102"
+            VALUE "FileVersion", "08.01.0001"
             VALUE "InternalName", "psqlodbc"
             VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation.  Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation."
             VALUE "OriginalFilename", "psqlodbc.dll"
             VALUE "ProductName", "Microsoft Open Database Connectivity"
-            VALUE "ProductVersion", "08.00.0102"
+            VALUE "ProductVersion", "08.01.0001"
         END
     END
     BLOCK "VarFileInfo"
@@ -368,7 +376,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 DLG_CONFIG DIALOGEX 65, 43, 305, 130
 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | 
     WS_VISIBLE | WS_CAPTION | WS_SYSMENU
-CAPTION "PostgreSQL ODBC Driver (psqlODBC) Setup"
+#ifdef USE_LIBPQ
+CAPTION "PostgreSQL ODBC Driver (libpq) Setup"
+#else
+CAPTION "PostgreSQL ODBC Driver Setup"
+#endif
 FONT 10, "Terminal", 0, 0, 0x0
 BEGIN
     RTEXT           "&Data Source",IDC_DSNAMETEXT,5,25,50,12,NOT WS_GROUP
@@ -594,8 +606,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 8,0,1,2
- PRODUCTVERSION 8,0,1,2
+ FILEVERSION 8,1,0,1
+ PRODUCTVERSION 8,1,0,1
  FILEFLAGSMASK 0x3L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -610,15 +622,19 @@ BEGIN
     BEGIN
         BLOCK "040904e4"
         BEGIN
+#ifdef USE_LIBPQ
+            VALUE "Comments", "PostgreSQL ODBC driver (libpq based)"
+#else
             VALUE "Comments", "PostgreSQL ODBC driver"
+#endif
             VALUE "CompanyName", "PostgreSQL Global Development Group"
             VALUE "FileDescription", "PostgreSQL Driver"
-            VALUE "FileVersion", "08.00.0102"
+            VALUE "FileVersion", "08.01.0001"
             VALUE "InternalName", "psqlodbc"
             VALUE "LegalTrademarks", "ODBC(TM) is a trademark of Microsoft Corporation.  Microsoft® is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation."
             VALUE "OriginalFilename", "psqlodbc.dll"
             VALUE "ProductName", "Microsoft Open Database Connectivity"
-            VALUE "ProductVersion", "08.00.0102"
+            VALUE "ProductVersion", "08.01.0001"
         END
     END
     BLOCK "VarFileInfo"
index 72005bf4e6540a19e68fb7c472ecbcdb6bebbd75..254769195ecc17f0e7715fbadcea967b96bb48ee 100644 (file)
--- a/qresult.c
+++ b/qresult.c
@@ -161,7 +161,12 @@ QR_Destructor(QResultClass *self)
     * If conn is defined, then we may have used "backend_tuples", so in
     * case we need to, free it up.  Also, close the cursor.
     */
+#ifdef USE_LIBPQ
+   self->backend_tuples = NULL;
+   if (conn && conn->pgconn && CC_is_in_trans(conn))
+#else
    if (conn && conn->sock && CC_is_in_trans(conn))
+#endif /* USE_LIBPQ */
    {
        if (!QR_close(self))    /* close the cursor if there is one */
        {
@@ -284,7 +289,11 @@ QR_free_memory(QResultClass *self)
        free(self->keyset);
        self->keyset = NULL;
        self->count_keyset_allocated = 0;
+#ifdef USE_LIBPQ
+       if (self->reload_count > 0 && conn && conn->pgconn)
+#else
        if (self->reload_count > 0 && conn && conn->sock)
+#endif /* USE_LIBPQ */
        {
            char    plannm[32];
 
@@ -357,7 +366,9 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
        {
            if (!cursor || cursor[0] == '\0')
            {
+#ifndef USE_LIBPQ
                self->status = PGRES_INTERNAL_ERROR;
+#endif /* USE_LIBPQ*/
                QR_set_message(self, "Internal Error -- no cursor for fetch");
                return FALSE;
            }
@@ -371,7 +382,9 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
         */
        if (CI_read_fields(self->fields, self->conn))
        {
+#ifndef USE_LIBPQ
            self->status = PGRES_FIELDS_OK;
+#endif /* USE_LIBPQ*/
            self->num_fields = CI_get_num_fields(self->fields);
            if (self->haskeyset)
                self->num_fields -= 2;
@@ -425,8 +438,11 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
        self->num_backend_rows = tuple_size + 1;
        self->fetch_count = tuple_size + 1;
        self->base = 0;
-
+#ifdef USE_LIBPQ
+       return TRUE;
+#else
        return QR_next_tuple(self);
+#endif /* USE_LIBPQ */
    }
    else
    {
@@ -503,6 +519,305 @@ QR_close(QResultClass *self)
 
 
 /* This function is called by fetch_tuples() AND SQLFetch() */
+
+#ifdef USE_LIBPQ
+
+int
+QR_next_tuple(QResultClass *self)
+{
+   int         id;
+   QResultClass *res;
+   ConnectionClass *conn;
+
+   /* Speed up access */
+   int         fetch_count = self->fetch_count;
+   int         num_backend_rows = self->num_backend_rows;
+   int         fetch_size,
+               offset = 0;
+   int         end_tuple = self->rowset_size + self->base;
+   char        corrected = FALSE;
+   TupleField *the_tuples = self->backend_tuples;
+
+   char        fetch[128];
+   QueryInfo   qi;
+   ConnInfo   *ci = NULL;
+   if (fetch_count < fetch_count)
+   {
+       /* return a row from cache */
+       mylog("next_tuple: fetch_count < fcount: returning tuple %d, fcount = %d\n", fetch_count, num_backend_rows);
+       self->tupleField = the_tuples + (fetch_count * self->num_fields);       /* next row */
+       self->fetch_count++;
+       return TRUE;
+   }
+   else if (self->num_backend_rows < self->cache_size)
+   {
+       /* last row from cache */
+       /* We are done because we didn't even get CACHE_SIZE tuples */
+       mylog("next_tuple: fcount < CACHE_SIZE: fcount = %d, fetch_count = %d\n", num_backend_rows, fetch_count);
+       self->tupleField = NULL;
+       /* self->status = PGRES_END_TUPLES;*/
+       /* end of tuples */
+       return -1;
+   }
+   else
+   {
+       /*
+        * See if we need to fetch another group of rows. We may be being
+        * called from send_query(), and if so, don't send another fetch,
+        * just fall through and read the tuples.
+        */
+       self->tupleField = NULL;
+       if (!self->inTuples)
+       {
+           ci = &(self->conn->connInfo);
+           if (!self->cursor || !ci->drivers.use_declarefetch)
+           {
+               mylog("next_tuple: ALL_ROWS: done, fcount = %d, fetch_count = %d\n", self->num_total_rows, fetch_count);
+               self->tupleField = NULL;
+               /* self->status = PGRES_END_TUPLES;*/
+               return -1;      /* end of tuples */
+           }
+
+           if (self->base == num_backend_rows)
+           {
+               int row, lf;
+               TupleField *tuple = self->backend_tuples;
+
+               /* not a correction */
+               /* Determine the optimum cache size.  */
+               if (ci->drivers.fetch_max % self->rowset_size == 0)
+                   fetch_size = ci->drivers.fetch_max;
+               else if (self->rowset_size < ci->drivers.fetch_max)
+                   fetch_size = (ci->drivers.fetch_max / self->rowset_size) * self->rowset_size;
+               else
+                   fetch_size = self->rowset_size;
+
+               self->cache_size = fetch_size;
+               /* clear obsolete tuples */
+inolog("clear obsolete %d tuples\n", num_backend_rows);
+               for (row = 0; row < num_backend_rows; row++)
+               {
+                   for (lf = 0; lf < self->num_fields; lf++)
+                   {
+                       if (tuple[lf].value != NULL)
+                       {
+                           free(tuple[lf].value);
+                           tuple[lf].value = NULL;
+                       }
+                   }
+                   tuple += self->num_fields;
+               }
+               self->fetch_count = 1;
+           }
+           else
+           {
+               /* need to correct */
+               corrected = TRUE;
+
+               fetch_size = end_tuple - num_backend_rows;
+
+               self->cache_size += fetch_size;
+
+               offset = self->fetch_count;
+               self->fetch_count++;
+           }
+
+           if (!self->backend_tuples || self->cache_size > self->count_backend_allocated)
+           {
+               self->count_backend_allocated = 0;
+               if (self->num_fields > 0)
+               {
+                   QR_REALLOC_return_with_error(self->backend_tuples, TupleField,
+                       (self->num_fields * sizeof(TupleField) * self->cache_size),
+                       self, "Out of memory while reading tuples.", FALSE)
+                   self->count_backend_allocated = self->cache_size;
+               }
+           }
+           if (self->haskeyset && (!self->keyset || self->cache_size > self->count_keyset_allocated))
+           {
+               self->count_keyset_allocated = 0;
+               QR_REALLOC_return_with_error(self->keyset, KeySet,
+                   (sizeof(KeySet) * self->cache_size),
+                   self, "Out of memory while reading tuples.", FALSE)
+               self->count_keyset_allocated = self->cache_size;
+           }
+           sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
+
+           mylog("next_tuple: sending actual fetch (%d) query '%s'\n", fetch_size, fetch);
+
+           /* don't read ahead for the next tuple (self) ! */
+           qi.row_size = self->cache_size;
+           qi.result_in = self;
+           qi.cursor = NULL;
+           res = CC_send_query(self->conn, fetch, &qi, CLEAR_RESULT_ON_ABORT);
+           if (res == NULL)
+           {
+               self->status = PGRES_FATAL_ERROR;
+               QR_set_message(self, "Error fetching next group.");
+               return FALSE;
+           }
+           self->inTuples = TRUE;
+       }
+       else
+       {
+           mylog("next_tuple: inTuples = true, falling through: fcount = %d, fetch_count = %d\n", self->num_backend_rows, self->fetch_count);
+
+           /*
+            * This is a pre-fetch (fetching rows right after query but
+            * before any real SQLFetch() calls.  This is done so the
+            * field attributes are available.
+            */
+           self->fetch_count = 0;
+       }
+   }
+   if (!corrected)
+   {
+       self->base = 0;
+       self->num_backend_rows = 0;
+   }
+
+   conn = self->conn;
+   self->tupleField = NULL;
+   ci = &(self->conn->connInfo);
+
+   for (;;)
+   {
+       if (!self->cursor || !ci->drivers.use_declarefetch)
+       {
+           if (self->num_fields > 0 &&
+           self->num_total_rows >= self->count_backend_allocated)
+           {
+               int tuple_size = self->count_backend_allocated;
+               mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
+               tuple_size *= 2;
+               QR_REALLOC_return_with_error(self->backend_tuples, TupleField,
+                       (tuple_size * self->num_fields * sizeof(TupleField)),
+                           self, "Out of memory while reading tuples.", FALSE)
+               self->count_backend_allocated = tuple_size;
+           }
+           if (self->haskeyset && self->num_total_rows >= self->count_keyset_allocated)
+           {
+               int tuple_size = self->count_keyset_allocated;
+               tuple_size *= 2;
+               QR_REALLOC_return_with_error(self->keyset, KeySet,
+                           (sizeof(KeySet) * tuple_size),
+                           self, "Out of memory while reading tuples.", FALSE)
+               self->count_keyset_allocated = tuple_size;
+           }
+       }
+       id = 67;
+       if (!QR_read_tuple(self, (char) (id==0)))
+       {
+           self->status = PGRES_BAD_RESPONSE;
+           QR_set_message(self, "Error reading the tuple");
+           return FALSE;
+       }
+       self->num_total_rows++;
+       if (self->num_fields > 0)
+           self->num_backend_rows++;
+       if (self->num_backend_rows > 0)
+       {
+       /* set to first row */
+           self->tupleField = self->backend_tuples + (offset * self->num_fields);
+           return TRUE;
+       }
+       else
+       {
+       /* We are surely done here (we read 0 tuples) */
+           mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
+           return -1;  /* end of tuples */
+       }
+          /* continue reading */
+   }
+
+   mylog("end of tuple list -- setting inUse to false: this = %u\n", self);
+
+   return TRUE;
+}
+
+
+char
+QR_read_tuple(QResultClass *self, char binary)
+{
+   Int2        field_lf;
+   TupleField *this_tuplefield;
+   KeySet  *this_keyset = NULL;
+   Int2        bitmaplen;      /* len of the bitmap in bytes */
+   Int4        len;
+   char       *buffer;
+   int     ci_num_fields = QR_NumResultCols(self); /* speed up access */
+   int     num_fields = self->num_fields;  /* speed up access */
+   ConnectionClass *conn = self->conn;
+   ColumnInfoClass *flds;
+   int     effective_cols;
+   char        tidoidbuf[32];
+
+   /* set the current row to read the fields into */
+   effective_cols = QR_NumPublicResultCols(self);
+   this_tuplefield = self->backend_tuples + (self->num_backend_rows * num_fields);
+   if (self->haskeyset)
+   {
+       this_keyset = self->keyset + self->num_total_rows;
+       this_keyset->status = 0;
+   }
+
+   bitmaplen = (Int2) ci_num_fields / BYTELEN;
+   if ((ci_num_fields % BYTELEN) > 0)
+       bitmaplen++;
+
+   /*
+    * At first the server sends a bitmap that indicates which database
+    * fields are null
+    */
+   flds = self->fields;
+   for (field_lf = 0; field_lf < ci_num_fields; field_lf++)
+   {
+       /*
+        * NO, the field is not null. so get at first the length of
+        * the field (four bytes)
+        */
+       if (!binary)
+           len -= VARHDRSZ;
+
+       if (field_lf >= effective_cols)
+           buffer = tidoidbuf;
+       else
+           QR_MALLOC_return_with_error(buffer, char,
+               (len + 1), self,
+               PGRES_FATAL_ERROR,
+               "Couldn't allocate buffer",
+               FALSE);
+       if (field_lf >= effective_cols)
+       {
+           if (field_lf == effective_cols)
+               sscanf(buffer, "(%lu,%hu)",
+                   &this_keyset->blocknum, &this_keyset->offset);
+           else
+               this_keyset->oid = strtoul(buffer, NULL, 10);
+       }
+       else
+       {
+           this_tuplefield[field_lf].len = len;
+           this_tuplefield[field_lf].value = buffer;
+       /*
+        * This can be used to set the longest length of the column
+        * for any row in the tuple cache.  It would not be accurate
+        * for varchar and text fields to use this since a tuple cache
+        * is only 100 rows. Bpchar can be handled since the strlen of
+        * all rows is fixed, assuming there are not 100 nulls in a
+        * row!
+        */
+           if (flds && flds->display_size && flds->display_size[field_lf] < len)
+               flds->display_size[field_lf] = len;
+       }
+   }
+
+   self->currTuple++;
+   return TRUE;
+}
+
+#else
+
 int
 QR_next_tuple(QResultClass *self)
 {
@@ -940,3 +1255,6 @@ QR_read_tuple(QResultClass *self, char binary)
    self->currTuple++;
    return TRUE;
 }
+
+
+#endif /* USE_LIBPQ */
index 0a1a55f5d774b12126fe67b21d397aa5708f06f2..ece650c4339518451c6a1cf8f5f0163a1d8076d8 100644 (file)
--- a/qresult.h
+++ b/qresult.h
 
 #include "psqlodbc.h"
 
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
 #include "socket.h"
+#endif /* USE_LIBPQ */
+
 #include "columninfo.h"
 #include "tuplelist.h"
 #include "tuple.h"
 
+#ifndef USE_LIBPQ
 enum QueryResultCode_
 {
    PGRES_EMPTY_QUERY = 0,
@@ -37,7 +43,7 @@ enum QueryResultCode_
    PGRES_INTERNAL_ERROR
 };
 typedef enum QueryResultCode_ QueryResultCode;
-
+#endif /*USE _LIBPQ */
 
 struct QResultClass_
 {
@@ -61,7 +67,11 @@ struct QResultClass_
    int         rowset_size;
    Int4            recent_processed_row_count;
 
+#ifdef USE_LIBPQ
+   ExecStatusType status;
+#else
    QueryResultCode status;
+#endif /* USE_LIBPQ*/
 
    char       *message;
    char       *cursor;         /* The name of the cursor for select
@@ -78,21 +88,28 @@ struct QResultClass_
    char        haskeyset;  /* this result contains keyset ? */
    KeySet      *keyset;
    UInt4       reload_count;
-   UInt2       rb_alloc;   /* count of allocated rollback info */  
-   UInt2       rb_count;   /* count of rollback info */    
-   Rollback    *rollback;  
-   UInt2       dl_alloc;   /* count of allocated deleted info */   
-   UInt2       dl_count;   /* count of deleted info */ 
-   UInt4       *deleted;   
+   UInt2       rb_alloc;   /* count of allocated rollback info */
+   UInt2       rb_count;   /* count of rollback info */
+   Rollback    *rollback;
+   UInt2       dl_alloc;   /* count of allocated deleted info */
+   UInt2       dl_count;   /* count of deleted info */
+   UInt4       *deleted;
 };
 
 #define QR_get_fields(self)                    (self->fields)
 
 
 /* These functions are for retrieving data from the qresult */
+#ifdef USE_LIBPQ
+/* Retrieve results from manual_tuples since it has the results */
+#define QR_get_value_manual(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno))
+#define QR_get_value_backend(self,fieldno)         (TL_get_fieldval(self->manual_tuples,self->currTuple, fieldno))
+#define QR_get_value_backend_row(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno))
+#else
 #define QR_get_value_manual(self, tupleno, fieldno) (TL_get_fieldval(self->manual_tuples, tupleno, fieldno))
 #define QR_get_value_backend(self, fieldno)            (self->tupleField[fieldno].value)
 #define QR_get_value_backend_row(self, tupleno, fieldno) ((self->backend_tuples + (tupleno * self->num_fields))[fieldno].value)
+#endif /* USE_LIBPQ */
 
 /* These functions are used by both manual and backend results */
 #define QR_NumResultCols(self)     (CI_get_num_fields(self->fields))
index 33a2eb12271aeb5d972da666e005af24e912f2b8..121138c62bc8ef4361084aeb77c868761b57b716 100644 (file)
@@ -52,10 +52,23 @@ Command Line Method
 
 3. Use NMAKE to build the dll eg:
 
-      C:\psqlodbc\> nmake /f win32.mak CFG=Release ALL
-
-      Possible configurations are Release and Debug.
-      Possible build types are ALL or CLEAN.
+      a. Using Libpq Interface (Default):
+            C:\psqlodbc\> nmake /f win32.mak CFG=Release ALL PG_INC="c:\postgresql\include"
+       or
+            C:\psqlodbc\> nmake /f win32.mak CFG=Release ALL MODE=USE_LIBPQ PG_INC="c:\postgresql\include"
+
+       Possible configurations are Release and Debug.
+            Possible build types are ALL or CLEAN.
+            PG_INC must contain the include folder name of PostgreSQL installation.
+
+      b. Using Socket:
+            C:\psqlodbc\> nmake /f win32.mak CFG=Release ALL MODE=USE_SOCK
+
+       Possible configurations are Release and Debug.
+            Possible build types are ALL or CLEAN.
+      
+      c. For cleaning up intermediate files:
+       C:\psqlodbc\> nmake /f win32.mak CFG=Release CLEAN MODE=USE_SOCK
 
 II.  Using Large Objects for handling LongVarBinary (OLE Objects in Access)
 
index ac1b52df4275ae30c94b720bf483817a21d5fa3b..e13ee6e78d297b029a91e9d4a64627c75a103e54 100644 (file)
--- a/results.c
+++ b/results.c
 #include <string.h>
 #include "dlg_specific.h"
 #include "environ.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
 #include "statement.h"
 #include "bind.h"
 #include "qresult.h"
@@ -1293,13 +1298,13 @@ PGAPI_ExtendedFetch(
                    EXTFETCH_RETURN_BOF(stmt, res)
                }
 #else
-               if (stmt->rowset_start < opts->rowset_size)
+               if (stmt->rowset_start < opts->size_of_rowset)
                {
                    SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior and before the beggining");
                    stmt->rowset_start = 0;
                }
                else
-                   stmt->rowset_start -= opts->rowset_size;
+                   stmt->rowset_start -= opts->size_of_rowset;
 #endif /* DRIVER_CURSOR_IMPLEMENT */
            }
            break;
@@ -1414,7 +1419,9 @@ PGAPI_ExtendedFetch(
     */
    if (SC_is_fetchcursor(stmt) && !stmt->manual_result)
    {
+#ifndef USE_LIBPQ
        if (QR_end_tuples(res))
+#endif /* USE_LIBPQ */
            return SQL_NO_DATA_FOUND;
    }
    else
diff --git a/setup.c b/setup.c
index 2ed8d0a060a6d6030304da368a416f0a15f71984..69dcff8d23ae398d11cace85de467fe82c792e3c 100644 (file)
--- a/setup.c
+++ b/setup.c
 
 #include  "psqlodbc.h"
 
+#ifdef USE_LIBPQ
+#include  "libpqconnection.h"
+#else
 #include  "connection.h"
+#endif /* USE_LIBPQ */
+
 #include  <windowsx.h>
 #include  <string.h>
 #include  <stdlib.h>
index a486228ba401627e0d1a6d7fabb692db7d3c46ca..f43db1c8adca4922e355f206dc2df623ec10c74d 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -12,6 +12,8 @@
  *-------
  */
 
+#ifndef USE_LIBPQ
+
 #include "socket.h"
 
 #include "connection.h"
@@ -116,7 +118,7 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname
        )
 {
 #if defined (POSIX_MULTITHREAD_SUPPORT)
-   const int bufsz = 8192; 
+   const int bufsz = 8192;
    char buf[bufsz];
    int error = 0;
    struct hostent host;
@@ -128,7 +130,7 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname
 #ifdef HAVE_UNIX_SOCKETS
    struct sockaddr_un *un;
 #endif /* HAVE_UNIX_SOCKETS */
-   int family, sLen; 
+   int family, sLen;
 #ifdef WIN32
         UInt4 iaddr;
 #else
@@ -156,9 +158,9 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname
        sLen = sizeof(self->sadr_in);
        if (iaddr == INADDR_NONE)
        {
-#if defined (POSIX_MULTITHREAD_SUPPORT) 
+#if defined (POSIX_MULTITHREAD_SUPPORT)
   #if defined (HAVE_GETIPNODEBYNAME) /* Free-BSD ? */
-           hp = getipnodebyname(hostname, AF_INET, 0, &error); 
+           hp = getipnodebyname(hostname, AF_INET, 0, &error);
   #elif defined (PGS_REENTRANT_API_1) /* solaris, irix */
            hp = gethostbyname_r(hostname, hp, buf, bufsz, &error);
   #elif defined (PGS_REENTRANT_API_2) /* linux */
@@ -474,3 +476,6 @@ SOCK_put_next_byte(SocketClass *self, UCHAR next_byte)
        } while (self->buffer_filled_out > 0);
    }
 }
+
+
+#endif /* USE_LIBPQ */
index d90a1a9018b561d2ce84f201a169efeae5746b88..b579fdb541c8b640e7445574c1b60d62a4ff3ed3 100644 (file)
 #include "statement.h"
 
 #include "bind.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
 #include "connection.h"
+#endif /* USE_LIBPQ */
 #include "qresult.h"
 #include "convert.h"
 #include "environ.h"
@@ -235,7 +240,11 @@ SC_Constructor(void)
        rv->phstmt = NULL;
        rv->result = NULL;
        rv->curres = NULL;
+#ifdef USE_LIBPQ
+       rv->manual_result = TRUE;
+#else
        rv->manual_result = FALSE;
+#endif /* USE_LIBPQ */
        rv->prepare = FALSE;
        rv->prepared = FALSE;
        rv->status = STMT_ALLOCATED;
@@ -614,7 +623,12 @@ SC_recycle_statement(StatementClass *self)
     * Reset only parameters that have anything to do with results
     */
    self->status = STMT_READY;
-   self->manual_result = FALSE;    /* very important */
+#ifdef USE_LIBPQ
+       self->manual_result = TRUE;     /* very important */
+#else
+       self->manual_result = FALSE;
+#endif /* USE_LIBPQ */
+
 
    self->currTuple = -1;
    self->rowset_start = -1;
@@ -760,6 +774,19 @@ SC_create_errormsg(const StatementClass *self)
        else
            return strdup(notice);
    }
+#ifdef USE_LIBPQ
+   if (conn)
+   {
+       PGconn *pgconn = conn->pgconn;
+
+       if (!detailmsg && CC_get_errormsg(conn) && (CC_get_errormsg(conn))[0] != '\0')
+       {
+           pos = strlen(msg);
+           sprintf(&msg[pos], ";\n%s", CC_get_errormsg(conn));
+       }
+
+   }
+#else
    if (conn)
    {
        SocketClass *sock = conn->sock;
@@ -776,6 +803,7 @@ SC_create_errormsg(const StatementClass *self)
            sprintf(&msg[pos], ";\n%s", sock->errormsg);
        }
    }
+#endif /* USE_LIBPQ */
    return msg[0] ? strdup(msg) : NULL;
 }
 
@@ -1232,7 +1260,11 @@ SC_execute(StatementClass *self)
    else
    {
        /* Bad Error -- The error message will be in the Connection */
+#ifdef USE_LIBPQ
+       if (!conn->pgconn)
+#else
        if (!conn->sock)
+#endif /* USE_LIBPQ */
            SC_set_error(self, STMT_BAD_ERROR, CC_get_errormsg(conn));
        else if (self->statement_type == STMT_TYPE_CREATE)
        {
index 0ae2130bff4d0ae1fbffa642c2e1656085d07b56..eaf78f021047c22a6e6262a44916e404ff99bc2e 100644 (file)
@@ -51,9 +51,10 @@ TL_Destructor(TupleListClass *self)
               *tp;
 
    mylog("TupleList: in DESTRUCTOR\n");
-
+   if(self && self->list_start)
+   {
    node = self->list_start;
-   while (node != NULL)
+       while (node)
    {
        for (lf = 0; lf < self->num_fields; lf++)
            if (node->tuple[lf].value != NULL)
@@ -63,6 +64,7 @@ TL_Destructor(TupleListClass *self)
        node = tp;
    }
 
+   }
    free(self);
 
    mylog("TupleList: exit DESTRUCTOR\n");
index 9ccdde23b13d94910e90d025761d118c38805385..e08d5b7bcf98a4f99c29e5961f3d9e0a2bd6a78a 100644 (file)
--- a/version.h
+++ b/version.h
@@ -5,14 +5,14 @@
  * Comments:       See "notice.txt" for copyright and license information.
  *
  * Note:            The version number should also be updated in :
- *                  psqlobdc.rc, configure.ac and installer/make.bat
+ *                  psqlodbc.rc, configure.ac and installer/make.bat
  */
 
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "08.00.0102"
-#define POSTGRES_RESOURCE_VERSION  "08.00.0102\0"
-#define PG_DRVFILE_VERSION     8,0,1,02
+#define POSTGRESDRIVERVERSION      "08.01.0001"
+#define POSTGRES_RESOURCE_VERSION  "08.01.0001\0"
+#define PG_DRVFILE_VERSION     8,1,0,1
 
 #endif
index ede22ba4c83da05ec5a5fa13503e58ba632bb4ac..198738572783c29e04daf83a38f874f9ecb2e3de 100644 (file)
--- a/win32.mak
+++ b/win32.mak
@@ -5,9 +5,9 @@
 #
 # Configurations:  Debug, Release
 # Build Types:     ALL, CLEAN
-# Usage:       NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN]
-#
+# Usage:       NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN] [MODE=[USE_LIBPQ | USE_SOCK]  PG_INC=<PostgreSQL include folder>]
 # Comments:        Created by Dave Page, 2001-02-12
+#              Modified by Anoop Kumar, 2005-06-27
 #
 
 !MESSAGE Building the PostgreSQL Unicode 3.0 Driver for Win32...
 !IF "$(CFG)" == ""
 CFG=Release
 !MESSAGE No configuration specified. Defaulting to Release.
-!MESSAGE
 !ENDIF 
 
+!IF "$(MODE)" == ""
+MODE=USE_LIBPQ
+!MESSAGE  Using Libpq.
+!ENDIF 
+
+!IF "$(MODE)"  == "USE_LIBPQ" 
+!IF "$(PG_INC)" == ""
+PG_INC=C:\Program Files\PostgreSQL\8.0\include
+!MESSAGE Using default PostgreSQL Include directory: $(PG_INC)
+!ENDIF 
+
+!IF "$(PG_LIB)" == ""
+PG_LIB=C:\Program Files\PostgreSQL\8.0\lib\ms
+!MESSAGE Using default PostgreSQL Library directory: $(PG_LIB)
+!ENDIF 
+!ENDIF
+
+!MESSAGE
+
 !IF "$(CFG)" != "Release" && "$(CFG)" != "Debug"
 !MESSAGE Invalid configuration "$(CFG)" specified.
 !MESSAGE You can specify a configuration when running NMAKE
 !MESSAGE by defining the macro CFG on the command line. For example:
 !MESSAGE 
-!MESSAGE NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN]
+!MESSAGE NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN] [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
 !MESSAGE 
 !MESSAGE Possible choices for configuration are:
 !MESSAGE 
@@ -33,6 +51,22 @@ CFG=Release
 !ERROR An invalid configuration was specified.
 !ENDIF 
 
+!IF "$(MODE)"  != "USE_LIBPQ" && "$(MODE)"  != "USE_SOCK"
+!MESSAGE Invalid mode "$(MODE)" specified.
+!MESSAGE You can specify the connection mode and PostgreSQL include folder
+!MESSAGE by defining the macros MODE  and  PG_INC on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN] [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
+!MESSAGE 
+!MESSAGE Possible choices for mode are:
+!MESSAGE 
+!MESSAGE "USE_LIBPQ" (Using Libpq Interface)
+!MESSAGE "USE_SOCK"   (Using Socket)
+!MESSAGE 
+!ERROR An invalid mode was specified.
+!ENDIF 
+
+
 !IF "$(OS)" == "Windows_NT"
 NULL=
 !ELSE 
@@ -93,7 +127,12 @@ CLEAN :
     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
 
 CPP=cl.exe
-CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+
+!IF "$(MODE)"=="USE_LIBPQ"
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "$(PG_INC)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+!ELSE
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+!ENDIF
 
 .c{$(INTDIR)}.obj::
    $(CPP) @<<
@@ -134,7 +173,14 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
 BSC32_SBRS= \
    
 LINK32=link.exe
+
+!IF "$(MODE)"=="USE_LIBPQ"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpq.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIRBIN)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /libpath:"$(PG_LIB)"
+!ELSE
 LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbc.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIRBIN)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" 
+!ENDIF
+
+
 DEF_FILE= "psqlodbc_win32.def"
 LINK32_OBJS= \
    "$(INTDIR)\bind.obj" \
@@ -234,7 +280,12 @@ CLEAN :
     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
 
 CPP=cl.exe
-CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+
+!IF "$(MODE)"=="USE_LIBPQ"
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /I "$(PG_INC)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+!ELSE
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+!ENDIF
 
 .c{$(INTDIR)}.obj::
    $(CPP) @<<
@@ -275,7 +326,13 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
 BSC32_SBRS= \
    
 LINK32=link.exe
+
+!IF "$(MODE)"=="USE_LIBPQ"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpq.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept /libpath:"$(PG_LIB)"
+!ELSE
 LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbc.pdb" /debug /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbc.dll" /implib:"$(OUTDIR)\psqlodbc.lib" /pdbtype:sept 
+!ENDIF
+
 DEF_FILE= "psqlodbc_win32.def"
 LINK32_OBJS= \
    "$(INTDIR)\bind.obj" \
@@ -452,6 +509,20 @@ SOURCE=psqlodbc.c
 
 SOURCE=psqlodbc.rc
 
+!IF "$(MODE)" == "USE_LIBPQ"
+
+!IF "$(CFG)" == "Release"
+"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" /d "USE_LIBPQ" $(SOURCE)
+!ENDIF
+
+!IF "$(CFG)" == "Debug"
+"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" /d "USE_LIBPQ" $(SOURCE)
+!ENDIF
+
+!ELSE
+
 !IF "$(CFG)" == "Release"
 "$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
    $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
@@ -462,6 +533,8 @@ SOURCE=psqlodbc.rc
    $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE)
 !ENDIF
 
+!ENDIF
+
 
 SOURCE=qresult.c