The version is now 8.2.0105.
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 23 Oct 2006 15:58:29 +0000 (15:58 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 23 Oct 2006 15:58:29 +0000 (15:58 +0000)
1. SQLStatistics now returns indices based on expression also.
2. Add a TEST button on the setup dialog.

16 files changed:
configure.ac
connection.c
convert.c
drvconn.c
execute.c
info.c
misc.h
mylog.c
psqlodbc.rc
resource.h
setup.c
socket.c
socket.h
statement.c
version.h
win32.mak

index 8a84b648a5d07f45f0be810b23f8b0c0237da165..1d2c07973f45eb1bff79eb772012aea91fdd6734 100644 (file)
@@ -1,5 +1,5 @@
 # Process this file with autoconf to produce a configure script.
-AC_INIT(psqlodbc, 08.02.0102, [pgsql-odbc@postgresql.org])
+AC_INIT(psqlodbc, 08.02.0105, [pgsql-odbc@postgresql.org])
 AC_PREREQ(2.52)
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([bind.c])
@@ -61,6 +61,8 @@ PGAC_ARG_BOOL(enable, unicode, yes,
 AM_CONDITIONAL(enable_unicode, [test x"$enable_unicode" = xyes])
 
 AC_CHECK_FUNCS(strtoul strtoll)
+PGAC_STRUCT_ADDRINFO
+# If `struct addrinfo' exists, define HAVE_STRUCT_ADDRINFO.
 
 # to implement the thread-safe driver
 PGAC_ARG_BOOL(enable, pthreads, no,
@@ -71,7 +73,7 @@ PGAC_ARG_BOOL(enable, pthreads, no,
    [Define _REENTRANT for several plaforms])
      AC_CHECK_LIB(pthreads, pthread_create, [],
        [AC_CHECK_LIB(pthread, pthread_create)])
-     AC_CHECK_FUNCS(localtime_r strtok_r pthread_mutexattr_settype)
+     AC_CHECK_FUNCS(localtime_r strtok_r strerror_r pthread_mutexattr_settype)
      if test x"$ac_cv_func_pthread_mutexattr_settype" = xyes; then
    AC_TRY_COMPILE([#include <pthread.h>],
    [ int i = PTHREAD_MUTEX_RECURSIVE;],
@@ -80,6 +82,7 @@ PGAC_ARG_BOOL(enable, pthreads, no,
    [ int i = PTHREAD_MUTEX_RECURSIVE_NP;],
         [AC_DEFINE(PG_RECURSIVE_MUTEXATTR, PTHREAD_MUTEX_RECURSIVE_NP, [Define if you have PTHREAD_MUTEX_RECURSIVE_NP])])])
      fi
+     PGAC_FUNC_STRERROR_R_INT
     ])
 
 AC_PROG_CC
index b78c61b2aa29de3ca6cd7823d90cfab1f414a379..2b07307407dd7fc0c115b879b6b961ff9695f7e9 100644 (file)
@@ -1848,6 +1848,7 @@ CC_create_errormsg(ConnectionClass *self)
    SocketClass *sock = self->sock;
    size_t  pos;
    char    msg[4096];
+   const char *sockerrmsg;
 
    mylog("enter CC_create_errormsg\n");
 
@@ -1858,10 +1859,10 @@ CC_create_errormsg(ConnectionClass *self)
 
    mylog("msg = '%s'\n", msg);
 
-   if (sock && sock->errormsg && sock->errormsg[0] != '\0')
+   if (sock && NULL != (sockerrmsg = SOCK_get_errmsg(sock)) && '\0' != sockerrmsg[0])
    {
        pos = strlen(msg);
-       snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sock->errormsg);
+       snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sockerrmsg);
    }
 
    mylog("exit CC_create_errormsg\n");
@@ -3102,7 +3103,7 @@ CC_log_error(const char *func, const char *desc, const ConnectionClass *self)
        {
            SocketClass *sock = self->sock;
 
-           qlog("            socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(sock->errormsg));
+           qlog("            socket=%d, reverse=%d, errornumber=%d, errormsg='%s'\n", sock->socket, sock->reverse, sock->errornumber, nullcheck(SOCK_get_errmsg(sock)));
            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);
        }
index 1c8773dec4c9950edbb5dc67475f813403ebcd1d..317cc963d9a74750cac525dec4d3c19f18743fa2 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -679,25 +679,29 @@ inolog("2stime fr=%d\n", std_time.fr);
 
            /* This is for internal use by SQLStatistics() */
        case PG_TYPE_INT2VECTOR:
+           if (SQL_C_DEFAULT == fCType)
            {
-               int         nval,
-                           i;
+               int i, nval, maxc;
                const char *vp;
-
                /* this is an array of eight integers */
-               short      *short_array = (short *) rgbValueBindRow;
+               short      *short_array = (short *) rgbValueBindRow, shortv;
 
-               len = INDEX_KEYS_STORAGE_COUNT * 2;
+               maxc = 0;
+               if (NULL != short_array)
+                   maxc = (int) cbValueMax / sizeof(short);
                vp = value;
                nval = 0;
                mylog("index=(");
-               for (i = 0; i < INDEX_KEYS_STORAGE_COUNT; i++)
+               for (i = 0;; i++)
                {
-                   if (sscanf(vp, "%hd", &short_array[i]) != 1)
+                   if (sscanf(vp, "%hi", &shortv) != 1)
+                       break;
+                   mylog(" %hi", shortv);
+                   if (0 == shortv && PG_VERSION_LT(conn, 7.2))
                        break;
-
-                   mylog(" %d", short_array[i]);
                    nval++;
+                   if (nval < maxc)
+                       short_array[i + 1] = shortv;
 
                    /* skip the current token */
                    while ((*vp != '\0') && (!isspace((UCHAR) *vp)))
@@ -708,30 +712,22 @@ inolog("2stime fr=%d\n", std_time.fr);
                    if (*vp == '\0')
                        break;
                }
-               mylog(") nval = %d\n", nval);
-
-               for (i = nval; i < INDEX_KEYS_STORAGE_COUNT; i++)
-                   short_array[i] = 0;
-
-#if 0
-               sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
-                      &short_array[0],
-                      &short_array[1],
-                      &short_array[2],
-                      &short_array[3],
-                      &short_array[4],
-                      &short_array[5],
-                      &short_array[6],
-                      &short_array[7]);
-#endif
+               mylog(") nval = %i\n", nval);
+               if (maxc > 0)
+                   short_array[0] = nval;
 
                /* There is no corresponding fCType for this. */
+               len = (nval + 1) * sizeof(short);
                if (pcbValue)
                    *((SQLLEN *) pcbValueBindRow) = len;
 
-               return COPY_OK; /* dont go any further or the data will be
+               if (len <= cbValueMax)
+                   return COPY_OK; /* dont go any further or the data will be
                                 * trashed */
+               else
+                   return COPY_RESULT_TRUNCATED;
            }
+           break;
 
            /*
             * This is a large object OID, which is used to store
@@ -3704,7 +3700,7 @@ mylog("cvt_null_date_string=%d pgtype=%d buf=%p\n", conn->connInfo.cvt_null_date
             * parameter marker -- the data has already been sent to
             * the large object
             */
-           sprintf(param_string, "%d", lobj_oid);
+           sprintf(param_string, "%u", lobj_oid);
            lastadd = "::lo";
            CVT_APPEND_STR(qb, param_string);
 
index 01889e0138b7f7ce23a907703a1dbd2603074b7e..253ce0ea6e29f4324e6e998c2d2e5d845a739c27 100644 (file)
--- a/drvconn.c
+++ b/drvconn.c
@@ -363,6 +363,11 @@ dconn_FDriverConnectProc(
            ShowWindow(GetDlgItem(hdlg, IDC_DESCTEXT), SW_HIDE);
            ShowWindow(GetDlgItem(hdlg, IDC_DESC), SW_HIDE);
            ShowWindow(GetDlgItem(hdlg, IDC_DRIVER), SW_HIDE);
+           ShowWindow(GetDlgItem(hdlg, IDC_TEST), SW_HIDE);
+           if ('\0' != ci->server[0])
+               EnableWindow(GetDlgItem(hdlg, IDC_SERVER), FALSE);
+           if ('\0' != ci->port[0])
+               EnableWindow(GetDlgItem(hdlg, IDC_PORT), FALSE);
 
            SetWindowLongPtr(hdlg, DWLP_USER, lParam);      /* Save the ConnInfo for
                                                         * the "OK" */
index 2560867ce9d05de86c0208f1cca31fd1d4b66a1d..f0d96fe43cf7c2f4e68a32761a8cb41e1f0802a1 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -1193,11 +1193,12 @@ PGAPI_Cancel(
 #ifdef WIN32
        if (ci->drivers.cancel_as_freestmt)
        {
+   typedef SQLRETURN (SQL_API *SQLAPIPROC)();
            HMODULE     hmodule;
-           FARPROC     addr;
+           SQLAPIPROC  addr;
 
            hmodule = GetModuleHandle("ODBC32");
-           addr = GetProcAddress(hmodule, "SQLFreeStmt");
+           addr = (SQLAPIPROC) GetProcAddress(hmodule, "SQLFreeStmt");
            ret = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE);
        }
        else
diff --git a/info.c b/info.c
index 658a2d3a3f2c4145a0846076e82e0711205213f4..bf9d2ea9894ab0eaeb597e5d2c3ae5ededc85097 100644 (file)
--- a/info.c
+++ b/info.c
@@ -2276,7 +2276,7 @@ retry_public_schema:
            else
                set_tuplefield_string(&tuple[COLUMNS_SCHEMA_NAME], NULL_STRING);
            set_tuplefield_string(&tuple[COLUMNS_TABLE_NAME], table_name);
-           set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], "oid");
+           set_tuplefield_string(&tuple[COLUMNS_COLUMN_NAME], OID_NAME);
            sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
            set_tuplefield_int2(&tuple[COLUMNS_DATA_TYPE], sqltype);
            set_tuplefield_string(&tuple[COLUMNS_TYPE_NAME], "OID");
@@ -2784,7 +2784,7 @@ inolog("Add ctid\n");
            tuple = QR_AddNew(res);
 
            set_tuplefield_int2(&tuple[0], SQL_SCOPE_SESSION);
-           set_tuplefield_string(&tuple[1], "oid");
+           set_tuplefield_string(&tuple[1], OID_NAME);
            set_tuplefield_int2(&tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
            set_tuplefield_string(&tuple[3], pgtype_to_name(stmt, the_type, TRUE));
            set_tuplefield_int4(&tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
@@ -2852,7 +2852,7 @@ PGAPI_Statistics(
    RETCODE     ret = SQL_ERROR, result;
    char        *escSchemaName = NULL, *table_name = NULL, *escTableName = NULL;
    char        index_name[MAX_INFO_STRING];
-   short       fields_vector[INDEX_KEYS_STORAGE_COUNT];
+   short       fields_vector[INDEX_KEYS_STORAGE_COUNT + 1];
    char        isunique[10],
                isclustered[10],
                ishash[MAX_INFO_STRING];
@@ -2875,7 +2875,7 @@ PGAPI_Statistics(
    char        buf[256];
    SQLSMALLINT internal_asis_type = SQL_C_CHAR, cbSchemaName, field_number;
    const char  *szSchemaName;
-   BOOL        unknownf;
+   OID     ioid;
 
    mylog("%s: entering...stmt=%p scnm=%p len=%d\n", func, stmt, NULL_IF_NULL(szTableOwner), cbTableOwner);
 
@@ -3039,6 +3039,7 @@ PGAPI_Statistics(
        escSchemaName = simpleCatalogEscape(table_schemaname, SQL_NTS, NULL, conn); 
        snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
            ", i.indisclustered, a.amname, c.relhasrules, n.nspname"
+           ", c.oid"
            " from pg_catalog.pg_index i, pg_catalog.pg_class c,"
            " pg_catalog.pg_class d, pg_catalog.pg_am a,"
            " pg_catalog.pg_namespace n"
@@ -3052,7 +3053,7 @@ PGAPI_Statistics(
    }
    else
        snprintf(index_query, sizeof(index_query), "select c.relname, i.indkey, i.indisunique"
-           ", i.indisclustered, a.amname, c.relhasrules"
+           ", i.indisclustered, a.amname, c.relhasrules, c.oid"
            " from pg_index i, pg_class c, pg_class d, pg_am a"
            " where d.relname = '%s'"
            " and d.oid = i.indrelid"
@@ -3089,7 +3090,7 @@ PGAPI_Statistics(
    }
    /* bind the vector column */
    result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT,
-           fields_vector, INDEX_KEYS_STORAGE_COUNT * 2, &fields_vector_len);
+           fields_vector, sizeof(fields_vector), &fields_vector_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, indx_stmt, TRUE); /* "Couldn't bind column 
@@ -3137,6 +3138,14 @@ PGAPI_Statistics(
        goto cleanup;
    }
 
+   result = PGAPI_BindCol(hindx_stmt, 8, SQL_C_ULONG,
+                   &ioid, sizeof(ioid), NULL);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   {
+       SC_error_copy(stmt, indx_stmt, TRUE);
+       goto cleanup;
+   }
+
    relhasrules[0] = '0';
    result = PGAPI_Fetch(hindx_stmt);
    /* fake index of OID */
@@ -3165,7 +3174,7 @@ PGAPI_Statistics(
        set_tuplefield_int2(&tuple[STATS_TYPE], (Int2) SQL_INDEX_OTHER);
        set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) 1);
 
-       set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "oid");
+       set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
        set_tuplefield_string(&tuple[STATS_COLLATION], "A");
        set_tuplefield_null(&tuple[STATS_CARDINALITY]);
        set_tuplefield_null(&tuple[STATS_PAGES]);
@@ -3178,9 +3187,11 @@ PGAPI_Statistics(
        if (fUnique == SQL_INDEX_ALL ||
            (fUnique == SQL_INDEX_UNIQUE && atoi(isunique)))
        {
-           i = 0;
+           int colcnt, attnum;
+
            /* add a row in this table for each field in the index */
-           while (i < INDEX_KEYS_STORAGE_COUNT && fields_vector[i] != 0)
+           colcnt = fields_vector[0];
+           for (i = 1; i <= colcnt; i++)
            {
                tuple = QR_AddNew(res);
 
@@ -3208,21 +3219,34 @@ PGAPI_Statistics(
                                (!strncmp(ishash, "hash", 4)) ? SQL_INDEX_HASHED : SQL_INDEX_OTHER));
                set_tuplefield_int2(&tuple[STATS_SEQ_IN_INDEX], (Int2) (i + 1));
 
-               if (fields_vector[i] == OID_ATTNUM)
+               attnum = fields_vector[i];
+               if (OID_ATTNUM == attnum)
                {
-                   set_tuplefield_string(&tuple[STATS_COLUMN_NAME], "oid");
+                   set_tuplefield_string(&tuple[STATS_COLUMN_NAME], OID_NAME);
                    mylog("%s: column name = oid\n", func);
                }
+               else if (0 == attnum)
+               {
+                   char    cmd[64];
+
+                   QResultClass *res;
+
+                   snprintf(cmd, sizeof(cmd), "select pg_get_indexdef(%u, %d, true)", ioid, i);
+                   res = CC_send_query(conn, cmd, NULL, IGNORE_ABORT_ON_CONN, stmt);
+                   if (QR_command_maybe_successful(res))
+                       set_tuplefield_string(&tuple[STATS_COLUMN_NAME], QR_get_value_backend_row(res, 0, 0));
+                   QR_Destructor(res);
+               }
                else
                {
                    int j, matchidx;
+                   BOOL    unknownf = TRUE;
 
-                   unknownf = TRUE;
-                   if (fields_vector[i] >= 0)
+                   if (attnum > 0)
                    {
                        for (j = 0; j < total_columns; j++)
                        {
-                           if (fields_vector[i] == column_names[j].pnum)
+                           if (attnum == column_names[j].pnum)
                            {
                                matchidx = j;
                                unknownf = FALSE;
@@ -3246,7 +3270,6 @@ PGAPI_Statistics(
                set_tuplefield_null(&tuple[STATS_CARDINALITY]);
                set_tuplefield_null(&tuple[STATS_PAGES]);
                set_tuplefield_null(&tuple[STATS_FILTER_CONDITION]);
-               i++;
            }
        }
 
diff --git a/misc.h b/misc.h
index 06637b8abe671f7822520ec1afb6809a7015adc0..88febdf896da1ae11c47616cb62fa87a22047aac 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -68,7 +68,7 @@ extern "C" {
 #else
 #define MYLOGDIR           "c:"
 #endif /* WIN32 */
-extern void mylog(char *fmt,...);
+extern void mylog(const char *fmt,...);
 extern void forcelog(const char *fmt,...);
 
 #else /* MY_LOG */
diff --git a/mylog.c b/mylog.c
index fccf675ade1ae758716763aacc40d7ce3de3148f..ab1fa85fdfe9b031e3592e475a75c08e62ca0764 100644 (file)
--- a/mylog.c
+++ b/mylog.c
@@ -35,14 +35,17 @@ void        generate_filename(const char *, const char *, char *);
 void
 generate_filename(const char *dirname, const char *prefix, char *filename)
 {
+#ifdef WIN32
    int pid = 0;
 
-#ifndef WIN32
+   pid = _getpid();
+#else
+   pid_t   pid = 0;
    struct passwd *ptr = 0;
 
    ptr = getpwuid(getuid());
-#endif
    pid = getpid();
+#endif
    if (dirname == 0 || filename == 0)
        return;
 
@@ -112,6 +115,9 @@ logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
    LEAVE_MYLOG_CS;
 }
 
+#ifdef WIN32
+#define    LOGGING_PROCESS_TIME
+#endif /* WIN32 */
 #ifdef LOGGING_PROCESS_TIME
 #include <mmsystem.h>
    static  DWORD   start_time = 0;
@@ -119,7 +125,7 @@ logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
 #ifdef MY_LOG
 static FILE *MLOGFP = NULL;
 void
-mylog(char *fmt,...)
+mylog(const char *fmt,...)
 {
    va_list     args;
    char        filebuf[80];
index 5ea58e2b6a1aa8159f29fd7557a24a8b88080f1e..41fcaaa7b316a1c81d9e2c7d6287f4722497f1ed 100644 (file)
@@ -71,6 +71,7 @@ BEGIN
     LTEXT           "In the original form, Japanese patch Hiroshi-saito",
                     IDC_STATIC,35,198,295,8
     PUSHBUTTON      "\8aÇ\97\9d",IDC_MANAGEDSN,295,10,50,14
+    PUSHBUTTON      "\83e\83X\83g",IDC_TEST,296,30,51,14
 END
 
 DLG_OPTIONS_DRV DIALOG DISCARDABLE  0, 0, 350, 241
@@ -445,14 +446,23 @@ BEGIN
     EDITTEXT        IDC_USER,57,69,72,12,ES_AUTOHSCROLL
     RTEXT           "Pass&word",IDC_STATIC,154,72,34,9
     EDITTEXT        IDC_PASSWORD,192,70,72,12,ES_PASSWORD | ES_AUTOHSCROLL
-    DEFPUSHBUTTON   "OK",IDOK,12,114,44,15,WS_GROUP
-    PUSHBUTTON      "Cancel",IDCANCEL,66,114,44,15
-    GROUPBOX        "Options",IDC_OPTIONS,121,101,177,35,BS_LEFT
-    PUSHBUTTON      "Datasource",IDC_DATASOURCE,128,115,50,14
-    PUSHBUTTON      "Global",IDC_DRIVER,184,115,50,14
+//    DEFPUSHBUTTON   "OK",IDOK,12,114,44,15,WS_GROUP
+//    PUSHBUTTON      "Cancel",IDCANCEL,66,114,44,15
+//    GROUPBOX        "Options",IDC_OPTIONS,121,101,177,35,BS_LEFT
+//    PUSHBUTTON      "Datasource",IDC_DATASOURCE,128,115,50,14
+//    PUSHBUTTON      "Global",IDC_DRIVER,184,115,50,14
     LTEXT           "Please supply any missing information required to connect.",
                     DRV_MSG_LABEL,12,5,249,10
-    PUSHBUTTON      "Manage DSN",IDC_MANAGEDSN,240,115,52,14
+//    PUSHBUTTON      "Manage DSN",IDC_MANAGEDSN,240,115,52,14
+
+     GROUPBOX        "Options",IDC_OPTIONS,5,100,177,35,BS_LEFT
+     PUSHBUTTON      "Datasource",IDC_DATASOURCE,12,114,50,14
+     PUSHBUTTON      "Global",IDC_DRIVER,67,114,50,14
+     PUSHBUTTON      "Manage DSN",IDC_MANAGEDSN,122,114,52,14
+
+     PUSHBUTTON      "Test",IDC_TEST,254,103,44,15
+     DEFPUSHBUTTON   "OK",IDOK,203,121,44,15,WS_GROUP
+     PUSHBUTTON      "Cancel",IDCANCEL,254,121,44,15
 END
 
 DLG_OPTIONS_DRV DIALOG DISCARDABLE  0, 0, 287, 231
index d5fe5be69989cb69e7ff234f5f4ff323fe48c6a9..51f62a3226ad98683cf64aad722b11794ed72a6f 100644 (file)
@@ -93,6 +93,7 @@
 #define DS_STATEMENT_ROLLBACK      1082
 #define DRV_DTCLOG         1083
 #define DS_EXTRA_OPTIONS       1084
+#define IDC_TEST           1085
 
 // Next default values for new objects
 // 
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        105
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1085
+#define _APS_NEXT_CONTROL_VALUE         1086
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif
diff --git a/setup.c b/setup.c
index 94d91e1de58f5e84290aedd1f43f16997f412e6b..450e85f1c06d4edd6b310f0bf609e76e9c11f4c4 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -20,6 +20,7 @@
 #include  <string.h>
 #include  <stdlib.h>
 #include  "resource.h"
+#include  "pgapifunc.h"
 #include  "dlg_specific.h"
 #include  "win_setup.h"
 
@@ -284,6 +285,39 @@ ConfigDlgProc(HWND hdlg,
                    EndDialog(hdlg, wParam);
                    return TRUE;
 
+               case IDC_TEST:
+               {
+                   lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWLP_USER);
+                   if (NULL != lpsetupdlg)
+                   {
+                       ConnectionClass *conn=CC_Constructor();
+                       char    szMsg[SQL_MAX_MESSAGE_LENGTH];
+
+                       /* Get Dialog Values */
+                       GetDlgStuff(hdlg, &lpsetupdlg->ci);
+                       if (conn)
+                       {
+                           char *emsg;
+
+                           memcpy(&conn->connInfo, &lpsetupdlg->ci, sizeof(ConnInfo));
+                           if (CC_connect(conn, AUTH_REQ_OK, NULL) > 0)
+                           {
+                               strncpy(szMsg, "Connection successful", sizeof(szMsg));
+                               emsg = szMsg;
+                           }
+                           else
+                           {
+                               int errnum;
+
+                               CC_get_error(conn, &errnum, &emsg);
+                           }
+                           MessageBox(lpsetupdlg->hwndParent, emsg, "Connection Test", MB_ICONEXCLAMATION | MB_OK);
+                           CC_Destructor(conn);
+                           return TRUE;
+                       }
+                   }
+                   break;
+               }
                case IDC_DATASOURCE:
                    lpsetupdlg = (LPSETUPDLG) GetWindowLong(hdlg, DWLP_USER);
                    DialogBoxParam(s_hModule, MAKEINTRESOURCE(DLG_OPTIONS_DRV),
index badfc502be0a4c09b41390700600787c9cf46fc3..f5933b7f642183832fb9ed4b5f135e131ff871ae 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -37,7 +37,12 @@ static void SOCK_set_error(SocketClass *s, int _no, const char *_msg)
 {
    int gerrno = SOCK_ERRNO;
    s->errornumber = _no;
-   s->errormsg = (char *) _msg;
+   if (NULL != s->_errormsg_)
+       free(s->_errormsg_);
+   if (NULL != _msg)
+       s->_errormsg_ = strdup(_msg);
+   else
+       s->_errormsg_ = NULL;
    mylog("(%d)%s ERRNO=%d\n", _no, _msg, gerrno);
 }
 
@@ -45,7 +50,9 @@ void
 SOCK_clear_error(SocketClass *self)
 {
    self->errornumber = 0;
-   self->errormsg = NULL;
+   if (NULL != self->_errormsg_)
+       free(self->_errormsg_);
+   self->_errormsg_ = NULL;
 }
 
 
@@ -86,7 +93,7 @@ SOCK_Constructor(const ConnectionClass *conn)
            free(rv);
            return NULL;
        }
-       rv->errormsg = NULL;
+       rv->_errormsg_ = NULL;
        rv->errornumber = 0;
        rv->reverse = FALSE;
    }
@@ -129,6 +136,8 @@ SOCK_Destructor(SocketClass *self)
 
    if (self->buffer_out)
        free(self->buffer_out);
+   if (self->_errormsg_)
+       free(self->_errormsg_);
 
    free(self);
 }
@@ -144,6 +153,48 @@ static getaddrinfo_func getaddrinfo_ptr = getaddrinfo;
 static getnameinfo_func getnameinfo_ptr = getnameinfo;
 #endif /* _MSC_VER */
 
+static BOOL format_sockerr(char *errmsg, size_t buflen, int errnum, const char *cmd, const char *host, int portno)
+{
+   BOOL ret = FALSE;
+
+#ifdef WIN32
+   if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+       errnum, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
+       errmsg, (DWORD)buflen, NULL))
+       ret = TRUE;
+#else
+#if defined(POSIX_MULTITHREAD_SUPPORT) && defined(HAVE_STRERROR_R)
+#ifdef STRERROR_R_INT
+   if (0 == strerror_r(errnum, errmsg, buflen))
+       ret = TRUE;
+#else
+   const char *pchar;
+
+   pchar = (const char *) strerror_r(errnum, errmsg, buflen);
+   if (NULL != pchar)
+   {
+       if (pchar != errmsg)
+           strncpy(errmsg, pchar, buflen);
+       ret = TRUE;
+   }
+#endif /* STRERROR_R_INT */
+#else
+   strncpy(errmsg, strerror(errnum), buflen);
+   ret = TRUE;
+#endif /* POSIX_MULTITHREAD_SUPPORT */
+#endif /* WIN32 */
+   if (ret)
+   {
+       size_t  tlen = strlen(errmsg);
+       errmsg += tlen;
+       buflen -= tlen;
+       snprintf(errmsg, buflen, " [%s:%d]", host, portno);
+   }
+   else
+       snprintf(errmsg, buflen, "%s failed for [%s:%d] ", cmd, host, portno);
+   return ret;
+}
 char
 SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname, long timeout)
 {
@@ -326,9 +377,10 @@ retry:
            getnameinfo_ptr((struct sockaddr *) &(self->sadr_area),
                    self->sadr_len, host, sizeof(host),
                    NULL, 0, NI_NUMERICHOST);
-           snprintf(errmsg, sizeof(errmsg), "connect getsockopt val %d addr=%s\n", optval, host);
+           /* snprintf(errmsg, sizeof(errmsg), "connect getsockopt val %d addr=%s\n", optval, host); */
+           format_sockerr(errmsg, sizeof(errmsg), optval, "connect", host, port);
            mylog(errmsg);
-           SOCK_set_error(self, SOCKET_COULD_NOT_CONNECT, "Could not connect to remote server.");
+           SOCK_set_error(self, SOCKET_COULD_NOT_CONNECT, errmsg);
        }
        else
            retval = 1;
index d98ed0099b6e45b463c2d3dbf0a8869e1eaa5d87..69dbac0e5f09465fcc2b4de8d797ee26e94b9897 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -130,7 +130,7 @@ struct SocketClass_
    unsigned int    pversion;
    int     reslen;
 
-   char        *errormsg;
+   char        *_errormsg_;
    int     errornumber;
    int     sadr_len;
    struct sockaddr_storage sadr_area; /* Used for various connections */
@@ -150,7 +150,7 @@ struct SocketClass_
 
 /* error functions */
 #define SOCK_get_errcode(self) (self ? self->errornumber : SOCKET_CLOSED)
-#define SOCK_get_errmsg(self)  (self ? self->errormsg : "socket closed")
+#define SOCK_get_errmsg(self)  (self ? self->_errormsg_ : "socket closed")
 
 /*
  * code taken from postgres libpq et al.
index f5e0bd853208997e585ec19e493b2e011a10c032..b7529a3f155953f5c035f5901038d8b59b1ebb9e 100644 (file)
@@ -1075,6 +1075,7 @@ SC_create_errorinfo(const StatementClass *self)
    if (conn && !msgend)
    {
        SocketClass *sock = conn->sock;
+       const char *sockerrmsg;
 
        if (!resmsg && (wmsg = CC_get_errormsg(conn)) && wmsg[0] != '\0')
        {
@@ -1082,10 +1083,10 @@ SC_create_errorinfo(const StatementClass *self)
            snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", CC_get_errormsg(conn));
        }
 
-       if (sock && sock->errormsg && sock->errormsg[0] != '\0')
+       if (sock && NULL != (sockerrmsg = SOCK_get_errmsg(sock)) && '\0' != sockerrmsg[0])
        {
            pos = strlen(msg);
-           snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sock->errormsg);
+           snprintf(&msg[pos], sizeof(msg) - pos, ";\n%s", sockerrmsg);
        }
        ermsg = msg;
    }
index e2c42189da7e55cb94ee9f179b63116236059a9b..e39205c67007dc34ff51aa5c469fa1a6cb8f2bac 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,8 +9,8 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "08.02.0104"
-#define POSTGRES_RESOURCE_VERSION  "08.02.0104\0"
-#define PG_DRVFILE_VERSION     8,2,01,0
+#define POSTGRESDRIVERVERSION      "08.02.0105"
+#define POSTGRES_RESOURCE_VERSION  "08.02.0105\0"
+#define PG_DRVFILE_VERSION     8,2,01,05
 
 #endif
index b7aecba463abd4f4a3cfc40687ffd7b8262042b2..588f2c15596be9d1db9b7c3c09ae5607c374874c 100644 (file)
--- a/win32.mak
+++ b/win32.mak
@@ -200,7 +200,7 @@ BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc"
 BSC32_SBRS= \
    
 LINK32=link.exe
-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 XOleHlp.lib /nologo /dll
+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 XOleHlp.lib winmm.lib /nologo /dll
 !IF  "$(ANSI_VERSION)" == "yes"
 DEF_FILE= "psqlodbca.def"
 !ELSE