Re-enable ANSI/Unicode compilation.
authorDave Page <dpage@pgadmin.org>
Tue, 6 Sep 2005 07:47:26 +0000 (07:47 +0000)
committerDave Page <dpage@pgadmin.org>
Tue, 6 Sep 2005 07:47:26 +0000 (07:47 +0000)
18 files changed:
Makefile.am
configure.ac
connection.c
convert.c
dlg_specific.h
execute.c
info.c
info30.c
installer/psqlodbcm.wxs
multibyte.c
options.c
pgtypes.c
psqlodbc.h
psqlodbc.rc
psqlodbc.reg
psqlodbca.def [new file with mode: 0644]
psqlodbcw.def [moved from psqlodbc_win32.def with 98% similarity]
win32.mak

index 46f328ddb96e539b1e78a3b2bad68258b382f6d8..e9d50d3fa0b17b579dfda5461b8d5f19528eb8ac 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile.am for psqlodbc (PostgreSQL ODBC driver)
 #
-# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.22 2005/08/27 23:19:32 dpage Exp $
+# $Header: /home/heikki/psqlodbc-cvs-copy/psqlodbc/Makefile.am,v 1.23 2005/09/06 07:47:25 dpage Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -17,9 +17,9 @@ psqlodbc_la_SOURCES = \
    environ.c execute.c lobj.c win_md5.c misc.c options.c \
    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 odbcapi30w.c odbcapiw.c \
+   multibyte.c \
    odbcapi30.c pgapi30.c info30.c descriptor.c \
-    win_unicode.c
+   win_unicode.c
 
 psqlodbc_la_SOURCES += \
    bind.h columninfo.h connection.h convert.h descriptor.h \
@@ -28,25 +28,31 @@ psqlodbc_la_SOURCES += \
    psqlodbc.h qresult.h resource.h socket.h statement.h tuple.h \
    tuplelist.h version.h
 
+if enable_unicode   
+psqlodbc_la_SOURCES += \    
+   odbcapi30w.c odbcapiw.c win_unicode.c    
+endif
+
 EXTRA_psqlodbc_la_SOURCES = md5.c
 
 EXTRA_DIST = license.txt readme.txt odbcinst.ini \
-   libtool.m4 psqlodbc_win32.def win32.mak \
+   libtool.m4 psqlodbca.def psqlodbcw.def win32.mak \
    dlg_wingui.c win_setup.h win_md5.c setup.c \
-   psqlodbc.rc psqlodbc.reg \\r
-    docs/index.html docs/config.html \\r
-    docs/faq.html docs/howto-accesslo.html \\r
-    docs/howto-accessvba.html docs/howto-bo.html \\r
-    docs/howto-ch.html docs/howto-csharp.html \\r
-    docs/howto-debian.html docs/howto-redhat.html \\r
-    docs/howto-vb.html docs/howto-vblo.html \\r
-    docs/unix-compilation.html docs/win32-compilation.html \
-    installer/banner.bmp installer/lgpl.rtf \\r
-    installer/new.bmp installer/up.bmp \
-    installer/Make.bat installer/psqlodbc.wxs \
-    installer/psqlodbcm.wxs installer/README.txt
+   win_unicode.c psqlodbc.rc psqlodbc.reg \
+   docs/index.html docs/config.html \
+   docs/faq.html docs/howto-accesslo.html \
+   docs/howto-accessvba.html docs/howto-bo.html \
+   docs/howto-ch.html docs/howto-csharp.html \
+   docs/howto-debian.html docs/howto-redhat.html \
+   docs/howto-vb.html docs/howto-vblo.html \
+   docs/unix-compilation.html docs/win32-compilation.html \
+   installer/banner.bmp installer/lgpl.rtf \
+   installer/new.bmp installer/up.bmp \
+   installer/Make.bat installer/psqlodbc.wxs \
+   installer/psqlodbcm.wxs installer/README.txt
    
 MAINTAINERCLEANFILES = \
    Makefile.in config.guess config.h.in config.sub configure \
    install-sh missing mkinstalldirs aclocal.m4 ltmain.sh \
    libtool.m4 depcomp
+
index bf0362a71d926e202b8e51269972d030056b06fe..2ffa64f38e787dc4ee11e6cf1b789118e18bb32b 100644 (file)
@@ -1,5 +1,5 @@
 # Process this file with autoconf to produce a configure script.\r
-AC_INIT(psqlodbclibpq, 08.01.0004, [pgsql-odbc@postgresql.org])\r
+AC_INIT(psqlodbc, 08.01.0004, [pgsql-odbc@postgresql.org])\r
 AC_PREREQ(2.52)\r
 AM_INIT_AUTOMAKE\r
 AC_CONFIG_SRCDIR([bind.c])\r
@@ -54,6 +54,19 @@ PGAC_ARG_REQ(with, odbcver, [  --with-odbcver=VERSION  change default ODBC versi
 AC_MSG_RESULT([$with_odbcver])\r
 AC_DEFINE_UNQUOTED(ODBCVER, [$with_odbcver], [Define to ODBC version (--with-odbcver)])\r
 \r
+# to implement the Unicode driver   \r
+PGAC_ARG_BOOL(enable, unicode, yes,     \r
+   [  --enable-unicode        build ODBC driver for Unicode [[yes]]],   \r
+   [AC_DEFINE(UNICODE_SUPPORT, 1,   \r
+       [Define to 1 to build with Unicode support (--enable-unicode)])      \r
+    AC_DEFINE(UNICODE, [],      \r
+       [Define to use wide APIs])   \r
+    AC_DEFINE(SQL_NOUNICODEMAP, [],     \r
+       [Define to disable mapping SQL* to SQL*W])   \r
+    AC_CHECK_FUNCS(iswascii)])      \r
+    \r
+AM_CONDITIONAL(enable_unicode, [test x"$enable_unicode" = xyes])\r
+\r
 AC_CHECK_FUNCS(strtoul strtoll)\r
 \r
 # to implement the thread-safe driver\r
index 4901841557c3a12dbe2e5e8e706cab2190392cfb..6b8703d67f2434b989d5e13644f74834586f4547 100644 (file)
@@ -1541,7 +1541,7 @@ another_version_retry:
        CC_lookup_characterset(self);
        if (CC_get_errornumber(self) != 0)
            return 0;
-       
+#ifdef UNICODE_SUPPORT
        if (self->unicode)
        {
            if (!self->client_encoding ||
@@ -1565,13 +1565,18 @@ another_version_retry:
                }
            }
        }
+#else   
+       {    
+       }    
+#endif /* UNICODE_SUPPORT */    
    }
+#ifdef UNICODE_SUPPORT
    else if (self->unicode)
    {
        CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4");
        return 0;
    }
-
+#endif /* UNICODE_SUPPORT */
    ci->updatable_cursors = 0;
 #ifdef DRIVER_CURSOR_IMPLEMENT
    if (!ci->drivers.use_declarefetch &&
@@ -2701,7 +2706,7 @@ CC_connect(ConnectionClass *self, char password_req, char *salt_para)
        CC_lookup_characterset(self);
        if (CC_get_errornumber(self) != 0)
            return 0;
-
+#ifdef UNICODE_SUPPORT
        if (self->unicode)
        {
            if (!self->client_encoding ||
@@ -2726,13 +2731,18 @@ CC_connect(ConnectionClass *self, char password_req, char *salt_para)
                }
            }
        }
+#else   
+       {    
+       }    
+#endif /* UNICODE_SUPPORT */    
    }
+#ifdef UNICODE_SUPPORT
    else if (self->unicode)
    {
        CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4");
        return 0;
    }
-
+#endif /* UNICODE_SUPPORT */
    ci->updatable_cursors = 0;
 #ifdef DRIVER_CURSOR_IMPLEMENT
    if (!ci->drivers.use_declarefetch &&
index 8af19683c9510261fe7826e37525aa8aa4b3c8a3..4f7dc4cb2dc0a095c8c7ed17e09b7ca11dfc715b 100644 (file)
--- a/convert.c
+++ b/convert.c
-/*-------\r
- * Module:              convert.c\r
- *\r
- * Description:    This module contains routines related to\r
- *                converting parameters and columns into requested data types.\r
- *                Parameters are converted from their SQL_C data types into\r
- *                the appropriate postgres type.  Columns are converted from\r
- *                their postgres type (SQL type) into the appropriate SQL_C\r
- *                data type.\r
- *\r
- * Classes:           n/a\r
- *\r
- * API functions:  none\r
- *\r
- * Comments:      See "notice.txt" for copyright and license information.\r
- *-------\r
- */\r
-/* Multibyte support  Eiji Tokuya  2001-03-15  */\r
-\r
-#include "convert.h"\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-\r
-#include "multibyte.h"\r
-\r
-#include <time.h>\r
-#ifdef HAVE_LOCALE_H\r
-#include <locale.h>\r
-#endif\r
-#include <math.h>\r
-#include <stdlib.h>\r
-#include "statement.h"\r
-#include "qresult.h"\r
-#include "bind.h"\r
-#include "pgtypes.h"\r
-#include "lobj.h"\r
-\r
-#ifdef USE_LIBPQ\r
-#include "libpqconnection.h"\r
-#else\r
-#include "connection.h"\r
-#endif /* USE_LIBPQ */\r
-\r
-#include "pgapifunc.h"\r
-\r
-#ifdef __CYGWIN__\r
-#  define TIMEZONE_GLOBAL _timezone\r
-#elif  defined(WIN32) || defined(HAVE_INT_TIMEZONE)\r
-#  ifdef __BORLANDC__\r
-#    define timezone _timzone\r
-#    define daylight _daylight\r
-#    define TIMEZONE_GLOBAL _timezone\r
-#  else\r
-#    define TIMEZONE_GLOBAL timezone\r
-#  endif\r
-#endif\r
-\r
-/*\r
- * How to map ODBC scalar functions {fn func(args)} to PostgreSQL.\r
- * This is just a simple substitution.  List augmented from:\r
- * http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm\r
- * - thomas 2000-04-03\r
- */\r
-char      *mapFuncs[][2] = {\r
-/* { "ASCII",       "ascii"      }, built_in */\r
-   {"CHAR", "chr($*)" },\r
-   {"CONCAT", "textcat($*)" },\r
-/* { "DIFFERENCE", "difference" }, how to ? */\r
-   {"INSERT", "substring($1 from 1 for $2 - 1) || $4 || substring($1 from $2 + $3)" },\r
-   {"LCASE", "lower($*)" },\r
-   {"LEFT", "substring($1 for $2)" },\r
-   {"%2LOCATE", "strpos($2,  $1)" },   /* 2 parameters */\r
-   {"%3LOCATE", "strpos(substring($2 from $3), $1) + $3 - 1" },    /* 3 parameters */\r
-/* { "LENGTH",      "length"     }, built_in */\r
-/* { "LTRIM",       "ltrim"      }, built_in */\r
-   {"RIGHT", "substring($1 from char_length($1) - $2 + 1)" },\r
-   {"SPACE", "repeat(' ', $1)" },\r
-/* { "REPEAT",      "repeat"     }, built_in */\r
-/* { "REPLACE",         "replace"    }, built_in */\r
-/* { "RTRIM",       "rtrim"      }, built_in */\r
-/* { "SOUNDEX", "soundex" }, how to ? */\r
-   {"SUBSTRING", "substr($*)" },\r
-   {"UCASE", "upper($*)" },\r
-\r
-/* { "ABS",         "abs"        }, built_in */\r
-/* { "ACOS",        "acos"       }, built_in */\r
-/* { "ASIN",        "asin"       }, built_in */\r
-/* { "ATAN",        "atan"       }, built_in */\r
-/* { "ATAN2",       "atan2"      }, built_in */\r
-   {"CEILING", "ceil($*)" },\r
-/* { "COS",         "cos"        }, built_in */\r
-/* { "COT",         "cot"        }, built_in */\r
-/* { "DEGREES",         "degrees"    }, built_in */\r
-/* { "EXP",         "exp"        }, built_in */\r
-/* { "FLOOR",       "floor"      }, built_in */\r
-   {"LOG", "ln($*)" },\r
-   {"LOG10", "log($*)" },\r
-/* { "MOD",         "mod"        }, built_in */\r
-/* { "PI",          "pi"         }, built_in */\r
-   {"POWER", "pow($*)" },\r
-/* { "RADIANS",         "radians"    }, built_in */\r
-   {"%0RAND", "random()" },    /* 0 parameters */\r
-   {"%1RAND", "(setseed($1) * .0 + random())" },   /* 1 parameters */\r
-/* { "ROUND",       "round"      }, built_in */\r
-/* { "SIGN",        "sign"       }, built_in */\r
-/* { "SIN",         "sin"        }, built_in */\r
-/* { "SQRT",        "sqrt"       }, built_in */\r
-/* { "TAN",         "tan"        }, built_in */\r
-   {"TRUNCATE", "trunc($*)" },\r
-\r
-   {"CURRENT_DATE", "current_date" },\r
-   {"%0CURRENT_TIME", "current_time" },\r
-   {"%1CURRENT_TIME", "current_time($1)" },\r
-   {"%0CURRENT_TIMESTAMP", "current_timestamp" },\r
-   {"%1CURRENT_TIMESTAMP", "current_timestamp($1)" },\r
-   {"%0LOCALTIME", "localtime" },\r
-   {"%1LOCALTIME", "localtime($1)" },\r
-   {"%0LOCALTIMESTAMP", "localtimestamp" },\r
-   {"%1LOCALTIMESTAMP", "localtimestamp($1)" },\r
-   {"CURDATE",  "current_date" },\r
-   {"CURTIME",  "current_time" },\r
-   {"DAYNAME",  "to_char($1, 'Day')" },\r
-   {"DAYOFMONTH",  "cast(extract(day from $1) as integer)" },\r
-   {"DAYOFWEEK",    "(cast(extract(dow from $1) as integer) + 1)" },\r
-   {"DAYOFYEAR",    "cast(extract(doy from $1) as integer)" }, \r
-   {"HOUR",     "cast(extract(hour from $1) as integer)" },\r
-   {"MINUTE",  "cast(extract(minute from $1) as integer)" },\r
-   {"MONTH",   "cast(extract(month from $1) as integer)" },\r
-   {"MONTHNAME",    " to_char($1, 'Month')" },\r
-/* { "NOW",         "now"        }, built_in */\r
-   {"QUARTER",  "cast(extract(quarter from $1) as integer)" },\r
-   {"SECOND",  "cast(extract(second from $1) as integer)" },\r
-   {"WEEK",    "cast(extract(week from $1) as integer)" },\r
-   {"YEAR",    "cast(extract(year from $1) as integer)" },\r
-\r
-   {"DATABASE", "current_database()" },\r
-   {"IFNULL", "coalesce($*)" },\r
-   {"USER", "cast(current_user as text)" },\r
-   {"CURRENT_USER", "cast(current_user as text)" },\r
-   {"SESSION_USER", "cast(session_user as text)" },\r
-   {0, 0}\r
-};\r
-\r
-static const char *mapFunction(const char *func, int param_count);\r
-static unsigned int conv_from_octal(const UCHAR *s);\r
-static unsigned int conv_from_hex(const UCHAR *s);\r
-static char *conv_to_octal(UCHAR val, char *octal);\r
-static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);\r
-\r
-/*---------\r
- *         A Guide for date/time/timestamp conversions\r
- *\r
- *         field_type      fCType              Output\r
- *         ----------      ------              ----------\r
- *         PG_TYPE_DATE    SQL_C_DEFAULT       SQL_C_DATE\r
- *         PG_TYPE_DATE    SQL_C_DATE          SQL_C_DATE\r
- *         PG_TYPE_DATE    SQL_C_TIMESTAMP     SQL_C_TIMESTAMP     (time = 0 (midnight))\r
- *         PG_TYPE_TIME    SQL_C_DEFAULT       SQL_C_TIME\r
- *         PG_TYPE_TIME    SQL_C_TIME          SQL_C_TIME\r
- *         PG_TYPE_TIME    SQL_C_TIMESTAMP     SQL_C_TIMESTAMP     (date = current date)\r
- *         PG_TYPE_ABSTIME SQL_C_DEFAULT       SQL_C_TIMESTAMP\r
- *         PG_TYPE_ABSTIME SQL_C_DATE          SQL_C_DATE          (time is truncated)\r
- *         PG_TYPE_ABSTIME SQL_C_TIME          SQL_C_TIME          (date is truncated)\r
- *         PG_TYPE_ABSTIME SQL_C_TIMESTAMP     SQL_C_TIMESTAMP\r
- *---------\r
- */\r
-\r
-\r
-/*\r
- * Macros for unsigned long handling.\r
- */\r
-#ifdef WIN32\r
-#define    ATOI32U atol\r
-#elif  defined(HAVE_STRTOUL)\r
-#define    ATOI32U(val)    strtoul(val, NULL, 10)\r
-#else /* HAVE_STRTOUL */\r
-#define    ATOI32U atol\r
-#endif /* WIN32 */\r
-\r
-/*\r
- * Macros for BIGINT handling.\r
- */\r
-#ifdef ODBCINT64\r
-#ifdef WIN32\r
-#define    ATOI64  _atoi64\r
-#define    ATOI64U _atoi64\r
-#define    FORMATI64   "%I64d"\r
-#define    FORMATI64U  "%I64u"\r
-#elif  defined(HAVE_STRTOLL)\r
-#define    ATOI64(val) strtoll(val, NULL, 10)\r
-#define    ATOI64U(val)    strtoull(val, NULL, 10)\r
-#define    FORMATI64   "%lld"\r
-#define    FORMATI64U  "%llu"\r
-#else /* HAVE_STRTOLL */\r
-#endif /* WIN32 */\r
-#endif /* ODBCINT64 */\r
-\r
-/*\r
- * TIMESTAMP <-----> SIMPLE_TIME\r
- *     precision support since 7.2.\r
- *     time zone support is unavailable(the stuff is unreliable)\r
- */\r
-static BOOL\r
-timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)\r
-{\r
-   char        rest[64],\r
-              *ptr;\r
-   int         scnt,\r
-               i;\r
-#ifdef TIMEZONE_GLOBAL\r
-   long        timediff;\r
-#endif\r
-   BOOL        withZone = *bZone;\r
-\r
-   *bZone = FALSE;\r
-   *zone = 0;\r
-   st->fr = 0;\r
-   st->infinity = 0;\r
-   rest[0] = '\0';\r
-   if ((scnt = sscanf(str, "%4d-%2d-%2d %2d:%2d:%2d%32s", &st->y, &st->m, &st->d, &st->hh, &st->mm, &st->ss, rest)) < 6)\r
-       return FALSE;\r
-   else if (scnt == 6)\r
-       return TRUE;\r
-   switch (rest[0])\r
-   {\r
-       case '+':\r
-           *bZone = TRUE;\r
-           *zone = atoi(&rest[1]);\r
-           break;\r
-       case '-':\r
-           *bZone = TRUE;\r
-           *zone = -atoi(&rest[1]);\r
-           break;\r
-       case '.':\r
-           if ((ptr = strchr(rest, '+')) != NULL)\r
-           {\r
-               *bZone = TRUE;\r
-               *zone = atoi(&ptr[1]);\r
-               *ptr = '\0';\r
-           }\r
-           else if ((ptr = strchr(rest, '-')) != NULL)\r
-           {\r
-               *bZone = TRUE;\r
-               *zone = -atoi(&ptr[1]);\r
-               *ptr = '\0';\r
-           }\r
-           for (i = 1; i < 10; i++)\r
-           {\r
-               if (!isdigit((UCHAR) rest[i]))\r
-                   break;\r
-           }\r
-           for (; i < 10; i++)\r
-               rest[i] = '0';\r
-           rest[i] = '\0';\r
-           st->fr = atoi(&rest[1]);\r
-           break;\r
-       default:\r
-           return TRUE;\r
-   }\r
-   if (!withZone || !*bZone || st->y < 1970)\r
-       return TRUE;\r
-#ifdef TIMEZONE_GLOBAL\r
-   if (!tzname[0] || !tzname[0][0])\r
-   {\r
-       *bZone = FALSE;\r
-       return TRUE;\r
-   }\r
-   timediff = TIMEZONE_GLOBAL + (*zone) * 3600;\r
-   if (!daylight && timediff == 0)     /* the same timezone */\r
-       return TRUE;\r
-   else\r
-   {\r
-       struct tm   tm,\r
-                  *tm2;\r
-       time_t      time0;\r
-\r
-       *bZone = FALSE;\r
-       tm.tm_year = st->y - 1900;\r
-       tm.tm_mon = st->m - 1;\r
-       tm.tm_mday = st->d;\r
-       tm.tm_hour = st->hh;\r
-       tm.tm_min = st->mm;\r
-       tm.tm_sec = st->ss;\r
-       tm.tm_isdst = -1;\r
-       time0 = mktime(&tm);\r
-       if (time0 < 0)\r
-           return TRUE;\r
-       if (tm.tm_isdst > 0)\r
-           timediff -= 3600;\r
-       if (timediff == 0)      /* the same time zone */\r
-           return TRUE;\r
-       time0 -= timediff;\r
-#ifdef HAVE_LOCALTIME_R\r
-       if (time0 >= 0 && (tm2 = localtime_r(&time0, &tm)) != NULL)\r
-#else\r
-       if (time0 >= 0 && (tm2 = localtime(&time0)) != NULL)\r
-#endif /* HAVE_LOCALTIME_R */\r
-       {\r
-           st->y = tm2->tm_year + 1900;\r
-           st->m = tm2->tm_mon + 1;\r
-           st->d = tm2->tm_mday;\r
-           st->hh = tm2->tm_hour;\r
-           st->mm = tm2->tm_min;\r
-           st->ss = tm2->tm_sec;\r
-           *bZone = TRUE;\r
-       }\r
-   }\r
-#endif /* TIMEZONE_GLOBAL */\r
-   return TRUE;\r
-}\r
-\r
-static BOOL\r
-stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)\r
-{\r
-   char        precstr[16],\r
-               zonestr[16];\r
-   int         i;\r
-\r
-   precstr[0] = '\0';\r
-   if (st->infinity > 0)\r
-   {\r
-       strcpy(str, "Infinity");\r
-       return TRUE;\r
-   }\r
-   else if (st->infinity < 0)\r
-   {\r
-       strcpy(str, "-Infinity");\r
-       return TRUE;\r
-   }\r
-   if (precision && st->fr)\r
-   {\r
-       sprintf(precstr, ".%09d", st->fr);\r
-       for (i = 9; i > 0; i--)\r
-       {\r
-           if (precstr[i] != '0')\r
-               break;\r
-           precstr[i] = '\0';\r
-       }\r
-   }\r
-   zonestr[0] = '\0';\r
-#ifdef TIMEZONE_GLOBAL\r
-   if (bZone && tzname[0] && tzname[0][0] && st->y >= 1970)\r
-   {\r
-       long        zoneint;\r
-       struct tm   tm;\r
-       time_t      time0;\r
-\r
-       zoneint = TIMEZONE_GLOBAL;\r
-       if (daylight && st->y >= 1900)\r
-       {\r
-           tm.tm_year = st->y - 1900;\r
-           tm.tm_mon = st->m - 1;\r
-           tm.tm_mday = st->d;\r
-           tm.tm_hour = st->hh;\r
-           tm.tm_min = st->mm;\r
-           tm.tm_sec = st->ss;\r
-           tm.tm_isdst = -1;\r
-           time0 = mktime(&tm);\r
-           if (time0 >= 0 && tm.tm_isdst > 0)\r
-               zoneint -= 3600;\r
-       }\r
-       if (zoneint > 0)\r
-           sprintf(zonestr, "-%02d", (int) zoneint / 3600);\r
-       else\r
-           sprintf(zonestr, "+%02d", -(int) zoneint / 3600);\r
-   }\r
-#endif /* TIMEZONE_GLOBAL */\r
-   sprintf(str, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d%s%s", st->y, st->m, st->d, st->hh, st->mm, st->ss, precstr, zonestr);\r
-   return TRUE;\r
-}\r
-\r
-/* This is called by SQLFetch() */\r
-int\r
-copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col)\r
-{\r
-   ARDFields *opts = SC_get_ARDF(stmt);\r
-   BindInfoClass *bic = &(opts->bindings[col]);\r
-   UInt4   offset = opts->row_offset_ptr ? *opts->row_offset_ptr : 0;\r
-\r
-   SC_set_current_col(stmt, -1);\r
-   return copy_and_convert_field(stmt, field_type, value, (Int2) bic->returntype, (PTR) (bic->buffer + offset),\r
-                            (SDWORD) bic->buflen, (SDWORD *) (bic->used + (offset >> 2)));\r
-}\r
-\r
-\r
-/* This is called by SQLGetData() */\r
-int\r
-copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,\r
-                      PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue)\r
-{\r
-   CSTR func = "copy_and_convert_field";\r
-   ARDFields   *opts = SC_get_ARDF(stmt);\r
-   GetDataInfo *gdata = SC_get_GDTI(stmt);\r
-   Int4        len = 0,\r
-               copy_len = 0;\r
-   SIMPLE_TIME std_time;\r
-   time_t      stmt_t = SC_get_time(stmt);\r
-   struct tm  *tim;\r
-#ifdef HAVE_LOCALTIME_R\r
-   struct tm  tm;\r
-#endif /* HAVE_LOCALTIME_R */\r
-   int         pcbValueOffset,\r
-               rgbValueOffset;\r
-   char       *rgbValueBindRow, *pcbValueBindRow = NULL;\r
-   const char *ptr;\r
-   int         bind_row = stmt->bind_row;\r
-   int         bind_size = opts->bind_size;\r
-   int         result = COPY_OK;\r
-   ConnectionClass     *conn = SC_get_conn(stmt);\r
-   BOOL        changed, true_is_minus1 = FALSE;\r
-   const char *neut_str = value;\r
-   char        midtemp[2][32];\r
-   int         mtemp_cnt = 0;\r
-   GetDataClass *pgdc;\r
-   BOOL    wchanged =   FALSE;\r
-#ifdef WIN32\r
-   SQLWCHAR    *allocbuf = NULL;\r
-   Int4        wstrlen;    \r
-#endif /* WIN32 */\r
-\r
-   if (stmt->current_col >= 0)\r
-   {\r
-       if (stmt->current_col >= opts->allocated)\r
-       {\r
-           return SQL_ERROR;\r
-       }\r
-       if (gdata->allocated != opts->allocated)\r
-           extend_getdata_info(gdata, opts->allocated, TRUE);\r
-       pgdc = &gdata->gdata[stmt->current_col];\r
-       if (pgdc->data_left == -2)\r
-           pgdc->data_left = (cbValueMax > 0) ? 0 : -1; /* This seems to be *\r
-                        * needed by ADO ? */\r
-       if (pgdc->data_left == 0)\r
-       {\r
-           if (pgdc->ttlbuf != NULL)\r
-           {\r
-               free(pgdc->ttlbuf);\r
-               pgdc->ttlbuf = NULL;\r
-               pgdc->ttlbuflen = 0;\r
-           }\r
-           pgdc->data_left = -2;       /* needed by ADO ? */\r
-           return COPY_NO_DATA_FOUND;\r
-       }\r
-   }\r
-   /*---------\r
-    *  rgbValueOffset is *ONLY* for character and binary data.\r
-    *  pcbValueOffset is for computing any pcbValue location\r
-    *---------\r
-    */\r
-\r
-   if (bind_size > 0)\r
-       pcbValueOffset = rgbValueOffset = (bind_size * bind_row);\r
-   else\r
-   {\r
-       pcbValueOffset = bind_row * sizeof(SDWORD);\r
-       rgbValueOffset = bind_row * cbValueMax;\r
-   }\r
-   /*\r
-    *  The following is applicable in case bind_size > 0\r
-    *  or the fCType is of variable length. \r
-    */\r
-   rgbValueBindRow = (char *) rgbValue + rgbValueOffset;\r
-   if (pcbValue)\r
-       pcbValueBindRow = (char *) pcbValue + pcbValueOffset;\r
-\r
-   memset(&std_time, 0, sizeof(SIMPLE_TIME));\r
-\r
-   /* Initialize current date */\r
-#ifdef HAVE_LOCALTIME_R\r
-   tim = localtime_r(&stmt_t, &tm);\r
-#else\r
-   tim = localtime(&stmt_t);\r
-#endif /* HAVE_LOCALTIME_R */\r
-   std_time.m = tim->tm_mon + 1;\r
-   std_time.d = tim->tm_mday;\r
-   std_time.y = tim->tm_year + 1900;\r
-\r
-   mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "<NULL>" : value, cbValueMax);\r
-   if (!value)\r
-   {\r
-       /*\r
-        * handle a null just by returning SQL_NULL_DATA in pcbValue, and\r
-        * doing nothing to the buffer.\r
-        */\r
-       if (pcbValue)\r
-       {\r
-           *((SDWORD *) pcbValueBindRow) = SQL_NULL_DATA;\r
-           return COPY_OK;\r
-       }\r
-       else\r
-       {\r
-           SC_set_error(stmt, STMT_RETURN_NULL_WITHOUT_INDICATOR, "StrLen_or_IndPtr was a null pointer and NULL data was retrieved");  \r
-           SC_log_error(func, "", stmt);\r
-           return  SQL_ERROR;\r
-       }\r
-   }\r
-\r
-   if (stmt->hdbc->DataSourceToDriver != NULL)\r
-   {\r
-       int         length = strlen(value);\r
-\r
-       stmt->hdbc->DataSourceToDriver(stmt->hdbc->translation_option,\r
-                                      SQL_CHAR,\r
-                                      value, length,\r
-                                      value, length, NULL,\r
-                                      NULL, 0, NULL);\r
-   }\r
-\r
-   /*\r
-    * First convert any specific postgres types into more useable data.\r
-    *\r
-    * NOTE: Conversions from PG char/varchar of a date/time/timestamp value\r
-    * to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported\r
-    */\r
-   switch (field_type)\r
-   {\r
-           /*\r
-            * $$$ need to add parsing for date/time/timestamp strings in\r
-            * PG_TYPE_CHAR,VARCHAR $$$\r
-            */\r
-       case PG_TYPE_DATE:\r
-           sscanf(value, "%4d-%2d-%2d", &std_time.y, &std_time.m, &std_time.d);\r
-           break;\r
-\r
-       case PG_TYPE_TIME:\r
-           sscanf(value, "%2d:%2d:%2d", &std_time.hh, &std_time.mm, &std_time.ss);\r
-           break;\r
-\r
-       case PG_TYPE_ABSTIME:\r
-       case PG_TYPE_DATETIME:\r
-       case PG_TYPE_TIMESTAMP_NO_TMZONE:\r
-       case PG_TYPE_TIMESTAMP:\r
-           std_time.fr = 0;\r
-           std_time.infinity = 0;\r
-           if (strnicmp(value, "infinity", 8) == 0)\r
-           {\r
-               std_time.infinity = 1;\r
-               std_time.m = 12;\r
-               std_time.d = 31;\r
-               std_time.y = 9999;\r
-               std_time.hh = 23;\r
-               std_time.mm = 59;\r
-               std_time.ss = 59;\r
-           }\r
-           if (strnicmp(value, "-infinity", 9) == 0)\r
-           {\r
-               std_time.infinity = -1;\r
-               std_time.m = 0;\r
-               std_time.d = 0;\r
-               std_time.y = 0;\r
-               std_time.hh = 0;\r
-               std_time.mm = 0;\r
-               std_time.ss = 0;\r
-           }\r
-           if (strnicmp(value, "invalid", 7) != 0)\r
-           {\r
-               BOOL        bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(conn, 7.2));\r
-               int         zone;\r
-\r
-               /*\r
-                * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &std_time.y, &std_time.m,\r
-                * &std_time.d, &std_time.hh, &std_time.mm, &std_time.ss);\r
-                */\r
-               bZone = FALSE;  /* time zone stuff is unreliable */\r
-               timestamp2stime(value, &std_time, &bZone, &zone);\r
-inolog("2stime fr=%d\n", std_time.fr);\r
-           }\r
-           else\r
-           {\r
-               /*\r
-                * The timestamp is invalid so set something conspicuous,\r
-                * like the epoch\r
-                */\r
-               time_t  t = 0;\r
-#ifdef HAVE_LOCALTIME_R\r
-               tim = localtime_r(&t, &tm);\r
-#else\r
-               tim = localtime(&t);\r
-#endif /* HAVE_LOCALTIME_R */\r
-               std_time.m = tim->tm_mon + 1;\r
-               std_time.d = tim->tm_mday;\r
-               std_time.y = tim->tm_year + 1900;\r
-               std_time.hh = tim->tm_hour;\r
-               std_time.mm = tim->tm_min;\r
-               std_time.ss = tim->tm_sec;\r
-           }\r
-           break;\r
-\r
-       case PG_TYPE_BOOL:\r
-           {                   /* change T/F to 1/0 */\r
-               char       *s;\r
-\r
-               s = midtemp[mtemp_cnt];\r
-               switch (((char *)value)[0])\r
-               {\r
-                   case 'f':\r
-                   case 'F':\r
-                   case 'n':\r
-                   case 'N':\r
-                   case '0':\r
-                       strcpy(s, "0");\r
-                       break;\r
-                   default:\r
-                       if (true_is_minus1)\r
-                           strcpy(s, "-1");\r
-                       else\r
-                           strcpy(s, "1");\r
-               }\r
-               neut_str = midtemp[mtemp_cnt];\r
-               mtemp_cnt++;\r
-           }\r
-           break;\r
-\r
-           /* This is for internal use by SQLStatistics() */\r
-       case PG_TYPE_INT2VECTOR:\r
-           {\r
-               int         nval,\r
-                           i;\r
-               const char *vp;\r
-\r
-               /* this is an array of eight integers */\r
-               short      *short_array = (short *) rgbValueBindRow;\r
-\r
-               len = INDEX_KEYS_STORAGE_COUNT * 2;\r
-               vp = value;\r
-               nval = 0;\r
-               mylog("index=(");\r
-               for (i = 0; i < INDEX_KEYS_STORAGE_COUNT; i++)\r
-               {\r
-                   if (sscanf(vp, "%hd", &short_array[i]) != 1)\r
-                       break;\r
-\r
-                   mylog(" %d", short_array[i]);\r
-                   nval++;\r
-\r
-                   /* skip the current token */\r
-                   while ((*vp != '\0') && (!isspace((UCHAR) *vp)))\r
-                       vp++;\r
-                   /* and skip the space to the next token */\r
-                   while ((*vp != '\0') && (isspace((UCHAR) *vp)))\r
-                       vp++;\r
-                   if (*vp == '\0')\r
-                       break;\r
-               }\r
-               mylog(") nval = %d\n", nval);\r
-\r
-               for (i = nval; i < INDEX_KEYS_STORAGE_COUNT; i++)\r
-                   short_array[i] = 0;\r
-\r
-#if 0\r
-               sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",\r
-                      &short_array[0],\r
-                      &short_array[1],\r
-                      &short_array[2],\r
-                      &short_array[3],\r
-                      &short_array[4],\r
-                      &short_array[5],\r
-                      &short_array[6],\r
-                      &short_array[7]);\r
-#endif\r
-\r
-               /* There is no corresponding fCType for this. */\r
-               if (pcbValue)\r
-                   *((SDWORD *) pcbValueBindRow) = len;\r
-\r
-               return COPY_OK; /* dont go any further or the data will be\r
-                                * trashed */\r
-           }\r
-\r
-           /*\r
-            * This is a large object OID, which is used to store\r
-            * LONGVARBINARY objects.\r
-            */\r
-       case PG_TYPE_LO_UNDEFINED:\r
-\r
-           return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SDWORD *) pcbValueBindRow);\r
-\r
-       default:\r
-\r
-           if (field_type == stmt->hdbc->lobj_type)    /* hack until permanent\r
-                                                        * type available */\r
-               return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SDWORD *) pcbValueBindRow);\r
-   }\r
-\r
-   /* Change default into something useable */\r
-   if (fCType == SQL_C_DEFAULT)\r
-   {\r
-       fCType = pgtype_to_ctype(stmt, field_type);\r
-\r
-       mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);\r
-   }\r
-\r
-   if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR\r
-       || fCType == INTERNAL_ASIS_TYPE)\r
-   {\r
-       /* Special character formatting as required */\r
-\r
-       /*\r
-        * These really should return error if cbValueMax is not big\r
-        * enough.\r
-        */\r
-       switch (field_type)\r
-       {\r
-           case PG_TYPE_DATE:\r
-               len = 10;\r
-               if (cbValueMax > len)\r
-                   sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", std_time.y, std_time.m, std_time.d);\r
-               break;\r
-\r
-           case PG_TYPE_TIME:\r
-               len = 8;\r
-               if (cbValueMax > len)\r
-                   sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", std_time.hh, std_time.mm, std_time.ss);\r
-               break;\r
-\r
-           case PG_TYPE_ABSTIME:\r
-           case PG_TYPE_DATETIME:\r
-           case PG_TYPE_TIMESTAMP_NO_TMZONE:\r
-           case PG_TYPE_TIMESTAMP:\r
-               len = 19;\r
-               if (cbValueMax > len)\r
-                   sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",\r
-                           std_time.y, std_time.m, std_time.d, std_time.hh, std_time.mm, std_time.ss);\r
-               break;\r
-\r
-           case PG_TYPE_BOOL:\r
-               len = strlen(neut_str);\r
-               if (cbValueMax > len)\r
-               {\r
-                   strcpy(rgbValueBindRow, neut_str);\r
-                   mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow);\r
-               }\r
-               break;\r
-\r
-               /*\r
-                * Currently, data is SILENTLY TRUNCATED for BYTEA and\r
-                * character data types if there is not enough room in\r
-                * cbValueMax because the driver can't handle multiple\r
-                * calls to SQLGetData for these, yet.  Most likely, the\r
-                * buffer passed in will be big enough to handle the\r
-                * maximum limit of postgres, anyway.\r
-                *\r
-                * LongVarBinary types are handled correctly above, observing\r
-                * truncation and all that stuff since there is\r
-                * essentially no limit on the large object used to store\r
-                * those.\r
-                */\r
-           case PG_TYPE_BYTEA:/* convert binary data to hex strings\r
-                                * (i.e, 255 = "FF") */\r
-\r
-           default:\r
-               if (stmt->current_col < 0)\r
-               {\r
-                   pgdc = &(gdata->fdata);\r
-                   pgdc->data_left = -1;\r
-               }\r
-               else\r
-                   pgdc = &gdata->gdata[stmt->current_col];\r
-               if (pgdc->data_left < 0)\r
-               {\r
-                   BOOL lf_conv = conn->connInfo.lf_conversion;\r
-\r
-                   if (fCType == SQL_C_WCHAR)\r
-                   {\r
-                       len = utf8_to_ucs2_lf(neut_str, -1, lf_conv, NULL, 0);\r
-                       len *= WCLEN;\r
-                       wchanged = changed = TRUE;\r
-                   }\r
-                   else\r
-\r
-                   if (PG_TYPE_BYTEA == field_type)\r
-                   {\r
-                       len = convert_from_pgbinary(neut_str, NULL, 0);\r
-                       len *= 2;\r
-                       changed = TRUE;\r
-                   }\r
-                   else\r
-#ifdef WIN32\r
-                   if (fCType == SQL_C_CHAR)\r
-                   {\r
-                       wstrlen = utf8_to_ucs2_lf(neut_str, -1, lf_conv, NULL, 0);\r
-                       allocbuf = (SQLWCHAR *) malloc(WCLEN * (wstrlen + 1));\r
-                       wstrlen = utf8_to_ucs2_lf(neut_str, -1, lf_conv, allocbuf, wstrlen + 1);\r
-                       len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) allocbuf, wstrlen, NULL, 0, NULL, NULL);\r
-                       changed = TRUE;\r
-                   }\r
-                   else\r
-#endif /* WIN32 */\r
-                       /* convert linefeeds to carriage-return/linefeed */\r
-                       len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);\r
-                   if (cbValueMax == 0)        /* just returns length\r
-                                                * info */\r
-                   {\r
-                       result = COPY_RESULT_TRUNCATED;\r
-#ifdef WIN32\r
-                       if (allocbuf)\r
-                           free(allocbuf);\r
-#endif /* WIN32 */\r
-                       break;\r
-                   }\r
-                   if (!pgdc->ttlbuf)\r
-                       pgdc->ttlbuflen = 0;\r
-                   if (changed || len >= cbValueMax)\r
-                   {\r
-                       if (len >= (int) pgdc->ttlbuflen)\r
-                       {\r
-                           pgdc->ttlbuf = realloc(pgdc->ttlbuf, len + 1);\r
-                           pgdc->ttlbuflen = len + 1;\r
-                       }\r
-\r
-                       if (fCType == SQL_C_WCHAR)\r
-                       {\r
-                           utf8_to_ucs2_lf(neut_str, -1, lf_conv, (SQLWCHAR *) pgdc->ttlbuf, len / WCLEN);\r
-                       }\r
-                       else\r
-\r
-                       if (PG_TYPE_BYTEA == field_type)\r
-                       {\r
-                           len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);\r
-                           pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);\r
-                           len *= 2; \r
-                       }\r
-                       else\r
-#ifdef WIN32\r
-                       if (fCType == SQL_C_CHAR)\r
-                       {\r
-                           len = WideCharToMultiByte(CP_ACP, 0, allocbuf, wstrlen, pgdc->ttlbuf, pgdc->ttlbuflen, NULL, NULL);\r
-                           free(allocbuf);\r
-                           allocbuf = NULL;\r
-                       }\r
-                       else\r
-#endif /* WIN32 */\r
-                           convert_linefeeds(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen, lf_conv, &changed);\r
-                       ptr = pgdc->ttlbuf;\r
-                       pgdc->ttlbufused = len;\r
-                   }\r
-                   else\r
-                   {\r
-                       if (pgdc->ttlbuf)\r
-                       {\r
-                           free(pgdc->ttlbuf);\r
-                           pgdc->ttlbuf = NULL;\r
-                       }\r
-                       ptr = neut_str;\r
-                   }\r
-               }\r
-               else\r
-               {\r
-                   ptr = pgdc->ttlbuf;\r
-                   len = pgdc->ttlbufused;\r
-               }\r
-\r
-               mylog("DEFAULT: len = %d, ptr = '%s'\n", len, ptr);\r
-\r
-               if (stmt->current_col >= 0)\r
-               {\r
-                   if (pgdc->data_left > 0)\r
-                   {\r
-                       ptr += len - pgdc->data_left;\r
-                       len = pgdc->data_left;\r
-                   }\r
-                   else\r
-                       pgdc->data_left = len;\r
-               }\r
-\r
-               if (cbValueMax > 0)\r
-               {\r
-                   BOOL    already_copied = FALSE;\r
-\r
-                   copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;\r
-\r
-                   if (fCType == SQL_C_WCHAR)\r
-                   {\r
-                       copy_len /= WCLEN;\r
-                       copy_len *= WCLEN;\r
-                   }\r
-#ifdef HAVE_LOCALE_H\r
-                   switch (field_type)\r
-                   {\r
-                       case PG_TYPE_FLOAT4:\r
-                       case PG_TYPE_FLOAT8:\r
-                       case PG_TYPE_NUMERIC:\r
-                       {\r
-                           struct lconv    *lc;\r
-                           char        *new_string;\r
-                           int     i, j;\r
-\r
-                           new_string = malloc(cbValueMax);\r
-                           lc = localeconv();\r
-                           for (i = 0, j = 0; ptr[i]; i++)\r
-                               if (ptr[i] == '.')\r
-                               {\r
-                                   strncpy(&new_string[j], lc->decimal_point, strlen(lc->decimal_point));\r
-                                   j += strlen(lc->decimal_point);\r
-                               }\r
-                               else\r
-                                   new_string[j++] = ptr[i];\r
-                           new_string[j] = '\0';\r
-                           strncpy_null(rgbValueBindRow, new_string, copy_len + 1);\r
-                           free(new_string);\r
-                           already_copied = TRUE;\r
-                           break;\r
-                       }\r
-                   }\r
-#endif /* HAVE_LOCALE_H */\r
-                   if (!already_copied)\r
-                   {\r
-                       /* Copy the data */\r
-                       memcpy(rgbValueBindRow, ptr, copy_len);\r
-                       /* Add null terminator */\r
-\r
-                       if (fCType == SQL_C_WCHAR)\r
-                           memset(rgbValueBindRow + copy_len, 0, WCLEN);\r
-                       else\r
-\r
-                       rgbValueBindRow[copy_len] = '\0';\r
-                   }\r
-                   /* Adjust data_left for next time */\r
-                   if (stmt->current_col >= 0)\r
-                       pgdc->data_left -= copy_len;\r
-               }\r
-\r
-               /*\r
-                * Finally, check for truncation so that proper status can\r
-                * be returned\r
-                */\r
-               if (cbValueMax > 0 && len >= cbValueMax)\r
-                   result = COPY_RESULT_TRUNCATED;\r
-               else\r
-               {\r
-                   if (pgdc->ttlbuf != NULL)\r
-                   {\r
-                       free(pgdc->ttlbuf);\r
-                       pgdc->ttlbuf = NULL;\r
-                   }\r
-               }\r
-\r
-\r
-               mylog("    SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow);\r
-               break;\r
-       }\r
-\r
-       if (SQL_C_WCHAR == fCType && ! wchanged)\r
-       {\r
-           if (cbValueMax > (SDWORD) (WCLEN * (len + 1)))\r
-           {\r
-               char *str = strdup(rgbValueBindRow);\r
-               UInt4   ucount = utf8_to_ucs2(str, len, (SQLWCHAR *) rgbValueBindRow, cbValueMax / WCLEN);\r
-               if (cbValueMax < (SDWORD) (WCLEN * ucount))\r
-                   result = COPY_RESULT_TRUNCATED;\r
-               free(str); \r
-           }\r
-           else\r
-           {\r
-                if ((SDWORD) (len + WCLEN) <= cbValueMax)\r
-                {\r
-                    result = COPY_OK;\r
-                }\r
-                else\r
-                    result = COPY_RESULT_TRUNCATED; \r
-           }\r
-       }\r
-\r
-   }\r
-   else\r
-   {\r
-       /*\r
-        * for SQL_C_CHAR, it's probably ok to leave currency symbols in.\r
-        * But to convert to numeric types, it is necessary to get rid of\r
-        * those.\r
-        */\r
-       if (field_type == PG_TYPE_MONEY)\r
-       {\r
-           if (convert_money(neut_str, midtemp[mtemp_cnt], sizeof(midtemp[0])))\r
-           {\r
-               neut_str = midtemp[mtemp_cnt];\r
-               mtemp_cnt++;\r
-           }\r
-           else\r
-           {\r
-               qlog("couldn't convert money type to %d\n", fCType);\r
-               return COPY_UNSUPPORTED_TYPE;\r
-           }\r
-       }\r
-\r
-       switch (fCType)\r
-       {\r
-           case SQL_C_DATE:\r
-           case SQL_C_TYPE_DATE:       /* 91 */\r
-\r
-               len = 6;\r
-               {\r
-                   DATE_STRUCT *ds;\r
-\r
-                   if (bind_size > 0)\r
-                       ds = (DATE_STRUCT *) rgbValueBindRow;\r
-                   else\r
-                       ds = (DATE_STRUCT *) rgbValue + bind_row;\r
-                   ds->year = std_time.y;\r
-                   ds->month = std_time.m;\r
-                   ds->day = std_time.d;\r
-               }\r
-               break;\r
-\r
-           case SQL_C_TIME:\r
-           case SQL_C_TYPE_TIME:       /* 92 */\r
-\r
-               len = 6;\r
-               {\r
-                   TIME_STRUCT *ts;\r
-\r
-                   if (bind_size > 0)\r
-                       ts = (TIME_STRUCT *) rgbValueBindRow;\r
-                   else\r
-                       ts = (TIME_STRUCT *) rgbValue + bind_row;\r
-                   ts->hour = std_time.hh;\r
-                   ts->minute = std_time.mm;\r
-                   ts->second = std_time.ss;\r
-               }\r
-               break;\r
-\r
-           case SQL_C_TIMESTAMP:\r
-           case SQL_C_TYPE_TIMESTAMP:  /* 93 */\r
-\r
-               len = 16;\r
-               {\r
-                   TIMESTAMP_STRUCT *ts;\r
-\r
-                   if (bind_size > 0)\r
-                       ts = (TIMESTAMP_STRUCT *) rgbValueBindRow;\r
-                   else\r
-                       ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row;\r
-                   ts->year = std_time.y;\r
-                   ts->month = std_time.m;\r
-                   ts->day = std_time.d;\r
-                   ts->hour = std_time.hh;\r
-                   ts->minute = std_time.mm;\r
-                   ts->second = std_time.ss;\r
-                   ts->fraction = std_time.fr;\r
-               }\r
-               break;\r
-\r
-           case SQL_C_BIT:\r
-               len = 1;\r
-               if (bind_size > 0)\r
-                   *((UCHAR *) rgbValueBindRow) = atoi(neut_str);\r
-               else\r
-                   *((UCHAR *) rgbValue + bind_row) = atoi(neut_str);\r
-\r
-               /*\r
-                * mylog("SQL_C_BIT: bind_row = %d val = %d, cb = %d,\r
-                * rgb=%d\n", bind_row, atoi(neut_str), cbValueMax,\r
-                * *((UCHAR *)rgbValue));\r
-                */\r
-               break;\r
-\r
-           case SQL_C_STINYINT:\r
-           case SQL_C_TINYINT:\r
-               len = 1;\r
-               if (bind_size > 0)\r
-                   *((SCHAR *) rgbValueBindRow) = atoi(neut_str);\r
-               else\r
-                   *((SCHAR *) rgbValue + bind_row) = atoi(neut_str);\r
-               break;\r
-\r
-           case SQL_C_UTINYINT:\r
-               len = 1;\r
-               if (bind_size > 0)\r
-                   *((UCHAR *) rgbValueBindRow) = atoi(neut_str);\r
-               else\r
-                   *((UCHAR *) rgbValue + bind_row) = atoi(neut_str);\r
-               break;\r
-\r
-           case SQL_C_FLOAT:\r
-           {\r
-#ifdef HAVE_LOCALE_H\r
-               char *saved_locale;\r
-\r
-               saved_locale = strdup(setlocale(LC_ALL, NULL));\r
-               setlocale(LC_ALL, "C");\r
-#endif /* HAVE_LOCALE_H */\r
-               len = 4;\r
-               if (bind_size > 0)\r
-                   *((SFLOAT *) rgbValueBindRow) = (float) atof(neut_str);\r
-               else\r
-                   *((SFLOAT *) rgbValue + bind_row) = (float) atof(neut_str);\r
-#ifdef HAVE_LOCALE_H\r
-               setlocale(LC_ALL, saved_locale);\r
-               free(saved_locale);\r
-#endif /* HAVE_LOCALE_H */\r
-               break;\r
-           }\r
-\r
-           case SQL_C_DOUBLE:\r
-           {\r
-#ifdef HAVE_LOCALE_H\r
-               char *saved_locale;\r
-\r
-               saved_locale = strdup(setlocale(LC_ALL, NULL));\r
-               setlocale(LC_ALL, "C");\r
-#endif /* HAVE_LOCALE_H */\r
-               len = 8;\r
-               if (bind_size > 0)\r
-                   *((SDOUBLE *) rgbValueBindRow) = atof(neut_str);\r
-               else\r
-                   *((SDOUBLE *) rgbValue + bind_row) = atof(neut_str);\r
-#ifdef HAVE_LOCALE_H\r
-               setlocale(LC_ALL, saved_locale);\r
-               free(saved_locale);\r
-#endif /* HAVE_LOCALE_H */\r
-               break;\r
-           }\r
-\r
-           case SQL_C_NUMERIC:\r
-           {\r
-               SQL_NUMERIC_STRUCT      *ns;\r
-               int i, nlen, bit, hval, tv, dig, sta, olen;\r
-               char    calv[SQL_MAX_NUMERIC_LEN * 3];\r
-               const char *wv;\r
-               BOOL    dot_exist;\r
-\r
-               len = sizeof(SQL_NUMERIC_STRUCT);\r
-               if (bind_size > 0)\r
-                   ns = (SQL_NUMERIC_STRUCT *) rgbValueBindRow;\r
-               else\r
-                   ns = (SQL_NUMERIC_STRUCT *) rgbValue + bind_row;\r
-               for (wv = neut_str; *wv && isspace(*wv); wv++)\r
-                   ;\r
-               ns->sign = 1;\r
-               if (*wv == '-')\r
-               {\r
-                   ns->sign = 0;\r
-                   wv++;\r
-               }\r
-               else if (*wv == '+')\r
-                   wv++;\r
-               while (*wv == '0') wv++;\r
-               ns->precision = 0;\r
-               ns->scale = 0;\r
-               for (nlen = 0, dot_exist = FALSE;; wv++) \r
-               {\r
-                   if (*wv == '.')\r
-                   {\r
-                       if (dot_exist)\r
-                           break;\r
-                       dot_exist = TRUE;\r
-                   }\r
-                   else if (!isdigit(*wv))\r
-                       break;\r
-                   else\r
-                   {\r
-                       if (dot_exist)\r
-                           ns->scale++;\r
-\r
-                       ns->precision++;\r
-                       calv[nlen++] = *wv;\r
-                   }\r
-               }\r
-               memset(ns->val, 0, sizeof(ns->val));\r
-               for (hval = 0, bit = 1L, sta = 0, olen = 0; sta < nlen;)\r
-               {\r
-                   for (dig = 0, i = sta; i < nlen; i++)\r
-                   {\r
-                       tv = dig * 10 + calv[i] - '0';\r
-                       dig = tv % 2;\r
-                       calv[i] = tv / 2 + '0';\r
-                       if (i == sta && tv < 2)\r
-                           sta++;\r
-                   }\r
-                   if (dig > 0)\r
-                       hval |= bit;\r
-                   bit <<= 1;\r
-                   if (bit >= (1L << 8))\r
-                   {\r
-                       ns->val[olen++] = hval;\r
-                       hval = 0;\r
-                       bit = 1L;\r
-                       if (olen >= SQL_MAX_NUMERIC_LEN - 1)\r
-                       {\r
-                           ns->scale = sta - ns->precision;\r
-                           break;\r
-                       }\r
-                   } \r
-               }\r
-               if (hval && olen < SQL_MAX_NUMERIC_LEN - 1)\r
-                   ns->val[olen++] = hval;\r
-\r
-               break;\r
-           }\r
-\r
-           case SQL_C_SSHORT:\r
-           case SQL_C_SHORT:\r
-               len = 2;\r
-               if (bind_size > 0)\r
-                   *((SWORD *) rgbValueBindRow) = atoi(neut_str);\r
-               else\r
-                   *((SWORD *) rgbValue + bind_row) = atoi(neut_str);\r
-               break;\r
-\r
-           case SQL_C_USHORT:\r
-               len = 2;\r
-               if (bind_size > 0)\r
-                   *((UWORD *) rgbValueBindRow) = atoi(neut_str);\r
-               else\r
-                   *((UWORD *) rgbValue + bind_row) = atoi(neut_str);\r
-               break;\r
-\r
-           case SQL_C_SLONG:\r
-           case SQL_C_LONG:\r
-               len = 4;\r
-               if (bind_size > 0)\r
-                   *((SDWORD *) rgbValueBindRow) = atol(neut_str);\r
-               else\r
-                   *((SDWORD *) rgbValue + bind_row) = atol(neut_str);\r
-               break;\r
-\r
-           case SQL_C_ULONG:\r
-               len = 4;\r
-               if (bind_size > 0)\r
-                   *((UDWORD *) rgbValueBindRow) = ATOI32U(neut_str);\r
-               else\r
-                   *((UDWORD *) rgbValue + bind_row) = ATOI32U(neut_str);\r
-               break;\r
-\r
-#ifdef ODBCINT64\r
-           case SQL_C_SBIGINT:\r
-           case SQL_BIGINT: /* Is this needed ? */\r
-               len = 8;\r
-               if (bind_size > 0)\r
-                   *((SQLBIGINT *) rgbValueBindRow) = ATOI64(neut_str);\r
-               else\r
-                   *((SQLBIGINT *) rgbValue + bind_row) = ATOI64(neut_str);\r
-               break;\r
-\r
-           case SQL_C_UBIGINT:\r
-               len = 8;\r
-               if (bind_size > 0)\r
-                   *((SQLUBIGINT *) rgbValueBindRow) = ATOI64U(neut_str);\r
-               else\r
-                   *((SQLUBIGINT *) rgbValue + bind_row) = ATOI64U(neut_str);\r
-               break;\r
-\r
-#endif /* ODBCINT64 */\r
-           case SQL_C_BINARY:\r
-               if (PG_TYPE_UNKNOWN == field_type ||\r
-                   PG_TYPE_TEXT == field_type ||\r
-                   PG_TYPE_VARCHAR == field_type ||\r
-                   PG_TYPE_BPCHAR == field_type)\r
-               {\r
-                   int len = SQL_NULL_DATA;\r
-\r
-                   if (neut_str)\r
-                       len = strlen(neut_str);\r
-                   if (pcbValue)\r
-                       *((SDWORD *) pcbValueBindRow) = len;\r
-                   if (len > 0 && cbValueMax > 0)\r
-                   {\r
-                       memcpy(rgbValueBindRow, neut_str, len < cbValueMax ? len : cbValueMax);\r
-                       if (cbValueMax >= len + 1)\r
-                           rgbValueBindRow[len] = '\0';\r
-                   }\r
-                   if (cbValueMax >= len)\r
-                       return COPY_OK;\r
-                   else\r
-                       return COPY_RESULT_TRUNCATED;\r
-               }\r
-               /* The following is for SQL_C_VARBOOKMARK */\r
-               else if (PG_TYPE_INT4 == field_type)\r
-               {\r
-                   UInt4   ival = ATOI32U(neut_str);\r
-\r
-inolog("SQL_C_VARBOOKMARK value=%d\n", ival);\r
-                   if (pcbValue)\r
-                       *((SDWORD *) pcbValueBindRow) = sizeof(ival);\r
-                   if (cbValueMax >= sizeof(ival))\r
-                   {\r
-                       memcpy(rgbValueBindRow, &ival, sizeof(ival));\r
-                       return COPY_OK;\r
-                   }\r
-                   else    \r
-                       return COPY_RESULT_TRUNCATED;\r
-               }\r
-               else if (PG_TYPE_BYTEA != field_type)\r
-               {\r
-                   mylog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);\r
-                   qlog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);\r
-                   return COPY_UNSUPPORTED_TYPE;\r
-               }\r
-               /* truncate if necessary */\r
-               /* convert octal escapes to bytes */\r
-\r
-               if (stmt->current_col < 0)\r
-               {\r
-                   pgdc = &(gdata->fdata);\r
-                   pgdc->data_left = -1;\r
-               }\r
-               else\r
-                   pgdc = &gdata->gdata[stmt->current_col];\r
-               if (!pgdc->ttlbuf)\r
-                   pgdc->ttlbuflen = 0;\r
-               if (pgdc->data_left < 0)\r
-               {\r
-                   if (cbValueMax <= 0)\r
-                   {\r
-                       len = convert_from_pgbinary(neut_str, NULL, 0);\r
-                       result = COPY_RESULT_TRUNCATED;\r
-                       break;\r
-                   }\r
-                   if (len = strlen(neut_str), len >= (int) pgdc->ttlbuflen)\r
-                   {\r
-                       pgdc->ttlbuf = realloc(pgdc->ttlbuf, len + 1);\r
-                       pgdc->ttlbuflen = len + 1;\r
-                   }\r
-                   len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);\r
-                   pgdc->ttlbufused = len;\r
-               }\r
-               else\r
-                   len = pgdc->ttlbufused;\r
-               ptr = pgdc->ttlbuf;\r
-\r
-               if (stmt->current_col >= 0)\r
-               {\r
-                   /*\r
-                    * Second (or more) call to SQLGetData so move the\r
-                    * pointer\r
-                    */\r
-                   if (pgdc->data_left > 0)\r
-                   {\r
-                       ptr += len - pgdc->data_left;\r
-                       len = pgdc->data_left;\r
-                   }\r
-\r
-                   /* First call to SQLGetData so initialize data_left */\r
-                   else\r
-                       pgdc->data_left = len;\r
-\r
-               }\r
-\r
-               if (cbValueMax > 0)\r
-               {\r
-                   copy_len = (len > cbValueMax) ? cbValueMax : len;\r
-\r
-                   /* Copy the data */\r
-                   memcpy(rgbValueBindRow, ptr, copy_len);\r
-\r
-                   /* Adjust data_left for next time */\r
-                   if (stmt->current_col >= 0)\r
-                       pgdc->data_left -= copy_len;\r
-               }\r
-\r
-               /*\r
-                * Finally, check for truncation so that proper status can\r
-                * be returned\r
-                */\r
-               if (len > cbValueMax)\r
-                   result = COPY_RESULT_TRUNCATED;\r
-               else if (pgdc->ttlbuf)\r
-               {\r
-                   free(pgdc->ttlbuf);\r
-                   pgdc->ttlbuf = NULL;\r
-               }\r
-               mylog("SQL_C_BINARY: len = %d, copy_len = %d\n", len, copy_len);\r
-               break;\r
-\r
-           default:\r
-               qlog("conversion to the type %d isn't supported\n", fCType);\r
-               return COPY_UNSUPPORTED_TYPE;\r
-       }\r
-   }\r
-\r
-   /* store the length of what was copied, if there's a place for it */\r
-   if (pcbValue)\r
-       *((SDWORD *) pcbValueBindRow) = len;\r
-\r
-   if (result == COPY_OK && stmt->current_col >= 0)\r
-       gdata->gdata[stmt->current_col].data_left = 0;\r
-   return result;\r
-\r
-}\r
-\r
-\r
-/*--------------------------------------------------------------------\r
- * Functions/Macros to get rid of query size limit.\r
- *\r
- * I always used the follwoing macros to convert from\r
- * old_statement to new_statement.  Please improve it\r
- * if you have a better way.   Hiroshi 2001/05/22\r
- *--------------------------------------------------------------------\r
- */\r
-\r
-#define    FLGP_PREPARE_DUMMY_CURSOR   1L\r
-#define    FLGP_CURSOR_CHECK_OK    (1L << 1)\r
-#define    FLGP_SELECT_INTO        (1L << 2)\r
-#define    FLGP_SELECT_FOR_UPDATE  (1L << 3)\r
-#define    FLGP_BUILDING_PREPARE_STATEMENT (1L << 4)\r
-typedef struct _QueryParse {\r
-   const char  *statement;\r
-   int     statement_type;\r
-   UInt4       opos;\r
-   int     from_pos;\r
-   int     where_pos;\r
-   UInt4       stmt_len;\r
-   BOOL        in_quote, in_dquote, in_escape;\r
-   char        token_save[64];\r
-   int     token_len;\r
-   BOOL        prev_token_end;\r
-   BOOL        proc_no_param;\r
-   unsigned    int declare_pos;\r
-   UInt4       flags;\r
-   encoded_str encstr;\r
-}  QueryParse;\r
-\r
-static int\r
-QP_initialize(QueryParse *q, const StatementClass *stmt)\r
-{\r
-   q->statement = stmt->execute_statement ? stmt->execute_statement : stmt->statement;\r
-   q->statement_type = stmt->statement_type;\r
-   q->opos = 0;\r
-   q->from_pos = -1;\r
-   q->where_pos = -1;\r
-   q->stmt_len = (q->statement) ? strlen(q->statement) : -1;\r
-   q->in_quote = q->in_dquote = q->in_escape = FALSE;\r
-   q->token_save[0] = '\0';\r
-   q->token_len = 0;\r
-   q->prev_token_end = TRUE;\r
-   q->proc_no_param = TRUE;\r
-   q->declare_pos = 0;\r
-   q->flags = 0;\r
-   make_encoded_str(&q->encstr, SC_get_conn(stmt), q->statement);\r
-\r
-   return q->stmt_len;\r
-}\r
-\r
-#define    FLGB_PRE_EXECUTING  1L\r
-#define    FLGB_INACCURATE_RESULT  (1L << 1)\r
-#define    FLGB_CREATE_KEYSET  (1L << 2)\r
-#define    FLGB_KEYSET_DRIVEN  (1L << 3)\r
-#define    FLGB_BUILDING_PREPARE_STATEMENT (1L << 4)\r
-typedef struct _QueryBuild {\r
-   char    *query_statement;\r
-   UInt4   str_size_limit;\r
-   UInt4   str_alsize;\r
-   UInt4   npos;\r
-   int current_row;\r
-   int param_number;\r
-   APDFields *apdopts;\r
-   IPDFields *ipdopts;\r
-   PutDataInfo *pdata;\r
-   UInt4   load_stmt_len;\r
-   UInt4   flags;\r
-   BOOL    lf_conv;\r
-   int ccsc;\r
-   int errornumber;\r
-   const char *errormsg;\r
-\r
-   ConnectionClass *conn; /* mainly needed for LO handling */\r
-   StatementClass  *stmt; /* needed to set error info in ENLARGE_.. */ \r
-}  QueryBuild;\r
-\r
-#define INIT_MIN_ALLOC 4096\r
-static int\r
-QB_initialize(QueryBuild *qb, UInt4 size, StatementClass *stmt, ConnectionClass *conn)\r
-{\r
-   UInt4   newsize = 0;\r
-\r
-   qb->flags = 0;\r
-   qb->load_stmt_len = 0;\r
-   qb->stmt = stmt;\r
-   qb->apdopts = NULL;\r
-   qb->ipdopts = NULL;\r
-   qb->pdata = NULL;\r
-   if (conn)\r
-       qb->conn = conn;\r
-   else if (stmt)\r
-   {\r
-       qb->apdopts = SC_get_APDF(stmt);\r
-       qb->ipdopts = SC_get_IPDF(stmt);\r
-       qb->pdata = SC_get_PDTI(stmt);\r
-       qb->conn = SC_get_conn(stmt);\r
-       if (stmt->pre_executing)\r
-           qb->flags |= FLGB_PRE_EXECUTING;\r
-   }\r
-   else\r
-   {\r
-       qb->conn = NULL;\r
-       return -1;\r
-   }\r
-   qb->lf_conv = qb->conn->connInfo.lf_conversion;\r
-   qb->ccsc = qb->conn->ccsc;\r
-       \r
-   if (stmt)\r
-       qb->str_size_limit = stmt->stmt_size_limit;\r
-   else\r
-       qb->str_size_limit = -1;\r
-   if (qb->str_size_limit > 0)\r
-   {\r
-       if (size > qb->str_size_limit)\r
-           return -1;\r
-       newsize = qb->str_size_limit;\r
-   }\r
-   else \r
-   {\r
-       newsize = INIT_MIN_ALLOC;\r
-       while (newsize <= size)\r
-           newsize *= 2;\r
-   }\r
-   if ((qb->query_statement = malloc(newsize)) == NULL)\r
-   {\r
-       qb->str_alsize = 0;\r
-       return -1;\r
-   }   \r
-   qb->query_statement[0] = '\0';\r
-   qb->str_alsize = newsize;\r
-   qb->npos = 0;\r
-   qb->current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;\r
-   qb->param_number = -1;\r
-   qb->errornumber = 0;\r
-   qb->errormsg = NULL;\r
-\r
-   return newsize;\r
-}\r
-\r
-static int\r
-QB_initialize_copy(QueryBuild *qb_to, const QueryBuild *qb_from, UInt4 size)\r
-{\r
-   memcpy(qb_to, qb_from, sizeof(QueryBuild));\r
-\r
-   if (qb_to->str_size_limit > 0)\r
-   {\r
-       if (size > qb_to->str_size_limit)\r
-           return -1;\r
-   }\r
-   if ((qb_to->query_statement = malloc(size)) == NULL)\r
-   {\r
-       qb_to->str_alsize = 0;\r
-       return -1;\r
-   }   \r
-   qb_to->query_statement[0] = '\0';\r
-   qb_to->str_alsize = size;\r
-   qb_to->npos = 0;\r
-\r
-   return size;\r
-}\r
-\r
-static void\r
-QB_Destructor(QueryBuild *qb)\r
-{\r
-   if (qb->query_statement)\r
-   {\r
-       free(qb->query_statement);\r
-       qb->query_statement = NULL;\r
-       qb->str_alsize = 0;\r
-   }\r
-}\r
-\r
-/*\r
- * New macros (Aceto)\r
- *--------------------\r
- */\r
-\r
-#define F_OldChar(qp) \\r
-qp->statement[qp->opos]\r
-\r
-#define F_OldPtr(qp) \\r
-(qp->statement + qp->opos)\r
-\r
-#define F_OldNext(qp) \\r
-(++qp->opos)\r
-\r
-#define F_OldPrior(qp) \\r
-(--qp->opos)\r
-\r
-#define F_OldPos(qp) \\r
-qp->opos\r
-\r
-#define F_ExtractOldTo(qp, buf, ch, maxsize) \\r
-do { \\r
-   unsigned int    c = 0; \\r
-   while (qp->statement[qp->opos] != '\0' && qp->statement[qp->opos] != ch) \\r
-   { \\r
-       buf[c++] = qp->statement[qp->opos++]; \\r
-       if (c >= maxsize - 1) \\r
-           break; \\r
-   } \\r
-   if (qp->statement[qp->opos] == '\0') \\r
-       return SQL_ERROR; \\r
-   buf[c] = '\0'; \\r
-} while (0)\r
-\r
-#define F_NewChar(qb) \\r
-qb->query_statement[qb->npos]\r
-\r
-#define F_NewPtr(qb) \\r
-(qb->query_statement + qb->npos)\r
-\r
-#define F_NewNext(qb) \\r
-(++qb->npos)\r
-\r
-#define F_NewPos(qb) \\r
-(qb->npos)\r
-\r
-\r
-static int\r
-convert_escape(QueryParse *qp, QueryBuild *qb);\r
-static int\r
-inner_process_tokens(QueryParse *qp, QueryBuild *qb);\r
-static int\r
-ResolveOneParam(QueryBuild *qb);\r
-static int\r
-processParameters(QueryParse *qp, QueryBuild *qb,\r
-UInt4 *output_count, Int4 param_pos[][2]);\r
-\r
-static int\r
-enlarge_query_statement(QueryBuild *qb, unsigned int newsize)\r
-{\r
-   unsigned int newalsize = INIT_MIN_ALLOC;\r
-   CSTR func = "enlarge_statement";\r
-\r
-   if (qb->str_size_limit > 0 && qb->str_size_limit < (int) newsize)\r
-   {\r
-       free(qb->query_statement);\r
-       qb->query_statement = NULL;\r
-       qb->str_alsize = 0;\r
-       if (qb->stmt)\r
-       {\r
-           \r
-           SC_set_error(qb->stmt, STMT_EXEC_ERROR, "Query buffer overflow in copy_statement_with_parameters");\r
-           SC_log_error(func, "", qb->stmt);\r
-       }\r
-       else\r
-       {\r
-           qb->errormsg = "Query buffer overflow in copy_statement_with_parameters";\r
-           qb->errornumber = STMT_EXEC_ERROR;\r
-       }\r
-       return -1;\r
-   }\r
-   while (newalsize <= newsize)\r
-       newalsize *= 2;\r
-   if (!(qb->query_statement = realloc(qb->query_statement, newalsize)))\r
-   {\r
-       qb->str_alsize = 0;\r
-       if (qb->stmt)\r
-       {\r
-           SC_set_error(qb->stmt, STMT_EXEC_ERROR, "Query buffer allocate error in copy_statement_with_parameters");\r
-       }\r
-       else\r
-       {\r
-           qb->errormsg = "Query buffer allocate error in copy_statement_with_parameters";\r
-           qb->errornumber = STMT_EXEC_ERROR;\r
-       }\r
-       return 0;\r
-   }\r
-   qb->str_alsize = newalsize;\r
-   return newalsize;\r
-}\r
-\r
-/*----------\r
- * Enlarge stmt_with_params if necessary.\r
- *----------\r
- */\r
-#define ENLARGE_NEWSTATEMENT(qb, newpos) \\r
-   if (newpos >= qb->str_alsize) \\r
-   { \\r
-       if (enlarge_query_statement(qb, newpos) <= 0) \\r
-           return SQL_ERROR; \\r
-   }\r
-\r
-/*----------\r
- * Terminate the stmt_with_params string with NULL.\r
- *----------\r
- */\r
-#define CVT_TERMINATE(qb) \\r
-do { \\r
-   qb->query_statement[qb->npos] = '\0'; \\r
-} while (0)\r
-\r
-/*----------\r
- * Append a data.\r
- *----------\r
- */\r
-#define CVT_APPEND_DATA(qb, s, len) \\r
-do { \\r
-   unsigned int    newpos = qb->npos + len; \\r
-   ENLARGE_NEWSTATEMENT(qb, newpos) \\r
-   memcpy(&qb->query_statement[qb->npos], s, len); \\r
-   qb->npos = newpos; \\r
-   qb->query_statement[newpos] = '\0'; \\r
-} while (0)\r
-\r
-/*----------\r
- * Append a string.\r
- *----------\r
- */\r
-#define CVT_APPEND_STR(qb, s) \\r
-do { \\r
-   unsigned int len = strlen(s); \\r
-   CVT_APPEND_DATA(qb, s, len); \\r
-} while (0)\r
-\r
-/*----------\r
- * Append a char.\r
- *----------\r
- */\r
-#define CVT_APPEND_CHAR(qb, c) \\r
-do { \\r
-   ENLARGE_NEWSTATEMENT(qb, qb->npos + 1); \\r
-   qb->query_statement[qb->npos++] = c; \\r
-} while (0)\r
-\r
-/*----------\r
- * Append a binary data.\r
- * Newly reqeuired size may be overestimated currently.\r
- *----------\r
- */\r
-#define CVT_APPEND_BINARY(qb, buf, used) \\r
-do { \\r
-   unsigned int    newlimit = qb->npos + 5 * used; \\r
-   ENLARGE_NEWSTATEMENT(qb, newlimit); \\r
-   qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used); \\r
-} while (0)\r
-\r
-/*----------\r
- *\r
- *----------\r
- */\r
-#define CVT_SPECIAL_CHARS(qb, buf, used) \\r
-do { \\r
-   int cnvlen = convert_special_chars(buf, NULL, used, qb->lf_conv, qb->ccsc); \\r
-   unsigned int    newlimit = qb->npos + cnvlen; \\r
-\\r
-   ENLARGE_NEWSTATEMENT(qb, newlimit); \\r
-   convert_special_chars(buf, &qb->query_statement[qb->npos], used, qb->lf_conv, qb->ccsc); \\r
-   qb->npos += cnvlen; \\r
-} while (0)\r
-\r
-/*----------\r
- * Check if the statement is\r
- * SELECT ... INTO table FROM .....\r
- * This isn't really a strict check but ...\r
- *----------\r
- */\r
-static BOOL\r
-into_table_from(const char *stmt)\r
-{\r
-   if (strnicmp(stmt, "into", 4))\r
-       return FALSE;\r
-   stmt += 4;\r
-   if (!isspace((UCHAR) *stmt))\r
-       return FALSE;\r
-   while (isspace((UCHAR) *(++stmt)));\r
-   switch (*stmt)\r
-   {\r
-       case '\0':\r
-       case ',':\r
-       case '\'':\r
-           return FALSE;\r
-       case '\"':              /* double quoted table name ? */\r
-           do\r
-           {\r
-               do\r
-                   while (*(++stmt) != '\"' && *stmt);\r
-               while (*stmt && *(++stmt) == '\"');\r
-               while (*stmt && !isspace((UCHAR) *stmt) && *stmt != '\"')\r
-                   stmt++;\r
-           }\r
-           while (*stmt == '\"');\r
-           break;\r
-       default:\r
-           while (!isspace((UCHAR) *(++stmt)));\r
-           break;\r
-   }\r
-   if (!*stmt)\r
-       return FALSE;\r
-   while (isspace((UCHAR) *(++stmt)));\r
-   if (strnicmp(stmt, "from", 4))\r
-       return FALSE;\r
-   return isspace((UCHAR) stmt[4]);\r
-}\r
-\r
-/*----------\r
- * Check if the statement is\r
- * SELECT ... FOR UPDATE .....\r
- * This isn't really a strict check but ...\r
- *----------\r
- */\r
-static BOOL\r
-table_for_update(const char *stmt, int *endpos)\r
-{\r
-   const char *wstmt = stmt;\r
-\r
-   while (isspace((UCHAR) *(++wstmt)));\r
-   if (!*wstmt)\r
-       return FALSE;\r
-   if (strnicmp(wstmt, "update", 6))\r
-       return FALSE;\r
-   wstmt += 6;\r
-   *endpos = wstmt - stmt;\r
-   return !wstmt[0] || isspace((UCHAR) wstmt[0]);\r
-}\r
-\r
-/*----------\r
- * Check if the statement is\r
- * INSERT INTO ... () VALUES ()\r
- * This isn't really a strict check but ...\r
- *----------\r
- */\r
-static BOOL\r
-insert_without_target(const char *stmt, int *endpos)\r
-{\r
-   const char *wstmt = stmt;\r
-\r
-   while (isspace((UCHAR) *(++wstmt)));\r
-   if (!*wstmt)\r
-       return FALSE;\r
-   if (strnicmp(wstmt, "VALUES", 6))\r
-       return FALSE;\r
-   wstmt += 6;\r
-   if (!wstmt[0] || !isspace((UCHAR) wstmt[0]))\r
-       return FALSE;\r
-   while (isspace((UCHAR) *(++wstmt)));\r
-   if (*wstmt != '(' || *(++wstmt) != ')')\r
-       return FALSE;\r
-   wstmt++;\r
-   *endpos = wstmt - stmt;\r
-   return !wstmt[0] || isspace((UCHAR) wstmt[0])\r
-       || ';' == wstmt[0];\r
-}\r
-\r
-static int\r
-Prepare_and_convert(StatementClass *stmt, QueryParse *qp, QueryBuild *qb)\r
-{\r
-   CSTR func = "Prepare_and_convert";\r
-   char    *new_statement, *exe_statement = NULL;\r
-   int retval;\r
-\r
-   if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)\r
-       return SQL_ERROR;\r
-   if (!stmt->prepared) /*  not yet prepared */\r
-   {\r
-       int i, elen;\r
-       SWORD   marker_count;\r
-       const IPDFields *ipdopts = qb->ipdopts;\r
-\r
-       new_statement = qb->query_statement;\r
-       qb->flags = FLGB_BUILDING_PREPARE_STATEMENT;\r
-       sprintf(new_statement, "PREPARE \"_PLAN%0x\"", stmt);\r
-       qb->npos = strlen(new_statement);\r
-       if (SQL_SUCCESS != PGAPI_NumParams(stmt, &marker_count))\r
-       {\r
-           QB_Destructor(qb);\r
-           return SQL_ERROR;\r
-       }\r
-       if (marker_count > 0)\r
-       {\r
-           CVT_APPEND_CHAR(qb, '(');\r
-           for (i = 0; i < marker_count; i++)\r
-           {\r
-               if (i > 0)\r
-                   CVT_APPEND_STR(qb, ", ");\r
-               CVT_APPEND_STR(qb, pgtype_to_name(stmt, ipdopts->parameters[i].PGType));\r
-           }\r
-           CVT_APPEND_CHAR(qb, ')');\r
-       }\r
-       CVT_APPEND_STR(qb, " as ");\r
-       for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)\r
-       {\r
-           retval = inner_process_tokens(qp, qb);\r
-           if (SQL_ERROR == retval)\r
-           {\r
-               if (0 == SC_get_errornumber(stmt))\r
-               {\r
-                   SC_set_error(stmt, qb->errornumber, qb->errormsg);\r
-               }\r
-               SC_log_error(func, "", stmt);\r
-               QB_Destructor(qb);\r
-               return retval;\r
-           }\r
-       }\r
-       CVT_APPEND_CHAR(qb, ';');\r
-       /* build the execute statement */\r
-       exe_statement = malloc(30 + 2 * marker_count);\r
-       sprintf(exe_statement, "EXECUTE \"_PLAN%0x\"", stmt);\r
-       if (marker_count > 0)\r
-       {\r
-           elen = strlen(exe_statement);\r
-           exe_statement[elen++] = '(';\r
-           for (i = 0; i < marker_count; i++)\r
-           {\r
-               if (i > 0)\r
-                   exe_statement[elen++] = ',';\r
-               exe_statement[elen++]  = '?';\r
-           }\r
-           exe_statement[elen++] = ')';\r
-           exe_statement[elen] = '\0';\r
-       }\r
-       stmt->execute_statement = exe_statement;\r
-       QP_initialize(qp, stmt);\r
-   }\r
-   qb->flags = 0;\r
-   qb->param_number = -1;\r
-   for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)\r
-   {\r
-       retval = inner_process_tokens(qp, qb);\r
-       if (SQL_ERROR == retval)\r
-       {\r
-           if (0 == SC_get_errornumber(stmt))\r
-           {\r
-               SC_set_error(stmt, qb->errornumber, qb->errormsg);\r
-           }\r
-           SC_log_error(func, "", stmt);\r
-           if (exe_statement)\r
-           {\r
-               free(exe_statement);\r
-               stmt->execute_statement = NULL;\r
-           }\r
-           QB_Destructor(qb);\r
-           return retval;\r
-       }\r
-   }\r
-   /* make sure new_statement is always null-terminated */\r
-   CVT_TERMINATE(qb);\r
-\r
-   if (exe_statement)\r
-       SC_set_prepare_before_exec(stmt);\r
-   stmt->stmt_with_params = qb->query_statement;\r
-   return SQL_SUCCESS;\r
-}\r
-\r
-#define        my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)\r
-\r
-/*\r
- * This function inserts parameters into an SQL statements.\r
- * It will also modify a SELECT statement for use with declare/fetch cursors.\r
- * This function does a dynamic memory allocation to get rid of query size limit!\r
- */\r
-int\r
-copy_statement_with_parameters(StatementClass *stmt, BOOL buildPrepareStatement)\r
-{\r
-   CSTR        func = "copy_statement_with_parameters";\r
-   RETCODE     retval;\r
-   QueryParse  query_org, *qp;\r
-   QueryBuild  query_crt, *qb;\r
-\r
-   char       *new_statement;\r
-\r
-   BOOL    begin_first = FALSE, prepare_dummy_cursor = FALSE;\r
-   ConnectionClass *conn = SC_get_conn(stmt);\r
-   ConnInfo   *ci = &(conn->connInfo);\r
-   int     current_row;\r
-\r
-   if (!stmt->statement)\r
-   {\r
-       SC_log_error(func, "No statement string", stmt);\r
-       return SQL_ERROR;\r
-   }\r
-\r
-   current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;\r
-   qp = &query_org;\r
-   QP_initialize(qp, stmt);\r
-\r
-#ifdef DRIVER_CURSOR_IMPLEMENT\r
-   if (stmt->statement_type != STMT_TYPE_SELECT)\r
-   {\r
-       stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;\r
-       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-   }\r
-   else if (stmt->options.cursor_type == SQL_CURSOR_FORWARD_ONLY)\r
-       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-   else if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)\r
-   {\r
-       if (stmt->parse_status == STMT_PARSE_NONE)\r
-           parse_statement(stmt);\r
-       if (stmt->parse_status == STMT_PARSE_FATAL)\r
-       {\r
-           stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-           if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)\r
-               stmt->options.cursor_type = SQL_CURSOR_STATIC;\r
-       }\r
-       else if (!stmt->updatable)\r
-       {\r
-           stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-           stmt->options.cursor_type = SQL_CURSOR_STATIC;\r
-       }\r
-       else\r
-       {\r
-           qp->from_pos = stmt->from_pos;\r
-           qp->where_pos = stmt->where_pos;\r
-       }\r
-   }\r
-#else\r
-   stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-   if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)\r
-       stmt->options.cursor_type = SQL_CURSOR_STATIC;\r
-#endif   /* DRIVER_CURSOR_IMPLEMENT */\r
-\r
-   stmt->miscinfo = 0;\r
-   /* If the application hasn't set a cursor name, then generate one */\r
-   if (stmt->cursor_name[0] == '\0')\r
-       sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);\r
-   if (stmt->stmt_with_params)\r
-   {\r
-       free(stmt->stmt_with_params);\r
-       stmt->stmt_with_params = NULL;\r
-   }\r
-\r
-   SC_no_fetchcursor(stmt);\r
-   SC_no_pre_executable(stmt);\r
-   if (stmt->statement_type == STMT_TYPE_SELECT)\r
-       SC_set_pre_executable(stmt);\r
-   qb = &query_crt;\r
-   if (stmt->prepared || (buildPrepareStatement && stmt->options.scroll_concurrency == SQL_CONCUR_READ_ONLY))\r
-   {\r
-       return Prepare_and_convert(stmt, qp, qb);\r
-   }\r
-\r
-   if (ci->disallow_premature)\r
-       prepare_dummy_cursor = stmt->pre_executing;\r
-   if (prepare_dummy_cursor)\r
-       qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;\r
-   if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)\r
-       return SQL_ERROR;\r
-   new_statement = qb->query_statement;\r
-\r
-   /* For selects, prepend a declare cursor to the statement */\r
-   if (stmt->statement_type == STMT_TYPE_SELECT)\r
-   {\r
-       if (prepare_dummy_cursor || ci->drivers.use_declarefetch)\r
-       {\r
-           if (prepare_dummy_cursor)\r
-           {\r
-               if (!CC_is_in_trans(conn) && PG_VERSION_GE(conn, 7.1))\r
-               {\r
-                   strcpy(new_statement, "BEGIN;");\r
-                   begin_first = TRUE;\r
-               }\r
-           }\r
-           else if (ci->drivers.use_declarefetch)\r
-               SC_set_fetchcursor(stmt);\r
-           sprintf(new_statement, "%sdeclare %s cursor for ",\r
-                   new_statement, stmt->cursor_name);\r
-           qb->npos = strlen(new_statement);\r
-           qp->flags |= FLGP_CURSOR_CHECK_OK;\r
-           qp->declare_pos = qb->npos;\r
-       }\r
-       else if (SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)\r
-       {\r
-           qb->flags |= FLGB_CREATE_KEYSET;\r
-           if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type)\r
-               qb->flags |= FLGB_KEYSET_DRIVEN;\r
-       }\r
-   }\r
-\r
-   for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)\r
-   {\r
-       retval = inner_process_tokens(qp, qb);\r
-       if (SQL_ERROR == retval)\r
-       {\r
-           if (0 == SC_get_errornumber(stmt))\r
-           {\r
-               SC_set_error(stmt, qb->errornumber, qb->errormsg);\r
-           }\r
-           SC_log_error(func, "", stmt);\r
-           QB_Destructor(qb);\r
-           return retval;\r
-       }\r
-   }\r
-   /* make sure new_statement is always null-terminated */\r
-   CVT_TERMINATE(qb);\r
-\r
-   new_statement = qb->query_statement;\r
-   stmt->statement_type = qp->statement_type;\r
-   stmt->inaccurate_result = (0 != (qb->flags & FLGB_INACCURATE_RESULT));\r
-   if (0 != (qp->flags & FLGP_SELECT_INTO))\r
-   {\r
-       SC_no_pre_executable(stmt);\r
-       SC_no_fetchcursor(stmt);\r
-       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-   }\r
-   if (0 != (qp->flags & FLGP_SELECT_FOR_UPDATE))\r
-   {\r
-       SC_no_fetchcursor(stmt);\r
-       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;\r
-   }\r
-\r
-   if (conn->DriverToDataSource != NULL)\r
-   {\r
-       int         length = strlen(new_statement);\r
-\r
-       conn->DriverToDataSource(conn->translation_option,\r
-                                SQL_CHAR,\r
-                                new_statement, length,\r
-                                new_statement, length, NULL,\r
-                                NULL, 0, NULL);\r
-   }\r
-\r
-#ifdef DRIVER_CURSOR_IMPLEMENT\r
-   if (!stmt->load_statement && qp->from_pos >= 0)\r
-   {\r
-       UInt4   npos = qb->load_stmt_len;\r
-\r
-       if (0 == npos)\r
-       {\r
-           npos = qb->npos;\r
-           for (; npos > 0; npos--)\r
-           {\r
-               if (isspace(new_statement[npos - 1]))\r
-                   continue;\r
-               if (';' != new_statement[npos - 1])\r
-                   break;\r
-           }\r
-           if (0 != (qb->flags & FLGB_KEYSET_DRIVEN))\r
-           {\r
-               qb->npos = npos;\r
-               /* ----------\r
-                * 1st query is for field information\r
-                * 2nd query is keyset gathering\r
-                */\r
-               CVT_APPEND_STR(qb, " where ctid = '(0,0)';select ctid, oid from ");\r
-               CVT_APPEND_DATA(qb, qp->statement + qp->from_pos + 5, npos - qp->from_pos - 5);\r
-           }\r
-       }\r
-       stmt->load_statement = malloc(npos + 1);\r
-       memcpy(stmt->load_statement, qb->query_statement, npos);\r
-       stmt->load_statement[npos] = '\0';\r
-   }\r
-#endif   /* DRIVER_CURSOR_IMPLEMENT */\r
-   if (prepare_dummy_cursor && SC_is_pre_executable(stmt))\r
-   {\r
-       char        fetchstr[128];\r
-\r
-       sprintf(fetchstr, ";fetch backward in %s;close %s;",\r
-               stmt->cursor_name, stmt->cursor_name);\r
-       if (begin_first && CC_is_in_autocommit(conn))\r
-           strcat(fetchstr, "COMMIT;");\r
-       CVT_APPEND_STR(qb, fetchstr);\r
-       stmt->inaccurate_result = TRUE;\r
-   }\r
-\r
-   stmt->stmt_with_params = qb->query_statement;\r
-   return SQL_SUCCESS;\r
-}\r
-\r
-static int\r
-inner_process_tokens(QueryParse *qp, QueryBuild *qb)\r
-{\r
-   CSTR func = "inner_process_tokens";\r
-   BOOL    lf_conv = qb->lf_conv;\r
-\r
-   RETCODE retval;\r
-   char       oldchar;\r
-\r
-   if (qp->from_pos == (Int4) qp->opos)\r
-   {\r
-       CVT_APPEND_STR(qb, ", CTID, OID ");\r
-   }\r
-   else if (qp->where_pos == (Int4) qp->opos)\r
-   {\r
-       qb->load_stmt_len = qb->npos;\r
-       if (0 != (qb->flags & FLGB_KEYSET_DRIVEN))\r
-       {\r
-           CVT_APPEND_STR(qb, "where ctid = '(0,0)';select CTID, OID from ");\r
-           CVT_APPEND_DATA(qb, qp->statement + qp->from_pos + 5, qp->where_pos - qp->from_pos - 5);\r
-       }\r
-   }\r
-   oldchar = encoded_byte_check(&qp->encstr, qp->opos);\r
-   if (ENCODE_STATUS(qp->encstr) != 0)\r
-   {\r
-       CVT_APPEND_CHAR(qb, oldchar);\r
-       return SQL_SUCCESS;\r
-   }\r
-\r
-   /*\r
-    * From here we are guaranteed to handle a 1-byte character.\r
-    */\r
-\r
-   if (qp->in_escape)          /* escape check */\r
-   {\r
-       qp->in_escape = FALSE;\r
-       CVT_APPEND_CHAR(qb, oldchar);\r
-       return SQL_SUCCESS;\r
-   }\r
-   else if (qp->in_quote || qp->in_dquote) /* quote/double quote check */\r
-   {\r
-       if (oldchar == '\\')\r
-           qp->in_escape = TRUE;\r
-       else if (oldchar == '\'' && qp->in_quote)\r
-           qp->in_quote = FALSE;\r
-       else if (oldchar == '\"' && qp->in_dquote)\r
-           qp->in_dquote = FALSE;\r
-       CVT_APPEND_CHAR(qb, oldchar);\r
-       return SQL_SUCCESS;\r
-   }\r
-\r
-   /*\r
-    * From here we are guranteed to be in neither an escape, a quote\r
-    * nor a double quote.\r
-    */\r
-   /* Squeeze carriage-return/linefeed pairs to linefeed only */\r
-   else if (lf_conv && oldchar == '\r' && qp->opos + 1 < qp->stmt_len &&\r
-           qp->statement[qp->opos + 1] == '\n')\r
-       return SQL_SUCCESS;\r
-\r
-   /*\r
-    * Handle literals (date, time, timestamp) and ODBC scalar\r
-    * functions\r
-    */\r
-   else if (oldchar == '{')\r
-   {\r
-       if (SQL_ERROR == convert_escape(qp, qb))\r
-       {\r
-           if (0 == qb->errornumber)\r
-           {\r
-               qb->errornumber = STMT_EXEC_ERROR;\r
-               qb->errormsg = "ODBC escape convert error";\r
-           }\r
-           mylog("%s convert_escape error\n", func);\r
-           return SQL_ERROR;\r
-       }\r
-       if (isalnum(F_OldPtr(qp)[1]))\r
-           CVT_APPEND_CHAR(qb, ' ');\r
-       return SQL_SUCCESS;\r
-   }\r
-   /* End of an escape sequence */\r
-   else if (oldchar == '}')\r
-   {\r
-       if (qp->statement_type == STMT_TYPE_PROCCALL)\r
-       {\r
-           if (qp->proc_no_param)\r
-               CVT_APPEND_STR(qb, "()");\r
-       }\r
-       else if (!isspace(F_OldPtr(qp)[1]))\r
-           CVT_APPEND_CHAR(qb, ' ');\r
-       return SQL_SUCCESS;\r
-   }\r
-\r
-   /*\r
-    * Can you have parameter markers inside of quotes?  I dont think\r
-    * so. All the queries I've seen expect the driver to put quotes\r
-    * if needed.\r
-    */\r
-   else if (oldchar != '?')\r
-   {\r
-       if (oldchar == '\'')\r
-           qp->in_quote = TRUE;\r
-       else if (oldchar == '\\')\r
-           qp->in_escape = TRUE;\r
-       else if (oldchar == '\"')\r
-           qp->in_dquote = TRUE;\r
-       else\r
-       {\r
-           if (isspace((UCHAR) oldchar))\r
-           {\r
-               if (!qp->prev_token_end)\r
-               {\r
-                   qp->prev_token_end = TRUE;\r
-                   qp->token_save[qp->token_len] = '\0';\r
-                   if (qp->token_len == 4)\r
-                   {\r
-                       if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&\r
-                           into_table_from(&qp->statement[qp->opos - qp->token_len]))\r
-                       {\r
-                           qp->flags |= FLGP_SELECT_INTO;\r
-                           qp->flags &= ~FLGP_CURSOR_CHECK_OK;\r
-                           qb->flags &= ~FLGB_KEYSET_DRIVEN;\r
-                           qp->statement_type = STMT_TYPE_CREATE;\r
-                           memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);\r
-                           qb->npos -= qp->declare_pos;\r
-                       }\r
-                   }\r
-                   else if (qp->token_len == 3)\r
-                   {\r
-                       int         endpos;\r
-\r
-                       if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&\r
-                           strnicmp(qp->token_save, "for", 3) == 0 &&\r
-                           table_for_update(&qp->statement[qp->opos], &endpos))\r
-                       {\r
-                           qp->flags |= FLGP_SELECT_FOR_UPDATE;\r
-                           qp->flags &= ~FLGP_CURSOR_CHECK_OK;\r
-                           if (qp->flags & FLGP_PREPARE_DUMMY_CURSOR)\r
-                           {\r
-                               qb->npos -= 4;\r
-                               qp->opos += endpos;\r
-                           }\r
-                           else\r
-                           {\r
-                               memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);\r
-                               qb->npos -= qp->declare_pos;\r
-                           }\r
-                       }\r
-                   }\r
-                   else if (qp->token_len == 2)\r
-                   {\r
-                       int endpos;\r
-\r
-                       if (STMT_TYPE_INSERT == qp->statement_type &&\r
-                           strnicmp(qp->token_save, "()", 2) == 0 &&\r
-                           insert_without_target(&qp->statement[qp->opos], &endpos))\r
-                       {\r
-                           qb->npos -= 2;\r
-                           CVT_APPEND_STR(qb, "DEFAULT VALUES");\r
-                           qp->opos += endpos;\r
-                           return SQL_SUCCESS;\r
-                       }\r
-                   }\r
-               }\r
-           }\r
-           else if (qp->prev_token_end)\r
-           {\r
-               qp->prev_token_end = FALSE;\r
-               qp->token_save[0] = oldchar;\r
-               qp->token_len = 1;\r
-           }\r
-           else if (qp->token_len + 1 < sizeof(qp->token_save))\r
-               qp->token_save[qp->token_len++] = oldchar;\r
-       }\r
-       CVT_APPEND_CHAR(qb, oldchar);\r
-       return SQL_SUCCESS;\r
-   }\r
-\r
-   /*\r
-    * Its a '?' parameter alright\r
-    */\r
-   if (retval = ResolveOneParam(qb), retval < 0)\r
-       return retval;\r
-\r
-   return SQL_SUCCESS;\r
-}\r
-\r
-static BOOL\r
-ResolveNumericParam(const SQL_NUMERIC_STRUCT *ns, char *chrform)\r
-{\r
-   static const int prec[] = {1, 3, 5, 8, 10, 13, 15, 17, 20, 22, 25, 29, 32, 34, 37, 39};\r
-   Int4    i, j, k, ival, vlen, len, newlen;\r
-   UCHAR       calv[40];\r
-   const UCHAR *val = (const UCHAR *) ns->val;\r
-   BOOL    next_figure;\r
-\r
-   if (0 == ns->precision)\r
-   {\r
-       strcpy(chrform, "0");\r
-       return TRUE;\r
-   }\r
-   else if (ns->precision < prec[sizeof(Int4)])\r
-   {\r
-       for (i = 0, ival = 0; i < sizeof(Int4) && prec[i] <= ns->precision; i++)\r
-       {\r
-           ival += (val[i] << (8 * i)); /* ns->val is little endian */\r
-       }\r
-       if (0 == ns->scale)\r
-       {\r
-           if (0 == ns->sign)\r
-               ival *= -1;\r
-           sprintf(chrform, "%d", ival);\r
-       }\r
-       else if (ns->scale > 0)\r
-       {\r
-           Int4    i, div, o1val, o2val;\r
-\r
-           for (i = 0, div = 1; i < ns->scale; i++)\r
-               div *= 10;\r
-           o1val = ival / div;\r
-           o2val = ival % div;\r
-           if (0 == ns->sign)\r
-               o1val *= -1;\r
-           sprintf(chrform, "%d.%0.*d", o1val, ns->scale, o2val);\r
-       }\r
-       return TRUE;\r
-   }\r
-\r
-   for (i = 0; i < SQL_MAX_NUMERIC_LEN && prec[i] <= ns->precision; i++)\r
-       ;\r
-   vlen = i;\r
-   len = 0;\r
-   memset(calv, 0, sizeof(calv));\r
-   for (i = vlen - 1; i >= 0; i--)\r
-   {\r
-       for (j = len - 1; j >= 0; j--)\r
-       {\r
-           if (!calv[j])\r
-               continue;\r
-           ival = (((Int4)calv[j]) << 8);\r
-           calv[j] = (ival % 10);\r
-           ival /= 10;\r
-           calv[j + 1] += (ival % 10);\r
-           ival /= 10;\r
-           calv[j + 2] += (ival % 10);\r
-           ival /= 10;\r
-           calv[j + 3] += ival;\r
-           for (k = j;; k++)\r
-           {\r
-               next_figure = FALSE;\r
-               if (calv[k] > 0)\r
-               {\r
-                   if (k >= len)\r
-                       len = k + 1;\r
-                   while (calv[k] > 9)\r
-                   {\r
-                       calv[k + 1]++;\r
-                       calv[k] -= 10;\r
-                       next_figure = TRUE;\r
-                   }\r
-               }\r
-               if (k >= j + 3 && !next_figure)\r
-                   break;\r
-           }\r
-       }\r
-       ival = val[i];\r
-       if (!ival)\r
-           continue;\r
-       calv[0] += (ival % 10);\r
-       ival /= 10;\r
-       calv[1] += (ival % 10);\r
-       ival /= 10;\r
-       calv[2] += ival;\r
-       for (j = 0;; j++)\r
-       {\r
-           next_figure = FALSE;\r
-           if (calv[j] > 0)\r
-           {\r
-               if (j >= len)\r
-                   len = j + 1;\r
-               while (calv[j] > 9)\r
-               {\r
-                   calv[j + 1]++;\r
-                   calv[j] -= 10;\r
-                   next_figure = TRUE;\r
-               }\r
-           }\r
-           if (j >= 2 && !next_figure)\r
-               break;\r
-       }\r
-   }\r
-   newlen = 0;\r
-   if (0 == ns->sign)\r
-       chrform[newlen++] = '-';\r
-   if (i = len - 1, i < ns->scale)\r
-       i = ns->scale;\r
-   for (; i >= ns->scale; i--)\r
-       chrform[newlen++] = calv[i] + '0';\r
-   if (ns->scale > 0)\r
-   {\r
-       chrform[newlen++] = '.';\r
-       for (; i >= 0; i--)\r
-           chrform[newlen++] = calv[i] + '0';\r
-   }\r
-   if (0 == len)\r
-       chrform[newlen++] = '0';\r
-   chrform[newlen] = '\0';\r
-   return TRUE;\r
-}\r
-\r
-/*\r
- *\r
- */\r
-static int\r
-ResolveOneParam(QueryBuild *qb)\r
-{\r
-   CSTR func = "ResolveOneParam";\r
-\r
-   ConnectionClass *conn = qb->conn;\r
-   ConnInfo   *ci = &(conn->connInfo);\r
-   const APDFields *apdopts = qb->apdopts;\r
-   const IPDFields *ipdopts = qb->ipdopts;\r
-   PutDataInfo *pdata = qb->pdata;\r
-\r
-   int     param_number;\r
-   char        param_string[128], tmp[256],\r
-           cbuf[PG_NUMERIC_MAX_PRECISION * 2]; /* seems big enough to handle the data in this function */\r
-   Int4        param_pgtype;\r
-   Int2        param_ctype, param_sqltype;\r
-   SIMPLE_TIME st;\r
-   time_t      t;\r
-   struct tm   *tim;\r
-#ifdef HAVE_LOCALTIME_R\r
-   struct tm   tm;\r
-#endif /* HAVE_LOCALTIME_R */\r
-   SDWORD      used;\r
-   char        *buffer, *buf, *allocbuf;\r
-   Oid     lobj_oid;\r
-   int     lobj_fd, retval;\r
-   UInt4   offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;\r
-   UInt4   current_row = qb->current_row;\r
-   BOOL    handling_large_object = FALSE;\r
-\r
-   /*\r
-    * Its a '?' parameter alright\r
-    */\r
-   param_number = ++qb->param_number;\r
-\r
-   if (param_number >= apdopts->allocated)\r
-   {\r
-       if (0 != (qb->flags & FLGB_PRE_EXECUTING))\r
-       {\r
-           CVT_APPEND_STR(qb, "NULL");\r
-           qb->flags |= FLGB_INACCURATE_RESULT;\r
-           return SQL_SUCCESS;\r
-       }\r
-       else\r
-       {\r
-           qb->errormsg = "The # of binded parameters < the # of parameter markers";\r
-           qb->errornumber = STMT_COUNT_FIELD_INCORRECT;\r
-           CVT_TERMINATE(qb);  /* just in case */\r
-           return SQL_ERROR;\r
-       }\r
-   }\r
-   if (SQL_PARAM_OUTPUT == ipdopts->parameters[param_number].paramType)\r
-   {\r
-       qb->errormsg = "Output parameter isn't available";\r
-       qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;\r
-       CVT_TERMINATE(qb);  /* just in case */\r
-       return SQL_ERROR;\r
-   }\r
-\r
-   if (0 != (qb->flags & FLGB_BUILDING_PREPARE_STATEMENT))\r
-   {\r
-       char    pnum[16];\r
-\r
-       sprintf(pnum, "$%d", param_number + 1);\r
-       CVT_APPEND_STR(qb, pnum); \r
-       return SQL_SUCCESS;\r
-   } \r
-   /* Assign correct buffers based on data at exec param or not */\r
-   if (apdopts->parameters[param_number].data_at_exec)\r
-   {\r
-       if (pdata->allocated != apdopts->allocated)\r
-           extend_putdata_info(pdata, apdopts->allocated, TRUE);\r
-       used = pdata->pdata[param_number].EXEC_used ? *pdata->pdata[param_number].EXEC_used : SQL_NTS;\r
-       buffer = pdata->pdata[param_number].EXEC_buffer;\r
-       if (pdata->pdata[param_number].lobj_oid)\r
-           handling_large_object = TRUE;\r
-   }\r
-   else\r
-   {\r
-       UInt4   bind_size = apdopts->param_bind_type;\r
-       UInt4   ctypelen;\r
-\r
-       buffer = apdopts->parameters[param_number].buffer + offset;\r
-       if (current_row > 0)\r
-       {\r
-           if (bind_size > 0)\r
-               buffer += (bind_size * current_row);\r
-           else if (ctypelen = ctype_length(apdopts->parameters[param_number].CType), ctypelen > 0)\r
-               buffer += current_row * ctypelen;\r
-           else \r
-               buffer += current_row * apdopts->parameters[param_number].buflen;\r
-       }\r
-       if (apdopts->parameters[param_number].used)\r
-       {\r
-           UInt4   p_offset = offset;\r
-           if (bind_size > 0)\r
-               p_offset = offset + bind_size * current_row;\r
-           else\r
-               p_offset = offset + sizeof(SDWORD) * current_row;\r
-           used = *(SDWORD *)((char *)apdopts->parameters[param_number].used + p_offset);\r
-       }\r
-       else\r
-           used = SQL_NTS;\r
-   }   \r
-\r
-   /* Handle NULL parameter data */\r
-   if (used == SQL_NULL_DATA)\r
-   {\r
-       CVT_APPEND_STR(qb, "NULL");\r
-       return SQL_SUCCESS;\r
-   }\r
-   /* Handle DEFAULT_PARAM parameter data */\r
-   if (used == SQL_DEFAULT_PARAM)\r
-   {\r
-       return SQL_SUCCESS;\r
-   }\r
-\r
-   /*\r
-    * If no buffer, and it's not null, then what the hell is it? Just\r
-    * leave it alone then.\r
-    */\r
-   if (!buffer)\r
-   {\r
-       if (0 != (qb->flags & FLGB_PRE_EXECUTING))\r
-       {\r
-           CVT_APPEND_STR(qb, "NULL");\r
-           qb->flags |= FLGB_INACCURATE_RESULT;\r
-           return SQL_SUCCESS;\r
-       }\r
-       else if (!handling_large_object)\r
-       {\r
-           CVT_APPEND_CHAR(qb, '?');\r
-           return SQL_SUCCESS;\r
-       }\r
-   }\r
-\r
-   param_ctype = apdopts->parameters[param_number].CType;\r
-   param_sqltype = ipdopts->parameters[param_number].SQLType;\r
-   param_pgtype = ipdopts->parameters[param_number].PGType;\r
-\r
-   mylog("%s: from(fcType)=%d, to(fSqlType)=%d\n", func,\r
-               param_ctype, param_sqltype);\r
-\r
-   /* replace DEFAULT with something we can use */\r
-   if (param_ctype == SQL_C_DEFAULT)\r
-       param_ctype = sqltype_to_default_ctype(conn, param_sqltype);\r
-\r
-   allocbuf = buf = NULL;\r
-   param_string[0] = '\0';\r
-   cbuf[0] = '\0';\r
-   memset(&st, 0, sizeof(st));\r
-   t = SC_get_time(qb->stmt);\r
-#ifdef HAVE_LOCALTIME_R\r
-   tim = localtime_r(&t, &tm);\r
-#else\r
-   tim = localtime(&t);\r
-#endif /* HAVE_LOCALTIME_R */\r
-   st.m = tim->tm_mon + 1;\r
-   st.d = tim->tm_mday;\r
-   st.y = tim->tm_year + 1900;\r
-\r
-   /* Convert input C type to a neutral format */\r
-   switch (param_ctype)\r
-   {\r
-       case SQL_C_BINARY:\r
-           buf = buffer;\r
-           break;\r
-       case SQL_C_CHAR:\r
-#ifdef WIN32\r
-           switch (param_sqltype)\r
-           {\r
-               case SQL_WCHAR:\r
-               case SQL_WVARCHAR:\r
-               case SQL_WLONGVARCHAR:\r
-                   if (SQL_NTS == used)\r
-                       used = strlen(buffer);\r
-                   allocbuf = malloc(WCLEN * (used + 1));\r
-                   used = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buffer,\r
-                       used, (LPWSTR) allocbuf, used + 1);\r
-                   buf = ucs2_to_utf8((SQLWCHAR *) allocbuf, used, (UInt4 *) &used, FALSE);\r
-                   free(allocbuf);\r
-                   allocbuf = buf;\r
-                   break;\r
-               default:\r
-                   buf = buffer;\r
-           }\r
-#else\r
-           buf = buffer;\r
-#endif /* WIN32 */\r
-           break;\r
-\r
-       case SQL_C_WCHAR:\r
-            if (SQL_NTS == used)\r
-                used = WCLEN * wcslen((SQLWCHAR *) buffer);\r
-           buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / WCLEN, (UInt4 *) &used, FALSE);\r
-           used *= WCLEN;\r
-           break;\r
-\r
-       case SQL_C_DOUBLE:\r
-           sprintf(param_string, "%.15g",\r
-                       *((SDOUBLE *) buffer));\r
-           break;\r
-\r
-       case SQL_C_FLOAT:\r
-           sprintf(param_string, "%.6g",\r
-                   *((SFLOAT *) buffer));\r
-           break;\r
-\r
-       case SQL_C_SLONG:\r
-       case SQL_C_LONG:\r
-           sprintf(param_string, "%d",\r
-                   *((SDWORD *) buffer));\r
-           break;\r
-\r
-#ifdef ODBCINT64\r
-       case SQL_C_SBIGINT:\r
-           sprintf(param_string, FORMATI64,\r
-                   *((SQLBIGINT *) buffer));\r
-           break;\r
-\r
-       case SQL_C_UBIGINT:\r
-           sprintf(param_string, FORMATI64U,\r
-                   *((SQLUBIGINT *) buffer));\r
-           break;\r
-\r
-#endif /* ODBCINT64 */\r
-       case SQL_C_SSHORT:\r
-       case SQL_C_SHORT:\r
-           sprintf(param_string, "%d",\r
-                   *((SWORD *) buffer));\r
-           break;\r
-\r
-       case SQL_C_STINYINT:\r
-       case SQL_C_TINYINT:\r
-           sprintf(param_string, "%d",\r
-                   *((SCHAR *) buffer));\r
-           break;\r
-\r
-       case SQL_C_ULONG:\r
-           sprintf(param_string, "%u",\r
-                   *((UDWORD *) buffer));\r
-           break;\r
-\r
-       case SQL_C_USHORT:\r
-           sprintf(param_string, "%u",\r
-                   *((UWORD *) buffer));\r
-           break;\r
-\r
-       case SQL_C_UTINYINT:\r
-           sprintf(param_string, "%u",\r
-                   *((UCHAR *) buffer));\r
-           break;\r
-\r
-       case SQL_C_BIT:\r
-           {\r
-               int         i = *((UCHAR *) buffer);\r
-\r
-                   sprintf(param_string, "%d", i ? 1 : 0);\r
-                   break;\r
-           }\r
-\r
-       case SQL_C_DATE:\r
-       case SQL_C_TYPE_DATE:       /* 91 */\r
-           {\r
-               DATE_STRUCT *ds = (DATE_STRUCT *) buffer;\r
-\r
-               st.m = ds->month;\r
-               st.d = ds->day;\r
-               st.y = ds->year;\r
-\r
-               break;\r
-           }\r
-\r
-       case SQL_C_TIME:\r
-       case SQL_C_TYPE_TIME:       /* 92 */\r
-           {\r
-               TIME_STRUCT *ts = (TIME_STRUCT *) buffer;\r
-\r
-               st.hh = ts->hour;\r
-               st.mm = ts->minute;\r
-               st.ss = ts->second;\r
-\r
-               break;\r
-           }\r
-\r
-       case SQL_C_TIMESTAMP:\r
-       case SQL_C_TYPE_TIMESTAMP:  /* 93 */\r
-           {\r
-               TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer;\r
-\r
-               st.m = tss->month;\r
-               st.d = tss->day;\r
-               st.y = tss->year;\r
-               st.hh = tss->hour;\r
-               st.mm = tss->minute;\r
-               st.ss = tss->second;\r
-               st.fr = tss->fraction;\r
-\r
-               mylog("m=%d,d=%d,y=%d,hh=%d,mm=%d,ss=%d\n", st.m, st.d, st.y, st.hh, st.mm, st.ss);\r
-\r
-               break;\r
-\r
-           }\r
-       case SQL_C_NUMERIC:\r
-           if (ResolveNumericParam((SQL_NUMERIC_STRUCT *) buffer, param_string))\r
-               break;\r
-       default:\r
-           /* error */\r
-           qb->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";\r
-           qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;\r
-           CVT_TERMINATE(qb);  /* just in case */\r
-           return SQL_ERROR;\r
-   }\r
-\r
-   /*\r
-    * Now that the input data is in a neutral format, convert it to\r
-    * the desired output format (sqltype)\r
-    */\r
-\r
-   switch (param_sqltype)\r
-   {\r
-       case SQL_CHAR:\r
-       case SQL_VARCHAR:\r
-       case SQL_LONGVARCHAR:\r
-       case SQL_WCHAR:\r
-       case SQL_WVARCHAR:\r
-       case SQL_WLONGVARCHAR:\r
-\r
-           CVT_APPEND_CHAR(qb, '\'');  /* Open Quote */\r
-\r
-           /* it was a SQL_C_CHAR */\r
-           if (buf)\r
-               CVT_SPECIAL_CHARS(qb, buf, used);\r
-\r
-           /* it was a numeric type */\r
-           else if (param_string[0] != '\0')\r
-               CVT_APPEND_STR(qb, param_string);\r
-\r
-           /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */\r
-           else\r
-           {\r
-               sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",\r
-                       st.y, st.m, st.d, st.hh, st.mm, st.ss);\r
-\r
-               CVT_APPEND_STR(qb, tmp);\r
-           }\r
-\r
-           CVT_APPEND_CHAR(qb, '\'');  /* Close Quote */\r
-\r
-           break;\r
-\r
-       case SQL_DATE:\r
-       case SQL_TYPE_DATE: /* 91 */\r
-           if (buf)\r
-           {               /* copy char data to time */\r
-               my_strcpy(cbuf, sizeof(cbuf), buf, used);\r
-               parse_datetime(cbuf, &st);\r
-           }\r
-\r
-           sprintf(tmp, "'%.4d-%.2d-%.2d'::date", st.y, st.m, st.d);\r
-\r
-           CVT_APPEND_STR(qb, tmp);\r
-           break;\r
-\r
-       case SQL_TIME:\r
-       case SQL_TYPE_TIME: /* 92 */\r
-           if (buf)\r
-           {               /* copy char data to time */\r
-               my_strcpy(cbuf, sizeof(cbuf), buf, used);\r
-               parse_datetime(cbuf, &st);\r
-           }\r
-\r
-           sprintf(tmp, "'%.2d:%.2d:%.2d'::time", st.hh, st.mm, st.ss);\r
-\r
-           CVT_APPEND_STR(qb, tmp);\r
-           break;\r
-\r
-       case SQL_TIMESTAMP:\r
-       case SQL_TYPE_TIMESTAMP:    /* 93 */\r
-\r
-           if (buf)\r
-           {\r
-               my_strcpy(cbuf, sizeof(cbuf), buf, used);\r
-               parse_datetime(cbuf, &st);\r
-           }\r
-\r
-           /*\r
-            * sprintf(tmp, "'%.4d-%.2d-%.2d %.2d:%.2d:%.2d'", st.y,\r
-            * st.m, st.d, st.hh, st.mm, st.ss);\r
-            */\r
-           tmp[0] = '\'';\r
-           /* Time zone stuff is unreliable */\r
-           stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));\r
-           strcat(tmp, "'::timestamp");\r
-\r
-           CVT_APPEND_STR(qb, tmp);\r
-\r
-           break;\r
-\r
-       case SQL_BINARY:\r
-       case SQL_VARBINARY:\r
-       case SQL_LONGVARBINARY:\r
-           switch (param_ctype)\r
-           {\r
-               case SQL_C_BINARY:\r
-                   break;\r
-               case SQL_C_CHAR:\r
-                   switch (used)\r
-                   {\r
-                       case SQL_NTS:\r
-                           used = strlen(buf);\r
-                           break;\r
-                   }\r
-                   allocbuf = malloc(used / 2 + 1);\r
-                   if (allocbuf)\r
-                   {\r
-                       pg_hex2bin(buf, allocbuf, used);\r
-                       buf = allocbuf;\r
-                       used /= 2;\r
-                   }\r
-                   break;\r
-               default:\r
-                   qb->errormsg = "Could not convert the ctype to binary type";\r
-                   qb->errornumber = STMT_EXEC_ERROR;\r
-                   return SQL_ERROR;\r
-           }\r
-           if (param_pgtype == PG_TYPE_BYTEA)\r
-           {\r
-               /* non-ascii characters should be\r
-                * converted to octal\r
-                */\r
-               CVT_APPEND_CHAR(qb, '\'');  /* Open Quote */\r
-\r
-               mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);\r
-\r
-               CVT_APPEND_BINARY(qb, buf, used);\r
-\r
-               CVT_APPEND_CHAR(qb, '\'');  /* Close Quote */\r
-\r
-               break;\r
-           }\r
-           if (param_pgtype != conn->lobj_type)\r
-           {\r
-               qb->errormsg = "Could not convert binary other than LO type";\r
-               qb->errornumber = STMT_EXEC_ERROR;\r
-               return SQL_ERROR;\r
-           }\r
-\r
-           if (apdopts->parameters[param_number].data_at_exec)\r
-               lobj_oid = pdata->pdata[param_number].lobj_oid;\r
-           else\r
-           {\r
-               /* begin transaction if needed */\r
-               if (!CC_is_in_trans(conn))\r
-               {\r
-                   if (!CC_begin(conn))\r
-                   {\r
-                       qb->errormsg = "Could not begin (in-line) a transaction";\r
-                       qb->errornumber = STMT_EXEC_ERROR;\r
-                       return SQL_ERROR;\r
-                   }\r
-               }\r
-\r
-               /* store the oid */\r
-#ifdef USE_LIBPQ\r
-               lobj_oid = lo_creat(conn->pgconn, INV_READ | INV_WRITE);\r
-#else\r
-               lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);\r
-#endif /* USE_LIBPQ */\r
-\r
-               if (lobj_oid == 0)\r
-               {\r
-                   qb->errornumber = STMT_EXEC_ERROR;\r
-                   qb->errormsg = "Couldnt create (in-line) large object.";\r
-                   return SQL_ERROR;\r
-               }\r
-\r
-               /* store the fd */\r
-#ifdef USE_LIBPQ\r
-               lobj_fd = lo_open(conn->pgconn, lobj_oid, INV_WRITE);\r
-#else\r
-               lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);\r
-#endif /* USE_LIBPQ */\r
-\r
-               if (lobj_fd < 0)\r
-               {\r
-                   qb->errornumber = STMT_EXEC_ERROR;\r
-                   qb->errormsg = "Couldnt open (in-line) large object for writing.";\r
-                   return SQL_ERROR;\r
-               }\r
-#ifdef USE_LIBPQ\r
-           retval = lo_write(conn->pgconn, lobj_fd, buffer, used);\r
-           lo_close(conn->pgconn, lobj_fd);\r
-\r
-#else\r
-               retval = lo_write(conn, lobj_fd, buffer, used);\r
-\r
-               lo_close(conn, lobj_fd);\r
-#endif /* USE_LIBPQ */\r
-\r
-               /* commit transaction if needed */\r
-               if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))\r
-               {\r
-                   if (!CC_commit(conn))\r
-                   {\r
-                       qb->errormsg = "Could not commit (in-line) a transaction";\r
-                       qb->errornumber = STMT_EXEC_ERROR;\r
-                       return SQL_ERROR;\r
-                   }\r
-               }\r
-           }\r
-\r
-           /*\r
-            * the oid of the large object -- just put that in for the\r
-            * parameter marker -- the data has already been sent to\r
-            * the large object\r
-            */\r
-           sprintf(param_string, "'%d'::lo", lobj_oid);\r
-           CVT_APPEND_STR(qb, param_string);\r
-\r
-           break;\r
-\r
-           /*\r
-            * because of no conversion operator for bool and int4,\r
-            * SQL_BIT\r
-            */\r
-           /* must be quoted (0 or 1 is ok to use inside the quotes) */\r
-\r
-       case SQL_REAL:\r
-           if (buf)\r
-               my_strcpy(param_string, sizeof(param_string), buf, used);\r
-           sprintf(tmp, "'%s'::float4", param_string);\r
-           CVT_APPEND_STR(qb, tmp);\r
-           break;\r
-       case SQL_FLOAT:\r
-       case SQL_DOUBLE:\r
-           if (buf)\r
-               my_strcpy(param_string, sizeof(param_string), buf, used);\r
-           sprintf(tmp, "'%s'::float8", param_string);\r
-           CVT_APPEND_STR(qb, tmp);\r
-           break;\r
-       case SQL_NUMERIC:\r
-           if (buf)\r
-           {\r
-               cbuf[0] = '\'';\r
-               my_strcpy(cbuf + 1, sizeof(cbuf) - 3, buf, used);   /* 3 = 1('\'') +\r
-                                                                   * strlen("'")\r
-                                                                   * + 1('\0') */\r
-               strcat(cbuf, "'");\r
-           }\r
-           else\r
-               sprintf(cbuf, "'%s'", param_string);\r
-           CVT_APPEND_STR(qb, cbuf);\r
-           break;\r
-\r
-       default:            /* a numeric type or SQL_BIT */\r
-           if (param_sqltype == SQL_BIT)\r
-               CVT_APPEND_CHAR(qb, '\'');      /* Open Quote */\r
-\r
-           if (param_sqltype == SQL_SMALLINT)\r
-           {\r
-               CVT_APPEND_STR(qb, "(");\r
-           }\r
-\r
-           if (buf)\r
-           {\r
-               switch (used)\r
-               {\r
-                   case SQL_NULL_DATA:\r
-                       break;\r
-                   case SQL_NTS:\r
-                       CVT_APPEND_STR(qb, buf);\r
-                       break;\r
-                   default:\r
-                       CVT_APPEND_DATA(qb, buf, used);\r
-               }\r
-           }\r
-           else\r
-               CVT_APPEND_STR(qb, param_string);\r
-\r
-           if (param_sqltype == SQL_SMALLINT)\r
-           {\r
-               /* needs cast because there is no automatic downcast from int4 constants */\r
-               CVT_APPEND_STR(qb, ")::int2");\r
-           }\r
-\r
-           if (param_sqltype == SQL_BIT)\r
-               CVT_APPEND_CHAR(qb, '\'');      /* Close Quote */\r
-\r
-           break;\r
-   }\r
-   if (allocbuf)\r
-       free(allocbuf);\r
-   return SQL_SUCCESS;\r
-}\r
-\r
-\r
-static const char *\r
-mapFunction(const char *func, int param_count)\r
-{\r
-   int         i;\r
-\r
-   for (i = 0; mapFuncs[i][0]; i++)\r
-   {\r
-       if (mapFuncs[i][0][0] == '%')\r
-       {\r
-           if (mapFuncs[i][0][1] - '0' == param_count &&\r
-               !stricmp(mapFuncs[i][0] + 2, func))\r
-               return mapFuncs[i][1];\r
-       }\r
-       else if (!stricmp(mapFuncs[i][0], func))\r
-           return mapFuncs[i][1];\r
-   }\r
-\r
-   return NULL;\r
-}\r
-\r
-/*\r
- * processParameters()\r
- * Process function parameters and work with embedded escapes sequences.\r
- */\r
-static int\r
-processParameters(QueryParse *qp, QueryBuild *qb,\r
-       UInt4 *output_count, Int4 param_pos[][2])\r
-{\r
-   CSTR func = "processParameters";\r
-   int retval, innerParenthesis, param_count;\r
-   BOOL stop;\r
-\r
-   /* begin with outer '(' */\r
-   innerParenthesis = 0;\r
-   param_count = 0;\r
-   stop = FALSE;\r
-   for (; F_OldPos(qp) < qp->stmt_len; F_OldNext(qp))\r
-   {\r
-       retval = inner_process_tokens(qp, qb);\r
-       if (retval == SQL_ERROR)\r
-           return retval;\r
-       if (ENCODE_STATUS(qp->encstr) != 0)\r
-           continue;\r
-       if (qp->in_dquote || qp->in_quote || qp->in_escape)\r
-           continue;\r
-\r
-       switch (F_OldChar(qp))\r
-       {\r
-           case ',':\r
-               if (1 == innerParenthesis)\r
-               {\r
-                   param_pos[param_count][1] = F_NewPos(qb) - 2;\r
-                   param_count++;\r
-                   param_pos[param_count][0] = F_NewPos(qb);\r
-                   param_pos[param_count][1] = -1;\r
-               }\r
-               break;\r
-           case '(':\r
-               if (0 == innerParenthesis)\r
-               {\r
-                   param_pos[param_count][0] = F_NewPos(qb);\r
-                   param_pos[param_count][1] = -1;\r
-               }\r
-               innerParenthesis++;\r
-               break;\r
-     \r
-           case ')':\r
-               innerParenthesis--;\r
-               if (0 == innerParenthesis)\r
-               {\r
-                   param_pos[param_count][1] = F_NewPos(qb) - 2;\r
-                   param_count++;\r
-                   param_pos[param_count][0] =\r
-                   param_pos[param_count][1] = -1;\r
-               }\r
-               if (output_count)\r
-                   *output_count = F_NewPos(qb);\r
-               break;\r
-\r
-           case '}':\r
-               stop = (0 == innerParenthesis);\r
-               break;\r
-\r
-       }\r
-       if (stop) /* returns with the last } position */\r
-           break;\r
-   }\r
-   if (param_pos[param_count][0] >= 0)\r
-   {\r
-       mylog("%s closing ) not found %d\n", func, innerParenthesis);\r
-       qb->errornumber = STMT_EXEC_ERROR;\r
-       qb->errormsg = "processParameters closing ) not found";\r
-       return SQL_ERROR;\r
-   }\r
-   else if (1 == param_count) /* the 1 parameter is really valid ? */\r
-   {\r
-       BOOL    param_exist = FALSE;\r
-       int i;\r
-\r
-       for (i = param_pos[0][0]; i <= param_pos[0][1]; i++)\r
-       {\r
-           if (!isspace(qb->query_statement[i]))\r
-           {\r
-               param_exist = TRUE;\r
-               break;\r
-           }\r
-       }\r
-       if (!param_exist)\r
-       {\r
-           param_pos[0][0] = param_pos[0][1] = -1;\r
-       }\r
-   }\r
-\r
-   return SQL_SUCCESS;\r
-}\r
-\r
-/*\r
- * convert_escape()\r
- * This function doesn't return a pointer to static memory any longer !\r
- */\r
-static int\r
-convert_escape(QueryParse *qp, QueryBuild *qb)\r
-{\r
-   CSTR func = "convert_escape";\r
-   RETCODE retval = SQL_SUCCESS;\r
-   char        buf[1024], buf_small[128], key[65];\r
-   UCHAR   ucv;\r
-   UInt4       prtlen;\r
\r
-   if (F_OldChar(qp) == '{') /* skip the first { */\r
-       F_OldNext(qp);\r
-   /* Separate off the key, skipping leading and trailing whitespace */\r
-   while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))\r
-       F_OldNext(qp);\r
-   /*\r
-    * procedure calls\r
-    */\r
-   if (qp->statement_type == STMT_TYPE_PROCCALL)\r
-   {\r
-       int lit_call_len = 4;\r
-       ConnectionClass *conn = qb->conn;\r
-\r
-       /* '?=' to accept return values exists ? */\r
-       if (F_OldChar(qp) == '?')\r
-       {\r
-           qb->param_number++;\r
-           while (isspace((UCHAR) qp->statement[++qp->opos]));\r
-           if (F_OldChar(qp) != '=')\r
-           {\r
-               F_OldPrior(qp);\r
-               return SQL_SUCCESS;\r
-           }\r
-           while (isspace((UCHAR) qp->statement[++qp->opos]));\r
-       }\r
-       if (strnicmp(F_OldPtr(qp), "call", lit_call_len) ||\r
-           !isspace((UCHAR) F_OldPtr(qp)[lit_call_len]))\r
-       {\r
-           F_OldPrior(qp);\r
-           return SQL_SUCCESS;\r
-       }\r
-       qp->opos += lit_call_len;\r
-       CVT_APPEND_STR(qb, "SELECT ");\r
-       if (my_strchr(conn, F_OldPtr(qp), '('))\r
-           qp->proc_no_param = FALSE;\r
-       return SQL_SUCCESS;\r
-   }\r
-\r
-   sscanf(F_OldPtr(qp), "%32s", key);\r
-   while ((ucv = F_OldChar(qp)) != '\0' && (!isspace(ucv)))\r
-       F_OldNext(qp);\r
-   while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))\r
-       F_OldNext(qp);\r
-    \r
-   /* Avoid the concatenation of the function name with the previous word. Aceto */\r
-\r
-   if (F_NewPos(qb) > 0 && isalnum(F_NewPtr(qb)[-1]))\r
-       CVT_APPEND_CHAR(qb, ' ');\r
-   \r
-   if (stricmp(key, "d") == 0)\r
-   {\r
-       /* Literal; return the escape part adding type cast */\r
-       F_ExtractOldTo(qp, buf_small, '}', sizeof(buf_small));\r
-       if (PG_VERSION_LT(qb->conn, 7.3))\r
-           prtlen = snprintf(buf, sizeof(buf), "%s ", buf_small);\r
-       else\r
-           prtlen = snprintf(buf, sizeof(buf), "%s::date ", buf_small);\r
-       CVT_APPEND_DATA(qb, buf, prtlen);\r
-   }\r
-   else if (stricmp(key, "t") == 0)\r
-   {\r
-       /* Literal; return the escape part adding type cast */\r
-       F_ExtractOldTo(qp, buf_small, '}', sizeof(buf_small));\r
-       prtlen = snprintf(buf, sizeof(buf), "%s::time", buf_small);\r
-       CVT_APPEND_DATA(qb, buf, prtlen);\r
-   }\r
-   else if (stricmp(key, "ts") == 0)\r
-   {\r
-       /* Literal; return the escape part adding type cast */\r
-       F_ExtractOldTo(qp, buf_small, '}', sizeof(buf_small));\r
-       if (PG_VERSION_LT(qb->conn, 7.1))\r
-           prtlen = snprintf(buf, sizeof(buf), "%s::datetime", buf_small);\r
-       else\r
-           prtlen = snprintf(buf, sizeof(buf), "%s::timestamp", buf_small);\r
-       CVT_APPEND_DATA(qb, buf, prtlen);\r
-   }\r
-   else if (stricmp(key, "oj") == 0) /* {oj syntax support for 7.1 * servers */\r
-   {\r
-       F_OldPrior(qp);\r
-       return SQL_SUCCESS; /* Continue at inner_process_tokens loop */\r
-   }\r
-   else if (stricmp(key, "fn") == 0)\r
-   {\r
-       QueryBuild  nqb;\r
-       const char *mapExpr;\r
-       int i, param_count;\r
-       UInt4   param_consumed;\r
-       Int4    param_pos[16][2];\r
-\r
-       /* Separate off the func name, skipping leading and trailing whitespace */\r
-       i = 0;\r
-       while ((ucv = F_OldChar(qp)) != '\0' && ucv != '(' &&\r
-              (!isspace(ucv)))\r
-       {\r
-           if (i < sizeof(key)-1)\r
-               key[i++] = ucv;\r
-           F_OldNext(qp);\r
-       }\r
-       key[i] = '\0';\r
-       while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))\r
-           F_OldNext(qp);\r
-\r
-       /*\r
-        * We expect left parenthesis here, else return fn body as-is\r
-        * since it is one of those "function constants".\r
-        */\r
-       if (F_OldChar(qp) != '(')\r
-       {\r
-           CVT_APPEND_STR(qb, key);\r
-           return SQL_SUCCESS;\r
-       }\r
-\r
-       /*\r
-        * Process parameter list and inner escape\r
-        * sequences\r
-        * Aceto 2002-01-29\r
-        */\r
-\r
-       QB_initialize_copy(&nqb, qb, 1024);\r
-       if (retval = processParameters(qp, &nqb, &param_consumed, param_pos), retval == SQL_ERROR)\r
-       {\r
-           qb->errornumber = nqb.errornumber;\r
-           qb->errormsg = nqb.errormsg;\r
-           QB_Destructor(&nqb);\r
-           return retval;\r
-       }\r
-\r
-       for (param_count = 0;; param_count++)\r
-       {\r
-           if (param_pos[param_count][0] < 0)\r
-               break;\r
-       }\r
-       if (param_count == 1 &&\r
-           param_pos[0][1] < param_pos[0][0])\r
-           param_count = 0;\r
-\r
-       mapExpr = mapFunction(key, param_count);\r
-       if (mapExpr == NULL)\r
-       {\r
-           CVT_APPEND_STR(qb, key);\r
-           CVT_APPEND_DATA(qb, nqb.query_statement, nqb.npos);\r
-       }\r
-       else\r
-       {\r
-           const char *mapptr;\r
-           int from, to, pidx, paramlen;\r
-\r
-           for (prtlen = 0, mapptr = mapExpr; *mapptr; mapptr++)\r
-           {\r
-               if (*mapptr != '$')\r
-               {\r
-                   CVT_APPEND_CHAR(qb, *mapptr);\r
-                   continue;\r
-               }\r
-               mapptr++;\r
-               if (*mapptr == '*')\r
-               {\r
-                   from = 1;\r
-                   to = param_consumed - 2;\r
-               }\r
-               else if (isdigit(*mapptr))\r
-               {\r
-                   pidx = *mapptr - '0' - 1;\r
-                   if (pidx < 0 ||\r
-                       param_pos[pidx][0] < 0)\r
-                   {\r
-                       qb->errornumber = STMT_EXEC_ERROR;\r
-                       qb->errormsg = "param not found";\r
-                       qlog("%s %dth param not found for the expression %s\n", pidx + 1, mapExpr);\r
-                       retval = SQL_ERROR;\r
-                       break;\r
-                   }\r
-                   from = param_pos[pidx][0];\r
-                   to = param_pos[pidx][1];\r
-               }\r
-               else\r
-               {\r
-                   qb->errornumber = STMT_EXEC_ERROR;\r
-                   qb->errormsg = "internal expression error";\r
-                   qlog("%s internal expression error %s\n", func, mapExpr);\r
-                   retval = SQL_ERROR;\r
-                   break;\r
-               }\r
-               paramlen = to - from + 1;\r
-               if (paramlen > 0)\r
-                   CVT_APPEND_DATA(qb, nqb.query_statement+ from, paramlen);\r
-           }\r
-       }\r
-       if (0 == qb->errornumber)\r
-       {\r
-           qb->errornumber = nqb.errornumber;\r
-           qb->errormsg = nqb.errormsg;\r
-       }\r
-       if (SQL_ERROR != retval)\r
-       {\r
-           qb->param_number = nqb.param_number;\r
-           qb->flags = nqb.flags;\r
-       }\r
-       QB_Destructor(&nqb);\r
-   }\r
-   else\r
-   {\r
-       /* Bogus key, leave untranslated */\r
-       return SQL_ERROR;\r
-   }\r
\r
-   return retval;\r
-}\r
-\r
-BOOL\r
-convert_money(const char *s, char *sout, size_t soutmax)\r
-{\r
-   size_t      i = 0,\r
-               out = 0;\r
-\r
-   for (i = 0; s[i]; i++)\r
-   {\r
-       if (s[i] == '$' || s[i] == ',' || s[i] == ')')\r
-           ;                   /* skip these characters */\r
-       else\r
-       {\r
-           if (out + 1 >= soutmax)\r
-               return FALSE;   /* sout is too short */\r
-           if (s[i] == '(')\r
-               sout[out++] = '-';\r
-           else\r
-               sout[out++] = s[i];\r
-       }\r
-   }\r
-   sout[out] = '\0';\r
-   return TRUE;\r
-}\r
-\r
-\r
-/*\r
- * This function parses a character string for date/time info and fills in SIMPLE_TIME\r
- * It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value\r
- */\r
-char\r
-parse_datetime(const char *buf, SIMPLE_TIME *st)\r
-{\r
-   int         y,\r
-               m,\r
-               d,\r
-               hh,\r
-               mm,\r
-               ss;\r
-   int         nf;\r
-\r
-   y = m = d = hh = mm = ss = 0;\r
-   st->fr = 0;\r
-   st->infinity = 0;\r
-\r
-   /* escape sequence ? */\r
-   if (buf[0] == '{')\r
-   {\r
-       while (*(++buf) && *buf != '\'');\r
-       if (!(*buf))\r
-           return FALSE;\r
-       buf++;\r
-   }\r
-   if (buf[4] == '-')          /* year first */\r
-       nf = sscanf(buf, "%4d-%2d-%2d %2d:%2d:%2d", &y, &m, &d, &hh, &mm, &ss);\r
-   else\r
-       nf = sscanf(buf, "%2d-%2d-%4d %2d:%2d:%2d", &m, &d, &y, &hh, &mm, &ss);\r
-\r
-   if (nf == 5 || nf == 6)\r
-   {\r
-       st->y = y;\r
-       st->m = m;\r
-       st->d = d;\r
-       st->hh = hh;\r
-       st->mm = mm;\r
-       st->ss = ss;\r
-\r
-       return TRUE;\r
-   }\r
-\r
-   if (buf[4] == '-')          /* year first */\r
-       nf = sscanf(buf, "%4d-%2d-%2d", &y, &m, &d);\r
-   else\r
-       nf = sscanf(buf, "%2d-%2d-%4d", &m, &d, &y);\r
-\r
-   if (nf == 3)\r
-   {\r
-       st->y = y;\r
-       st->m = m;\r
-       st->d = d;\r
-\r
-       return TRUE;\r
-   }\r
-\r
-   nf = sscanf(buf, "%2d:%2d:%2d", &hh, &mm, &ss);\r
-   if (nf == 2 || nf == 3)\r
-   {\r
-       st->hh = hh;\r
-       st->mm = mm;\r
-       st->ss = ss;\r
-\r
-       return TRUE;\r
-   }\r
-\r
-   return FALSE;\r
-}\r
-\r
-\r
-/* Change linefeed to carriage-return/linefeed */\r
-int\r
-convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *changed)\r
-{\r
-   size_t      i = 0,\r
-               out = 0;\r
-\r
-   if (max == 0)\r
-       max = 0xffffffff;\r
-   *changed = FALSE;\r
-   for (i = 0; si[i] && out < max - 1; i++)\r
-   {\r
-       if (convlf && si[i] == '\n')\r
-       {\r
-           /* Only add the carriage-return if needed */\r
-           if (i > 0 && si[i - 1] == '\r')\r
-           {\r
-               if (dst)\r
-                   dst[out++] = si[i];\r
-               else\r
-                   out++;\r
-               continue;\r
-           }\r
-           *changed = TRUE;\r
-\r
-           if (dst)\r
-           {\r
-               dst[out++] = '\r';\r
-               dst[out++] = '\n';\r
-           }\r
-           else\r
-               out += 2;\r
-       }\r
-       else\r
-       {\r
-           if (dst)\r
-               dst[out++] = si[i];\r
-           else\r
-               out++;\r
-       }\r
-   }\r
-   if (dst)\r
-       dst[out] = '\0';\r
-   return out;\r
-}\r
-\r
-\r
-/*\r
- * Change carriage-return/linefeed to just linefeed\r
- * Plus, escape any special characters.\r
- */\r
-int\r
-convert_special_chars(const char *si, char *dst, int used, BOOL convlf, int ccsc)\r
-{\r
-   size_t      i = 0,\r
-               out = 0,\r
-               max;\r
-   char       *p = NULL;\r
-   encoded_str encstr;\r
-\r
-   if (used == SQL_NTS)\r
-       max = strlen(si);\r
-   else\r
-       max = used;\r
-   if (dst)\r
-   {\r
-       p = dst;\r
-       p[0] = '\0';\r
-   }\r
-   encoded_str_constr(&encstr, ccsc, si);\r
-\r
-   for (i = 0; i < max && si[i]; i++)\r
-   {\r
-       encoded_nextchar(&encstr);\r
-       if (ENCODE_STATUS(encstr) != 0)\r
-       {\r
-           if (p)\r
-               p[out] = si[i];\r
-           out++;\r
-           continue;\r
-       }\r
-       if (convlf && si[i] == '\r' && si[i + 1] == '\n')\r
-           continue;\r
-       else if (si[i] == '\'' || si[i] == '\\')\r
-       {\r
-           if (p)\r
-               p[out++] = '\\';\r
-           else\r
-               out++;\r
-       }\r
-       if (p)\r
-           p[out++] = si[i];\r
-       else\r
-           out++;\r
-   }\r
-   if (p)\r
-       p[out] = '\0';\r
-   return out;\r
-}\r
-\r
-\r
-/* !!! Need to implement this function !!!  */\r
-int\r
-convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax)\r
-{\r
-   mylog("convert_pgbinary_to_char: value = '%s'\n", value);\r
-\r
-   strncpy_null(rgbValue, value, cbValueMax);\r
-   return 0;\r
-}\r
-\r
-\r
-static unsigned int\r
-conv_from_octal(const UCHAR *s)\r
-{\r
-   int         i,\r
-               y = 0;\r
-\r
-   for (i = 1; i <= 3; i++)\r
-       y += (s[i] - '0') << (3 * (3 - i));\r
-\r
-   return y;\r
-\r
-}\r
-\r
-\r
-static unsigned int\r
-conv_from_hex(const UCHAR *s)\r
-{\r
-   int         i,\r
-               y = 0,\r
-               val;\r
-\r
-   for (i = 1; i <= 2; i++)\r
-   {\r
-       if (s[i] >= 'a' && s[i] <= 'f')\r
-           val = s[i] - 'a' + 10;\r
-       else if (s[i] >= 'A' && s[i] <= 'F')\r
-           val = s[i] - 'A' + 10;\r
-       else\r
-           val = s[i] - '0';\r
-\r
-       y += val << (4 * (2 - i));\r
-   }\r
-\r
-   return y;\r
-}\r
-\r
-\r
-/* convert octal escapes to bytes */\r
-int\r
-convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax)\r
-{\r
-   size_t      i,\r
-               ilen = strlen(value);\r
-   int         o = 0;\r
-\r
-\r
-   for (i = 0; i < ilen;)\r
-   {\r
-       if (value[i] == '\\')\r
-       {\r
-           if (value[i + 1] == '\\')\r
-           {\r
-               if (rgbValue)\r
-                   rgbValue[o] = value[i];\r
-               i += 2;\r
-           }\r
-           else\r
-           {\r
-               if (rgbValue)\r
-                   rgbValue[o] = conv_from_octal(&value[i]);\r
-               i += 4;\r
-           }\r
-       }\r
-       else\r
-       {\r
-           if (rgbValue)\r
-               rgbValue[o] = value[i];\r
-           i++;\r
-       }\r
-       /** if (rgbValue)\r
-           mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]); ***/\r
-       o++;\r
-   }\r
-\r
-   if (rgbValue)\r
-       rgbValue[o] = '\0';     /* extra protection */\r
-\r
-   mylog("convert_from_pgbinary: in=%d, out = %d\n", ilen, o);\r
-\r
-   return o;\r
-}\r
-\r
-\r
-static char *\r
-conv_to_octal(UCHAR val, char *octal)\r
-{\r
-   int         i;\r
-\r
-   octal[0] = '\\';\r
-   octal[1] = '\\';\r
-   octal[5] = '\0';\r
-\r
-   for (i = 4; i > 1; i--)\r
-   {\r
-       octal[i] = (val & 7) + '0';\r
-       val >>= 3;\r
-   }\r
-\r
-   return octal;\r
-}\r
-\r
-\r
-/* convert non-ascii bytes to octal escape sequences */\r
-int\r
-convert_to_pgbinary(const UCHAR *in, char *out, int len)\r
-{\r
-   int         i,\r
-               o = 0;\r
-\r
-   for (i = 0; i < len; i++)\r
-   {\r
-       mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);\r
-       if (isalnum(in[i]) || in[i] == ' ')\r
-           out[o++] = in[i];\r
-       else\r
-       {\r
-           conv_to_octal(in[i], &out[o]);\r
-           o += 5;\r
-       }\r
-   }\r
-\r
-   mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);\r
-\r
-   return o;\r
-}\r
-\r
-\r
-void\r
-encode(const char *in, char *out)\r
-{\r
-   unsigned int i,\r
-               ilen = strlen(in),\r
-               o = 0;\r
-\r
-   for (i = 0; i < ilen; i++)\r
-   {\r
-       if (in[i] == '+')\r
-       {\r
-           sprintf(&out[o], "%%2B");\r
-           o += 3;\r
-       }\r
-       else if (isspace((UCHAR) in[i]))\r
-           out[o++] = '+';\r
-       else if (!isalnum((UCHAR) in[i]))\r
-       {\r
-           sprintf(&out[o], "%%%02x", (UCHAR) in[i]);\r
-           o += 3;\r
-       }\r
-       else\r
-           out[o++] = in[i];\r
-   }\r
-   out[o++] = '\0';\r
-}\r
-\r
-\r
-void\r
-decode(const char *in, char *out)\r
-{\r
-   unsigned int i,\r
-               ilen = strlen(in),\r
-               o = 0;\r
-\r
-   for (i = 0; i < ilen; i++)\r
-   {\r
-       if (in[i] == '+')\r
-           out[o++] = ' ';\r
-       else if (in[i] == '%')\r
-       {\r
-           sprintf(&out[o++], "%c", conv_from_hex(&in[i]));\r
-           i += 2;\r
-       }\r
-       else\r
-           out[o++] = in[i];\r
-   }\r
-   out[o++] = '\0';\r
-}\r
-\r
-static const char *hextbl = "0123456789ABCDEF";\r
-static int\r
-pg_bin2hex(UCHAR *src, UCHAR *dst, int length)\r
-{\r
-   UCHAR       chr,\r
-              *src_wk,\r
-              *dst_wk;\r
-   BOOL        backwards;\r
-   int         i;\r
-\r
-   backwards = FALSE;\r
-   if (dst < src)\r
-   {\r
-       if (dst + length > src + 1)\r
-           return -1;\r
-   }\r
-   else if (dst < src + length)\r
-       backwards = TRUE;\r
-   if (backwards)\r
-   {\r
-       for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--)\r
-       {\r
-           chr = *src_wk;\r
-           *dst_wk-- = hextbl[chr % 16];\r
-           *dst_wk-- = hextbl[chr >> 4];\r
-       }\r
-   }\r
-   else\r
-   {\r
-       for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)\r
-       {\r
-           chr = *src_wk;\r
-           *dst_wk++ = hextbl[chr >> 4];\r
-           *dst_wk++ = hextbl[chr % 16];\r
-       }\r
-   }\r
-   dst[2 * length] = '\0';\r
-   return length;\r
-}\r
-\r
-int\r
-pg_hex2bin(const UCHAR *src, UCHAR *dst, int length)\r
-{\r
-   UCHAR       chr;\r
-   const UCHAR *src_wk;\r
-   UCHAR       *dst_wk;\r
-   int     i, val;\r
-   BOOL        HByte = TRUE;\r
-\r
-   for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)\r
-   {\r
-       chr = *src_wk;\r
-       if (chr >= 'a' && chr <= 'f')\r
-           val = chr - 'a' + 10;\r
-       else if (chr >= 'A' && chr <= 'F')\r
-           val = chr - 'A' + 10;\r
-       else\r
-           val = chr - '0';\r
-       if (HByte)\r
-           *dst_wk = (val << 4);\r
-       else\r
-       {\r
-           *dst_wk += val; \r
-           dst_wk++;\r
-       }\r
-       HByte = !HByte;\r
-   }\r
-   *dst_wk = '\0';\r
-   return length;\r
-}\r
-\r
-/*-------\r
- * 1. get oid (from 'value')\r
- * 2. open the large object\r
- * 3. read from the large object (handle multiple GetData)\r
- * 4. close when read less than requested?  -OR-\r
- *     lseek/read each time\r
- *     handle case where application receives truncated and\r
- *     decides not to continue reading.\r
- *\r
- * CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only\r
- * data type currently mapped to a PG_TYPE_LO.  But, if any other types\r
- * are desired to map to a large object (PG_TYPE_LO), then that would\r
- * need to be handled here.  For example, LONGVARCHAR could possibly be\r
- * mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.\r
- *-------\r
- */\r
-int\r
-convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,\r
-          SDWORD cbValueMax, SDWORD *pcbValue)\r
-{\r
-   Oid         oid;\r
-   int         retval,\r
-               result,\r
-               left = -1;\r
-   GetDataClass *gdata = NULL;\r
-   ConnectionClass *conn = SC_get_conn(stmt);\r
-   ConnInfo   *ci = &(conn->connInfo);\r
-   GetDataInfo *gdata_info = SC_get_GDTI(stmt);\r
-   int         factor;\r
-\r
-   switch (fCType)\r
-   {\r
-       case SQL_C_CHAR:\r
-           factor = 2;\r
-           break;\r
-       case SQL_C_BINARY:\r
-           factor = 1;\r
-           break;\r
-       default:\r
-           SC_set_error(stmt, STMT_EXEC_ERROR, "Could not convert lo to the c-type");\r
-           return COPY_GENERAL_ERROR;\r
-   }\r
-   /* If using SQLGetData, then current_col will be set */\r
-   if (stmt->current_col >= 0)\r
-   {\r
-       gdata = &gdata_info->gdata[stmt->current_col];\r
-       left = gdata->data_left;\r
-   }\r
-\r
-   /*\r
-    * if this is the first call for this column, open the large object\r
-    * for reading\r
-    */\r
-\r
-   if (!gdata || gdata->data_left == -1)\r
-   {\r
-       /* begin transaction if needed */\r
-       if (!CC_is_in_trans(conn))\r
-       {\r
-           if (!CC_begin(conn))\r
-           {\r
-               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction");\r
-               return COPY_GENERAL_ERROR;\r
-           }\r
-       }\r
-\r
-       oid = ATOI32U(value);\r
-#ifdef USE_LIBPQ\r
-           stmt->lobj_fd = lo_open(conn->pgconn, oid, INV_READ);\r
-#else\r
-       stmt->lobj_fd = lo_open(conn, oid, INV_READ);\r
-#endif /* USE_LIBPQ*/\r
-\r
-       if (stmt->lobj_fd < 0)\r
-       {\r
-           SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for reading.");\r
-           return COPY_GENERAL_ERROR;\r
-       }\r
-\r
-       /* Get the size */\r
-#ifdef USE_LIBPQ\r
-           retval = lo_lseek(conn->pgconn, stmt->lobj_fd, 0L, SEEK_END);\r
-#else\r
-       retval = lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_END);\r
-#endif /* USE_LIBPQ*/\r
-\r
-       if (retval >= 0)\r
-       {\r
-#ifdef USE_LIBPQ\r
-           left = lo_tell(conn->pgconn, stmt->lobj_fd);\r
-#else\r
-           left = lo_tell(conn, stmt->lobj_fd);\r
-#endif /* USE_LIBPQ*/\r
-\r
-           if (gdata)\r
-               gdata->data_left = left;\r
-\r
-           /* return to beginning */\r
-#ifdef USE_LIBPQ\r
-           lo_lseek(conn->pgconn, stmt->lobj_fd, 0L, SEEK_SET);\r
-#else\r
-           lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET);\r
-#endif /* USE_LIBPQ*/\r
-\r
-       }\r
-   }\r
-   mylog("lo data left = %d\n", left);\r
-\r
-   if (left == 0)\r
-       return COPY_NO_DATA_FOUND;\r
-\r
-   if (stmt->lobj_fd < 0)\r
-   {\r
-       SC_set_error(stmt, STMT_EXEC_ERROR, "Large object FD undefined for multiple read.");\r
-       return COPY_GENERAL_ERROR;\r
-   }\r
-\r
-#ifdef USE_LIBPQ\r
-   retval = lo_read(conn->pgconn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax);\r
-#else\r
-   retval = lo_read(conn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax);\r
-#endif /* USE_LIBPQ */\r
-\r
-   if (retval < 0)\r
-   {\r
-#ifdef USE_LIBPQ\r
-       lo_close(conn->pgconn, stmt->lobj_fd);\r
-#else\r
-       lo_close(conn, stmt->lobj_fd);\r
-#endif /* USE_LIBPQ */\r
-\r
-\r
-       /* commit transaction if needed */\r
-       if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))\r
-       {\r
-           if (!CC_commit(conn))\r
-           {\r
-               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");\r
-               return COPY_GENERAL_ERROR;\r
-           }\r
-       }\r
-\r
-       stmt->lobj_fd = -1;\r
-\r
-       SC_set_error(stmt, STMT_EXEC_ERROR, "Error reading from large object.");\r
-       return COPY_GENERAL_ERROR;\r
-   }\r
-\r
-   if (factor > 1)\r
-       pg_bin2hex((char *) rgbValue, (char *) rgbValue, retval);\r
-   if (retval < left)\r
-       result = COPY_RESULT_TRUNCATED;\r
-   else\r
-       result = COPY_OK;\r
-\r
-   if (pcbValue)\r
-       *pcbValue = left < 0 ? SQL_NO_TOTAL : left * factor;\r
-\r
-   if (gdata && gdata->data_left > 0)\r
-       gdata->data_left -= retval;\r
-\r
-   if (!gdata || gdata->data_left == 0)\r
-   {\r
-#ifdef USE_LIBPQ\r
-       lo_close(conn->pgconn, stmt->lobj_fd);\r
-#else\r
-       lo_close(conn, stmt->lobj_fd);\r
-#endif /* USE_LIBPQ */\r
-\r
-       /* commit transaction if needed */\r
-       if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))\r
-       {\r
-           if (!CC_commit(conn))\r
-           {\r
-               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");\r
-               return COPY_GENERAL_ERROR;\r
-           }\r
-       }\r
-\r
-       stmt->lobj_fd = -1;     /* prevent further reading */\r
-   }\r
-\r
-   return result;\r
-}\r
+/*-------
+ * Module:              convert.c
+ *
+ * Description:    This module contains routines related to
+ *                converting parameters and columns into requested data types.
+ *                Parameters are converted from their SQL_C data types into
+ *                the appropriate postgres type.  Columns are converted from
+ *                their postgres type (SQL type) into the appropriate SQL_C
+ *                data type.
+ *
+ * Classes:           n/a
+ *
+ * API functions:  none
+ *
+ * Comments:      See "notice.txt" for copyright and license information.
+ *-------
+ */
+/* Multibyte support  Eiji Tokuya  2001-03-15  */
+
+#include "convert.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "multibyte.h"
+
+#include <time.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#include <math.h>
+#include <stdlib.h>
+#include "statement.h"
+#include "qresult.h"
+#include "bind.h"
+#include "pgtypes.h"
+#include "lobj.h"
+
+#ifdef USE_LIBPQ
+#include "libpqconnection.h"
+#else
+#include "connection.h"
+#endif /* USE_LIBPQ */
+
+#include "pgapifunc.h"
+
+#if defined(UNICODE_SUPPORT) && defined(WIN32)
+#define    WIN_UNICODE_SUPPORT
+#endif
+
+#ifdef __CYGWIN__
+#  define TIMEZONE_GLOBAL _timezone
+#elif  defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#  ifdef __BORLANDC__
+#    define timezone _timzone
+#    define daylight _daylight
+#    define TIMEZONE_GLOBAL _timezone
+#  else
+#    define TIMEZONE_GLOBAL timezone
+#  endif
+#endif
+
+/*
+ * How to map ODBC scalar functions {fn func(args)} to PostgreSQL.
+ * This is just a simple substitution.  List augmented from:
+ * http://www.merant.com/datadirect/download/docs/odbc16/Odbcref/rappc.htm
+ * - thomas 2000-04-03
+ */
+char      *mapFuncs[][2] = {
+/* { "ASCII",       "ascii"      }, built_in */
+   {"CHAR", "chr($*)" },
+   {"CONCAT", "textcat($*)" },
+/* { "DIFFERENCE", "difference" }, how to ? */
+   {"INSERT", "substring($1 from 1 for $2 - 1) || $4 || substring($1 from $2 + $3)" },
+   {"LCASE", "lower($*)" },
+   {"LEFT", "substring($1 for $2)" },
+   {"%2LOCATE", "strpos($2,  $1)" },   /* 2 parameters */
+   {"%3LOCATE", "strpos(substring($2 from $3), $1) + $3 - 1" },    /* 3 parameters */
+/* { "LENGTH",      "length"     }, built_in */
+/* { "LTRIM",       "ltrim"      }, built_in */
+   {"RIGHT", "substring($1 from char_length($1) - $2 + 1)" },
+   {"SPACE", "repeat(' ', $1)" },
+/* { "REPEAT",      "repeat"     }, built_in */
+/* { "REPLACE",         "replace"    }, built_in */
+/* { "RTRIM",       "rtrim"      }, built_in */
+/* { "SOUNDEX", "soundex" }, how to ? */
+   {"SUBSTRING", "substr($*)" },
+   {"UCASE", "upper($*)" },
+
+/* { "ABS",         "abs"        }, built_in */
+/* { "ACOS",        "acos"       }, built_in */
+/* { "ASIN",        "asin"       }, built_in */
+/* { "ATAN",        "atan"       }, built_in */
+/* { "ATAN2",       "atan2"      }, built_in */
+   {"CEILING", "ceil($*)" },
+/* { "COS",         "cos"        }, built_in */
+/* { "COT",         "cot"        }, built_in */
+/* { "DEGREES",         "degrees"    }, built_in */
+/* { "EXP",         "exp"        }, built_in */
+/* { "FLOOR",       "floor"      }, built_in */
+   {"LOG", "ln($*)" },
+   {"LOG10", "log($*)" },
+/* { "MOD",         "mod"        }, built_in */
+/* { "PI",          "pi"         }, built_in */
+   {"POWER", "pow($*)" },
+/* { "RADIANS",         "radians"    }, built_in */
+   {"%0RAND", "random()" },    /* 0 parameters */
+   {"%1RAND", "(setseed($1) * .0 + random())" },   /* 1 parameters */
+/* { "ROUND",       "round"      }, built_in */
+/* { "SIGN",        "sign"       }, built_in */
+/* { "SIN",         "sin"        }, built_in */
+/* { "SQRT",        "sqrt"       }, built_in */
+/* { "TAN",         "tan"        }, built_in */
+   {"TRUNCATE", "trunc($*)" },
+
+   {"CURRENT_DATE", "current_date" },
+   {"%0CURRENT_TIME", "current_time" },
+   {"%1CURRENT_TIME", "current_time($1)" },
+   {"%0CURRENT_TIMESTAMP", "current_timestamp" },
+   {"%1CURRENT_TIMESTAMP", "current_timestamp($1)" },
+   {"%0LOCALTIME", "localtime" },
+   {"%1LOCALTIME", "localtime($1)" },
+   {"%0LOCALTIMESTAMP", "localtimestamp" },
+   {"%1LOCALTIMESTAMP", "localtimestamp($1)" },
+   {"CURDATE",  "current_date" },
+   {"CURTIME",  "current_time" },
+   {"DAYNAME",  "to_char($1, 'Day')" },
+   {"DAYOFMONTH",  "cast(extract(day from $1) as integer)" },
+   {"DAYOFWEEK",    "(cast(extract(dow from $1) as integer) + 1)" },
+   {"DAYOFYEAR",    "cast(extract(doy from $1) as integer)" }, 
+   {"HOUR",     "cast(extract(hour from $1) as integer)" },
+   {"MINUTE",  "cast(extract(minute from $1) as integer)" },
+   {"MONTH",   "cast(extract(month from $1) as integer)" },
+   {"MONTHNAME",    " to_char($1, 'Month')" },
+/* { "NOW",         "now"        }, built_in */
+   {"QUARTER",  "cast(extract(quarter from $1) as integer)" },
+   {"SECOND",  "cast(extract(second from $1) as integer)" },
+   {"WEEK",    "cast(extract(week from $1) as integer)" },
+   {"YEAR",    "cast(extract(year from $1) as integer)" },
+
+   {"DATABASE", "current_database()" },
+   {"IFNULL", "coalesce($*)" },
+   {"USER", "cast(current_user as text)" },
+   {"CURRENT_USER", "cast(current_user as text)" },
+   {"SESSION_USER", "cast(session_user as text)" },
+   {0, 0}
+};
+
+static const char *mapFunction(const char *func, int param_count);
+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);
+
+/*---------
+ *         A Guide for date/time/timestamp conversions
+ *
+ *         field_type      fCType              Output
+ *         ----------      ------              ----------
+ *         PG_TYPE_DATE    SQL_C_DEFAULT       SQL_C_DATE
+ *         PG_TYPE_DATE    SQL_C_DATE          SQL_C_DATE
+ *         PG_TYPE_DATE    SQL_C_TIMESTAMP     SQL_C_TIMESTAMP     (time = 0 (midnight))
+ *         PG_TYPE_TIME    SQL_C_DEFAULT       SQL_C_TIME
+ *         PG_TYPE_TIME    SQL_C_TIME          SQL_C_TIME
+ *         PG_TYPE_TIME    SQL_C_TIMESTAMP     SQL_C_TIMESTAMP     (date = current date)
+ *         PG_TYPE_ABSTIME SQL_C_DEFAULT       SQL_C_TIMESTAMP
+ *         PG_TYPE_ABSTIME SQL_C_DATE          SQL_C_DATE          (time is truncated)
+ *         PG_TYPE_ABSTIME SQL_C_TIME          SQL_C_TIME          (date is truncated)
+ *         PG_TYPE_ABSTIME SQL_C_TIMESTAMP     SQL_C_TIMESTAMP
+ *---------
+ */
+
+
+/*
+ * Macros for unsigned long handling.
+ */
+#ifdef WIN32
+#define    ATOI32U atol
+#elif  defined(HAVE_STRTOUL)
+#define    ATOI32U(val)    strtoul(val, NULL, 10)
+#else /* HAVE_STRTOUL */
+#define    ATOI32U atol
+#endif /* WIN32 */
+
+/*
+ * Macros for BIGINT handling.
+ */
+#ifdef ODBCINT64
+#ifdef WIN32
+#define    ATOI64  _atoi64
+#define    ATOI64U _atoi64
+#define    FORMATI64   "%I64d"
+#define    FORMATI64U  "%I64u"
+#elif  defined(HAVE_STRTOLL)
+#define    ATOI64(val) strtoll(val, NULL, 10)
+#define    ATOI64U(val)    strtoull(val, NULL, 10)
+#define    FORMATI64   "%lld"
+#define    FORMATI64U  "%llu"
+#else /* HAVE_STRTOLL */
+#endif /* WIN32 */
+#endif /* ODBCINT64 */
+
+/*
+ * TIMESTAMP <-----> SIMPLE_TIME
+ *     precision support since 7.2.
+ *     time zone support is unavailable(the stuff is unreliable)
+ */
+static BOOL
+timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)
+{
+   char        rest[64],
+              *ptr;
+   int         scnt,
+               i;
+#ifdef TIMEZONE_GLOBAL
+   long        timediff;
+#endif
+   BOOL        withZone = *bZone;
+
+   *bZone = FALSE;
+   *zone = 0;
+   st->fr = 0;
+   st->infinity = 0;
+   rest[0] = '\0';
+   if ((scnt = sscanf(str, "%4d-%2d-%2d %2d:%2d:%2d%32s", &st->y, &st->m, &st->d, &st->hh, &st->mm, &st->ss, rest)) < 6)
+       return FALSE;
+   else if (scnt == 6)
+       return TRUE;
+   switch (rest[0])
+   {
+       case '+':
+           *bZone = TRUE;
+           *zone = atoi(&rest[1]);
+           break;
+       case '-':
+           *bZone = TRUE;
+           *zone = -atoi(&rest[1]);
+           break;
+       case '.':
+           if ((ptr = strchr(rest, '+')) != NULL)
+           {
+               *bZone = TRUE;
+               *zone = atoi(&ptr[1]);
+               *ptr = '\0';
+           }
+           else if ((ptr = strchr(rest, '-')) != NULL)
+           {
+               *bZone = TRUE;
+               *zone = -atoi(&ptr[1]);
+               *ptr = '\0';
+           }
+           for (i = 1; i < 10; i++)
+           {
+               if (!isdigit((UCHAR) rest[i]))
+                   break;
+           }
+           for (; i < 10; i++)
+               rest[i] = '0';
+           rest[i] = '\0';
+           st->fr = atoi(&rest[1]);
+           break;
+       default:
+           return TRUE;
+   }
+   if (!withZone || !*bZone || st->y < 1970)
+       return TRUE;
+#ifdef TIMEZONE_GLOBAL
+   if (!tzname[0] || !tzname[0][0])
+   {
+       *bZone = FALSE;
+       return TRUE;
+   }
+   timediff = TIMEZONE_GLOBAL + (*zone) * 3600;
+   if (!daylight && timediff == 0)     /* the same timezone */
+       return TRUE;
+   else
+   {
+       struct tm   tm,
+                  *tm2;
+       time_t      time0;
+
+       *bZone = FALSE;
+       tm.tm_year = st->y - 1900;
+       tm.tm_mon = st->m - 1;
+       tm.tm_mday = st->d;
+       tm.tm_hour = st->hh;
+       tm.tm_min = st->mm;
+       tm.tm_sec = st->ss;
+       tm.tm_isdst = -1;
+       time0 = mktime(&tm);
+       if (time0 < 0)
+           return TRUE;
+       if (tm.tm_isdst > 0)
+           timediff -= 3600;
+       if (timediff == 0)      /* the same time zone */
+           return TRUE;
+       time0 -= timediff;
+#ifdef HAVE_LOCALTIME_R
+       if (time0 >= 0 && (tm2 = localtime_r(&time0, &tm)) != NULL)
+#else
+       if (time0 >= 0 && (tm2 = localtime(&time0)) != NULL)
+#endif /* HAVE_LOCALTIME_R */
+       {
+           st->y = tm2->tm_year + 1900;
+           st->m = tm2->tm_mon + 1;
+           st->d = tm2->tm_mday;
+           st->hh = tm2->tm_hour;
+           st->mm = tm2->tm_min;
+           st->ss = tm2->tm_sec;
+           *bZone = TRUE;
+       }
+   }
+#endif /* TIMEZONE_GLOBAL */
+   return TRUE;
+}
+
+static BOOL
+stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
+{
+   char        precstr[16],
+               zonestr[16];
+   int         i;
+
+   precstr[0] = '\0';
+   if (st->infinity > 0)
+   {
+       strcpy(str, "Infinity");
+       return TRUE;
+   }
+   else if (st->infinity < 0)
+   {
+       strcpy(str, "-Infinity");
+       return TRUE;
+   }
+   if (precision && st->fr)
+   {
+       sprintf(precstr, ".%09d", st->fr);
+       for (i = 9; i > 0; i--)
+       {
+           if (precstr[i] != '0')
+               break;
+           precstr[i] = '\0';
+       }
+   }
+   zonestr[0] = '\0';
+#ifdef TIMEZONE_GLOBAL
+   if (bZone && tzname[0] && tzname[0][0] && st->y >= 1970)
+   {
+       long        zoneint;
+       struct tm   tm;
+       time_t      time0;
+
+       zoneint = TIMEZONE_GLOBAL;
+       if (daylight && st->y >= 1900)
+       {
+           tm.tm_year = st->y - 1900;
+           tm.tm_mon = st->m - 1;
+           tm.tm_mday = st->d;
+           tm.tm_hour = st->hh;
+           tm.tm_min = st->mm;
+           tm.tm_sec = st->ss;
+           tm.tm_isdst = -1;
+           time0 = mktime(&tm);
+           if (time0 >= 0 && tm.tm_isdst > 0)
+               zoneint -= 3600;
+       }
+       if (zoneint > 0)
+           sprintf(zonestr, "-%02d", (int) zoneint / 3600);
+       else
+           sprintf(zonestr, "+%02d", -(int) zoneint / 3600);
+   }
+#endif /* TIMEZONE_GLOBAL */
+   sprintf(str, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d%s%s", st->y, st->m, st->d, st->hh, st->mm, st->ss, precstr, zonestr);
+   return TRUE;
+}
+
+/* This is called by SQLFetch() */
+int
+copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, void *value, int col)
+{
+   ARDFields *opts = SC_get_ARDF(stmt);
+   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)));
+}
+
+
+/* This is called by SQLGetData() */
+int
+copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
+                      PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue)
+{
+   CSTR func = "copy_and_convert_field";
+   ARDFields   *opts = SC_get_ARDF(stmt);
+   GetDataInfo *gdata = SC_get_GDTI(stmt);
+   Int4        len = 0,
+               copy_len = 0;
+   SIMPLE_TIME std_time;
+   time_t      stmt_t = SC_get_time(stmt);
+   struct tm  *tim;
+#ifdef HAVE_LOCALTIME_R
+   struct tm  tm;
+#endif /* HAVE_LOCALTIME_R */
+   int         pcbValueOffset,
+               rgbValueOffset;
+   char       *rgbValueBindRow, *pcbValueBindRow = NULL;
+   const char *ptr;
+   int         bind_row = stmt->bind_row;
+   int         bind_size = opts->bind_size;
+   int         result = COPY_OK;
+   ConnectionClass     *conn = SC_get_conn(stmt);
+   BOOL        changed, true_is_minus1 = FALSE;
+   const char *neut_str = value;
+   char        midtemp[2][32];
+   int         mtemp_cnt = 0;
+   GetDataClass *pgdc;
+#ifdef UNICODE_SUPPORT
+   BOOL    wchanged =   FALSE;
+#endif /* UNICODE_SUPPORT */
+#ifdef WIN_UNICODE_SUPPORT
+   SQLWCHAR    *allocbuf = NULL;
+   Int4        wstrlen;    
+#endif /* WIN_UNICODE_SUPPORT */
+
+   if (stmt->current_col >= 0)
+   {
+       if (stmt->current_col >= opts->allocated)
+       {
+           return SQL_ERROR;
+       }
+       if (gdata->allocated != opts->allocated)
+           extend_getdata_info(gdata, opts->allocated, TRUE);
+       pgdc = &gdata->gdata[stmt->current_col];
+       if (pgdc->data_left == -2)
+           pgdc->data_left = (cbValueMax > 0) ? 0 : -1; /* This seems to be *
+                        * needed by ADO ? */
+       if (pgdc->data_left == 0)
+       {
+           if (pgdc->ttlbuf != NULL)
+           {
+               free(pgdc->ttlbuf);
+               pgdc->ttlbuf = NULL;
+               pgdc->ttlbuflen = 0;
+           }
+           pgdc->data_left = -2;       /* needed by ADO ? */
+           return COPY_NO_DATA_FOUND;
+       }
+   }
+   /*---------
+    *  rgbValueOffset is *ONLY* for character and binary data.
+    *  pcbValueOffset is for computing any pcbValue location
+    *---------
+    */
+
+   if (bind_size > 0)
+       pcbValueOffset = rgbValueOffset = (bind_size * bind_row);
+   else
+   {
+       pcbValueOffset = bind_row * sizeof(SDWORD);
+       rgbValueOffset = bind_row * cbValueMax;
+   }
+   /*
+    *  The following is applicable in case bind_size > 0
+    *  or the fCType is of variable length. 
+    */
+   rgbValueBindRow = (char *) rgbValue + rgbValueOffset;
+   if (pcbValue)
+       pcbValueBindRow = (char *) pcbValue + pcbValueOffset;
+
+   memset(&std_time, 0, sizeof(SIMPLE_TIME));
+
+   /* Initialize current date */
+#ifdef HAVE_LOCALTIME_R
+   tim = localtime_r(&stmt_t, &tm);
+#else
+   tim = localtime(&stmt_t);
+#endif /* HAVE_LOCALTIME_R */
+   std_time.m = tim->tm_mon + 1;
+   std_time.d = tim->tm_mday;
+   std_time.y = tim->tm_year + 1900;
+
+   mylog("copy_and_convert: field_type = %d, fctype = %d, value = '%s', cbValueMax=%d\n", field_type, fCType, (value == NULL) ? "<NULL>" : value, cbValueMax);
+   if (!value)
+   {
+       /*
+        * handle a null just by returning SQL_NULL_DATA in pcbValue, and
+        * doing nothing to the buffer.
+        */
+       if (pcbValue)
+       {
+           *((SDWORD *) pcbValueBindRow) = SQL_NULL_DATA;
+           return COPY_OK;
+       }
+       else
+       {
+           SC_set_error(stmt, STMT_RETURN_NULL_WITHOUT_INDICATOR, "StrLen_or_IndPtr was a null pointer and NULL data was retrieved");  
+           SC_log_error(func, "", stmt);
+           return  SQL_ERROR;
+       }
+   }
+
+   if (stmt->hdbc->DataSourceToDriver != NULL)
+   {
+       int         length = strlen(value);
+
+       stmt->hdbc->DataSourceToDriver(stmt->hdbc->translation_option,
+                                      SQL_CHAR,
+                                      value, length,
+                                      value, length, NULL,
+                                      NULL, 0, NULL);
+   }
+
+   /*
+    * First convert any specific postgres types into more useable data.
+    *
+    * NOTE: Conversions from PG char/varchar of a date/time/timestamp value
+    * to SQL_C_DATE,SQL_C_TIME, SQL_C_TIMESTAMP not supported
+    */
+   switch (field_type)
+   {
+           /*
+            * $$$ need to add parsing for date/time/timestamp strings in
+            * PG_TYPE_CHAR,VARCHAR $$$
+            */
+       case PG_TYPE_DATE:
+           sscanf(value, "%4d-%2d-%2d", &std_time.y, &std_time.m, &std_time.d);
+           break;
+
+       case PG_TYPE_TIME:
+           sscanf(value, "%2d:%2d:%2d", &std_time.hh, &std_time.mm, &std_time.ss);
+           break;
+
+       case PG_TYPE_ABSTIME:
+       case PG_TYPE_DATETIME:
+       case PG_TYPE_TIMESTAMP_NO_TMZONE:
+       case PG_TYPE_TIMESTAMP:
+           std_time.fr = 0;
+           std_time.infinity = 0;
+           if (strnicmp(value, "infinity", 8) == 0)
+           {
+               std_time.infinity = 1;
+               std_time.m = 12;
+               std_time.d = 31;
+               std_time.y = 9999;
+               std_time.hh = 23;
+               std_time.mm = 59;
+               std_time.ss = 59;
+           }
+           if (strnicmp(value, "-infinity", 9) == 0)
+           {
+               std_time.infinity = -1;
+               std_time.m = 0;
+               std_time.d = 0;
+               std_time.y = 0;
+               std_time.hh = 0;
+               std_time.mm = 0;
+               std_time.ss = 0;
+           }
+           if (strnicmp(value, "invalid", 7) != 0)
+           {
+               BOOL        bZone = (field_type != PG_TYPE_TIMESTAMP_NO_TMZONE && PG_VERSION_GE(conn, 7.2));
+               int         zone;
+
+               /*
+                * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &std_time.y, &std_time.m,
+                * &std_time.d, &std_time.hh, &std_time.mm, &std_time.ss);
+                */
+               bZone = FALSE;  /* time zone stuff is unreliable */
+               timestamp2stime(value, &std_time, &bZone, &zone);
+inolog("2stime fr=%d\n", std_time.fr);
+           }
+           else
+           {
+               /*
+                * The timestamp is invalid so set something conspicuous,
+                * like the epoch
+                */
+               time_t  t = 0;
+#ifdef HAVE_LOCALTIME_R
+               tim = localtime_r(&t, &tm);
+#else
+               tim = localtime(&t);
+#endif /* HAVE_LOCALTIME_R */
+               std_time.m = tim->tm_mon + 1;
+               std_time.d = tim->tm_mday;
+               std_time.y = tim->tm_year + 1900;
+               std_time.hh = tim->tm_hour;
+               std_time.mm = tim->tm_min;
+               std_time.ss = tim->tm_sec;
+           }
+           break;
+
+       case PG_TYPE_BOOL:
+           {                   /* change T/F to 1/0 */
+               char       *s;
+
+               s = midtemp[mtemp_cnt];
+               switch (((char *)value)[0])
+               {
+                   case 'f':
+                   case 'F':
+                   case 'n':
+                   case 'N':
+                   case '0':
+                       strcpy(s, "0");
+                       break;
+                   default:
+                       if (true_is_minus1)
+                           strcpy(s, "-1");
+                       else
+                           strcpy(s, "1");
+               }
+               neut_str = midtemp[mtemp_cnt];
+               mtemp_cnt++;
+           }
+           break;
+
+           /* This is for internal use by SQLStatistics() */
+       case PG_TYPE_INT2VECTOR:
+           {
+               int         nval,
+                           i;
+               const char *vp;
+
+               /* this is an array of eight integers */
+               short      *short_array = (short *) rgbValueBindRow;
+
+               len = INDEX_KEYS_STORAGE_COUNT * 2;
+               vp = value;
+               nval = 0;
+               mylog("index=(");
+               for (i = 0; i < INDEX_KEYS_STORAGE_COUNT; i++)
+               {
+                   if (sscanf(vp, "%hd", &short_array[i]) != 1)
+                       break;
+
+                   mylog(" %d", short_array[i]);
+                   nval++;
+
+                   /* skip the current token */
+                   while ((*vp != '\0') && (!isspace((UCHAR) *vp)))
+                       vp++;
+                   /* and skip the space to the next token */
+                   while ((*vp != '\0') && (isspace((UCHAR) *vp)))
+                       vp++;
+                   if (*vp == '\0')
+                       break;
+               }
+               mylog(") nval = %d\n", nval);
+
+               for (i = nval; i < INDEX_KEYS_STORAGE_COUNT; i++)
+                   short_array[i] = 0;
+
+#if 0
+               sscanf(value, "%hd %hd %hd %hd %hd %hd %hd %hd",
+                      &short_array[0],
+                      &short_array[1],
+                      &short_array[2],
+                      &short_array[3],
+                      &short_array[4],
+                      &short_array[5],
+                      &short_array[6],
+                      &short_array[7]);
+#endif
+
+               /* There is no corresponding fCType for this. */
+               if (pcbValue)
+                   *((SDWORD *) pcbValueBindRow) = len;
+
+               return COPY_OK; /* dont go any further or the data will be
+                                * trashed */
+           }
+
+           /*
+            * This is a large object OID, which is used to store
+            * LONGVARBINARY objects.
+            */
+       case PG_TYPE_LO_UNDEFINED:
+
+           return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SDWORD *) pcbValueBindRow);
+
+       default:
+
+           if (field_type == stmt->hdbc->lobj_type)    /* hack until permanent
+                                                        * type available */
+               return convert_lo(stmt, value, fCType, rgbValueBindRow, cbValueMax, (SDWORD *) pcbValueBindRow);
+   }
+
+   /* Change default into something useable */
+   if (fCType == SQL_C_DEFAULT)
+   {
+       fCType = pgtype_to_ctype(stmt, field_type);
+
+       mylog("copy_and_convert, SQL_C_DEFAULT: fCType = %d\n", fCType);
+   }
+
+#ifdef UNICODE_SUPPORT
+   if (fCType == SQL_C_CHAR || fCType == SQL_C_WCHAR
+#else
+   if (fCType == SQL_C_CHAR
+#endif /* UNICODE_SUPPORT */
+       || fCType == INTERNAL_ASIS_TYPE)
+   {
+       /* Special character formatting as required */
+
+       /*
+        * These really should return error if cbValueMax is not big
+        * enough.
+        */
+       switch (field_type)
+       {
+           case PG_TYPE_DATE:
+               len = 10;
+               if (cbValueMax > len)
+                   sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", std_time.y, std_time.m, std_time.d);
+               break;
+
+           case PG_TYPE_TIME:
+               len = 8;
+               if (cbValueMax > len)
+                   sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", std_time.hh, std_time.mm, std_time.ss);
+               break;
+
+           case PG_TYPE_ABSTIME:
+           case PG_TYPE_DATETIME:
+           case PG_TYPE_TIMESTAMP_NO_TMZONE:
+           case PG_TYPE_TIMESTAMP:
+               len = 19;
+               if (cbValueMax > len)
+                   sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
+                           std_time.y, std_time.m, std_time.d, std_time.hh, std_time.mm, std_time.ss);
+               break;
+
+           case PG_TYPE_BOOL:
+               len = strlen(neut_str);
+               if (cbValueMax > len)
+               {
+                   strcpy(rgbValueBindRow, neut_str);
+                   mylog("PG_TYPE_BOOL: rgbValueBindRow = '%s'\n", rgbValueBindRow);
+               }
+               break;
+
+               /*
+                * Currently, data is SILENTLY TRUNCATED for BYTEA and
+                * character data types if there is not enough room in
+                * cbValueMax because the driver can't handle multiple
+                * calls to SQLGetData for these, yet.  Most likely, the
+                * buffer passed in will be big enough to handle the
+                * maximum limit of postgres, anyway.
+                *
+                * LongVarBinary types are handled correctly above, observing
+                * truncation and all that stuff since there is
+                * essentially no limit on the large object used to store
+                * those.
+                */
+           case PG_TYPE_BYTEA:/* convert binary data to hex strings
+                                * (i.e, 255 = "FF") */
+
+           default:
+               if (stmt->current_col < 0)
+               {
+                   pgdc = &(gdata->fdata);
+                   pgdc->data_left = -1;
+               }
+               else
+                   pgdc = &gdata->gdata[stmt->current_col];
+               if (pgdc->data_left < 0)
+               {
+                   BOOL lf_conv = conn->connInfo.lf_conversion;
+#ifdef UNICODE_SUPPORT
+                   if (fCType == SQL_C_WCHAR)
+                   {
+                       len = utf8_to_ucs2_lf(neut_str, -1, lf_conv, NULL, 0);
+                       len *= WCLEN;
+                       wchanged = changed = TRUE;
+                   }
+                   else
+#endif /* UNICODE_SUPPORT */
+                   if (PG_TYPE_BYTEA == field_type)
+                   {
+                       len = convert_from_pgbinary(neut_str, NULL, 0);
+                       len *= 2;
+                       changed = TRUE;
+                   }
+                   else
+#ifdef WIN_UNICODE_SUPPORT
+                   if (fCType == SQL_C_CHAR)
+                   {
+                       wstrlen = utf8_to_ucs2_lf(neut_str, -1, lf_conv, NULL, 0);
+                       allocbuf = (SQLWCHAR *) malloc(WCLEN * (wstrlen + 1));
+                       wstrlen = utf8_to_ucs2_lf(neut_str, -1, lf_conv, allocbuf, wstrlen + 1);
+                       len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) allocbuf, wstrlen, NULL, 0, NULL, NULL);
+                       changed = TRUE;
+                   }
+                   else
+#endif /* WIN_UNICODE_SUPPORT */
+                       /* convert linefeeds to carriage-return/linefeed */
+                       len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);
+                   if (cbValueMax == 0)        /* just returns length
+                                                * info */
+                   {
+                       result = COPY_RESULT_TRUNCATED;
+#ifdef WIN_UNICODE_SUPPORT
+                       if (allocbuf)
+                           free(allocbuf);
+#endif /* WIN_UNICODE_SUPPORT */
+                       break;
+                   }
+                   if (!pgdc->ttlbuf)
+                       pgdc->ttlbuflen = 0;
+                   if (changed || len >= cbValueMax)
+                   {
+                       if (len >= (int) pgdc->ttlbuflen)
+                       {
+                           pgdc->ttlbuf = realloc(pgdc->ttlbuf, len + 1);
+                           pgdc->ttlbuflen = len + 1;
+                       }
+#ifdef UNICODE_SUPPORT
+                       if (fCType == SQL_C_WCHAR)
+                       {
+                           utf8_to_ucs2_lf(neut_str, -1, lf_conv, (SQLWCHAR *) pgdc->ttlbuf, len / WCLEN);
+                       }
+                       else
+#endif /* UNICODE_SUPPORT */
+                       if (PG_TYPE_BYTEA == field_type)
+                       {
+                           len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
+                           pg_bin2hex(pgdc->ttlbuf, pgdc->ttlbuf, len);
+                           len *= 2; 
+                       }
+                       else
+#ifdef WIN_UNICODE_SUPPORT
+                       if (fCType == SQL_C_CHAR)
+                       {
+                           len = WideCharToMultiByte(CP_ACP, 0, allocbuf, wstrlen, pgdc->ttlbuf, pgdc->ttlbuflen, NULL, NULL);
+                           free(allocbuf);
+                           allocbuf = NULL;
+                       }
+                       else
+#endif /* WIN_UNICODE_SUPPORT */
+                           convert_linefeeds(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen, lf_conv, &changed);
+                       ptr = pgdc->ttlbuf;
+                       pgdc->ttlbufused = len;
+                   }
+                   else
+                   {
+                       if (pgdc->ttlbuf)
+                       {
+                           free(pgdc->ttlbuf);
+                           pgdc->ttlbuf = NULL;
+                       }
+                       ptr = neut_str;
+                   }
+               }
+               else
+               {
+                   ptr = pgdc->ttlbuf;
+                   len = pgdc->ttlbufused;
+               }
+
+               mylog("DEFAULT: len = %d, ptr = '%s'\n", len, ptr);
+
+               if (stmt->current_col >= 0)
+               {
+                   if (pgdc->data_left > 0)
+                   {
+                       ptr += len - pgdc->data_left;
+                       len = pgdc->data_left;
+                   }
+                   else
+                       pgdc->data_left = len;
+               }
+
+               if (cbValueMax > 0)
+               {
+                   BOOL    already_copied = FALSE;
+
+                   copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
+#ifdef UNICODE_SUPPORT
+                   if (fCType == SQL_C_WCHAR)
+                   {
+                       copy_len /= WCLEN;
+                       copy_len *= WCLEN;
+                   }
+#endif /* UNICODE_SUPPORT */
+#ifdef HAVE_LOCALE_H
+                   switch (field_type)
+                   {
+                       case PG_TYPE_FLOAT4:
+                       case PG_TYPE_FLOAT8:
+                       case PG_TYPE_NUMERIC:
+                       {
+                           struct lconv    *lc;
+                           char        *new_string;
+                           int     i, j;
+
+                           new_string = malloc(cbValueMax);
+                           lc = localeconv();
+                           for (i = 0, j = 0; ptr[i]; i++)
+                               if (ptr[i] == '.')
+                               {
+                                   strncpy(&new_string[j], lc->decimal_point, strlen(lc->decimal_point));
+                                   j += strlen(lc->decimal_point);
+                               }
+                               else
+                                   new_string[j++] = ptr[i];
+                           new_string[j] = '\0';
+                           strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
+                           free(new_string);
+                           already_copied = TRUE;
+                           break;
+                       }
+                   }
+#endif /* HAVE_LOCALE_H */
+                   if (!already_copied)
+                   {
+                       /* Copy the data */
+                       memcpy(rgbValueBindRow, ptr, copy_len);
+                       /* Add null terminator */
+#ifdef UNICODE_SUPPORT
+                       if (fCType == SQL_C_WCHAR)
+                           memset(rgbValueBindRow + copy_len, 0, WCLEN);
+                       else
+#endif /* UNICODE_SUPPORT */
+                       rgbValueBindRow[copy_len] = '\0';
+                   }
+                   /* Adjust data_left for next time */
+                   if (stmt->current_col >= 0)
+                       pgdc->data_left -= copy_len;
+               }
+
+               /*
+                * Finally, check for truncation so that proper status can
+                * be returned
+                */
+               if (cbValueMax > 0 && len >= cbValueMax)
+                   result = COPY_RESULT_TRUNCATED;
+               else
+               {
+                   if (pgdc->ttlbuf != NULL)
+                   {
+                       free(pgdc->ttlbuf);
+                       pgdc->ttlbuf = NULL;
+                   }
+               }
+
+
+               mylog("    SQL_C_CHAR, default: len = %d, cbValueMax = %d, rgbValueBindRow = '%s'\n", len, cbValueMax, rgbValueBindRow);
+               break;
+       }
+#ifdef UNICODE_SUPPORT
+       if (SQL_C_WCHAR == fCType && ! wchanged)
+       {
+           if (cbValueMax > (SDWORD) (WCLEN * (len + 1)))
+           {
+               char *str = strdup(rgbValueBindRow);
+               UInt4   ucount = utf8_to_ucs2(str, len, (SQLWCHAR *) rgbValueBindRow, cbValueMax / WCLEN);
+               if (cbValueMax < (SDWORD) (WCLEN * ucount))
+                   result = COPY_RESULT_TRUNCATED;
+               free(str); 
+           }
+           else
+           {
+                if ((SDWORD) (len + WCLEN) <= cbValueMax)
+                {
+                    result = COPY_OK;
+                }
+                else
+                    result = COPY_RESULT_TRUNCATED; 
+           }
+       }
+#endif /* UNICODE_SUPPORT */
+
+   }
+   else
+   {
+       /*
+        * for SQL_C_CHAR, it's probably ok to leave currency symbols in.
+        * But to convert to numeric types, it is necessary to get rid of
+        * those.
+        */
+       if (field_type == PG_TYPE_MONEY)
+       {
+           if (convert_money(neut_str, midtemp[mtemp_cnt], sizeof(midtemp[0])))
+           {
+               neut_str = midtemp[mtemp_cnt];
+               mtemp_cnt++;
+           }
+           else
+           {
+               qlog("couldn't convert money type to %d\n", fCType);
+               return COPY_UNSUPPORTED_TYPE;
+           }
+       }
+
+       switch (fCType)
+       {
+           case SQL_C_DATE:
+           case SQL_C_TYPE_DATE:       /* 91 */
+
+               len = 6;
+               {
+                   DATE_STRUCT *ds;
+
+                   if (bind_size > 0)
+                       ds = (DATE_STRUCT *) rgbValueBindRow;
+                   else
+                       ds = (DATE_STRUCT *) rgbValue + bind_row;
+                   ds->year = std_time.y;
+                   ds->month = std_time.m;
+                   ds->day = std_time.d;
+               }
+               break;
+
+           case SQL_C_TIME:
+           case SQL_C_TYPE_TIME:       /* 92 */
+
+               len = 6;
+               {
+                   TIME_STRUCT *ts;
+
+                   if (bind_size > 0)
+                       ts = (TIME_STRUCT *) rgbValueBindRow;
+                   else
+                       ts = (TIME_STRUCT *) rgbValue + bind_row;
+                   ts->hour = std_time.hh;
+                   ts->minute = std_time.mm;
+                   ts->second = std_time.ss;
+               }
+               break;
+
+           case SQL_C_TIMESTAMP:
+           case SQL_C_TYPE_TIMESTAMP:  /* 93 */
+
+               len = 16;
+               {
+                   TIMESTAMP_STRUCT *ts;
+
+                   if (bind_size > 0)
+                       ts = (TIMESTAMP_STRUCT *) rgbValueBindRow;
+                   else
+                       ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row;
+                   ts->year = std_time.y;
+                   ts->month = std_time.m;
+                   ts->day = std_time.d;
+                   ts->hour = std_time.hh;
+                   ts->minute = std_time.mm;
+                   ts->second = std_time.ss;
+                   ts->fraction = std_time.fr;
+               }
+               break;
+
+           case SQL_C_BIT:
+               len = 1;
+               if (bind_size > 0)
+                   *((UCHAR *) rgbValueBindRow) = atoi(neut_str);
+               else
+                   *((UCHAR *) rgbValue + bind_row) = atoi(neut_str);
+
+               /*
+                * mylog("SQL_C_BIT: bind_row = %d val = %d, cb = %d,
+                * rgb=%d\n", bind_row, atoi(neut_str), cbValueMax,
+                * *((UCHAR *)rgbValue));
+                */
+               break;
+
+           case SQL_C_STINYINT:
+           case SQL_C_TINYINT:
+               len = 1;
+               if (bind_size > 0)
+                   *((SCHAR *) rgbValueBindRow) = atoi(neut_str);
+               else
+                   *((SCHAR *) rgbValue + bind_row) = atoi(neut_str);
+               break;
+
+           case SQL_C_UTINYINT:
+               len = 1;
+               if (bind_size > 0)
+                   *((UCHAR *) rgbValueBindRow) = atoi(neut_str);
+               else
+                   *((UCHAR *) rgbValue + bind_row) = atoi(neut_str);
+               break;
+
+           case SQL_C_FLOAT:
+           {
+#ifdef HAVE_LOCALE_H
+               char *saved_locale;
+
+               saved_locale = strdup(setlocale(LC_ALL, NULL));
+               setlocale(LC_ALL, "C");
+#endif /* HAVE_LOCALE_H */
+               len = 4;
+               if (bind_size > 0)
+                   *((SFLOAT *) rgbValueBindRow) = (float) atof(neut_str);
+               else
+                   *((SFLOAT *) rgbValue + bind_row) = (float) atof(neut_str);
+#ifdef HAVE_LOCALE_H
+               setlocale(LC_ALL, saved_locale);
+               free(saved_locale);
+#endif /* HAVE_LOCALE_H */
+               break;
+           }
+
+           case SQL_C_DOUBLE:
+           {
+#ifdef HAVE_LOCALE_H
+               char *saved_locale;
+
+               saved_locale = strdup(setlocale(LC_ALL, NULL));
+               setlocale(LC_ALL, "C");
+#endif /* HAVE_LOCALE_H */
+               len = 8;
+               if (bind_size > 0)
+                   *((SDOUBLE *) rgbValueBindRow) = atof(neut_str);
+               else
+                   *((SDOUBLE *) rgbValue + bind_row) = atof(neut_str);
+#ifdef HAVE_LOCALE_H
+               setlocale(LC_ALL, saved_locale);
+               free(saved_locale);
+#endif /* HAVE_LOCALE_H */
+               break;
+           }
+
+           case SQL_C_NUMERIC:
+           {
+               SQL_NUMERIC_STRUCT      *ns;
+               int i, nlen, bit, hval, tv, dig, sta, olen;
+               char    calv[SQL_MAX_NUMERIC_LEN * 3];
+               const char *wv;
+               BOOL    dot_exist;
+
+               len = sizeof(SQL_NUMERIC_STRUCT);
+               if (bind_size > 0)
+                   ns = (SQL_NUMERIC_STRUCT *) rgbValueBindRow;
+               else
+                   ns = (SQL_NUMERIC_STRUCT *) rgbValue + bind_row;
+               for (wv = neut_str; *wv && isspace(*wv); wv++)
+                   ;
+               ns->sign = 1;
+               if (*wv == '-')
+               {
+                   ns->sign = 0;
+                   wv++;
+               }
+               else if (*wv == '+')
+                   wv++;
+               while (*wv == '0') wv++;
+               ns->precision = 0;
+               ns->scale = 0;
+               for (nlen = 0, dot_exist = FALSE;; wv++) 
+               {
+                   if (*wv == '.')
+                   {
+                       if (dot_exist)
+                           break;
+                       dot_exist = TRUE;
+                   }
+                   else if (!isdigit(*wv))
+                       break;
+                   else
+                   {
+                       if (dot_exist)
+                           ns->scale++;
+
+                       ns->precision++;
+                       calv[nlen++] = *wv;
+                   }
+               }
+               memset(ns->val, 0, sizeof(ns->val));
+               for (hval = 0, bit = 1L, sta = 0, olen = 0; sta < nlen;)
+               {
+                   for (dig = 0, i = sta; i < nlen; i++)
+                   {
+                       tv = dig * 10 + calv[i] - '0';
+                       dig = tv % 2;
+                       calv[i] = tv / 2 + '0';
+                       if (i == sta && tv < 2)
+                           sta++;
+                   }
+                   if (dig > 0)
+                       hval |= bit;
+                   bit <<= 1;
+                   if (bit >= (1L << 8))
+                   {
+                       ns->val[olen++] = hval;
+                       hval = 0;
+                       bit = 1L;
+                       if (olen >= SQL_MAX_NUMERIC_LEN - 1)
+                       {
+                           ns->scale = sta - ns->precision;
+                           break;
+                       }
+                   } 
+               }
+               if (hval && olen < SQL_MAX_NUMERIC_LEN - 1)
+                   ns->val[olen++] = hval;
+
+               break;
+           }
+
+           case SQL_C_SSHORT:
+           case SQL_C_SHORT:
+               len = 2;
+               if (bind_size > 0)
+                   *((SWORD *) rgbValueBindRow) = atoi(neut_str);
+               else
+                   *((SWORD *) rgbValue + bind_row) = atoi(neut_str);
+               break;
+
+           case SQL_C_USHORT:
+               len = 2;
+               if (bind_size > 0)
+                   *((UWORD *) rgbValueBindRow) = atoi(neut_str);
+               else
+                   *((UWORD *) rgbValue + bind_row) = atoi(neut_str);
+               break;
+
+           case SQL_C_SLONG:
+           case SQL_C_LONG:
+               len = 4;
+               if (bind_size > 0)
+                   *((SDWORD *) rgbValueBindRow) = atol(neut_str);
+               else
+                   *((SDWORD *) rgbValue + bind_row) = atol(neut_str);
+               break;
+
+           case SQL_C_ULONG:
+               len = 4;
+               if (bind_size > 0)
+                   *((UDWORD *) rgbValueBindRow) = ATOI32U(neut_str);
+               else
+                   *((UDWORD *) rgbValue + bind_row) = ATOI32U(neut_str);
+               break;
+
+#ifdef ODBCINT64
+           case SQL_C_SBIGINT:
+           case SQL_BIGINT: /* Is this needed ? */
+               len = 8;
+               if (bind_size > 0)
+                   *((SQLBIGINT *) rgbValueBindRow) = ATOI64(neut_str);
+               else
+                   *((SQLBIGINT *) rgbValue + bind_row) = ATOI64(neut_str);
+               break;
+
+           case SQL_C_UBIGINT:
+               len = 8;
+               if (bind_size > 0)
+                   *((SQLUBIGINT *) rgbValueBindRow) = ATOI64U(neut_str);
+               else
+                   *((SQLUBIGINT *) rgbValue + bind_row) = ATOI64U(neut_str);
+               break;
+
+#endif /* ODBCINT64 */
+           case SQL_C_BINARY:
+               if (PG_TYPE_UNKNOWN == field_type ||
+                   PG_TYPE_TEXT == field_type ||
+                   PG_TYPE_VARCHAR == field_type ||
+                   PG_TYPE_BPCHAR == field_type)
+               {
+                   int len = SQL_NULL_DATA;
+
+                   if (neut_str)
+                       len = strlen(neut_str);
+                   if (pcbValue)
+                       *((SDWORD *) pcbValueBindRow) = len;
+                   if (len > 0 && cbValueMax > 0)
+                   {
+                       memcpy(rgbValueBindRow, neut_str, len < cbValueMax ? len : cbValueMax);
+                       if (cbValueMax >= len + 1)
+                           rgbValueBindRow[len] = '\0';
+                   }
+                   if (cbValueMax >= len)
+                       return COPY_OK;
+                   else
+                       return COPY_RESULT_TRUNCATED;
+               }
+               /* The following is for SQL_C_VARBOOKMARK */
+               else if (PG_TYPE_INT4 == field_type)
+               {
+                   UInt4   ival = ATOI32U(neut_str);
+
+inolog("SQL_C_VARBOOKMARK value=%d\n", ival);
+                   if (pcbValue)
+                       *((SDWORD *) pcbValueBindRow) = sizeof(ival);
+                   if (cbValueMax >= sizeof(ival))
+                   {
+                       memcpy(rgbValueBindRow, &ival, sizeof(ival));
+                       return COPY_OK;
+                   }
+                   else    
+                       return COPY_RESULT_TRUNCATED;
+               }
+               else if (PG_TYPE_BYTEA != field_type)
+               {
+                   mylog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);
+                   qlog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);
+                   return COPY_UNSUPPORTED_TYPE;
+               }
+               /* truncate if necessary */
+               /* convert octal escapes to bytes */
+
+               if (stmt->current_col < 0)
+               {
+                   pgdc = &(gdata->fdata);
+                   pgdc->data_left = -1;
+               }
+               else
+                   pgdc = &gdata->gdata[stmt->current_col];
+               if (!pgdc->ttlbuf)
+                   pgdc->ttlbuflen = 0;
+               if (pgdc->data_left < 0)
+               {
+                   if (cbValueMax <= 0)
+                   {
+                       len = convert_from_pgbinary(neut_str, NULL, 0);
+                       result = COPY_RESULT_TRUNCATED;
+                       break;
+                   }
+                   if (len = strlen(neut_str), len >= (int) pgdc->ttlbuflen)
+                   {
+                       pgdc->ttlbuf = realloc(pgdc->ttlbuf, len + 1);
+                       pgdc->ttlbuflen = len + 1;
+                   }
+                   len = convert_from_pgbinary(neut_str, pgdc->ttlbuf, pgdc->ttlbuflen);
+                   pgdc->ttlbufused = len;
+               }
+               else
+                   len = pgdc->ttlbufused;
+               ptr = pgdc->ttlbuf;
+
+               if (stmt->current_col >= 0)
+               {
+                   /*
+                    * Second (or more) call to SQLGetData so move the
+                    * pointer
+                    */
+                   if (pgdc->data_left > 0)
+                   {
+                       ptr += len - pgdc->data_left;
+                       len = pgdc->data_left;
+                   }
+
+                   /* First call to SQLGetData so initialize data_left */
+                   else
+                       pgdc->data_left = len;
+
+               }
+
+               if (cbValueMax > 0)
+               {
+                   copy_len = (len > cbValueMax) ? cbValueMax : len;
+
+                   /* Copy the data */
+                   memcpy(rgbValueBindRow, ptr, copy_len);
+
+                   /* Adjust data_left for next time */
+                   if (stmt->current_col >= 0)
+                       pgdc->data_left -= copy_len;
+               }
+
+               /*
+                * Finally, check for truncation so that proper status can
+                * be returned
+                */
+               if (len > cbValueMax)
+                   result = COPY_RESULT_TRUNCATED;
+               else if (pgdc->ttlbuf)
+               {
+                   free(pgdc->ttlbuf);
+                   pgdc->ttlbuf = NULL;
+               }
+               mylog("SQL_C_BINARY: len = %d, copy_len = %d\n", len, copy_len);
+               break;
+
+           default:
+               qlog("conversion to the type %d isn't supported\n", fCType);
+               return COPY_UNSUPPORTED_TYPE;
+       }
+   }
+
+   /* store the length of what was copied, if there's a place for it */
+   if (pcbValue)
+       *((SDWORD *) pcbValueBindRow) = len;
+
+   if (result == COPY_OK && stmt->current_col >= 0)
+       gdata->gdata[stmt->current_col].data_left = 0;
+   return result;
+
+}
+
+
+/*--------------------------------------------------------------------
+ * Functions/Macros to get rid of query size limit.
+ *
+ * I always used the follwoing macros to convert from
+ * old_statement to new_statement.  Please improve it
+ * if you have a better way.   Hiroshi 2001/05/22
+ *--------------------------------------------------------------------
+ */
+
+#define    FLGP_PREPARE_DUMMY_CURSOR   1L
+#define    FLGP_CURSOR_CHECK_OK    (1L << 1)
+#define    FLGP_SELECT_INTO        (1L << 2)
+#define    FLGP_SELECT_FOR_UPDATE  (1L << 3)
+#define    FLGP_BUILDING_PREPARE_STATEMENT (1L << 4)
+typedef struct _QueryParse {
+   const char  *statement;
+   int     statement_type;
+   UInt4       opos;
+   int     from_pos;
+   int     where_pos;
+   UInt4       stmt_len;
+   BOOL        in_quote, in_dquote, in_escape;
+   char        token_save[64];
+   int     token_len;
+   BOOL        prev_token_end;
+   BOOL        proc_no_param;
+   unsigned    int declare_pos;
+   UInt4       flags;
+   encoded_str encstr;
+}  QueryParse;
+
+static int
+QP_initialize(QueryParse *q, const StatementClass *stmt)
+{
+   q->statement = stmt->execute_statement ? stmt->execute_statement : stmt->statement;
+   q->statement_type = stmt->statement_type;
+   q->opos = 0;
+   q->from_pos = -1;
+   q->where_pos = -1;
+   q->stmt_len = (q->statement) ? strlen(q->statement) : -1;
+   q->in_quote = q->in_dquote = q->in_escape = FALSE;
+   q->token_save[0] = '\0';
+   q->token_len = 0;
+   q->prev_token_end = TRUE;
+   q->proc_no_param = TRUE;
+   q->declare_pos = 0;
+   q->flags = 0;
+   make_encoded_str(&q->encstr, SC_get_conn(stmt), q->statement);
+
+   return q->stmt_len;
+}
+
+#define    FLGB_PRE_EXECUTING  1L
+#define    FLGB_INACCURATE_RESULT  (1L << 1)
+#define    FLGB_CREATE_KEYSET  (1L << 2)
+#define    FLGB_KEYSET_DRIVEN  (1L << 3)
+#define    FLGB_BUILDING_PREPARE_STATEMENT (1L << 4)
+typedef struct _QueryBuild {
+   char    *query_statement;
+   UInt4   str_size_limit;
+   UInt4   str_alsize;
+   UInt4   npos;
+   int current_row;
+   int param_number;
+   APDFields *apdopts;
+   IPDFields *ipdopts;
+   PutDataInfo *pdata;
+   UInt4   load_stmt_len;
+   UInt4   flags;
+   BOOL    lf_conv;
+   int ccsc;
+   int errornumber;
+   const char *errormsg;
+
+   ConnectionClass *conn; /* mainly needed for LO handling */
+   StatementClass  *stmt; /* needed to set error info in ENLARGE_.. */ 
+}  QueryBuild;
+
+#define INIT_MIN_ALLOC 4096
+static int
+QB_initialize(QueryBuild *qb, UInt4 size, StatementClass *stmt, ConnectionClass *conn)
+{
+   UInt4   newsize = 0;
+
+   qb->flags = 0;
+   qb->load_stmt_len = 0;
+   qb->stmt = stmt;
+   qb->apdopts = NULL;
+   qb->ipdopts = NULL;
+   qb->pdata = NULL;
+   if (conn)
+       qb->conn = conn;
+   else if (stmt)
+   {
+       qb->apdopts = SC_get_APDF(stmt);
+       qb->ipdopts = SC_get_IPDF(stmt);
+       qb->pdata = SC_get_PDTI(stmt);
+       qb->conn = SC_get_conn(stmt);
+       if (stmt->pre_executing)
+           qb->flags |= FLGB_PRE_EXECUTING;
+   }
+   else
+   {
+       qb->conn = NULL;
+       return -1;
+   }
+   qb->lf_conv = qb->conn->connInfo.lf_conversion;
+   qb->ccsc = qb->conn->ccsc;
+       
+   if (stmt)
+       qb->str_size_limit = stmt->stmt_size_limit;
+   else
+       qb->str_size_limit = -1;
+   if (qb->str_size_limit > 0)
+   {
+       if (size > qb->str_size_limit)
+           return -1;
+       newsize = qb->str_size_limit;
+   }
+   else 
+   {
+       newsize = INIT_MIN_ALLOC;
+       while (newsize <= size)
+           newsize *= 2;
+   }
+   if ((qb->query_statement = malloc(newsize)) == NULL)
+   {
+       qb->str_alsize = 0;
+       return -1;
+   }   
+   qb->query_statement[0] = '\0';
+   qb->str_alsize = newsize;
+   qb->npos = 0;
+   qb->current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
+   qb->param_number = -1;
+   qb->errornumber = 0;
+   qb->errormsg = NULL;
+
+   return newsize;
+}
+
+static int
+QB_initialize_copy(QueryBuild *qb_to, const QueryBuild *qb_from, UInt4 size)
+{
+   memcpy(qb_to, qb_from, sizeof(QueryBuild));
+
+   if (qb_to->str_size_limit > 0)
+   {
+       if (size > qb_to->str_size_limit)
+           return -1;
+   }
+   if ((qb_to->query_statement = malloc(size)) == NULL)
+   {
+       qb_to->str_alsize = 0;
+       return -1;
+   }   
+   qb_to->query_statement[0] = '\0';
+   qb_to->str_alsize = size;
+   qb_to->npos = 0;
+
+   return size;
+}
+
+static void
+QB_Destructor(QueryBuild *qb)
+{
+   if (qb->query_statement)
+   {
+       free(qb->query_statement);
+       qb->query_statement = NULL;
+       qb->str_alsize = 0;
+   }
+}
+
+/*
+ * New macros (Aceto)
+ *--------------------
+ */
+
+#define F_OldChar(qp) \
+qp->statement[qp->opos]
+
+#define F_OldPtr(qp) \
+(qp->statement + qp->opos)
+
+#define F_OldNext(qp) \
+(++qp->opos)
+
+#define F_OldPrior(qp) \
+(--qp->opos)
+
+#define F_OldPos(qp) \
+qp->opos
+
+#define F_ExtractOldTo(qp, buf, ch, maxsize) \
+do { \
+   unsigned int    c = 0; \
+   while (qp->statement[qp->opos] != '\0' && qp->statement[qp->opos] != ch) \
+   { \
+       buf[c++] = qp->statement[qp->opos++]; \
+       if (c >= maxsize - 1) \
+           break; \
+   } \
+   if (qp->statement[qp->opos] == '\0') \
+       return SQL_ERROR; \
+   buf[c] = '\0'; \
+} while (0)
+
+#define F_NewChar(qb) \
+qb->query_statement[qb->npos]
+
+#define F_NewPtr(qb) \
+(qb->query_statement + qb->npos)
+
+#define F_NewNext(qb) \
+(++qb->npos)
+
+#define F_NewPos(qb) \
+(qb->npos)
+
+
+static int
+convert_escape(QueryParse *qp, QueryBuild *qb);
+static int
+inner_process_tokens(QueryParse *qp, QueryBuild *qb);
+static int
+ResolveOneParam(QueryBuild *qb);
+static int
+processParameters(QueryParse *qp, QueryBuild *qb,
+UInt4 *output_count, Int4 param_pos[][2]);
+
+static int
+enlarge_query_statement(QueryBuild *qb, unsigned int newsize)
+{
+   unsigned int newalsize = INIT_MIN_ALLOC;
+   CSTR func = "enlarge_statement";
+
+   if (qb->str_size_limit > 0 && qb->str_size_limit < (int) newsize)
+   {
+       free(qb->query_statement);
+       qb->query_statement = NULL;
+       qb->str_alsize = 0;
+       if (qb->stmt)
+       {
+           
+           SC_set_error(qb->stmt, STMT_EXEC_ERROR, "Query buffer overflow in copy_statement_with_parameters");
+           SC_log_error(func, "", qb->stmt);
+       }
+       else
+       {
+           qb->errormsg = "Query buffer overflow in copy_statement_with_parameters";
+           qb->errornumber = STMT_EXEC_ERROR;
+       }
+       return -1;
+   }
+   while (newalsize <= newsize)
+       newalsize *= 2;
+   if (!(qb->query_statement = realloc(qb->query_statement, newalsize)))
+   {
+       qb->str_alsize = 0;
+       if (qb->stmt)
+       {
+           SC_set_error(qb->stmt, STMT_EXEC_ERROR, "Query buffer allocate error in copy_statement_with_parameters");
+       }
+       else
+       {
+           qb->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
+           qb->errornumber = STMT_EXEC_ERROR;
+       }
+       return 0;
+   }
+   qb->str_alsize = newalsize;
+   return newalsize;
+}
+
+/*----------
+ * Enlarge stmt_with_params if necessary.
+ *----------
+ */
+#define ENLARGE_NEWSTATEMENT(qb, newpos) \
+   if (newpos >= qb->str_alsize) \
+   { \
+       if (enlarge_query_statement(qb, newpos) <= 0) \
+           return SQL_ERROR; \
+   }
+
+/*----------
+ * Terminate the stmt_with_params string with NULL.
+ *----------
+ */
+#define CVT_TERMINATE(qb) \
+do { \
+   qb->query_statement[qb->npos] = '\0'; \
+} while (0)
+
+/*----------
+ * Append a data.
+ *----------
+ */
+#define CVT_APPEND_DATA(qb, s, len) \
+do { \
+   unsigned int    newpos = qb->npos + len; \
+   ENLARGE_NEWSTATEMENT(qb, newpos) \
+   memcpy(&qb->query_statement[qb->npos], s, len); \
+   qb->npos = newpos; \
+   qb->query_statement[newpos] = '\0'; \
+} while (0)
+
+/*----------
+ * Append a string.
+ *----------
+ */
+#define CVT_APPEND_STR(qb, s) \
+do { \
+   unsigned int len = strlen(s); \
+   CVT_APPEND_DATA(qb, s, len); \
+} while (0)
+
+/*----------
+ * Append a char.
+ *----------
+ */
+#define CVT_APPEND_CHAR(qb, c) \
+do { \
+   ENLARGE_NEWSTATEMENT(qb, qb->npos + 1); \
+   qb->query_statement[qb->npos++] = c; \
+} while (0)
+
+/*----------
+ * Append a binary data.
+ * Newly reqeuired size may be overestimated currently.
+ *----------
+ */
+#define CVT_APPEND_BINARY(qb, buf, used) \
+do { \
+   unsigned int    newlimit = qb->npos + 5 * used; \
+   ENLARGE_NEWSTATEMENT(qb, newlimit); \
+   qb->npos += convert_to_pgbinary(buf, &qb->query_statement[qb->npos], used); \
+} while (0)
+
+/*----------
+ *
+ *----------
+ */
+#define CVT_SPECIAL_CHARS(qb, buf, used) \
+do { \
+   int cnvlen = convert_special_chars(buf, NULL, used, qb->lf_conv, qb->ccsc); \
+   unsigned int    newlimit = qb->npos + cnvlen; \
+\
+   ENLARGE_NEWSTATEMENT(qb, newlimit); \
+   convert_special_chars(buf, &qb->query_statement[qb->npos], used, qb->lf_conv, qb->ccsc); \
+   qb->npos += cnvlen; \
+} while (0)
+
+/*----------
+ * Check if the statement is
+ * SELECT ... INTO table FROM .....
+ * This isn't really a strict check but ...
+ *----------
+ */
+static BOOL
+into_table_from(const char *stmt)
+{
+   if (strnicmp(stmt, "into", 4))
+       return FALSE;
+   stmt += 4;
+   if (!isspace((UCHAR) *stmt))
+       return FALSE;
+   while (isspace((UCHAR) *(++stmt)));
+   switch (*stmt)
+   {
+       case '\0':
+       case ',':
+       case '\'':
+           return FALSE;
+       case '\"':              /* double quoted table name ? */
+           do
+           {
+               do
+                   while (*(++stmt) != '\"' && *stmt);
+               while (*stmt && *(++stmt) == '\"');
+               while (*stmt && !isspace((UCHAR) *stmt) && *stmt != '\"')
+                   stmt++;
+           }
+           while (*stmt == '\"');
+           break;
+       default:
+           while (!isspace((UCHAR) *(++stmt)));
+           break;
+   }
+   if (!*stmt)
+       return FALSE;
+   while (isspace((UCHAR) *(++stmt)));
+   if (strnicmp(stmt, "from", 4))
+       return FALSE;
+   return isspace((UCHAR) stmt[4]);
+}
+
+/*----------
+ * Check if the statement is
+ * SELECT ... FOR UPDATE .....
+ * This isn't really a strict check but ...
+ *----------
+ */
+static BOOL
+table_for_update(const char *stmt, int *endpos)
+{
+   const char *wstmt = stmt;
+
+   while (isspace((UCHAR) *(++wstmt)));
+   if (!*wstmt)
+       return FALSE;
+   if (strnicmp(wstmt, "update", 6))
+       return FALSE;
+   wstmt += 6;
+   *endpos = wstmt - stmt;
+   return !wstmt[0] || isspace((UCHAR) wstmt[0]);
+}
+
+/*----------
+ * Check if the statement is
+ * INSERT INTO ... () VALUES ()
+ * This isn't really a strict check but ...
+ *----------
+ */
+static BOOL
+insert_without_target(const char *stmt, int *endpos)
+{
+   const char *wstmt = stmt;
+
+   while (isspace((UCHAR) *(++wstmt)));
+   if (!*wstmt)
+       return FALSE;
+   if (strnicmp(wstmt, "VALUES", 6))
+       return FALSE;
+   wstmt += 6;
+   if (!wstmt[0] || !isspace((UCHAR) wstmt[0]))
+       return FALSE;
+   while (isspace((UCHAR) *(++wstmt)));
+   if (*wstmt != '(' || *(++wstmt) != ')')
+       return FALSE;
+   wstmt++;
+   *endpos = wstmt - stmt;
+   return !wstmt[0] || isspace((UCHAR) wstmt[0])
+       || ';' == wstmt[0];
+}
+
+static int
+Prepare_and_convert(StatementClass *stmt, QueryParse *qp, QueryBuild *qb)
+{
+   CSTR func = "Prepare_and_convert";
+   char    *new_statement, *exe_statement = NULL;
+   int retval;
+
+   if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
+       return SQL_ERROR;
+   if (!stmt->prepared) /*  not yet prepared */
+   {
+       int i, elen;
+       SWORD   marker_count;
+       const IPDFields *ipdopts = qb->ipdopts;
+
+       new_statement = qb->query_statement;
+       qb->flags = FLGB_BUILDING_PREPARE_STATEMENT;
+       sprintf(new_statement, "PREPARE \"_PLAN%0x\"", stmt);
+       qb->npos = strlen(new_statement);
+       if (SQL_SUCCESS != PGAPI_NumParams(stmt, &marker_count))
+       {
+           QB_Destructor(qb);
+           return SQL_ERROR;
+       }
+       if (marker_count > 0)
+       {
+           CVT_APPEND_CHAR(qb, '(');
+           for (i = 0; i < marker_count; i++)
+           {
+               if (i > 0)
+                   CVT_APPEND_STR(qb, ", ");
+               CVT_APPEND_STR(qb, pgtype_to_name(stmt, ipdopts->parameters[i].PGType));
+           }
+           CVT_APPEND_CHAR(qb, ')');
+       }
+       CVT_APPEND_STR(qb, " as ");
+       for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
+       {
+           retval = inner_process_tokens(qp, qb);
+           if (SQL_ERROR == retval)
+           {
+               if (0 == SC_get_errornumber(stmt))
+               {
+                   SC_set_error(stmt, qb->errornumber, qb->errormsg);
+               }
+               SC_log_error(func, "", stmt);
+               QB_Destructor(qb);
+               return retval;
+           }
+       }
+       CVT_APPEND_CHAR(qb, ';');
+       /* build the execute statement */
+       exe_statement = malloc(30 + 2 * marker_count);
+       sprintf(exe_statement, "EXECUTE \"_PLAN%0x\"", stmt);
+       if (marker_count > 0)
+       {
+           elen = strlen(exe_statement);
+           exe_statement[elen++] = '(';
+           for (i = 0; i < marker_count; i++)
+           {
+               if (i > 0)
+                   exe_statement[elen++] = ',';
+               exe_statement[elen++]  = '?';
+           }
+           exe_statement[elen++] = ')';
+           exe_statement[elen] = '\0';
+       }
+       stmt->execute_statement = exe_statement;
+       QP_initialize(qp, stmt);
+   }
+   qb->flags = 0;
+   qb->param_number = -1;
+   for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
+   {
+       retval = inner_process_tokens(qp, qb);
+       if (SQL_ERROR == retval)
+       {
+           if (0 == SC_get_errornumber(stmt))
+           {
+               SC_set_error(stmt, qb->errornumber, qb->errormsg);
+           }
+           SC_log_error(func, "", stmt);
+           if (exe_statement)
+           {
+               free(exe_statement);
+               stmt->execute_statement = NULL;
+           }
+           QB_Destructor(qb);
+           return retval;
+       }
+   }
+   /* make sure new_statement is always null-terminated */
+   CVT_TERMINATE(qb);
+
+   if (exe_statement)
+       SC_set_prepare_before_exec(stmt);
+   stmt->stmt_with_params = qb->query_statement;
+   return SQL_SUCCESS;
+}
+
+#define        my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
+
+/*
+ * This function inserts parameters into an SQL statements.
+ * It will also modify a SELECT statement for use with declare/fetch cursors.
+ * This function does a dynamic memory allocation to get rid of query size limit!
+ */
+int
+copy_statement_with_parameters(StatementClass *stmt, BOOL buildPrepareStatement)
+{
+   CSTR        func = "copy_statement_with_parameters";
+   RETCODE     retval;
+   QueryParse  query_org, *qp;
+   QueryBuild  query_crt, *qb;
+
+   char       *new_statement;
+
+   BOOL    begin_first = FALSE, prepare_dummy_cursor = FALSE;
+   ConnectionClass *conn = SC_get_conn(stmt);
+   ConnInfo   *ci = &(conn->connInfo);
+   int     current_row;
+
+   if (!stmt->statement)
+   {
+       SC_log_error(func, "No statement string", stmt);
+       return SQL_ERROR;
+   }
+
+   current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
+   qp = &query_org;
+   QP_initialize(qp, stmt);
+
+#ifdef DRIVER_CURSOR_IMPLEMENT
+   if (stmt->statement_type != STMT_TYPE_SELECT)
+   {
+       stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
+       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+   }
+   else if (stmt->options.cursor_type == SQL_CURSOR_FORWARD_ONLY)
+       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+   else if (stmt->options.scroll_concurrency != SQL_CONCUR_READ_ONLY)
+   {
+       if (stmt->parse_status == STMT_PARSE_NONE)
+           parse_statement(stmt);
+       if (stmt->parse_status == STMT_PARSE_FATAL)
+       {
+           stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+           if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
+               stmt->options.cursor_type = SQL_CURSOR_STATIC;
+       }
+       else if (!stmt->updatable)
+       {
+           stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+           stmt->options.cursor_type = SQL_CURSOR_STATIC;
+       }
+       else
+       {
+           qp->from_pos = stmt->from_pos;
+           qp->where_pos = stmt->where_pos;
+       }
+   }
+#else
+   stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+   if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
+       stmt->options.cursor_type = SQL_CURSOR_STATIC;
+#endif   /* DRIVER_CURSOR_IMPLEMENT */
+
+   stmt->miscinfo = 0;
+   /* If the application hasn't set a cursor name, then generate one */
+   if (stmt->cursor_name[0] == '\0')
+       sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
+   if (stmt->stmt_with_params)
+   {
+       free(stmt->stmt_with_params);
+       stmt->stmt_with_params = NULL;
+   }
+
+   SC_no_fetchcursor(stmt);
+   SC_no_pre_executable(stmt);
+   if (stmt->statement_type == STMT_TYPE_SELECT)
+       SC_set_pre_executable(stmt);
+   qb = &query_crt;
+   if (stmt->prepared || (buildPrepareStatement && stmt->options.scroll_concurrency == SQL_CONCUR_READ_ONLY))
+   {
+       return Prepare_and_convert(stmt, qp, qb);
+   }
+
+   if (ci->disallow_premature)
+       prepare_dummy_cursor = stmt->pre_executing;
+   if (prepare_dummy_cursor)
+       qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
+   if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
+       return SQL_ERROR;
+   new_statement = qb->query_statement;
+
+   /* For selects, prepend a declare cursor to the statement */
+   if (stmt->statement_type == STMT_TYPE_SELECT)
+   {
+       if (prepare_dummy_cursor || ci->drivers.use_declarefetch)
+       {
+           if (prepare_dummy_cursor)
+           {
+               if (!CC_is_in_trans(conn) && PG_VERSION_GE(conn, 7.1))
+               {
+                   strcpy(new_statement, "BEGIN;");
+                   begin_first = TRUE;
+               }
+           }
+           else if (ci->drivers.use_declarefetch)
+               SC_set_fetchcursor(stmt);
+           sprintf(new_statement, "%sdeclare %s cursor for ",
+                   new_statement, stmt->cursor_name);
+           qb->npos = strlen(new_statement);
+           qp->flags |= FLGP_CURSOR_CHECK_OK;
+           qp->declare_pos = qb->npos;
+       }
+       else if (SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
+       {
+           qb->flags |= FLGB_CREATE_KEYSET;
+           if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type)
+               qb->flags |= FLGB_KEYSET_DRIVEN;
+       }
+   }
+
+   for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
+   {
+       retval = inner_process_tokens(qp, qb);
+       if (SQL_ERROR == retval)
+       {
+           if (0 == SC_get_errornumber(stmt))
+           {
+               SC_set_error(stmt, qb->errornumber, qb->errormsg);
+           }
+           SC_log_error(func, "", stmt);
+           QB_Destructor(qb);
+           return retval;
+       }
+   }
+   /* make sure new_statement is always null-terminated */
+   CVT_TERMINATE(qb);
+
+   new_statement = qb->query_statement;
+   stmt->statement_type = qp->statement_type;
+   stmt->inaccurate_result = (0 != (qb->flags & FLGB_INACCURATE_RESULT));
+   if (0 != (qp->flags & FLGP_SELECT_INTO))
+   {
+       SC_no_pre_executable(stmt);
+       SC_no_fetchcursor(stmt);
+       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+   }
+   if (0 != (qp->flags & FLGP_SELECT_FOR_UPDATE))
+   {
+       SC_no_fetchcursor(stmt);
+       stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+   }
+
+   if (conn->DriverToDataSource != NULL)
+   {
+       int         length = strlen(new_statement);
+
+       conn->DriverToDataSource(conn->translation_option,
+                                SQL_CHAR,
+                                new_statement, length,
+                                new_statement, length, NULL,
+                                NULL, 0, NULL);
+   }
+
+#ifdef DRIVER_CURSOR_IMPLEMENT
+   if (!stmt->load_statement && qp->from_pos >= 0)
+   {
+       UInt4   npos = qb->load_stmt_len;
+
+       if (0 == npos)
+       {
+           npos = qb->npos;
+           for (; npos > 0; npos--)
+           {
+               if (isspace(new_statement[npos - 1]))
+                   continue;
+               if (';' != new_statement[npos - 1])
+                   break;
+           }
+           if (0 != (qb->flags & FLGB_KEYSET_DRIVEN))
+           {
+               qb->npos = npos;
+               /* ----------
+                * 1st query is for field information
+                * 2nd query is keyset gathering
+                */
+               CVT_APPEND_STR(qb, " where ctid = '(0,0)';select ctid, oid from ");
+               CVT_APPEND_DATA(qb, qp->statement + qp->from_pos + 5, npos - qp->from_pos - 5);
+           }
+       }
+       stmt->load_statement = malloc(npos + 1);
+       memcpy(stmt->load_statement, qb->query_statement, npos);
+       stmt->load_statement[npos] = '\0';
+   }
+#endif   /* DRIVER_CURSOR_IMPLEMENT */
+   if (prepare_dummy_cursor && SC_is_pre_executable(stmt))
+   {
+       char        fetchstr[128];
+
+       sprintf(fetchstr, ";fetch backward in %s;close %s;",
+               stmt->cursor_name, stmt->cursor_name);
+       if (begin_first && CC_is_in_autocommit(conn))
+           strcat(fetchstr, "COMMIT;");
+       CVT_APPEND_STR(qb, fetchstr);
+       stmt->inaccurate_result = TRUE;
+   }
+
+   stmt->stmt_with_params = qb->query_statement;
+   return SQL_SUCCESS;
+}
+
+static int
+inner_process_tokens(QueryParse *qp, QueryBuild *qb)
+{
+   CSTR func = "inner_process_tokens";
+   BOOL    lf_conv = qb->lf_conv;
+
+   RETCODE retval;
+   char       oldchar;
+
+   if (qp->from_pos == (Int4) qp->opos)
+   {
+       CVT_APPEND_STR(qb, ", CTID, OID ");
+   }
+   else if (qp->where_pos == (Int4) qp->opos)
+   {
+       qb->load_stmt_len = qb->npos;
+       if (0 != (qb->flags & FLGB_KEYSET_DRIVEN))
+       {
+           CVT_APPEND_STR(qb, "where ctid = '(0,0)';select CTID, OID from ");
+           CVT_APPEND_DATA(qb, qp->statement + qp->from_pos + 5, qp->where_pos - qp->from_pos - 5);
+       }
+   }
+   oldchar = encoded_byte_check(&qp->encstr, qp->opos);
+   if (ENCODE_STATUS(qp->encstr) != 0)
+   {
+       CVT_APPEND_CHAR(qb, oldchar);
+       return SQL_SUCCESS;
+   }
+
+   /*
+    * From here we are guaranteed to handle a 1-byte character.
+    */
+
+   if (qp->in_escape)          /* escape check */
+   {
+       qp->in_escape = FALSE;
+       CVT_APPEND_CHAR(qb, oldchar);
+       return SQL_SUCCESS;
+   }
+   else if (qp->in_quote || qp->in_dquote) /* quote/double quote check */
+   {
+       if (oldchar == '\\')
+           qp->in_escape = TRUE;
+       else if (oldchar == '\'' && qp->in_quote)
+           qp->in_quote = FALSE;
+       else if (oldchar == '\"' && qp->in_dquote)
+           qp->in_dquote = FALSE;
+       CVT_APPEND_CHAR(qb, oldchar);
+       return SQL_SUCCESS;
+   }
+
+   /*
+    * From here we are guranteed to be in neither an escape, a quote
+    * nor a double quote.
+    */
+   /* Squeeze carriage-return/linefeed pairs to linefeed only */
+   else if (lf_conv && oldchar == '\r' && qp->opos + 1 < qp->stmt_len &&
+           qp->statement[qp->opos + 1] == '\n')
+       return SQL_SUCCESS;
+
+   /*
+    * Handle literals (date, time, timestamp) and ODBC scalar
+    * functions
+    */
+   else if (oldchar == '{')
+   {
+       if (SQL_ERROR == convert_escape(qp, qb))
+       {
+           if (0 == qb->errornumber)
+           {
+               qb->errornumber = STMT_EXEC_ERROR;
+               qb->errormsg = "ODBC escape convert error";
+           }
+           mylog("%s convert_escape error\n", func);
+           return SQL_ERROR;
+       }
+       if (isalnum(F_OldPtr(qp)[1]))
+           CVT_APPEND_CHAR(qb, ' ');
+       return SQL_SUCCESS;
+   }
+   /* End of an escape sequence */
+   else if (oldchar == '}')
+   {
+       if (qp->statement_type == STMT_TYPE_PROCCALL)
+       {
+           if (qp->proc_no_param)
+               CVT_APPEND_STR(qb, "()");
+       }
+       else if (!isspace(F_OldPtr(qp)[1]))
+           CVT_APPEND_CHAR(qb, ' ');
+       return SQL_SUCCESS;
+   }
+
+   /*
+    * Can you have parameter markers inside of quotes?  I dont think
+    * so. All the queries I've seen expect the driver to put quotes
+    * if needed.
+    */
+   else if (oldchar != '?')
+   {
+       if (oldchar == '\'')
+           qp->in_quote = TRUE;
+       else if (oldchar == '\\')
+           qp->in_escape = TRUE;
+       else if (oldchar == '\"')
+           qp->in_dquote = TRUE;
+       else
+       {
+           if (isspace((UCHAR) oldchar))
+           {
+               if (!qp->prev_token_end)
+               {
+                   qp->prev_token_end = TRUE;
+                   qp->token_save[qp->token_len] = '\0';
+                   if (qp->token_len == 4)
+                   {
+                       if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&
+                           into_table_from(&qp->statement[qp->opos - qp->token_len]))
+                       {
+                           qp->flags |= FLGP_SELECT_INTO;
+                           qp->flags &= ~FLGP_CURSOR_CHECK_OK;
+                           qb->flags &= ~FLGB_KEYSET_DRIVEN;
+                           qp->statement_type = STMT_TYPE_CREATE;
+                           memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);
+                           qb->npos -= qp->declare_pos;
+                       }
+                   }
+                   else if (qp->token_len == 3)
+                   {
+                       int         endpos;
+
+                       if (0 != (qp->flags & FLGP_CURSOR_CHECK_OK) &&
+                           strnicmp(qp->token_save, "for", 3) == 0 &&
+                           table_for_update(&qp->statement[qp->opos], &endpos))
+                       {
+                           qp->flags |= FLGP_SELECT_FOR_UPDATE;
+                           qp->flags &= ~FLGP_CURSOR_CHECK_OK;
+                           if (qp->flags & FLGP_PREPARE_DUMMY_CURSOR)
+                           {
+                               qb->npos -= 4;
+                               qp->opos += endpos;
+                           }
+                           else
+                           {
+                               memmove(qb->query_statement, qb->query_statement + qp->declare_pos, qb->npos - qp->declare_pos);
+                               qb->npos -= qp->declare_pos;
+                           }
+                       }
+                   }
+                   else if (qp->token_len == 2)
+                   {
+                       int endpos;
+
+                       if (STMT_TYPE_INSERT == qp->statement_type &&
+                           strnicmp(qp->token_save, "()", 2) == 0 &&
+                           insert_without_target(&qp->statement[qp->opos], &endpos))
+                       {
+                           qb->npos -= 2;
+                           CVT_APPEND_STR(qb, "DEFAULT VALUES");
+                           qp->opos += endpos;
+                           return SQL_SUCCESS;
+                       }
+                   }
+               }
+           }
+           else if (qp->prev_token_end)
+           {
+               qp->prev_token_end = FALSE;
+               qp->token_save[0] = oldchar;
+               qp->token_len = 1;
+           }
+           else if (qp->token_len + 1 < sizeof(qp->token_save))
+               qp->token_save[qp->token_len++] = oldchar;
+       }
+       CVT_APPEND_CHAR(qb, oldchar);
+       return SQL_SUCCESS;
+   }
+
+   /*
+    * Its a '?' parameter alright
+    */
+   if (retval = ResolveOneParam(qb), retval < 0)
+       return retval;
+
+   return SQL_SUCCESS;
+}
+
+static BOOL
+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;
+   UCHAR       calv[40];
+   const UCHAR *val = (const UCHAR *) ns->val;
+   BOOL    next_figure;
+
+   if (0 == ns->precision)
+   {
+       strcpy(chrform, "0");
+       return TRUE;
+   }
+   else if (ns->precision < prec[sizeof(Int4)])
+   {
+       for (i = 0, ival = 0; i < sizeof(Int4) && prec[i] <= ns->precision; i++)
+       {
+           ival += (val[i] << (8 * i)); /* ns->val is little endian */
+       }
+       if (0 == ns->scale)
+       {
+           if (0 == ns->sign)
+               ival *= -1;
+           sprintf(chrform, "%d", ival);
+       }
+       else if (ns->scale > 0)
+       {
+           Int4    i, div, o1val, o2val;
+
+           for (i = 0, div = 1; i < ns->scale; i++)
+               div *= 10;
+           o1val = ival / div;
+           o2val = ival % div;
+           if (0 == ns->sign)
+               o1val *= -1;
+           sprintf(chrform, "%d.%0.*d", o1val, ns->scale, o2val);
+       }
+       return TRUE;
+   }
+
+   for (i = 0; i < SQL_MAX_NUMERIC_LEN && prec[i] <= ns->precision; i++)
+       ;
+   vlen = i;
+   len = 0;
+   memset(calv, 0, sizeof(calv));
+   for (i = vlen - 1; i >= 0; i--)
+   {
+       for (j = len - 1; j >= 0; j--)
+       {
+           if (!calv[j])
+               continue;
+           ival = (((Int4)calv[j]) << 8);
+           calv[j] = (ival % 10);
+           ival /= 10;
+           calv[j + 1] += (ival % 10);
+           ival /= 10;
+           calv[j + 2] += (ival % 10);
+           ival /= 10;
+           calv[j + 3] += ival;
+           for (k = j;; k++)
+           {
+               next_figure = FALSE;
+               if (calv[k] > 0)
+               {
+                   if (k >= len)
+                       len = k + 1;
+                   while (calv[k] > 9)
+                   {
+                       calv[k + 1]++;
+                       calv[k] -= 10;
+                       next_figure = TRUE;
+                   }
+               }
+               if (k >= j + 3 && !next_figure)
+                   break;
+           }
+       }
+       ival = val[i];
+       if (!ival)
+           continue;
+       calv[0] += (ival % 10);
+       ival /= 10;
+       calv[1] += (ival % 10);
+       ival /= 10;
+       calv[2] += ival;
+       for (j = 0;; j++)
+       {
+           next_figure = FALSE;
+           if (calv[j] > 0)
+           {
+               if (j >= len)
+                   len = j + 1;
+               while (calv[j] > 9)
+               {
+                   calv[j + 1]++;
+                   calv[j] -= 10;
+                   next_figure = TRUE;
+               }
+           }
+           if (j >= 2 && !next_figure)
+               break;
+       }
+   }
+   newlen = 0;
+   if (0 == ns->sign)
+       chrform[newlen++] = '-';
+   if (i = len - 1, i < ns->scale)
+       i = ns->scale;
+   for (; i >= ns->scale; i--)
+       chrform[newlen++] = calv[i] + '0';
+   if (ns->scale > 0)
+   {
+       chrform[newlen++] = '.';
+       for (; i >= 0; i--)
+           chrform[newlen++] = calv[i] + '0';
+   }
+   if (0 == len)
+       chrform[newlen++] = '0';
+   chrform[newlen] = '\0';
+   return TRUE;
+}
+
+/*
+ *
+ */
+static int
+ResolveOneParam(QueryBuild *qb)
+{
+   CSTR func = "ResolveOneParam";
+
+   ConnectionClass *conn = qb->conn;
+   ConnInfo   *ci = &(conn->connInfo);
+   const APDFields *apdopts = qb->apdopts;
+   const IPDFields *ipdopts = qb->ipdopts;
+   PutDataInfo *pdata = qb->pdata;
+
+   int     param_number;
+   char        param_string[128], tmp[256],
+           cbuf[PG_NUMERIC_MAX_PRECISION * 2]; /* seems big enough to handle the data in this function */
+   Int4        param_pgtype;
+   Int2        param_ctype, param_sqltype;
+   SIMPLE_TIME st;
+   time_t      t;
+   struct tm   *tim;
+#ifdef HAVE_LOCALTIME_R
+   struct tm   tm;
+#endif /* HAVE_LOCALTIME_R */
+   SDWORD      used;
+   char        *buffer, *buf, *allocbuf;
+   Oid     lobj_oid;
+   int     lobj_fd, retval;
+   UInt4   offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
+   UInt4   current_row = qb->current_row;
+   BOOL    handling_large_object = FALSE;
+
+   /*
+    * Its a '?' parameter alright
+    */
+   param_number = ++qb->param_number;
+
+   if (param_number >= apdopts->allocated)
+   {
+       if (0 != (qb->flags & FLGB_PRE_EXECUTING))
+       {
+           CVT_APPEND_STR(qb, "NULL");
+           qb->flags |= FLGB_INACCURATE_RESULT;
+           return SQL_SUCCESS;
+       }
+       else
+       {
+           qb->errormsg = "The # of binded parameters < the # of parameter markers";
+           qb->errornumber = STMT_COUNT_FIELD_INCORRECT;
+           CVT_TERMINATE(qb);  /* just in case */
+           return SQL_ERROR;
+       }
+   }
+   if (SQL_PARAM_OUTPUT == ipdopts->parameters[param_number].paramType)
+   {
+       qb->errormsg = "Output parameter isn't available";
+       qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+       CVT_TERMINATE(qb);  /* just in case */
+       return SQL_ERROR;
+   }
+
+   if (0 != (qb->flags & FLGB_BUILDING_PREPARE_STATEMENT))
+   {
+       char    pnum[16];
+
+       sprintf(pnum, "$%d", param_number + 1);
+       CVT_APPEND_STR(qb, pnum); 
+       return SQL_SUCCESS;
+   } 
+   /* Assign correct buffers based on data at exec param or not */
+   if (apdopts->parameters[param_number].data_at_exec)
+   {
+       if (pdata->allocated != apdopts->allocated)
+           extend_putdata_info(pdata, apdopts->allocated, TRUE);
+       used = pdata->pdata[param_number].EXEC_used ? *pdata->pdata[param_number].EXEC_used : SQL_NTS;
+       buffer = pdata->pdata[param_number].EXEC_buffer;
+       if (pdata->pdata[param_number].lobj_oid)
+           handling_large_object = TRUE;
+   }
+   else
+   {
+       UInt4   bind_size = apdopts->param_bind_type;
+       UInt4   ctypelen;
+
+       buffer = apdopts->parameters[param_number].buffer + offset;
+       if (current_row > 0)
+       {
+           if (bind_size > 0)
+               buffer += (bind_size * current_row);
+           else if (ctypelen = ctype_length(apdopts->parameters[param_number].CType), ctypelen > 0)
+               buffer += current_row * ctypelen;
+           else 
+               buffer += current_row * apdopts->parameters[param_number].buflen;
+       }
+       if (apdopts->parameters[param_number].used)
+       {
+           UInt4   p_offset = offset;
+           if (bind_size > 0)
+               p_offset = offset + bind_size * current_row;
+           else
+               p_offset = offset + sizeof(SDWORD) * current_row;
+           used = *(SDWORD *)((char *)apdopts->parameters[param_number].used + p_offset);
+       }
+       else
+           used = SQL_NTS;
+   }   
+
+   /* Handle NULL parameter data */
+   if (used == SQL_NULL_DATA)
+   {
+       CVT_APPEND_STR(qb, "NULL");
+       return SQL_SUCCESS;
+   }
+   /* Handle DEFAULT_PARAM parameter data */
+   if (used == SQL_DEFAULT_PARAM)
+   {
+       return SQL_SUCCESS;
+   }
+
+   /*
+    * If no buffer, and it's not null, then what the hell is it? Just
+    * leave it alone then.
+    */
+   if (!buffer)
+   {
+       if (0 != (qb->flags & FLGB_PRE_EXECUTING))
+       {
+           CVT_APPEND_STR(qb, "NULL");
+           qb->flags |= FLGB_INACCURATE_RESULT;
+           return SQL_SUCCESS;
+       }
+       else if (!handling_large_object)
+       {
+           CVT_APPEND_CHAR(qb, '?');
+           return SQL_SUCCESS;
+       }
+   }
+
+   param_ctype = apdopts->parameters[param_number].CType;
+   param_sqltype = ipdopts->parameters[param_number].SQLType;
+   param_pgtype = ipdopts->parameters[param_number].PGType;
+
+   mylog("%s: from(fcType)=%d, to(fSqlType)=%d\n", func,
+               param_ctype, param_sqltype);
+
+   /* replace DEFAULT with something we can use */
+   if (param_ctype == SQL_C_DEFAULT)
+       param_ctype = sqltype_to_default_ctype(conn, param_sqltype);
+
+   allocbuf = buf = NULL;
+   param_string[0] = '\0';
+   cbuf[0] = '\0';
+   memset(&st, 0, sizeof(st));
+   t = SC_get_time(qb->stmt);
+#ifdef HAVE_LOCALTIME_R
+   tim = localtime_r(&t, &tm);
+#else
+   tim = localtime(&t);
+#endif /* HAVE_LOCALTIME_R */
+   st.m = tim->tm_mon + 1;
+   st.d = tim->tm_mday;
+   st.y = tim->tm_year + 1900;
+
+   /* Convert input C type to a neutral format */
+   switch (param_ctype)
+   {
+       case SQL_C_BINARY:
+           buf = buffer;
+           break;
+       case SQL_C_CHAR:
+#ifdef WIN_UNICODE_SUPPORT
+           switch (param_sqltype)
+           {
+               case SQL_WCHAR:
+               case SQL_WVARCHAR:
+               case SQL_WLONGVARCHAR:
+                   if (SQL_NTS == used)
+                       used = strlen(buffer);
+                   allocbuf = malloc(WCLEN * (used + 1));
+                   used = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buffer,
+                       used, (LPWSTR) allocbuf, used + 1);
+                   buf = ucs2_to_utf8((SQLWCHAR *) allocbuf, used, (UInt4 *) &used, FALSE);
+                   free(allocbuf);
+                   allocbuf = buf;
+                   break;
+               default:
+                   buf = buffer;
+           }
+#else
+           buf = buffer;
+#endif /* WIN_UNICODE_SUPPORT */
+           break;
+
+#ifdef UNICODE_SUPPORT
+       case SQL_C_WCHAR:
+            if (SQL_NTS == used)
+                used = WCLEN * wcslen((SQLWCHAR *) buffer);
+           buf = allocbuf = ucs2_to_utf8((SQLWCHAR *) buffer, used / WCLEN, (UInt4 *) &used, FALSE);
+           used *= WCLEN;
+           break;
+#endif /* UNICODE_SUPPORT */
+
+       case SQL_C_DOUBLE:
+           sprintf(param_string, "%.15g",
+                       *((SDOUBLE *) buffer));
+           break;
+
+       case SQL_C_FLOAT:
+           sprintf(param_string, "%.6g",
+                   *((SFLOAT *) buffer));
+           break;
+
+       case SQL_C_SLONG:
+       case SQL_C_LONG:
+           sprintf(param_string, "%d",
+                   *((SDWORD *) buffer));
+           break;
+
+#ifdef ODBCINT64
+       case SQL_C_SBIGINT:
+           sprintf(param_string, FORMATI64,
+                   *((SQLBIGINT *) buffer));
+           break;
+
+       case SQL_C_UBIGINT:
+           sprintf(param_string, FORMATI64U,
+                   *((SQLUBIGINT *) buffer));
+           break;
+
+#endif /* ODBCINT64 */
+       case SQL_C_SSHORT:
+       case SQL_C_SHORT:
+           sprintf(param_string, "%d",
+                   *((SWORD *) buffer));
+           break;
+
+       case SQL_C_STINYINT:
+       case SQL_C_TINYINT:
+           sprintf(param_string, "%d",
+                   *((SCHAR *) buffer));
+           break;
+
+       case SQL_C_ULONG:
+           sprintf(param_string, "%u",
+                   *((UDWORD *) buffer));
+           break;
+
+       case SQL_C_USHORT:
+           sprintf(param_string, "%u",
+                   *((UWORD *) buffer));
+           break;
+
+       case SQL_C_UTINYINT:
+           sprintf(param_string, "%u",
+                   *((UCHAR *) buffer));
+           break;
+
+       case SQL_C_BIT:
+           {
+               int         i = *((UCHAR *) buffer);
+
+                   sprintf(param_string, "%d", i ? 1 : 0);
+                   break;
+           }
+
+       case SQL_C_DATE:
+       case SQL_C_TYPE_DATE:       /* 91 */
+           {
+               DATE_STRUCT *ds = (DATE_STRUCT *) buffer;
+
+               st.m = ds->month;
+               st.d = ds->day;
+               st.y = ds->year;
+
+               break;
+           }
+
+       case SQL_C_TIME:
+       case SQL_C_TYPE_TIME:       /* 92 */
+           {
+               TIME_STRUCT *ts = (TIME_STRUCT *) buffer;
+
+               st.hh = ts->hour;
+               st.mm = ts->minute;
+               st.ss = ts->second;
+
+               break;
+           }
+
+       case SQL_C_TIMESTAMP:
+       case SQL_C_TYPE_TIMESTAMP:  /* 93 */
+           {
+               TIMESTAMP_STRUCT *tss = (TIMESTAMP_STRUCT *) buffer;
+
+               st.m = tss->month;
+               st.d = tss->day;
+               st.y = tss->year;
+               st.hh = tss->hour;
+               st.mm = tss->minute;
+               st.ss = tss->second;
+               st.fr = tss->fraction;
+
+               mylog("m=%d,d=%d,y=%d,hh=%d,mm=%d,ss=%d\n", st.m, st.d, st.y, st.hh, st.mm, st.ss);
+
+               break;
+
+           }
+       case SQL_C_NUMERIC:
+           if (ResolveNumericParam((SQL_NUMERIC_STRUCT *) buffer, param_string))
+               break;
+       default:
+           /* error */
+           qb->errormsg = "Unrecognized C_parameter type in copy_statement_with_parameters";
+           qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+           CVT_TERMINATE(qb);  /* just in case */
+           return SQL_ERROR;
+   }
+
+   /*
+    * Now that the input data is in a neutral format, convert it to
+    * the desired output format (sqltype)
+    */
+
+   switch (param_sqltype)
+   {
+       case SQL_CHAR:
+       case SQL_VARCHAR:
+       case SQL_LONGVARCHAR:
+#ifdef UNICODE_SUPPORT
+       case SQL_WCHAR:
+       case SQL_WVARCHAR:
+       case SQL_WLONGVARCHAR:
+#endif /* UNICODE_SUPPORT */
+
+           CVT_APPEND_CHAR(qb, '\'');  /* Open Quote */
+
+           /* it was a SQL_C_CHAR */
+           if (buf)
+               CVT_SPECIAL_CHARS(qb, buf, used);
+
+           /* it was a numeric type */
+           else if (param_string[0] != '\0')
+               CVT_APPEND_STR(qb, param_string);
+
+           /* it was date,time,timestamp -- use m,d,y,hh,mm,ss */
+           else
+           {
+               sprintf(tmp, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
+                       st.y, st.m, st.d, st.hh, st.mm, st.ss);
+
+               CVT_APPEND_STR(qb, tmp);
+           }
+
+           CVT_APPEND_CHAR(qb, '\'');  /* Close Quote */
+
+           break;
+
+       case SQL_DATE:
+       case SQL_TYPE_DATE: /* 91 */
+           if (buf)
+           {               /* copy char data to time */
+               my_strcpy(cbuf, sizeof(cbuf), buf, used);
+               parse_datetime(cbuf, &st);
+           }
+
+           sprintf(tmp, "'%.4d-%.2d-%.2d'::date", st.y, st.m, st.d);
+
+           CVT_APPEND_STR(qb, tmp);
+           break;
+
+       case SQL_TIME:
+       case SQL_TYPE_TIME: /* 92 */
+           if (buf)
+           {               /* copy char data to time */
+               my_strcpy(cbuf, sizeof(cbuf), buf, used);
+               parse_datetime(cbuf, &st);
+           }
+
+           sprintf(tmp, "'%.2d:%.2d:%.2d'::time", st.hh, st.mm, st.ss);
+
+           CVT_APPEND_STR(qb, tmp);
+           break;
+
+       case SQL_TIMESTAMP:
+       case SQL_TYPE_TIMESTAMP:    /* 93 */
+
+           if (buf)
+           {
+               my_strcpy(cbuf, sizeof(cbuf), buf, used);
+               parse_datetime(cbuf, &st);
+           }
+
+           /*
+            * sprintf(tmp, "'%.4d-%.2d-%.2d %.2d:%.2d:%.2d'", st.y,
+            * st.m, st.d, st.hh, st.mm, st.ss);
+            */
+           tmp[0] = '\'';
+           /* Time zone stuff is unreliable */
+           stime2timestamp(&st, tmp + 1, USE_ZONE, PG_VERSION_GE(conn, 7.2));
+           strcat(tmp, "'::timestamp");
+
+           CVT_APPEND_STR(qb, tmp);
+
+           break;
+
+       case SQL_BINARY:
+       case SQL_VARBINARY:
+       case SQL_LONGVARBINARY:
+           switch (param_ctype)
+           {
+               case SQL_C_BINARY:
+                   break;
+               case SQL_C_CHAR:
+                   switch (used)
+                   {
+                       case SQL_NTS:
+                           used = strlen(buf);
+                           break;
+                   }
+                   allocbuf = malloc(used / 2 + 1);
+                   if (allocbuf)
+                   {
+                       pg_hex2bin(buf, allocbuf, used);
+                       buf = allocbuf;
+                       used /= 2;
+                   }
+                   break;
+               default:
+                   qb->errormsg = "Could not convert the ctype to binary type";
+                   qb->errornumber = STMT_EXEC_ERROR;
+                   return SQL_ERROR;
+           }
+           if (param_pgtype == PG_TYPE_BYTEA)
+           {
+               /* non-ascii characters should be
+                * converted to octal
+                */
+               CVT_APPEND_CHAR(qb, '\'');  /* Open Quote */
+
+               mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
+
+               CVT_APPEND_BINARY(qb, buf, used);
+
+               CVT_APPEND_CHAR(qb, '\'');  /* Close Quote */
+
+               break;
+           }
+           if (param_pgtype != conn->lobj_type)
+           {
+               qb->errormsg = "Could not convert binary other than LO type";
+               qb->errornumber = STMT_EXEC_ERROR;
+               return SQL_ERROR;
+           }
+
+           if (apdopts->parameters[param_number].data_at_exec)
+               lobj_oid = pdata->pdata[param_number].lobj_oid;
+           else
+           {
+               /* begin transaction if needed */
+               if (!CC_is_in_trans(conn))
+               {
+                   if (!CC_begin(conn))
+                   {
+                       qb->errormsg = "Could not begin (in-line) a transaction";
+                       qb->errornumber = STMT_EXEC_ERROR;
+                       return SQL_ERROR;
+                   }
+               }
+
+               /* store the oid */
+#ifdef USE_LIBPQ
+               lobj_oid = lo_creat(conn->pgconn, INV_READ | INV_WRITE);
+#else
+               lobj_oid = lo_creat(conn, INV_READ | INV_WRITE);
+#endif /* USE_LIBPQ */
+
+               if (lobj_oid == 0)
+               {
+                   qb->errornumber = STMT_EXEC_ERROR;
+                   qb->errormsg = "Couldnt create (in-line) large object.";
+                   return SQL_ERROR;
+               }
+
+               /* store the fd */
+#ifdef USE_LIBPQ
+               lobj_fd = lo_open(conn->pgconn, lobj_oid, INV_WRITE);
+#else
+               lobj_fd = lo_open(conn, lobj_oid, INV_WRITE);
+#endif /* USE_LIBPQ */
+
+               if (lobj_fd < 0)
+               {
+                   qb->errornumber = STMT_EXEC_ERROR;
+                   qb->errormsg = "Couldnt open (in-line) large object for writing.";
+                   return SQL_ERROR;
+               }
+#ifdef USE_LIBPQ
+           retval = lo_write(conn->pgconn, lobj_fd, buffer, used);
+           lo_close(conn->pgconn, lobj_fd);
+
+#else
+               retval = lo_write(conn, lobj_fd, buffer, used);
+
+               lo_close(conn, lobj_fd);
+#endif /* USE_LIBPQ */
+
+               /* commit transaction if needed */
+               if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
+               {
+                   if (!CC_commit(conn))
+                   {
+                       qb->errormsg = "Could not commit (in-line) a transaction";
+                       qb->errornumber = STMT_EXEC_ERROR;
+                       return SQL_ERROR;
+                   }
+               }
+           }
+
+           /*
+            * the oid of the large object -- just put that in for the
+            * parameter marker -- the data has already been sent to
+            * the large object
+            */
+           sprintf(param_string, "'%d'::lo", lobj_oid);
+           CVT_APPEND_STR(qb, param_string);
+
+           break;
+
+           /*
+            * because of no conversion operator for bool and int4,
+            * SQL_BIT
+            */
+           /* must be quoted (0 or 1 is ok to use inside the quotes) */
+
+       case SQL_REAL:
+           if (buf)
+               my_strcpy(param_string, sizeof(param_string), buf, used);
+           sprintf(tmp, "'%s'::float4", param_string);
+           CVT_APPEND_STR(qb, tmp);
+           break;
+       case SQL_FLOAT:
+       case SQL_DOUBLE:
+           if (buf)
+               my_strcpy(param_string, sizeof(param_string), buf, used);
+           sprintf(tmp, "'%s'::float8", param_string);
+           CVT_APPEND_STR(qb, tmp);
+           break;
+       case SQL_NUMERIC:
+           if (buf)
+           {
+               cbuf[0] = '\'';
+               my_strcpy(cbuf + 1, sizeof(cbuf) - 3, buf, used);   /* 3 = 1('\'') +
+                                                                   * strlen("'")
+                                                                   * + 1('\0') */
+               strcat(cbuf, "'");
+           }
+           else
+               sprintf(cbuf, "'%s'", param_string);
+           CVT_APPEND_STR(qb, cbuf);
+           break;
+
+       default:            /* a numeric type or SQL_BIT */
+           if (param_sqltype == SQL_BIT)
+               CVT_APPEND_CHAR(qb, '\'');      /* Open Quote */
+
+           if (param_sqltype == SQL_SMALLINT)
+           {
+               CVT_APPEND_STR(qb, "(");
+           }
+
+           if (buf)
+           {
+               switch (used)
+               {
+                   case SQL_NULL_DATA:
+                       break;
+                   case SQL_NTS:
+                       CVT_APPEND_STR(qb, buf);
+                       break;
+                   default:
+                       CVT_APPEND_DATA(qb, buf, used);
+               }
+           }
+           else
+               CVT_APPEND_STR(qb, param_string);
+
+           if (param_sqltype == SQL_SMALLINT)
+           {
+               /* needs cast because there is no automatic downcast from int4 constants */
+               CVT_APPEND_STR(qb, ")::int2");
+           }
+
+           if (param_sqltype == SQL_BIT)
+               CVT_APPEND_CHAR(qb, '\'');      /* Close Quote */
+
+           break;
+   }
+   if (allocbuf)
+       free(allocbuf);
+   return SQL_SUCCESS;
+}
+
+
+static const char *
+mapFunction(const char *func, int param_count)
+{
+   int         i;
+
+   for (i = 0; mapFuncs[i][0]; i++)
+   {
+       if (mapFuncs[i][0][0] == '%')
+       {
+           if (mapFuncs[i][0][1] - '0' == param_count &&
+               !stricmp(mapFuncs[i][0] + 2, func))
+               return mapFuncs[i][1];
+       }
+       else if (!stricmp(mapFuncs[i][0], func))
+           return mapFuncs[i][1];
+   }
+
+   return NULL;
+}
+
+/*
+ * processParameters()
+ * Process function parameters and work with embedded escapes sequences.
+ */
+static int
+processParameters(QueryParse *qp, QueryBuild *qb,
+       UInt4 *output_count, Int4 param_pos[][2])
+{
+   CSTR func = "processParameters";
+   int retval, innerParenthesis, param_count;
+   BOOL stop;
+
+   /* begin with outer '(' */
+   innerParenthesis = 0;
+   param_count = 0;
+   stop = FALSE;
+   for (; F_OldPos(qp) < qp->stmt_len; F_OldNext(qp))
+   {
+       retval = inner_process_tokens(qp, qb);
+       if (retval == SQL_ERROR)
+           return retval;
+       if (ENCODE_STATUS(qp->encstr) != 0)
+           continue;
+       if (qp->in_dquote || qp->in_quote || qp->in_escape)
+           continue;
+
+       switch (F_OldChar(qp))
+       {
+           case ',':
+               if (1 == innerParenthesis)
+               {
+                   param_pos[param_count][1] = F_NewPos(qb) - 2;
+                   param_count++;
+                   param_pos[param_count][0] = F_NewPos(qb);
+                   param_pos[param_count][1] = -1;
+               }
+               break;
+           case '(':
+               if (0 == innerParenthesis)
+               {
+                   param_pos[param_count][0] = F_NewPos(qb);
+                   param_pos[param_count][1] = -1;
+               }
+               innerParenthesis++;
+               break;
+     
+           case ')':
+               innerParenthesis--;
+               if (0 == innerParenthesis)
+               {
+                   param_pos[param_count][1] = F_NewPos(qb) - 2;
+                   param_count++;
+                   param_pos[param_count][0] =
+                   param_pos[param_count][1] = -1;
+               }
+               if (output_count)
+                   *output_count = F_NewPos(qb);
+               break;
+
+           case '}':
+               stop = (0 == innerParenthesis);
+               break;
+
+       }
+       if (stop) /* returns with the last } position */
+           break;
+   }
+   if (param_pos[param_count][0] >= 0)
+   {
+       mylog("%s closing ) not found %d\n", func, innerParenthesis);
+       qb->errornumber = STMT_EXEC_ERROR;
+       qb->errormsg = "processParameters closing ) not found";
+       return SQL_ERROR;
+   }
+   else if (1 == param_count) /* the 1 parameter is really valid ? */
+   {
+       BOOL    param_exist = FALSE;
+       int i;
+
+       for (i = param_pos[0][0]; i <= param_pos[0][1]; i++)
+       {
+           if (!isspace(qb->query_statement[i]))
+           {
+               param_exist = TRUE;
+               break;
+           }
+       }
+       if (!param_exist)
+       {
+           param_pos[0][0] = param_pos[0][1] = -1;
+       }
+   }
+
+   return SQL_SUCCESS;
+}
+
+/*
+ * convert_escape()
+ * This function doesn't return a pointer to static memory any longer !
+ */
+static int
+convert_escape(QueryParse *qp, QueryBuild *qb)
+{
+   CSTR func = "convert_escape";
+   RETCODE retval = SQL_SUCCESS;
+   char        buf[1024], buf_small[128], key[65];
+   UCHAR   ucv;
+   UInt4       prtlen;
+   if (F_OldChar(qp) == '{') /* skip the first { */
+       F_OldNext(qp);
+   /* Separate off the key, skipping leading and trailing whitespace */
+   while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
+       F_OldNext(qp);
+   /*
+    * procedure calls
+    */
+   if (qp->statement_type == STMT_TYPE_PROCCALL)
+   {
+       int lit_call_len = 4;
+       ConnectionClass *conn = qb->conn;
+
+       /* '?=' to accept return values exists ? */
+       if (F_OldChar(qp) == '?')
+       {
+           qb->param_number++;
+           while (isspace((UCHAR) qp->statement[++qp->opos]));
+           if (F_OldChar(qp) != '=')
+           {
+               F_OldPrior(qp);
+               return SQL_SUCCESS;
+           }
+           while (isspace((UCHAR) qp->statement[++qp->opos]));
+       }
+       if (strnicmp(F_OldPtr(qp), "call", lit_call_len) ||
+           !isspace((UCHAR) F_OldPtr(qp)[lit_call_len]))
+       {
+           F_OldPrior(qp);
+           return SQL_SUCCESS;
+       }
+       qp->opos += lit_call_len;
+       CVT_APPEND_STR(qb, "SELECT ");
+       if (my_strchr(conn, F_OldPtr(qp), '('))
+           qp->proc_no_param = FALSE;
+       return SQL_SUCCESS;
+   }
+
+   sscanf(F_OldPtr(qp), "%32s", key);
+   while ((ucv = F_OldChar(qp)) != '\0' && (!isspace(ucv)))
+       F_OldNext(qp);
+   while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
+       F_OldNext(qp);
+    
+   /* Avoid the concatenation of the function name with the previous word. Aceto */
+
+   if (F_NewPos(qb) > 0 && isalnum(F_NewPtr(qb)[-1]))
+       CVT_APPEND_CHAR(qb, ' ');
+   
+   if (stricmp(key, "d") == 0)
+   {
+       /* Literal; return the escape part adding type cast */
+       F_ExtractOldTo(qp, buf_small, '}', sizeof(buf_small));
+       if (PG_VERSION_LT(qb->conn, 7.3))
+           prtlen = snprintf(buf, sizeof(buf), "%s ", buf_small);
+       else
+           prtlen = snprintf(buf, sizeof(buf), "%s::date ", buf_small);
+       CVT_APPEND_DATA(qb, buf, prtlen);
+   }
+   else if (stricmp(key, "t") == 0)
+   {
+       /* Literal; return the escape part adding type cast */
+       F_ExtractOldTo(qp, buf_small, '}', sizeof(buf_small));
+       prtlen = snprintf(buf, sizeof(buf), "%s::time", buf_small);
+       CVT_APPEND_DATA(qb, buf, prtlen);
+   }
+   else if (stricmp(key, "ts") == 0)
+   {
+       /* Literal; return the escape part adding type cast */
+       F_ExtractOldTo(qp, buf_small, '}', sizeof(buf_small));
+       if (PG_VERSION_LT(qb->conn, 7.1))
+           prtlen = snprintf(buf, sizeof(buf), "%s::datetime", buf_small);
+       else
+           prtlen = snprintf(buf, sizeof(buf), "%s::timestamp", buf_small);
+       CVT_APPEND_DATA(qb, buf, prtlen);
+   }
+   else if (stricmp(key, "oj") == 0) /* {oj syntax support for 7.1 * servers */
+   {
+       F_OldPrior(qp);
+       return SQL_SUCCESS; /* Continue at inner_process_tokens loop */
+   }
+   else if (stricmp(key, "fn") == 0)
+   {
+       QueryBuild  nqb;
+       const char *mapExpr;
+       int i, param_count;
+       UInt4   param_consumed;
+       Int4    param_pos[16][2];
+
+       /* Separate off the func name, skipping leading and trailing whitespace */
+       i = 0;
+       while ((ucv = F_OldChar(qp)) != '\0' && ucv != '(' &&
+              (!isspace(ucv)))
+       {
+           if (i < sizeof(key)-1)
+               key[i++] = ucv;
+           F_OldNext(qp);
+       }
+       key[i] = '\0';
+       while ((ucv = F_OldChar(qp)) != '\0' && isspace(ucv))
+           F_OldNext(qp);
+
+       /*
+        * We expect left parenthesis here, else return fn body as-is
+        * since it is one of those "function constants".
+        */
+       if (F_OldChar(qp) != '(')
+       {
+           CVT_APPEND_STR(qb, key);
+           return SQL_SUCCESS;
+       }
+
+       /*
+        * Process parameter list and inner escape
+        * sequences
+        * Aceto 2002-01-29
+        */
+
+       QB_initialize_copy(&nqb, qb, 1024);
+       if (retval = processParameters(qp, &nqb, &param_consumed, param_pos), retval == SQL_ERROR)
+       {
+           qb->errornumber = nqb.errornumber;
+           qb->errormsg = nqb.errormsg;
+           QB_Destructor(&nqb);
+           return retval;
+       }
+
+       for (param_count = 0;; param_count++)
+       {
+           if (param_pos[param_count][0] < 0)
+               break;
+       }
+       if (param_count == 1 &&
+           param_pos[0][1] < param_pos[0][0])
+           param_count = 0;
+
+       mapExpr = mapFunction(key, param_count);
+       if (mapExpr == NULL)
+       {
+           CVT_APPEND_STR(qb, key);
+           CVT_APPEND_DATA(qb, nqb.query_statement, nqb.npos);
+       }
+       else
+       {
+           const char *mapptr;
+           int from, to, pidx, paramlen;
+
+           for (prtlen = 0, mapptr = mapExpr; *mapptr; mapptr++)
+           {
+               if (*mapptr != '$')
+               {
+                   CVT_APPEND_CHAR(qb, *mapptr);
+                   continue;
+               }
+               mapptr++;
+               if (*mapptr == '*')
+               {
+                   from = 1;
+                   to = param_consumed - 2;
+               }
+               else if (isdigit(*mapptr))
+               {
+                   pidx = *mapptr - '0' - 1;
+                   if (pidx < 0 ||
+                       param_pos[pidx][0] < 0)
+                   {
+                       qb->errornumber = STMT_EXEC_ERROR;
+                       qb->errormsg = "param not found";
+                       qlog("%s %dth param not found for the expression %s\n", pidx + 1, mapExpr);
+                       retval = SQL_ERROR;
+                       break;
+                   }
+                   from = param_pos[pidx][0];
+                   to = param_pos[pidx][1];
+               }
+               else
+               {
+                   qb->errornumber = STMT_EXEC_ERROR;
+                   qb->errormsg = "internal expression error";
+                   qlog("%s internal expression error %s\n", func, mapExpr);
+                   retval = SQL_ERROR;
+                   break;
+               }
+               paramlen = to - from + 1;
+               if (paramlen > 0)
+                   CVT_APPEND_DATA(qb, nqb.query_statement+ from, paramlen);
+           }
+       }
+       if (0 == qb->errornumber)
+       {
+           qb->errornumber = nqb.errornumber;
+           qb->errormsg = nqb.errormsg;
+       }
+       if (SQL_ERROR != retval)
+       {
+           qb->param_number = nqb.param_number;
+           qb->flags = nqb.flags;
+       }
+       QB_Destructor(&nqb);
+   }
+   else
+   {
+       /* Bogus key, leave untranslated */
+       return SQL_ERROR;
+   }
+   return retval;
+}
+
+BOOL
+convert_money(const char *s, char *sout, size_t soutmax)
+{
+   size_t      i = 0,
+               out = 0;
+
+   for (i = 0; s[i]; i++)
+   {
+       if (s[i] == '$' || s[i] == ',' || s[i] == ')')
+           ;                   /* skip these characters */
+       else
+       {
+           if (out + 1 >= soutmax)
+               return FALSE;   /* sout is too short */
+           if (s[i] == '(')
+               sout[out++] = '-';
+           else
+               sout[out++] = s[i];
+       }
+   }
+   sout[out] = '\0';
+   return TRUE;
+}
+
+
+/*
+ * This function parses a character string for date/time info and fills in SIMPLE_TIME
+ * It does not zero out SIMPLE_TIME in case it is desired to initialize it with a value
+ */
+char
+parse_datetime(const char *buf, SIMPLE_TIME *st)
+{
+   int         y,
+               m,
+               d,
+               hh,
+               mm,
+               ss;
+   int         nf;
+
+   y = m = d = hh = mm = ss = 0;
+   st->fr = 0;
+   st->infinity = 0;
+
+   /* escape sequence ? */
+   if (buf[0] == '{')
+   {
+       while (*(++buf) && *buf != '\'');
+       if (!(*buf))
+           return FALSE;
+       buf++;
+   }
+   if (buf[4] == '-')          /* year first */
+       nf = sscanf(buf, "%4d-%2d-%2d %2d:%2d:%2d", &y, &m, &d, &hh, &mm, &ss);
+   else
+       nf = sscanf(buf, "%2d-%2d-%4d %2d:%2d:%2d", &m, &d, &y, &hh, &mm, &ss);
+
+   if (nf == 5 || nf == 6)
+   {
+       st->y = y;
+       st->m = m;
+       st->d = d;
+       st->hh = hh;
+       st->mm = mm;
+       st->ss = ss;
+
+       return TRUE;
+   }
+
+   if (buf[4] == '-')          /* year first */
+       nf = sscanf(buf, "%4d-%2d-%2d", &y, &m, &d);
+   else
+       nf = sscanf(buf, "%2d-%2d-%4d", &m, &d, &y);
+
+   if (nf == 3)
+   {
+       st->y = y;
+       st->m = m;
+       st->d = d;
+
+       return TRUE;
+   }
+
+   nf = sscanf(buf, "%2d:%2d:%2d", &hh, &mm, &ss);
+   if (nf == 2 || nf == 3)
+   {
+       st->hh = hh;
+       st->mm = mm;
+       st->ss = ss;
+
+       return TRUE;
+   }
+
+   return FALSE;
+}
+
+
+/* Change linefeed to carriage-return/linefeed */
+int
+convert_linefeeds(const char *si, char *dst, size_t max, BOOL convlf, BOOL *changed)
+{
+   size_t      i = 0,
+               out = 0;
+
+   if (max == 0)
+       max = 0xffffffff;
+   *changed = FALSE;
+   for (i = 0; si[i] && out < max - 1; i++)
+   {
+       if (convlf && si[i] == '\n')
+       {
+           /* Only add the carriage-return if needed */
+           if (i > 0 && si[i - 1] == '\r')
+           {
+               if (dst)
+                   dst[out++] = si[i];
+               else
+                   out++;
+               continue;
+           }
+           *changed = TRUE;
+
+           if (dst)
+           {
+               dst[out++] = '\r';
+               dst[out++] = '\n';
+           }
+           else
+               out += 2;
+       }
+       else
+       {
+           if (dst)
+               dst[out++] = si[i];
+           else
+               out++;
+       }
+   }
+   if (dst)
+       dst[out] = '\0';
+   return out;
+}
+
+
+/*
+ * Change carriage-return/linefeed to just linefeed
+ * Plus, escape any special characters.
+ */
+int
+convert_special_chars(const char *si, char *dst, int used, BOOL convlf, int ccsc)
+{
+   size_t      i = 0,
+               out = 0,
+               max;
+   char       *p = NULL;
+   encoded_str encstr;
+
+   if (used == SQL_NTS)
+       max = strlen(si);
+   else
+       max = used;
+   if (dst)
+   {
+       p = dst;
+       p[0] = '\0';
+   }
+   encoded_str_constr(&encstr, ccsc, si);
+
+   for (i = 0; i < max && si[i]; i++)
+   {
+       encoded_nextchar(&encstr);
+       if (ENCODE_STATUS(encstr) != 0)
+       {
+           if (p)
+               p[out] = si[i];
+           out++;
+           continue;
+       }
+       if (convlf && si[i] == '\r' && si[i + 1] == '\n')
+           continue;
+       else if (si[i] == '\'' || si[i] == '\\')
+       {
+           if (p)
+               p[out++] = '\\';
+           else
+               out++;
+       }
+       if (p)
+           p[out++] = si[i];
+       else
+           out++;
+   }
+   if (p)
+       p[out] = '\0';
+   return out;
+}
+
+
+/* !!! Need to implement this function !!!  */
+int
+convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax)
+{
+   mylog("convert_pgbinary_to_char: value = '%s'\n", value);
+
+   strncpy_null(rgbValue, value, cbValueMax);
+   return 0;
+}
+
+
+static unsigned int
+conv_from_octal(const UCHAR *s)
+{
+   int         i,
+               y = 0;
+
+   for (i = 1; i <= 3; i++)
+       y += (s[i] - '0') << (3 * (3 - i));
+
+   return y;
+
+}
+
+
+static unsigned int
+conv_from_hex(const UCHAR *s)
+{
+   int         i,
+               y = 0,
+               val;
+
+   for (i = 1; i <= 2; i++)
+   {
+       if (s[i] >= 'a' && s[i] <= 'f')
+           val = s[i] - 'a' + 10;
+       else if (s[i] >= 'A' && s[i] <= 'F')
+           val = s[i] - 'A' + 10;
+       else
+           val = s[i] - '0';
+
+       y += val << (4 * (2 - i));
+   }
+
+   return y;
+}
+
+
+/* convert octal escapes to bytes */
+int
+convert_from_pgbinary(const UCHAR *value, UCHAR *rgbValue, int cbValueMax)
+{
+   size_t      i,
+               ilen = strlen(value);
+   int         o = 0;
+
+
+   for (i = 0; i < ilen;)
+   {
+       if (value[i] == '\\')
+       {
+           if (value[i + 1] == '\\')
+           {
+               if (rgbValue)
+                   rgbValue[o] = value[i];
+               i += 2;
+           }
+           else
+           {
+               if (rgbValue)
+                   rgbValue[o] = conv_from_octal(&value[i]);
+               i += 4;
+           }
+       }
+       else
+       {
+           if (rgbValue)
+               rgbValue[o] = value[i];
+           i++;
+       }
+       /** if (rgbValue)
+           mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]); ***/
+       o++;
+   }
+
+   if (rgbValue)
+       rgbValue[o] = '\0';     /* extra protection */
+
+   mylog("convert_from_pgbinary: in=%d, out = %d\n", ilen, o);
+
+   return o;
+}
+
+
+static char *
+conv_to_octal(UCHAR val, char *octal)
+{
+   int         i;
+
+   octal[0] = '\\';
+   octal[1] = '\\';
+   octal[5] = '\0';
+
+   for (i = 4; i > 1; i--)
+   {
+       octal[i] = (val & 7) + '0';
+       val >>= 3;
+   }
+
+   return octal;
+}
+
+
+/* convert non-ascii bytes to octal escape sequences */
+int
+convert_to_pgbinary(const UCHAR *in, char *out, int len)
+{
+   int         i,
+               o = 0;
+
+   for (i = 0; i < len; i++)
+   {
+       mylog("convert_to_pgbinary: in[%d] = %d, %c\n", i, in[i], in[i]);
+       if (isalnum(in[i]) || in[i] == ' ')
+           out[o++] = in[i];
+       else
+       {
+           conv_to_octal(in[i], &out[o]);
+           o += 5;
+       }
+   }
+
+   mylog("convert_to_pgbinary: returning %d, out='%.*s'\n", o, o, out);
+
+   return o;
+}
+
+
+void
+encode(const char *in, char *out)
+{
+   unsigned int i,
+               ilen = strlen(in),
+               o = 0;
+
+   for (i = 0; i < ilen; i++)
+   {
+       if (in[i] == '+')
+       {
+           sprintf(&out[o], "%%2B");
+           o += 3;
+       }
+       else if (isspace((UCHAR) in[i]))
+           out[o++] = '+';
+       else if (!isalnum((UCHAR) in[i]))
+       {
+           sprintf(&out[o], "%%%02x", (UCHAR) in[i]);
+           o += 3;
+       }
+       else
+           out[o++] = in[i];
+   }
+   out[o++] = '\0';
+}
+
+
+void
+decode(const char *in, char *out)
+{
+   unsigned int i,
+               ilen = strlen(in),
+               o = 0;
+
+   for (i = 0; i < ilen; i++)
+   {
+       if (in[i] == '+')
+           out[o++] = ' ';
+       else if (in[i] == '%')
+       {
+           sprintf(&out[o++], "%c", conv_from_hex(&in[i]));
+           i += 2;
+       }
+       else
+           out[o++] = in[i];
+   }
+   out[o++] = '\0';
+}
+
+static const char *hextbl = "0123456789ABCDEF";
+static int
+pg_bin2hex(UCHAR *src, UCHAR *dst, int length)
+{
+   UCHAR       chr,
+              *src_wk,
+              *dst_wk;
+   BOOL        backwards;
+   int         i;
+
+   backwards = FALSE;
+   if (dst < src)
+   {
+       if (dst + length > src + 1)
+           return -1;
+   }
+   else if (dst < src + length)
+       backwards = TRUE;
+   if (backwards)
+   {
+       for (i = 0, src_wk = src + length - 1, dst_wk = dst + 2 * length - 1; i < length; i++, src_wk--)
+       {
+           chr = *src_wk;
+           *dst_wk-- = hextbl[chr % 16];
+           *dst_wk-- = hextbl[chr >> 4];
+       }
+   }
+   else
+   {
+       for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)
+       {
+           chr = *src_wk;
+           *dst_wk++ = hextbl[chr >> 4];
+           *dst_wk++ = hextbl[chr % 16];
+       }
+   }
+   dst[2 * length] = '\0';
+   return length;
+}
+
+int
+pg_hex2bin(const UCHAR *src, UCHAR *dst, int length)
+{
+   UCHAR       chr;
+   const UCHAR *src_wk;
+   UCHAR       *dst_wk;
+   int     i, val;
+   BOOL        HByte = TRUE;
+
+   for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)
+   {
+       chr = *src_wk;
+       if (chr >= 'a' && chr <= 'f')
+           val = chr - 'a' + 10;
+       else if (chr >= 'A' && chr <= 'F')
+           val = chr - 'A' + 10;
+       else
+           val = chr - '0';
+       if (HByte)
+           *dst_wk = (val << 4);
+       else
+       {
+           *dst_wk += val; 
+           dst_wk++;
+       }
+       HByte = !HByte;
+   }
+   *dst_wk = '\0';
+   return length;
+}
+
+/*-------
+ * 1. get oid (from 'value')
+ * 2. open the large object
+ * 3. read from the large object (handle multiple GetData)
+ * 4. close when read less than requested?  -OR-
+ *     lseek/read each time
+ *     handle case where application receives truncated and
+ *     decides not to continue reading.
+ *
+ * CURRENTLY, ONLY LONGVARBINARY is handled, since that is the only
+ * data type currently mapped to a PG_TYPE_LO.  But, if any other types
+ * are desired to map to a large object (PG_TYPE_LO), then that would
+ * need to be handled here.  For example, LONGVARCHAR could possibly be
+ * mapped to PG_TYPE_LO someday, instead of PG_TYPE_TEXT as it is now.
+ *-------
+ */
+int
+convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
+          SDWORD cbValueMax, SDWORD *pcbValue)
+{
+   Oid         oid;
+   int         retval,
+               result,
+               left = -1;
+   GetDataClass *gdata = NULL;
+   ConnectionClass *conn = SC_get_conn(stmt);
+   ConnInfo   *ci = &(conn->connInfo);
+   GetDataInfo *gdata_info = SC_get_GDTI(stmt);
+   int         factor;
+
+   switch (fCType)
+   {
+       case SQL_C_CHAR:
+           factor = 2;
+           break;
+       case SQL_C_BINARY:
+           factor = 1;
+           break;
+       default:
+           SC_set_error(stmt, STMT_EXEC_ERROR, "Could not convert lo to the c-type");
+           return COPY_GENERAL_ERROR;
+   }
+   /* If using SQLGetData, then current_col will be set */
+   if (stmt->current_col >= 0)
+   {
+       gdata = &gdata_info->gdata[stmt->current_col];
+       left = gdata->data_left;
+   }
+
+   /*
+    * if this is the first call for this column, open the large object
+    * for reading
+    */
+
+   if (!gdata || gdata->data_left == -1)
+   {
+       /* begin transaction if needed */
+       if (!CC_is_in_trans(conn))
+       {
+           if (!CC_begin(conn))
+           {
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction");
+               return COPY_GENERAL_ERROR;
+           }
+       }
+
+       oid = ATOI32U(value);
+#ifdef USE_LIBPQ
+           stmt->lobj_fd = lo_open(conn->pgconn, oid, INV_READ);
+#else
+       stmt->lobj_fd = lo_open(conn, oid, INV_READ);
+#endif /* USE_LIBPQ*/
+
+       if (stmt->lobj_fd < 0)
+       {
+           SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for reading.");
+           return COPY_GENERAL_ERROR;
+       }
+
+       /* Get the size */
+#ifdef USE_LIBPQ
+           retval = lo_lseek(conn->pgconn, stmt->lobj_fd, 0L, SEEK_END);
+#else
+       retval = lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_END);
+#endif /* USE_LIBPQ*/
+
+       if (retval >= 0)
+       {
+#ifdef USE_LIBPQ
+           left = lo_tell(conn->pgconn, stmt->lobj_fd);
+#else
+           left = lo_tell(conn, stmt->lobj_fd);
+#endif /* USE_LIBPQ*/
+
+           if (gdata)
+               gdata->data_left = left;
+
+           /* return to beginning */
+#ifdef USE_LIBPQ
+           lo_lseek(conn->pgconn, stmt->lobj_fd, 0L, SEEK_SET);
+#else
+           lo_lseek(conn, stmt->lobj_fd, 0L, SEEK_SET);
+#endif /* USE_LIBPQ*/
+
+       }
+   }
+   mylog("lo data left = %d\n", left);
+
+   if (left == 0)
+       return COPY_NO_DATA_FOUND;
+
+   if (stmt->lobj_fd < 0)
+   {
+       SC_set_error(stmt, STMT_EXEC_ERROR, "Large object FD undefined for multiple read.");
+       return COPY_GENERAL_ERROR;
+   }
+
+#ifdef USE_LIBPQ
+   retval = lo_read(conn->pgconn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax);
+#else
+   retval = lo_read(conn, stmt->lobj_fd, (char *) rgbValue, factor > 1 ? (cbValueMax - 1) / factor : cbValueMax);
+#endif /* USE_LIBPQ */
+
+   if (retval < 0)
+   {
+#ifdef USE_LIBPQ
+       lo_close(conn->pgconn, stmt->lobj_fd);
+#else
+       lo_close(conn, stmt->lobj_fd);
+#endif /* USE_LIBPQ */
+
+
+       /* commit transaction if needed */
+       if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
+       {
+           if (!CC_commit(conn))
+           {
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");
+               return COPY_GENERAL_ERROR;
+           }
+       }
+
+       stmt->lobj_fd = -1;
+
+       SC_set_error(stmt, STMT_EXEC_ERROR, "Error reading from large object.");
+       return COPY_GENERAL_ERROR;
+   }
+
+   if (factor > 1)
+       pg_bin2hex((char *) rgbValue, (char *) rgbValue, retval);
+   if (retval < left)
+       result = COPY_RESULT_TRUNCATED;
+   else
+       result = COPY_OK;
+
+   if (pcbValue)
+       *pcbValue = left < 0 ? SQL_NO_TOTAL : left * factor;
+
+   if (gdata && gdata->data_left > 0)
+       gdata->data_left -= retval;
+
+   if (!gdata || gdata->data_left == 0)
+   {
+#ifdef USE_LIBPQ
+       lo_close(conn->pgconn, stmt->lobj_fd);
+#else
+       lo_close(conn, stmt->lobj_fd);
+#endif /* USE_LIBPQ */
+
+       /* commit transaction if needed */
+       if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(conn))
+       {
+           if (!CC_commit(conn))
+           {
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");
+               return COPY_GENERAL_ERROR;
+           }
+       }
+
+       stmt->lobj_fd = -1;     /* prevent further reading */
+   }
+
+   return result;
+}
index 9e2a44ba29d05c3b3a0caa366ee9d606573c9d79..e02e3d6b84f0ffbfdc52ae1129a4b54b6f46fade 100644 (file)
 
 #define    ODBC_DATASOURCES        "ODBC Data Sources"
 
-#define INI_DSN                DBMS_NAME
+#define INI_DSN                DRIVERNAME
 
 #define INI_KDESC          "Description"   /* Data source description */
 #define INI_SERVER         "Servername"    /* Name of Server running PostgreSQL */
 #define INI_PORT           "Port"      /* Port on which the Postmaster is listening */
-#define INI_SSLMODE         "SSLmode"
+#define INI_SSLMODE                "SSLmode"
 
 #if !defined WIN32 && defined HAVE_SYS_UN_H
 #ifndef HAVE_UNIX_SOCKETS
index 9960413d0f95d5e84d5f0e5f9bb0d3488bb4396a..43c04418c67852bde88c8a7f7873c73c710d929d 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -1007,12 +1007,14 @@ PGAPI_PutData(
        ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
    if (SQL_NTS == cbValue)
    {
+#ifdef  UNICODE_SUPPORT
        if (SQL_C_WCHAR == ctype)
        {
            putlen = WCLEN * ucs2strlen((SQLWCHAR *) rgbValue);
            lenset = TRUE;
        }
        else
+#endif /* UNICODE_SUPPORT */
        if (SQL_C_CHAR == ctype)
        {
            putlen = strlen(rgbValue);
@@ -1024,7 +1026,11 @@ PGAPI_PutData(
        if (cbValue < 0)
            putlen = cbValue;
        else
+#ifdef  UNICODE_SUPPORT
        if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
+#else   
+       if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)    
+#endif /* UNICODE_SUPPORT */
            putlen = cbValue;
        else
            putlen = ctype_length(ctype);
diff --git a/info.c b/info.c
index 4d8de952bf3b546178317c693184f2a080580d3e..a6c533779cfb03a4b7fbbe13b222561ee175c283 100644 (file)
--- a/info.c
+++ b/info.c
@@ -748,7 +748,7 @@ PGAPI_GetInfo(
    {
        /* char/binary data */
        len = strlen(p);
-                
+#ifdef  UNICODE_SUPPORT                
                 /* Note that at this point we don't know if we've been called just
                  * to get the length of the output. If it's unicode, then we better
                  * adjust to bytes now, so we don't return a buffer size that's too
@@ -756,12 +756,15 @@ PGAPI_GetInfo(
                  */
                 if (conn->unicode)
                     len = len * WCLEN;
+#endif
 
        if (rgbInfoValue)
        {
+#ifdef  UNICODE_SUPPORT
            if (conn->unicode)
                len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
            else
+#endif
                strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
 
            if (len >= cbInfoValueMax)
@@ -1431,8 +1434,10 @@ retry_public_schema:
        }
    }
 
+#ifdef  UNICODE_SUPPORT
    if (conn->unicode)
        internal_asis_type = INTERNAL_ASIS_TYPE;
+#endif
 
    result = PGAPI_BindCol(htbl_stmt, 1, internal_asis_type,
                           table_name, MAX_INFO_STRING, NULL);
@@ -1713,10 +1718,10 @@ PGAPI_Columns(
 
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
-
+#ifdef  UNICODE_SUPPORT
    if (conn->unicode)
        internal_asis_type = INTERNAL_ASIS_TYPE;
-
+#endif
    szSchemaName = szTableOwner;
    cbSchemaName = cbTableOwner;
 
@@ -2249,10 +2254,10 @@ PGAPI_SpecialColumns(
        return result;
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
-
+#ifdef  UNICODE_SUPPORT
    if (conn->unicode)
        internal_asis_type = INTERNAL_ASIS_TYPE;
-
+#endif
    stmt->manual_result = TRUE;
    szSchemaName = szTableOwner;
    cbSchemaName = cbTableOwner;
@@ -2516,10 +2521,10 @@ PGAPI_Statistics(
 
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
-
+#ifdef  UNICODE_SUPPORT
    if (conn->unicode)
        internal_asis_type = INTERNAL_ASIS_TYPE;
-
+#endif
    if (res = QR_Constructor(), !res)
    {
        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Statistics result.");
@@ -3005,10 +3010,10 @@ PGAPI_PrimaryKeys(
    tbl_stmt = (StatementClass *) htbl_stmt;
 
    conn = SC_get_conn(stmt);
-
+#ifdef  UNICODE_SUPPORT
    if (conn->unicode)
        internal_asis_type = INTERNAL_ASIS_TYPE;
-
+#endif
    pktab = make_string(szTableName, cbTableName, NULL, 0);
    if (pktab == NULL || pktab[0] == '\0')
    {
@@ -4824,3 +4829,4 @@ mylog("guid=%s\n", uid);
    QR_Destructor(allures); 
    return SQL_SUCCESS;
 }
+
index 3b3d5a29af82771cb05ac8e77ca197ecddedbbdd..9a193d1f4ed6c75be37fbd27abd7001220c19d7b 100644 (file)
--- a/info30.c
+++ b/info30.c
@@ -151,7 +151,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
            value = SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT;
            break;
        case SQL_CATALOG_NAME:
-           len = 0;\r
+           len = 0;
             p = "N";
            break;
        case SQL_COLLATION_SEQ:
@@ -366,7 +366,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
    {
        /* char/binary data */
        len = strlen(p);
-
+#ifdef  UNICODE_SUPPORT
                 /* Note that at this point we don't know if we've been called just
                  * to get the length of the output. If it's unicode, then we better
                  * adjust to bytes now, so we don't return a buffer size that's too
@@ -374,13 +374,14 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
                  */
                 if (conn->unicode)
                     len = len * WCLEN;
-
+#endif
        if (rgbInfoValue)
        {
-
+#ifdef  UNICODE_SUPPORT
            if (conn->unicode)
                len = utf8_to_ucs2(p, len, (SQLWCHAR *) rgbInfoValue, cbInfoValueMax / 2);
            else
+#endif
                strncpy_null((char *) rgbInfoValue, p, (size_t) cbInfoValueMax);
 
            if (len >= cbInfoValueMax)
index 9e29ccea8a0bc06674d658fce6f88753a3294cbc..271543a7b9dc472224a26c2c6bf160a4f2af8039 100644 (file)
@@ -22,7 +22,8 @@
         <Component Id="psqlodbc.files" Guid="F66FBDE8-2E5C-4759-A8DC-85052DAA1374">
         
           <!-- PostgreSQL -->
-          <File Id="psqlodbclibpq.dll" LongName="psqlodbclibpq.dll" Name="psqlodXX.dll" KeyPath="yes" src="../Release/psqlodbclibpq.dll" />
+          <File Id="psqlodbca.dll" LongName="psqlodbca.dll" Name="psqlodxA.dll" KeyPath="yes" src="../Release/psqlodbca.dll" />
+          <File Id="psqlodbcw.dll" LongName="psqlodbcw.dll" Name="psqlodxW.dll" KeyPath="yes" src="../Release/psqlodbcw.dll" />
           <File Id="libpq.dll" Name="libpq.dll" src="C:\Windows\System32\libpq.dll" />
           
           <!-- Gettext -->
           
           <!-- Note, installing the driver properly (IE, using ODBCDriver) has proven unreliable -->
           <!--       so we install the registry keys manually ourselves.                         -->
-          <Registry Id="psqlodbc.reg.1" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers" Name="PostgreSQL-libpq" Type="string" Value="Installed" />
-          <Registry Id="psqlodbc.reg.2" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="APILevel" Type="string" Value="1" />
-          <Registry Id="psqlodbc.reg.3" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="ConnectFunctions" Type="string" Value="YYN" />
-          <Registry Id="psqlodbc.reg.4" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="Driver" Type="string" Value="[#psqlodbclibpq.dll]" />
-          <Registry Id="psqlodbc.reg.5" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="DriverODBCVer" Type="string" Value="03.00" />
-          <Registry Id="psqlodbc.reg.6" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="FileUsage" Type="string" Value="0" />
-          <Registry Id="psqlodbc.reg.7" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="Setup" Type="string" Value="[#psqlodbclibpq.dll]" />
-          <Registry Id="psqlodbc.reg.8" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="SQLLevel" Type="string" Value="1" />
-          <Registry Id="psqlodbc.reg.9" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq" Name="UsageCount" Type="integer" Value="1" />
+          <Registry Id="psqlodbca.reg.1" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers" Name="PostgreSQL ANSI" Type="string" Value="Installed" />
+          <Registry Id="psqlodbca.reg.2" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="APILevel" Type="string" Value="1" />
+          <Registry Id="psqlodbca.reg.3" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="ConnectFunctions" Type="string" Value="YYN" />
+          <Registry Id="psqlodbca.reg.4" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="Driver" Type="string" Value="[#psqlodbca.dll]" />
+          <Registry Id="psqlodbca.reg.5" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="DriverODBCVer" Type="string" Value="03.00" />
+          <Registry Id="psqlodbca.reg.6" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="FileUsage" Type="string" Value="0" />
+          <Registry Id="psqlodbca.reg.7" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="Setup" Type="string" Value="[#psqlodbca.dll]" />
+          <Registry Id="psqlodbca.reg.8" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="SQLLevel" Type="string" Value="1" />
+          <Registry Id="psqlodbca.reg.9" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI" Name="UsageCount" Type="integer" Value="1" />
+
+          <Registry Id="psqlodbcw.reg.1" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers" Name="PostgreSQL Unicode" Type="string" Value="Installed" />
+          <Registry Id="psqlodbcw.reg.2" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="APILevel" Type="string" Value="1" />
+          <Registry Id="psqlodbcw.reg.3" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="ConnectFunctions" Type="string" Value="YYN" />
+          <Registry Id="psqlodbcw.reg.4" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="Driver" Type="string" Value="[#psqlodbcw.dll]" />
+          <Registry Id="psqlodbcw.reg.5" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="DriverODBCVer" Type="string" Value="03.00" />
+          <Registry Id="psqlodbcw.reg.6" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="FileUsage" Type="string" Value="0" />
+          <Registry Id="psqlodbcw.reg.7" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="Setup" Type="string" Value="[#psqlodbcw.dll]" />
+          <Registry Id="psqlodbcw.reg.8" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="SQLLevel" Type="string" Value="1" />
+          <Registry Id="psqlodbcw.reg.9" Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode" Name="UsageCount" Type="integer" Value="1" />
         </Component>
       </Directory>
     </Directory>
      
   </Module>
-</Wix>
\ No newline at end of file
+</Wix>
index a7df17cbe72d3f44eba803cc9c5671259564388f..7f76d441f0b420879c393b5f58efe157963561b6 100644 (file)
@@ -382,7 +382,58 @@ CC_lookup_characterset(ConnectionClass *self)
        encstr = CC_lookup_cs_new(self);
    if (self->client_encoding)
        free(self->client_encoding);
-
+#ifndef UNICODE_SUPPORT     
+#ifdef  WIN32   
+   else     
+   {    
+       const char *wenc = NULL;     
+       switch (GetACP())    
+       {    
+           case 932:    
+               wenc = "SJIS";   
+               break;   
+           case 936:    
+               if (!encstr || PG_VERSION_GT(self, 7.2))     
+                   wenc = "GBK";    
+               break;   
+           case 949:    
+               if (!encstr || (PG_VERSION_GT(self, 7.2) && stricmp(encstr, "EUC_KR")))      
+                   wenc = "UHC";    
+               break;   
+           case 950:    
+               wenc = "BIG5";   
+               break;   
+           case 1250:   
+               wenc = "WIN1250";    
+               break;   
+           case 1252:   
+               if (PG_VERSION_GE(self, 7.2))    
+                   wenc = "latin9";     
+               else     
+                   wenc = "latin1";     
+               break;   
+       }    
+       if (wenc && (!encstr || stricmp(encstr, wenc)))      
+       {    
+           QResultClass    *res;    
+           char            query[64];   
+           int             errnum = CC_get_errornumber(self);   
+
+           sprintf(query, "set client_encoding to '%s'", wenc);     
+           res = CC_send_query(self, query, NULL, CLEAR_RESULT_ON_ABORT);   
+           CC_set_errornumber(self, errnum);    
+           if (res)     
+           {    
+               self->client_encoding = strdup(wenc);    
+               self->ccsc = pg_CS_code(self->client_encoding);      
+               QR_Destructor(res);      
+               free(encstr);    
+               return;      
+           }    
+       }    
+   }    
+#endif /* WIN32 */      
+#endif /* UNICODE_SUPPORT */
    if (encstr)
    {
        self->client_encoding = encstr;
index 4679d9bf48b4470d07632db272816b8cd495ca89..17c8f68669028cd2a159169c34ec8f50db1e0286 100644 (file)
--- a/options.c
+++ b/options.c
@@ -494,6 +494,7 @@ PGAPI_SetConnectOption(
                if (fOption == 30002 && vParam)
                {
                    int cmp;
+#ifdef UNICODE_SUPPORT
                    char *asPara;
                    if (conn->unicode)
                    {
@@ -502,6 +503,7 @@ PGAPI_SetConnectOption(
                        free(asPara);
                    }
                    else
+#endif
                        cmp = strncmp((char *) vParam, "Microsoft Jet", 13);
                    
                    if (0 == cmp)
index b530d2ee2b3eedb989543b33378d7639259713ce..76b652bf45a9b86156ea9f6df2ea284eda04e9a4 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
@@ -102,9 +102,11 @@ Int2       sqlTypes[] = {
    SQL_TINYINT,
    SQL_VARBINARY,
    SQL_VARCHAR,
+#ifdef  UNICODE_SUPPORT
    SQL_WCHAR,
    SQL_WVARCHAR,
    SQL_WLONGVARCHAR,
+#endif
    0
 };
 
@@ -132,9 +134,11 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
            pgType = PG_TYPE_BPCHAR;
            break;
 
+#ifdef  UNICODE_SUPPORT
        case SQL_WCHAR:
            pgType = PG_TYPE_BPCHAR;
            break;
+#endif
 
        case SQL_BIT:
            pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
@@ -174,9 +178,11 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
            pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
            break;
 
+#ifdef  UNICODE_SUPPORT
        case SQL_WLONGVARCHAR:
            pgType = ci->drivers.text_as_longvarchar ? PG_TYPE_TEXT : PG_TYPE_VARCHAR;
            break;
+#endif
 
        case SQL_REAL:
            pgType = PG_TYPE_FLOAT4;
@@ -205,9 +211,11 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
            pgType = PG_TYPE_VARCHAR;
            break;
 
+#ifdef  UNICODE_SUPPORT
        case SQL_WVARCHAR:
            pgType = PG_TYPE_VARCHAR;
            break;
+#endif
 
        default:
            pgType = 0;         /* ??? */
@@ -247,6 +255,7 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type, int col)
        case PG_TYPE_NAME:
            return SQL_CHAR;
 
+#ifdef  UNICODE_SUPPORT
        case PG_TYPE_BPCHAR:
            if (col >= 0 &&
                getCharColumnSize(stmt, type, col, UNKNOWNS_AS_MAX) > ci->drivers.max_varchar_size)
@@ -263,6 +272,22 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type, int col)
            return ci->drivers.text_as_longvarchar ? 
                (conn->unicode ? SQL_WLONGVARCHAR : SQL_LONGVARCHAR) :
                (conn->unicode ? SQL_WVARCHAR : SQL_VARCHAR);
+#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:   
+           return ci->drivers.text_as_longvarchar ? SQL_LONGVARCHAR : SQL_VARCHAR;      
+#endif /* UNICODE_SUPPORT */
 
        case PG_TYPE_BYTEA:
            if (ci->bytea_as_longvarbinary)
@@ -413,12 +438,14 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
            return SQL_C_BINARY;
        case PG_TYPE_LO_UNDEFINED:
            return SQL_C_BINARY;
+#ifdef  UNICODE_SUPPORT
        case PG_TYPE_BPCHAR:
        case PG_TYPE_VARCHAR:
        case PG_TYPE_TEXT:
            if (conn->unicode && ! conn->ms_jet && ! stmt->manual_result)
                return SQL_C_WCHAR;
            return SQL_C_CHAR;
+#endif
 
        default:
            /* hack until permanent type is available */
@@ -1403,12 +1430,14 @@ sqltype_to_default_ctype(const ConnectionClass *conn, Int2 sqltype)
            return SQL_C_CHAR;
        case SQL_BIGINT:
            return ALLOWED_C_BIGINT;
+#ifdef  UNICODE_SUPPORT
        case SQL_WCHAR:
        case SQL_WVARCHAR:
        case SQL_WLONGVARCHAR:
            if (conn->ms_jet || ! conn->unicode)
                return SQL_C_CHAR;
            return SQL_C_WCHAR;
+#endif
 
        case SQL_BIT:
            return SQL_C_BIT;
@@ -1507,7 +1536,9 @@ ctype_length(Int2 ctype)
 
        case SQL_C_BINARY:
        case SQL_C_CHAR:
+#ifdef  UNICODE_SUPPORT
        case SQL_C_WCHAR:
+#endif
            return 0;
 
        default:                /* should never happen */
index 83ad5fea1c94ea73a1a089188b67196393a56214..8ccd315191e8b27f673afa0a3547c7c103117845 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.89 2005/07/13 14:23:35 dpage Exp $
+ * $Id: psqlodbc.h,v 1.90 2005/09/06 07:47:26 dpage Exp $
  *
  */
 
@@ -42,7 +42,7 @@
 
 #include <sql.h>
 #include <sqlext.h>
-#if !defined(WIN32)
+#if defined(UNICODE_SUPPORT) && !defined(WIN32)
 # include <sqlucode.h>
 #endif
 
@@ -123,13 +123,21 @@ typedef UInt4 Oid;
 #endif
 
 /* Driver stuff */
-
-#define DRIVERNAME             "PostgreSQL ODBC"
-#define DRIVER_ODBC_VER                "03.00"
 #define DBMS_NAME              "PostgreSQL"
+#define DRIVER_ODBC_VER                "03.00"
+
+#ifdef  UNICODE_SUPPORT     
+#define DRIVERNAME             "PostgreSQL Unicode"     
+#else
+#define DRIVERNAME             "PostgreSQL ANSI"
+#endif /* UNICODE_SUPPORT */
 
 #ifdef WIN32
-#define DRIVER_FILE_NAME           "PSQLODBC.DLL"
+#ifdef  UNICODE_SUPPORT
+#define DRIVER_FILE_NAME           "PSQLODBCW.DLL"
+#else
+#define DRIVER_FILE_NAME           "PSQLODBCA.DLL"
+#endif
 #else
 #define DRIVER_FILE_NAME           "libpsqlodbc.so"
 #endif   /* WIN32 */
@@ -322,11 +330,13 @@ int   initialize_global_cs(void);
 #ifdef POSIX_THREADMUTEX_SUPPORT
 const pthread_mutexattr_t *getMutexAttr(void);
 #endif /* POSIX_THREADMUTEX_SUPPORT */
+#ifdef  UNICODE_SUPPORT
 #define WCLEN sizeof(SQLWCHAR)
 UInt4  ucs2strlen(const SQLWCHAR *ucs2str);
 char   *ucs2_to_utf8(const SQLWCHAR *ucs2str, Int4 ilen, UInt4 *olen, BOOL tolower);
 UInt4  utf8_to_ucs2_lf(const char * utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *ucs2str, UInt4 buflen);
 #define    utf8_to_ucs2(utf8str, ilen, ucs2str, buflen) utf8_to_ucs2_lf(utf8str, ilen, FALSE, ucs2str, buflen)
+#endif /* UNICODE_SUPPORT */
 
 /*#define  _MEMORY_DEBUG_ */
 #ifdef _MEMORY_DEBUG_
index fd917dbd561eeb2df033aa6a97053ce3d6679ad0..68e8d928c16429c7f2994e74deb622a5f38516c6 100644 (file)
@@ -30,10 +30,18 @@ LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
 DLG_CONFIG DIALOGEX 65, 43, 359, 219
 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | 
     WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+#ifdef UNICODE_SUPPORT
 #ifdef USE_LIBPQ
-CAPTION "PostgreSQL ODBC (libpq) \83Z\83b\83g\83A\83b\83v"
+CAPTION "PostgreSQL Unicode ODBC (libpq) \83Z\83b\83g\83A\83b\83v"
 #else
-CAPTION "PostgreSQL ODBC \83Z\83b\83g\83A\83b\83v"
+CAPTION "PostgreSQL Unicode ODBC \83Z\83b\83g\83A\83b\83v"
+#endif
+#else
+#ifdef USE_LIBPQ
+CAPTION "PostgreSQL ANSI ODBC (libpq) \83Z\83b\83g\83A\83b\83v"
+#else
+CAPTION "PostgreSQL ANSI ODBC \83Z\83b\83g\83A\83b\83v"
+#endif
 #endif
 FONT 9, "\82l\82\83S\83V\83b\83N", 0, 0, 0x1
 BEGIN
@@ -318,10 +326,18 @@ BEGIN
     BEGIN
         BLOCK "040904e4"
         BEGIN
+#ifdef UNICODE_SUPPORT
 #ifdef USE_LIBPQ
-            VALUE "Comments", "PostgreSQL ODBC driver (libpq based)"
+            VALUE "Comments", "PostgreSQL Unicode ODBC driver (libpq based)"
 #else
-            VALUE "Comments", "PostgreSQL ODBC driver"
+            VALUE "Comments", "PostgreSQL Unicode ODBC driver"
+#endif
+#else
+#ifdef USE_LIBPQ
+            VALUE "Comments", "PostgreSQL ANSI ODBC driver (libpq based)"
+#else
+            VALUE "Comments", "PostgreSQL ANSI ODBC driver"
+#endif
 #endif
             VALUE "CompanyName", "PostgreSQL Global Development Group"
             VALUE "FileDescription", "PostgreSQL Driver"
@@ -383,10 +399,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 DLG_CONFIG DIALOGEX 65, 43, 305, 130
 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | 
     WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+#ifdef UNICODE_SUPPORT
 #ifdef USE_LIBPQ
-CAPTION "PostgreSQL ODBC Driver (libpq) Setup"
+CAPTION "PostgreSQL Unicode ODBC (libpq)"
 #else
-CAPTION "PostgreSQL ODBC Driver Setup"
+CAPTION "PostgreSQL Unicode ODBC"
+#endif
+#else
+#ifdef USE_LIBPQ
+CAPTION "PostgreSQL ANSI ODBC (libpq)"
+#else
+CAPTION "PostgreSQL ANSI ODBC"
+#endif
 #endif
 FONT 10, "Terminal", 0, 0, 0x0
 BEGIN
@@ -632,10 +656,18 @@ BEGIN
     BEGIN
         BLOCK "040904e4"
         BEGIN
+#ifdef UNICODE_SUPPORT
 #ifdef USE_LIBPQ
-            VALUE "Comments", "PostgreSQL ODBC driver (libpq based)"
+            VALUE "Comments", "PostgreSQL Unicode ODBC driver (libpq based)"
 #else
-            VALUE "Comments", "PostgreSQL ODBC driver"
+            VALUE "Comments", "PostgreSQL Unicode ODBC driver"
+#endif
+#else
+#ifdef USE_LIBPQ
+            VALUE "Comments", "PostgreSQL ANSI ODBC driver (libpq based)"
+#else
+            VALUE "Comments", "PostgreSQL ANSI ODBC driver"
+#endif
 #endif
             VALUE "CompanyName", "PostgreSQL Global Development Group"
             VALUE "FileDescription", "PostgreSQL Driver"
index c0603ea89f72c9b7ae55cc8ea52209fc3a7a5866..607694b6926c0b4e81201b08837881a2b3ac27b8 100644 (file)
@@ -3,14 +3,25 @@ REGEDIT4
 [HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI]
 
 [HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers]
-"PostgreSQL-libpq"="Installed"
+"PostgreSQL Unicode"="Installed"
+"PostgreSQL ANSI"="Installed"
 
-[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL-libpq]
+[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL Unicode]
 "APILevel"="1"
 "ConnectFunctions"="YYN"
-"Driver"="PSQLODBCLIBPQ.DLL"
+"Driver"="PSQLODBCW.DLL"
 "DriverODBCVer"="03.00"
 "FileUsage"="0"
-"Setup"="PSQLODBCLIBPQ.DLL"
+"Setup"="PSQLODBCW.DLL"
 "SQLLevel"="1"
-"UsageCount"=dword:00000001
\ No newline at end of file
+"UsageCount"=dword:00000001
+
+[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI]
+"APILevel"="1"
+"ConnectFunctions"="YYN"
+"Driver"="PSQLODBCA.DLL"
+"DriverODBCVer"="03.00"
+"FileUsage"="0"
+"Setup"="PSQLODBCA.DLL"
+"SQLLevel"="1"
+"UsageCount"=dword:00000001
diff --git a/psqlodbca.def b/psqlodbca.def
new file mode 100644 (file)
index 0000000..0f19542
--- /dev/null
@@ -0,0 +1,83 @@
+LIBRARY psqlodbca\r
+EXPORTS\r
+;SQLAllocConnect @1\r
+;SQLAllocEnv @2\r
+;SQLAllocStmt @3\r
+SQLBindCol @4\r
+SQLCancel @5\r
+; SQLColAttributes @6 */\r
+SQLConnect @7\r
+SQLDescribeCol @8\r
+SQLDisconnect @9\r
+;SQLError @10\r
+SQLExecDirect @11\r
+SQLExecute @12\r
+SQLFetch @13\r
+;SQLFreeConnect @14\r
+;SQLFreeEnv @15\r
+SQLFreeStmt @16\r
+SQLGetCursorName @17\r
+SQLNumResultCols @18\r
+SQLPrepare @19\r
+SQLRowCount @20\r
+SQLSetCursorName @21\r
+;SQLTransact @23\r
+SQLColumns @40\r
+SQLDriverConnect @41\r
+;SQLGetConnectOption @42\r
+SQLGetData @43\r
+SQLGetFunctions @44\r
+SQLGetInfo @45\r
+;SQLGetStmtOption @46\r
+SQLGetTypeInfo @47\r
+SQLParamData @48\r
+SQLPutData @49\r
+;SQLSetConnectOption @50\r
+;SQLSetStmtOption @51\r
+SQLSpecialColumns @52\r
+SQLStatistics @53\r
+SQLTables @54\r
+SQLBrowseConnect @55\r
+SQLColumnPrivileges @56\r
+SQLDescribeParam @58\r
+SQLExtendedFetch @59\r
+SQLForeignKeys @60\r
+SQLMoreResults @61\r
+SQLNativeSql @62\r
+SQLNumParams @63\r
+SQLParamOptions @64\r
+SQLPrimaryKeys @65\r
+SQLProcedureColumns @66\r
+SQLProcedures @67\r
+SQLSetPos @68\r
+SQLSetScrollOptions @69\r
+SQLTablePrivileges @70\r
+SQLBindParameter @72\r
+\r
+SQLAllocHandle @80\r
+SQLBindParam @81\r
+SQLCloseCursor @82\r
+SQLColAttribute @83\r
+SQLCopyDesc @84\r
+SQLEndTran @85\r
+SQLFetchScroll @86\r
+SQLFreeHandle @87\r
+SQLGetDescField @88\r
+SQLGetDescRec @89\r
+SQLGetDiagField @90\r
+SQLGetDiagRec @91\r
+SQLGetEnvAttr @92\r
+SQLGetConnectAttr @93\r
+SQLGetStmtAttr @94\r
+SQLSetConnectAttr @95\r
+SQLSetDescField @96\r
+SQLSetDescRec @97\r
+SQLSetEnvAttr @98\r
+SQLSetStmtAttr @99\r
+SQLBulkOperations @100\r
+\r
+SQLDummyOrdinal @199\r
+dconn_FDriverConnectProc @200\r
+DllMain @201\r
+ConfigDSN @202\r
+\r
similarity index 98%
rename from psqlodbc_win32.def
rename to psqlodbcw.def
index defb69e75d577761078d684ac491c9260b0721b3..e8fbe2839ccddc8bd5eecf45078fc550a5d07440 100644 (file)
@@ -1,4 +1,4 @@
-LIBRARY psqlodbclibpq
+LIBRARY psqlodbcw
 EXPORTS
 ;SQLAllocConnect @1
 ;SQLAllocEnv @2
index 2bf1c08bc1533a45b3368b8734ca3790f6b6b4d8..1a79d541edc47d38bff811080b278d1cd73a28c9 100644 (file)
--- a/win32.mak
+++ b/win32.mak
@@ -5,12 +5,15 @@
 #
 # Configurations:  Debug, Release
 # Build Types:     ALL, CLEAN
-# Usage:       NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN] [MODE=[USE_LIBPQ | USE_SOCK]  PG_INC=<PostgreSQL include folder>]
+# Usage:       NMAKE /f win32.mak [CFG=[Release | Debug]]
+#                                          [ENCODING=[ANSI | UNICODE]]
+#                                          [MODE=[USE_LIBPQ | USE_SOCK]  PG_INC=<PostgreSQL include folder>]
+#                                          [ALL | CLEAN] 
 # Comments:        Created by Dave Page, 2001-02-12
 #              Modified by Anoop Kumar, 2005-06-27
 #
 
-!MESSAGE Building the PostgreSQL Unicode 3.0 Driver for Win32...
+!MESSAGE Building the PostgreSQL ODBC Driver for Win32...
 !MESSAGE
 !IF "$(CFG)" == ""
 CFG=Release
@@ -22,7 +25,7 @@ MODE=USE_LIBPQ
 !MESSAGE  Using Libpq.
 !ENDIF 
 
-!IF "$(MODE)"  == "USE_LIBPQ" 
+!IF "$(MODE)"  == "USE_LIBPQ"
 !IF "$(PG_INC)" == ""
 PG_INC=C:\Program Files\PostgreSQL\8.0\include
 !MESSAGE Using default PostgreSQL Include directory: $(PG_INC)
@@ -34,6 +37,20 @@ PG_LIB=C:\Program Files\PostgreSQL\8.0\lib\ms
 !ENDIF 
 !ENDIF
 
+!IF "$(ENCODING)" == "ANSI"
+DLLNAME=psqlodbca
+!MESSAGE Building an ANSI driver.
+!ENDIF 
+!IF "$(ENCODING)" == "UNICODE"
+DLLNAME=psqlodbcw
+!MESSAGE Building a Unicode driver.
+!ENDIF
+!IF "$(ENCODING)" == ""
+DLLNAME=psqlodbca
+ENCODING=ANSI
+!MESSAGE No encoding specified. Building an ANSI driver.
+!ENDIF 
+
 !MESSAGE
 
 !IF "$(CFG)" != "Release" && "$(CFG)" != "Debug"
@@ -41,12 +58,15 @@ PG_LIB=C:\Program Files\PostgreSQL\8.0\lib\ms
 !MESSAGE You can specify a configuration when running NMAKE
 !MESSAGE by defining the macro CFG on the command line. For example:
 !MESSAGE 
-!MESSAGE NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN] [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
+!MESSAGE NMAKE /f win32.mak [CFG=[Release | Debug]]
+!MESSAGE                    [ENCODING=[ANSI | UNICODE]]
+!MESSAGE                    [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
+!MESSAGE                    [ALL | CLEAN]
 !MESSAGE 
 !MESSAGE Possible choices for configuration are:
 !MESSAGE 
 !MESSAGE "Release" (Win32 Release DLL)
-!MESSAGE "Debug" (Win32 Debug DLL)
+!MESSAGE "Debug"   (Win32 Debug DLL)
 !MESSAGE 
 !ERROR An invalid configuration was specified.
 !ENDIF 
@@ -56,16 +76,36 @@ PG_LIB=C:\Program Files\PostgreSQL\8.0\lib\ms
 !MESSAGE You can specify the connection mode and PostgreSQL include folder
 !MESSAGE by defining the macros MODE  and  PG_INC on the command line. For example:
 !MESSAGE 
-!MESSAGE NMAKE /f win32.mak CFG=[Release | Debug] [ALL | CLEAN] [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
+!MESSAGE NMAKE /f win32.mak [CFG=[Release | Debug]]
+!MESSAGE                    [ENCODING=[ANSI | UNICODE]]
+!MESSAGE                    [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
+!MESSAGE                    [ALL | CLEAN]
 !MESSAGE 
 !MESSAGE Possible choices for mode are:
 !MESSAGE 
-!MESSAGE "USE_LIBPQ" (Using Libpq Interface)
+!MESSAGE "USE_LIBPQ"  (Using Libpq Interface)
 !MESSAGE "USE_SOCK"   (Using Socket)
 !MESSAGE 
 !ERROR An invalid mode was specified.
 !ENDIF 
 
+!IF "$(ENCODING)"  != "ANSI" && "$(ENCODING)"  != "UNICODE"
+!MESSAGE Invalid encoding "$(ENCODING)" specified.
+!MESSAGE You can specify the connection mode and PostgreSQL include folder
+!MESSAGE by defining the macros MODE  and  PG_INC on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f win32.mak [CFG=[Release | Debug]]
+!MESSAGE                    [ENCODING=[ANSI | UNICODE]]
+!MESSAGE                    [MODE=[USE_LIBPQ | USE_SOCK] PG_INC=<PG include folder> PG_LIB=<PG lib folder>]
+!MESSAGE                    [ALL | CLEAN]
+!MESSAGE 
+!MESSAGE Possible choices for mode are:
+!MESSAGE 
+!MESSAGE "ANSI"    (Build an ANSI/Multibyte driver)
+!MESSAGE "UNICODE" (Build a Unicode driver)
+!MESSAGE 
+!ERROR An invalid mode was specified.
+!ENDIF 
 
 !IF "$(OS)" == "Windows_NT"
 NULL=
@@ -75,11 +115,17 @@ NULL=nul
 
 !IF  "$(CFG)" == "Release"
 
-OUTDIR=.\Release
-OUTDIRBIN=.\Release
-INTDIR=.\Release
+!IF "$(ENCODING)"=="UNICODE"
+OUTDIR=.\Unicode-Release
+OUTDIRBIN=.\Unicode-Release
+INTDIR=.\Unicode-Release
+!ELSE
+OUTDIR=.\ANSI-Release
+OUTDIRBIN=.\ANSI-Release
+INTDIR=.\ANSI-Release
+!ENDIF
 
-ALL : "$(OUTDIRBIN)\psqlodbclibpq.dll"
+ALL : "$(OUTDIRBIN)\$(DLLNAME).dll"
 
 
 CLEAN :
@@ -99,14 +145,16 @@ CLEAN :
    -@erase "$(INTDIR)\misc.obj"
    -@erase "$(INTDIR)\pgapi30.obj"
    -@erase "$(INTDIR)\multibyte.obj"
+!IF "$(ENCODING)"=="UNICODE"
    -@erase "$(INTDIR)\odbcapiw.obj"
    -@erase "$(INTDIR)\odbcapi30w.obj"
    -@erase "$(INTDIR)\win_unicode.obj"
+!ENDIF
    -@erase "$(INTDIR)\options.obj"
    -@erase "$(INTDIR)\parse.obj"
    -@erase "$(INTDIR)\pgtypes.obj"
    -@erase "$(INTDIR)\psqlodbc.obj"
-   -@erase "$(INTDIR)\psqlodbc.res"
+   -@erase "$(INTDIR)\$(DLLNAME).res"
    -@erase "$(INTDIR)\qresult.obj"
    -@erase "$(INTDIR)\results.obj"
    -@erase "$(INTDIR)\setup.obj"
@@ -118,20 +166,32 @@ CLEAN :
    -@erase "$(INTDIR)\odbcapi30.obj"
    -@erase "$(INTDIR)\descriptor.obj"
    -@erase "$(INTDIR)\vc60.idb"
-   -@erase "$(OUTDIR)\psqlodbclibpq.dll"
-   -@erase "$(OUTDIR)\psqlodbclibpq.exp"
-   -@erase "$(OUTDIR)\psqlodbclibpq.lib"
-   -@erase "$(OUTDIR)\psqlodbclibpq.pch"
+   -@erase "$(OUTDIR)\$(DLLNAME).dll"
+   -@erase "$(OUTDIR)\$(DLLNAME).exp"
+   -@erase "$(OUTDIR)\$(DLLNAME).lib"
+   -@erase "$(OUTDIR)\$(DLLNAME).pch"
 
 "$(OUTDIR)" :
     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
 
 CPP=cl.exe
 
+!IF "$(ENCODING)"=="UNICODE"
+
 !IF "$(MODE)"=="USE_LIBPQ"
-CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "$(PG_INC)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbclibpq.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "$(PG_INC)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "UNICODE_SUPPORT" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
 !ELSE
-CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbclibpq.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "UNICODE_SUPPORT" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+!ENDIF
+
+!ELSE
+
+!IF "$(MODE)"=="USE_LIBPQ"
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "$(PG_INC)" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+!ELSE
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)" /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
+!ENDIF
+
 !ENDIF
 
 .c{$(INTDIR)}.obj::
@@ -167,21 +227,21 @@ CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS"
 MTL=midl.exe
 MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 
 RSC=rc.exe
-RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" 
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "NDEBUG" 
 BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" 
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\$(DLLNAME).bsc" 
 BSC32_SBRS= \
    
 LINK32=link.exe
 
 !IF "$(MODE)"=="USE_LIBPQ"
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpq.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbclibpq.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIRBIN)\psqlodbclibpq.dll" /implib:"$(OUTDIR)\psqlodbclibpq.lib" /libpath:"$(PG_LIB)"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpq.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\$(DLLNAME).pdb" /machine:I386 /def:"$(DLLNAME).def" /out:"$(OUTDIRBIN)\$(DLLNAME).dll" /implib:"$(OUTDIR)\$(DLLNAME).lib" /libpath:"$(PG_LIB)"
 !ELSE
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\psqlodbclibpq.pdb" /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIRBIN)\psqlodbclibpq.dll" /implib:"$(OUTDIR)\psqlodbclibpq.lib" 
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\$(DLLNAME).pdb" /machine:I386 /def:"$(DLLNAME).def" /out:"$(OUTDIRBIN)\$(DLLNAME).dll" /implib:"$(OUTDIR)\$(DLLNAME).lib" 
 !ENDIF
 
 
-DEF_FILE= "psqlodbc_win32.def"
+DEF_FILE= "$(DLLNAME).def"
 LINK32_OBJS= \
    "$(INTDIR)\bind.obj" \
    "$(INTDIR)\columninfo.obj" \
@@ -199,9 +259,11 @@ LINK32_OBJS= \
    "$(INTDIR)\misc.obj" \
    "$(INTDIR)\pgapi30.obj" \
    "$(INTDIR)\multibyte.obj" \
+!IF "$(ENCODING)"=="UNICODE"
    "$(INTDIR)\odbcapiw.obj" \
    "$(INTDIR)\odbcapi30w.obj" \
    "$(INTDIR)\win_unicode.obj" \
+!ENDIF
    "$(INTDIR)\options.obj" \
    "$(INTDIR)\parse.obj" \
    "$(INTDIR)\pgtypes.obj" \
@@ -216,20 +278,26 @@ LINK32_OBJS= \
    "$(INTDIR)\odbcapi.obj" \
    "$(INTDIR)\odbcapi30.obj" \
    "$(INTDIR)\descriptor.obj" \
-   "$(INTDIR)\psqlodbc.res"
+   "$(INTDIR)\$(DLLNAME).res"
 
-"$(OUTDIRBIN)\psqlodbclibpq.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+"$(OUTDIRBIN)\$(DLLNAME).dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
     $(LINK32) @<<
   $(LINK32_FLAGS) $(LINK32_OBJS)
 <<
 
 !ELSEIF  "$(CFG)" == "Debug"
 
-OUTDIR=.\Debug
-OUTDIRBIN=.\Debug
-INTDIR=.\Debug
+!IF "$(ENCODING)"=="UNICODE"
+OUTDIR=.\Unicode-Debug
+OUTDIRBIN=.\Unicode-Debug
+INTDIR=.\Unicode-Debug
+!ELSE
+OUTDIR=.\ANSI-Debug
+OUTDIRBIN=.\ANSI-Debug
+INTDIR=.\ANSI-Debug
+!ENDIF
 
-ALL : "$(OUTDIR)\psqlodbclibpq.dll"
+ALL : "$(OUTDIR)\$(DLLNAME).dll"
 
 
 CLEAN :
@@ -249,14 +317,16 @@ CLEAN :
    -@erase "$(INTDIR)\misc.obj"
    -@erase "$(INTDIR)\pgapi30.obj"
    -@erase "$(INTDIR)\multibyte.obj"
+!IF "$(ENCODING)"=="UNICODE"
    -@erase "$(INTDIR)\odbcapiw.obj"
    -@erase "$(INTDIR)\odbcapi30w.obj"
    -@erase "$(INTDIR)\win_unicode.obj"
+!ENDIF
    -@erase "$(INTDIR)\options.obj"
    -@erase "$(INTDIR)\parse.obj"
    -@erase "$(INTDIR)\pgtypes.obj"
    -@erase "$(INTDIR)\psqlodbc.obj"
-   -@erase "$(INTDIR)\psqlodbc.res"
+   -@erase "$(INTDIR)\$(DLLNAME).res"
    -@erase "$(INTDIR)\qresult.obj"
    -@erase "$(INTDIR)\results.obj"
    -@erase "$(INTDIR)\setup.obj"
@@ -269,24 +339,37 @@ CLEAN :
    -@erase "$(INTDIR)\descriptor.obj"
    -@erase "$(INTDIR)\vc60.idb"
    -@erase "$(INTDIR)\vc60.pdb"
-   -@erase "$(OUTDIR)\psqlodbclibpq.dll"
-   -@erase "$(OUTDIR)\psqlodbclibpq.exp"
-   -@erase "$(OUTDIR)\psqlodbclibpq.ilk"
-   -@erase "$(OUTDIR)\psqlodbclibpq.lib"
-   -@erase "$(OUTDIR)\psqlodbclibpq.pdb"
-   -@erase "$(OUTDIR)\psqlodbclibpq.pch"
+   -@erase "$(OUTDIR)\$(DLLNAME).dll"
+   -@erase "$(OUTDIR)\$(DLLNAME).exp"
+   -@erase "$(OUTDIR)\$(DLLNAME).ilk"
+   -@erase "$(OUTDIR)\$(DLLNAME).lib"
+   -@erase "$(OUTDIR)\$(DLLNAME).pdb"
+   -@erase "$(OUTDIR)\$(DLLNAME).pch"
 
 "$(OUTDIR)" :
     if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
 
 CPP=cl.exe
 
+!IF "$(ENCODING)"=="UNICODE"
+
 !IF "$(MODE)"=="USE_LIBPQ"
-CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /I "$(PG_INC)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbclibpq.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /I "$(PG_INC)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "UNICODE_SUPPORT" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
 !ELSE
-CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\psqlodbclibpq.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "UNICODE_SUPPORT" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
 !ENDIF
 
+!ELSE
+
+!IF "$(MODE)"=="USE_LIBPQ"
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /I "$(PG_INC)" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+!ELSE
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PSQLODBC_EXPORTS" /D "$(MODE)"  /D "ODBCVER=0x0300" /D "DRIVER_CURSOR_IMPLEMENT" /D "WIN_MULTITHREAD_SUPPORT" $(ADD_DEFINES) /Fp"$(INTDIR)\$(DLLNAME).pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c 
+!ENDIF
+
+!ENDIF
+
+
 .c{$(INTDIR)}.obj::
    $(CPP) @<<
    $(CPP_PROJ) $< 
@@ -320,20 +403,20 @@ CPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od  /D "WIN32" /D "_DEBUG" /D "_WINDOWS"
 MTL=midl.exe
 MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 
 RSC=rc.exe
-RSC_PROJ=/l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" 
+RSC_PROJ=/l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "_DEBUG" 
 BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\psqlodbc.bsc" 
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\$(DLLNAME).bsc" 
 BSC32_SBRS= \
    
 LINK32=link.exe
 
 !IF "$(MODE)"=="USE_LIBPQ"
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpq.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbclibpq.pdb" /debug /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbclibpq.dll" /implib:"$(OUTDIR)\psqlodbclibpq.lib" /pdbtype:sept /libpath:"$(PG_LIB)"
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libpq.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbclibpq.pdb" /debug /machine:I386 /def:"$(DLLNAME).def" /out:"$(OUTDIR)\$(DLLNAME).dll" /implib:"$(OUTDIR)\$(DLLNAME).lib" /pdbtype:sept /libpath:"$(PG_LIB)"
 !ELSE
-LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\psqlodbclibpq.pdb" /debug /machine:I386 /def:"psqlodbc_win32.def" /out:"$(OUTDIR)\psqlodbclibpq.dll" /implib:"$(OUTDIR)\psqlodbclibpq.lib" /pdbtype:sept 
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\$(DLLNAME).pdb" /debug /machine:I386 /def:"$(DLLNAME).def" /out:"$(OUTDIR)\$(DLLNAME).dll" /implib:"$(OUTDIR)\$(DLLNAME).lib" /pdbtype:sept 
 !ENDIF
 
-DEF_FILE= "psqlodbc_win32.def"
+DEF_FILE= "$(DLLNAME).def"
 LINK32_OBJS= \
    "$(INTDIR)\bind.obj" \
    "$(INTDIR)\columninfo.obj" \
@@ -351,9 +434,11 @@ LINK32_OBJS= \
    "$(INTDIR)\misc.obj" \
    "$(INTDIR)\pgapi30.obj" \
    "$(INTDIR)\multibyte.obj" \
+!IF "$(ENCODING)"=="UNICODE"
    "$(INTDIR)\odbcapiw.obj" \
    "$(INTDIR)\odbcapi30w.obj" \
    "$(INTDIR)\win_unicode.obj" \
+!ENDIF
    "$(INTDIR)\options.obj" \
    "$(INTDIR)\parse.obj" \
    "$(INTDIR)\pgtypes.obj" \
@@ -368,9 +453,9 @@ LINK32_OBJS= \
    "$(INTDIR)\odbcapi.obj" \
    "$(INTDIR)\odbcapi30.obj" \
    "$(INTDIR)\descriptor.obj" \
-   "$(INTDIR)\psqlodbc.res"
+   "$(INTDIR)\$(DLLNAME).res"
 
-"$(OUTDIR)\psqlodbclibpq.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+"$(OUTDIR)\$(DLLNAME).dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
     $(LINK32) @<<
   $(LINK32_FLAGS) $(LINK32_OBJS)
 <<
@@ -462,14 +547,16 @@ SOURCE=multibyte.c
 "$(INTDIR)\multibyte.obj" : $(SOURCE) "$(INTDIR)"
    $(CPP) $(CPP_PROJ) $(SOURCE)
 
-SOURCE=odbcapiw.c
+SOURCE=pgapi30.c
 
-"$(INTDIR)\odbcapiw.obj" : $(SOURCE) "$(INTDIR)"
+"$(INTDIR)\pgapi30.obj" : $(SOURCE) "$(INTDIR)"
    $(CPP) $(CPP_PROJ) $(SOURCE)
 
-SOURCE=pgapi30.c
+!IF "$(ENCODING)"=="UNICODE"
 
-"$(INTDIR)\pgapi30.obj" : $(SOURCE) "$(INTDIR)"
+SOURCE=odbcapiw.c
+
+"$(INTDIR)\odbcapiw.obj" : $(SOURCE) "$(INTDIR)"
    $(CPP) $(CPP_PROJ) $(SOURCE)
 
 SOURCE=odbcapi30w.c
@@ -482,6 +569,7 @@ SOURCE=win_unicode.c
 "$(INTDIR)\win_unicode.obj" : $(SOURCE) "$(INTDIR)"
    $(CPP) $(CPP_PROJ) $(SOURCE)
 
+!ENDIF
 
 SOURCE=options.c
 
@@ -509,28 +597,60 @@ SOURCE=psqlodbc.c
 
 SOURCE=psqlodbc.rc
 
+!IF "$(ENCODING)"=="UNICODE"
+
+!IF "$(MODE)" == "USE_LIBPQ"
+
+!IF "$(CFG)" == "Release"
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "NDEBUG" /d "MULTIBYTE" /d "USE_LIBPQ" /d "UNICODE_SUPPORT" $(SOURCE)
+!ENDIF
+
+!IF "$(CFG)" == "Debug"
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "_DEBUG" /d "MULTIBYTE" /d "USE_LIBPQ" /d "UNICODE_SUPPORT" $(SOURCE)
+!ENDIF
+
+!ELSE
+
+!IF "$(CFG)" == "Release"
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "NDEBUG" /d "MULTIBYTE" /d "UNICODE_SUPPORT" $(SOURCE)
+!ENDIF
+
+!IF "$(CFG)" == "Debug"
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "_DEBUG" /d "MULTIBYTE" /d "UNICODE_SUPPORT" $(SOURCE)
+!ENDIF
+
+!ENDIF
+
+!ELSE
+
 !IF "$(MODE)" == "USE_LIBPQ"
 
 !IF "$(CFG)" == "Release"
-"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
-   $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" /d "USE_LIBPQ" $(SOURCE)
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "NDEBUG" /d "MULTIBYTE" /d "USE_LIBPQ" $(SOURCE)
 !ENDIF
 
 !IF "$(CFG)" == "Debug"
-"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
-   $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" /d "USE_LIBPQ" $(SOURCE)
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "_DEBUG" /d "MULTIBYTE" /d "USE_LIBPQ" $(SOURCE)
 !ENDIF
 
 !ELSE
 
 !IF "$(CFG)" == "Release"
-"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
-   $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "NDEBUG" /d "MULTIBYTE" $(SOURCE)
 !ENDIF
 
 !IF "$(CFG)" == "Debug"
-"$(INTDIR)\psqlodbc.res" : $(SOURCE) "$(INTDIR)"
-   $(RSC) /l 0x809 /fo"$(INTDIR)\psqlodbc.res" /d "_DEBUG" $(SOURCE)
+"$(INTDIR)\$(DLLNAME).res" : $(SOURCE) "$(INTDIR)"
+   $(RSC) /l 0x809 /fo"$(INTDIR)\$(DLLNAME).res" /d "_DEBUG" /d "MULTIBYTE" $(SOURCE)
+!ENDIF
+
 !ENDIF
 
 !ENDIF