2) Reduce time() calls for the performance.
3) Improve the handling of per Driver resource.
4) #define HAVE_STRTOLL
  etc.
   AC_MSG_ERROR([ODBC driver cannot be built for both unixODBC and iODBC])
 fi
 
+#
+# Default odbc version number (--with-odbcver), default 0x0250
+#
+AC_MSG_CHECKING([for ODBC version number])
+PGAC_ARG_REQ(with, odbcver, [  --with-odbcver=VERSION  change default ODBC version number
+ [0x0250]],
+             [AC_DEFINE_UNQUOTED(ODBCVER, ${withval},
+           [Define to ODBC version (--with-odbcver)])])
+AC_MSG_RESULT([$with_odbcver])
+
 AM_CONDITIONAL(with_unixodbc, [test $with_unixodbc = yes])
 AM_CONDITIONAL(with_iodbc, [test $with_iodbc = yes])
 
+AC_CHECK_FUNCS(strtoll)
+
 # to implement the thread-safe driver
 PGAC_ARG_BOOL(enable, pthreads, no,
     [  --enable-pthreads         build pthread implementation if possible],
      AC_CHECK_LIB(c_r, gethostbyname)
      AC_CHECK_LIB(nsl, gethostbyname_r, [],
    [AC_CHECK_FUNCS(getipnodebyname gethostbyname_r, break)])
-     if test "$ac_cv_func_gethostbyname_r" = yes || test "$ac_cv_lib_nsl_gethostbyname_r" = yes; then
+     if test x"$ac_cv_func_gethostbyname_r" = xyes || test x"$ac_cv_lib_nsl_gethostbyname_r" = xyes; then
    AC_TRY_COMPILE([#include <netdb.h>],
    [ gethostbyname_r((char *) 0, (struct hostent *) 0, (char *) 0, 0, (int *) 0);],
         [AC_DEFINE(PGS_REENTRANT_API_1, 1, [Define if you have 5 parameter gethostbyname_r])],
 
    /* fill in any defaults */
    getDSNdefaults(ci);
 
-   qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password);
+   qlog("conn = %u, %s(DSN='%s', UID='%s', PWD='%s')\n", conn, func, ci->dsn, ci->username, ci->password ? "xxxxx" : "");
 
    if (CC_connect(conn, AUTH_REQ_OK, NULL) <= 0)
    {
            return 0;
        }
 
-       mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password);
+       mylog("CC_connect(): DSN = '%s', server = '%s', port = '%s', database = '%s', username = '%s', password='%s'\n", ci->dsn, ci->server, ci->port, ci->database, ci->username, ci->password ? "xxxxx" : "");
 
 another_version_retry:
 
 
 static unsigned int conv_from_hex(const unsigned char *s);
 static char *conv_to_octal(unsigned char val, char *octal);
 static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);
-static int pg_hex2bin(UCHAR *src, UCHAR *dst, int length);
 
 /*---------
  *         A Guide for date/time/timestamp conversions
 #define    ATOI64U _atoi64
 #define    FORMATI64   "%I64d"
 #define    FORMATI64U  "%I64u"
-#else
+#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 */
 
    ARDFields   *opts = SC_get_ARD(stmt);
    Int4        len = 0,
                copy_len = 0;
-   SIMPLE_TIME st;
-   time_t      t = time(NULL);
+   SIMPLE_TIME std_time;
+   time_t      stmt_t = SC_get_time(stmt);
    struct tm  *tim;
 #ifdef HAVE_LOCALTIME_R
    struct tm  tm;
 
    }
 
-   memset(&st, 0, sizeof(SIMPLE_TIME));
+   memset(&std_time, 0, sizeof(SIMPLE_TIME));
 
    /* Initialize current date */
 #ifdef HAVE_LOCALTIME_R
-   tim = localtime_r(&t, &tm);
+   tim = localtime_r(&stmt_t, &tm);
 #else
-   tim = localtime(&t);
+   tim = localtime(&stmt_t);
 #endif /* HAVE_LOCALTIME_R */
-   st.m = tim->tm_mon + 1;
-   st.d = tim->tm_mday;
-   st.y = tim->tm_year + 1900;
+   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);
 
             * PG_TYPE_CHAR,VARCHAR $$$
             */
        case PG_TYPE_DATE:
-           sscanf(value, "%4d-%2d-%2d", &st.y, &st.m, &st.d);
+           sscanf(value, "%4d-%2d-%2d", &std_time.y, &std_time.m, &std_time.d);
            break;
 
        case PG_TYPE_TIME:
-           sscanf(value, "%2d:%2d:%2d", &st.hh, &st.mm, &st.ss);
+           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:
-           st.fr = 0;
-           st.infinity = 0;
+           std_time.fr = 0;
+           std_time.infinity = 0;
            if (strnicmp(value, "infinity", 8) == 0)
            {
-               st.infinity = 1;
-               st.m = 12;
-               st.d = 31;
-               st.y = 9999;
-               st.hh = 23;
-               st.mm = 59;
-               st.ss = 59;
+               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)
            {
-               st.infinity = -1;
-               st.m = 0;
-               st.d = 0;
-               st.y = 0;
-               st.hh = 0;
-               st.mm = 0;
-               st.ss = 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)
            {
                int         zone;
 
                /*
-                * sscanf(value, "%4d-%2d-%2d %2d:%2d:%2d", &st.y, &st.m,
-                * &st.d, &st.hh, &st.mm, &st.ss);
+                * 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, &st, &bZone, &zone);
+               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
                 */
-               t = 0;
+               time_t  t = 0;
 #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;
-               st.hh = tim->tm_hour;
-               st.mm = tim->tm_min;
-               st.ss = tim->tm_sec;
+               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_DATE:
                len = 10;
                if (cbValueMax > len)
-                   sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d", st.y, st.m, st.d);
+                   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", st.hh, st.mm, st.ss);
+                   sprintf(rgbValueBindRow, "%.2d:%.2d:%.2d", std_time.hh, std_time.mm, std_time.ss);
                break;
 
            case PG_TYPE_ABSTIME:
                len = 19;
                if (cbValueMax > len)
                    sprintf(rgbValueBindRow, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
-                           st.y, st.m, st.d, st.hh, st.mm, st.ss);
+                           std_time.y, std_time.m, std_time.d, std_time.hh, std_time.mm, std_time.ss);
                break;
 
            case PG_TYPE_BOOL:
                        ds = (DATE_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
                    else
                        ds = (DATE_STRUCT *) rgbValue + bind_row;
-                   ds->year = st.y;
-                   ds->month = st.m;
-                   ds->day = st.d;
+                   ds->year = std_time.y;
+                   ds->month = std_time.m;
+                   ds->day = std_time.d;
                }
                break;
 
                        ts = (TIME_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
                    else
                        ts = (TIME_STRUCT *) rgbValue + bind_row;
-                   ts->hour = st.hh;
-                   ts->minute = st.mm;
-                   ts->second = st.ss;
+                   ts->hour = std_time.hh;
+                   ts->minute = std_time.mm;
+                   ts->second = std_time.ss;
                }
                break;
 
                        ts = (TIMESTAMP_STRUCT *) ((char *) rgbValue + (bind_row * bind_size));
                    else
                        ts = (TIMESTAMP_STRUCT *) rgbValue + bind_row;
-                   ts->year = st.y;
-                   ts->month = st.m;
-                   ts->day = st.d;
-                   ts->hour = st.hh;
-                   ts->minute = st.mm;
-                   ts->second = st.ss;
-                   ts->fraction = st.fr;
+                   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;
 
 #endif /* ODBCINT64 */
            case SQL_C_BINARY:
 
-               if (PG_TYPE_BYTEA != field_type)
+               if (PG_TYPE_UNKNOWN == field_type)
+               {
+                   if (pcbValue)
+                       *(SDWORD *) ((char *) pcbValue + pcbValueOffset) = SQL_NULL_DATA;
+                   return COPY_OK;
+               }
+               else if (PG_TYPE_BYTEA != field_type)
                {
                    mylog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);
                    return COPY_UNSUPPORTED_TYPE;
    param_string[0] = '\0';
    cbuf[0] = '\0';
    memset(&st, 0, sizeof(st));
-   t = time(NULL);
+   t = SC_get_time(qb->stmt);
 #ifdef HAVE_LOCALTIME_R
    tim = localtime_r(&t, &tm);
 #else
    return length;
 }
 
-static int
-pg_hex2bin(UCHAR *src, UCHAR *dst, int length)
+int
+pg_hex2bin(const UCHAR *src, UCHAR *dst, int length)
 {
-   UCHAR       chr,
-              *src_wk,
-              *dst_wk;
+   UCHAR       chr;
+   const UCHAR *src_wk;
+   UCHAR       *dst_wk;
    int     i, val;
    BOOL        HByte = TRUE;
 
 
 int            convert_pgbinary_to_char(const char *value, char *rgbValue, int cbValueMax);
 int            convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int cbValueMax);
 int            convert_to_pgbinary(const unsigned char *in, char *out, int len);
+int        pg_hex2bin(const UCHAR *in, UCHAR *out, int len);
 void       encode(const char *in, char *out);
 void       decode(const char *in, char *out);
 int convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
 
    else if (stricmp(attribute, "CX") == 0)
        unfoldCXAttribute(ci, value);
 
-   mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password, ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
+   mylog("copyAttributes: DSN='%s',server='%s',dbase='%s',user='%s',passwd='%s',port='%s',onlyread='%s',protocol='%s',conn_settings='%s',disallow_premature=%d)\n", ci->dsn, ci->server, ci->database, ci->username, ci->password ? "xxxxx" : "", ci->port, ci->onlyread, ci->protocol, ci->conn_settings, ci->disallow_premature);
 }
 
 void
    while (*(DSN + strlen(DSN) - 1) == ' ')
        *(DSN + strlen(DSN) - 1) = '\0';
 
+   if (ci->driver[0] == '\0' || overwrite)
+   {
+       SQLGetPrivateProfileString(ODBC_DATASOURCES, DSN, "", ci->driver, sizeof(ci->driver), ODBC_INI);
+       if (ci->driver[0] && stricmp(ci->driver, DBMS_NAME))
+           getCommonDefaults(ci->driver, ODBCINST_INI, ci);
+   }
+
    /* Proceed with getting info for the given DSN. */
 
    if (ci->desc[0] == '\0' || overwrite)
         ci->port,
         ci->database,
         ci->username,
-        ci->password);
+        ci->password ? "xxxxx" : "");
    qlog("          onlyread='%s',protocol='%s',showoid='%s',fakeoidindex='%s',showsystable='%s'\n",
         ci->onlyread,
         ci->protocol,
  * to the ODBCINST.INI portion of the registry
  */
 void
-writeDriverCommoninfo(const ConnInfo *ci)
+writeDriverCommoninfo(const char *fileName, const char *sectionName,
+            const GLOBAL_VALUES *comval)
 {
-   const char *sectionName;
-   const char *fileName;
-   const GLOBAL_VALUES *comval;
    char        tmp[128];
 
-   if (ci)
-       if (ci->dsn && ci->dsn[0])
-       {
-           mylog("DSN=%s updating\n", ci->dsn);
-           comval = &(ci->drivers);
-           sectionName = ci->dsn;
-           fileName = ODBC_INI;
-       }
-       else
-       {
-           mylog("ci but dsn==NULL\n");
-           return;
-       }
-   else
-   {
-       mylog("drivers updating\n");
-       comval = &globals;
+   if (ODBCINST_INI == fileName && NULL == sectionName)
        sectionName = DBMS_NAME;
-       fileName = ODBCINST_INI;
-   }
+ 
    sprintf(tmp, "%d", comval->fetch_max);
    SQLWritePrivateProfileString(sectionName,
                                 INI_FETCH, tmp, fileName);
    /*
     * Never update the onlyread from this module.
     */
-   if (!ci)
+   if (ODBCINST_INI == fileName)
    {
        sprintf(tmp, "%d", comval->onlyread);
        SQLWritePrivateProfileString(sectionName, INI_READONLY, tmp,
 
 #define ODBCINST_INI                   "ODBCINST.INI"
 #endif
 
+#define    ODBC_DATASOURCES    "ODBC Data Sources"
 
 #if (ODBCVER >= 0x0300)
 #ifdef  UNICODE_SUPPORT
 #endif   /* WIN32 */
 
 void       updateGlobals(void);
-void       writeDriverCommoninfo(const ConnInfo *ci);
+void       writeDriverCommoninfo(const char *fileName, const char *sectionName,
+       const GLOBAL_VALUES *);
 void       writeDSNinfo(const ConnInfo *ci);
 void       getDSNdefaults(ConnInfo *ci);
 void       getDSNinfo(ConnInfo *ci, char overwrite);
 
 
 extern HINSTANCE NEAR s_hModule;
 static int driver_optionsDraw(HWND, const ConnInfo *, int src, BOOL enable);
-static int driver_options_update(HWND hdlg, ConnInfo *ci, BOOL);
+static int driver_options_update(HWND hdlg, ConnInfo *ci, const char *);
 
 void
 SetDlgStuff(HWND hdlg, const ConnInfo *ci)
     * If driver attribute NOT present, then set the datasource name and
     * description
     */
-   if (ci->driver[0] == '\0')
-   {
+   /**if (ci->driver[0] == '\0')
+   {**/
        SetDlgItemText(hdlg, IDC_DSNAME, ci->dsn);
        SetDlgItemText(hdlg, IDC_DESC, ci->desc);
-   }
+   /**}**/
 
    SetDlgItemText(hdlg, IDC_DATABASE, ci->database);
    SetDlgItemText(hdlg, IDC_SERVER, ci->server);
 }
 
 static int
-driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile)
+driver_options_update(HWND hdlg, ConnInfo *ci, const char *updateDriver)
 {
    GLOBAL_VALUES *comval;
 
    if (!ci)
        GetDlgItemText(hdlg, DRV_CONNSETTINGS, comval->conn_settings, sizeof(comval->conn_settings));
 
-   if (updateProfile)
-       writeDriverCommoninfo(ci);
+   if (updateDriver)
+       writeDriverCommoninfo(ODBCINST_INI, updateDriver, comval);
 
    /* fall through */
    return 0;
                case IDOK:
                    ci = (ConnInfo *) GetWindowLong(hdlg, DWL_USER);
                    driver_options_update(hdlg, NULL,
-                                         ci && ci->dsn && ci->dsn[0]);
+                       ci ? ci->driver : NULL);
 
                case IDCANCEL:
                    EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
                case IDOK:
                    globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
                    globals.debug = IsDlgButtonChecked(hdlg, DRV_DEBUG);
-                   writeDriverCommoninfo(NULL);
+                   writeDriverCommoninfo(ODBCINST_INI, NULL, &globals);
 
                case IDCANCEL:
                    EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
            switch (GET_WM_COMMAND_ID(wParam, lParam))
            {
                case IDOK:
-                   driver_options_update(hdlg, ci, FALSE);
+                   driver_options_update(hdlg, ci, NULL);
 
                case IDCANCEL:
                    EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
                    return TRUE;
 
                case IDAPPLY:
-                   driver_options_update(hdlg, ci, FALSE);
+                   driver_options_update(hdlg, ci, NULL);
                    SendMessage(GetWindow(hdlg, GW_OWNER), WM_COMMAND, wParam, lParam);
                    break;
 
                    break;
 
                case IDNEXTPAGE:
-                   driver_options_update(hdlg, ci, FALSE);
+                   driver_options_update(hdlg, ci, NULL);
 
                    EndDialog(hdlg, FALSE);
                    DialogBoxParam(s_hModule,
 
 
 #include "dlg_specific.h"
 
+static char * hide_password(const char *str)
+{
+   char *outstr, *pwdp;
+
+   outstr = strdup(str);
+   if (pwdp = strstr(outstr, "PWD="), !pwdp)
+       pwdp = strstr(outstr, "pwd=");
+   if (pwdp)
+   {
+       char    *p;
+
+       for (p=pwdp + 4; *p && *p != ';'; p++)
+           *p = 'x';
+   }
+   return outstr;
+}
+
 /* prototypes */
 void       dconn_get_connect_attributes(const UCHAR FAR * connect_string, ConnInfo *ci);
 static void dconn_get_common_attributes(const UCHAR FAR * connect_string, ConnInfo *ci);
 
    make_string(szConnStrIn, cbConnStrIn, connStrIn);
 
+#ifdef FORCE_PASSWORD_DISPLAY
    mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, connStrIn);
    qlog("conn=%u, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, connStrIn, fDriverCompletion);
+#else
+   if (get_qlog() || get_mylog())
+   {
+       char    *hide_str = hide_password(connStrIn);
+
+       mylog("**** PGAPI_DriverConnect: fDriverCompletion=%d, connStrIn='%s'\n", fDriverCompletion, hide_str);
+       qlog("conn=%u, PGAPI_DriverConnect( in)='%s', fDriverCompletion=%d\n", conn, hide_str, fDriverCompletion);
+       free(hide_str);
+   }
+#endif /* FORCE_PASSWORD_DISPLAY */
 
    ci = &(conn->connInfo);
 
    if (pcbConnStrOut)
        *pcbConnStrOut = len;
 
+#ifdef FORCE_PASSWORD_DISPLAY
    mylog("szConnStrOut = '%s' len=%d,%d\n", szConnStrOut, len, cbConnStrOutMax);
    qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, szConnStrOut);
+#else
+   if (get_qlog() || get_mylog())
+   {
+       char    *hide_str = hide_password(szConnStrOut);
+
+       mylog("szConnStrOut = '%s' len=%d,%d\n", hide_str, len, cbConnStrOutMax);
+       qlog("conn=%u, PGAPI_DriverConnect(out)='%s'\n", conn, hide_str);
+       free(hide_str);
+   }
+#endif /* FORCE_PASSWORD_DISPLAY */
 
 
    mylog("PGAPI_DriverConnect: returning %d\n", result);
    our_connect_string = strdup(connect_string);
    strtok_arg = our_connect_string;
 
+#ifdef FORCE_PASSWORD_DISPLAY
    mylog("our_connect_string = '%s'\n", our_connect_string);
+#else
+   if (get_mylog())
+   {
+       char    *hide_str = hide_password(our_connect_string);
+
+       mylog("our_connect_string = '%s'\n", hide_str);
+       free(hide_str);
+   }
+#endif /* FORCE_PASSWORD_DISPLAY */
 
    while (1)
    {
        attribute = pair;       /* ex. DSN */
        value = equals + 1;     /* ex. 'CEO co1' */
 
-       mylog("attribute = '%s', value = '%s'\n", attribute, value);
+#ifndef    FORCE_PASSWORD_DISPLAY
+       if (stricmp(attribute, INI_PASSWORD) == 0 ||
+           stricmp(attribute, "pwd") == 0)
+           mylog("attribute = '%s', value = 'xxxxx'\n", attribute);
+       else
+#endif /* FORCE_PASSWORD_DISPLAY */
+           mylog("attribute = '%s', value = '%s'\n", attribute, value);
 
        if (!attribute || !value)
            continue;
    our_connect_string = strdup(connect_string);
    strtok_arg = our_connect_string;
 
+#ifdef FORCE_PASSWORD_DISPLAY
    mylog("our_connect_string = '%s'\n", our_connect_string);
+#else
+   if (get_mylog())
+   {
+       char    *hide_str = hide_password(our_connect_string);
+
+       mylog("our_connect_string = '%s'\n", hide_str);
+       free(hide_str);
+   }
+#endif /* FORCE_PASSWORD_DISPLAY */
 
    while (1)
    {
        attribute = pair;       /* ex. DSN */
        value = equals + 1;     /* ex. 'CEO co1' */
 
-       mylog("attribute = '%s', value = '%s'\n", attribute, value);
+#ifndef    FORCE_PASSWORD_DISPLAY
+       if (stricmp(attribute, INI_PASSWORD) == 0 ||
+           stricmp(attribute, "pwd") == 0)
+           mylog("attribute = '%s', value = 'xxxxx'\n", attribute);
+       else
+#endif /* FORCE_PASSWORD_DISPLAY */
+           mylog("attribute = '%s', value = '%s'\n", attribute, value);
 
        if (!attribute || !value)
            continue;
 
                retval;
    ParameterInfoClass *current_param;
    ParameterImplClass *current_iparam;
-   char       *buffer;
+   char       *buffer, *putbuf, *allocbuf = NULL;
+   Int2        ctype;
+   SDWORD      putlen;
+   BOOL        lenset = FALSE;
 
    mylog("%s: entering...\n", func);
 
    current_param = &(apdopts->parameters[stmt->current_exec_param]);
    ipdopts = SC_get_IPD(stmt);
    current_iparam = &(ipdopts->parameters[stmt->current_exec_param]);
+   ctype = current_param->CType;
 
    conn = SC_get_conn(stmt);
+   if (ctype == SQL_C_DEFAULT)
+       ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
+   if (SQL_NTS == cbValue)
+   {
+#ifdef UNICODE_SUPPORT
+       if (SQL_C_WCHAR == ctype)
+       {
+           putlen = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
+           lenset = TRUE;
+       }
+       else
+#endif /* UNICODE_SUPPORT */
+       if (SQL_C_CHAR == ctype)
+       {
+           putlen = strlen(rgbValue);
+           lenset = TRUE;
+       }
+   }
+   if (!lenset)
+   {
+       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);
+   }
+   putbuf = rgbValue;
+   if (current_iparam->PGType == conn->lobj_type && SQL_C_CHAR == ctype)
+   {
+       allocbuf = malloc(putlen / 2 + 1);
+       if (allocbuf)
+       {
+           pg_hex2bin(rgbValue, allocbuf, putlen);
+           putbuf = allocbuf;
+           putlen /= 2;
+       }
+   }
+
    if (!stmt->put_data)
    {                           /* first call */
        mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue);
            return SQL_ERROR;
        }
 
-       *current_param->EXEC_used = cbValue;
+       *current_param->EXEC_used = putlen;
 
        if (cbValue == SQL_NULL_DATA)
            return SQL_SUCCESS;
                return SQL_ERROR;
            }
 
-           retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
-           mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval);
+           retval = lo_write(stmt->hdbc, stmt->lobj_fd, putbuf, putlen);
+           mylog("lo_write: cbValue=%d, wrote %d bytes\n", putlen, retval);
        }
        else
        {
-           Int2        ctype = current_param->CType;
-           if (ctype == SQL_C_DEFAULT)
-               ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
-
-#ifdef UNICODE_SUPPORT
-           if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
-               cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
-#endif /* UNICODE_SUPPORT */
-           /* for handling fields */
-           if (cbValue == SQL_NTS)
-           {
-               current_param->EXEC_buffer = strdup(rgbValue);
-               if (!current_param->EXEC_buffer)
-               {
-                   SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
-                   SC_log_error(func, "", stmt);
-                   return SQL_ERROR;
-               }
-           }
-           else
+           current_param->EXEC_buffer = malloc(putlen + 1);
+           if (!current_param->EXEC_buffer)
            {
-#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 */
-               {
-                   current_param->EXEC_buffer = malloc(cbValue + 1);
-                   if (!current_param->EXEC_buffer)
-                   {
-                       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
-                       SC_log_error(func, "", stmt);
-                       return SQL_ERROR;
-                   }
-                   memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
-                   current_param->EXEC_buffer[cbValue] = '\0';
-               }
-               else
-               {
-                   Int4        used = ctype_length(ctype);
-
-                   current_param->EXEC_buffer = malloc(used);
-                   if (!current_param->EXEC_buffer)
-                   {
-                       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
-                       SC_log_error(func, "", stmt);
-                       return SQL_ERROR;
-                   }
-                   memcpy(current_param->EXEC_buffer, rgbValue, used);
-               }
+               SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
+               SC_log_error(func, "", stmt);
+               return SQL_ERROR;
            }
+           memcpy(current_param->EXEC_buffer, putbuf, putlen);
+           current_param->EXEC_buffer[putlen] = '\0';
        }
    }
    else
        if (current_iparam->PGType == conn->lobj_type)
        {
            /* the large object fd is in EXEC_buffer */
-           retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
-           mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval);
+           retval = lo_write(stmt->hdbc, stmt->lobj_fd, putbuf, putlen);
+           mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", putlen, retval);
 
-           *current_param->EXEC_used += cbValue;
+           *current_param->EXEC_used += putlen;
        }
        else
        {
-           Int2    ctype = current_param->CType;
-
-           if (ctype == SQL_C_DEFAULT)
-               ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
            buffer = current_param->EXEC_buffer;
-           if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
-           {
-#ifdef UNICODE_SUPPORT
-               if (SQL_C_WCHAR == ctype)
-                   old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
-               else
-#endif /* UNICODE_SUPPORT */
-               old_pos = strlen(buffer);
-           }
-           if (SQL_NTS == cbValue)
-           {
-#ifdef UNICODE_SUPPORT
-               if (SQL_C_WCHAR == ctype)
-                   cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
-               else
-#endif /* UNICODE_SUPPORT */
-               cbValue = strlen(rgbValue);
-           }
-           if (cbValue > 0)
+           old_pos = *current_param->EXEC_used;
+           if (putlen > 0)
            {
-               *current_param->EXEC_used += cbValue;
+               *current_param->EXEC_used += putlen;
 
-               mylog("        cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used);
+               mylog("        cbValue = %d, old_pos = %d, *used = %d\n", putlen, old_pos, *current_param->EXEC_used);
 
                /* dont lose the old pointer in case out of memory */
                buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
                    return SQL_ERROR;
                }
 
-               memcpy(&buffer[old_pos], rgbValue, cbValue);
+               memcpy(&buffer[old_pos], putbuf, putlen);
                buffer[*current_param->EXEC_used] = '\0';
 
                /* reassign buffer incase realloc moved it */
            }
        }
    }
+   if (allocbuf)
+       free(allocbuf);
 
    return SQL_SUCCESS;
 }
 
 
        if (fSqlType == SQL_ALL_TYPES || fSqlType == sqlType)
        {
+           int pgtcount = 1, cnt;
+
+           if (SQL_INTEGER == sqlType && PG_VERSION_GE(SC_get_conn(stmt), 6.4))
+               pgtcount = 2;
+           for (cnt = 0; cnt < pgtcount; cnt ++)
+           {
+
            row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
 
            /* These values can't be NULL */
-           set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType));
+           if (1 == cnt)
+           {
+               set_tuplefield_string(&row->tuple[0], "serial");
+               set_tuplefield_int2(&row->tuple[6], SQL_NO_NULLS);
+inolog("serial in\n");
+           }
+           else
+           {
+               set_tuplefield_string(&row->tuple[0], pgtype_to_name(stmt, pgType));
+               set_tuplefield_int2(&row->tuple[6], pgtype_nullable(stmt, pgType));
+           }
            set_tuplefield_int2(&row->tuple[1], (Int2) sqlType);
-           set_tuplefield_int2(&row->tuple[6], pgtype_nullable(stmt, pgType));
            set_tuplefield_int2(&row->tuple[7], pgtype_case_sensitive(stmt, pgType));
            set_tuplefield_int2(&row->tuple[8], pgtype_searchable(stmt, pgType));
            set_tuplefield_int2(&row->tuple[10], pgtype_money(stmt, pgType));
            set_nullfield_string(&row->tuple[3], pgtype_literal_prefix(stmt, pgType));
            set_nullfield_string(&row->tuple[4], pgtype_literal_suffix(stmt, pgType));
            set_nullfield_string(&row->tuple[5], pgtype_create_params(stmt, pgType));
-           set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType));
-           set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType));
+           if (1 == cnt)
+           {
+               set_nullfield_int2(&row->tuple[9], TRUE);
+               set_nullfield_int2(&row->tuple[11], TRUE);
+           }
+           else
+           {
+               set_nullfield_int2(&row->tuple[9], pgtype_unsigned(stmt, pgType));
+               set_nullfield_int2(&row->tuple[11], pgtype_auto_increment(stmt, pgType));
+           }
            set_nullfield_int2(&row->tuple[13], pgtype_scale(stmt, pgType, PG_STATIC));
            set_nullfield_int2(&row->tuple[14], pgtype_scale(stmt, pgType, PG_STATIC));
 #if (ODBCVER >=0x0300)
 #endif /* ODBCVER */
 
            QR_add_tuple(res, row);
+
+           }
        }
    }
 
 
 #endif /* WIN_MULTITHREAD_SUPPORT */
 static int mylog_on = 0,
            qlog_on = 0;
+
+int    get_mylog(void)
+{
+   return mylog_on;
+}
+int    get_qlog(void)
+{
+   return qlog_on;
+}
+
 void
 logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
 {
 
 #endif
 #endif
 #define    inoqlog qlog
+int    get_qlog(void);
+int    get_mylog(void);
 
 #ifndef WIN32
 #define DIRSEPARATOR       "/"
 
                wenc = "BIG5";
                break;
        }
-       if (wenc && stricmp(encstr, wenc))
+       if (wenc && (!encstr || stricmp(encstr, wenc)))
        {
            QResultClass    *res;
            char        query[64];
 
    return FALSE;
 }
 
+/*
+ * lower the unquoted name
+ */
+static
+void lower_the_name(char *name, ConnectionClass *conn, BOOL dquote)
+{
+   if (!dquote)
+   {
+       char        *ptr;
+       encoded_str encstr;
+       make_encoded_str(&encstr, conn, name);
+
+       /* lower case table name */
+       for (ptr = name; *ptr; ptr++)
+       {
+           encoded_nextchar(&encstr);
+           if (ENCODE_STATUS(encstr) != 0)
+               ptr++;
+           else
+               *ptr = tolower((unsigned char) *ptr);
+       }
+   }
+}
 
 char
 parse_statement(StatementClass *stmt)
            }
            if (out_table && !in_table) /* new table */
            {
-
+               if (!dquote)
+               {
+                   if (token[0] == '(' ||
+                       token[0] == ')')
+                       continue;
+               }
                if (!(stmt->ntab % TAB_INCR))
                {
                    ti = (TABLE_INFO **) realloc(ti, (stmt->ntab + TAB_INCR) * sizeof(TABLE_INFO *));
                ti[stmt->ntab]->updatable = 1;
 
                strcpy(ti[stmt->ntab]->name, token);
-               if (!dquote)
-               {
-                   char       *ptr;
-                   encoded_str encstr;
-                   make_encoded_str(&encstr, conn, ti[stmt->ntab]->name);
-
-                   /* lower case table name */
-                   for (ptr = ti[stmt->ntab]->name; *ptr; ptr++)
-                   {
-                       encoded_nextchar(&encstr);
-                       if (ENCODE_STATUS(encstr) != 0)
-                           ptr++;
-                       else
-                           *ptr = tolower((unsigned char) *ptr);
-                   }
-               }
+               lower_the_name(ti[stmt->ntab]->name, conn, dquote);
                mylog("got table = '%s'\n", ti[stmt->ntab]->name);
 
                if (delim == ',')
                {
                    strcpy(ti[stmt->ntab - 1]->schema, ti[stmt->ntab - 1]->name);
                    strcpy(ti[stmt->ntab - 1]->name, token);
+                   lower_the_name(ti[stmt->ntab - 1]->name, conn, dquote);
                    in_dot = FALSE;
                    continue;
                }
 
    SQL_CHAR,
 #if (ODBCVER >= 0x0300)
    SQL_TYPE_DATE,
-#else
-   SQL_DATE,
 #endif /* ODBCVER */
+   SQL_DATE,
    SQL_DECIMAL,
    SQL_DOUBLE,
    SQL_FLOAT,
 #if (ODBCVER >= 0x0300)
    SQL_TYPE_TIME,
    SQL_TYPE_TIMESTAMP,
-#else
+#endif /* ODBCVER */
    SQL_TIME,
    SQL_TIMESTAMP,
-#endif /* ODBCVER */
    SQL_TINYINT,
    SQL_VARBINARY,
    SQL_VARCHAR,
    0
 };
 
-#if (ODBCVER >= 0x0300) && defined(OBDCINT64)
-/* #define ALLOWED_C_BIGINT    SQL_C_SBIGINT */
-#define    ALLOWED_C_BIGINT    SQL_C_CHAR /* Delphi should be either ? */
+#if (ODBCVER >= 0x0300) && defined(ODBCINT64)
+#define    ALLOWED_C_BIGINT    SQL_C_SBIGINT
+/* #define ALLOWED_C_BIGINT    SQL_C_CHAR */ /* Delphi should be either ? */
 #else
 #define    ALLOWED_C_BIGINT    SQL_C_CHAR
 #endif
            pgType = ci->drivers.bools_as_char ? PG_TYPE_CHAR : PG_TYPE_BOOL;
            break;
 
-       case SQL_DATE:
 #if (ODBCVER >= 0x0300)
        case SQL_TYPE_DATE:
+#else
+       case SQL_DATE:
 #endif /* ODBCVER */
            pgType = PG_TYPE_DATE;
            break;
        case PG_TYPE_INT8:
            if (ci->int8_as != 0) 
                return ci->int8_as;
-           if (conn->ms_jet) 
-               return SQL_NUMERIC; /* maybe a little better than SQL_VARCHAR */
+           /***if (conn->ms_jet) 
+               return SQL_NUMERIC; ***/ /* maybe a little better than SQL_VARCHAR */
 #if (ODBCVER >= 0x0300)
            return SQL_BIGINT;
 #else
 
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.75 2003/01/03 16:08:14 hinoue Exp $
+ * $Id: psqlodbc.h,v 1.76 2003/04/23 09:49:47 hinoue Exp $
  *
  */
 
 
                mylog("end of tuple list -- setting inUse to false: this = %u\n", self);
 
                self->inTuples = FALSE;
-               if (self->num_total_rows > 0)
+               qlog("    [ fetched %d rows ]\n", self->num_total_rows);
+               mylog("_next_tuple: 'C' fetch_total = %d & this_fetch = %d\n", self->num_total_rows, self->num_backend_rows);
+               if (self->num_backend_rows > 0)
                {
-                   qlog("    [ fetched %d rows ]\n", self->num_total_rows);
-                   mylog("_next_tuple: 'C' fetch_max && fcount = %d\n", self->num_total_rows);
-
                    /* set to first row */
                    self->tupleField = self->backend_tuples + (offset * self->num_fields);
                    return TRUE;
                else
                {
                    /* We are surely done here (we read 0 tuples) */
-                   qlog("    [ fetched 0 rows ]\n");
                    mylog("_next_tuple: 'C': DONE (fcount == 0)\n");
                    return -1;  /* end of tuples */
                }
 
            break;
 
        default:
+           SC_set_error(stmt, STMT_FETCH_OUT_OF_RANGE, "Unsupported PGAPI_ExtendedFetch Direction");
            SC_log_error(func, "Unsupported PGAPI_ExtendedFetch Direction", stmt);
            return SQL_ERROR;
    }
    if (count)
        *count = 0;
    if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_reload.");
        return SQL_ERROR;
+   }
    if (!stmt->ti)
        parse_statement(stmt);  /* not preferable */
    if (!stmt->updatable)
    {
        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
        return SQL_ERROR;
    }
    res_ridx = global_ridx - stmt->rowset_start + res->base;
    if (!(oid = getOid(res, global_ridx)))
+   {
+       SC_set_error(stmt, STMT_ROW_VERSION_CHANGED, "the row was already deleted ?");
        return SQL_SUCCESS_WITH_INFO;
+   }
    getTid(res, global_ridx, &blocknum, &offset);
    sprintf(tidval, "(%u, %u)", blocknum, offset);
    res_cols = getNumResultCols(res);
 
    mylog("SC_pos_reload_needed\n");
    if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_reload_needed.");
        return SQL_ERROR;
+   }
    if (!stmt->ti)
        parse_statement(stmt);  /* not preferable */
    if (!stmt->updatable)
    {
        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
        return SQL_ERROR;
    }
    limitrow = stmt->rowset_start + res->rowset_size;
 
    mylog("positioned new ti=%x\n", stmt->ti);
    if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_newload.");
        return SQL_ERROR;
+   }
    if (!stmt->ti)
        parse_statement(stmt);  /* not preferable */
    if (!stmt->updatable)
    {
        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
        return SQL_ERROR;
    }
    if (qres = positioned_load(stmt, tidRef ? USE_INSERTED_TID : 0, oid, NULL), qres)
    UInt2   pgoffset;
    Int4    *used, bind_size = opts->bind_size;
 
-   mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, SC_get_Curres(stmt)->base,fi, stmt->ti);
    if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_update.");
        return SQL_ERROR;
+   }
+   mylog("POS UPDATE %d+%d fi=%x ti=%x\n", irow, res->base, fi, stmt->ti);
    if (!stmt->ti)
        parse_statement(stmt);  /* not preferable */
    if (!stmt->updatable)
    {
        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
        return SQL_ERROR;
    }
    if (!(oid = getOid(res, global_ridx)))
    {
-       SC_set_errormsg(stmt, "The row is already deleted");
+       SC_set_error(stmt, STMT_INVALID_CURSOR_POSITION, "The row is already deleted ?");
        return SQL_ERROR;
    }
    getTid(res, global_ridx, &blocknum, &pgoffset);
                blocknum, pgoffset, oid);
        mylog("updstr=%s\n", updstr);
        if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
+       {
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "internal AllocStmt error");
            return SQL_ERROR;
+       }
        qstmt = (StatementClass *) hstmt;
        apdopts = SC_get_APD(qstmt);
        apdopts->param_bind_type = opts->bind_size;
    else
    {
        ret = SQL_SUCCESS_WITH_INFO;
-       SC_set_errormsg(stmt, "update list null");
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "update list null");
    }
    if (SQL_SUCCESS == ret && res->keyset)
    {
 
    mylog("POS DELETE ti=%x\n", stmt->ti);
    if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_delete.");
        return SQL_ERROR;
+   }
    if (!stmt->ti)
        parse_statement(stmt);  /* not preferable */
    if (!stmt->updatable)
    {
        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
        return SQL_ERROR;
    }
    if (!(oid = getOid(res, global_ridx)))
    {
-       SC_set_errormsg(stmt, "The row is already deleted");
+       SC_set_error(stmt, STMT_INVALID_CURSOR_POSITION, "The row is already deleted ?");
        return SQL_ERROR;
    }
    getTid(res, global_ridx, &blocknum, &offset);
 
    mylog("POS ADD fi=%x ti=%x\n", fi, stmt->ti);
    if (!(res = SC_get_Curres(stmt)))
+   {
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in SC_pos_add.");
        return SQL_ERROR;
+   }
    if (!stmt->ti)
        parse_statement(stmt);  /* not preferable */
    if (!stmt->updatable)
    {
        stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
+       SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "the statement is read-only");
        return SQL_ERROR;
    }
    num_cols = irdflds->nfields;
    else
        sprintf(addstr, "insert into \"%s\" (", stmt->ti[0]->name);
    if (PGAPI_AllocStmt(conn, &hstmt) != SQL_SUCCESS)
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "internal AllocStmt error");
        return SQL_ERROR;
+   }
    if (opts->row_offset_ptr)
        offset = *opts->row_offset_ptr;
    else
    else
    {
        ret = SQL_SUCCESS_WITH_INFO;
-       SC_set_errormsg(stmt, "insert list null");
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "insert list null");
    }
    PGAPI_FreeStmt(hstmt, SQL_DROP);
    if (SQL_SUCCESS == ret && res->keyset)
 
    if (!(res = SC_get_Curres(stmt)))
    {
-       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Null statement result in PGAPI_SetPos.");
+       SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Null statement result in PGAPI_SetPos.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
    }
    else
    {
-       if (irow > stmt->last_fetch_count)
+       if (SQL_ADD != fOption && irow > stmt->last_fetch_count)
        {
            SC_set_error(stmt, STMT_ROW_OUT_OF_RANGE, "Row value out of range");
            SC_log_error(func, "", stmt);
    else if (SC_get_IRD(stmt)->rowsFetched)
        *(SC_get_IRD(stmt)->rowsFetched) = processed;
    res->recent_processed_row_count = stmt->diag_row_count = processed;
-inolog("rowset=%d processed=%d ret=%d\n", opts->rowset_size, processed, ret);
    return ret; 
 }
 
 
    }
 
    /* Update ODBC.INI */
-   writeDriverCommoninfo(&lpsetupdlg->ci);
+   writeDriverCommoninfo(ODBC_INI, lpsetupdlg->ci.dsn, &(lpsetupdlg->ci.drivers));
    writeDSNinfo(&lpsetupdlg->ci);
 
    /* If the data source name has changed, remove the old name */
 
        rv->updatable = FALSE;
        rv->error_recsize = -1;
        rv->diag_row_count = 0;
+       rv->stmt_time = 0;
        INIT_STMT_CS(rv);
    }
    return rv;
 }
 
 
+time_t
+SC_get_time(StatementClass *stmt)
+{
+   if (!stmt)
+       return time(NULL);
+   if (!stmt->stmt_time)
+       stmt->stmt_time = time(NULL);
+   return stmt->stmt_time;
+}
 /*
  * Currently, the driver offers very simple bookmark support -- it is
  * just the current row number.  But it could be more sophisticated
 
 #define __STATEMENT_H__
 
 #include "psqlodbc.h"
+#include <time.h>
 
 #include "bind.h"
 #include "descriptor.h"
    Int4        from_pos;   
    Int4        where_pos;
    Int4        last_fetch_count_include_ommitted;
+   time_t      stmt_time;
 #if defined(WIN_MULTITHREAD_SUPPORT)
    CRITICAL_SECTION    cs;
 #elif defined(POSIX_MULTITHREAD_SUPPORT)
 RETCODE        SC_fetch(StatementClass *self);
 void       SC_free_params(StatementClass *self, char option);
 void       SC_log_error(const char *func, const char *desc, const StatementClass *self);
+time_t     SC_get_time(StatementClass *self);
 unsigned long SC_get_bookmark(StatementClass *self);
 RETCODE        SC_pos_update(StatementClass *self, UWORD irow, UDWORD index);
 RETCODE        SC_pos_delete(StatementClass *self, UWORD irow, UDWORD index);
 
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "07.02.0005"
-#define POSTGRES_RESOURCE_VERSION  "07.02.0005\0"
-#define PG_DRVFILE_VERSION     7,2,0,05
+#define POSTGRESDRIVERVERSION      "07.03.0001"
+#define POSTGRES_RESOURCE_VERSION  "07.03.0001\0"
+#define PG_DRVFILE_VERSION     7,3,0,01
 
 #endif