1) Correct the handling of SQL_C_ULONG (for *nix).
authorHiroshi Inoue <inoue@tpf.co.jp>
Tue, 6 Jan 2004 09:58:22 +0000 (09:58 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Tue, 6 Jan 2004 09:58:22 +0000 (09:58 +0000)
2) Prevent plan deallocation errors when the transaction
   is in abort status.
3) Avoid a connection failure when notice message arrives.
4) Improve the handling of mutex(critical section).
5) Correct the cursor open check.
6) Change the Unicode driver to set the NULL terminator
   of SQL_C_WCHAR type data properly.
7) Add some m(re)alloc error check.
8) Add proper cleanup steps for some functions.
9) Return proper min & max scale for timestamp data type.
10) Return proper scale for timestamp data fields.
11) Fix the bug that .009 numeric generates .9 output. (George A.J)

20 files changed:
configure.ac
connection.c
connection.h
convert.c
dlg_specific.c
execute.c
info.c
odbcapi.c
odbcapi30w.c
options.c
pgtypes.c
pgtypes.h
qresult.c
qresult.h
results.c
socket.c
statement.c
statement.h
version.h
win_unicode.c

index 45251b39fe7ab9564d11fa4f18fe23410c7e84fa..4ef425323899b524a0c3f792d58041ca252155af 100644 (file)
@@ -37,7 +37,7 @@ 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)
+AC_CHECK_FUNCS(strtoul strtoll)
 AC_CHECK_LIB(socket, socket)
 
 # to implement the thread-safe driver
@@ -89,5 +89,9 @@ AC_CHECK_HEADERS([sys/un.h])
 AC_CHECK_TYPES(uint8)
 PGAC_VAR_INT_TIMEZONE
 
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_STRUCT_TM
+
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
index c39fb54248d3150fbb84c249458a79b5386bf656..324b3d9f5bdccad01b73a570b90d29108d04cbb6 100644 (file)
@@ -308,7 +308,8 @@ CC_Constructor()
        rv->client_encoding = NULL;
        rv->server_encoding = NULL;
        rv->current_schema = NULL;
-
+       rv->num_discardp = 0;
+       rv->discardp = NULL;
 
        /* Initialize statement options to defaults */
        /* Statements under this conn will inherit these options */
@@ -550,8 +551,6 @@ CC_cleanup(ConnectionClass *self)
    /* Free cached table info */
    if (self->col_info)
    {
-       int         i;
-
        for (i = 0; i < self->ntables; i++)
        {
            if (self->col_info[i]->result)  /* Free the SQLColumns result structure */
@@ -565,6 +564,18 @@ CC_cleanup(ConnectionClass *self)
        self->col_info = NULL;
    }
    self->ntables = 0;
+   if (self->num_discardp > 0 && self->discardp)
+   {
+       for (i = 0; i < self->num_discardp; i++)
+           free(self->discardp[i]);
+       self->num_discardp = 0;
+   }
+   if (self->discardp)
+   {
+       free(self->discardp);
+       self->discardp = NULL;
+   }
+
    mylog("exit CC_Cleanup\n");
    return TRUE;
 }
@@ -950,7 +961,9 @@ another_version_retry:
    mylog("sending an empty query...\n");
 
    res = CC_send_query(self, " ", NULL, CLEAR_RESULT_ON_ABORT);
-   if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
+   if (res == NULL ||
+       (QR_get_status(res) != PGRES_EMPTY_QUERY &&
+        QR_command_nonfatal(res)))
    {
        mylog("got no result from the empty query.  (probably database does not exist)\n");
        CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.");
@@ -1086,9 +1099,11 @@ CC_remove_statement(ConnectionClass *self, StatementClass *stmt)
 {
    int         i;
 
+   if (stmt->status == STMT_EXECUTING)
+       return FALSE;
    for (i = 0; i < self->num_stmts; i++)
    {
-       if (self->stmts[i] == stmt && stmt->status != STMT_EXECUTING)
+       if (self->stmts[i] == stmt)
        {
            self->stmts[i] = NULL;
            return TRUE;
@@ -1221,9 +1236,14 @@ void CC_on_commit(ConnectionClass *conn)
    }
    conn->result_uncommitted = 0;
    CC_clear_cursors(conn, TRUE);
+   CC_discard_marked_plans(conn);
 }
 void   CC_on_abort(ConnectionClass *conn, UDWORD opt)
 {
+   BOOL    set_no_trans = FALSE;
+
+   if (0 != (opt & CONN_DEAD))
+       opt |= NO_TRANS;
    if (CC_is_in_trans(conn))
    {
 #ifdef DRIVER_CURSOR_IMPLEMENT
@@ -1234,8 +1254,10 @@ void CC_on_abort(ConnectionClass *conn, UDWORD opt)
        {
            CC_set_no_trans(conn);
            CC_set_no_manual_trans(conn);
+           set_no_trans = TRUE;
        }
    }
+   CC_clear_cursors(conn, TRUE);
    if (0 != (opt & CONN_DEAD))
    {
        conn->status = CONN_DOWN;
@@ -1245,8 +1267,9 @@ void  CC_on_abort(ConnectionClass *conn, UDWORD opt)
            conn->sock = NULL;
        }
    }
+   else if (set_no_trans)
+       CC_discard_marked_plans(conn);
    conn->result_uncommitted = 0;
-   CC_clear_cursors(conn, TRUE);
 }
 
 /*
@@ -1273,13 +1296,13 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
    int         maxlen,
                empty_reqs;
    BOOL        msg_truncated,
-               ReadyToReturn,
+               ReadyToReturn = FALSE,
                query_completed = FALSE,
                before_64 = PG_VERSION_LT(self, 6.4),
                aborted = FALSE,
                used_passed_result_object = FALSE;
    UDWORD      abort_opt;
-   int     entered;
+   int     func_cs_count = 0;
 
    /* ERROR_MSG_LENGTH is suffcient */
    char msgbuffer[ERROR_MSG_LENGTH + 1];
@@ -1315,13 +1338,14 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
        return NULL;
    }
 
-   ENTER_INNER_CONN_CS(self, entered);
+#define    return DONT_CALL_RETURN_FROM_HERE???
+   ENTER_INNER_CONN_CS(self, func_cs_count);
    SOCK_put_char(sock, 'Q');
    if (SOCK_get_errcode(sock) != 0)
    {
        CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       RETURN_AFTER_LEAVE_CS(entered, self, NULL);
+       goto cleanup;
    }
 
    if (issue_begin)
@@ -1333,12 +1357,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
    {
        CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
-       RETURN_AFTER_LEAVE_CS(entered, self, NULL);
+       goto cleanup;
    }
 
    mylog("send_query: done sending query\n");
 
-   ReadyToReturn = FALSE;
    empty_reqs = 0;
    for (wq = query; isspace((UCHAR) *wq); wq++)
        ;
@@ -1353,7 +1376,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
        if (!cmdres)
        {
            CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
-           RETURN_AFTER_LEAVE_CS(entered, self, NULL);
+           goto cleanup;
        }
    }
    res = cmdres;
@@ -1522,7 +1545,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                    abort_opt = NO_TRANS | CONN_DEAD;
                }
                else
+               {
                    CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);
+                   if (CC_is_in_trans(self))
+                       CC_set_in_error_trans(self);
+               }
                CC_on_abort(self, abort_opt);
                QR_set_status(res, PGRES_FATAL_ERROR);
                QR_set_message(res, msgbuffer);
@@ -1629,6 +1656,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
        }
    }
 
+cleanup:
+   CLEANUP_FUNC_CONN_CS(func_cs_count, self);
    /*
     * Break before being ready to return.
     */
@@ -1677,7 +1706,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
            }
        }
    }
-   RETURN_AFTER_LEAVE_CS(entered, self, retres);
+#undef return
+   return retres;
 }
 
 
@@ -1762,6 +1792,8 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
            case 'E':
                SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
                CC_set_errormsg(self, msgbuffer);
+               if (CC_is_in_trans(self))
+                   CC_set_in_error_trans(self);
                CC_on_abort(self, 0);
 
                mylog("send_function(V): 'E' - %s\n", CC_get_errormsg(self));
@@ -2247,3 +2279,40 @@ CC_send_cancel_request(const ConnectionClass *conn)
 
    return ret;
 }
+
+int    CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plan)
+{
+   int cnt = conn->num_discardp + 1;
+   char    *pname;
+
+   CC_REALLOC_return_with_error(conn->discardp, char *,
+       (cnt * sizeof(char *)), conn, "Couldn't alloc discardp.", -1) 
+   CC_MALLOC_return_with_error(pname, char, (strlen(plan) + 1),
+       conn, "Couldn't alloc discardp mem.", -1)
+   strcpy(pname, plan);
+   conn->discardp[conn->num_discardp++] = pname; 
+   return 1;
+}
+int    CC_discard_marked_plans(ConnectionClass *conn)
+{
+   int i, cnt;
+   QResultClass *res;
+   char    cmd[32];
+
+   if ((cnt = conn->num_discardp) <= 0)
+       return 0;
+   for (i = cnt - 1; i >= 0; i--)
+   {
+       sprintf(cmd, "DEALLOCATE \"%s\"", conn->discardp[i]);
+       res = CC_send_query(conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
+       if (res)
+       {
+           QR_Destructor(res);
+           free(conn->discardp[i]);
+           conn->num_discardp--;
+       }
+       else
+           return -1;
+   }
+   return 1;
+}
index f2e131760ac47e8486ada6f5186a0468c1d32b79..5eb0023b8e36d55dae3705c25ce6453af1ed98f4 100644 (file)
@@ -66,6 +66,7 @@ typedef enum
 #define CONN_IN_AUTOCOMMIT     1L 
 #define CONN_IN_TRANSACTION        (1L<<1)
 #define CONN_IN_MANUAL_TRANSACTION (1L<<2)
+#define CONN_IN_ERROR_BEFORE_IDLE  (1L<<3)
 
 /* AutoCommit functions */
 #define CC_set_autocommit_off(x)   (x->transact_status &= ~CONN_IN_AUTOCOMMIT)
@@ -74,7 +75,7 @@ typedef enum
 
 /* Transaction in/not functions */
 #define CC_set_in_trans(x) (x->transact_status |= CONN_IN_TRANSACTION)
-#define CC_set_no_trans(x) (x->transact_status &= ~CONN_IN_TRANSACTION)
+#define CC_set_no_trans(x) (x->transact_status &= ~(CONN_IN_TRANSACTION | CONN_IN_ERROR_BEFORE_IDLE))
 #define CC_is_in_trans(x)  (x->transact_status & CONN_IN_TRANSACTION)
 
 /* Manual transaction in/not functions */
@@ -82,16 +83,38 @@ typedef enum
 #define CC_set_no_manual_trans(x) (x->transact_status &= ~CONN_IN_MANUAL_TRANSACTION)
 #define CC_is_in_manual_trans(x) (x->transact_status & CONN_IN_MANUAL_TRANSACTION)
 
+/* Error waiting for ROLLBACK */
+#define CC_set_in_error_trans(x) (x->transact_status |= CONN_IN_ERROR_BEFORE_IDLE)
+#define CC_set_no_error_trans(x) (x->transact_status &= ~CONN_IN_ERROR_BEFORE_IDLE)
+#define CC_is_in_error_trans(x) (x->transact_status & CONN_IN_ERROR_BEFORE_IDLE)
+
 #define CC_get_errornumber(x)  (x->__error_number)
 #define CC_get_errormsg(x) (x->__error_message)
 #define CC_set_errornumber(x, n)   (x->__error_number = n)
 
+#define CC_MALLOC_return_with_error(t, tp, s, x, m, ret) \
+   { \
+       if (t = malloc(s), NULL == t) \
+       { \
+           CC_set_error(x, CONN_NO_MEMORY_ERROR, m); \
+           return ret; \
+       } \
+   }
+#define CC_REALLOC_return_with_error(t, tp, s, x, m, ret) \
+   { \
+       if (t = (tp *) realloc(t, s), NULL == t) \
+       { \
+           CC_set_error(x, CONN_NO_MEMORY_ERROR, m); \
+           return ret; \
+       } \
+   }
+
 /* For Multi-thread */
 #if defined(WIN_MULTITHREAD_SUPPORT)
 #define INIT_CONN_CS(x)        InitializeCriticalSection(&((x)->cs))
 #define ENTER_CONN_CS(x)   EnterCriticalSection(&((x)->cs))
 #define ENTER_INNER_CONN_CS(x, entered) \
-   { EnterCriticalSection(&((x)->cs)); entered = 1; }
+   { EnterCriticalSection(&((x)->cs)); entered++; }
 #define LEAVE_CONN_CS(x)   LeaveCriticalSection(&((x)->cs))
 #define DELETE_CONN_CS(x)  DeleteCriticalSection(&((x)->cs))
 #elif defined(POSIX_THREADMUTEX_SUPPORT)
@@ -102,27 +125,37 @@ typedef enum
        if (getMutexAttr()) \
        { \
            if (pthread_mutex_lock(&((x)->cs)) == 0) \
-               entered = 1; \
+               entered++; \
            else \
-               entered = -1; \
+               -1; \
        } \
        else \
-           entered = 0; \
+           0; \
    }
 #define LEAVE_CONN_CS(x)   pthread_mutex_unlock(&((x)->cs))
 #define DELETE_CONN_CS(x)  pthread_mutex_destroy(&((x)->cs))
 #else
 #define INIT_CONN_CS(x)    
 #define ENTER_CONN_CS(x)
-#define ENTER_INNER_CONN_CS(x, entered) {entered = 0;}
+#define ENTER_INNER_CONN_CS(x, entered) (0)
 #define LEAVE_CONN_CS(x)
 #define DELETE_CONN_CS(x)
 #endif /* WIN_MULTITHREAD_SUPPORT */
 
 #define    LEAVE_INNER_CONN_CS(entered, conn) \
-   { if (entered > 0) LEAVE_CONN_CS(conn); }
-#define    RETURN_AFTER_LEAVE_CS(entered, conn, ret) \
-   { if (entered > 0) LEAVE_CONN_CS(conn); return ret; }
+   { \
+       if (entered > 0) \
+       { \
+           LEAVE_CONN_CS(conn); \
+           entered--; \
+       } \
+   }
+#define    CLEANUP_FUNC_CONN_CS(entered, conn) \
+   while (entered > 0) \
+   { \
+       LEAVE_CONN_CS(conn); \
+       entered--; \
+   }
 
 /* Authentication types */
 #define AUTH_REQ_OK                                    0
@@ -351,6 +384,8 @@ struct ConnectionClass_
    int     be_key; /* auth code needed to send cancel */
    UInt4       isolation;
    char        *current_schema;
+   int     num_discardp;
+   char        **discardp;
 #if (ODBCVER >= 0x0300)
    int     num_descs;
    DescriptorClass **descs;
@@ -412,6 +447,8 @@ void        CC_on_commit(ConnectionClass *conn);
 void       CC_on_abort(ConnectionClass *conn, UDWORD opt);
 void       ProcessRollback(ConnectionClass *conn, BOOL undo);
 const char *CC_get_current_schema(ConnectionClass *conn);
+int        CC_mark_a_plan_to_discard(ConnectionClass *conn, const char *plannm);
+int        CC_discard_marked_plans(ConnectionClass *conn);
 
 /* CC_send_query options */
 #define    CLEAR_RESULT_ON_ABORT   1L
index c9e61bf08f02d857f34239db26e7a9def15efc17..5332be1daca099204f0f3d9e0a52987849cd5494 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -156,6 +156,17 @@ static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);
  */
 
 
+/*
+ * 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.
  */
@@ -186,7 +197,7 @@ timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)
               *ptr;
    int         scnt,
                i;
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#ifdef TIMEZONE_GLOBAL
    long        timediff;
 #endif
    BOOL        withZone = *bZone;
@@ -195,7 +206,8 @@ timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)
    *zone = 0;
    st->fr = 0;
    st->infinity = 0;
-   if ((scnt = sscanf(str, "%4d-%2d-%2d %2d:%2d:%2d%s", &st->y, &st->m, &st->d, &st->hh, &st->mm, &st->ss, rest)) < 6)
+   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;
@@ -237,7 +249,7 @@ timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)
    }
    if (!withZone || !*bZone || st->y < 1970)
        return TRUE;
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#ifdef TIMEZONE_GLOBAL
    if (!tzname[0] || !tzname[0][0])
    {
        *bZone = FALSE;
@@ -283,7 +295,7 @@ timestamp2stime(const char *str, SIMPLE_TIME *st, BOOL *bZone, int *zone)
            *bZone = TRUE;
        }
    }
-#endif   /* WIN32 */
+#endif /* TIMEZONE_GLOBAL */
    return TRUE;
 }
 
@@ -316,7 +328,7 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
        }
    }
    zonestr[0] = '\0';
-#if defined(WIN32) || defined(HAVE_INT_TIMEZONE)
+#ifdef TIMEZONE_GLOBAL
    if (bZone && tzname[0] && tzname[0][0] && st->y >= 1970)
    {
        long        zoneint;
@@ -342,7 +354,7 @@ stime2timestamp(const SIMPLE_TIME *st, char *str, BOOL bZone, BOOL precision)
        else
            sprintf(zonestr, "+%02d", -(int) zoneint / 3600);
    }
-#endif   /* WIN32 */
+#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;
 }
@@ -853,8 +865,16 @@ inolog("2stime fr=%d\n", std_time.fr);
 
                if (cbValueMax > 0)
                {
-                   copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
+                   BOOL    already_copied = FALSE;
 
+                   copy_len = (len >= cbValueMax) ? cbValueMax - 1 : len;
+#ifdef WIN_UNICODE_SUPPORT
+                   if (fCType == SQL_C_WCHAR)
+                   {
+                       copy_len /= 2;
+                       copy_len *= 2;
+                   }
+#endif /* WIN_UNICODE_SUPPORT */
 #ifdef HAVE_LOCALE_H
                    switch (field_type)
                    {
@@ -866,7 +886,7 @@ inolog("2stime fr=%d\n", std_time.fr);
                            char        *new_string;
                            int     i, j;
 
-                           new_string = malloc( cbValueMax );
+                           new_string = malloc(cbValueMax);
                            lc = localeconv();
                            for (i = 0, j = 0; ptr[i]; i++)
                                if (ptr[i] == '.')
@@ -879,17 +899,21 @@ inolog("2stime fr=%d\n", std_time.fr);
                            new_string[j] = '\0';
                            strncpy_null(rgbValueBindRow, new_string, copy_len + 1);
                            free(new_string);
+                           already_copied = TRUE;
                            break;
                        }
-                       default:
-                       /*      Copy the data */
-                       strncpy_null(rgbValueBindRow, ptr, copy_len + 1);
-                   }
-#else /* HAVE_LOCALE_H */
-                   /* Copy the data */
-                   memcpy(rgbValueBindRow, ptr, copy_len);
-                   rgbValueBindRow[copy_len] = '\0';
+                   }
 #endif /* HAVE_LOCALE_H */
+                   if (!already_copied)
+                   {
+                       /* Copy the data */
+                       memcpy(rgbValueBindRow, ptr, copy_len);
+                       rgbValueBindRow[copy_len] = '\0';
+                   }
+#ifdef WIN_UNICODE_SUPPORT
+                   if (fCType == SQL_C_WCHAR)
+                       rgbValueBindRow[copy_len + 1] = '\0';
+#endif /* WIN_UNICODE_SUPPORT */
 
                    /* Adjust data_left for next time */
                    if (stmt->current_col >= 0)
@@ -1192,9 +1216,9 @@ inolog("2stime fr=%d\n", std_time.fr);
            case SQL_C_ULONG:
                len = 4;
                if (bind_size > 0)
-                   *((UDWORD *) rgbValueBindRow) = atol(neut_str);
+                   *((UDWORD *) rgbValueBindRow) = ATOI32U(neut_str);
                else
-                   *((UDWORD *) rgbValue + bind_row) = atol(neut_str);
+                   *((UDWORD *) rgbValue + bind_row) = ATOI32U(neut_str);
                break;
 
 #if (ODBCVER >= 0x0300) && defined(ODBCINT64)
@@ -1242,7 +1266,7 @@ inolog("2stime fr=%d\n", std_time.fr);
                /* The following is for SQL_C_VARBOOKMARK */
                else if (PG_TYPE_INT4 == field_type)
                {
-                   UInt4   ival = atol(neut_str);
+                   UInt4   ival = ATOI32U(neut_str);
 
 inolog("SQL_C_VARBOOKMARK value=%d\n", ival);
                    if (pcbValue)
@@ -1818,7 +1842,7 @@ Prepare_and_convert(StatementClass *stmt, QueryParse *qp, QueryBuild *qb)
 
        new_statement = qb->query_statement;
        qb->flags = FLGB_BUILDING_PREPARE_STATEMENT;
-       sprintf(new_statement, "PREPARE _PLAN%0x", stmt);
+       sprintf(new_statement, "PREPARE \"_PLAN%0x\"", stmt);
        qb->npos = strlen(new_statement);
        if (SQL_SUCCESS != PGAPI_NumParams(stmt, &marker_count))
        {
@@ -1854,7 +1878,7 @@ Prepare_and_convert(StatementClass *stmt, QueryParse *qp, QueryBuild *qb)
        CVT_APPEND_CHAR(qb, ';');
        /* build the execute statement */
        exe_statement = malloc(30 + 2 * marker_count);
-       sprintf(exe_statement, "EXECUTE _PLAN%0x", stmt);
+       sprintf(exe_statement, "EXECUTE \"_PLAN%0x\"", stmt);
        if (marker_count > 0)
        {
            elen = strlen(exe_statement);
@@ -2410,7 +2434,9 @@ ResolveNumericParam(const SQL_NUMERIC_STRUCT *ns, char *chrform)
    newlen = 0;
    if (0 == ns->sign)
        chrform[newlen++] = '-';
-   for (i = len - 1; i >= ns->scale; i--)
+   if (i = len - 1, i < ns->scale)
+       i = ns->scale;
+   for (; i >= ns->scale; i--)
        chrform[newlen++] = calv[i] + '0';
    if (ns->scale > 0)
    {
@@ -3875,7 +3901,7 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
            }
        }
 
-       oid = atoi(value);
+       oid = ATOI32U(value);
        stmt->lobj_fd = lo_open(conn, oid, INV_READ);
        if (stmt->lobj_fd < 0)
        {
index 9627a30d9d6053d28e3911b2db5dd9bca71f1796..08451619439aaf0643cdd8309e5bb356b458520c 100644 (file)
@@ -140,6 +140,8 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
            flag |= BIT_PROTOCOL_64;
        else if (strncmp(ci->protocol, PG63, strlen(PG63)) == 0)
            flag |= BIT_PROTOCOL_63;
+       else if (strncmp(ci->protocol, "7.4", 3) == 0)
+           flag |= (BIT_PROTOCOL_63 | BIT_PROTOCOL_64);
        switch (ci->drivers.unknown_sizes)
        {
            case UNKNOWNS_AS_DONTKNOW:
index 5024368f5e2d3d579309a693d1a13a805339dd6f..2e1933de6591eb0ac204c3489a4ce031c313d3e8 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -140,7 +140,7 @@ PGAPI_ExecDirect(
 
    mylog("%s: entering...\n", func);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    /*
diff --git a/info.c b/info.c
index 107de759792393e2916cbc07e9edbed92f958e8a..e0676d55680701182add79056b5f2e55b2c62b7e 100644 (file)
--- a/info.c
+++ b/info.c
@@ -801,7 +801,7 @@ PGAPI_GetTypeInfo(
 
    mylog("%s: entering...fSqlType = %d\n", func, fSqlType);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    stmt->manual_result = TRUE;
@@ -855,7 +855,8 @@ PGAPI_GetTypeInfo(
            for (cnt = 0; cnt < pgtcount; cnt ++)
            {
 
-           row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField));
+           SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+               stmt, "Couldn't alloc row", SQL_ERROR)
 
            /* These values can't be NULL */
            if (1 == cnt)
@@ -895,8 +896,8 @@ inolog("serial in\n");
                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));
+           set_nullfield_int2(&row->tuple[13], pgtype_min_decimal_digits(stmt, pgType));
+           set_nullfield_int2(&row->tuple[14], pgtype_max_decimal_digits(stmt, pgType));
 #if (ODBCVER >=0x0300)
            set_nullfield_int2(&row->tuple[15], pgtype_to_sqldesctype(stmt, pgType, PG_STATIC));
            set_nullfield_int2(&row->tuple[16], pgtype_to_datetime_sub(stmt, pgType));
@@ -1293,7 +1294,7 @@ PGAPI_Tables(
    QResultClass    *res;
    TupleNode  *row;
    HSTMT       htbl_stmt;
-   RETCODE     result;
+   RETCODE     ret = SQL_ERROR, result;
    char       *tableType;
    char        tables_query[INFO_INQUIRY_LEN];
    char        table_name[MAX_INFO_STRING],
@@ -1320,7 +1321,7 @@ PGAPI_Tables(
 
    mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    stmt->manual_result = TRUE;
@@ -1345,24 +1346,27 @@ PGAPI_Tables(
    {
        /* view is represented by its relkind since 7.1 */
        strcpy(tables_query, "select relname, nspname, relkind"
-       " from pg_catalog.pg_class, pg_catalog.pg_namespace");
+       " from pg_catalog.pg_class c, pg_catalog.pg_namespace n");
        strcat(tables_query, " where relkind in ('r', 'v')");
    }
    else if (PG_VERSION_GE(conn, 7.1))
    {
        /* view is represented by its relkind since 7.1 */
        strcpy(tables_query, "select relname, usename, relkind"
-       " from pg_class, pg_user");
+       " from pg_class c, pg_user u");
        strcat(tables_query, " where relkind in ('r', 'v')");
    }
    else
    {
-       strcpy(tables_query, "select relname, usename, relhasrules from pg_class, pg_user");
+       strcpy(tables_query, "select relname, usename, relhasrules from pg_class c, pg_user u");
        strcat(tables_query, " where relkind = 'r'");
    }
 
    if (conn->schema_support)
+   {
        schema_strcat1(tables_query, " and nspname %s '%.*s'", likeeq, szTableOwner, cbTableOwner, szTableName, cbTableName, conn);
+       strcat(tables_query, " and pg_catalog.pg_table_is_visible(c.oid)");
+   }
    else
        my_strcat1(tables_query, " and usename %s '%.*s'", likeeq, szTableOwner, cbTableOwner);
    my_strcat1(tables_query, " and relname %s '%.*s'", likeeq, szTableName, cbTableName);
@@ -1457,7 +1461,7 @@ PGAPI_Tables(
        strcat(tables_query, " and relname !~ '^xinv[0-9]+'");
 
    if (conn->schema_support)
-       strcat(tables_query, " and pg_namespace.oid = relnamespace order by nspname, relname");
+       strcat(tables_query, " and n.oid = relnamespace order by nspname, relname");
    else
        strcat(tables_query, " and usesysid = relowner order by relname");
 
@@ -1465,9 +1469,7 @@ PGAPI_Tables(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_full_error_copy(stmt, htbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
 
 #ifdef UNICODE_SUPPORT
@@ -1479,9 +1481,7 @@ PGAPI_Tables(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, tbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
 
    result = PGAPI_BindCol(htbl_stmt, 2, internal_asis_type,
@@ -1489,26 +1489,20 @@ PGAPI_Tables(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, tbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
    result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
                           relkind_or_hasrules, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, tbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
 
    if (res = QR_Constructor(), !res)
    {
        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Tables result.");
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
    SC_set_Result(stmt, res);
 
@@ -1580,7 +1574,7 @@ PGAPI_Tables(
            (view && show_views) ||
            (regular_table && show_regular_tables))
        {
-           row = (TupleNode *) malloc(sizeof(TupleNode) + (5 - 1) *sizeof(TupleField));
+           SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (5 - 1) * sizeof(TupleField)), stmt, "Couldn't alloc row", SQL_ERROR) 
 
            /*set_tuplefield_string(&row->tuple[0], "");*/
            set_tuplefield_null(&row->tuple[0]);
@@ -1612,25 +1606,29 @@ PGAPI_Tables(
    if (result != SQL_NO_DATA_FOUND)
    {
        SC_full_error_copy(stmt, htbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
+   ret = SQL_SUCCESS;
 
+cleanup:
    /*
     * also, things need to think that this statement is finished so the
     * results can be retrieved.
     */
    stmt->status = STMT_FINISHED;
+   if (SQL_ERROR == ret)
+       SC_log_error(func, "", stmt);
 
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
    SC_set_current_col(stmt, -1);
 
-   PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-   mylog("%s: EXIT,  stmt=%u\n", func, stmt);
-   return SQL_SUCCESS;
+   if (htbl_stmt)
+       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+
+   mylog("%s: EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+   return ret;
 }
 
 
@@ -1717,7 +1715,7 @@ PGAPI_Columns(
                table_name[MAX_INFO_STRING],
                field_name[MAX_INFO_STRING],
                field_type_name[MAX_INFO_STRING];
-   Int2        field_number, sqltype,
+   Int2        field_number, sqltype, concise_type,
                reserved_cols,
                result_cols,
                decimal_digits;
@@ -1727,7 +1725,7 @@ PGAPI_Columns(
                mod_length,
                column_size,
                ordinal;
-   char        useStaticPrecision;
+   char        useStaticPrecision, useStaticScale;
    char        not_null[MAX_INFO_STRING],
                relhasrules[MAX_INFO_STRING], relkind[8];
    BOOL        relisaview;
@@ -1738,7 +1736,7 @@ PGAPI_Columns(
 
    mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    stmt->manual_result = TRUE;
@@ -2012,8 +2010,9 @@ PGAPI_Columns(
        {
            /* For OID fields */
            the_type = PG_TYPE_OID;
-           row = (TupleNode *) malloc(sizeof(TupleNode) +
-                                 (result_cols - 1) *sizeof(TupleField));
+           SC_MALLOC_return_with_error(row, TupleNode,
+            (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+               stmt, "Couldn't alloc row", SQL_ERROR)
 
            set_tuplefield_string(&row->tuple[0], "");
            /* see note in SQLTables() */
@@ -2052,9 +2051,9 @@ PGAPI_Columns(
 
    while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
    {
-       row = (TupleNode *) malloc(sizeof(TupleNode) +
-                                  (result_cols - 1) *sizeof(TupleField));
-
+       SC_MALLOC_return_with_error(row, TupleNode,
+       (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+           stmt, "Couldn't alloc row", SQL_ERROR)
 
        sqltype = SQL_TYPE_NULL;    /* unspecified */
        set_tuplefield_string(&row->tuple[0], "");
@@ -2065,8 +2064,6 @@ PGAPI_Columns(
            set_tuplefield_string(&row->tuple[1], "");
        set_tuplefield_string(&row->tuple[2], table_name);
        set_tuplefield_string(&row->tuple[3], field_name);
-       sqltype = pgtype_to_concise_type(stmt, field_type, -1);
-       set_tuplefield_int2(&row->tuple[4], sqltype);
        set_tuplefield_string(&row->tuple[5], field_type_name);
 
 
@@ -2087,6 +2084,7 @@ PGAPI_Columns(
             table_name, field_name, field_type, field_type_name);
 
        useStaticPrecision = TRUE;
+       useStaticScale = TRUE;
 
        if (field_type == PG_TYPE_NUMERIC)
        {
@@ -2096,6 +2094,7 @@ PGAPI_Columns(
            if (mod_length >= 0)
            {
                useStaticPrecision = FALSE;
+               useStaticScale = FALSE;
 
                column_size = (mod_length >> 16) & 0xffff;
                decimal_digits = mod_length & 0xffff;
@@ -2111,6 +2110,16 @@ PGAPI_Columns(
                set_tuplefield_int4(&row->tuple[reserved_cols], column_size + 2);   /* sign+dec.point */
            }
        }
+       else if ((field_type == PG_TYPE_DATETIME) ||
+           (field_type == PG_TYPE_TIMESTAMP_NO_TMZONE))
+       {
+           if (PG_VERSION_GE(conn, 7.2))
+           {
+               useStaticScale = FALSE;
+
+               set_nullfield_int2(&row->tuple[8], (Int2) mod_length);
+           }
+       }
 
        if ((field_type == PG_TYPE_VARCHAR) ||
            (field_type == PG_TYPE_BPCHAR))
@@ -2132,8 +2141,6 @@ PGAPI_Columns(
 
            set_tuplefield_int4(&row->tuple[6], mod_length);
            set_tuplefield_int4(&row->tuple[7], mod_length);
-           set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
-           set_tuplefield_int2(&row->tuple[13], sqltype);
 #if (ODBCVER >= 0x0300)
            set_tuplefield_int4(&row->tuple[15], pgtype_transfer_octet_length(stmt, field_type, PG_STATIC, PG_STATIC));
 #endif /* ODBCVER */
@@ -2146,18 +2153,23 @@ PGAPI_Columns(
 
            set_tuplefield_int4(&row->tuple[6], pgtype_column_size(stmt, field_type, PG_STATIC, PG_STATIC));
            set_tuplefield_int4(&row->tuple[7], pgtype_buffer_length(stmt, field_type, PG_STATIC, PG_STATIC));
-           set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
 #if (ODBCVER >= 0x0300)
            set_tuplefield_null(&row->tuple[15]);
 #endif /* ODBCVER */
            set_tuplefield_int4(&row->tuple[reserved_cols], pgtype_display_size(stmt, field_type, PG_STATIC, PG_STATIC));
        }
+       if (useStaticScale)
+       {
+           set_nullfield_int2(&row->tuple[8], pgtype_decimal_digits(stmt, field_type, PG_STATIC));
+       }
 
        if (SQL_TYPE_NULL == sqltype)
        {
            sqltype = pgtype_to_concise_type(stmt, field_type, PG_STATIC);
-           set_tuplefield_int2(&row->tuple[13], pgtype_to_sqldesctype(stmt, field_type, PG_STATIC));
+           concise_type = pgtype_to_sqldesctype(stmt, field_type, PG_STATIC);
        }
+       else
+           concise_type = sqltype;
        set_tuplefield_int2(&row->tuple[4], sqltype);
 
        set_nullfield_int2(&row->tuple[9], pgtype_radix(stmt, field_type));
@@ -2165,6 +2177,7 @@ PGAPI_Columns(
        set_tuplefield_string(&row->tuple[11], "");
 #if (ODBCVER >= 0x0300)
        set_tuplefield_null(&row->tuple[12]);
+       set_tuplefield_int2(&row->tuple[13], concise_type);
        set_nullfield_int2(&row->tuple[14], pgtype_to_datetime_sub(stmt, field_type));
        set_tuplefield_int4(&row->tuple[16], ordinal);
        set_tuplefield_null(&row->tuple[17]);
@@ -2194,8 +2207,8 @@ PGAPI_Columns(
        /* For Row Versioning fields */
        the_type = PG_TYPE_INT4;
 
-       row = (TupleNode *) malloc(sizeof(TupleNode) +
-                                  (result_cols - 1) *sizeof(TupleField));
+       SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (result_cols - 1) * sizeof(TupleField)),
+           stmt, "Couldn't alloc row", SQL_ERROR)
 
        set_tuplefield_string(&row->tuple[0], "");
        if (conn->schema_support)
@@ -2274,7 +2287,7 @@ PGAPI_SpecialColumns(
 
    mylog("%s: entering...stmt=%u scnm=%x len=%d colType=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
    conn = SC_get_conn(stmt);
    ci = &(conn->connInfo);
@@ -2393,7 +2406,8 @@ PGAPI_SpecialColumns(
        {
            Int2        the_type = PG_TYPE_TID;
 
-           row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
+           SC_MALLOC_return_with_error(row, TupleNode, (sizeof(TupleNode) + (8 - 1) * sizeof(TupleField)),
+               stmt, "Couldn't alloc row", SQL_ERROR)
 
            set_tuplefield_null(&row->tuple[0]);
            set_tuplefield_string(&row->tuple[1], "ctid");
@@ -2415,7 +2429,8 @@ inolog("Add ctid\n");
        {
            if (relhasoids[0] != '1')
                return SQL_NO_DATA_FOUND;
-           row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
+           SC_MALLOC_return_with_error(row,  TupleNode, (sizeof(TupleNode) + (8 - 1) *sizeof(TupleField)),
+               stmt, "Couldn't alloc row", SQL_ERROR)
 
            set_tuplefield_int2(&row->tuple[0], SQL_SCOPE_SESSION);
            set_tuplefield_string(&row->tuple[1], "oid");
@@ -2435,7 +2450,9 @@ inolog("Add ctid\n");
 
            if (atoi(ci->row_versioning))
            {
-               row = (TupleNode *) malloc(sizeof(TupleNode) + (8 - 1) *sizeof(TupleField));
+               SC_MALLOC_return_with_error(row, TupleNode,
+               (sizeof(TupleNode) + (8 - 1) * sizeof(TupleField)),
+                   stmt, "Couldn't alloc row", SQL_ERROR)
 
                set_tuplefield_null(&row->tuple[0]);
                set_tuplefield_string(&row->tuple[1], "xmin");
@@ -2478,9 +2495,9 @@ PGAPI_Statistics(
    ConnectionClass *conn;
    QResultClass    *res;
    char        index_query[INFO_INQUIRY_LEN];
-   HSTMT       hindx_stmt;
-   RETCODE     result;
-   char       *table_name;
+   HSTMT       hcol_stmt = NULL, hindx_stmt = NULL;
+   RETCODE     ret = SQL_ERROR, result;
+   char        *table_name = NULL;
    char        index_name[MAX_INFO_STRING];
    short       fields_vector[INDEX_KEYS_STORAGE_COUNT];
    char        isunique[10],
@@ -2490,23 +2507,21 @@ PGAPI_Statistics(
                fields_vector_len;
    TupleNode  *row;
    int         i;
-   HSTMT       hcol_stmt;
    StatementClass *col_stmt,
               *indx_stmt;
    char        column_name[MAX_INFO_STRING],
            table_qualifier[MAX_INFO_STRING],
                relhasrules[10], relkind[8];
-   char      **column_names = 0;
+   char      **column_names = NULL;
    SQLINTEGER  column_name_len;
    int         total_columns = 0;
-   char        error = TRUE;
    ConnInfo   *ci;
    char        buf[256];
    SWORD       internal_asis_type = SQL_C_CHAR;
 
    mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    stmt->manual_result = TRUE;
@@ -2574,7 +2589,7 @@ PGAPI_Statistics(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.");
-       goto SEEYA;
+       goto cleanup;
    }
 
    col_stmt = (StatementClass *) hcol_stmt;
@@ -2594,16 +2609,14 @@ PGAPI_Statistics(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, col_stmt);
-       PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
    }
    result = PGAPI_BindCol(hcol_stmt, 4, internal_asis_type,
                         column_name, sizeof(column_name), &column_name_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, col_stmt);
-       PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
 
    }
 
@@ -2615,8 +2628,9 @@ PGAPI_Statistics(
        column_names =
            (char **) realloc(column_names,
                              total_columns * sizeof(char *));
-       column_names[total_columns - 1] =
-           (char *) malloc(strlen(column_name) + 1);
+       SC_MALLOC_return_with_error(column_names[total_columns - 1],
+           char, (strlen(column_name) + 1), stmt, 
+           "Couldn't alloc column_name", SQL_ERROR)
        strcpy(column_names[total_columns - 1], column_name);
 
        mylog("%s: column_name = '%s'\n", func, column_name);
@@ -2624,24 +2638,26 @@ PGAPI_Statistics(
        result = PGAPI_Fetch(hcol_stmt);
    }
 
-   if (result != SQL_NO_DATA_FOUND || total_columns == 0)
+   PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
+   hcol_stmt = NULL;
+   if (result != SQL_NO_DATA_FOUND)
    {
-       SC_full_error_copy(stmt, col_stmt); /* "Couldn't get column
-                                                        * names in
-                                                        * SQLStatistics."; */
-       PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
-       goto SEEYA;
-
+       SC_full_error_copy(stmt, col_stmt);
+       goto cleanup;
+   }
+   if (total_columns == 0)
+   {
+       /* Couldn't get column names in SQLStatistics.; */
+       ret = SQL_SUCCESS;
+       goto cleanup;
    }
-
-   PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
 
    /* get a list of indexes on this table */
    result = PGAPI_AllocStmt(stmt->hdbc, &hindx_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in SQLStatistics for indices.");
-       goto SEEYA;
+       goto cleanup;
 
    }
    indx_stmt = (StatementClass *) hindx_stmt;
@@ -2683,8 +2699,7 @@ PGAPI_Statistics(
         * SQLStatistics.";
         */
        SC_full_error_copy(stmt, indx_stmt);
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
    }
 
    /* bind the index name column */
@@ -2694,8 +2709,7 @@ PGAPI_Statistics(
    {
        SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column 
                        * in SQLStatistics."; */
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
 
    }
    /* bind the vector column */
@@ -2705,8 +2719,7 @@ PGAPI_Statistics(
    {
        SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column 
                         * in SQLStatistics."; */
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
 
    }
    /* bind the "is unique" column */
@@ -2716,8 +2729,7 @@ PGAPI_Statistics(
    {
        SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column 
                         * in SQLStatistics."; */
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
    }
 
    /* bind the "is clustered" column */
@@ -2727,8 +2739,7 @@ PGAPI_Statistics(
    {
        SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column *
                         * in SQLStatistics."; */
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
 
    }
 
@@ -2739,8 +2750,7 @@ PGAPI_Statistics(
    {
        SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column * 
                         * in SQLStatistics."; */
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
 
    }
 
@@ -2749,8 +2759,7 @@ PGAPI_Statistics(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, indx_stmt);
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
    }
 
    relhasrules[0] = '0';
@@ -2860,41 +2869,50 @@ PGAPI_Statistics(
    {
        /* "SQLFetch failed in SQLStatistics."; */
        SC_full_error_copy(stmt, indx_stmt);
-       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-       goto SEEYA;
+       goto cleanup;
    }
 
-   PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
-
    /*
     * also, things need to think that this statement is finished so the
     * results can be retrieved.
     */
    stmt->status = STMT_FINISHED;
 
-   /* set up the current tuple pointer for SQLFetch */
-   stmt->currTuple = -1;
-   stmt->rowset_start = -1;
-   SC_set_current_col(stmt, -1);
+   ret = SQL_SUCCESS;
 
-   error = FALSE;
+cleanup:
+   /*
+    * also, things need to think that this statement is finished so the
+    * results can be retrieved.
+    */
+   stmt->status = STMT_FINISHED;
 
-SEEYA:
+   if (SQL_ERROR == ret)
+       SC_log_error(func, "", stmt);
+   if (hcol_stmt)
+       PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
+   if (hindx_stmt)
+       PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
    /* These things should be freed on any error ALSO! */
-   free(table_name);
-   for (i = 0; i < total_columns; i++)
-       free(column_names[i]);
-   free(column_names);
-
-   mylog("%s: EXIT, %s, stmt=%u\n", func, error ? "error" : "success", stmt);
+   if (table_name)
+       free(table_name);
+   if (column_names)
+   {
+       for (i = 0; i < total_columns; i++)
+           free(column_names[i]);
+       free(column_names);
+   }
 
-   if (error)
+   if (SQL_SUCCESS == ret)
    {
-       SC_log_error(func, "", stmt);
-       return SQL_ERROR;
+       /* set up the current tuple pointer for SQLFetch */
+       stmt->currTuple = -1;
+       stmt->rowset_start = -1;
+       SC_set_current_col(stmt, -1);
    }
-   else
-       return SQL_SUCCESS;
+   mylog("%s: EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+
+   return ret;
 }
 
 
@@ -2918,7 +2936,7 @@ PGAPI_ColumnPrivileges(
 
    /* Neither Access or Borland care about this. */
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
    SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "not implemented");
    SC_log_error(func, "Function not implemented", stmt);
@@ -2946,9 +2964,9 @@ PGAPI_PrimaryKeys(
    QResultClass    *res;
    ConnectionClass *conn;
    TupleNode  *row;
-   RETCODE     result;
+   RETCODE     ret = SQL_ERROR, result;
    int         seq = 0;
-   HSTMT       htbl_stmt;
+   HSTMT       htbl_stmt = NULL;
    StatementClass *tbl_stmt;
    char        tables_query[INFO_INQUIRY_LEN];
    char        attname[MAX_INFO_STRING];
@@ -2962,7 +2980,7 @@ PGAPI_PrimaryKeys(
 
    mylog("%s: entering...stmt=%u scnm=%x len=%d\n", func, stmt, szTableOwner, cbTableOwner);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
    stmt->manual_result = TRUE;
    stmt->errormsg_created = TRUE;
@@ -3013,9 +3031,7 @@ PGAPI_PrimaryKeys(
    if (pktab[0] == '\0')
    {
        SC_set_error(stmt, STMT_INTERNAL_ERROR, "No Table specified to PGAPI_PrimaryKeys.");
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
    pkscm[0] = '\0';
    if (conn->schema_support)
@@ -3026,9 +3042,7 @@ PGAPI_PrimaryKeys(
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
        SC_error_copy(stmt, tbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
 
    if (PG_VERSION_LE(conn, 6.4))
@@ -3111,9 +3125,7 @@ PGAPI_PrimaryKeys(
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_full_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_Fetch(htbl_stmt);
@@ -3149,27 +3161,29 @@ PGAPI_PrimaryKeys(
    if (result != SQL_NO_DATA_FOUND)
    {
        SC_full_error_copy(stmt, htbl_stmt);
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
+   ret = SQL_SUCCESS;
 
-   PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-
-
+cleanup:
    /*
     * also, things need to think that this statement is finished so the
     * results can be retrieved.
     */
    stmt->status = STMT_FINISHED;
 
+   if (SQL_ERROR == ret)
+       SC_log_error(func, "", stmt);
+   if (htbl_stmt)
+       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+
    /* set up the current tuple pointer for SQLFetch */
    stmt->currTuple = -1;
    stmt->rowset_start = -1;
    SC_set_current_col(stmt, -1);
 
-   mylog("%s: EXIT, stmt=%u\n", func, stmt);
-   return SQL_SUCCESS;
+   mylog("%s: EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+   return ret;
 }
 
 
@@ -3423,11 +3437,9 @@ PGAPI_ForeignKeys(
    StatementClass *stmt = (StatementClass *) hstmt;
    QResultClass    *res;
    TupleNode  *row;
-   HSTMT       htbl_stmt,
-               hpkey_stmt;
+   HSTMT       htbl_stmt = NULL, hpkey_stmt = NULL;
    StatementClass *tbl_stmt;
-   RETCODE     result,
-               keyresult;
+   RETCODE     ret = SQL_ERROR, result, keyresult;
    char        tables_query[INFO_INQUIRY_LEN];
    char        trig_deferrable[2];
    char        trig_initdeferred[2];
@@ -3466,7 +3478,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
 
    mylog("%s: entering...stmt=%u\n", func, stmt);
 
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    stmt->manual_result = TRUE;
@@ -3641,9 +3653,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_full_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
@@ -3651,9 +3661,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
@@ -3661,9 +3669,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
@@ -3671,9 +3677,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
@@ -3681,9 +3685,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
@@ -3691,9 +3693,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
@@ -3701,9 +3701,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
@@ -3711,27 +3709,21 @@ char        schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
        result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
                               &relid2, sizeof(relid2), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
        result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
                    pk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        if (conn->schema_support)
@@ -3741,30 +3733,28 @@ char        schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
            if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
            {
                SC_error_copy(stmt, tbl_stmt);
-               SC_log_error(func, "", stmt);
-               PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-               return SQL_ERROR;
+               goto cleanup;
            }
        }
 
        result = PGAPI_Fetch(htbl_stmt);
        if (result == SQL_NO_DATA_FOUND)
-           return SQL_SUCCESS;
+       {
+           ret = SQL_SUCCESS;
+           goto cleanup;
+       }
 
        if (result != SQL_SUCCESS)
        {
            SC_full_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        keyresult = PGAPI_AllocStmt(stmt->hdbc, &hpkey_stmt);
        if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO))
        {
            SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.");
-           SC_log_error(func, "", stmt);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        keyresult = PGAPI_BindCol(hpkey_stmt, 4, internal_asis_type,
@@ -3772,9 +3762,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if (keyresult != SQL_SUCCESS)
        {
            SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.");
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        while (result == SQL_SUCCESS)
@@ -3799,9 +3787,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
            if (keyresult != SQL_SUCCESS)
            {
                SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't get primary keys for PGAPI_ForeignKeys result.");
-               SC_log_error(func, "", stmt);
-               PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
-               return SQL_ERROR;
+               goto cleanup;
            }
 
 
@@ -3925,6 +3911,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
            result = PGAPI_Fetch(htbl_stmt);
        }
        PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
+       hpkey_stmt = NULL;
    }
 
    /*
@@ -4014,9 +4001,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 1, SQL_C_BINARY,
@@ -4024,9 +4009,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 2, SQL_C_SHORT,
@@ -4034,9 +4017,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 3, internal_asis_type,
@@ -4044,9 +4025,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 4, internal_asis_type,
@@ -4054,9 +4033,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 5, internal_asis_type,
@@ -4064,9 +4041,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 6, internal_asis_type,
@@ -4074,9 +4049,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        result = PGAPI_BindCol(htbl_stmt, 7, SQL_C_ULONG,
@@ -4084,27 +4057,21 @@ char        schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
        result = PGAPI_BindCol(htbl_stmt, 8, SQL_C_ULONG,
                        &relid2, sizeof(relid2), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
        result = PGAPI_BindCol(htbl_stmt, 9, internal_asis_type,
                    fk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
            SC_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        if (conn->schema_support)
@@ -4114,22 +4081,21 @@ char        schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
            if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
            {
                SC_error_copy(stmt, tbl_stmt);
-               SC_log_error(func, "", stmt);
-               PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-               return SQL_ERROR;
+               goto cleanup;
            }
        }
 
        result = PGAPI_Fetch(htbl_stmt);
        if (result == SQL_NO_DATA_FOUND)
-           return SQL_SUCCESS;
+       {
+           ret = SQL_SUCCESS;
+           goto cleanup;
+       }
 
        if (result != SQL_SUCCESS)
        {
            SC_full_error_copy(stmt, tbl_stmt);
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           goto cleanup;
        }
 
        while (result == SQL_SUCCESS)
@@ -4240,19 +4206,35 @@ char        schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
    else
    {
        SC_set_error(stmt, STMT_INTERNAL_ERROR, "No tables specified to PGAPI_ForeignKeys.");
-       SC_log_error(func, "", stmt);
-       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-       return SQL_ERROR;
+       goto cleanup;
    }
+   ret = SQL_SUCCESS;
+cleanup:
+   /*
+    * also, things need to think that this statement is finished so the
+    * results can be retrieved.
+    */
+   stmt->status = STMT_FINISHED;
+
+   if (SQL_ERROR == ret)
+       SC_log_error(func, "", stmt);
    if (pkey_alloced)
        free(pkey_text);
    if (fkey_alloced)
        free(fkey_text);
 
-   PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+   if (htbl_stmt)
+       PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
+   if (hpkey_stmt)
+       PGAPI_FreeStmt(hpkey_stmt, SQL_DROP);
 
-   mylog("PGAPI_ForeignKeys(): EXIT, stmt=%u\n", stmt);
-   return SQL_SUCCESS;
+   /* set up the current tuple pointer for SQLFetch */
+   stmt->currTuple = -1;
+   stmt->rowset_start = -1;
+   SC_set_current_col(stmt, -1);
+
+   mylog("%s(): EXIT, stmt=%u, ret=%d\n", func, stmt, ret);
+   return ret;
 }
 
 
@@ -4288,7 +4270,7 @@ PGAPI_ProcedureColumns(
        SC_log_error(func, "Function not implemented", stmt);
        return SQL_ERROR;
    }
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
    if (conn->schema_support)
    {
@@ -4474,7 +4456,7 @@ PGAPI_Procedures(
        SC_log_error(func, "Function not implemented", stmt);
        return SQL_ERROR;
    }
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    /*
@@ -4597,7 +4579,7 @@ PGAPI_TablePrivileges(
    const char *likeeq = "like";
 
    mylog("%s: entering... scnm=%x len-%d\n", func, szTableOwner, cbTableOwner);
-   if (result = SC_initialize_ifclosed(stmt, func), SQL_SUCCESS != result)
+   if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
        return result;
 
    /*
index a760c105d743a45e22338cbfa7ef59bb3e85924f..d191b82bef3958205504728e4b0c82663751489a 100644 (file)
--- a/odbcapi.c
+++ b/odbcapi.c
@@ -110,15 +110,19 @@ SQLColumns(HSTMT StatementHandle,
           SQLCHAR *TableName, SQLSMALLINT NameLength3,
           SQLCHAR *ColumnName, SQLSMALLINT NameLength4)
 {
+   CSTR func = "SQLColumns";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    SQLCHAR *ctName = CatalogName, *scName = SchemaName,
        *tbName = TableName, *clName = ColumnName;
 
-   mylog("[SQLColumns]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_Columns(StatementHandle, ctName, NameLength1,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_Columns(StatementHandle, ctName, NameLength1,
                scName, NameLength2, tbName, NameLength3,
                clName, NameLength4, 0);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
@@ -306,13 +310,17 @@ RETCODE       SQL_API
 SQLExecDirect(HSTMT StatementHandle,
              SQLCHAR *StatementText, SQLINTEGER TextLength)
 {
+   CSTR func = "SQLExecDirect";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
 
-   mylog("[SQLExecDirect]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength, 0);
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength, 0);
    LEAVE_STMT_CS(stmt);
    return ret;
 }
@@ -524,13 +532,17 @@ RETCODE       SQL_API
 SQLGetTypeInfo(HSTMT StatementHandle,
               SQLSMALLINT DataType)
 {
+   CSTR func = "SQLGetTypeInfo";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
 
-   mylog("[SQLGetTypeInfo]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
    LEAVE_STMT_CS(stmt);
    return ret;
 }
@@ -685,14 +697,18 @@ SQLSpecialColumns(HSTMT StatementHandle,
                  SQLSMALLINT NameLength3, SQLUSMALLINT Scope,
                  SQLUSMALLINT Nullable)
 {
+   CSTR func = "SQLSpecialColumns";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
 
-   mylog("[SQLSpecialColumns]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
            NameLength1, scName, NameLength2, tbName, NameLength3,
                            Scope, Nullable);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
@@ -742,14 +758,18 @@ SQLStatistics(HSTMT StatementHandle,
              SQLCHAR *TableName, SQLSMALLINT NameLength3,
              SQLUSMALLINT Unique, SQLUSMALLINT Reserved)
 {
+   CSTR func = "SQLStatistics";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
 
-   mylog("[SQLStatistics]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_Statistics(StatementHandle, ctName, NameLength1,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_Statistics(StatementHandle, ctName, NameLength1,
                 scName, NameLength2, tbName, NameLength3,
                 Unique, Reserved);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
@@ -799,14 +819,18 @@ SQLTables(HSTMT StatementHandle,
          SQLCHAR *TableName, SQLSMALLINT NameLength3,
          SQLCHAR *TableType, SQLSMALLINT NameLength4)
 {
+   CSTR func = "SQLTables";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
    SQLCHAR *ctName = CatalogName, *scName = SchemaName, *tbName = TableName;
 
-   mylog("[SQLTables]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_Tables(StatementHandle, ctName, NameLength1,
                scName, NameLength2, tbName, NameLength3,
                        TableType, NameLength4);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
@@ -904,15 +928,19 @@ SQLColumnPrivileges(
                    SQLCHAR *szColumnName,
                    SQLSMALLINT cbColumnName)
 {
+   CSTR func = "SQLColumnPrivileges";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
        *tbName = szTableName, *clName = szColumnName;
 
-   mylog("[SQLColumnPrivileges]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_ColumnPrivileges(hstmt, ctName, cbCatalogName,
                scName, cbSchemaName, tbName, cbTableName,
                        clName, cbColumnName);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
@@ -1019,16 +1047,20 @@ SQLForeignKeys(
               SQLCHAR *szFkTableName,
               SQLSMALLINT cbFkTableName)
 {
+   CSTR func = "SQLForeignKeys";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *pkctName = szPkCatalogName, *pkscName = szPkSchemaName,
        *pktbName = szPkTableName, *fkctName = szFkCatalogName,
        *fkscName = szFkSchemaName, *fktbName = szFkTableName;
 
-   mylog("[SQLForeignKeys]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_ForeignKeys(hstmt, pkctName, cbPkCatalogName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_ForeignKeys(hstmt, pkctName, cbPkCatalogName,
            pkscName, cbPkSchemaName, pktbName, cbPkTableName,
            fkctName, cbFkCatalogName, fkscName, cbFkSchemaName,
            fktbName, cbFkTableName);
@@ -1173,15 +1205,19 @@ SQLPrimaryKeys(
               SQLCHAR *szTableName,
               SQLSMALLINT cbTableName)
 {
+   CSTR func = "SQLPrimaryKeys";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
        *tbName = szTableName;
 
-   mylog("[SQLPrimaryKeys]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_PrimaryKeys(hstmt, ctName, cbCatalogName,
            scName, cbSchemaName, tbName, cbTableName);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
    {
@@ -1234,15 +1270,19 @@ SQLProcedureColumns(
                    SQLCHAR *szColumnName,
                    SQLSMALLINT cbColumnName)
 {
+   CSTR func = "SQLProcedureColumns";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
        *prName = szProcName, *clName = szColumnName;
 
-   mylog("[SQLProcedureColumns]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_ProcedureColumns(hstmt, ctName, cbCatalogName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_ProcedureColumns(hstmt, ctName, cbCatalogName,
                scName, cbSchemaName, prName, cbProcName,
                    clName, cbColumnName);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
@@ -1302,15 +1342,19 @@ SQLProcedures(
              SQLCHAR *szProcName,
              SQLSMALLINT cbProcName)
 {
+   CSTR func = "SQLProcedures";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
        *prName = szProcName;
 
-   mylog("[SQLProcedures]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_Procedures(hstmt, ctName, cbCatalogName,
                     scName, cbSchemaName, prName, cbProcName);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
    {
@@ -1379,15 +1423,19 @@ SQLTablePrivileges(
                   SQLCHAR *szTableName,
                   SQLSMALLINT cbTableName)
 {
+   CSTR func = "SQLTablePrivileges";
    RETCODE ret;
    StatementClass *stmt = (StatementClass *) hstmt;
    SQLCHAR *ctName = szCatalogName, *scName = szSchemaName,
        *tbName = szTableName;
 
-   mylog("[SQLTablePrivileges]");
+   mylog("[%s]", func);
    ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   ret = PGAPI_TablePrivileges(hstmt, ctName, cbCatalogName,
+   if (SC_opencheck(stmt, func))
+       ret = SQL_ERROR;
+   else
+       ret = PGAPI_TablePrivileges(hstmt, ctName, cbCatalogName,
            scName, cbSchemaName, tbName, cbTableName, 0);
    if (SQL_SUCCESS == ret && 0 == QR_get_num_total_tuples(SC_get_Result(stmt))) 
    {
index b82fcaf5121c70227cc5f36aea46e3c2d15282d2..6ac15a9c1652c5c6564098579dbe7c9ec28c8674 100644 (file)
@@ -306,7 +306,7 @@ RETCODE SQL_API SQLGetDiagFieldW(
    SQLSMALLINT *rgbL, blen, bMax;
         char    *rgbD = NULL;
 
-   mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", fHandleType,
+   mylog("[[SQLGetDiagFieldW]] Handle=(%u,%x) Rec=%d Id=%d\n", fHandleType,
            handle, iRecord, fDiagField);
    switch (fDiagField)
    { 
index 0a8a4d9b4ea3e71de9dc4ac911ee46489f028673..3bf551950f36bf589bd735e37b1be6295b07846d 100644 (file)
--- a/options.c
+++ b/options.c
@@ -249,8 +249,9 @@ set_statement_option(ConnectionClass *conn,
                conn->stmtOptions.use_bookmarks = vParam;
            break;
 
-       case 1227:
-       case 1228:
+       case 1204: /* SQL_COPT_SS_PRESERVE_CURSORS ? */
+       case 1227: /* SQL_SOPT_SS_HIDDEN_COLUMNS ? */
+       case 1228: /* SQL_SOPT_SS_NOBROWSETABLE ? */
            if (stmt)
            {
                SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "The option may be for MS SQL Server(Set)");
index ca634de68e4e3ceb64c33c191d99378341257fea..773982ccc2aacda7046e10ee32fd5675a73a9bd4 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
@@ -755,6 +755,16 @@ getCharColumnSize(StatementClass *stmt, Int4 type, int col, int handle_unknown_s
        return -1;
 }
 
+static Int2
+getTimestampMaxDecimalDigits(StatementClass *stmt, Int4 type)
+{
+   ConnectionClass *conn = SC_get_conn(stmt);
+
+   if (PG_VERSION_LT(conn, 7.2))
+       return 0;
+   return 6;
+}
+
 static Int2
 getTimestampDecimalDigits(StatementClass *stmt, Int4 type, int col)
 {
@@ -1122,6 +1132,64 @@ pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handl
    return -1;
 }
 
+/*
+ * corrsponds to "min_scale" in ODBC 2.x.
+ */
+Int2
+pgtype_min_decimal_digits(StatementClass *stmt, Int4 type)
+{
+   switch (type)
+   {
+       case PG_TYPE_INT2:
+       case PG_TYPE_OID:
+       case PG_TYPE_XID:
+       case PG_TYPE_INT4:
+       case PG_TYPE_INT8:
+       case PG_TYPE_FLOAT4:
+       case PG_TYPE_FLOAT8:
+       case PG_TYPE_MONEY:
+       case PG_TYPE_BOOL:
+       case PG_TYPE_ABSTIME:
+       case PG_TYPE_TIMESTAMP:
+       case PG_TYPE_DATETIME:
+       case PG_TYPE_TIMESTAMP_NO_TMZONE:
+       case PG_TYPE_NUMERIC:
+           return 0;
+       default:
+           return -1;
+   }
+}
+
+/*
+ * corrsponds to "max_scale" in ODBC 2.x.
+ */
+Int2
+pgtype_max_decimal_digits(StatementClass *stmt, Int4 type)
+{
+   switch (type)
+   {
+       case PG_TYPE_INT2:
+       case PG_TYPE_OID:
+       case PG_TYPE_XID:
+       case PG_TYPE_INT4:
+       case PG_TYPE_INT8:
+       case PG_TYPE_FLOAT4:
+       case PG_TYPE_FLOAT8:
+       case PG_TYPE_MONEY:
+       case PG_TYPE_BOOL:
+       case PG_TYPE_ABSTIME:
+       case PG_TYPE_TIMESTAMP:
+           return 0;
+       case PG_TYPE_DATETIME:
+       case PG_TYPE_TIMESTAMP_NO_TMZONE:
+           return getTimestampMaxDecimalDigits(stmt, type);
+       case PG_TYPE_NUMERIC:
+           return 38;
+       default:
+           return -1;
+   }
+}
+
 /*
  * corrsponds to "scale" in ODBC 2.x.
  */
index 1148cb5fc58bc1815e2dba9a65ac22c40d9e647f..140d8933ae426b04500494c4998827fff6b83e73 100644 (file)
--- a/pgtypes.h
+++ b/pgtypes.h
@@ -88,6 +88,8 @@ Int4      pgtype_desclength(StatementClass *stmt, Int4 type, int col, int handle_unk
 Int4       pgtype_transfer_octet_length(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as);
 
 Int2       pgtype_decimal_digits(StatementClass *stmt, Int4 type, int col); /* corresponds to "scale" in ODBC 2.x */
+Int2       pgtype_min_decimal_digits(StatementClass *stmt, Int4 type); /* corresponds to "min_scale" in ODBC 2.x */
+Int2       pgtype_max_decimal_digits(StatementClass *stmt, Int4 type); /* corresponds to "max_scale" in ODBC 2.x */
 Int2       pgtype_scale(StatementClass *stmt, Int4 type, int col); /* ODBC 3.x " */
 Int2       pgtype_radix(StatementClass *stmt, Int4 type);
 Int2       pgtype_nullable(StatementClass *stmt, Int4 type);
index 19c458c505bb2e3632cbe25d1263717c5d9cb47e..72005bf4e6540a19e68fb7c472ecbcdb6bebbd75 100644 (file)
--- a/qresult.c
+++ b/qresult.c
@@ -145,6 +145,8 @@ QR_Constructor()
 void
 QR_Destructor(QResultClass *self)
 {
+   ConnectionClass *conn = self->conn;
+
    if (!self)  return;
    mylog("QResult: in DESTRUCTOR\n");
 
@@ -159,7 +161,7 @@ QR_Destructor(QResultClass *self)
     * If conn is defined, then we may have used "backend_tuples", so in
     * case we need to, free it up.  Also, close the cursor.
     */
-   if (self->conn && self->conn->sock && CC_is_in_trans(self->conn))
+   if (conn && conn->sock && CC_is_in_trans(conn))
    {
        if (!QR_close(self))    /* close the cursor if there is one */
        {
@@ -248,11 +250,10 @@ QR_set_notice(QResultClass *self, const char *msg)
 void
 QR_free_memory(QResultClass *self)
 {
-   register int lf,
-               row;
-   register TupleField *tuple = self->backend_tuples;
-   int         num_backend_rows = self->num_backend_rows;
-   int         num_fields = self->num_fields;
+   int     lf, row;
+   TupleField  *tuple = self->backend_tuples;
+   int     num_backend_rows = self->num_backend_rows;
+   int     num_fields = self->num_fields;
 
    mylog("QResult: free memory in, fcount=%d\n", num_backend_rows);
 
@@ -278,18 +279,30 @@ QR_free_memory(QResultClass *self)
    }
    if (self->keyset)
    {
+       ConnectionClass *conn = self->conn;
+
        free(self->keyset);
        self->keyset = NULL;
        self->count_keyset_allocated = 0;
-       if (self->reload_count > 0 && self->conn)
+       if (self->reload_count > 0 && conn && conn->sock)
        {
-           QResultClass    *res;
-           char        cmd[64];
+           char    plannm[32];
+
+           sprintf(plannm, "_KEYSET_%x", self);
+           if (CC_is_in_error_trans(conn))
+           {
+               CC_mark_a_plan_to_discard(conn, plannm);
+           }
+           else
+           {
+               QResultClass    *res;
+               char        cmd[64];
 
-           sprintf(cmd, "DEALLOCATE \"_KEYSET_%x\"", self);
-           res = CC_send_query(self->conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
-           if (res)
-               QR_Destructor(res);
+               sprintf(cmd, "DEALLOCATE \"%s\"", plannm);
+               res = CC_send_query(conn, cmd, NULL, CLEAR_RESULT_ON_ABORT);
+               if (res)
+                   QR_Destructor(res);
+           }
        }
        self->reload_count = 0;
    }
@@ -386,13 +399,12 @@ QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor)
        self->count_backend_allocated = self->count_keyset_allocated = 0;
        if (self->num_fields > 0)
        {
-           self->backend_tuples = (TupleField *) malloc(self->num_fields * sizeof(TupleField) * tuple_size);
-           if (!self->backend_tuples)
-           {
-               self->status = PGRES_FATAL_ERROR;
-               QR_set_message(self, "Could not get memory for tuple cache.");
-               return FALSE;
-           }
+           QR_MALLOC_return_with_error(self->backend_tuples,
+               TupleField,
+               (self->num_fields * sizeof(TupleField) * tuple_size),
+               self, PGRES_FATAL_ERROR,
+               "Could not get memory for tuple cache.",
+               FALSE)
            self->count_backend_allocated = tuple_size;
        }
        if (self->haskeyset)
@@ -442,29 +454,35 @@ int
 QR_close(QResultClass *self)
 {
    QResultClass *res;
+   ConnectionClass *conn = self->conn;
+   int ret = TRUE;
 
-   if (self->conn && self->cursor && self->conn->connInfo.drivers.use_declarefetch)
+   if (conn && self->cursor && conn->connInfo.drivers.use_declarefetch)
    {
-       char        buf[64];
+       if (!CC_is_in_error_trans(conn))
+       {
+           char        buf[64];
 
-       sprintf(buf, "close %s", self->cursor);
-       mylog("QResult: closing cursor: '%s'\n", buf);
+           sprintf(buf, "close %s", self->cursor);
+           mylog("QResult: closing cursor: '%s'\n", buf);
 
-       res = CC_send_query(self->conn, buf, NULL, CLEAR_RESULT_ON_ABORT);
+           res = CC_send_query(conn, buf, NULL, CLEAR_RESULT_ON_ABORT);
+           if (NULL == res)
+           {
+               QR_set_status(self, PGRES_FATAL_ERROR);
+               QR_set_message(self, "Error closing cursor.");
+               ret = FALSE;
+           }
+           QR_Destructor(res);
+       }
 
        self->inTuples = FALSE;
        self->currTuple = -1;
 
        free(self->cursor);
        self->cursor = NULL;
-
-       if (res == NULL)
-       {
-           self->status = PGRES_FATAL_ERROR;
-           QR_set_message(self, "Error closing cursor.");
-           return FALSE;
-       }
-       QR_Destructor(res);
+       if (!ret)
+           return ret;
 
        /* End the transaction if there are no cursors left on this conn */
        if (CC_is_in_autocommit(self->conn) && CC_cursor_count(self->conn) == 0)
@@ -475,12 +493,12 @@ QR_close(QResultClass *self)
            {
                self->status = PGRES_FATAL_ERROR;
                QR_set_message(self, "Error ending transaction.");
-               return FALSE;
+               ret = FALSE;
            }
        }
    }
 
-   return TRUE;
+   return ret;
 }
 
 
@@ -599,21 +617,18 @@ inolog("clear obsolete %d tuples\n", num_backend_rows);
                self->count_backend_allocated = 0;
                if (self->num_fields > 0)
                {
-                   self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
-                       self->num_fields * sizeof(TupleField) * self->cache_size);
-                   if (!self->backend_tuples)
-                   {
-                       self->status = PGRES_FATAL_ERROR;
-                       QR_set_message(self, "Out of memory while reading tuples.");
-                       return FALSE;
-                   }
+                   QR_REALLOC_return_with_error(self->backend_tuples, TupleField, 
+                       (self->num_fields * sizeof(TupleField) * self->cache_size),
+                       self, "Out of memory while reading tuples.", FALSE)
                    self->count_backend_allocated = self->cache_size;
                }
            }
            if (self->haskeyset && (!self->keyset || self->cache_size > self->count_keyset_allocated))
            {
                self->count_keyset_allocated = 0;
-               self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * self->cache_size); 
+               QR_REALLOC_return_with_error(self->keyset, KeySet,
+                   (sizeof(KeySet) * self->cache_size), 
+                   self, "Out of memory while reading tuples.", FALSE)
                self->count_keyset_allocated = self->cache_size;
            }
            sprintf(fetch, "fetch %d in %s", fetch_size, self->cursor);
@@ -709,14 +724,9 @@ inolog("clear obsolete %d tuples\n", num_backend_rows);
 
                        mylog("REALLOC: old_count = %d, size = %d\n", tuple_size, self->num_fields * sizeof(TupleField) * tuple_size);
                        tuple_size *= 2;
-                       self->backend_tuples = (TupleField *) realloc(self->backend_tuples,
-                           tuple_size * self->num_fields * sizeof(TupleField));
-                       if (!self->backend_tuples)
-                       {
-                           self->status = PGRES_FATAL_ERROR;
-                           QR_set_message(self, "Out of memory while reading tuples.");
-                           return FALSE;
-                       }
+                       QR_REALLOC_return_with_error(self->backend_tuples, TupleField,
+                           (tuple_size * self->num_fields * sizeof(TupleField)),
+                           self, "Out of memory while reading tuples.", FALSE)
                        self->count_backend_allocated = tuple_size;
                    }
                    if (self->haskeyset &&
@@ -724,7 +734,9 @@ inolog("clear obsolete %d tuples\n", num_backend_rows);
                    {
                        int tuple_size = self->count_keyset_allocated;
                        tuple_size *= 2;
-                       self->keyset = (KeySet *) realloc(self->keyset, sizeof(KeySet) * tuple_size);
+                       QR_REALLOC_return_with_error(self->keyset, KeySet,
+                           (sizeof(KeySet) * tuple_size),
+                           self, "Out of memory while reading tuples.", FALSE)
                        self->count_keyset_allocated = tuple_size;
                    }
                }
@@ -875,7 +887,11 @@ QR_read_tuple(QResultClass *self, char binary)
            if (field_lf >= effective_cols)
                buffer = tidoidbuf;
            else
-               buffer = (char *) malloc(len + 1);
+               QR_MALLOC_return_with_error(buffer, char,
+                   (len + 1), self,
+                   PGRES_FATAL_ERROR,
+                   "Couldn't allocate buffer",
+                   FALSE);
            SOCK_get_n_char(sock, buffer, len);
            buffer[len] = '\0';
 
index 9f433e369fc7afcc35c76493194c57d2402c0ec4..0a1a55f5d774b12126fe67b21d397aa5708f06f2 100644 (file)
--- a/qresult.h
+++ b/qresult.h
@@ -110,10 +110,10 @@ struct QResultClass_
 #define QR_set_field_info(self, field_num, name, adtid, adtsize)  (CI_set_field_info(self->fields, field_num, name, adtid, adtsize, -1))
 
 /* status macros */
-#define QR_command_successful(self)            ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR))
+#define QR_command_successful(self)    ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_NONFATAL_ERROR || self->status == PGRES_FATAL_ERROR))
 #define QR_command_maybe_successful(self) ( !(self->status == PGRES_BAD_RESPONSE || self->status == PGRES_FATAL_ERROR))
-#define QR_command_nonfatal(self)          ( self->status == PGRES_NONFATAL_ERROR)
-#define QR_end_tuples(self)                    ( self->status == PGRES_END_TUPLES)
+#define QR_command_nonfatal(self)  ( self->status == PGRES_NONFATAL_ERROR)
+#define QR_end_tuples(self)        ( self->status == PGRES_END_TUPLES)
 #define QR_set_status(self, condition)     ( self->status = condition )
 #define QR_set_aborted(self, aborted_)     ( self->aborted = aborted_)
 #define QR_set_haskeyset(self)     (self->haskeyset = TRUE)
@@ -126,6 +126,34 @@ struct QResultClass_
 
 #define QR_aborted(self)                   (!self || self->aborted)
 
+#define QR_MALLOC_return_with_error(t, tp, s, self, n, m, r) \
+   { \
+       if (t = (tp *) malloc(s), NULL == t) \
+       { \
+           QR_set_status(self, n); \
+           QR_set_message(self, m); \
+           return r; \
+       } \
+   }
+#define QR_REALLOC_return_with_error(t, tp, s, self, m, r) \
+   { \
+       if (t = (tp *) realloc(t, s), NULL == t) \
+       { \
+           QR_set_status(self, PGRES_FATAL_ERROR); \
+           QR_set_message(self, m); \
+           return r; \
+       } \
+   }
+#define QR_MALLOC_exit_if_error(t, tp, s, self, n, m) \
+   { \
+       if (t = (tp *) malloc(s), NULL == t) \
+       { \
+           self->status = n; \
+           QR_set_message(self, m); \
+           goto MALLOC_exit; \
+       } \
+   }
+
 /* Core Functions */
 QResultClass *QR_Constructor(void);
 void       QR_Destructor(QResultClass *self);
index 23cb323f438894f4180c25b85762628e2ab1aae2..43616e3a76c0894dbff7385433f713b862e26327 100644 (file)
--- a/results.c
+++ b/results.c
@@ -736,7 +736,7 @@ inolog("COLUMN_TYPE=%d\n", value);
            value = (fi && !fi->name[0] && !fi->alias[0]) ? SQL_UNNAMED : SQL_NAMED;
            break;
 #endif /* ODBCVER */
-       case 1212:
+       case 1212: /* SQL_CA_SS_COLUMN_KEY ? */
            SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "this request may be for MS SQL Server");
            return SQL_ERROR;
        default:
@@ -1820,9 +1820,15 @@ positioned_load(StatementClass *stmt, UInt4 flag, UInt4 oid, const char *tidval)
 
    len = strlen(stmt->load_statement);
    if (tidval)
-   {
        len += 100;
-       selstr = malloc(len);
+   else if ((flag & USE_INSERTED_TID) != 0)
+       len += 50;
+   else
+       len += 20;
+   SC_MALLOC_return_with_error(selstr, char, len, stmt,
+       "Couldn't alloc selstr", NULL)
+   if (tidval)
+   {
        if (latest)
        {
            if (stmt->ti[0]->schema[0])
@@ -1836,17 +1842,9 @@ positioned_load(StatementClass *stmt, UInt4 flag, UInt4 oid, const char *tidval)
            sprintf(selstr, "%s where ctid = '%s' and oid = %u", stmt->load_statement, tidval, oid); 
    }
    else if ((flag & USE_INSERTED_TID) != 0)
-   {
-       len += 50;
-       selstr = malloc(len);
        sprintf(selstr, "%s where ctid = currtid(0, '(,)') and oid = %u", stmt->load_statement, oid);
-   } 
    else
-   {
-       len += 20;
-       selstr = malloc(len);
        sprintf(selstr, "%s where oid = %u", stmt->load_statement, oid);
-   } 
 
    mylog("selstr=%s\n", selstr);
    qres = CC_send_query(SC_get_conn(stmt), selstr, NULL, CLEAR_RESULT_ON_ABORT);
@@ -1945,7 +1943,7 @@ SC_pos_reload(StatementClass *stmt, UDWORD global_ridx, UWORD *count, BOOL logCh
    return ret;
 }
 
-static const int   ahead_fetch_count = 32;
+static const int   pre_fetch_count = 32;
 static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per_fetch, int limitrow)
 {
    ConnectionClass *conn = SC_get_conn(stmt);
@@ -2040,8 +2038,8 @@ static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per
                        int j;
                        QResultClass    *qres;
 
-                       if (rows_per_fetch >= ahead_fetch_count * 2)
-                           keys_per_fetch = ahead_fetch_count;
+                       if (rows_per_fetch >= pre_fetch_count * 2)
+                           keys_per_fetch = pre_fetch_count;
                        else
                            keys_per_fetch = rows_per_fetch;
                        lodlen = strlen(stmt->load_statement);
@@ -2050,7 +2048,8 @@ static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per
                            3 + 4 * keys_per_fetch + 1
                            + 1 + 2 + lodlen + 20 +
                            4 * keys_per_fetch + 1;
-                       qval = malloc(allen);
+                       SC_MALLOC_return_with_error(qval, char, allen,
+                           stmt, "Couldn't alloc qval", -1)
                        sprintf(qval, "PREPARE \"%s\"", planname);
                        sval = strchr(qval, '\0');
                        for (j = 0; j < keys_per_fetch; j++)
@@ -2074,7 +2073,10 @@ static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per
                        strcpy(sval, ")");
                        qres = CC_send_query(conn, qval, NULL, CLEAR_RESULT_ON_ABORT);
                        if (qres)
+                       {
                            res->reload_count = keys_per_fetch;
+                           QR_Destructor(qres);
+                       }
                        else
                        {
                            SC_set_error(stmt, STMT_EXEC_ERROR, "Prepare for Data Load Error");
@@ -2083,15 +2085,15 @@ static int LoadFromKeyset(StatementClass *stmt, QResultClass * res, int rows_per
                        }
                    }
                    allen = 25 + 23 * keys_per_fetch;
-                   qval = realloc(qval, allen);
                }
                else
                {
-                   keys_per_fetch = ahead_fetch_count;
+                   keys_per_fetch = pre_fetch_count;
                    lodlen = strlen(stmt->load_statement);
                    allen = lodlen + 20 + 23 * keys_per_fetch;
-                   qval = malloc(allen);
                }
+               SC_REALLOC_return_with_error(qval, char, allen,
+                   stmt, "Couldn't alloc qval", -1)
            }
            if (res->reload_count > 0)
            {
@@ -2156,7 +2158,7 @@ SC_pos_reload_needed(StatementClass *stmt, UDWORD flag)
    }
    if (create_from_scratch)
    {
-       rows_per_fetch = ((ahead_fetch_count - 1) / res->rowset_size + 1) * res->rowset_size;
+       rows_per_fetch = ((pre_fetch_count - 1) / res->rowset_size + 1) * res->rowset_size;
        limitrow = RowIdx2GIdx(rows_per_fetch, stmt);
    }
    else
index 1bef35d9b28fb3de957f58929354be7598b50790..1c3801d24bfa0be52ba81e991ca04e734ac9c28d 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -184,6 +184,12 @@ SOCK_connect_to(SocketClass *self, unsigned short port, char *hostname)
 #ifdef HAVE_UNIX_SOCKETS
    {
        un = (struct sockaddr_un *) malloc(sizeof(struct sockaddr_un));
+       if (!un)
+       {
+           self->errornumber = SOCKET_COULD_NOT_CREATE_SOCKET;
+           self->errormsg = "coulnd't allocate memory for un.";
+           return 0;
+       }
        un->sun_family = family = AF_UNIX;
        /* passing NULL means that this only suports the pg default "/tmp" */
        UNIXSOCK_PATH(un, port, ((char *) NULL));
index 2246bc2182640cb1685f3df6e8499f847087fb13..ef4e2466ad4684888e74af49c366cfca358eeb64 100644 (file)
@@ -422,15 +422,26 @@ SC_set_prepared(StatementClass *stmt, BOOL prepared)
    if (!prepared)
    {
        ConnectionClass *conn = SC_get_conn(stmt);
-       if (CONN_CONNECTED == conn->status)
+
+       if (conn && CONN_CONNECTED == conn->status)
        {
-           QResultClass    *res;
-           char dealloc_stmt[128];
+           char    plannm[32];
+
+           sprintf(plannm, "_PLAN%0x", stmt);
+           if (CC_is_in_error_trans(conn))
+           {
+               CC_mark_a_plan_to_discard(conn, plannm);
+           }
+           else
+           {
+               QResultClass    *res;
+               char dealloc_stmt[128];
 
-           sprintf(dealloc_stmt, "DEALLOCATE _PLAN%0x", stmt);
-           res = CC_send_query(conn, dealloc_stmt, NULL, 0);
-           if (res)
-               QR_Destructor(res); 
+               sprintf(dealloc_stmt, "DEALLOCATE \"%s\"", plannm);
+               res = CC_send_query(conn, dealloc_stmt, NULL, 0);
+               if (res)
+                   QR_Destructor(res);
+           } 
        }
    }
    stmt->prepared = prepared;
@@ -457,7 +468,7 @@ SC_initialize_stmts(StatementClass *self, BOOL initializeOriginal)
            self->execute_statement = NULL;
        }
        self->prepare = FALSE;
-       SC_set_prepared(self,FALSE);
+       SC_set_prepared(self, FALSE);
        self->statement_type = STMT_TYPE_UNKNOWN;
    }
    if (self->stmt_with_params)
@@ -474,38 +485,31 @@ SC_initialize_stmts(StatementClass *self, BOOL initializeOriginal)
    return 0;
 }
 
-BOOL   SC_is_open(const StatementClass *self)
+BOOL   SC_opencheck(StatementClass *self, const char *func)
 {
    QResultClass    *res;
 
+   if (self->status == STMT_EXECUTING)
+   {
+       SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
+       return TRUE;
+   }
    if (res = SC_get_Curres(self), NULL != res)
    {
        if (res->backend_tuples)
+       {
+           SC_set_error(self, STMT_SEQUENCE_ERROR, "The cursor is open.");
+           SC_log_error(func, "", self);
            return TRUE;
+       }
    }
 
    return  FALSE;
 }
 
 RETCODE
-SC_initialize_ifclosed(StatementClass *self, const char *func)
+SC_initialize_and_recycle(StatementClass *self)
 {
-   if (!self)
-   {
-       SC_log_error(func, "", NULL);
-       return SQL_INVALID_HANDLE;
-   }
-   if (self->status == STMT_EXECUTING)
-   {
-       SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
-       return FALSE;
-   }
-   if (SC_is_open(self))
-   {
-       SC_set_error(self, STMT_INVALID_CURSOR_STATE_ERROR, "The cursor is open");
-       SC_log_error(func, "", self);
-       return SQL_ERROR;
-   }
    SC_initialize_stmts(self, TRUE);
    if (!SC_recycle_statement(self))
        return SQL_ERROR;
@@ -1031,6 +1035,7 @@ SC_fetch(StatementClass *self)
    return result;
 }
 
+#define    return  DONT_CALL_RETURN_FROM_HERE???
 
 RETCODE
 SC_execute(StatementClass *self)
@@ -1046,7 +1051,7 @@ SC_execute(StatementClass *self)
    ConnInfo   *ci;
    UDWORD      qflag = 0;
    BOOL        auto_begin = FALSE, is_in_trans;
-   int     entered;
+   int     func_cs_count = 0;
 
 
    conn = SC_get_conn(self);
@@ -1062,13 +1067,12 @@ SC_execute(StatementClass *self)
     * 2) we are in autocommit off state and the statement isn't of type
     * OTHER.
     */
-   ENTER_INNER_CONN_CS(conn, entered);
+   ENTER_INNER_CONN_CS(conn, func_cs_count);
    if (CONN_EXECUTING == conn->status)
    {
        SC_set_error(self, STMT_SEQUENCE_ERROR, "Connection is already in use.");
-       SC_log_error(func, "", self);
        mylog("%s: problem with connection\n", func);
-       RETURN_AFTER_LEAVE_CS(entered, conn, SQL_ERROR);
+       goto cleanup;
    }
    is_in_trans = CC_is_in_trans(conn);
    if (!self->internal && !is_in_trans &&
@@ -1082,8 +1086,7 @@ SC_execute(StatementClass *self)
                 else if (!CC_begin(conn))
                 {
            SC_set_error(self, STMT_EXEC_ERROR, "Could not begin a transaction");
-                        SC_log_error(func, "", self);
-                        RETURN_AFTER_LEAVE_CS(entered, conn, SQL_ERROR);
+           goto cleanup;
                 }
    }
 
@@ -1161,7 +1164,7 @@ SC_execute(StatementClass *self)
    if (CONN_DOWN != conn->status)
        conn->status = oldstatus;
    self->status = STMT_FINISHED;
-   LEAVE_INNER_CONN_CS(entered, conn);
+   LEAVE_INNER_CONN_CS(func_cs_count, conn);
 
    /* Check the status of the result */
    if (res)
@@ -1203,8 +1206,7 @@ SC_execute(StatementClass *self)
                {
                    QR_Destructor(res);
                    SC_set_error(self, STMT_NO_MEMORY_ERROR,"Could not get enough free memory to store the binding information");
-                   SC_log_error(func, "", self);
-                   return SQL_ERROR;
+                   goto cleanup;
                }
            }
        }
@@ -1270,6 +1272,9 @@ SC_execute(StatementClass *self)
            SC_set_error(self, STMT_EXEC_ERROR, "SC_fetch to get a Procedure return failed.");
        }
    }
+#undef return
+cleanup:
+   CLEANUP_FUNC_CONN_CS(func_cs_count, conn);
    if (SC_get_errornumber(self) == STMT_OK)
        return SQL_SUCCESS;
    else if (SC_get_errornumber(self) == STMT_INFO_ONLY)
@@ -1288,9 +1293,10 @@ int enqueueNeedDataCallback(StatementClass *stmt, NeedDataCallfunc func, void *d
 {
    if (stmt->num_callbacks >= stmt->allocated_callbacks)
    {
-       stmt->callbacks = (NeedDataCallback *) realloc(stmt->callbacks,
+       SC_REALLOC_return_with_error(stmt->callbacks, NeedDataCallback,
            sizeof(NeedDataCallback) * (stmt->allocated_callbacks +
-               CALLBACK_ALLOC_ONCE));
+               CALLBACK_ALLOC_ONCE), stmt,
+            "Couldn't alloc callbacks", -1) 
        stmt->allocated_callbacks += CALLBACK_ALLOC_ONCE;
    }
    stmt->callbacks[stmt->num_callbacks].func = func;
index 0f9f494a09273c01551d097cea8fdf48ef47c85a..04588a37eef6681b6957848c6b0f0f4ce9129c12 100644 (file)
@@ -263,6 +263,23 @@ struct StatementClass_
 #define    SC_is_lower_case(a, b) (b->connInfo.lower_case_identifier)
 #endif /* ODBCVER */
 
+#define    SC_MALLOC_return_with_error(t, tp, s, a, m, r) \
+   { \
+       if (t = (tp *) malloc(s), NULL == t) \
+       { \
+           SC_set_error(a, STMT_NO_MEMORY_ERROR, m); \
+           return r; \
+       } \
+   }
+#define    SC_REALLOC_return_with_error(t, tp, s, a, m, r) \
+   { \
+       if (t = (tp *) realloc(t, s), NULL == t) \
+       { \
+           SC_set_error(a, STMT_NO_MEMORY_ERROR, m); \
+           return r; \
+       } \
+   }
+
 /* options for SC_free_params() */
 #define STMT_FREE_PARAMS_ALL               0
 #define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
@@ -299,8 +316,8 @@ struct StatementClass_
 StatementClass *SC_Constructor(void);
 void       InitializeStatementOptions(StatementOptions *opt);
 char       SC_Destructor(StatementClass *self);
-BOOL       SC_is_open(const StatementClass *self);
-RETCODE        SC_initialize_ifclosed(StatementClass *self, const char *func);
+BOOL       SC_opencheck(StatementClass *self, const char *func);
+RETCODE        SC_initialize_and_recycle(StatementClass *self);
 int        statement_type(const char *statement);
 char       parse_statement(StatementClass *stmt);
 void       SC_pre_execute(StatementClass *self);
index 800ab3cdd0ce81e4b5230d05aa0ce9c06bec5988..bfe57ee2378d00c532037619911ad5e432a20c91 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,8 +9,8 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "07.03.0205"
-#define POSTGRES_RESOURCE_VERSION  "07.03.0205\0"
-#define PG_DRVFILE_VERSION     7,3,2,05
+#define POSTGRESDRIVERVERSION      "07.03.0207"
+#define POSTGRES_RESOURCE_VERSION  "07.03.0207\0"
+#define PG_DRVFILE_VERSION     7,3,2,07
 
 #endif
index a106ef187254345dff5c4c1c134b744f5b694569..e3ab7f8ec899289cf7dc477e045d0ca66e1d872c 100644 (file)
@@ -94,7 +94,7 @@ UInt4 utf8_to_ucs2_lf(const char *utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *ucs
    const UCHAR *str;
 
 /*mylog("utf8_to_ucs2 ilen=%d bufcount=%d", ilen, bufcount);*/
-   if (!utf8str || !ilen)
+   if (!utf8str)
        return 0;
 /*mylog(" string=%s\n", utf8str);*/
    if (!bufcount)
@@ -146,7 +146,7 @@ UInt4   utf8_to_ucs2_lf(const char *utf8str, Int4 ilen, BOOL lfconv, SQLWCHAR *ucs
            str += 2;
        }
    }
-   if (ocount && ocount < bufcount && ucs2str)
+   if (ocount < bufcount && ucs2str)
        ucs2str[ocount] = 0;
 /*mylog(" ocount=%d\n", ocount);*/
    return ocount;