1. Correct the command/responce sequence of Function Call used for large
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 18 Dec 2006 14:45:54 +0000 (14:45 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 18 Dec 2006 14:45:54 +0000 (14:45 +0000)
   object handling.
2. Add support for NaN and (-)Infinity float values.

connection.c
convert.c
dlg_specific.c
statement.c
version.h

index 639780baf6a1a8a6ab430356cb7a42afa615a8ad..c41309f78861c7e146cc62097279317f27dcb356 100644 (file)
@@ -1396,7 +1396,7 @@ inolog("protocol=%s version=%d,%d\n", ci->protocol, self->pg_version_major, self
 
    if (!PROTOCOL_62(ci))
    {
-       BOOL        before_64 = PG_VERSION_LT(self, 6.4),
+       BOOL        beforeV2 = PG_VERSION_LT(self, 6.4),
                    ReadyForQuery = FALSE, retry = FALSE;
        uint32  leng;
 
@@ -1566,7 +1566,7 @@ inolog("Ekita\n");
            /*
             * There were no ReadyForQuery responce before 6.4.
             */
-           if (before_64 && areq == AUTH_REQ_OK)
+           if (beforeV2 && areq == AUTH_REQ_OK)
                ReadyForQuery = TRUE;
        } while (!ReadyForQuery);
    }
@@ -2082,7 +2082,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag, St
    BOOL        msg_truncated,
                ReadyToReturn = FALSE,
                query_completed = FALSE,
-               before_64 = PG_VERSION_LT(self, 6.4),
+               beforeV2 = PG_VERSION_LT(self, 6.4),
                aborted = FALSE,
                used_passed_result_object = FALSE,
            discard_next_begin = FALSE,
@@ -2314,7 +2314,7 @@ inolog("Discarded the first SAVEPOINT\n");
                    QR_set_command(res, cmdbuffer);
                    query_completed = TRUE;
                    mylog("send_query: returning res = %p\n", res);
-                   if (!before_64)
+                   if (!beforeV2)
                        break;
 
                    /*
@@ -2496,7 +2496,7 @@ inolog("Discarded the first SAVEPOINT\n");
        /*
         * There was no ReadyForQuery response before 6.4.
         */
-       if (before_64)
+       if (beforeV2)
        {
            if (empty_reqs == 0 && query_completed)
                break;
@@ -2606,7 +2606,8 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
    UInt4           leng;
    Int4            response_length;
    ConnInfo        *ci;
-   int         func_cs_count = 0; 
+   int         func_cs_count = 0;
+   BOOL            sinceV3, beforeV3, beforeV2, resultResponse;
 
    mylog("send_function(): conn=%p, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
 
@@ -2627,7 +2628,10 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
 #define    return DONT_CALL_RETURN_FROM_HERE???
    ENTER_INNER_CONN_CS(self, func_cs_count);
    ci = &(self->connInfo);
-   if (PROTOCOL_74(ci))
+   sinceV3 = PROTOCOL_74(ci);
+   beforeV3 = (!sinceV3);
+   beforeV2 = (beforeV3 && !PROTOCOL_64(ci));
+   if (sinceV3)
    {
        leng = 4 + sizeof(uint32) + 2 + 2
            + sizeof(uint16);
@@ -2658,7 +2662,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
    }
 
    SOCK_put_int(sock, fnid, 4);
-   if (PROTOCOL_74(ci))
+   if (sinceV3)
    {
        SOCK_put_int(sock, 1, 2); /* # of formats */
        SOCK_put_int(sock, 1, 2); /* the format is binary */
@@ -2681,7 +2685,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
 
    }
 
-   if (PROTOCOL_74(ci))
+   if (sinceV3)
        SOCK_put_int(sock, 1, 2); /* result format is binary */
    mylog("    done sending args\n");
 
@@ -2689,6 +2693,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
    mylog("  after flush output\n");
 
    done = FALSE;
+   resultResponse = FALSE; /* for before V3 only */
    while (!done)
    {
        id = SOCK_get_id(sock);
@@ -2699,16 +2704,21 @@ inolog("send_func response_length=%d\n", response_length);
        switch (id)
        {
            case 'G':
-               if (PROTOCOL_74(ci))
+               if (!resultResponse)
                {
                    done = TRUE;
                    ret = FALSE;
                    break;
-               }
+               } /* fall through */
            case 'V':
                if ('V' == id)
-                   if (!PROTOCOL_74(ci))
+               {
+                   if (beforeV3) /* FunctionResultResponse */
+                   {
+                       resultResponse = TRUE;
                        break;
+                   }
+               }
                *actual_result_len = SOCK_get_int(sock, 4);
                if (-1 != *actual_result_len)
                {
@@ -2719,12 +2729,14 @@ inolog("send_func response_length=%d\n", response_length);
 
                    mylog("  after get result\n");
                }
-               if (!PROTOCOL_74(ci))
+               if (beforeV3)
                {
-                   c = SOCK_get_char(sock); /* get the last '0' */ 
+                   c = SOCK_get_char(sock); /* get the last '0' */
+                   if (beforeV2)
+                       done = TRUE;
+                   resultResponse = FALSE;
                    mylog("   after get 0\n");
                }
-               done = TRUE; 
                break;          /* ok */
 
            case 'N':
@@ -2741,18 +2753,25 @@ inolog("send_func response_length=%d\n", response_length);
 
                mylog("send_function(V): 'E' - %s\n", CC_get_errormsg(self));
                qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
-               done = TRUE;
+               if (beforeV2)
+                   done = TRUE;
                ret = FALSE;
                break;
 
            case 'Z':
                EatReadyForQuery(self);
-               break;
-
-           case '0':           /* empty result */
                done = TRUE;
                break;
 
+           case '0':   /* empty result */
+               if (resultResponse)
+               {
+                   if (beforeV2)
+                       done = TRUE;
+                   resultResponse = FALSE;
+                   break;
+               } /* fall through */
+
            default:
                /* skip the unexpected response if possible */
                if (response_length >= 0)
index 638dfa1e1816416c4a8095775bae08adf3d61d7f..e73d73197619e2c24a1f755ac06c8f1f7bb37175 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -18,6 +18,9 @@
 /* Multibyte support  Eiji Tokuya  2001-03-15  */
 
 #include "convert.h"
+#ifdef WIN32
+#include <float.h>
+#endif /* WIN32 */
 
 #include <stdio.h>
 #include <string.h>
 #define    WIN_UNICODE_SUPPORT
 #endif
 
+CSTR   NAN_STRING = "NaN";
+CSTR   INFINITY_STRING = "Infinity";
+CSTR   MINFINITY_STRING = "-Infinity";
+
 #ifdef __CYGWIN__
 #define TIMEZONE_GLOBAL _timezone
 #elif  defined(WIN32) || defined(HAVE_INT_TIMEZONE)
@@ -336,12 +343,12 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
    precstr[0] = '\0';
    if (st->infinity > 0)
    {
-       strcpy(str, "Infinity");
+       strcpy(str, INFINITY_STRING);
        return TRUE;
    }
    else if (st->infinity < 0)
    {
-       strcpy(str, "-Infinity");
+       strcpy(str, MINFINITY_STRING);
        return TRUE;
    }
    if (precision && st->fr)
@@ -403,6 +410,31 @@ copy_and_convert_field_bindinfo(StatementClass *stmt, OID field_type, void *valu
            LENADDR_SHIFT(bic->used, offset), LENADDR_SHIFT(bic->indicator, offset));
 }
 
+static double get_double_value(const char *str)
+{
+   if (stricmp(str, NAN_STRING) == 0)
+#ifdef NAN
+       return (double) NAN;
+#else
+   {
+       double  a = .0;
+       return .0 / a;
+   }
+#endif /* NAN */
+   else if (stricmp(str, INFINITY_STRING) == 0)
+#ifdef INFINITY
+       return (double) INFINITY;
+#else
+       return (double) (HUGE_VAL * HUGE_VAL);
+#endif /* INFINITY */
+   else if (stricmp(str, MINFINITY_STRING) == 0)
+#ifdef INFINITY
+       return (double) -INFINITY;
+#else
+       return (double) -(HUGE_VAL * HUGE_VAL);
+#endif /* INFINITY */
+   return atof(str);
+}
 
 /* This is called by SQLGetData() */
 int
@@ -607,7 +639,7 @@ mylog("null_cvt_date_string=%d\n", conn->connInfo.cvt_null_date_string);
        case PG_TYPE_TIMESTAMP:
            std_time.fr = 0;
            std_time.infinity = 0;
-           if (strnicmp(value, "infinity", 8) == 0)
+           if (strnicmp(value, INFINITY_STRING, 8) == 0)
            {
                std_time.infinity = 1;
                std_time.m = 12;
@@ -617,7 +649,7 @@ mylog("null_cvt_date_string=%d\n", conn->connInfo.cvt_null_date_string);
                std_time.mm = 59;
                std_time.ss = 59;
            }
-           if (strnicmp(value, "-infinity", 9) == 0)
+           if (strnicmp(value, MINFINITY_STRING, 9) == 0)
            {
                std_time.infinity = -1;
                std_time.m = 0;
@@ -1210,9 +1242,9 @@ inolog("2stime fr=%d\n", std_time.fr);
 #endif /* HAVE_LOCALE_H */
                len = 4;
                if (bind_size > 0)
-                   *((SFLOAT *) rgbValueBindRow) = (float) atof(neut_str);
+                   *((SFLOAT *) rgbValueBindRow) = (float) get_double_value(neut_str);
                else
-                   *((SFLOAT *) rgbValue + bind_row) = (float) atof(neut_str);
+                   *((SFLOAT *) rgbValue + bind_row) = (float) get_double_value(neut_str);
 #ifdef HAVE_LOCALE_H
                setlocale(LC_ALL, saved_locale);
                free(saved_locale);
@@ -1226,9 +1258,9 @@ inolog("2stime fr=%d\n", std_time.fr);
 #endif /* HAVE_LOCALE_H */
                len = 8;
                if (bind_size > 0)
-                   *((SDOUBLE *) rgbValueBindRow) = atof(neut_str);
+                   *((SDOUBLE *) rgbValueBindRow) = get_double_value(neut_str);
                else
-                   *((SDOUBLE *) rgbValue + bind_row) = atof(neut_str);
+                   *((SDOUBLE *) rgbValue + bind_row) = get_double_value(neut_str);
 #ifdef HAVE_LOCALE_H
                setlocale(LC_ALL, saved_locale);
                free(saved_locale);
@@ -2656,7 +2688,7 @@ inner_process_tokens(QueryParse *qp, QueryBuild *qb)
            mylog("%s convert_escape error\n", func);
            return SQL_ERROR;
        }
-       if (isalnum(F_OldPtr(qp)[1]))
+       if (isalnum((UCHAR)F_OldPtr(qp)[1]))
            CVT_APPEND_CHAR(qb, ' ');
        return SQL_SUCCESS;
    }
@@ -3155,6 +3187,8 @@ ResolveOneParam(QueryBuild *qb, QueryParse *qp)
    ParameterInfoClass  *apara;
    ParameterImplClass  *ipara;
    BOOL outputDiscard, valueOutput;
+   SDOUBLE dbv;
+   SFLOAT  flv;
 
    outputDiscard = (0 != (qb->flags & FLGB_DISCARD_OUTPUT));
    valueOutput = (0 == (qb->flags & (FLGB_PRE_EXECUTING | FLGB_BUILDING_PREPARE_STATEMENT)));
@@ -3425,13 +3459,35 @@ mylog("C_WCHAR=%s(%d)\n", buffer, used);
 #endif /* UNICODE_SUPPORT */
 
        case SQL_C_DOUBLE:
-           sprintf(param_string, "%.15g",
-                       *((SDOUBLE *) buffer));
+           dbv = *((SDOUBLE *) buffer);
+#ifdef WIN32
+           if (_finite(dbv))
+#endif /* WIN32 */
+           sprintf(param_string, "%.15g", dbv);
+#ifdef WIN32
+           else if (_isnan(dbv))
+               strcpy(param_string, NAN_STRING);
+           else if (dbv < .0)
+               strcpy(param_string, MINFINITY_STRING);
+           else 
+               strcpy(param_string, INFINITY_STRING);
+#endif /* WIN32 */
            break;
 
        case SQL_C_FLOAT:
-           sprintf(param_string, "%.6g",
-                   *((SFLOAT *) buffer));
+           flv = *((SFLOAT *) buffer);
+#ifdef WIN32
+           if (_finite(flv))
+#endif /* WIN32 */
+           sprintf(param_string, "%.6g", flv);
+#ifdef WIN32
+           else if (_isnan(flv))
+               strcpy(param_string, NAN_STRING);
+           else if (flv < .0)
+               strcpy(param_string, MINFINITY_STRING);
+           else 
+               strcpy(param_string, INFINITY_STRING);
+#endif /* WIN32 */
            break;
 
        case SQL_C_SLONG:
@@ -4042,7 +4098,7 @@ convert_escape(QueryParse *qp, QueryBuild *qb)
     
    /* Avoid the concatenation of the function name with the previous word. Aceto */
 
-   if (F_NewPos(qb) > 0 && isalnum(F_NewPtr(qb)[-1]))
+   if (F_NewPos(qb) > 0 && isalnum((UCHAR)F_NewPtr(qb)[-1]))
        CVT_APPEND_CHAR(qb, ' ');
    
    if (stricmp(key, "d") == 0)
@@ -4864,10 +4920,9 @@ convert_lo(StatementClass *stmt, const void *value, SQLSMALLINT fCType, PTR rgbV
            odbc_lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET);
        }
    }
-   mylog("lo data left = %d\n", left);
-
-   if (left == 0)
+   else if (left == 0)
        return COPY_NO_DATA_FOUND;
+   mylog("lo data left = %d\n", left);
 
    if (stmt->lobj_fd < 0)
    {
@@ -4875,7 +4930,10 @@ convert_lo(StatementClass *stmt, const void *value, SQLSMALLINT fCType, PTR rgbV
        return COPY_GENERAL_ERROR;
    }
 
-   retval = odbc_lo_read(conn, stmt->lobj_fd, (char *) rgbValue, (Int4) (factor > 1 ? (cbValueMax - 1) / factor : cbValueMax));
+   if (0 >= cbValueMax)
+       retval = 0;
+   else
+       retval = odbc_lo_read(conn, stmt->lobj_fd, (char *) rgbValue, (Int4) (factor > 1 ? (cbValueMax - 1) / factor : cbValueMax));
    if (retval < 0)
    {
        odbc_lo_close(conn, stmt->lobj_fd);
index 6257a58007426c2c695b6bf1964beea6e3bd66fb..94d4f989ae890d3a1a56d960c98af6a4d52945f2 100644 (file)
@@ -27,8 +27,8 @@
 
 extern GLOBAL_VALUES globals;
 
-static void encode(const char *in, char *out);
-static void decode(const char *in, char *out);
+static void encode(const UCHAR *in, UCHAR *out);
+static void decode(const UCHAR *in, UCHAR *out);
 
 UInt4  getExtraOptions(const ConnInfo *ci)
 {
@@ -1319,27 +1319,29 @@ getCommonDefaults(const char *section, const char *filename, ConnInfo *ci)
 }
 
 static void
-encode(const char *in, char *out)
+encode(const UCHAR *in, UCHAR *out)
 {
    size_t i, ilen = strlen(in),
                o = 0;
+   UCHAR   inc;
 
    for (i = 0; i < ilen; i++)
    {
-       if (in[i] == '+')
+       inc = in[i];
+       if (inc == '+')
        {
            sprintf(&out[o], "%%2B");
            o += 3;
        }
-       else if (isspace((UCHAR) in[i]))
+       else if (isspace(inc))
            out[o++] = '+';
-       else if (!isalnum((UCHAR) in[i]))
+       else if (!isalnum(inc))
        {
-           sprintf(&out[o], "%%%02x", (UCHAR) in[i]);
+           sprintf(&out[o], "%%%02x", inc);
            o += 3;
        }
        else
-           out[o++] = in[i];
+           out[o++] = inc;
    }
    out[o++] = '\0';
 }
@@ -1367,22 +1369,24 @@ conv_from_hex(const UCHAR *s)
 }
 
 static void
-decode(const char *in, char *out)
+decode(const UCHAR *in, UCHAR *out)
 {
    size_t i, ilen = strlen(in),
                o = 0;
+   UCHAR   inc;
 
    for (i = 0; i < ilen; i++)
    {
-       if (in[i] == '+')
+       inc = in[i];
+       if (inc == '+')
            out[o++] = ' ';
-       else if (in[i] == '%')
+       else if (inc == '%')
        {
            sprintf(&out[o++], "%c", conv_from_hex(&in[i]));
            i += 2;
        }
        else
-           out[o++] = in[i];
+           out[o++] = inc;
    }
    out[o++] = '\0';
 }
index 4ffb585b3e61a846064863c103cf1a0ef56390ef..ac7e04eb5aea6fe4c5dd8ee7e60346a9b30a4756 100644 (file)
@@ -1465,6 +1465,8 @@ inolog("%s: stmt=%p ommitted++\n", func, self);
        /* reset for SQLGetData */
        gdata->gdata[lf].data_left = -1;
 
+       if (NULL == opts->bindings)
+           continue;
        if (opts->bindings[lf].buffer != NULL)
        {
            /* this column has a binding */
index 8ed970c5cf9b594bbf6f8b9447c9adc51ba84288..8ddd82de2a3d6f1c2dc2463f097698ca2efa508f 100644 (file)
--- a/version.h
+++ b/version.h
@@ -11,6 +11,6 @@
 
 #define POSTGRESDRIVERVERSION      "08.02.0203"
 #define POSTGRES_RESOURCE_VERSION  "08.02.0203\0"
-#define PG_DRVFILE_VERSION     8,2,02,03
+#define PG_DRVFILE_VERSION     8,2,02,03 
 
 #endif