object handling.
2. Add support for NaN and (-)Infinity float values.
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;
/*
* 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);
}
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,
QR_set_command(res, cmdbuffer);
query_completed = TRUE;
mylog("send_query: returning res = %p\n", res);
- if (!before_64)
+ if (!beforeV2)
break;
/*
/*
* There was no ReadyForQuery response before 6.4.
*/
- if (before_64)
+ if (beforeV2)
{
if (empty_reqs == 0 && query_completed)
break;
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);
#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);
}
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 */
}
- if (PROTOCOL_74(ci))
+ if (sinceV3)
SOCK_put_int(sock, 1, 2); /* result format is binary */
mylog(" done sending args\n");
mylog(" after flush output\n");
done = FALSE;
+ resultResponse = FALSE; /* for before V3 only */
while (!done)
{
id = SOCK_get_id(sock);
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)
{
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':
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)
/* 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)
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)
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
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;
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;
#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);
#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);
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;
}
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)));
#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:
/* 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)
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)
{
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);
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)
{
}
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';
}
}
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';
}
/* 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 */
#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