The version is now 8.03.0402.
authorHiroshi Inoue <inoue@tpf.co.jp>
Fri, 20 Mar 2009 15:39:22 +0000 (15:39 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Fri, 20 Mar 2009 15:39:22 +0000 (15:39 +0000)
1. Close (holdable) cursors on commit if possible.
2. Recycle columns cache info if the size becomes pretty large.
3. Add sslverify=none to conninfo in case of SSL connections
   via libpq of version 8.4.
4. Add a functionality to change the directory for logging.
5. Correct the error code for communication errors.

17 files changed:
Makefile.am
configure.ac
connection.c
connection.h
convert.c
descriptor.c
dlg_specific.h
environ.c
execute.c
loadlib.c
loadlib.h
mylog.c
parse.c
psqlodbc.h
statement.c
statement.h
version.h

index 36cdfca848b23c82c9b808edc9bee70992c6be56..90d9a8b074936bac1120b7fe6a3ede8a4f91ff13 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile.am for psqlodbc30w (PostgreSQL ODBC driver)
 #
-# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.51 2008/11/07 14:37:25 h-saito Exp $
+# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.52 2009/03/20 15:39:22 hinoue Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -22,8 +22,8 @@ endif
 
 AM_LDFLAGS = -module -no-undefined -avoid-version
 
-psqlodbca_la_LIBADD = -lpq
-psqlodbcw_la_LIBADD = -lpq
+psqlodbca_la_LIBADD = -lpq -lssl
+psqlodbcw_la_LIBADD = -lpq -lssl
     
 psqlodbca_la_SOURCES = \
    info.c bind.c columninfo.c connection.c convert.c drvconn.c \
index 96e629d169a1ca8fe12463be4603cc6e7159f3c2..672a08263c37775c37e5b5db9ff2db4f7f863aa6 100644 (file)
@@ -148,8 +148,8 @@ if test -z "$PG_CONFIG"; then
   AC_MSG_ERROR([pg_config not found (set PG_CONFIG environment variable)])
 fi
 
-pg_includedir=`$PG_CONFIG --includedir`
-pg_libdir=`$PG_CONFIG --libdir`
+pg_includedir=`"$PG_CONFIG" --includedir`
+pg_libdir=`"$PG_CONFIG" --libdir`
 CPPFLAGS="$CPPFLAGS -I$pg_includedir"
 LDFLAGS="$LDFLAGS -L$pg_libdir"
 
@@ -237,6 +237,8 @@ if test "$enable_pthreads" = yes; then
   fi
 fi
 
+# 8. Libltdl
+AC_CHECK_LIB(ltdl, lt_dloepn)
 
 
 AC_CONFIG_FILES([Makefile])
index 88dc0959ea9174f54dc1591bc790e78f4f2ae529..ec6b882f2ee1a40be04ae6b808ec81019b804de2 100644 (file)
@@ -51,6 +51,7 @@
 static void CC_lookup_pg_version(ConnectionClass *self);
 static void CC_lookup_lo(ConnectionClass *self);
 static char *CC_create_errormsg(ConnectionClass *self);
+static int  CC_close_eof_cursors(ConnectionClass *self);
 
 extern GLOBAL_VALUES globals;
 
@@ -444,6 +445,7 @@ CC_clear_error(ConnectionClass *self)
 
 
 CSTR   bgncmd = "BEGIN";
+CSTR   cmtcmd = "COMMIT";
 CSTR   rbkcmd = "ROLLBACK";
 CSTR   semi_colon = ";";
 /*
@@ -475,10 +477,14 @@ CC_commit(ConnectionClass *self)
    char    ret = TRUE;
    if (CC_is_in_trans(self))
    {
-       QResultClass *res = CC_send_query(self, "COMMIT", NULL, 0, NULL);
-       mylog("CC_commit:  sending COMMIT!\n");
-       ret = QR_command_maybe_successful(res);
-       QR_Destructor(res);
+       CC_close_eof_cursors(self);
+       if (CC_is_in_trans(self))
+       {
+           QResultClass *res = CC_send_query(self, cmtcmd, NULL, 0, NULL);
+           mylog("CC_commit:  sending COMMIT!\n");
+           ret = QR_command_maybe_successful(res);
+           QR_Destructor(res);
+       }
    }
 
    return ret;
@@ -1070,9 +1076,22 @@ static int   protocol3_opts_array(ConnectionClass *self, const char *opts[][2], BO
    }
    if (libpqopt)
    {
-       if (ci->sslmode[0])
+       switch (ci->sslmode[0])
        {
-           opts[cnt][0] = "sslmode";   opts[cnt++][1] = ci->sslmode;
+           case '\0':
+               break;
+           case 'd':
+               opts[cnt][0] = "sslmode";
+               opts[cnt++][1] = ci->sslmode;
+               break;
+           default:
+               opts[cnt][0] = "sslmode";
+               opts[cnt++][1] = ci->sslmode;
+               if (sslverify_needed())
+               {
+                   opts[cnt][0] = "sslverify";
+                   opts[cnt++][1] = "none";
+               }
        }
        if (ci->password[0])
        {
@@ -2128,6 +2147,37 @@ CC_get_error(ConnectionClass *self, int *number, char **message)
 }
 
 
+static int CC_close_eof_cursors(ConnectionClass *self)
+{
+   int i, ccount = 0;
+   StatementClass  *stmt;
+   QResultClass    *res;
+
+   if (!self->ncursors)
+       return ccount;
+   CONNLOCK_ACQUIRE(self);
+   for (i = 0; i < self->num_stmts; i++)
+   {
+       if (stmt = self->stmts[i], NULL == stmt)
+           continue;
+       if (res = SC_get_Result(stmt), NULL == res)
+           continue;
+       if (NULL != QR_get_cursor(res) &&
+           QR_is_withhold(res) &&
+           QR_once_reached_eof(res))
+       {
+           if (QR_get_num_cached_tuples(res) >= QR_get_num_total_tuples(res) ||
+                   SQL_CURSOR_FORWARD_ONLY == stmt->options.cursor_type)
+           {
+               QR_close(res);
+               ccount++;
+           }
+       }
+   }
+   CONNLOCK_RELEASE(self);
+   return ccount;
+}
+
 static void CC_clear_cursors(ConnectionClass *self, BOOL on_abort)
 {
    int i;
@@ -2587,7 +2637,7 @@ inolog("Discarded the first SAVEPOINT\n");
                        }
                        else
                        {
-                           if (strnicmp(cmdbuffer, "COMMIT", 6) == 0)
+                           if (strnicmp(cmdbuffer, cmtcmd, 6) == 0)
                                CC_on_commit(self);
                            else if (strnicmp(cmdbuffer, "END", 3) == 0)
                                CC_on_commit(self);
index c500c0406113ea1699cdcdfd019d43face622b6c..9651cd3415691647534bb689ee6a13a537f235f4 100644 (file)
@@ -10,6 +10,7 @@
 #define __CONNECTION_H__
 
 #include "psqlodbc.h"
+#include <time.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -371,17 +372,23 @@ typedef struct
 struct col_info
 {
    Int2        num_reserved_cols;
+   Int2        refcnt;
    QResultClass    *result;
    pgNAME      schema_name;
    pgNAME      table_name;
    OID     table_oid;
+   time_t      acc_time;
 };
 #define free_col_info_contents(coli) \
 { \
    if (NULL != coli->result) \
        QR_Destructor(coli->result); \
+   coli->result = NULL; \
    NULL_THE_NAME(coli->schema_name); \
    NULL_THE_NAME(coli->table_name); \
+   coli->table_oid = 0; \
+   coli->refcnt = 0; \
+   coli->acc_time = 0; \
 }
 #define col_info_initialize(coli) (memset(coli, 0, sizeof(COL_INFO)))
 
index 42ba628b31224410c9875bea895d5a8d4b667cd0..36d79960f4658a13bc284d849465c67147170436 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -2374,7 +2374,7 @@ inolog("prep_params\n");
    SC_set_planname(stmt, plan_name);
    if (!(res = SendSyncAndReceive(stmt, NULL, "prepare_and_describe")))
    {
-       SC_set_error(stmt, STMT_EXEC_ERROR, "commnication error while preapreand_describe", func);
+       SC_set_error(stmt, STMT_NO_RESPONSE, "commnication error while preapreand_describe", func);
        CC_on_abort(conn, CONN_DEAD);
        goto cleanup;
    }
@@ -2409,7 +2409,7 @@ inolog("prep_params\n");
                goto cleanup;
            if (!(res = SendSyncAndReceive(stmt, NULL, "prepare_and_describe")))
            {
-               SC_set_error(stmt, STMT_EXEC_ERROR, "commnication error while preapreand_describe", func);
+               SC_set_error(stmt, STMT_NO_RESPONSE, "commnication error while preapreand_describe", func);
                CC_on_abort(conn, CONN_DEAD);
                goto cleanup;
            }
index 0cf355531ccef3f0cc7f9991fed2ef386b7b1784..e5d990ffee8b44b81e20a480f1628ddeda002a0b 100644 (file)
@@ -49,6 +49,12 @@ inolog("TI_Destructor count=%d\n", count);
        {
            if (ti[i])
            {
+               COL_INFO *coli = ti[i]->col_info;
+               if (coli)
+               {
+mylog("!!!refcnt %p:%d -> %d\n", coli, coli->refcnt, coli->refcnt - 1);
+                   coli->refcnt--;
+               }
                NULL_THE_NAME(ti[i]->schema_name);
                NULL_THE_NAME(ti[i]->table_name);
                NULL_THE_NAME(ti[i]->table_alias);
index efc28ab08dd16e82d92e586fdddb81d868b6ef77..578e6b25688f411657748f579692b59f753b0e92 100644 (file)
@@ -143,6 +143,7 @@ extern "C" {
 #define INI_SSLMODE            "SSLmode"
 #define ABBR_SSLMODE           "CA"
 #define INI_EXTRAOPTIONS       "AB"
+#define INI_LOGDIR         "Logdir"
 
 #define    SSLMODE_DISABLE     "disable"
 #define    SSLMODE_ALLOW       "allow"
index 09302e5c788584aae12b7a5ec161124cf16ccc66..d96e760c622329858169cc6983b50dc4d35cd0d3 100644 (file)
--- a/environ.c
+++ b/environ.c
@@ -378,6 +378,7 @@ PGAPI_ConnectError( HDBC hdbc,
            case CONNECTION_COULD_NOT_SEND:
            case CONNECTION_COULD_NOT_RECEIVE:
            case CONNECTION_COMMUNICATION_ERROR:
+           case CONNECTION_NO_RESPONSE:
                pg_sqlstate_set(env, szSqlState, "08S01", "08S01");
                break;
            default:
@@ -510,7 +511,7 @@ EN_Constructor(void)
 #ifdef WIN32
    WORD        wVersionRequested;
    WSADATA     wsaData;
-   const int   major = 1, minor = 1;
+   const int   major = 2, minor = 2;
 
    /* Load the WinSock Library */
    wVersionRequested = MAKEWORD(major, minor);
@@ -521,8 +522,11 @@ EN_Constructor(void)
        return rv;
    }
    /* Verify that this is the minimum version of WinSock */
-   if (LOBYTE(wsaData.wVersion) != major ||
-       HIBYTE(wsaData.wVersion) != minor)
+   if (LOBYTE(wsaData.wVersion) >= 1 &&
+       (LOBYTE(wsaData.wVersion) >= 2 ||
+        HIBYTE(wsaData.wVersion) >= 1))
+       ;
+   else
    {
        mylog("%s: WSAStartup version=(%d,%d)\n", __FUNCTION__,
            LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
index c5d7964185b9f77e32929a0db8a2a22bb068388e..b0831cf5447cb8c860cf8ba1befcc5bd4f807172 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -1091,9 +1091,7 @@ PGAPI_Transact(
 {
    CSTR func = "PGAPI_Transact";
    ConnectionClass *conn;
-   QResultClass *res;
-   char        ok,
-              *stmt_string;
+   char        ok;
    int         lf;
 
    mylog("entering %s: hdbc=%p, henv=%p\n", func, hdbc, henv);
@@ -1125,11 +1123,8 @@ PGAPI_Transact(
 
    conn = (ConnectionClass *) hdbc;
 
-   if (fType == SQL_COMMIT)
-       stmt_string = "COMMIT";
-   else if (fType == SQL_ROLLBACK)
-       stmt_string = "ROLLBACK";
-   else
+   if (fType != SQL_COMMIT &&
+       fType != SQL_ROLLBACK)
    {
        CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter", func);
        return SQL_ERROR;
@@ -1138,11 +1133,9 @@ PGAPI_Transact(
    /* If manual commit and in transaction, then proceed. */
    if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
    {
-       mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string);
+       mylog("PGAPI_Transact: sending on conn %p '%d'\n", conn, fType);
 
-       res = CC_send_query(conn, stmt_string, NULL, 0, NULL);
-       ok = QR_command_maybe_successful(res);
-       QR_Destructor(res);
+       ok = (SQL_COMMIT == fType) ? CC_commit(conn) : CC_abort(conn);
        if (!ok)
        {
            /* error msg will be in the connection */
index 8442b3856d558b6407e3c6d22dc5d56bc8c4dcb1..38c292ab8af94ab0e36afa09a9b0f8ffd7acda68 100644 (file)
--- a/loadlib.c
+++ b/loadlib.c
@@ -58,9 +58,9 @@
 #pragma comment(linker, "/Delay:UNLOAD")
 #endif /* _MSC_VER */
 #endif /* _MSC_VER */
+
 #if defined(DYNAMIC_LOAD)
 #define    WIN_DYN_LOAD
-CSTR   libpq = "libpq";
 CSTR   libpqdll = "LIBPQ.dll";
 #ifdef UNICODE_SUPPORT
 CSTR   pgenlist = "pgenlist";
@@ -75,6 +75,12 @@ CSTR pgenlistdll = "PGENLISTA.dll";
 #endif /* DYNAMIC_LOAD */
 #endif /* WIN32 */
 
+#ifndef    NOT_USE_LIBPQ
+CSTR   libpq = "libpq";
+CSTR   checkproc = "PQconninfoParse";
+static int sslverify_available = -1;
+#endif /* NOT_USE_LIBPQ */
+
 #if defined(_MSC_DELAY_LOAD_IMPORT)
 static BOOL    loaded_libpq = FALSE, loaded_ssllib = FALSE;
 static BOOL    loaded_pgenlist = FALSE;
@@ -138,6 +144,15 @@ DliErrorHook(unsigned  dliNotify,
            {
                if (hmodule = MODULE_load_from_psqlodbc_path(libpq), NULL == hmodule)
                    hmodule = LoadLibrary(libpq);
+#ifndef    NOT_USE_LIBPQ
+               if (sslverify_available < 0 && NULL != hmodule)
+               {
+                   if (NULL == GetProcAddress(hmodule, checkproc))
+                       sslverify_available = FALSE;
+                   else
+                       sslverify_available = TRUE;
+               }
+#endif /* NOT_USE_LIBPQ */
            }
            else if (_strnicmp(pdli->szDll, pgenlist, strlen(pgenlist)) == 0)
            {
@@ -215,6 +230,61 @@ void CleanupDelayLoadedDLLs(void)
 #endif /* _MSC_DELAY_LOAD_IMPORT */
 
 #ifndef    NOT_USE_LIBPQ
+#if defined(_MSC_DELAY_LOAD_IMPORT)
+static int filter_conninfoParse(int level)
+{
+   switch (level & 0xffff)
+   {
+       case ERROR_MOD_NOT_FOUND:
+       case ERROR_PROC_NOT_FOUND:
+           return EXCEPTION_EXECUTE_HANDLER;
+   }
+   return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif /* _MSC_DELAY_LOAD_IMPORT */
+
+BOOL   sslverify_needed(void)
+{
+   if (sslverify_available < 0)
+   {
+#if defined(_MSC_DELAY_LOAD_IMPORT)
+       __try {
+           PQconninfoOption *conninfo;
+#if (_MSC_VER < 1300)
+           __pfnDliFailureHook = DliErrorHook;
+           __pfnDliNotifyHook = DliErrorHook;
+#else
+           __pfnDliFailureHook2 = DliErrorHook;
+           __pfnDliNotifyHook2 = DliErrorHook;
+#endif /* _MSC_VER */
+           if (conninfo = PQconninfoParse("sslverify=none", NULL), NULL == conninfo)
+               sslverify_available = 0;
+           {
+               sslverify_available = 1;
+               PQconninfoFree(conninfo);
+           }
+       }
+       __except (filter_conninfoParse(GetExceptionCode())) {
+           sslverify_available = 0;
+       }
+#else
+#ifdef HAVE_LIBLTDL
+       lt_dlhandle dlhandle = lt_dlopenext(libpq);
+
+       sslverify_available = 1;
+       if (NULL != dlhandle)
+       {
+           if (NULL == lt_dlsym(dlhandle, checkproc))
+               sslverify_available = 0;
+           lt_dlclose(dlhandle);
+       }
+#endif /* HAVE_LIBLTDL */
+#endif /* _MSC_DELAY_LOAD_IMPORT */
+   }
+
+   return (0 != sslverify_available);
+}
+
 void *CALL_PQconnectdb(const char *conninfo, BOOL *libpqLoaded)
 {
    void *pqconn = NULL;
index beabb3f0db3e13c34f19f36dc93978b4d4bb24ad..2fac4d7515f00ac167138bbabf6ec5bf44ec8615 100644 (file)
--- a/loadlib.h
+++ b/loadlib.h
 #define __LOADLIB_H__
 
 #include "psqlodbc.h"
+#ifdef HAVE_LIBLTDL
+#include <ltdl.h>
+#else
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif /* HAVE_DLFCN_H */
+#endif /* HAVE_LIBLTDL */
 
 #include <stdlib.h>
 #ifdef  __cplusplus
@@ -19,6 +26,7 @@ extern "C" {
 BOOL   SSLLIB_check(void);
 #ifndef    NOT_USE_LIBPQ
 void   *CALL_PQconnectdb(const char *conninfo, BOOL *);
+BOOL   sslverify_needed(void);
 #endif /* NOT_USE_LIBPQ */
 #ifdef _HANDLE_ENLIST_IN_DTC_
 RETCODE    CALL_EnlistInDtc(ConnectionClass *conn, void * pTra, int method);
diff --git a/mylog.c b/mylog.c
index d790bdd1fb113749e29bd6ddab44b799c4fb8dff..f8ab7b8dbe983d53ef53cbe9515fb9bedf04dfc9 100644 (file)
--- a/mylog.c
+++ b/mylog.c
@@ -13,6 +13,7 @@
  */
 
 #include "psqlodbc.h"
+#include "dlg_specific.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,7 +36,8 @@
 #endif
 
 extern GLOBAL_VALUES globals;
-void   generate_filename(const char *, const char *, char *);
+
+static char *logdir = NULL;
 
 void
 generate_filename(const char *dirname, const char *prefix, char *filename)
@@ -168,7 +170,7 @@ mylog(const char *fmt,...)
 
    if (!MLOGFP)
    {
-       generate_filename(MYLOGDIR, MYLOGFILE, filebuf);
+       generate_filename(logdir ? logdir : MYLOGDIR, MYLOGFILE, filebuf);
        MLOGFP = fopen(filebuf, PG_BINARY_A);
        if (!MLOGFP)
        {
@@ -176,7 +178,7 @@ mylog(const char *fmt,...)
            MLOGFP = fopen(filebuf, PG_BINARY_A);
            if (!MLOGFP)
            {
-               generate_filename("c:\\podbclog", MYLOGFILE, filebuf);
+               generate_filename("C:\\podbclog", MYLOGFILE, filebuf);
                MLOGFP = fopen(filebuf, PG_BINARY_A);
            }
        }
@@ -222,7 +224,7 @@ forcelog(const char *fmt,...)
 
    if (!MLOGFP)
    {
-       generate_filename(MYLOGDIR, MYLOGFILE, filebuf);
+       generate_filename(logdir ? logdir : MYLOGDIR, MYLOGFILE, filebuf);
        MLOGFP = fopen(filebuf, PG_BINARY_A);
        if (MLOGFP)
            setbuf(MLOGFP, NULL);
@@ -308,7 +310,7 @@ qlog(char *fmt,...)
 
    if (!QLOGFP)
    {
-       generate_filename(QLOGDIR, QLOGFILE, filebuf);
+       generate_filename(logdir ? logdir : QLOGDIR, QLOGFILE, filebuf);
        QLOGFP = fopen(filebuf, PG_BINARY_A);
        if (!QLOGFP)
        {
@@ -355,6 +357,11 @@ static void qlog_finalize() {}
 
 void InitializeLogging()
 {
+   char dir[PATH_MAX];
+
+   SQLGetPrivateProfileString(DBMS_NAME, INI_LOGDIR, "", dir, sizeof(dir), ODBCINST_INI);
+   if (dir[0])
+       logdir = strdup(dir);
    mylog_initialize();
    qlog_initialize();
 }
@@ -363,4 +370,9 @@ void FinalizeLogging()
 {
    mylog_finalize();
    qlog_finalize();
+   if (logdir)
+   {
+       free(logdir);
+       logdir = NULL;
+   }
 }
diff --git a/parse.c b/parse.c
index 2cedf377b892d0f173ee40ed6577620ea932f054..40a560c0e8d3881cf06cf2c967a9c4095acbdb8b 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -40,6 +40,7 @@
 #define FLD_INCR   32
 #define TAB_INCR   8
 #define COLI_INCR  16
+#define COLI_RECYCLE   128
 
 static char    *getNextToken(int ccsc, char escape_in_literal, char *s, char *token, int smax, char *delim, char *quote, char *dquote, char *numeric);
 static void    getColInfo(COL_INFO *col_info, FIELD_INFO *fi, int k);
@@ -705,7 +706,7 @@ COL_INFO **coli)
             * Though current_schema() doesn't have
             * much sense in PostgreSQL, we first
             * check the current_schema() when no
-            * explicit schema name was specified.
+            * explicit schema name is specified.
             */
            for (colidx = 0; colidx < conn->ntables; colidx++)
            {
@@ -811,21 +812,52 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
        && res != NULL && QR_get_num_cached_tuples(res) > 0)
    {
        BOOL        coli_exist = FALSE;
-       COL_INFO    *coli = NULL;
+       COL_INFO    *coli = NULL, *ccoli = NULL, *tcoli;
+       int     k;
+       time_t      acctime = 0;
 
        mylog("      Success\n");
        if (greloid != 0)
        {
-           int k;
-
            for (k = 0; k < conn->ntables; k++)
            {
-               if (conn->col_info[k]->table_oid == greloid)
+               tcoli = conn->col_info[k];
+               if (tcoli->table_oid == greloid)
+               {
+                   coli = tcoli;
+                   coli_exist = TRUE;
+                   break;
+               }
+           }
+       }
+       if (!coli_exist)
+       {
+           for (k = 0; k < conn->ntables; k++)
+           {
+               tcoli = conn->col_info[k];
+               if (0 < tcoli->refcnt)
+                   continue;
+               if ((0 == tcoli->table_oid &&
+                   NAME_IS_NULL(tcoli->table_name)) ||
+                   strnicmp(SAFE_NAME(tcoli->schema_name), "pg_temp_", 8) == 0)
                {
-                   coli = conn->col_info[k];
+                   coli = tcoli;
                    coli_exist = TRUE;
                    break;
                }
+               if (NULL == ccoli ||
+                   tcoli->acc_time < acctime)
+               {
+                   ccoli = tcoli;
+                   acctime = tcoli->acc_time;
+               }
+           }
+           if (!coli_exist &&
+               NULL != ccoli &&
+               conn->ntables >= COLI_RECYCLE)
+           {
+               coli_exist = TRUE;
+               coli = ccoli;
            }
        }
        if (coli_exist)
@@ -837,19 +869,21 @@ getColumnsInfo(ConnectionClass *conn, TABLE_INFO *wti, OID greloid, StatementCla
            if (conn->ntables >= conn->coli_allocated)
            {
                Int2    new_alloc;
+               COL_INFO **col_info;
 
                new_alloc = conn->coli_allocated * 2;
                if (new_alloc <= conn->ntables)
                    new_alloc = COLI_INCR;
                mylog("PARSE: Allocating col_info at ntables=%d\n", conn->ntables);
 
-               conn->col_info = (COL_INFO **) realloc(conn->col_info, new_alloc * sizeof(COL_INFO *));
-               if (!conn->col_info)
+               col_info = (COL_INFO **) realloc(conn->col_info, new_alloc * sizeof(COL_INFO *));
+               if (!col_info)
                {
                    if (stmt)
                        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for col_info.", __FUNCTION__);
                    goto cleanup;
                }
+               conn->col_info = col_info;
                conn->coli_allocated = new_alloc;
            }
 
@@ -907,6 +941,7 @@ inolog("oid item == %s\n", QR_get_value_backend_text(res, 0, 3));
        mylog("Created col_info table='%s', ntables=%d\n", PRINT_NAME(wti->table_name), conn->ntables);
        /* Associate a table from the statement with a SQLColumn info */
        found = TRUE;
+       coli->refcnt++;
        wti->col_info = coli;
    }
 cleanup:
@@ -928,8 +963,11 @@ inolog("getCOLIfromTI reloid=%u ti=%p\n", reloid, wti);
    if (!wti)   /* SQLColAttribute case */
    {
        int i;
+
        if (0 == greloid)
            return FALSE;
+       if (!stmt)
+           return FALSE;
        colatt = TRUE;
        for (i = 0; i < stmt->ntab; i++)
        {
@@ -987,6 +1025,7 @@ inolog("fi=%p greloid=%d col_info=%p\n", wti, greloid, wti->col_info);
        else if (NULL != coli)
        {
            found = TRUE;
+           coli->refcnt++;
            wti->col_info = coli;
        }
    }
@@ -1019,6 +1058,7 @@ inolog("#1 %p->table_name=%s(%u)\n", wti, PRINT_NAME(wti->table_name), wti->tabl
            if (stmt)
                ColAttSet(stmt, wti);
        }
+       wti->col_info->acc_time = SC_get_time(stmt);
    }
    else if (!colatt && stmt)
        SC_set_parse_status(stmt, STMT_PARSE_FATAL);
index f38db0ed738be736e6005eb44f049e3568f07656..c6c4800ce50e9df0fd259b6452b2ea84f686d2e8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.124 2008/11/23 01:00:53 hinoue Exp $
+ * $Id: psqlodbc.h,v 1.125 2009/03/20 15:39:22 hinoue Exp $
  *
  */
 
@@ -181,7 +181,12 @@ typedef double SDOUBLE;
 #define    FALSE   (BOOL)0
 #endif /* FALSE */
 #else
+#if (_MSC_VER >= 1400)
+#define snprintf sprintf_s
+#define strncat(d, s, l) strcat_s(d, l, s)
+#else
 #define snprintf _snprintf
+#endif
 #ifndef strdup
 #define strdup _strdup
 #endif /* strdup */
@@ -470,7 +475,7 @@ const pthread_mutexattr_t *getMutexAttr(void);
 #define WCLEN sizeof(SQLWCHAR)
 SQLULEN    ucs2strlen(const SQLWCHAR *ucs2str);
 char   *ucs2_to_utf8(const SQLWCHAR *ucs2str, SQLLEN ilen, SQLLEN *olen, BOOL tolower);
-SQLULEN    utf8_to_ucs2_lf(const char * utf8str, SQLLEN ilen, BOOL lfconv, SQLWCHAR *ucs2str, SQLULEN buflen);
+SQLLEN utf8_to_ucs2_lf(const char * utf8str, SQLLEN ilen, BOOL lfconv, SQLWCHAR *ucs2str, SQLULEN buflen);
 #define    utf8_to_ucs2(utf8str, ilen, ucs2str, buflen) utf8_to_ucs2_lf(utf8str, ilen, FALSE, ucs2str, buflen)
 #endif /* UNICODE_SUPPORT */
 
index c123ebc53452cac6567a0fe6e6b0cb28190cf26d..b491656069f4d04f4952e177860cc3c0e146a2e4 100644 (file)
@@ -771,7 +771,7 @@ SC_recycle_statement(StatementClass *self)
            if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
            {
                if (SC_is_pre_executable(self) && !SC_is_parse_tricky(self))
-                   CC_abort(conn);
+                   /* CC_abort(conn) */;
            }
            break;
 
@@ -1146,7 +1146,8 @@ static struct
    { STMT_OPTION_NOT_FOR_THE_DRIVER, "HYC00", "HYC00" },
    { STMT_FETCH_OUT_OF_RANGE, "HY106", "S1106" },
    { STMT_COUNT_FIELD_INCORRECT, "07002", "07002" },
-   { STMT_INVALID_NULL_ARG, "HY009", "S1009" }
+   { STMT_INVALID_NULL_ARG, "HY009", "S1009" },
+   { STMT_NO_RESPONSE, "08S01", "08S01" }
 };
 
 static PG_ErrorInfo *
@@ -1821,7 +1822,7 @@ inolog("get_Result=%p %p %d\n", res, SC_get_Result(self), self->curr_param_resul
        if (!(res = SendSyncAndReceive(self, self->curr_param_result ? res : NULL, "bind_and_execute")))
        {
            if (SC_get_errornumber(self) <= 0)
-               SC_set_error(self, STMT_EXEC_ERROR, "Could not receive the response, communication down ??", func);
+               SC_set_error(self, STMT_NO_RESPONSE, "Could not receive the response, communication down ??", func);
            CC_on_abort(conn, CONN_DEAD);
            goto cleanup;
        }
@@ -2293,7 +2294,7 @@ QResultClass *SendSyncAndReceive(StatementClass *stmt, QResultClass *res, const
        id = SOCK_get_id(sock);
        if ((SOCK_get_errcode(sock) != 0) || (id == EOF))
        {
-           SC_set_error(stmt, CONNECTION_NO_RESPONSE, "No response rom the backend", func);
+           SC_set_error(stmt, STMT_NO_RESPONSE, "No response rom the backend", func);
 
            mylog("%s: 'id' - %s\n", func, SC_get_errormsg(stmt));
            CC_on_abort(conn, CONN_DEAD);
index a8bb075e3f4bc0829f8e151d40ac6a5181824fbb..453d61bdcee96f4701bfdf8864822d502b09ac30 100644 (file)
@@ -93,6 +93,7 @@ enum {
    ,STMT_FETCH_OUT_OF_RANGE
    ,STMT_COUNT_FIELD_INCORRECT
    ,STMT_INVALID_NULL_ARG
+   ,STMT_NO_RESPONSE
 };
 
 /* statement types */
index 663c1d794fbe169345682b36070368b73d11d56c..3cc35649e64045bddb23313fd29d9175410fc1ae 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,9 +9,9 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "08.03.0401"
-#define POSTGRES_RESOURCE_VERSION  "08.03.0401\0"
-#define PG_DRVFILE_VERSION     8,3,04,01
-#define PG_BUILD_VERSION       "200901180001"
+#define POSTGRESDRIVERVERSION      "08.03.0402"
+#define POSTGRES_RESOURCE_VERSION  "08.03.0402\0"
+#define PG_DRVFILE_VERSION     8,3,04,02
+#define PG_BUILD_VERSION       "200903200002"
 
 #endif