[7.3.0205]
authorHiroshi Inoue <inoue@tpf.co.jp>
Tue, 9 Dec 2003 10:01:38 +0000 (10:01 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Tue, 9 Dec 2003 10:01:38 +0000 (10:01 +0000)
(for *nix)
1. Detect -lsocket for some platforms.
2. Handle unix domain sockets.
3. EINTR safety for send/recv.
4. Set TCP_NDEALY option for inet connections.
    <1-4: thanks to Hartmut Raschick>
5. Use recursive mutex if possible.
6. Add descriptor.c to Makefile.
(for Windows)
7. Automatic setting of client encoding for latin1(9).
(common)
8. Avoid those notorious core dumps when logging on hitting
      "null" data...
    <8: thanls to Hartmut Raschick>
9. Removed a static varible for thread-safety.
10. Improve the performance of keyset-driven fetch operation.
11. Map (var)char type to SQL type more properly.
12. Change create_params for NUMERIC type to (precison, scale).
13. Add type cast to remove some compiler warnings.

32 files changed:
Makefile.am
bind.c
bind.h
configure.ac
connection.c
connection.h
convert.c
convert.h
descriptor.h
drvconn.c
environ.h
info.c
misc.c
multibyte.c
multibyte.h
odbcapi.c
odbcapi30.c
parse.c
pgapi30.c
pgtypes.c
pgtypes.h
psqlodbc.c
psqlodbc.h
qresult.c
qresult.h
results.c
socket.c
socket.h
statement.c
statement.h
version.h
win_unicode.c

index d14af97334bafc480670598998d67405ab6a331d..28fc87bf41b95689e0b58821ac7f3296aa2fb815 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile.am for psqlodbc (PostgreSQL ODBC driver)
 #
-# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.8 2003/05/15 15:53:13 dpage Exp $
+# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.9 2003/12/09 10:01:37 hinoue Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -18,7 +18,7 @@ psqlodbc_la_SOURCES = \
    pgtypes.c psqlodbc.c qresult.c results.c socket.c parse.c \
    statement.c tuple.c tuplelist.c dlg_specific.c odbcapi.c \
    multibyte.c \
-   gpps.c odbcapi30.c pgapi30.c info30.c
+   gpps.c odbcapi30.c pgapi30.c info30.c descriptor.c
 
 psqlodbc_la_SOURCES += \
    bind.h columninfo.h connection.h convert.h descriptor.h \
diff --git a/bind.c b/bind.c
index 550a1245de97d1b7a7c137402575a31d01c6c079..fe2168cb693e61f27d8617c185ce6fada7a7ee95 100644 (file)
--- a/bind.c
+++ b/bind.c
@@ -723,6 +723,13 @@ void   GDATA_unbind_cols(GetDataInfo *self, BOOL freeall)
    Int2    lf;
 
 inolog("GDATA_unbind_cols freeall=%d allocated=%d gdata=%x", freeall, self->allocated, self->gdata);
+   if (self->fdata.ttlbuf)
+   {
+       free(self->fdata.ttlbuf);
+       self->fdata.ttlbuf = NULL;
+   }
+   self->fdata.ttlbuflen = self->fdata.ttlbufused = 0;
+   self->fdata.data_left = -1;
    for (lf = 1; lf <= self->allocated; lf++)
        reset_a_getdata_info(self, lf);
    if (freeall)
@@ -736,6 +743,9 @@ inolog("GDATA_unbind_cols freeall=%d allocated=%d gdata=%x", freeall, self->allo
 
 void GetDataInfoInitialize(GetDataInfo *gdata_info)
 {
+   gdata_info->fdata.data_left = -1;
+   gdata_info->fdata.ttlbuf = NULL;
+   gdata_info->fdata.ttlbuflen = gdata_info->fdata.ttlbufused = 0;
    gdata_info->allocated = 0;
    gdata_info->gdata = NULL;
 }
diff --git a/bind.h b/bind.h
index 9fba18bc7a799b76de7c826c6fce9a78ace771c2..cd9fb0cda4c684dd7d5262688c1ae8be95781a94 100644 (file)
--- a/bind.h
+++ b/bind.h
@@ -75,6 +75,7 @@ struct ParameterImplClass_
 
 typedef struct
 {
+   GetDataClass    fdata;
    Int4        allocated;
    GetDataClass    *gdata;
 }  GetDataInfo;
index 377105682f6e9b14d75de8d17d586891a0bed39c..45251b39fe7ab9564d11fa4f18fe23410c7e84fa 100644 (file)
@@ -1,5 +1,5 @@
 # Process this file with autoconf to produce a configure script.
-AC_INIT(psqlodbc, 07.03.0200, [pgsql-odbc@postgresql.org])
+AC_INIT(psqlodbc, 07.03.0205, [pgsql-odbc@postgresql.org])
 AC_PREREQ(2.52)
 AM_INIT_AUTOMAKE
 AC_CONFIG_SRCDIR([bind.c])
@@ -38,6 +38,7 @@ AM_CONDITIONAL(with_unixodbc, [test $with_unixodbc = yes])
 AM_CONDITIONAL(with_iodbc, [test $with_iodbc = yes])
 
 AC_CHECK_FUNCS(strtoll)
+AC_CHECK_LIB(socket, socket)
 
 # to implement the thread-safe driver
 PGAC_ARG_BOOL(enable, pthreads, no,
@@ -47,7 +48,9 @@ PGAC_ARG_BOOL(enable, pthreads, no,
      AC_DEFINE(_REENTRANT, 1,
    [Define _REENTRANT for several plaforms])
      AC_CHECK_LIB(c_r, gethostbyname)
-     AC_CHECK_LIB(nsl, gethostbyname_r, [],
+     AC_CHECK_LIB(pthreads, pthread_create, [],
+       [AC_CHECK_LIB(pthread, pthread_create)])
+     AC_CHECK_LIB(nsl, gethostbyname_r, [AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, [])],
    [AC_CHECK_FUNCS(getipnodebyname gethostbyname_r, break)])
      if test x"$ac_cv_func_gethostbyname_r" = xyes || test x"$ac_cv_lib_nsl_gethostbyname_r" = xyes; then
    AC_TRY_COMPILE([#include <netdb.h>],
@@ -55,9 +58,15 @@ PGAC_ARG_BOOL(enable, pthreads, no,
         [AC_DEFINE(PGS_REENTRANT_API_1, 1, [Define if you have 5 parameter gethostbyname_r])],
         [AC_DEFINE(PGS_REENTRANT_API_2, 1, [Define if you have 6 parameter gethostbyname_r])])
      fi
-     AC_CHECK_FUNCS(localtime_r strtok_r)
-     AC_CHECK_LIB(pthreads, pthread_create, [],
-       [AC_CHECK_LIB(pthread, pthread_create)])
+     AC_CHECK_FUNCS(localtime_r strtok_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;],
+        [AC_DEFINE(PG_RECURSIVE_MUTEXATTR, PTHREAD_MUTEX_RECURSIVE, [Define if you have PTHREAD_MUTEX_RECURSIVE])], [
+   AC_TRY_COMPILE([#include <pthread.h>],
+   [ int i = PTHREAD_MUTEX_RECURSIVE_NP;],
+        [AC_DEFINE(PG_RECURSIVE_MUTEXATTR, PTHREAD_MUTEX_RECURSIVE_NP, [Define if you have PTHREAD_MUTEX_RECURSIVE_NP])])])
+     fi
     ])
 
 # Allow for overriding the default location of the odbcinst.ini
@@ -76,6 +85,7 @@ AC_LIBTOOL_DLOPEN
 AC_PROG_LIBTOOL
 
 AC_CHECK_HEADERS([locale.h])
+AC_CHECK_HEADERS([sys/un.h])
 AC_CHECK_TYPES(uint8)
 PGAC_VAR_INT_TIMEZONE
 
index 35b012579a55ae146b8592d1b2cad582ee1c79c2..c39fb54248d3150fbb84c249458a79b5386bf656 100644 (file)
@@ -707,7 +707,11 @@ CC_connect(ConnectionClass *self, char password_req, char *salt_para)
            return 0;
        }
 
-       if (ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\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;
@@ -1275,6 +1279,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                aborted = FALSE,
                used_passed_result_object = FALSE;
    UDWORD      abort_opt;
+   int     entered;
 
    /* ERROR_MSG_LENGTH is suffcient */
    char msgbuffer[ERROR_MSG_LENGTH + 1];
@@ -1310,13 +1315,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
        return NULL;
    }
 
-   ENTER_CONN_CS(self);
+   ENTER_INNER_CONN_CS(self, entered);
    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);
-       RETURN_AFTER_LEAVE_CS(self, NULL);
+       RETURN_AFTER_LEAVE_CS(entered, self, NULL);
    }
 
    if (issue_begin)
@@ -1328,14 +1333,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
    {
        CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       RETURN_AFTER_LEAVE_CS(self, NULL);
+       RETURN_AFTER_LEAVE_CS(entered, self, NULL);
    }
 
    mylog("send_query: done sending query\n");
 
    ReadyToReturn = FALSE;
    empty_reqs = 0;
-   for (wq = query; isspace((unsigned char) *wq); wq++)
+   for (wq = query; isspace((UCHAR) *wq); wq++)
        ;
    if (*wq == '\0')
        empty_reqs = 1;
@@ -1348,7 +1353,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
        if (!cmdres)
        {
            CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
-           RETURN_AFTER_LEAVE_CS(self, NULL);
+           RETURN_AFTER_LEAVE_CS(entered, self, NULL);
        }
    }
    res = cmdres;
@@ -1672,7 +1677,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
            }
        }
    }
-   RETURN_AFTER_LEAVE_CS(self, retres);
+   RETURN_AFTER_LEAVE_CS(entered, self, retres);
 }
 
 
@@ -2195,38 +2200,30 @@ CC_get_current_schema(ConnectionClass *conn)
 int
 CC_send_cancel_request(const ConnectionClass *conn)
 {
-#ifdef WIN32
-   int         save_errno = (WSAGetLastError());
-#else
-   int         save_errno = errno;
-#endif
+   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)
-       return FALSE;
-
-   if (conn->sock == NULL )
-   {
+   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(AF_INET, SOCK_STREAM, 0)) < 0)
+   if ((tmpsock = socket(conn->sock->sadr->sa_family, SOCK_STREAM, 0)) < 0)
    {
        return FALSE;
    }
-   if (connect(tmpsock, (struct sockaddr *)&(conn->sock->sadr),
-               sizeof(conn->sock->sadr)) < 0)
+   if (connect(tmpsock, conn->sock->sadr, conn->sock->sadr_len) < 0)
    {
+       closesocket(tmpsock);
        return FALSE;
    }
 
@@ -2240,15 +2237,13 @@ CC_send_cancel_request(const ConnectionClass *conn)
 
    if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
    {
-       return FALSE;
+       save_errno = SOCK_ERRNO;
+       ret = FALSE;
    }
 
    /* Sent it, done */
    closesocket(tmpsock);
-#ifdef WIN32
-   WSASetLastError(save_errno);
-#else
-   errno = save_errno;
-#endif
-   return TRUE;
+   SOCK_ERRNO_SET(save_errno);
+
+   return ret;
 }
index da0e9b4ed13655a2168a727e7f9d473b8c9ef8f6..f2e131760ac47e8486ada6f5186a0468c1d32b79 100644 (file)
@@ -90,22 +90,39 @@ typedef enum
 #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 = 1; }
 #define LEAVE_CONN_CS(x)   LeaveCriticalSection(&((x)->cs))
 #define DELETE_CONN_CS(x)  DeleteCriticalSection(&((x)->cs))
-#elif defined(POSIX_MULTITHREAD_SUPPORT)
+#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 = 1; \
+           else \
+               entered = -1; \
+       } \
+       else \
+           entered = 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) {entered = 0;}
 #define LEAVE_CONN_CS(x)
 #define DELETE_CONN_CS(x)
 #endif /* WIN_MULTITHREAD_SUPPORT */
 
-#define    RETURN_AFTER_LEAVE_CS(conn, ret) \
-   { LEAVE_CONN_CS(conn); return ret; }
+#define    LEAVE_INNER_CONN_CS(entered, conn) \
+   { if (entered > 0) LEAVE_CONN_CS(conn); }
+#define    RETURN_AFTER_LEAVE_CS(entered, conn, ret) \
+   { if (entered > 0) LEAVE_CONN_CS(conn); return ret; }
 
 /* Authentication types */
 #define AUTH_REQ_OK                                    0
@@ -340,8 +357,8 @@ struct ConnectionClass_
 #endif /* ODBCVER */
 #if defined(WIN_MULTITHREAD_SUPPORT)
    CRITICAL_SECTION    cs;
-#elif defined(POSIX_MULTITHREAD_SUPPORT)
-    pthread_mutex_t     cs;
+#elif defined(POSIX_THREADMUTEX_SUPPORT)
+   pthread_mutex_t     cs;
 #endif /* WIN_MULTITHREAD_SUPPORT */
 };
 
index 8e21b6b31fed715a7caf12f0b9d7c57f8209a2e6..c9e61bf08f02d857f34239db26e7a9def15efc17 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -132,9 +132,9 @@ char       *mapFuncs[][2] = {
 };
 
 static const char *mapFunction(const char *func, int param_count);
-static unsigned int conv_from_octal(const unsigned char *s);
-static unsigned int conv_from_hex(const unsigned char *s);
-static char *conv_to_octal(unsigned char val, char *octal);
+static unsigned int conv_from_octal(const UCHAR *s);
+static unsigned int conv_from_hex(const UCHAR *s);
+static char *conv_to_octal(UCHAR val, char *octal);
 static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);
 
 /*---------
@@ -224,7 +224,7 @@ timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)
            }
            for (i = 1; i < 10; i++)
            {
-               if (!isdigit((unsigned char) rest[i]))
+               if (!isdigit((UCHAR) rest[i]))
                    break;
            }
            for (; i < 10; i++)
@@ -355,6 +355,7 @@ copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *val
    BindInfoClass *bic = &(opts->bindings[col]);
    UInt4   offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
 
+   SC_set_current_col(stmt, -1);
    return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) (bic->buffer + offset),
                             (SDWORD) bic->buflen, (SDWORD *) (bic->used + (offset >> 2)));
 }
@@ -391,7 +392,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
    const char *neut_str = value;
    char        midtemp[2][32];
    int         mtemp_cnt = 0;
-   static GetDataClass sgdc;
    GetDataClass *pgdc;
 #ifdef UNICODE_SUPPORT
    BOOL    wchanged =   FALSE;
@@ -618,10 +618,10 @@ inolog("2stime fr=%d\n", std_time.fr);
                    nval++;
 
                    /* skip the current token */
-                   while ((*vp != '\0') && (!isspace((unsigned char) *vp)))
+                   while ((*vp != '\0') && (!isspace((UCHAR) *vp)))
                        vp++;
                    /* and skip the space to the next token */
-                   while ((*vp != '\0') && (isspace((unsigned char) *vp)))
+                   while ((*vp != '\0') && (isspace((UCHAR) *vp)))
                        vp++;
                    if (*vp == '\0')
                        break;
@@ -739,7 +739,7 @@ inolog("2stime fr=%d\n", std_time.fr);
            default:
                if (stmt->current_col < 0)
                {
-                   pgdc = &sgdc;
+                   pgdc = &(gdata->fdata);
                    pgdc->data_left = -1;
                }
                else
@@ -1266,7 +1266,7 @@ inolog("SQL_C_VARBOOKMARK value=%d\n", ival);
 
                if (stmt->current_col < 0)
                {
-                   pgdc = &sgdc;
+                   pgdc = &(gdata->fdata);
                    pgdc->data_left = -1;
                }
                else
@@ -1720,9 +1720,9 @@ into_table_from(const char *stmt)
    if (strnicmp(stmt, "into", 4))
        return FALSE;
    stmt += 4;
-   if (!isspace((unsigned char) *stmt))
+   if (!isspace((UCHAR) *stmt))
        return FALSE;
-   while (isspace((unsigned char) *(++stmt)));
+   while (isspace((UCHAR) *(++stmt)));
    switch (*stmt)
    {
        case '\0':
@@ -1735,21 +1735,21 @@ into_table_from(const char *stmt)
                do
                    while (*(++stmt) != '\"' && *stmt);
                while (*stmt && *(++stmt) == '\"');
-               while (*stmt && !isspace((unsigned char) *stmt) && *stmt != '\"')
+               while (*stmt && !isspace((UCHAR) *stmt) && *stmt != '\"')
                    stmt++;
            }
            while (*stmt == '\"');
            break;
        default:
-           while (!isspace((unsigned char) *(++stmt)));
+           while (!isspace((UCHAR) *(++stmt)));
            break;
    }
    if (!*stmt)
        return FALSE;
-   while (isspace((unsigned char) *(++stmt)));
+   while (isspace((UCHAR) *(++stmt)));
    if (strnicmp(stmt, "from", 4))
        return FALSE;
-   return isspace((unsigned char) stmt[4]);
+   return isspace((UCHAR) stmt[4]);
 }
 
 /*----------
@@ -1763,14 +1763,14 @@ table_for_update(const char *stmt, int *endpos)
 {
    const char *wstmt = stmt;
 
-   while (isspace((unsigned char) *(++wstmt)));
+   while (isspace((UCHAR) *(++wstmt)));
    if (!*wstmt)
        return FALSE;
    if (strnicmp(wstmt, "update", 6))
        return FALSE;
    wstmt += 6;
    *endpos = wstmt - stmt;
-   return !wstmt[0] || isspace((unsigned char) wstmt[0]);
+   return !wstmt[0] || isspace((UCHAR) wstmt[0]);
 }
 
 /*----------
@@ -1784,20 +1784,20 @@ insert_without_target(const char *stmt, int *endpos)
 {
    const char *wstmt = stmt;
 
-   while (isspace((unsigned char) *(++wstmt)));
+   while (isspace((UCHAR) *(++wstmt)));
    if (!*wstmt)
        return FALSE;
    if (strnicmp(wstmt, "VALUES", 6))
        return FALSE;
    wstmt += 6;
-   if (!wstmt[0] || !isspace((unsigned char) wstmt[0]))
+   if (!wstmt[0] || !isspace((UCHAR) wstmt[0]))
        return FALSE;
-   while (isspace((unsigned char) *(++wstmt)));
+   while (isspace((UCHAR) *(++wstmt)));
    if (*wstmt != '(' || *(++wstmt) != ')')
        return FALSE;
    wstmt++;
    *endpos = wstmt - stmt;
-   return !wstmt[0] || isspace((unsigned char) wstmt[0])
+   return !wstmt[0] || isspace((UCHAR) wstmt[0])
        || ';' == wstmt[0];
 }
 
@@ -2223,7 +2223,7 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
            qp->in_dquote = TRUE;
        else
        {
-           if (isspace((unsigned char) oldchar))
+           if (isspace((UCHAR) oldchar))
            {
                if (!qp->prev_token_end)
                {
@@ -2308,8 +2308,8 @@ ResolveNumericParam(const SQL_NUMERIC_STRUCT *ns, char *chrform)
 {
    static const int prec[] = {1, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 29, 32, 34, 37, 39};
    Int4    i, j, k, ival, vlen, len, newlen;
-   unsigned char       calv[40];
-   const unsigned char *val = (const unsigned char *) ns->val;
+   UCHAR       calv[40];
+   const UCHAR *val = (const UCHAR *) ns->val;
    BOOL    next_figure;
 
    if (0 == ns->precision)
@@ -3140,7 +3140,7 @@ convert_escape(QueryParse *qp, QueryBuild *qb)
    CSTR func = "convert_escape";
    RETCODE retval = SQL_SUCCESS;
    char        buf[1024], buf_small[128], key[65];
-   unsigned char   ucv;
+   UCHAR   ucv;
    UInt4       prtlen;
  
    if (F_OldChar(qp) == '{') /* skip the first { */
@@ -3160,16 +3160,16 @@ convert_escape(QueryParse *qp, QueryBuild *qb)
        if (F_OldChar(qp) == '?')
        {
            qb->param_number++;
-           while (isspace((unsigned char) qp->statement[++qp->opos]));
+           while (isspace((UCHAR) qp->statement[++qp->opos]));
            if (F_OldChar(qp) != '=')
            {
                F_OldPrior(qp);
                return SQL_SUCCESS;
            }
-           while (isspace((unsigned char) qp->statement[++qp->opos]));
+           while (isspace((UCHAR) qp->statement[++qp->opos]));
        }
        if (strnicmp(F_OldPtr(qp), "call", lit_call_len) ||
-           !isspace((unsigned char) F_OldPtr(qp)[lit_call_len]))
+           !isspace((UCHAR) F_OldPtr(qp)[lit_call_len]))
        {
            F_OldPrior(qp);
            return SQL_SUCCESS;
@@ -3562,7 +3562,7 @@ convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax)
 
 
 static unsigned int
-conv_from_octal(const unsigned char *s)
+conv_from_octal(const UCHAR *s)
 {
    int         i,
                y = 0;
@@ -3576,7 +3576,7 @@ conv_from_octal(const unsigned char *s)
 
 
 static unsigned int
-conv_from_hex(const unsigned char *s)
+conv_from_hex(const UCHAR *s)
 {
    int         i,
                y = 0,
@@ -3600,7 +3600,7 @@ conv_from_hex(const unsigned char *s)
 
 /* convert octal escapes to bytes */
 int
-convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax)
+convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax)
 {
    size_t      i,
                ilen = strlen(value);
@@ -3645,7 +3645,7 @@ convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int c
 
 
 static char *
-conv_to_octal(unsigned char val, char *octal)
+conv_to_octal(UCHAR val, char *octal)
 {
    int         i;
 
@@ -3665,7 +3665,7 @@ conv_to_octal(unsigned char val, char *octal)
 
 /* convert non-ascii bytes to octal escape sequences */
 int
-convert_to_pgbinary(const unsigned char *in, char *out, int len)
+convert_to_pgbinary(const UCHAR *in, char *out, int len)
 {
    int         i,
                o = 0;
@@ -3702,11 +3702,11 @@ encode(const char *in, char *out)
            sprintf(&out[o], "%%2B");
            o += 3;
        }
-       else if (isspace((unsigned char) in[i]))
+       else if (isspace((UCHAR) in[i]))
            out[o++] = '+';
-       else if (!isalnum((unsigned char) in[i]))
+       else if (!isalnum((UCHAR) in[i]))
        {
-           sprintf(&out[o], "%%%02x", (unsigned char) in[i]);
+           sprintf(&out[o], "%%%02x", (UCHAR) in[i]);
            o += 3;
        }
        else
index 9e6b4f77011215e00e99e7d142e45e0b183286ac..5788bbcfe7c9dd1dc07b516560d8ec8b75a87812 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -46,8 +46,8 @@ int           convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL
 int            convert_special_chars(const char *si, char *dst, int used, BOOL convlf,int ccsc);
 
 int            convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax);
-int            convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax);
-int            convert_to_pgbinary(const unsigned char *in, char *out, int len);
+int            convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax);
+int            convert_to_pgbinary(const UCHAR *in, char *out, int len);
 int        pg_hex2bin(const UCHAR *in, UCHAR *out, int len);
 void       encode(const char *in, char *out);
 void       decode(const char *in, char *out);
index f05cfcd87f874d278976faf0d8499a1ef5617b86..45aff330f171827069a6bdd58e10549bec864e64 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: descriptor.h,v 1.11 2003/10/25 04:19:19 hinoue Exp $
+ * $Id: descriptor.h,v 1.12 2003/12/09 10:01:37 hinoue Exp $
  *
  */
 
@@ -145,7 +145,7 @@ typedef struct
 
 void InitializeEmbeddedDescriptor(DescriptorClass *, StatementClass *stmt,
                UInt4 desc_type);
-void   DC_Destructor(desc);
+void   DC_Destructor(DescriptorClass *desc);
 void   InitializeARDFields(ARDFields *self);
 void   InitializeAPDFields(APDFields *self);
 /* void    InitializeIRDFields(IRDFields *self);
index 48f843bd7894b68c948615ee5f9a2a7092e0d7bb..0211eda93840a7f04976aeb464d46480d1ed63da 100644 (file)
--- a/drvconn.c
+++ b/drvconn.c
@@ -171,7 +171,9 @@ dialog:
 
            /* Password is not a required parameter. */
            if (ci->username[0] == '\0' ||
+#ifdef WIN32
                ci->server[0] == '\0' ||
+#endif /* WIN32 */
                ci->database[0] == '\0' ||
                ci->port[0] == '\0' ||
                password_required)
@@ -197,7 +199,9 @@ dialog:
     * Cancel to get out)
     */
    if (ci->username[0] == '\0' ||
+#ifdef WIN32
        ci->server[0] == '\0' ||
+#endif /* WIN32 */
        ci->database[0] == '\0' ||
        ci->port[0] == '\0')
    {
index 168763768c66748de7f0dfbfed215f42e60bfa69..7870ac5b5563b429aac8ff3611e698da8e261ae3 100644 (file)
--- a/environ.h
+++ b/environ.h
@@ -26,7 +26,7 @@ struct EnvironmentClass_
 #if defined(WIN_MULTITHREAD_SUPPORT)
    CRITICAL_SECTION    cs;
 #elif defined(POSIX_MULTITHREAD_SUPPORT)
-    pthread_mutex_t     cs;
+   pthread_mutex_t     cs;
 #endif /* WIN_MULTITHREAD_SUPPORT */
 };
 
diff --git a/info.c b/info.c
index 271a8cf3920bcec6a048b38fc89c447de27dcc72..107de759792393e2916cbc07e9edbed92f958e8a 100644 (file)
--- a/info.c
+++ b/info.c
@@ -898,7 +898,7 @@ inolog("serial in\n");
            set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
            set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
 #if (ODBCVER >=0x0300)
-           set_nullfield_int2(&row->tuple[15], pgtype_to_sqldesctype(stmt, pgType));
+           set_nullfield_int2(&row->tuple[15], pgtype_to_sqldesctype(stmt, pgType, PG_STATIC));
            set_nullfield_int2(&row->tuple[16], pgtype_to_datetime_sub(stmt, pgType));
            set_nullfield_int4(&row->tuple[17], pgtype_radix(stmt, pgType));
            set_nullfield_int4(&row->tuple[18], 0);
@@ -913,7 +913,7 @@ inolog("serial in\n");
    stmt->status = STMT_FINISHED;
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    return SQL_SUCCESS;
 }
@@ -1626,7 +1626,7 @@ PGAPI_Tables(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
    mylog("%s: EXIT,  stmt=%u\n", func, stmt);
@@ -2023,7 +2023,7 @@ PGAPI_Columns(
                set_tuplefield_string(&row->tuple[1], "");
            set_tuplefield_string(&row->tuple[2], table_name);
            set_tuplefield_string(&row->tuple[3], "oid");
-           sqltype = pgtype_to_concise_type(stmt, the_type);
+           sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
            set_tuplefield_int2(&row->tuple[4], sqltype);
            set_tuplefield_string(&row->tuple[5], "OID");
 
@@ -2056,6 +2056,7 @@ PGAPI_Columns(
                                   (result_cols - 1) *sizeof(TupleField));
 
 
+       sqltype = SQL_TYPE_NULL;    /* unspecified */
        set_tuplefield_string(&row->tuple[0], "");
        /* see note in SQLTables() */
        if (conn->schema_support)
@@ -2064,7 +2065,7 @@ PGAPI_Columns(
            set_tuplefield_string(&row->tuple[1], "");
        set_tuplefield_string(&row->tuple[2], table_name);
        set_tuplefield_string(&row->tuple[3], field_name);
-       sqltype = pgtype_to_concise_type(stmt, field_type);
+       sqltype = pgtype_to_concise_type(stmt, field_type, -1);
        set_tuplefield_int2(&row->tuple[4], sqltype);
        set_tuplefield_string(&row->tuple[5], field_type_name);
 
@@ -2119,14 +2120,20 @@ PGAPI_Columns(
            if (mod_length >= 4)
                mod_length -= 4;    /* the length is in atttypmod - 4 */
 
-           if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0)
+           /* if (mod_length > ci->drivers.max_varchar_size || mod_length <= 0) */
+           if (mod_length <= 0)
                mod_length = ci->drivers.max_varchar_size;
+           if (mod_length > ci->drivers.max_varchar_size)
+               sqltype = SQL_LONGVARCHAR;
+           else
+               sqltype = (field_type == PG_TYPE_BPCHAR) ? SQL_CHAR : SQL_VARCHAR;
 
            mylog("%s: field type is VARCHAR,BPCHAR: field_type = %d, mod_length = %d\n", func, field_type, mod_length);
 
            set_tuplefield_int4(&row->tuple[6], mod_length);
            set_tuplefield_int4(&row->tuple[7], mod_length);
            set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
+           set_tuplefield_int2(&row->tuple[13], sqltype);
 #if (ODBCVER >= 0x0300)
            set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, field_type, PG_STATIC, PG_STATIC));
 #endif /* ODBCVER */
@@ -2146,12 +2153,18 @@ PGAPI_Columns(
            set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
        }
 
+       if (SQL_TYPE_NULL == sqltype)
+       {
+           sqltype = pgtype_to_concise_type(stmt, field_type, PG_STATIC);
+           set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type, PG_STATIC));
+       }
+       set_tuplefield_int2(&row->tuple[4], sqltype);
+
        set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
        set_tuplefield_int2(&row->tuple[10], (Int2) (not_null[0] == '1' ? SQL_NO_NULLS : pgtype_nullable(stmt, field_type)));
        set_tuplefield_string(&row->tuple[11], "");
 #if (ODBCVER >= 0x0300)
        set_tuplefield_null(&row->tuple[12]);
-       set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type));
        set_nullfield_int2(&row->tuple[14], pgtype_to_datetime_sub(stmt, field_type));
        set_tuplefield_int4(&row->tuple[16], ordinal);
        set_tuplefield_null(&row->tuple[17]);
@@ -2191,7 +2204,7 @@ PGAPI_Columns(
            set_tuplefield_string(&row->tuple[1], "");
        set_tuplefield_string(&row->tuple[2], table_name);
        set_tuplefield_string(&row->tuple[3], "xmin");
-       sqltype = pgtype_to_concise_type(stmt, the_type);
+       sqltype = pgtype_to_concise_type(stmt, the_type, PG_STATIC);
        set_tuplefield_int2(&row->tuple[4], sqltype);
        set_tuplefield_string(&row->tuple[5], pgtype_to_name(stmt, the_type));
        set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
@@ -2224,7 +2237,7 @@ PGAPI_Columns(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
    mylog("%s: EXIT,  stmt=%u\n", func, stmt);
@@ -2384,7 +2397,7 @@ PGAPI_SpecialColumns(
 
            set_tuplefield_null(&row->tuple[0]);
            set_tuplefield_string(&row->tuple[1], "ctid");
-           set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type));
+           set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
            set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
            set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
@@ -2406,7 +2419,7 @@ inolog("Add ctid\n");
 
            set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION);
            set_tuplefield_string(&row->tuple[1], "oid");
-           set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, PG_TYPE_OID));
+           set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, PG_TYPE_OID, PG_STATIC));
            set_tuplefield_string(&row->tuple[3], "OID");
            set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, PG_TYPE_OID, PG_STATIC, PG_STATIC));
@@ -2426,7 +2439,7 @@ inolog("Add ctid\n");
 
                set_tuplefield_null(&row->tuple[0]);
                set_tuplefield_string(&row->tuple[1], "xmin");
-               set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type));
+               set_tuplefield_int2(&row->tuple[2], pgtype_to_concise_type(stmt, the_type, PG_STATIC));
                set_tuplefield_string(&row->tuple[3], pgtype_to_name(stmt, the_type));
                set_tuplefield_int4(&row->tuple[4], pgtype_column_size(stmt, the_type, PG_STATIC, PG_STATIC));
                set_tuplefield_int4(&row->tuple[5], pgtype_buffer_length(stmt, the_type, PG_STATIC, PG_STATIC));
@@ -2441,7 +2454,7 @@ inolog("Add ctid\n");
    stmt->status = STMT_FINISHED;
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    mylog("%s: EXIT,  stmt=%u\n", func, stmt);
    return SQL_SUCCESS;
@@ -2862,7 +2875,7 @@ PGAPI_Statistics(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    error = FALSE;
 
@@ -3153,7 +3166,7 @@ PGAPI_PrimaryKeys(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    mylog("%s: EXIT, stmt=%u\n", func, stmt);
    return SQL_SUCCESS;
@@ -3166,7 +3179,7 @@ PGAPI_PrimaryKeys(
  * future version. The way is very forcible currently.
  */
 static BOOL
-isMultibyte(const unsigned char *str)
+isMultibyte(const UCHAR *str)
 {
    for (; *str; str++)
    {
@@ -3509,7 +3522,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
 
    result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
@@ -4368,7 +4381,7 @@ PGAPI_ProcedureColumns(
            set_tuplefield_string(&row->tuple[2], procname);
            set_tuplefield_string(&row->tuple[3], "");
            set_tuplefield_int2(&row->tuple[4], SQL_RETURN_VALUE);
-           set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype));
+           set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype, PG_STATIC));
            set_tuplefield_string(&row->tuple[6], pgtype_to_name(stmt, pgtype));
            set_nullfield_int4(&row->tuple[7], pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[8], pgtype_buffer_length(stmt, pgtype, PG_STATIC, PG_STATIC));
@@ -4378,7 +4391,7 @@ PGAPI_ProcedureColumns(
            set_tuplefield_null(&row->tuple[12]);
 #if (ODBCVER >= 0x0300)
            set_tuplefield_null(&row->tuple[13]);
-           set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype));
+           set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype, PG_STATIC));
            set_nullfield_int2(&row->tuple[15], pgtype_to_datetime_sub(stmt, pgtype));
            set_nullfield_int4(&row->tuple[16], pgtype_transfer_octet_length(stmt, pgtype, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[17], 0);
@@ -4399,7 +4412,7 @@ PGAPI_ProcedureColumns(
            set_tuplefield_string(&row->tuple[2], procname);
            set_tuplefield_string(&row->tuple[3], "");
            set_tuplefield_int2(&row->tuple[4], SQL_PARAM_INPUT);
-           set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype));
+           set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype, PG_STATIC));
            set_tuplefield_string(&row->tuple[6], pgtype_to_name(stmt, pgtype));
            set_nullfield_int4(&row->tuple[7], pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[8], pgtype_buffer_length(stmt, pgtype, PG_STATIC, PG_STATIC));
@@ -4409,7 +4422,7 @@ PGAPI_ProcedureColumns(
            set_tuplefield_null(&row->tuple[12]);
 #if (ODBCVER >= 0x0300)
            set_tuplefield_null(&row->tuple[13]);
-           set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype));
+           set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype, PG_STATIC));
            set_nullfield_int2(&row->tuple[15], pgtype_to_datetime_sub(stmt, pgtype));
            set_nullfield_int4(&row->tuple[16], pgtype_transfer_octet_length(stmt, pgtype, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[17], j + 1);
@@ -4429,7 +4442,7 @@ PGAPI_ProcedureColumns(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    return SQL_SUCCESS;
 }
@@ -4506,7 +4519,7 @@ PGAPI_Procedures(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
 
    return SQL_SUCCESS;
 }
@@ -4615,7 +4628,7 @@ PGAPI_TablePrivileges(
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
-   stmt->current_col = -1;
+   SC_set_current_col(stmt, -1);
    if (conn->schema_support)
        strncpy_null(proc_query, "select relname, usename, relacl, nspname"
        " from pg_catalog.pg_namespace, pg_catalog.pg_class ,"
diff --git a/misc.c b/misc.c
index bd835a2ace01817dd7f587e260deeb1bed3aa078..96cc94a4927e5dd65dd1a37a5c30d153a420599d 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -136,8 +136,8 @@ mylog(char *fmt,...)
 #endif /* WIN32 */
 #endif /* WIN_MULTITHREAD_SUPPORT */
 #if defined(POSIX_MULTITHREAD_SUPPORT)
-        if (LOGFP)
-            fprintf(LOGFP, "[%d]", pthread_self());
+       if (LOGFP)
+           fprintf(LOGFP, "[%d]", pthread_self());
 #endif /* POSIX_MULTITHREAD_SUPPORT */
        if (LOGFP)
            vfprintf(LOGFP, fmt, args);
index 8b2c4f2ad9d01a7e3734aca6a6d62e75d3139f2a..467806db1b230c61ecb0748e8e6b894c1bbdb804 100644 (file)
@@ -75,7 +75,7 @@ pg_ismb(int characterset_code)
 #endif
 
 int
-pg_CS_code(const unsigned char *characterset_string)
+pg_CS_code(const UCHAR *characterset_string)
 {
    int i = 0, c = -1;
    unsigned len = 0;
@@ -96,7 +96,7 @@ pg_CS_code(const unsigned char *characterset_string)
    return (c);
 }
 
-unsigned char *
+UCHAR *
 pg_CS_name(int characterset_code)
 {
    int i;
@@ -273,30 +273,30 @@ pg_CS_stat(int stat,unsigned int character,int characterset_code)
 }
 
 
-unsigned char *
-pg_mbschr(int csc, const unsigned char *string, unsigned int character)
+UCHAR *
+pg_mbschr(int csc, const UCHAR *string, unsigned int character)
 {
    int         mb_st = 0;
-   const unsigned char *s, *rs = NULL;
+   const UCHAR *s, *rs = NULL;
 
    for(s = string; *s ; s++) 
    {
-       mb_st = pg_CS_stat(mb_st, (unsigned char) *s, csc);
+       mb_st = pg_CS_stat(mb_st, (UCHAR) *s, csc);
        if (mb_st == 0 && (*s == character))
        {
            rs = s;
            break;
        }
    }
-   return ((unsigned char *) rs);
+   return ((UCHAR *) rs);
 }
 
 int
-pg_mbslen(int csc, const unsigned char *string)
+pg_mbslen(int csc, const UCHAR *string)
 {
-   unsigned char *s;
+   UCHAR *s;
    int len, cs_stat;
-   for (len = 0, cs_stat = 0, s = (unsigned char *) string; *s != 0; s++)
+   for (len = 0, cs_stat = 0, s = (UCHAR *) string; *s != 0; s++)
    {
        cs_stat = pg_CS_stat(cs_stat,(unsigned int) *s, csc);
        if (cs_stat < 2)
@@ -305,8 +305,8 @@ pg_mbslen(int csc, const unsigned char *string)
    return len;
 }
 
-unsigned char *
-pg_mbsinc(int csc, const unsigned char *current )
+UCHAR *
+pg_mbsinc(int csc, const UCHAR *current )
 {
    int mb_stat = 0;
    if (*current != 0)
@@ -314,7 +314,7 @@ pg_mbsinc(int csc, const unsigned char *current )
        mb_stat = (int) pg_CS_stat(mb_stat, *current, csc);
        if (mb_stat == 0)
            mb_stat = 1;
-       return ((unsigned char *) current + mb_stat);
+       return ((UCHAR *) current + mb_stat);
    }
    else
        return NULL;
@@ -397,6 +397,12 @@ CC_lookup_characterset(ConnectionClass *self)
            case 950:
                wenc = "BIG5";
                break;
+           case 1252:
+               if (PG_VERSION_GE(self, 7.2))
+                   wenc = "latin9";
+               else
+                   wenc = "latin1";
+               break;
        }
        if (wenc && (!encstr || stricmp(encstr, wenc)))
        {
index 3d9d6621460e02ddd7f288444fd5952ce0bd6c4e..ca965215c1056268af58bb2d0bfb11a90596a123 100644 (file)
 extern void CC_lookup_characterset(ConnectionClass *self);
 
 extern int pg_CS_stat(int stat,unsigned int charcter,int characterset_code);
-extern int pg_CS_code(const unsigned char *stat_string);
-extern unsigned char *pg_CS_name(int code);
+extern int pg_CS_code(const UCHAR *stat_string);
+extern UCHAR *pg_CS_name(int code);
 
 typedef struct pg_CS
 {
-   unsigned char *name;
+   UCHAR *name;
    int code;
 }pg_CS;
-extern int pg_mbslen(int ccsc, const unsigned char *string);
-extern unsigned char *pg_mbschr(int ccsc, const unsigned char *string, unsigned int character);
-extern unsigned char *pg_mbsinc(int ccsc, const unsigned char *current );
+extern int pg_mbslen(int ccsc, const UCHAR *string);
+extern UCHAR *pg_mbschr(int ccsc, const UCHAR *string, unsigned int character);
+extern UCHAR *pg_mbsinc(int ccsc, const UCHAR *current );
 
 /* Old Type Compatible */
 typedef struct
 {
    int ccsc;
-   const unsigned char *encstr;
+   const UCHAR *encstr;
    int pos;
    int ccst;
 } encoded_str;
index 2d1d75a68eebb3d55ca6b16cbdd07f076e3b6b87..a760c105d743a45e22338cbfa7ef59bb3e85924f 100644 (file)
--- a/odbcapi.c
+++ b/odbcapi.c
@@ -346,7 +346,7 @@ SQLFetch(HSTMT StatementHandle)
        IRDFields   *irdopts = SC_get_IRDF(stmt);
        ARDFields   *ardopts = SC_get_ARDF(stmt);
        SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
-       SQLINTEGER *pcRow = irdopts->rowsFetched;
+       SQLINTEGER *pcRow = (SQLINTEGER *) irdopts->rowsFetched;
 
        mylog("[[%s]]", func);
        ret = PGAPI_ExtendedFetch(StatementHandle, SQL_FETCH_NEXT, 0,
index 9f98baec8739729376d09fe41db797577206bc5e..ccf25f5bab848ec85932e14f966cf6fb94ee3ecd 100644 (file)
@@ -170,7 +170,7 @@ SQLFetchScroll(HSTMT StatementHandle,
    RETCODE     ret = SQL_SUCCESS;
    IRDFields   *irdopts = SC_get_IRDF(stmt);
    SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
-   SQLINTEGER *pcRow = irdopts->rowsFetched, bkmarkoff = 0;
+   SQLINTEGER *pcRow = (SQLINTEGER *) irdopts->rowsFetched, bkmarkoff = 0;
 
    mylog("[[%s]] %d,%d\n", func, FetchOrientation, FetchOffset);
    ENTER_STMT_CS(stmt);
diff --git a/parse.c b/parse.c
index 559043b696bdb0be7c18a86060d4640fa3a69644..03226fbfa0775e1efa0cbeedff85467d2fe7c4f3 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -85,7 +85,7 @@ getNextToken(
    smax--;
 
    /* skip leading delimiters */
-   while (isspace((unsigned char) s[i]) || s[i] == ',')
+   while (isspace((UCHAR) s[i]) || s[i] == ',')
    {
        /* mylog("skipping '%c'\n", s[i]); */
        i++;
@@ -114,7 +114,7 @@ getNextToken(
            token[out++] = s[i++];
            continue;
        }
-       if (isspace((unsigned char) s[i]) || s[i] == ',')
+       if (isspace((UCHAR) s[i]) || s[i] == ',')
            break;
        /* Handle quoted stuff */
        if (out == 0 && (s[i] == '\"' || s[i] == '\''))
@@ -157,18 +157,18 @@ getNextToken(
        }
 
        /* Check for numeric literals */
-       if (out == 0 && isdigit((unsigned char) s[i]))
+       if (out == 0 && isdigit((UCHAR) s[i]))
        {
            if (numeric)
                *numeric = TRUE;
            token[out++] = s[i++];
-           while (isalnum((unsigned char) s[i]) || s[i] == '.')
+           while (isalnum((UCHAR) s[i]) || s[i] == '.')
                token[out++] = s[i++];
 
            break;
        }
 
-       if (ispunct((unsigned char) s[i]) && s[i] != '_')
+       if (ispunct((UCHAR) s[i]) && s[i] != '_')
        {
            mylog("got ispunct: s[%d] = '%c'\n", i, s[i]);
 
@@ -192,7 +192,7 @@ getNextToken(
    token[out] = '\0';
 
    /* find the delimiter  */
-   while (isspace((unsigned char) s[i]))
+   while (isspace((UCHAR) s[i]))
        i++;
 
    /* return the most priority delimiter */
@@ -213,7 +213,7 @@ getNextToken(
    }
 
    /* skip trailing blanks  */
-   while (isspace((unsigned char) s[i]))
+   while (isspace((UCHAR) s[i]))
        i++;
 
    return &s[i];
@@ -310,7 +310,7 @@ void lower_the_name(char *name, ConnectionClass *conn, BOOL dquote)
        {
            encoded_nextchar(&encstr);
            if (ENCODE_STATUS(encstr) == 0)
-               *ptr = tolower((unsigned char) *ptr);
+               *ptr = tolower((UCHAR) *ptr);
        }
    }
 }
index 43e4e38fb3a95fc80a841ba3175d44e60aa4a343..32c5a8df79476048e0afb4c1a3f211a7ed6addb6 100644 (file)
--- a/pgapi30.c
+++ b/pgapi30.c
@@ -727,7 +727,7 @@ IRDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            opts->rowStatusArray = (SQLUSMALLINT *) Value;
            break;
        case SQL_DESC_ROWS_PROCESSED_PTR:
-           opts->rowsFetched = (SQLUINTEGER *) Value;
+           opts->rowsFetched = (UInt4 *) Value;
            break;
        case SQL_DESC_ALLOC_TYPE: /* read-only */
        case SQL_DESC_COUNT: /* read-only */
@@ -784,7 +784,7 @@ IPDSetField(DescriptorClass *desc, SQLSMALLINT RecNumber,
            ipdopts->param_status_ptr = (SQLUSMALLINT *) Value;
            return ret;
        case SQL_DESC_ROWS_PROCESSED_PTR:
-           ipdopts->param_processed_ptr = (SQLUINTEGER *) Value;
+           ipdopts->param_processed_ptr = (UInt4 *) Value;
            return ret;
        case SQL_DESC_UNNAMED: /* only SQL_UNNAMED is allowed */ 
            if (SQL_UNNAMED !=  (SQLUINTEGER) Value)
@@ -1416,7 +1416,7 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
            len = 4;
            break;
        case SQL_ATTR_PARAM_BIND_OFFSET_PTR:    /* 17 */
-           *((SQLUINTEGER **) Value) = SC_get_APDF(stmt)->param_offset_ptr;
+           *((SQLUINTEGER **) Value) = (SQLUINTEGER *) SC_get_APDF(stmt)->param_offset_ptr;
            len = 4;
            break;
        case SQL_ATTR_PARAM_BIND_TYPE:  /* 18 */
@@ -1432,7 +1432,7 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
            len = 4;
            break;
        case SQL_ATTR_PARAMS_PROCESSED_PTR:     /* 21 */
-           *((SQLUINTEGER **) Value) = SC_get_IPDF(stmt)->param_processed_ptr;
+           *((SQLUINTEGER **) Value) = (SQLUINTEGER *) SC_get_IPDF(stmt)->param_processed_ptr;
            len = 4;
            break;
        case SQL_ATTR_PARAMSET_SIZE:    /* 22 */
@@ -1440,7 +1440,7 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
            len = 4;
            break;
        case SQL_ATTR_ROW_BIND_OFFSET_PTR:      /* 23 */
-           *((SQLUINTEGER **) Value) = SC_get_ARDF(stmt)->row_offset_ptr;
+           *((SQLUINTEGER **) Value) = (SQLUINTEGER *) SC_get_ARDF(stmt)->row_offset_ptr;
            len = 4;
            break;
        case SQL_ATTR_ROW_OPERATION_PTR:        /* 24 */
@@ -1452,7 +1452,7 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
            len = 4;
            break;
        case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
-           *((SQLUINTEGER **) Value) = SC_get_IRDF(stmt)->rowsFetched;
+           *((SQLUINTEGER **) Value) = (SQLUINTEGER *) SC_get_IRDF(stmt)->rowsFetched;
            len = 4;
            break;
        case SQL_ATTR_ROW_ARRAY_SIZE:   /* 27 */
@@ -1686,7 +1686,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
            stmt->options.bookmark_ptr = Value;
            break;
        case SQL_ATTR_PARAM_BIND_OFFSET_PTR:    /* 17 */
-           SC_get_APDF(stmt)->param_offset_ptr = (SQLUINTEGER *) Value;
+           SC_get_APDF(stmt)->param_offset_ptr = (UInt4 *) Value;
            break;
        case SQL_ATTR_PARAM_BIND_TYPE:  /* 18 */
            SC_get_APDF(stmt)->param_bind_type = (SQLUINTEGER) Value;
@@ -1698,13 +1698,13 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
            SC_get_IPDF(stmt)->param_status_ptr = (SQLUSMALLINT *) Value;
            break;
        case SQL_ATTR_PARAMS_PROCESSED_PTR:     /* 21 */
-           SC_get_IPDF(stmt)->param_processed_ptr = (SQLUINTEGER *) Value;
+           SC_get_IPDF(stmt)->param_processed_ptr = (UInt4 *) Value;
            break;
        case SQL_ATTR_PARAMSET_SIZE:    /* 22 */
            SC_get_APDF(stmt)->paramset_size = (SQLUINTEGER) Value;
            break;
        case SQL_ATTR_ROW_BIND_OFFSET_PTR:      /* 23 */
-           SC_get_ARDF(stmt)->row_offset_ptr = (SQLUINTEGER *) Value;
+           SC_get_ARDF(stmt)->row_offset_ptr = (UInt4 *) Value;
            break;
        case SQL_ATTR_ROW_OPERATION_PTR:        /* 24 */
            SC_get_ARDF(stmt)->row_operation_ptr = Value;
@@ -1713,7 +1713,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
            SC_get_IRDF(stmt)->rowStatusArray = (SQLUSMALLINT *) Value;
            break;
        case SQL_ATTR_ROWS_FETCHED_PTR: /* 26 */
-           SC_get_IRDF(stmt)->rowsFetched = (SQLUINTEGER *) Value;
+           SC_get_IRDF(stmt)->rowsFetched = (UInt4 *) Value;
            break;
        case SQL_ATTR_ROW_ARRAY_SIZE:   /* 27 */
            SC_get_ARDF(stmt)->size_of_rowset = (SQLUINTEGER) Value;
@@ -1741,9 +1741,10 @@ typedef struct
 }  bop_cdata;
 
 static 
-RETCODE    bulk_ope_callback(RETCODE retcode, bop_cdata *s)
+RETCODE    bulk_ope_callback(RETCODE retcode, void *para)
 {
    RETCODE ret = retcode;
+   bop_cdata *s = (bop_cdata *) para;
    UInt4       offset, bind_size, global_idx;
    ConnectionClass *conn;
    QResultClass    *res;
index b39ff01b1466ca575f08ca2160b896fe71caf05a..ca634de68e4e3ceb64c33c191d99378341257fea 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
@@ -66,6 +66,7 @@ Int4 pgtypes_defined[]    = {
                PG_TYPE_MONEY,
                PG_TYPE_BOOL,
                PG_TYPE_BYTEA,
+               PG_TYPE_NUMERIC,
                PG_TYPE_LO_UNDEFINED,
                0 };
 */
@@ -243,7 +244,7 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
  * types that are unknown.  All other pg routines in here return a suitable default.
  */
 Int2
-pgtype_to_concise_type(StatementClass *stmt, Int4 type)
+pgtype_to_concise_type(StatementClass *stmt, Int4 type, int col)
 {
    ConnectionClass *conn = SC_get_conn(stmt);
    ConnInfo    *ci = &(conn->connInfo);
@@ -262,9 +263,15 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type)
 
 #ifdef UNICODE_SUPPORT
        case PG_TYPE_BPCHAR:
+           if (col >= 0 &&
+               getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
+               return conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR;
            return conn->unicode ? SQL_WCHAR : SQL_CHAR;
 
        case PG_TYPE_VARCHAR:
+           if (col >= 0 &&
+               getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
+               return conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR;
            return conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR;
 
        case PG_TYPE_TEXT:
@@ -274,9 +281,15 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type)
 
 #else
        case PG_TYPE_BPCHAR:
+           if (col >= 0 &&
+               getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
+               return SQL_LONGVARCHAR;
            return SQL_CHAR;
 
        case PG_TYPE_VARCHAR:
+           if (col >= 0 &&
+               getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
+               return SQL_LONGVARCHAR;
            return SQL_VARCHAR;
 
        case PG_TYPE_TEXT:
@@ -360,11 +373,11 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type)
 }
 
 Int2
-pgtype_to_sqldesctype(StatementClass *stmt, Int4 type)
+pgtype_to_sqldesctype(StatementClass *stmt, Int4 type, int col)
 {
    Int2    rettype;
 
-   switch (rettype = pgtype_to_concise_type(stmt, type))
+   switch (rettype = pgtype_to_concise_type(stmt, type, col))
    {
 #if (ODBCVER >= 0x0300)
        case SQL_TYPE_DATE:
@@ -379,7 +392,7 @@ pgtype_to_sqldesctype(StatementClass *stmt, Int4 type)
 Int2
 pgtype_to_datetime_sub(StatementClass *stmt, Int4 type)
 {
-   switch (pgtype_to_concise_type(stmt, type))
+   switch (pgtype_to_concise_type(stmt, type, PG_STATIC))
    {
 #if (ODBCVER >= 0x0300)
        case SQL_TYPE_DATE:
@@ -489,11 +502,11 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
        case PG_TYPE_INT8:
            return "int8";
        case PG_TYPE_NUMERIC:
-           return "numeric";
+           return "numeric()";
        case PG_TYPE_VARCHAR:
-           return "varchar";
+           return "varchar()";
        case PG_TYPE_BPCHAR:
-           return "char";
+           return "char()";
        case PG_TYPE_TEXT:
            return "text";
        case PG_TYPE_NAME:
@@ -515,10 +528,12 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
        case PG_TYPE_ABSTIME:
            return "abstime";
        case PG_TYPE_DATETIME:
-           if (PG_VERSION_GE(conn, 7.0))
-               return "timestamp with time zone";
-           else
+           if (PG_VERSION_GT(conn, 7.1))
+               return "timestamptz";
+           else if (PG_VERSION_LT(conn, 7.0))
                return "datetime";
+           else
+               return "timestamp";
        case PG_TYPE_TIMESTAMP_NO_TMZONE:
            return "timestamp without time zone";
        case PG_TYPE_TIMESTAMP:
@@ -1352,6 +1367,8 @@ pgtype_create_params(StatementClass *stmt, Int4 type)
        case PG_TYPE_BPCHAR:
        case PG_TYPE_VARCHAR:
            return "max. length";
+       case PG_TYPE_NUMERIC:
+           return "precision, scale";
        default:
            return NULL;
    }
index 20e0c4e5977b3203b2bcce4ccc3ba7fee94566ec..1148cb5fc58bc1815e2dba9a65ac22c40d9e647f 100644 (file)
--- a/pgtypes.h
+++ b/pgtypes.h
@@ -73,8 +73,8 @@ extern Int2 sqlTypes[];
 
 Int4       sqltype_to_pgtype(StatementClass *stmt, Int2 fSqlType);
 
-Int2       pgtype_to_concise_type(StatementClass *stmt, Int4 type);
-Int2       pgtype_to_sqldesctype(StatementClass *stmt, Int4 type);
+Int2       pgtype_to_concise_type(StatementClass *stmt, Int4 type, int col);
+Int2       pgtype_to_sqldesctype(StatementClass *stmt, Int4 type, int col);
 Int2       pgtype_to_datetime_sub(StatementClass *stmt, Int4 type);
 Int2       pgtype_to_ctype(StatementClass *stmt, Int4 type);
 const char *pgtype_to_name(StatementClass *stmt, Int4 type);
index 67acb213d686c0a15e530867da6f748beb390a41..b019e37af244de33244bb1f8e8624c3266512df2 100644 (file)
@@ -29,8 +29,11 @@ RETCODE SQL_API SQLDummyOrdinal(void);
 extern CRITICAL_SECTION    qlog_cs, mylog_cs, conns_cs;
 #elif defined(POSIX_MULTITHREAD_SUPPORT)
 extern pthread_mutex_t     qlog_cs, mylog_cs, conns_cs;
+
+#ifdef POSIX_THREADMUTEX_SUPPORT
+#ifdef PG_RECURSIVE_MUTEXATTR
 static pthread_mutexattr_t recur_attr;
-const pthread_mutexattr_t* getMutexAttr(void)
+const  pthread_mutexattr_t*    getMutexAttr(void)
 {
    static int  init = 1;
 
@@ -38,13 +41,20 @@ const pthread_mutexattr_t*  getMutexAttr(void)
    {
        if (0 != pthread_mutexattr_init(&recur_attr))
            return NULL;
-       if (0 != pthread_mutexattr_settype(&recur_attr, PTHREAD_MUTEX_RECURSIVE_NP))
+       if (0 != pthread_mutexattr_settype(&recur_attr, PG_RECURSIVE_MUTEXATTR))
            return NULL;
    }
    init = 0;
 
    return  &recur_attr;
 }
+#else
+const  pthread_mutexattr_t*    getMutexAttr(void)
+{
+   return NULL;
+}
+#endif /* PG_RECURSIVE_MUTEXATTR */
+#endif /* POSIX_THREADMUTEX_SUPPORT */
 #endif /* WIN_MULTITHREAD_SUPPORT */
 
 int    initialize_global_cs(void)
@@ -54,9 +64,9 @@ int   initialize_global_cs(void)
    if (!init)
        return 0;
    init = 0;
-#ifdef POSIX_MULTITHREAD_SUPPORT
+#ifdef POSIX_THREADMUTEX_SUPPORT
    getMutexAttr();
-#endif /* POSIX_MULTITHREAD_SUPPORT */
+#endif /* POSIX_THREADMUTEX_SUPPORT */
    INIT_QLOG_CS;
    INIT_MYLOG_CS;
    INIT_CONNS_CS;
index 1538625ad00160691320413053b9b1c7a138b354..2448ef860fbde17e17c6505277ed5b1245884185 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.80 2003/11/10 07:10:07 hinoue Exp $
+ * $Id: psqlodbc.h,v 1.81 2003/12/09 10:01:38 hinoue Exp $
  *
  */
 
@@ -19,7 +19,9 @@
 #endif
 
 #include <stdio.h>             /* for FILE* pointers: see GLOBAL_VALUES */
-
+#ifdef POSIX_MULTITHREAD_SUPPORT
+#include <pthread.h>
+#endif
 #include "version.h"
 
 /* Must come before sql.h */
@@ -120,10 +122,10 @@ typedef UInt4 Oid;
 #ifdef UNICODE_SUPPORT
 #define DRIVER_FILE_NAME           "PSQLODBC30W.DLL"
 #else
-#define DRIVER_FILE_NAME           "PSQLODBC30.DLL"
+#define DRIVER_FILE_NAME           "PSQLODBC.DLL"
 #endif   /* UNICODE_SUPPORT */
 #else
-#define DRIVER_FILE_NAME           "PSQLODBC.DLL"
+#define DRIVER_FILE_NAME           "PSQLODBC25.DLL"
 #endif   /* ODBCVER */
 #else
 #define DRIVER_FILE_NAME           "libpsqlodbc.so"
@@ -309,9 +311,15 @@ void       logs_on_off(int cnopen, int, int);
 #include "misc.h"
 
 int    initialize_global_cs(void);
-#ifdef POSIX_MULTITHTREAD_SUPPORT
+#ifdef POSIX_MULTITHREAD_SUPPORT
+#if    !defined(HAVE_ECO_THREAD_LOCKS)
+#define    POSIX_THREADMUTEX_SUPPORT
+#endif /* HAVE_ECO_THREAD_LOCKS */
+#endif /* POSIX_MULTITHREAD_SUPPORT */
+
+#ifdef POSIX_THREADMUTEX_SUPPORT
 const pthread_mutexattr_t *getMutexAttr(void);
-#endif /* POSIX_MULTITHTREAD_SUPPORT */
+#endif /* POSIX_THREADMUTEX_SUPPORT */
 #ifdef UNICODE_SUPPORT
 UInt4  ucs2strlen(const SQLWCHAR *ucs2str);
 char   *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen, BOOL tolower);
@@ -322,6 +330,7 @@ UInt4   utf8_to_ucs2_lf(const char * utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *uc
 /*#define  _MEMORY_DEBUG_ */
 #ifdef _MEMORY_DEBUG_
 void       *debug_alloc(size_t);
+void       *debug_calloc(size_t, size_t);
 void       *debug_realloc(void *, size_t);
 char       *debug_strdup(const char *);
 void       debug_free(void *);
@@ -329,6 +338,7 @@ void        debug_memory_check(void);
 
 #define malloc debug_alloc
 #define realloc debug_realloc
+#define calloc debug_calloc
 #define strdup debug_strdup
 #define free   debug_free
 #endif   /* _MEMORY_DEBUG_ */
index b653fa68aeb2d0c5a484e9670e21baa340a2e4a7..19c458c505bb2e3632cbe25d1263717c5d9cb47e 100644 (file)
--- a/qresult.c
+++ b/qresult.c
@@ -128,6 +128,7 @@ QR_Constructor()
        rv->rowset_size = 1;
        rv->haskeyset = 0;
        rv->keyset = NULL;
+       rv->reload_count = 0;
        rv->rb_alloc = 0;
        rv->rb_count = 0;
        rv->rollback = NULL;
@@ -280,6 +281,17 @@ QR_free_memory(QResultClass *self)
        free(self->keyset);
        self->keyset = NULL;
        self->count_keyset_allocated = 0;
+       if (self->reload_count > 0 && self->conn)
+       {
+           QResultClass    *res;
+           char        cmd[64];
+
+           sprintf(cmd, "DEALLOCATE \"_KEYSET_%x\"", self);
+           res = CC_send_query(self->conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
+           if (res)
+               QR_Destructor(res);
+       }
+       self->reload_count = 0;
    }
    if (self->rollback)
    {
index 752a5737211c9aca4303e7480ce306d485fc81de..9f433e369fc7afcc35c76493194c57d2402c0ec4 100644 (file)
--- a/qresult.h
+++ b/qresult.h
@@ -72,11 +72,12 @@ struct QResultClass_
    TupleField *backend_tuples; /* data from the backend (the tuple cache) */
    TupleField *tupleField;     /* current backend tuple being retrieved */
 
-   char        inTuples;       /* is a fetch of rows from the backend in
-                                * progress? */
-   char        aborted;        /* was aborted? */
-   char        haskeyset;      /* this result contains keyset ? */
+   char        inTuples;   /* is a fetch of rows from the backend
+                       in  progress ? */
+   char        aborted;    /* was aborted ? */
+   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;  
index 2f75e68d7fa9d75bf9d0677df895b84bf308c003..23cb323f438894f4180c25b85762628e2ab1aae2 100644 (file)
--- a/results.c
+++ b/results.c
@@ -333,7 +333,7 @@ PGAPI_DescribeCol(
     */
    if (pfSqlType)
    {
-       *pfSqlType = pgtype_to_concise_type(stmt, fieldtype);
+       *pfSqlType = pgtype_to_concise_type(stmt, fieldtype, icol);
 
        mylog("describeCol: col %d *pfSqlType = %d\n", icol, *pfSqlType);
    }
@@ -644,7 +644,7 @@ inolog("COLUMN_SCALE=%d\n", value);
            break;
 
        case SQL_COLUMN_TYPE: /* == SQL_DESC_CONCISE_TYPE */
-           value = pgtype_to_concise_type(stmt, field_type);
+           value = pgtype_to_concise_type(stmt, field_type, col_idx);
 inolog("COLUMN_TYPE=%d\n", value);
            break;
 
@@ -721,7 +721,7 @@ inolog("COLUMN_TYPE=%d\n", value);
            p = pgtype_to_name(stmt, field_type);
            break;
        case SQL_DESC_TYPE:
-           value = pgtype_to_sqldesctype(stmt, field_type);
+           value = pgtype_to_sqldesctype(stmt, field_type, col_idx);
            break;
        case SQL_DESC_NUM_PREC_RADIX:
            value = pgtype_radix(stmt, field_type);
@@ -884,7 +884,7 @@ inolog("GetData Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
                Int4    curt = GIdx2ResultIdx(stmt->currTuple, stmt, res);
                value = QR_get_value_backend_row(res, curt, icol);
            }
-           mylog("     value = '%s'\n", value);
+           mylog("     value = '%s'\n", value ? value : "(null)");
        }
    }
    else
@@ -900,7 +900,7 @@ inolog("GetData Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
        if (!get_bookmark)
            value = QR_get_value_backend(res, icol);
 
-       mylog("  socket: value = '%s'\n", value);
+       mylog("  socket: value = '%s'\n", value ? value : "(null)");
    }
 
    if (get_bookmark)
@@ -929,15 +929,13 @@ inolog("GetData Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
 
    field_type = QR_get_field_type(res, icol);
 
-   mylog("**** PGAPI_GetData: icol = %d, fCType = %d, field_type = %d, value = '%s'\n", icol, fCType, field_type, value);
+   mylog("**** PGAPI_GetData: icol = %d, fCType = %d, field_type = %d, value = '%s'\n", icol, fCType, field_type, value ? value : "(null)");
 
-   stmt->current_col = icol;
+   SC_set_current_col(stmt, icol);
 
    result = copy_and_convert_field(stmt, field_type, value,
                                 fCType, rgbValue, cbValueMax, pcbValue);
 
-   stmt->current_col = -1;
-
    switch (result)
    {
        case COPY_OK:
@@ -1459,14 +1457,26 @@ PGAPI_ExtendedFetch(
 
    /* increment the base row in the tuple cache */
    QR_set_rowset_size(res, rowsetSize);
-   if (SC_is_fetchcursor(stmt))
+   if (SC_is_fetchcursor(stmt) ||
+       SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type)
        QR_inc_base(res, stmt->last_fetch_count_include_ommitted);
    else
        res->base = stmt->rowset_start;
 
 #ifdef DRIVER_CURSOR_IMPLEMENT
    if (res->keyset)
-       SC_pos_reload_needed(stmt, SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type);
+   {
+       UDWORD  flag = 0;
+
+       if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
+           SQL_RD_ON == stmt->options.retrieve_data)
+       {
+           if (fFetchType != SQL_FETCH_NEXT ||
+               res->base + rowsetSize > QR_get_num_backend_tuples(res))
+               flag = 1;
+       }
+       SC_pos_reload_needed(stmt, flag);
+   }
 #endif /* DRIVER_CURSOR_IMPLEMENT */
    /* Physical Row advancement occurs for each row fetched below */
 
@@ -1935,74 +1945,38 @@ SC_pos_reload(StatementClass *stmt, UDWORD global_ridx, UWORD *count, BOOL logCh
    return ret;
 }
 
-static RETCODE SQL_API
-SC_pos_reload_needed(StatementClass *stmt, UDWORD flag)
+static const int   ahead_fetch_count = 32;
+static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per_fetch, int limitrow)
 {
-   Int4        i, limitrow;
-   UWORD       qcount;
-   QResultClass    *res;
-   IRDFields   *irdflds = SC_get_IRDF(stmt);
-   RETCODE     ret = SQL_ERROR;
    ConnectionClass *conn = SC_get_conn(stmt);
-   UInt4       oid, blocknum, lodlen;
-   char        *qval = NULL, *sval;
-   Int4        rowc;
-   UWORD       offset;
-   BOOL        create_from_scratch = (0 != flag);
-
-   mylog("SC_pos_reload_needed\n");
-   if (!(res = SC_get_Curres(stmt)))
-   {
-       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_reload_needed.");
-       return SQL_ERROR;
-   }
-   if (!stmt->ti)
-       parse_statement(stmt);  /* not preferable */
-   if (!stmt->updatable)
-   {
-       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
-       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
-       return SQL_ERROR;
-   }
-   limitrow = RowIdx2GIdx(res->rowset_size, stmt);
-   if (limitrow > res->num_total_rows)
-       limitrow = res->num_total_rows;
-   if (create_from_scratch)
-   {
-       int flds_cnt = res->num_backend_rows * res->num_fields,
-           brows;
-
-       for (i = 0; i < flds_cnt; i++)
-       {
-           if (res->backend_tuples[i].value)
-               free(res->backend_tuples[i].value);
-       }
-       brows = GIdx2RowIdx(limitrow, stmt);
-       if (brows > res->count_backend_allocated)
-       {
-           res->backend_tuples = realloc(res->backend_tuples, sizeof(TupleField) * res->num_fields * brows);
-           res->count_backend_allocated = brows;
-       }
-       if (brows > 0)
-           memset(res->backend_tuples, 0, sizeof(TupleField) * res->num_fields * brows);
-       res->num_backend_rows = brows;
-       res->base = 0;
-       for (i = stmt->rowset_start; i < limitrow; i++)
-       {
-           if (0 == (res->keyset[i].status & (CURS_SELF_DELETING | CURS_SELF_DELETED | CURS_OTHER_DELETED)))
-               res->keyset[i].status |= CURS_NEEDS_REREAD;
-       }
-   }
-
+   int i, j, rowc, rcnt = 0;
+   BOOL    prepare;
+   UInt4   oid, blocknum, lodlen;
+   UWORD   offset;
+   char    *qval = NULL, *sval;
+   int keys_per_fetch = 10;
+
+   prepare = PG_VERSION_GE(conn, 7.3);
    for (i = stmt->rowset_start, rowc = 0;; i++)
    {
        if (i >= limitrow)
        {
            if (!rowc)
                break;
+           if (res->reload_count > 0)
+           {
+               for (j = rowc; j < keys_per_fetch; j++)
+               {
+                   if (j)
+                       strcpy(sval, ",NULL");
+                   else
+                       strcpy(sval, "NULL");
+                   sval = strchr(sval, '\0');
+               }
+           }
            rowc = -1; /* end of loop */
        }
-       if (rowc < 0 || rowc >= 10)
+       if (rowc < 0 || rowc >= keys_per_fetch)
        {
            QResultClass    *qres;
 
@@ -2040,6 +2014,12 @@ SC_pos_reload_needed(StatementClass *stmt, UDWORD flag)
                }
                QR_Destructor(qres);
            }
+           else
+           {
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Data Load Error");
+               rcnt = -1;
+               break;
+           }
            if (rowc < 0)
                break;
            rowc = 0;
@@ -2050,32 +2030,169 @@ SC_pos_reload_needed(StatementClass *stmt, UDWORD flag)
            {
                UInt4   allen;
 
-               lodlen = strlen(stmt->load_statement);
-               allen = lodlen + 20 + 23 * 10;
-               qval = malloc(allen);
+               if (prepare)
+               {
+                   if (res->reload_count > 0)
+                       keys_per_fetch = res->reload_count;
+                   else
+                   {
+                       char    planname[32];
+                       int j;
+                       QResultClass    *qres;
+
+                       if (rows_per_fetch >= ahead_fetch_count * 2)
+                           keys_per_fetch = ahead_fetch_count;
+                       else
+                           keys_per_fetch = rows_per_fetch;
+                       lodlen = strlen(stmt->load_statement);
+                       sprintf(planname, "_KEYSET_%0x", res);
+                       allen = 8 + strlen(planname) +
+                           3 + 4 * keys_per_fetch + 1
+                           + 1 + 2 + lodlen + 20 +
+                           4 * keys_per_fetch + 1;
+                       qval = malloc(allen);
+                       sprintf(qval, "PREPARE \"%s\"", planname);
+                       sval = strchr(qval, '\0');
+                       for (j = 0; j < keys_per_fetch; j++)
+                       {
+                           if (j == 0)
+                               strcpy(sval, "(tid");
+                           else 
+                               strcpy(sval, ",tid");
+                           sval = strchr(sval, '\0');
+                       }
+                       sprintf(sval, ") as %s where ctid in ", stmt->load_statement);
+                       sval = strchr(sval, '\0'); 
+                       for (j = 0; j < keys_per_fetch; j++)
+                       {
+                           if (j == 0)
+                               strcpy(sval, "($1");
+                           else 
+                               sprintf(sval, ",$%d", j + 1);
+                           sval = strchr(sval, '\0');
+                       }
+                       strcpy(sval, ")");
+                       qres = CC_send_query(conn, qval, NULL, CLEAR_RESULT_ON_ABORT);
+                       if (qres)
+                           res->reload_count = keys_per_fetch;
+                       else
+                       {
+                           SC_set_error(stmt, STMT_EXEC_ERROR, "Prepare for Data Load Error");
+                           rcnt = -1;
+                           break;
+                       }
+                   }
+                   allen = 25 + 23 * keys_per_fetch;
+                   qval = realloc(qval, allen);
+               }
+               else
+               {
+                   keys_per_fetch = ahead_fetch_count;
+                   lodlen = strlen(stmt->load_statement);
+                   allen = lodlen + 20 + 23 * keys_per_fetch;
+                   qval = malloc(allen);
+               }
+           }
+           if (res->reload_count > 0)
+           {
+               sprintf(qval, "EXECUTE \"_KEYSET_%x\"(", res);
+               sval = qval;
+           }
+           else
+           {
+               memcpy(qval, stmt->load_statement, lodlen);
+               sval = qval + lodlen;
+               sval[0]= '\0';
+               strcpy(sval, " where ctid in (");
            }
-           memcpy(qval, stmt->load_statement, lodlen);
-           sval = qval + lodlen;
-           sval[0]= '\0';
-           strcpy(sval, " where ctid in (");
            sval = strchr(sval, '\0');
        }
        if (0 != (res->keyset[i].status & CURS_NEEDS_REREAD))
        {
            getTid(res, i, &blocknum, &offset);
            if (rowc)
-               sprintf(sval, ", '(%u, %u)'", blocknum, offset);
+               sprintf(sval, ",'(%u,%u)'", blocknum, offset);
            else
-               sprintf(sval, "'(%u, %u)'", blocknum, offset);
+               sprintf(sval, "'(%u,%u)'", blocknum, offset);
            sval = strchr(sval, '\0');
            rowc++;
+           rcnt++;
        }
    }
    if (qval)
        free(qval);
+   return rcnt;
+}
+
+static RETCODE SQL_API
+SC_pos_reload_needed(StatementClass *stmt, UDWORD flag)
+{
+   Int4        i, limitrow;
+   UWORD       qcount;
+   QResultClass    *res;
+   IRDFields   *irdflds = SC_get_IRDF(stmt);
+   RETCODE     ret = SQL_ERROR;
+   ConnectionClass *conn = SC_get_conn(stmt);
+   /**** UInt4     oid, blocknum, lodlen;
+   UWORD       offset;
+   char        *sval; ****/
+   char        *qval = NULL;
+   Int4        rowc, rows_per_fetch;
+   BOOL        create_from_scratch = (0 != flag);
+
+   mylog("SC_pos_reload_needed\n");
+   if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_reload_needed.");
+       return SQL_ERROR;
+   }
+   if (!stmt->ti)
+       parse_statement(stmt);  /* not preferable */
+   if (!stmt->updatable)
+   {
+       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
+       return SQL_ERROR;
+   }
+   if (create_from_scratch)
+   {
+       rows_per_fetch = ((ahead_fetch_count - 1) / res->rowset_size + 1) * res->rowset_size;
+       limitrow = RowIdx2GIdx(rows_per_fetch, stmt);
+   }
    else
-       return SQL_SUCCESS;
+       limitrow = RowIdx2GIdx(res->rowset_size, stmt);
+   if (limitrow > res->num_total_rows)
+       limitrow = res->num_total_rows;
+   if (create_from_scratch)
+   {
+       int flds_cnt = res->num_backend_rows * res->num_fields,
+           brows;
 
+       for (i = 0; i < flds_cnt; i++)
+       {
+           if (res->backend_tuples[i].value)
+               free(res->backend_tuples[i].value);
+       }
+       brows = GIdx2RowIdx(limitrow, stmt);
+       if (brows > res->count_backend_allocated)
+       {
+           res->backend_tuples = realloc(res->backend_tuples, sizeof(TupleField) * res->num_fields * brows);
+           res->count_backend_allocated = brows;
+       }
+       if (brows > 0)
+           memset(res->backend_tuples, 0, sizeof(TupleField) * res->num_fields * brows);
+       res->num_backend_rows = brows;
+       res->base = 0;
+       for (i = stmt->rowset_start; i < limitrow; i++)
+       {
+           if (0 == (res->keyset[i].status & (CURS_SELF_DELETING | CURS_SELF_DELETED | CURS_OTHER_DELETED)))
+               res->keyset[i].status |= CURS_NEEDS_REREAD;
+       }
+   }
+   if (rowc = LoadFromKeyset(stmt, res, rows_per_fetch, limitrow), rowc < 0)
+   {
+       return SQL_ERROR;
+   }
    for (i = stmt->rowset_start; i < limitrow; i++)
    {
        if (0 != (res->keyset[i].status & CURS_NEEDS_REREAD))
@@ -2235,9 +2352,10 @@ typedef struct
    UDWORD      global_ridx;
 }  pup_cdata;
 static RETCODE
-pos_update_callback(RETCODE retcode, pup_cdata *s)
+pos_update_callback(RETCODE retcode, void *para)
 {
    RETCODE ret = retcode;
+   pup_cdata *s = (pup_cdata *) para;
 
    if (s->updyes)
    {
@@ -2387,7 +2505,7 @@ SC_pos_update(StatementClass *stmt,
                        (SQLUSMALLINT) ++j,
                        SQL_PARAM_INPUT,
                        bindings[i].returntype,
-                       pgtype_to_concise_type(s.stmt, fieldtype),
+                       pgtype_to_concise_type(s.stmt, fieldtype, i),
                                                                fi[i]->column_size > 0 ? fi[i]->column_size : pgtype_column_size(s.stmt, fieldtype, i, ci->drivers.unknown_sizes),
                        (SQLSMALLINT) fi[i]->decimal_digits,
                        bindings[i].buffer,
@@ -2567,6 +2685,7 @@ irow_insert(RETCODE ret, StatementClass *stmt, StatementClass *istmt, int addpos
                UInt4   offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
 
                sprintf(buf, "%lu", addpos + 1);
+               SC_set_current_col(stmt, -1);
                copy_and_convert_field(stmt,
                    PG_TYPE_INT4,
                    buf,
@@ -2596,9 +2715,10 @@ typedef struct
 }  padd_cdata;
 
 static RETCODE
-pos_add_callback(RETCODE retcode, padd_cdata *s)
+pos_add_callback(RETCODE retcode, void *para)
 {
    RETCODE ret = retcode;
+   padd_cdata *s = (padd_cdata *) para;
 
    if (s->updyes)
    {
@@ -2723,7 +2843,7 @@ SC_pos_add(StatementClass *stmt,
                    (SQLUSMALLINT) ++add_cols,
                    SQL_PARAM_INPUT,
                    bindings[i].returntype,
-                   pgtype_to_concise_type(s.stmt, fieldtype),
+                   pgtype_to_concise_type(s.stmt, fieldtype, i),
                                                            fi[i]->column_size > 0 ? fi[i]->column_size : pgtype_column_size(s.stmt, fieldtype, i, ci->drivers.unknown_sizes),
                    (SQLSMALLINT) fi[i]->decimal_digits,
                    bindings[i].buffer,
@@ -2835,9 +2955,10 @@ typedef struct
    UWORD   fOption, irow, nrow;
 }  spos_cdata;
 static 
-RETCODE spos_callback(RETCODE retcode, spos_cdata *s)
+RETCODE spos_callback(RETCODE retcode, void *para)
 {
    RETCODE ret;
+   spos_cdata *s = (spos_cdata *) para;
    ConnectionClass *conn;
    UDWORD  global_ridx;
 
index 0b080885a842e6bd8dae8412066b9d619c5eeab7..1bef35d9b28fb3de957f58929354be7598b50790 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -19,7 +19,7 @@
 #ifndef WIN32
 #include <stdlib.h>
 #include <string.h>                /* for memset */
-#endif
+#endif /* WIN32 */
 
 extern GLOBAL_VALUES globals;
 
@@ -60,20 +60,21 @@ SOCK_Constructor(const ConnectionClass *conn)
            rv->buffer_size = conn->connInfo.drivers.socket_buffersize;
        else
            rv->buffer_size = globals.socket_buffersize;
-       rv->buffer_in = (unsigned char *) malloc(rv->buffer_size);
+       rv->buffer_in = (UCHAR *) malloc(rv->buffer_size);
        if (!rv->buffer_in)
        {
            free(rv);
            return NULL;
        }
 
-       rv->buffer_out = (unsigned char *) malloc(rv->buffer_size);
+       rv->buffer_out = (UCHAR *) malloc(rv->buffer_size);
        if (!rv->buffer_out)
        {
            free(rv->buffer_in);
            free(rv);
            return NULL;
        }
+       rv->sadr = NULL;
        rv->errormsg = NULL;
        rv->errornumber = 0;
        rv->reverse = FALSE;
@@ -100,6 +101,8 @@ SOCK_Destructor(SocketClass *self)
 
    if (self->buffer_out)
        free(self->buffer_out);
+   if (self->sadr != (struct sockaddr *) &(self->sadr_in))
+       free(self->sadr);
 
    free(self);
 }
@@ -109,14 +112,19 @@ char
 SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
 {
 #if defined (POSIX_MULTITHREAD_SUPPORT)
-    const int bufsz = 8192; 
-    char buf[bufsz];
-    int error = 0;
-    struct hostent host;
-    struct hostent* hp = &host;
+   const int bufsz = 8192; 
+   char buf[bufsz];
+   int error = 0;
+   struct hostent host;
+   struct hostent* hp = &host;
 #else
-    struct hostent* hp;
-#endif 
+   struct hostent* hp;
+#endif /* POSIX_MULTITHREAD_SUPPORT */
+   struct sockaddr_in *in;
+#ifdef HAVE_UNIX_SOCKETS
+   struct sockaddr_un *un;
+#endif /* HAVE_UNIX_SOCKETS */
+   int family, sLen; 
    unsigned long iaddr;
 
    if (self->socket != -1)
@@ -126,57 +134,97 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
        return 0;
    }
 
-   memset((char *) &(self->sadr), 0, sizeof(self->sadr));
 
    /*
     * If it is a valid IP address, use it. Otherwise use hostname lookup.
     */
-   iaddr = inet_addr(hostname);
-   if (iaddr == INADDR_NONE)
+   if (hostname && hostname[0])
    {
+       iaddr = inet_addr(hostname);
+       memset((char *) &(self->sadr_in), 0, sizeof(self->sadr_in));
+       in = &(self->sadr_in);
+       in->sin_family = family = AF_INET;
+       in->sin_port = htons(port);
+       sLen = sizeof(self->sadr_in);
+       if (iaddr == INADDR_NONE)
+       {
 #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);
+           hp = gethostbyname_r(hostname, hp, buf, bufsz, &error);
   #elif defined (PGS_REENTRANT_API_2) /* linux */
-        int result = 0;
-        result = gethostbyname_r(hostname, hp, buf, bufsz, &hp, &error);
-        if (result)
-          hp = 0;
+           int result = 0;
+           result = gethostbyname_r(hostname, hp, buf, bufsz, &hp, &error);
+           if (result)
+               hp = NULL;
   #else
-        hp = gethostbyname(hostname);
-  #endif
+           hp = gethostbyname(hostname);
+  #endif /* HAVE_GETIPNODEBYNAME */
 #else
-        hp = gethostbyname(hostname);
-#endif
-       if (hp == NULL)
-       {
-           self->errornumber = SOCKET_HOST_NOT_FOUND;
-           self->errormsg = "Could not resolve hostname.";
-           return 0;
+           hp = gethostbyname(hostname);
+#endif /* POSIX_MULTITHREAD_SUPPORT */
+           if (hp == NULL)
+           {
+               self->errornumber = SOCKET_HOST_NOT_FOUND;
+               self->errormsg = "Could not resolve hostname.";
+               return 0;
+           }
+           memcpy(&(in->sin_addr), hp->h_addr, hp->h_length);
        }
-       memcpy(&(self->sadr.sin_addr), hp->h_addr, hp->h_length);
-   }
-   else
-       memcpy(&(self->sadr.sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
+       else
+           memcpy(&(in->sin_addr), (struct in_addr *) & iaddr, sizeof(iaddr));
+       self->sadr = (struct sockaddr *) in;
 
 #if defined (HAVE_GETIPNODEBYNAME)
-   freehostent(hp);
+       freehostent(hp);
 #endif /* HAVE_GETIPNODEBYNAME */
-   self->sadr.sin_family = AF_INET;
-   self->sadr.sin_port = htons(port);
+   }
+   else
+#ifdef HAVE_UNIX_SOCKETS
+   {
+       un = (struct sockaddr_un *) malloc(sizeof(struct sockaddr_un));
+       un->sun_family = family = AF_UNIX;
+       /* passing NULL means that this only suports the pg default "/tmp" */
+       UNIXSOCK_PATH(un, port, ((char *) NULL));
+       sLen = UNIXSOCK_LEN(un);
+       self->sadr = (struct sockaddr *) un;
+   }
+#else
+   {
+       self->errornumber = SOCKET_HOST_NOT_FOUND;
+       self->errormsg = "Hostname isn't specified.";
+       return 0;
+   }
+#endif /* HAVE_UNIX_SOCKETS */
 
-   self->socket = socket(AF_INET, SOCK_STREAM, 0);
+   self->socket = socket(family, SOCK_STREAM, 0);
    if (self->socket == -1)
    {
        self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
        self->errormsg = "Could not create Socket.";
        return 0;
    }
+#ifdef TCP_NODELAY
+   if (family == AF_INET)
+   {
+       int i, len;
+
+       i = 1;
+       len = sizeof(i);
+       if (setsockopt(self->socket, IPPROTO_TCP, TCP_NODELAY, (char *) &i, len) < 0)
+       {
+           self->errornumber = SOCKET_COULD_NOT_CONNECT;
+           self->errormsg = "Could not set socket to NODELAY.";
+           closesocket(self->socket);
+           self->socket = (SOCKETFD) - 1;
+           return 0;
+       }
+   }
+#endif /* TCP_NODELAY */
 
-   if (connect(self->socket, (struct sockaddr *) & (self->sadr),
-               sizeof(self->sadr)) < 0)
+   self->sadr_len = sLen;
+   if (connect(self->socket, self->sadr, sLen) < 0)
    {
        self->errornumber = SOCKET_COULD_NOT_CONNECT;
        self->errormsg = "Could not connect to remote socket.";
@@ -184,6 +232,7 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
        self->socket = (SOCKETFD) - 1;
        return 0;
    }
+
    return 1;
 }
 
@@ -222,7 +271,7 @@ SOCK_put_n_char(SocketClass *self, char *buffer, int len)
    }
 
    for (lf = 0; lf < len; lf++)
-       SOCK_put_next_byte(self, (unsigned char) buffer[lf]);
+       SOCK_put_next_byte(self, (UCHAR) buffer[lf]);
 }
 
 
@@ -254,7 +303,7 @@ SOCK_put_string(SocketClass *self, char *string)
    len = strlen(string) + 1;
 
    for (lf = 0; lf < len; lf++)
-       SOCK_put_next_byte(self, (unsigned char) string[lf]);
+       SOCK_put_next_byte(self, (UCHAR) string[lf]);
 }
 
 
@@ -325,21 +374,28 @@ SOCK_put_int(SocketClass *self, int value, short len)
 void
 SOCK_flush_output(SocketClass *self)
 {
-   int         written;
+   int         written, pos = 0;
 
    if (!self)
        return;
-   written = send(self->socket, (char *) self->buffer_out, self->buffer_filled_out, 0);
-   if (written != self->buffer_filled_out)
+   do
    {
-       self->errornumber = SOCKET_WRITE_ERROR;
-       self->errormsg = "Could not flush socket buffer.";
-   }
-   self->buffer_filled_out = 0;
+       written = send(self->socket, (char *) self->buffer_out + pos, self->buffer_filled_out, 0);
+       if (written < 0)
+       {
+           if (SOCK_ERRNO == EINTR)
+               continue;
+           self->errornumber = SOCKET_WRITE_ERROR;
+           self->errormsg = "Could not flush socket buffer.";
+           break;
+       }
+       pos += written;
+       self->buffer_filled_out -= written;
+   } while (self->buffer_filled_out > 0);
 }
 
 
-unsigned char
+UCHAR
 SOCK_get_next_byte(SocketClass *self)
 {
    if (!self)
@@ -350,12 +406,15 @@ SOCK_get_next_byte(SocketClass *self)
         * there are no more bytes left in the buffer so reload the buffer
         */
        self->buffer_read_in = 0;
+retry:
        self->buffer_filled_in = recv(self->socket, (char *) self->buffer_in, self->buffer_size, 0);
 
        mylog("read %d, global_socket_buffersize=%d\n", self->buffer_filled_in, self->buffer_size);
 
        if (self->buffer_filled_in < 0)
        {
+           if (SOCK_ERRNO == EINTR)
+               goto retry;
            self->errornumber = SOCKET_READ_ERROR;
            self->errormsg = "Error while reading from the socket.";
            self->buffer_filled_in = 0;
@@ -374,9 +433,9 @@ SOCK_get_next_byte(SocketClass *self)
 
 
 void
-SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
+SOCK_put_next_byte(SocketClass *self, UCHAR next_byte)
 {
-   int         bytes_sent;
+   int         bytes_sent, pos = 0;
 
    if (!self)
        return;
@@ -385,12 +444,19 @@ SOCK_put_next_byte(SocketClass *self, unsigned char next_byte)
    if (self->buffer_filled_out == self->buffer_size)
    {
        /* buffer is full, so write it out */
-       bytes_sent = send(self->socket, (char *) self->buffer_out, self->buffer_size, 0);
-       if (bytes_sent != self->buffer_size)
+       do
        {
-           self->errornumber = SOCKET_WRITE_ERROR;
-           self->errormsg = "Error while writing to the socket.";
-       }
-       self->buffer_filled_out = 0;
+           bytes_sent = send(self->socket, (char *) self->buffer_out + pos, self->buffer_filled_out, 0);
+           if (bytes_sent < 0)
+           {
+               if (SOCK_ERRNO == EINTR)
+                   continue;
+               self->errornumber = SOCKET_WRITE_ERROR;
+               self->errormsg = "Error while writing to the socket.";
+               break;
+           }
+           pos += bytes_sent;
+           self->buffer_filled_out -= bytes_sent;
+       } while (self->buffer_filled_out > 0);
    }
 }
index cbdcbaeb869e1c02691a1e96164e9113ea836d71..1a9b4dd796b8b93f4ab9971ecf4eca3b6cebe54c 100644 (file)
--- a/socket.h
+++ b/socket.h
 #define __SOCKET_H__
 
 #include "psqlodbc.h"
+#include <errno.h>
 
 #ifndef WIN32
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <unistd.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #ifndef _IN_ADDR_T
 #define _IN_ADDR_T
 typedef unsigned int in_addr_t;
-#endif
+#endif /* _IN_ADDR_T */
 #define INADDR_NONE ((in_addr_t)-1)
-#endif
+#endif /* _IN_ADDR_NONE */
 
+#define SOCK_ERRNO errno
+#define SOCK_ERRNO_SET(e)  (errno = e)
+#ifdef HAVE_SYS_UN_H
+#define HAVE_UNIX_SOCKETS
+#endif /* HAVE_SYS_UN_H */
 #else
 #include <winsock.h>
 #define SOCKETFD SOCKET
-#endif
+#define SOCK_ERRNO (WSAGetLastError())
+#define SOCK_ERRNO_SET(e)  WSASetLastError(e)
+#endif /* WIN32 */
 
 #define SOCKET_ALREADY_CONNECTED           1
 #define SOCKET_HOST_NOT_FOUND              2
@@ -54,14 +63,16 @@ struct SocketClass_
    int         buffer_filled_in;
    int         buffer_filled_out;
    int         buffer_read_in;
-   unsigned char *buffer_in;
-   unsigned char *buffer_out;
+   UCHAR *buffer_in;
+   UCHAR *buffer_out;
 
    SOCKETFD    socket;
 
    char       *errormsg;
    int         errornumber;
-   struct sockaddr_in  sadr; /* Used for handling connections for cancel */
+   struct sockaddr *sadr; /* Used for handling connections for cancel */
+   int     sadr_len;
+   struct sockaddr_in sadr_in; /* Used for INET connections */
 
    char        reverse;        /* used to handle Postgres 6.2 protocol
                                 * (reverse byte order) */
@@ -76,6 +87,36 @@ struct SocketClass_
 #define SOCK_get_errcode(self) (self ? self->errornumber : SOCKET_CLOSED)
 #define SOCK_get_errmsg(self)  (self ? self->errormsg : "socket closed")
 
+/*
+ * code taken from postgres libpq et al.
+ */
+#ifndef WIN32
+#define DEFAULT_PGSOCKET_DIR   "/tmp"
+#define UNIXSOCK_PATH(sun, port, defpath) \
+   snprintf((sun)->sun_path, sizeof((sun)->sun_path), "%s/.s.PGSQL.%d", \
+       ((defpath) && *(defpath) != '\0') ? (defpath) : \
+           DEFAULT_PGSOCKET_DIR, \
+           (port))
+
+/*
+ * We do this because sun_len is in BSD's struct, while others don't.
+ * We never actually set BSD's sun_len, and I can't think of a
+ * platform-safe way of doing it, but the code still works. bjm
+ */
+#ifndef    offsetof
+#define offsetof(type, field)  ((long) &((type *)0)->field)
+#endif /* offsetof */
+#if defined(SUN_LEN)
+#define UNIXSOCK_LEN(sun) SUN_LEN(sun)
+#else
+#define UNIXSOCK_LEN(sun) \
+   (strlen((sun)->sun_path) + offsetof(struct sockaddr_un, sun_path))
+#endif /* SUN_LEN */
+#endif /* WIN32 */
+/*
+ * END code taken from postgres libpq et al.
+ */
+
 
 /* Socket prototypes */
 SocketClass *SOCK_Constructor(const ConnectionClass *conn);
@@ -88,8 +129,8 @@ void     SOCK_put_string(SocketClass *self, char *string);
 int            SOCK_get_int(SocketClass *self, short len);
 void       SOCK_put_int(SocketClass *self, int value, short len);
 void       SOCK_flush_output(SocketClass *self);
-unsigned char SOCK_get_next_byte(SocketClass *self);
-void       SOCK_put_next_byte(SocketClass *self, unsigned char next_byte);
+UCHAR      SOCK_get_next_byte(SocketClass *self);
+void       SOCK_put_next_byte(SocketClass *self, UCHAR next_byte);
 void       SOCK_clear_error(SocketClass *self);
 
-#endif
+#endif /* __SOCKET_H__ */
index 0d16cd4c35a7cfbf0d88a5768090a4aa645dd4a8..2246bc2182640cb1685f3df6e8499f847087fb13 100644 (file)
@@ -392,7 +392,7 @@ statement_type(const char *statement)
    int         i;
 
    /* ignore leading whitespace in query string */
-   while (*statement && (isspace((unsigned char) *statement) || *statement == '('))
+   while (*statement && (isspace((UCHAR) *statement) || *statement == '('))
        statement++;
 
    for (i = 0; Statement_Type[i].s; i++)
@@ -402,6 +402,18 @@ statement_type(const char *statement)
    return STMT_TYPE_OTHER;
 }
 
+int
+SC_set_current_col(StatementClass *stmt, int col)
+{
+   if (col == stmt->current_col)
+       return col;
+   if (col >= 0)
+       reset_a_getdata_info(SC_get_GDTI(stmt), col + 1);
+   stmt->current_col = col;
+
+   return stmt->current_col;
+}
+
 void
 SC_set_prepared(StatementClass *stmt, BOOL prepared)
 {
@@ -587,7 +599,7 @@ SC_recycle_statement(StatementClass *self)
 
    self->currTuple = -1;
    self->rowset_start = -1;
-   self->current_col = -1;
+   SC_set_current_col(self, -1);
    self->bind_row = 0;
    self->last_fetch_count = self->last_fetch_count_include_ommitted = 0;
 
@@ -926,6 +938,7 @@ SC_fetch(StatementClass *self)
        UInt4   offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;
 
        sprintf(buf, "%ld", SC_get_bookmark(self));
+       SC_set_current_col(self, -1);
        result = copy_and_convert_field(self, 0, buf,
             SQL_C_ULONG, bookmark->buffer + offset, 0,
            bookmark->used ? bookmark->used + (offset >> 2) : NULL);
@@ -1033,6 +1046,7 @@ SC_execute(StatementClass *self)
    ConnInfo   *ci;
    UDWORD      qflag = 0;
    BOOL        auto_begin = FALSE, is_in_trans;
+   int     entered;
 
 
    conn = SC_get_conn(self);
@@ -1048,14 +1062,13 @@ SC_execute(StatementClass *self)
     * 2) we are in autocommit off state and the statement isn't of type
     * OTHER.
     */
-   ENTER_CONN_CS(conn);
+   ENTER_INNER_CONN_CS(conn, entered);
    if (CONN_EXECUTING == conn->status)
    {
-       LEAVE_CONN_CS(conn);
        SC_set_error(self, STMT_SEQUENCE_ERROR, "Connection is already in use.");
        SC_log_error(func, "", self);
        mylog("%s: problem with connection\n", func);
-       return SQL_ERROR;
+       RETURN_AFTER_LEAVE_CS(entered, conn, SQL_ERROR);
    }
    is_in_trans = CC_is_in_trans(conn);
    if (!self->internal && !is_in_trans &&
@@ -1068,10 +1081,9 @@ SC_execute(StatementClass *self)
            qflag |= GO_INTO_TRANSACTION;
                 else if (!CC_begin(conn))
                 {
-           LEAVE_CONN_CS(conn);
            SC_set_error(self, STMT_EXEC_ERROR, "Could not begin a transaction");
                         SC_log_error(func, "", self);
-                        return SQL_ERROR;
+                        RETURN_AFTER_LEAVE_CS(entered, conn, SQL_ERROR);
                 }
    }
 
@@ -1149,7 +1161,7 @@ SC_execute(StatementClass *self)
    if (CONN_DOWN != conn->status)
        conn->status = oldstatus;
    self->status = STMT_FINISHED;
-   LEAVE_CONN_CS(conn);
+   LEAVE_INNER_CONN_CS(entered, conn);
 
    /* Check the status of the result */
    if (res)
@@ -1164,7 +1176,7 @@ SC_execute(StatementClass *self)
 
        /* set cursor before the first tuple in the list */
        self->currTuple = -1;
-       self->current_col = -1;
+       SC_set_current_col(self, -1);
        self->rowset_start = -1;
 
        /* issue "ABORT" when query aborted */
@@ -1378,57 +1390,3 @@ SC_log_error(const char *func, const char *desc, const StatementClass *self)
    }
 #undef PRN_NULLCHECK
 }
-
-/* Map sql commands to statement types */
-static struct
-{
-   int number;
-   const   char    * ver3str;
-   const   char    * ver2str;
-}  Descriptor_sqlstate[] =
-
-{
-   { STMT_OK,  "00000", "00000" }, /* OK */
-   { STMT_EXEC_ERROR, "HY000", "S1000" }, /* also a general error */
-   { STMT_STATUS_ERROR, "HY010", "S1010" },
-   { STMT_SEQUENCE_ERROR, "HY010", "S1010" }, /* Function sequence error */
-   { STMT_NO_MEMORY_ERROR, "HY001", "S1001" }, /* memory allocation failure */
-   { STMT_COLNUM_ERROR, "07009", "S1002" }, /* invalid column number */
-   { STMT_NO_STMTSTRING, "HY001", "S1001" }, /* having no stmtstring is also a malloc problem */
-   { STMT_ERROR_TAKEN_FROM_BACKEND, "HY000", "S1000" }, /* general error */
-   { STMT_INTERNAL_ERROR, "HY000", "S1000" }, /* general error */
-   { STMT_STILL_EXECUTING, "HY010", "S1010" },
-   { STMT_NOT_IMPLEMENTED_ERROR, "HYC00", "S1C00" }, /* == 'driver not 
-                             * capable' */
-   { STMT_BAD_PARAMETER_NUMBER_ERROR, "07009", "S1093" },
-   { STMT_OPTION_OUT_OF_RANGE_ERROR, "HY092", "S1092" },
-   { STMT_INVALID_COLUMN_NUMBER_ERROR, "07009", "S1002" },
-   { STMT_RESTRICTED_DATA_TYPE_ERROR, "07006", "07006" },
-   { STMT_INVALID_CURSOR_STATE_ERROR, "07005", "24000" },
-   { STMT_OPTION_VALUE_CHANGED, "01S02", "01S02" },
-   { STMT_CREATE_TABLE_ERROR, "42S01", "S0001" }, /* table already exists */
-   { STMT_NO_CURSOR_NAME, "S1015", "S1015" },
-   { STMT_INVALID_CURSOR_NAME, "34000", "34000" },
-   { STMT_INVALID_ARGUMENT_NO, "HY024", "S1009" }, /* invalid argument value */
-   { STMT_ROW_OUT_OF_RANGE, "HY107", "S1107" },
-   { STMT_OPERATION_CANCELLED, "HY008", "S1008" },
-   { STMT_INVALID_CURSOR_POSITION, "HY109", "S1109" },
-   { STMT_VALUE_OUT_OF_RANGE, "HY019", "22003" },
-   { STMT_OPERATION_INVALID, "HY011", "S1011" },
-   { STMT_PROGRAM_TYPE_OUT_OF_RANGE, "?????", "?????" }, 
-   { STMT_BAD_ERROR, "08S01", "08S01" }, /* communication link failure */
-   { STMT_INVALID_OPTION_IDENTIFIER, "HY092", "HY092" },
-   { STMT_RETURN_NULL_WITHOUT_INDICATOR, "22002", "22002" },
-   { STMT_ERROR_IN_ROW, "01S01", "01S01" },
-   { STMT_INVALID_DESCRIPTOR_IDENTIFIER, "HY091", "HY091" },
-   { STMT_OPTION_NOT_FOR_THE_DRIVER, "HYC00", "HYC00" },
-   { STMT_FETCH_OUT_OF_RANGE, "HY106", "S1106" },
-   { STMT_COUNT_FIELD_INCORRECT, "07002", "07002" },
-
-
-   { STMT_ROW_VERSION_CHANGED,  "01001", "01001" }, /* data changed */
-   { STMT_TRUNCATED, "01004", "01004" }, /* data truncated */
-   { STMT_INFO_ONLY, "00000", "00000" }, /* just information that is returned, no error */
-   { STMT_POS_BEFORE_RECORDSET, "01S06", "01S06" },
-};
-
index 35da097cd96a738ffa7c60d98c69e4b2ae48508f..0f9f494a09273c01551d097cea8fdf48ef47c85a 100644 (file)
@@ -228,8 +228,8 @@ struct StatementClass_
    NeedDataCallback    *callbacks;
 #if defined(WIN_MULTITHREAD_SUPPORT)
    CRITICAL_SECTION    cs;
-#elif defined(POSIX_MULTITHREAD_SUPPORT)
-    pthread_mutex_t     cs;
+#elif defined(POSIX_THREADMUTEX_SUPPORT)
+   pthread_mutex_t     cs;
 #endif /* WIN_MULTITHREAD_SUPPORT */
 
 };
@@ -284,7 +284,7 @@ struct StatementClass_
 #define ENTER_STMT_CS(x)   EnterCriticalSection(&((x)->cs))
 #define LEAVE_STMT_CS(x)   LeaveCriticalSection(&((x)->cs))
 #define DELETE_STMT_CS(x)  DeleteCriticalSection(&((x)->cs))
-#elif defined(POSIX_MULTITHREAD_SUPPORT)
+#elif defined(POSIX_THREADMUTEX_SUPPORT)
 #define INIT_STMT_CS(x)        pthread_mutex_init(&((x)->cs),0)
 #define ENTER_STMT_CS(x)   pthread_mutex_lock(&((x)->cs))
 #define LEAVE_STMT_CS(x)   pthread_mutex_unlock(&((x)->cs))
@@ -326,6 +326,7 @@ RETCODE     SC_pos_update(StatementClass *self, UWORD irow, UDWORD index);
 RETCODE        SC_pos_delete(StatementClass *self, UWORD irow, UDWORD index);
 RETCODE        SC_pos_refresh(StatementClass *self, UWORD irow, UDWORD index);
 RETCODE        SC_pos_add(StatementClass *self, UWORD irow);
+int        SC_set_current_col(StatementClass *self, int col);
 
 DescriptorClass    *SC_set_ARD(StatementClass *stmt, DescriptorClass *desc);
 DescriptorClass    *SC_set_APD(StatementClass *stmt, DescriptorClass *desc);
index 214a9cf2399dd800c75499ca9e64f18fae91003f..800ab3cdd0ce81e4b5230d05aa0ce9c06bec5988 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,8 +9,8 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "07.03.0204"
-#define POSTGRES_RESOURCE_VERSION  "07.03.0204\0"
-#define PG_DRVFILE_VERSION     7,3,2,04
+#define POSTGRESDRIVERVERSION      "07.03.0205"
+#define POSTGRES_RESOURCE_VERSION  "07.03.0205\0"
+#define PG_DRVFILE_VERSION     7,3,2,05
 
 #endif
index ff1ef29bef4d19ca6cf77017517451f5e4679f72..a106ef187254345dff5c4c1c134b744f5b694569 100644 (file)
@@ -91,7 +91,7 @@ UInt4 utf8_to_ucs2_lf(const char *utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *ucs
 {
    int i;
    UInt4   ocount, wcode;
-   const unsigned char *str;
+   const UCHAR *str;
 
 /*mylog("utf8_to_ucs2 ilen=%d bufcount=%d", ilen, bufcount);*/
    if (!utf8str || !ilen)