1) Removed most static variables for thread safety.
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 23 Sep 2002 08:08:22 +0000 (08:08 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 23 Sep 2002 08:08:22 +0000 (08:08 +0000)
2) Trial implementation of the thread safe driver under
   Windows.
3)  Fix a bug about DSN options setting.
4)  Fix a bug about Driver options setting.
5) Implement SQLProcedureColumns().
6) Changed default numeric precision/scale.
7) Fix some memory leaks in Unicode driver.
8) datetime -> timestamp with time zone since 7.0.
9) Change manually started(using begin) transactions never
   be implicitly committed.

32 files changed:
bind.c
connection.c
connection.h
convert.c
descriptor.h
dlg_specific.h
dlg_wingui.c
drvconn.c
environ.c
environ.h
execute.c
info.c
info30.c
misc.c
misc.h
multibyte.c
odbcapi.c
odbcapi30.c
odbcapi30w.c
odbcapiw.c
options.c
parse.c
pgapi30.c
pgtypes.c
psqlodbc.c
psqlodbc.h
qresult.c
qresult.h
results.c
statement.c
statement.h
version.h

diff --git a/bind.c b/bind.c
index e6deedaa8b6b8107ce20d9c8d01b7bfac9ec0a58..46a646e41fa538fab42cb3a859243403766cfb9d 100644 (file)
--- a/bind.c
+++ b/bind.c
@@ -153,8 +153,7 @@ PGAPI_BindCol(
    opts = SC_get_ARD(stmt);
    if (stmt->status == STMT_EXECUTING)
    {
-       stmt->errormsg = "Can't bind columns while statement is still executing.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't bind columns while statement is still executing.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -180,9 +179,8 @@ PGAPI_BindCol(
 #endif /* ODBCVER */
                    break;
                default:
-                   stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
+                   SC_set_error(stmt, STMT_PROGRAM_TYPE_OUT_OF_RANGE, "Column 0 is not of type SQL_C_BOOKMARK");
 inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
-                   stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
                    SC_log_error(func, "", stmt);
                    return SQL_ERROR;
            }
@@ -204,8 +202,7 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
    /* check to see if the bindings were allocated */
    if (!opts->bindings)
    {
-       stmt->errormsg = "Could not allocate memory for bindings.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Could not allocate memory for bindings.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -285,8 +282,7 @@ PGAPI_DescribeParam(
    opts = SC_get_APD(stmt);
    if ((ipar < 1) || (ipar > opts->allocated))
    {
-       stmt->errormsg = "Invalid parameter number for PGAPI_DescribeParam.";
-       stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
+       SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_DescribeParam.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -374,8 +370,7 @@ PGAPI_NumParams(
    if (!stmt->statement)
    {
        /* no statement has been allocated */
-       stmt->errormsg = "PGAPI_NumParams called with no statement ready.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "PGAPI_NumParams called with no statement ready.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
index ee3edc0e869f10dceabc1a2b539d11efe0e27b2a..0cf0d723cf1003e79793d9601afc986762369973 100644 (file)
@@ -181,8 +181,7 @@ PGAPI_Disconnect(
 
    if (conn->status == CONN_EXECUTING)
    {
-       conn->errornumber = CONN_IN_USE;
-       conn->errormsg = "A transaction is currently being executed";
+       CC_set_error(conn, CONN_IN_USE, "A transaction is currently being executed");
        CC_log_error(func, "", conn);
        return SQL_ERROR;
    }
@@ -219,8 +218,7 @@ PGAPI_FreeConnect(
    /* Remove the connection from the environment */
    if (!EN_remove_connection(conn->henv, conn))
    {
-       conn->errornumber = CONN_IN_USE;
-       conn->errormsg = "A transaction is currently being executed";
+       CC_set_error(conn, CONN_IN_USE, "A transaction is currently being executed");
        CC_log_error(func, "", conn);
        return SQL_ERROR;
    }
@@ -258,8 +256,8 @@ CC_Constructor()
    {
        rv->henv = NULL;        /* not yet associated with an environment */
 
-       rv->errormsg = NULL;
-       rv->errornumber = 0;
+       rv->__error_message = NULL;
+       rv->__error_number = 0;
        rv->errormsg_created = FALSE;
 
        rv->status = CONN_NOT_CONNECTED;
@@ -309,6 +307,7 @@ CC_Constructor()
        InitializeStatementOptions(&rv->stmtOptions);
        InitializeARDFields(&rv->ardOptions);
        InitializeAPDFields(&rv->apdOptions);
+       INIT_CONN_CS(rv);
    }
    return rv;
 }
@@ -334,6 +333,9 @@ CC_Destructor(ConnectionClass *self)
    }
    mylog("after free statement holders\n");
 
+   if (self->__error_message)
+       free(self->__error_message);
+   DELETE_CONN_CS(self);
    free(self);
 
    mylog("exit CC_Destructor\n");
@@ -368,8 +370,10 @@ CC_cursor_count(ConnectionClass *self)
 void
 CC_clear_error(ConnectionClass *self)
 {
-   self->errornumber = 0;
-   self->errormsg = NULL;
+   self->__error_number = 0;
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_message = NULL;
    self->errormsg_created = FALSE;
 }
 
@@ -552,8 +556,7 @@ CC_set_translation(ConnectionClass *self)
 
    if (self->translation_handle == NULL)
    {
-       self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
-       self->errormsg = "Could not load the translation DLL.";
+       CC_set_error(self, CONN_UNABLE_TO_LOAD_DLL, "Could not load the translation DLL.");
        return FALSE;
    }
 
@@ -567,8 +570,7 @@ CC_set_translation(ConnectionClass *self)
 
    if (self->DataSourceToDriver == NULL || self->DriverToDataSource == NULL)
    {
-       self->errornumber = CONN_UNABLE_TO_LOAD_DLL;
-       self->errormsg = "Could not find translation DLL functions.";
+       CC_set_error(self, CONN_UNABLE_TO_LOAD_DLL, "Could not find translation DLL functions.");
        return FALSE;
    }
 #endif
@@ -618,7 +620,7 @@ CC_connect(ConnectionClass *self, char password_req, char *salt_para)
    ConnInfo   *ci = &(self->connInfo);
    int         areq = -1;
    int         beresp;
-   static char     msgbuffer[ERROR_MSG_LENGTH];
+   char        msgbuffer[ERROR_MSG_LENGTH];
    char        salt[5], notice[512];
    static char *func = "CC_connect";
 
@@ -676,15 +678,13 @@ CC_connect(ConnectionClass *self, char password_req, char *salt_para)
 
        if (self->status != CONN_NOT_CONNECTED)
        {
-           self->errormsg = "Already connected.";
-           self->errornumber = CONN_OPENDB_ERROR;
+           CC_set_error(self, CONN_OPENDB_ERROR, "Already connected.");
            return 0;
        }
 
        if (ci->server[0] == '\0' || ci->port[0] == '\0' || ci->database[0] == '\0')
        {
-           self->errornumber = CONN_INIREAD_ERROR;
-           self->errormsg = "Missing server name, port, or database name in call to CC_connect.";
+           CC_set_error(self, CONN_INIREAD_ERROR, "Missing server name, port, or database name in call to CC_connect.");
            return 0;
        }
 
@@ -701,8 +701,7 @@ another_version_retry:
            self->sock = SOCK_Constructor(self);
            if (!self->sock)
            {
-               self->errornumber = CONNECTION_SERVER_NOT_REACHED;
-               self->errormsg = "Could not open a socket to the server";
+               CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not open a socket to the server");
                return 0;
            }
        }
@@ -715,8 +714,7 @@ another_version_retry:
        if (SOCK_get_errcode(sock) != 0)
        {
            mylog("connection to the server socket failed.\n");
-           self->errornumber = CONNECTION_SERVER_NOT_REACHED;
-           self->errormsg = "Could not connect to the server";
+           CC_set_error(self, CONNECTION_SERVER_NOT_REACHED, "Could not connect to the server");
            return 0;
        }
        mylog("connection to the server socket succeeded.\n");
@@ -760,8 +758,7 @@ another_version_retry:
        if (sock->errornumber != 0)
        {
            mylog("couldn't send the authentication block properly.\n");
-           self->errornumber = CONN_INVALID_AUTHENTICATION;
-           self->errormsg = "Sending the authentication packet failed";
+           CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Sending the authentication packet failed");
            return 0;
        }
        mylog("sent the authentication block successfully.\n");
@@ -795,9 +792,8 @@ another_version_retry:
                case 'E':
 
                    SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-                   self->errornumber = CONN_INVALID_AUTHENTICATION;
-                   self->errormsg = msgbuffer;
-                   qlog("ERROR from backend during authentication: '%s'\n", self->errormsg);
+                   CC_set_error(self, CONN_INVALID_AUTHENTICATION, msgbuffer);
+                   qlog("ERROR from backend during authentication: '%s'\n", msgbuffer);
                    if (strncmp(msgbuffer, "Unsupported frontend protocol", 29) == 0)
                    {           /* retry older version */
                        if (PROTOCOL_63(ci))
@@ -838,13 +834,11 @@ another_version_retry:
                            break;
 
                        case AUTH_REQ_KRB4:
-                           self->errormsg = "Kerberos 4 authentication not supported";
-                           self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 4 authentication not supported");
                            return 0;
 
                        case AUTH_REQ_KRB5:
-                           self->errormsg = "Kerberos 5 authentication not supported";
-                           self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Kerberos 5 authentication not supported");
                            return 0;
 
                        case AUTH_REQ_PASSWORD:
@@ -852,8 +846,7 @@ another_version_retry:
 
                            if (ci->password[0] == '\0')
                            {
-                               self->errornumber = CONNECTION_NEED_PASSWORD;
-                               self->errormsg = "A password is required for this connection.";
+                               CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.");
                                return -areq;       /* need password */
                            }
 
@@ -867,35 +860,30 @@ another_version_retry:
                            break;
 
                        case AUTH_REQ_CRYPT:
-                           self->errormsg = "Password crypt authentication not supported";
-                           self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Password crypt authentication not supported");
                            return 0;
                        case AUTH_REQ_MD5:
                            mylog("in AUTH_REQ_MD5\n");
                            if (ci->password[0] == '\0')
                            {
-                               self->errornumber = CONNECTION_NEED_PASSWORD;
-                               self->errormsg = "A password is required for this connection.";
+                               CC_set_error(self, CONNECTION_NEED_PASSWORD, "A password is required for this connection.");
                                if (salt_para)
                                    memcpy(salt_para, salt, sizeof(salt));
                                return -areq; /* need password */
                            }
                            if (md5_auth_send(self, salt))
                            {
-                               self->errormsg = "md5 hashing failed";
-                               self->errornumber = CONN_INVALID_AUTHENTICATION;
+                               CC_set_error(self, CONN_INVALID_AUTHENTICATION, "md5 hashing failed");
                                return 0;
                            }
                            break;
 
                        case AUTH_REQ_SCM_CREDS:
-                           self->errormsg = "Unix socket credential authentication not supported";
-                           self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unix socket credential authentication not supported");
                            return 0;
 
                        default:
-                           self->errormsg = "Unknown authentication type";
-                           self->errornumber = CONN_AUTH_TYPE_UNSUPPORTED;
+                           CC_set_error(self, CONN_AUTH_TYPE_UNSUPPORTED, "Unknown authentication type");
                            return 0;
                    }
                    break;
@@ -911,8 +899,7 @@ another_version_retry:
                    while (SOCK_get_string(sock, notice, sizeof(notice) - 1)) ;
                    break;
                default:
-                   self->errormsg = "Unexpected protocol character during authentication";
-                   self->errornumber = CONN_INVALID_AUTHENTICATION;
+                   CC_set_error(self, CONN_INVALID_AUTHENTICATION, "Unexpected protocol character during authentication");
                    return 0;
            }
 
@@ -937,8 +924,7 @@ another_version_retry:
    if (res == NULL || QR_get_status(res) != PGRES_EMPTY_QUERY)
    {
        mylog("got no result from the empty query.  (probably database does not exist)\n");
-       self->errornumber = CONNECTION_NO_SUCH_DATABASE;
-       self->errormsg = "The database does not exist on the server\nor user authentication failed.";
+       CC_set_error(self, CONNECTION_NO_SUCH_DATABASE, "The database does not exist on the server\nor user authentication failed.");
        if (res != NULL)
            QR_Destructor(res);
        return 0;
@@ -978,7 +964,7 @@ another_version_retry:
    if (PG_VERSION_GE(self, 6.4))
    {
        CC_lookup_characterset(self);
-       if (self->errornumber != 0)
+       if (CC_get_errornumber(self) != 0)
            return 0;
 #ifdef UNICODE_SUPPORT
        if (self->unicode)
@@ -989,8 +975,7 @@ another_version_retry:
                QResultClass    *res;
                if (PG_VERSION_LT(self, 7.1))
                {
-                   self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
-                   self->errormsg = "UTF-8 conversion isn't implemented before 7.1";
+                   CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "UTF-8 conversion isn't implemented before 7.1");
                    return 0;
                }
                if (self->client_encoding)
@@ -1013,8 +998,7 @@ another_version_retry:
 #ifdef UNICODE_SUPPORT
    else if (self->unicode)
    {
-       self->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
-       self->errormsg = "Unicode isn't supported before 6.4";
+       CC_set_error(self, CONN_NOT_IMPLEMENTED_ERROR, "Unicode isn't supported before 6.4");
        return 0;
    }
 #endif /* UNICODE_SUPPORT */
@@ -1096,14 +1080,14 @@ CC_create_errormsg(ConnectionClass *self)
 {
    SocketClass *sock = self->sock;
    int         pos;
-   static char msg[4096];
+   char     msg[4096];
 
    mylog("enter CC_create_errormsg\n");
 
    msg[0] = '\0';
 
-   if (self->errormsg)
-       strcpy(msg, self->errormsg);
+   if (CC_get_errormsg(self))
+       strncpy(msg, CC_get_errormsg(self), sizeof(msg));
 
    mylog("msg = '%s'\n", msg);
 
@@ -1114,7 +1098,26 @@ CC_create_errormsg(ConnectionClass *self)
    }
 
    mylog("exit CC_create_errormsg\n");
-   return msg;
+   return msg ? strdup(msg) : NULL;
+}
+
+
+void
+CC_set_error(ConnectionClass *self, int number, const char *message)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_number = number;
+   self->__error_message = message ? strdup(message) : NULL;
+}
+
+
+void
+CC_set_errormsg(ConnectionClass *self, const char *message)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_message = message ? strdup(message) : NULL;
 }
 
 
@@ -1122,24 +1125,28 @@ char
 CC_get_error(ConnectionClass *self, int *number, char **message)
 {
    int         rv;
+   char *msgcrt;
 
    mylog("enter CC_get_error\n");
 
    /* Create a very informative errormsg if it hasn't been done yet. */
    if (!self->errormsg_created)
    {
-       self->errormsg = CC_create_errormsg(self);
+       msgcrt = CC_create_errormsg(self);
+       if (self->__error_message)
+           free(self->__error_message);
+       self->__error_message = msgcrt;
        self->errormsg_created = TRUE;
    }
 
-   if (self->errornumber)
+   if (CC_get_errornumber(self))
    {
-       *number = self->errornumber;
-       *message = self->errormsg;
+       *number = CC_get_errornumber(self);
+       *message = CC_get_errormsg(self);
    }
-   rv = (self->errornumber != 0);
+   rv = (CC_get_errornumber(self) != 0);
 
-   self->errornumber = 0;      /* clear the error */
+   self->__error_number = 0;       /* clear the error */
 
    mylog("exit CC_get_error\n");
 
@@ -1156,6 +1163,7 @@ void  CC_on_commit(ConnectionClass *conn)
            ProcessRollback(conn, FALSE);
 #endif /* DRIVER_CURSOR_IMPLEMENT */
        CC_set_no_trans(conn);
+       CC_set_no_manual_trans(conn);
    }
    conn->result_uncommitted = 0;
 }
@@ -1168,7 +1176,10 @@ void CC_on_abort(ConnectionClass *conn, UDWORD opt)
            ProcessRollback(conn, TRUE);
 #endif /* DRIVER_CURSOR_IMPLEMENT */
        if (0 != (opt & NO_TRANS))
+       {
            CC_set_no_trans(conn);
+           CC_set_no_manual_trans(conn);
+       }
    }
    if (0 != (opt & CONN_DEAD))
        conn->status = CONN_DOWN;
@@ -1207,7 +1218,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
    UDWORD      abort_opt;
 
    /* ERROR_MSG_LENGTH is suffcient */
-   static char msgbuffer[ERROR_MSG_LENGTH + 1];
+   char msgbuffer[ERROR_MSG_LENGTH + 1];
 
    /* QR_set_command() dups this string so doesn't need static */
    char        cmdbuffer[ERROR_MSG_LENGTH + 1];
@@ -1219,8 +1230,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
    maxlen = CC_get_max_query_len(self);
    if (maxlen > 0 && maxlen < (int) strlen(query) + 1)
    {
-       self->errornumber = CONNECTION_MSG_TOO_LONG;
-       self->errormsg = "Query string is too long";
+       CC_set_error(self, CONNECTION_MSG_TOO_LONG, "Query string is too long");
        return NULL;
    }
 
@@ -1229,8 +1239,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
 
    if (SOCK_get_errcode(sock) != 0)
    {
-       self->errornumber = CONNECTION_COULD_NOT_SEND;
-       self->errormsg = "Could not send Query to backend";
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
        return NULL;
    }
@@ -1238,21 +1247,19 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
    SOCK_put_char(sock, 'Q');
    if (SOCK_get_errcode(sock) != 0)
    {
-       self->errornumber = CONNECTION_COULD_NOT_SEND;
-       self->errormsg = "Could not send Query to backend";
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
        return NULL;
    }
 
    if (issue_begin)
-       SOCK_put_n_char(sock, "begin;", 6);
+       SOCK_put_n_char(sock, "BEGIN;", 6);
    SOCK_put_string(sock, query);
    SOCK_flush_output(sock);
 
    if (SOCK_get_errcode(sock) != 0)
    {
-       self->errornumber = CONNECTION_COULD_NOT_SEND;
-       self->errormsg = "Could not send Query to backend";
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send Query to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
        return NULL;
    }
@@ -1273,8 +1280,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
        cmdres = QR_Constructor();
        if (!cmdres)
        {
-           self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
-           self->errormsg = "Could not create result info in send_query.";
+           CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
            return NULL;
        }
    }
@@ -1286,10 +1292,9 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
 
        if ((SOCK_get_errcode(sock) != 0) || (id == EOF))
        {
-           self->errornumber = CONNECTION_NO_RESPONSE;
-           self->errormsg = "No response from the backend";
+           CC_set_error(self, CONNECTION_NO_RESPONSE, "No response from the backend");
 
-           mylog("send_query: 'id' - %s\n", self->errormsg);
+           mylog("send_query: 'id' - %s\n", CC_get_errormsg(self));
            CC_on_abort(self, NO_TRANS | CONN_DEAD);
            ReadyToReturn = TRUE;
            retres = NULL;
@@ -1311,9 +1316,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                SOCK_get_string(sock, cmdbuffer, ERROR_MSG_LENGTH);
                if (SOCK_get_errcode(sock) != 0)
                {
-                   self->errornumber = CONNECTION_NO_RESPONSE;
-                   self->errormsg = "No response from backend while receiving a portal query command";
-                   mylog("send_query: 'C' - %s\n", self->errormsg);
+                   CC_set_error(self, CONNECTION_NO_RESPONSE, "No response from backend while receiving a portal query command");
+                   mylog("send_query: 'C' - %s\n", CC_get_errormsg(self));
                    CC_on_abort(self, NO_TRANS | CONN_DEAD);
                    ReadyToReturn = TRUE;
                    retres = NULL;
@@ -1409,7 +1413,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                swallow = SOCK_get_char(sock);
                if ((swallow != '\0') || SOCK_get_errcode(sock) != 0)
                {
-                   self->errornumber = CONNECTION_BACKEND_CRAZY;
+                   CC_set_errornumber(self, CONNECTION_BACKEND_CRAZY);
                    QR_set_message(res, "Unexpected protocol character from backend (send_query - I)");
                    QR_set_status(res, PGRES_FATAL_ERROR);
                    ReadyToReturn = TRUE;
@@ -1442,11 +1446,11 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                abort_opt = 0;
                if (!strncmp(msgbuffer, "FATAL", 5))
                {
-                   self->errornumber = CONNECTION_SERVER_REPORTED_ERROR;
+                   CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_ERROR);
                    abort_opt = NO_TRANS | CONN_DEAD;
                }
                else
-                   self->errornumber = CONNECTION_SERVER_REPORTED_WARNING;
+                   CC_set_errornumber(self, CONNECTION_SERVER_REPORTED_WARNING);
                CC_on_abort(self, abort_opt);
                QR_set_status(res, PGRES_FATAL_ERROR);
                QR_set_message(res, msgbuffer);
@@ -1467,8 +1471,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                    res->next = QR_Constructor();
                    if (!res->next)
                    {
-                       self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
-                       self->errormsg = "Could not create result info in send_query.";
+                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
                        ReadyToReturn = TRUE;
                        retres = NULL;
                        break;
@@ -1487,8 +1490,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                        QR_set_haskeyset(res);
                    if (!QR_fetch_tuples(res, self, qi ? qi->cursor : NULL))
                    {
-                       self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
-                       self->errormsg = QR_get_message(res);
+                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
                        ReadyToReturn = TRUE;
                        if (PGRES_FATAL_ERROR == QR_get_status(res))
                            retres = cmdres;
@@ -1508,8 +1510,7 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                    ReadyToReturn = TRUE;
                    if (!QR_fetch_tuples(res, NULL, NULL))
                    {
-                       self->errornumber = CONNECTION_COULD_NOT_RECEIVE;
-                       self->errormsg = QR_get_message(res);
+                       CC_set_error(self, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(res));
                        retres = NULL;
                        break;
                    }
@@ -1537,11 +1538,10 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                retres = cmdres;
                break;
            default:
-               self->errornumber = CONNECTION_BACKEND_CRAZY;
-               self->errormsg = "Unexpected protocol character from backend (send_query)";
+               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_query)");
                CC_on_abort(self, NO_TRANS | CONN_DEAD);
 
-               mylog("send_query: error - %s\n", self->errormsg);
+               mylog("send_query: error - %s\n", CC_get_errormsg(self));
                ReadyToReturn = TRUE;
                retres = NULL;
                break;
@@ -1600,8 +1600,8 @@ CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag)
                /*
                 *  If error message isn't set
                 */
-               if (retres && (!self->errormsg || !self->errormsg[0]))
-                   self->errormsg = QR_get_message(retres);
+               if (retres && (!CC_get_errormsg(self) || !CC_get_errormsg(self)[0]))
+                   CC_set_errormsg(self, QR_get_message(retres));
            }
        }
    }
@@ -1618,15 +1618,14 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
    SocketClass *sock = self->sock;
 
    /* ERROR_MSG_LENGTH is sufficient */
-   static char msgbuffer[ERROR_MSG_LENGTH + 1];
+   char msgbuffer[ERROR_MSG_LENGTH + 1];
    int         i;
 
    mylog("send_function(): conn=%u, fnid=%d, result_is_int=%d, nargs=%d\n", self, fnid, result_is_int, nargs);
 
    if (SOCK_get_errcode(sock) != 0)
    {
-       self->errornumber = CONNECTION_COULD_NOT_SEND;
-       self->errormsg = "Could not send function to backend";
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
        return FALSE;
    }
@@ -1634,8 +1633,7 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
    SOCK_put_string(sock, "F ");
    if (SOCK_get_errcode(sock) != 0)
    {
-       self->errornumber = CONNECTION_COULD_NOT_SEND;
-       self->errormsg = "Could not send function to backend";
+       CC_set_error(self, CONNECTION_COULD_NOT_SEND, "Could not send function to backend");
        CC_on_abort(self, NO_TRANS | CONN_DEAD);
        return FALSE;
    }
@@ -1684,11 +1682,11 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
 
            case 'E':
                SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               self->errormsg = msgbuffer;
+               CC_set_errormsg(self, msgbuffer);
                CC_on_abort(self, 0);
 
-               mylog("send_function(V): 'E' - %s\n", self->errormsg);
-               qlog("ERROR from backend during send_function: '%s'\n", self->errormsg);
+               mylog("send_function(V): 'E' - %s\n", CC_get_errormsg(self));
+               qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
 
                return FALSE;
 
@@ -1696,11 +1694,10 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
                break;
 
            default:
-               self->errornumber = CONNECTION_BACKEND_CRAZY;
-               self->errormsg = "Unexpected protocol character from backend (send_function, args)";
+               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_function, args)");
                CC_on_abort(self, NO_TRANS | CONN_DEAD);
 
-               mylog("send_function: error - %s\n", self->errormsg);
+               mylog("send_function: error - %s\n", CC_get_errormsg(self));
                return FALSE;
        }
    }
@@ -1731,10 +1728,10 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
 
            case 'E':
                SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
-               self->errormsg = msgbuffer;
+               CC_set_errormsg(self, msgbuffer);
                CC_on_abort(self, 0);
-               mylog("send_function(G): 'E' - %s\n", self->errormsg);
-               qlog("ERROR from backend during send_function: '%s'\n", self->errormsg);
+               mylog("send_function(G): 'E' - %s\n", CC_get_errormsg(self));
+               qlog("ERROR from backend during send_function: '%s'\n", CC_get_errormsg(self));
 
                return FALSE;
 
@@ -1751,11 +1748,10 @@ CC_send_function(ConnectionClass *self, int fnid, void *result_buf, int *actual_
                return TRUE;
 
            default:
-               self->errornumber = CONNECTION_BACKEND_CRAZY;
-               self->errormsg = "Unexpected protocol character from backend (send_function, result)";
+               CC_set_error(self, CONNECTION_BACKEND_CRAZY, "Unexpected protocol character from backend (send_function, result)");
                CC_on_abort(self, NO_TRANS | CONN_DEAD);
 
-               mylog("send_function: error - %s\n", self->errormsg);
+               mylog("send_function: error - %s\n", CC_get_errormsg(self));
                return FALSE;
        }
    }
@@ -2030,8 +2026,8 @@ CC_log_error(const char *func, const char *desc, const ConnectionClass *self)
 
    if (self)
    {
-       qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
-       mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
+       qlog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
+       mylog("CONN ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
        qlog("            ------------------------------------------------------------\n");
        qlog("            henv=%u, conn=%u, status=%u, num_stmts=%d\n", self->henv, self, self->status, self->num_stmts);
        qlog("            sock=%u, stmts=%u, lobj_type=%d\n", self->sock, self->stmts, self->lobj_type);
index d9682d6f3ffa96e43d186b6a989bd85d0ccc1c2d..186fac5de021b206ff39e003a1f31d2ceefa2e6e 100644 (file)
@@ -60,8 +60,9 @@ typedef enum
 #define CONN_TRUNCATED                             215
 
 /* Conn_status defines */
-#define CONN_IN_AUTOCOMMIT                         0x01
-#define CONN_IN_TRANSACTION                            0x02
+#define CONN_IN_AUTOCOMMIT     1L 
+#define CONN_IN_TRANSACTION        (1L<<1)
+#define CONN_IN_MANUAL_TRANSACTION (1L<<2)
 
 /* AutoCommit functions */
 #define CC_set_autocommit_off(x)   (x->transact_status &= ~CONN_IN_AUTOCOMMIT)
@@ -73,6 +74,28 @@ typedef enum
 #define CC_set_no_trans(x) (x->transact_status &= ~CONN_IN_TRANSACTION)
 #define CC_is_in_trans(x)  (x->transact_status & CONN_IN_TRANSACTION)
 
+/* Manual transaction in/not functions */
+#define CC_set_in_manual_trans(x) (x->transact_status |= CONN_IN_MANUAL_TRANSACTION)
+#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)
+
+#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)
+
+/* For Multi-thread */
+#ifdef WIN_MULTITHREAD_SUPPORT
+#define INIT_CONN_CS(x)        InitializeCriticalSection(&((x)->cs))
+#define ENTER_CONN_CS(x)   EnterCriticalSection(&((x)->cs))
+#define LEAVE_CONN_CS(x)   LeaveCriticalSection(&((x)->cs))
+#define DELETE_CONN_CS(x)  DeleteCriticalSection(&((x)->cs))
+#else
+#define INIT_CONN_CS(x)    
+#define ENTER_CONN_CS(x)
+#define LEAVE_CONN_CS(x)
+#define DELETE_CONN_CS(x)
+#endif /* WIN_MULTITHREAD_SUPPORT */
+
 
 /* Authentication types */
 #define AUTH_REQ_OK                                    0
@@ -263,8 +286,8 @@ struct ConnectionClass_
    StatementOptions stmtOptions;
    ARDFields   ardOptions;
    APDFields   apdOptions;
-   char       *errormsg;
-   int         errornumber;
+   char       *__error_message;
+   int         __error_number;
    CONN_Status status;
    ConnInfo    connInfo;
    StatementClass **stmts;
@@ -301,6 +324,9 @@ struct ConnectionClass_
    int     be_key; /* auth code needed to send cancel */
    UInt4       isolation;
    char        *current_schema;
+#ifdef WIN_MULTITHREAD_SUPPORT
+   CRITICAL_SECTION    cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
 };
 
 
@@ -331,6 +357,8 @@ int         CC_set_translation(ConnectionClass *self);
 char       CC_connect(ConnectionClass *self, char password_req, char *salt);
 char       CC_add_statement(ConnectionClass *self, StatementClass *stmt);
 char       CC_remove_statement(ConnectionClass *self, StatementClass *stmt);
+void       CC_set_error(ConnectionClass *self, int number, const char *message);
+void       CC_set_errormsg(ConnectionClass *self, const char *message);
 char       CC_get_error(ConnectionClass *self, int *number, char **message);
 QResultClass *CC_send_query(ConnectionClass *self, char *query, QueryInfo *qi, UDWORD flag);
 void       CC_clear_error(ConnectionClass *self);
index fb3e09c10ca5cd4d02d3d95a8c1be86e151a9459..c2f95d2b90d37a4d27d20fdd72f388ab590ec45c 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -424,8 +424,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
        }
        else
        {
-           stmt->errornumber = STMT_RETURN_NULL_WITHOUT_INDICATOR;
-           stmt->errormsg = "StrLen_or_IndPtr was a null pointer and NULL data was retrieved"; 
+           SC_set_error(stmt, STMT_RETURN_NULL_WITHOUT_INDICATOR, "StrLen_or_IndPtr was a null pointer and NULL data was retrieved");  
            SC_log_error(func, "", stmt);
            return  SQL_ERROR;
        }
@@ -995,7 +994,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
            SQL_NUMERIC_STRUCT      *ns;
            int i, nlen, bit, hval, tv, dig, sta, olen;
            char    calv[SQL_MAX_NUMERIC_LEN * 3];
-           const char  *wv;
+           const char *wv;
            BOOL    dot_exist;
 
            len = sizeof(SQL_NUMERIC_STRUCT);
@@ -1447,8 +1446,8 @@ enlarge_query_statement(QueryBuild *qb, unsigned int newsize)
        qb->str_alsize = 0;
        if (qb->stmt)
        {
-           qb->stmt->errormsg = "Query buffer overflow in copy_statement_with_parameters";
-           qb->stmt->errornumber = STMT_EXEC_ERROR;
+           
+           SC_set_error(qb->stmt, STMT_EXEC_ERROR, "Query buffer overflow in copy_statement_with_parameters");
            SC_log_error(func, "", qb->stmt);
        }
        else
@@ -1465,8 +1464,7 @@ enlarge_query_statement(QueryBuild *qb, unsigned int newsize)
        qb->str_alsize = 0;
        if (qb->stmt)
        {
-           qb->stmt->errormsg = "Query buffer allocate error in copy_statement_with_parameters";
-           qb->stmt->errornumber = STMT_EXEC_ERROR;
+           SC_set_error(qb->stmt, STMT_EXEC_ERROR, "Query buffer allocate error in copy_statement_with_parameters");
        }
        else
        {
@@ -1688,7 +1686,7 @@ copy_statement_with_parameters(StatementClass *stmt)
 
    if (ci->disallow_premature)
        prepare_dummy_cursor = stmt->pre_executing;
-   if (prepare_dummy_cursor);
+   if (prepare_dummy_cursor)
        qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
 
 
@@ -1775,10 +1773,9 @@ copy_statement_with_parameters(StatementClass *stmt)
        retval = inner_process_tokens(qp, qb);
        if (SQL_ERROR == retval)
        {
-           if (0 == stmt->errornumber)
+           if (0 == SC_get_errornumber(stmt))
            {
-               stmt->errornumber = qb->errornumber;
-               stmt->errormsg = qb->errormsg;
+               SC_set_error(stmt, qb->errornumber, qb->errormsg);
            }
            SC_log_error(func, "", stmt);
            QB_Destructor(qb);
@@ -3481,8 +3478,7 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        {
            if (!CC_begin(conn))
            {
-               stmt->errormsg = "Could not begin (in-line) a transaction";
-               stmt->errornumber = STMT_EXEC_ERROR;
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction");
                return COPY_GENERAL_ERROR;
            }
        }
@@ -3491,8 +3487,7 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        stmt->lobj_fd = lo_open(conn, oid, INV_READ);
        if (stmt->lobj_fd < 0)
        {
-           stmt->errornumber = STMT_EXEC_ERROR;
-           stmt->errormsg = "Couldnt open large object for reading.";
+           SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for reading.");
            return COPY_GENERAL_ERROR;
        }
 
@@ -3515,8 +3510,7 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
 
    if (stmt->lobj_fd < 0)
    {
-       stmt->errornumber = STMT_EXEC_ERROR;
-       stmt->errormsg = "Large object FD undefined for multiple read.";
+       SC_set_error(stmt, STMT_EXEC_ERROR, "Large object FD undefined for multiple read.");
        return COPY_GENERAL_ERROR;
    }
 
@@ -3530,16 +3524,14 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        {
            if (!CC_commit(conn))
            {
-               stmt->errormsg = "Could not commit (in-line) a transaction";
-               stmt->errornumber = STMT_EXEC_ERROR;
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");
                return COPY_GENERAL_ERROR;
            }
        }
 
        stmt->lobj_fd = -1;
 
-       stmt->errornumber = STMT_EXEC_ERROR;
-       stmt->errormsg = "Error reading from large object.";
+       SC_set_error(stmt, STMT_EXEC_ERROR, "Error reading from large object.");
        return COPY_GENERAL_ERROR;
    }
 
@@ -3565,8 +3557,7 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
        {
            if (!CC_commit(conn))
            {
-               stmt->errormsg = "Could not commit (in-line) a transaction";
-               stmt->errornumber = STMT_EXEC_ERROR;
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");
                return COPY_GENERAL_ERROR;
            }
        }
index 4abe0ec156574282174b02c963725d9d998dd7f5..abae3fddc9926cf098dbce1881a1eef832645c40 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: descriptor.h,v 1.7 2002/09/06 05:51:45 hinoue Exp $
+ * $Id: descriptor.h,v 1.8 2002/09/23 08:08:21 hinoue Exp $
  *
  */
 
index 99005d3a3384cad98000954364d1fb9ac55d48ca..370d936fef4f0d15a9c9efdb70ba54d8575ac3bb 100644 (file)
 #endif
 
 
-#define INI_DSN                            DBMS_NAME       /* Name of default
-                                                        * Datasource in ini
-                                                        * file (not used?) */
+#if (ODBCVER >= 0x0300)
+#ifdef  UNICODE_SUPPORT
+#define INI_DSN                "PostgreSQL30W"
+#else
+#define INI_DSN                "PostgreSQL30"
+#endif /* UNICODE_SUPPORT */
+#else
+#define INI_DSN                DBMS_NAME
+#endif   /* ODBCVER */
+
 #define INI_KDESC                      "Description"   /* Data source
                                                         * description */
 #define INI_SERVER                     "Servername"    /* Name of Server
index 88c2e9f4c45a366e619276dc78816d6df5c96827..1eb304a1268d51c50314bfecb70446e1b6004eba 100644 (file)
@@ -170,6 +170,7 @@ driver_optionsDraw(HWND hdlg, const ConnInfo *ci, int src, BOOL enable)
    ShowWindow(GetDlgItem(hdlg, IDNEXTPAGE), enable ? SW_HIDE : SW_SHOW);
    return 0;
 }
+
 static int
 driver_options_update(HWND hdlg, ConnInfo *ci, BOOL updateProfile)
 {
@@ -292,7 +293,7 @@ global_optionsProc(HWND hdlg,
                case IDOK:
                    globals.commlog = IsDlgButtonChecked(hdlg, DRV_COMMLOG);
                    globals.debug = IsDlgButtonChecked(hdlg, DRV_DEBUG);
-                   driver_options_update(hdlg, NULL, TRUE);
+                   writeDriverCommoninfo(NULL);
 
                case IDCANCEL:
                    EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
index 6c08376ac4bc05de7097e7cca498e906a9fd104a..3dc772f91ad5c8af8ec93c74017f86b3ff8bf204 100644 (file)
--- a/drvconn.c
+++ b/drvconn.c
@@ -232,8 +232,7 @@ dialog:
            for (clen = strlen(szConnStrOut) - 1; clen >= 0 && szConnStrOut[clen] != ';'; clen--)
                szConnStrOut[clen] = '\0';
            result = SQL_SUCCESS_WITH_INFO;
-           conn->errornumber = CONN_TRUNCATED;
-           conn->errormsg = "The buffer was too small for the ConnStrOut.";
+           CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the ConnStrOut.");
        }
    }
 
index 9ac8f8eb6cf2a1b898b37ce8e1f0f2d9dafff443..9889c9064b09ad005dcd0f9ddea0208c95af17be 100644 (file)
--- a/environ.c
+++ b/environ.c
@@ -26,6 +26,9 @@ extern GLOBAL_VALUES globals;
 
 /* The one instance of the handles */
 ConnectionClass *conns[MAX_CONNECTIONS];
+#ifdef WIN_MULTITHREAD_SUPPORT
+CRITICAL_SECTION   conns_cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
 
 
 RETCODE        SQL_API
@@ -110,7 +113,8 @@ PGAPI_StmtError(    HSTMT hstmt,
    if (cbErrorMsgMax < 0)
        return SQL_ERROR;
 
-   if (!SC_get_error(stmt, &status, &msg) || NULL == msg || !msg[0])
+   if (STMT_EXECUTING == stmt->status || !SC_get_error(stmt, &status, &msg)
+        || NULL == msg || !msg[0])
    {
        mylog("SC_Get_error returned nothing.\n");
        if (NULL != szSqlState)
@@ -336,7 +340,7 @@ PGAPI_ConnectError( HDBC hdbc,
        return SQL_NO_DATA_FOUND;
    if (cbErrorMsgMax < 0)
        return SQL_ERROR;
-   if (!CC_get_error(conn, &status, &msg) || NULL == msg)
+   if (CONN_EXECUTING == conn->status || !CC_get_error(conn, &status, &msg) || NULL == msg)
    {
        mylog("CC_Get_error returned nothing.\n");
        if (NULL != szSqlState)
@@ -436,7 +440,7 @@ PGAPI_ConnectError( HDBC hdbc,
    mylog("      szSqlState = '%s',len=%d, szError='%s'\n", szSqlState, msglen, szErrorMsg);
    if (once_again)
    {
-       conn->errornumber = status;
+       CC_set_errornumber(conn, status);
        return SQL_SUCCESS_WITH_INFO;
    }
    else
@@ -560,6 +564,7 @@ EN_Constructor(void)
        rv->errormsg = 0;
        rv->errornumber = 0;
        rv->flag = 0;
+       INIT_ENV_CS(rv);
    }
 
    return rv;
@@ -585,6 +590,7 @@ EN_Destructor(EnvironmentClass *self)
        if (conns[lf] && conns[lf]->henv == self)
            rv = rv && CC_Destructor(conns[lf]);
    }
+   DELETE_ENV_CS(self);
    free(self);
 
    mylog("exit EN_Destructor: rv = %d\n", rv);
@@ -618,18 +624,21 @@ EN_add_connection(EnvironmentClass *self, ConnectionClass *conn)
 
    mylog("EN_add_connection: self = %u, conn = %u\n", self, conn);
 
+   ENTER_CONNS_CS;
    for (i = 0; i < MAX_CONNECTIONS; i++)
    {
        if (!conns[i])
        {
            conn->henv = self;
            conns[i] = conn;
+           LEAVE_CONNS_CS;
 
            mylog("       added at i =%d, conn->henv = %u, conns[i]->henv = %u\n", i, conn->henv, conns[i]->henv);
 
            return TRUE;
        }
    }
+   LEAVE_CONNS_CS;
 
    return FALSE;
 }
@@ -643,7 +652,9 @@ EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn)
    for (i = 0; i < MAX_CONNECTIONS; i++)
        if (conns[i] == conn && conns[i]->status != CONN_EXECUTING)
        {
+           ENTER_CONNS_CS;
            conns[i] = NULL;
+           LEAVE_CONNS_CS;
            return TRUE;
        }
 
index 24b456d489915d9f479bb3f902d8f3bdf9d8bb61..b2e0e38124f242fa44711cf7f13a019f19893fd0 100644 (file)
--- a/environ.h
+++ b/environ.h
@@ -19,6 +19,9 @@ struct EnvironmentClass_
    char       *errormsg;
    int     errornumber;
    Int4    flag;
+#ifdef WIN_MULTITHREAD_SUPPORT
+   CRITICAL_SECTION    cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
 };
 
 /* Environment prototypes */
@@ -30,9 +33,33 @@ char     EN_remove_connection(EnvironmentClass *self, ConnectionClass *conn);
 void       EN_log_error(char *func, char *desc, EnvironmentClass *self);
 
 #define    EN_OV_ODBC2 1L
+#define    EN_CONN_POOLING (1L<<1)
 #define    EN_is_odbc2(env) ((env->flag & EN_OV_ODBC2) != 0)
 #define    EN_is_odbc3(env) ((env->flag & EN_OV_ODBC2) == 0)
 #define EN_set_odbc2(env) (env->flag |= EN_OV_ODBC2)
 #define EN_set_odbc3(env) (env->flag &= EN_OV_ODBC2)
+#define    EN_is_pooling(env) ((env->flag & EN_CONN_POOLING) != 0)
+#define    EN_set_pooling(env) (env->flag |= EN_CONN_POOLING)
+#define    EN_unset_pooling(env) (env->flag &= ~EN_CONN_POOLING)
 
+/* For Multi-thread */
+#ifdef  WIN_MULTITHREAD_SUPPORT
+#define    INIT_CONNS_CS   InitializeCriticalSection(&conns_cs)
+#define    ENTER_CONNS_CS  EnterCriticalSection(&conns_cs)
+#define    LEAVE_CONNS_CS  LeaveCriticalSection(&conns_cs)
+#define    DELETE_CONNS_CS DeleteCriticalSection(&conns_cs)
+#define INIT_ENV_CS(x)     InitializeCriticalSection(&((x)->cs))
+#define ENTER_ENV_CS(x)        EnterCriticalSection(&((x)->cs))
+#define LEAVE_ENV_CS(x)        LeaveCriticalSection(&((x)->cs))
+#define DELETE_ENV_CS(x)   DeleteCriticalSection(&((x)->cs))
+#else
+#define    INIT_CONNS_CS
+#define    ENTER_CONNS_CS
+#define    LEAVE_CONNS_CS
+#define    DELETE_CONNS_CS
+#define INIT_ENV_CS(x)
+#define ENTER_ENV_CS(x)
+#define LEAVE_ENV_CS(x)
+#define DELETE_ENV_CS(x)
+#endif /* WIN_MULTITHREAD_SUPPORT */
 #endif
index 598c2a2f61a5d59b7cf24dd6bc39de41987b3faf..3c0f52f81fe156c8cc3dc36145b7aeecee4d5a5a 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -79,15 +79,13 @@ PGAPI_Prepare(HSTMT hstmt,
        case STMT_EXECUTING:
            mylog("**** PGAPI_Prepare: STMT_EXECUTING, error!\n");
 
-           self->errornumber = STMT_SEQUENCE_ERROR;
-           self->errormsg = "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed";
+           SC_set_error(self, STMT_SEQUENCE_ERROR, "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed");
            SC_log_error(func, "", self);
 
            return SQL_ERROR;
 
        default:
-           self->errornumber = STMT_INTERNAL_ERROR;
-           self->errormsg = "An Internal Error has occured -- Unknown statement status.";
+           SC_set_error(self, STMT_INTERNAL_ERROR, "An Internal Error has occured -- Unknown statement status.");
            SC_log_error(func, "", self);
            return SQL_ERROR;
    }
@@ -104,8 +102,7 @@ PGAPI_Prepare(HSTMT hstmt,
    self->statement = make_string(szSqlStr, cbSqlStr, NULL);
    if (!self->statement)
    {
-       self->errornumber = STMT_NO_MEMORY_ERROR;
-       self->errormsg = "No memory available to store statement";
+       SC_set_error(self, STMT_NO_MEMORY_ERROR, "No memory available to store statement");
        SC_log_error(func, "", self);
        return SQL_ERROR;
    }
@@ -116,8 +113,7 @@ PGAPI_Prepare(HSTMT hstmt,
    /* Check if connection is onlyread (only selects are allowed) */
    if (CC_is_onlyread(self->hdbc) && STMT_UPDATE(self))
    {
-       self->errornumber = STMT_EXEC_ERROR;
-       self->errormsg = "Connection is readonly, only select statements are allowed.";
+       SC_set_error(self, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.");
        SC_log_error(func, "", self);
        return SQL_ERROR;
    }
@@ -161,8 +157,7 @@ PGAPI_ExecDirect(
    stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
    if (!stmt->statement)
    {
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-       stmt->errormsg = "No memory available to store statement";
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "No memory available to store statement");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -184,8 +179,7 @@ PGAPI_ExecDirect(
    /* Check if connection is onlyread (only selects are allowed) */
    if (CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt))
    {
-       stmt->errornumber = STMT_EXEC_ERROR;
-       stmt->errormsg = "Connection is readonly, only select statements are allowed.";
+       SC_set_error(stmt, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -241,7 +235,7 @@ PGAPI_Execute(
        else
        {
            stmt->status = STMT_FINISHED;
-           if (stmt->errormsg == NULL)
+           if (NULL == SC_get_errormsg(stmt))
            {
                mylog("%s: premature statement but return SQL_SUCCESS\n", func);
                return SQL_SUCCESS;
@@ -262,8 +256,7 @@ PGAPI_Execute(
    conn = SC_get_conn(stmt);
    if (conn->status == CONN_EXECUTING)
    {
-       stmt->errormsg = "Connection is already in use.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Connection is already in use.");
        SC_log_error(func, "", stmt);
        mylog("%s: problem with connection\n", func);
        return SQL_ERROR;
@@ -271,8 +264,7 @@ PGAPI_Execute(
 
    if (!stmt->statement)
    {
-       stmt->errornumber = STMT_NO_STMTSTRING;
-       stmt->errormsg = "This handle does not have a SQL statement stored in it";
+       SC_set_error(stmt, STMT_NO_STMTSTRING, "This handle does not have a SQL statement stored in it");
        SC_log_error(func, "", stmt);
        mylog("%s: problem with handle\n", func);
        return SQL_ERROR;
@@ -294,8 +286,7 @@ PGAPI_Execute(
    if ((stmt->prepare && stmt->status != STMT_READY) ||
        (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
    {
-       stmt->errornumber = STMT_STATUS_ERROR;
-       stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
+       SC_set_error(stmt, STMT_STATUS_ERROR, "The handle does not point to a statement that is ready to be executed");
        SC_log_error(func, "", stmt);
        mylog("%s: problem with statement\n", func);
        return SQL_ERROR;
@@ -466,8 +457,7 @@ next_param_row:
        {
            if (issued_begin = CC_begin(conn), !issued_begin)
            {
-               stmt->errornumber = STMT_EXEC_ERROR;
-               stmt->errormsg = "Handle prepare error";
+               SC_set_error(stmt, STMT_EXEC_ERROR,  "Handle prepare error");
                return SQL_ERROR;
            }
        }
@@ -476,8 +466,7 @@ next_param_row:
        if (!res)
        {
            CC_abort(conn);
-           stmt->errornumber = STMT_EXEC_ERROR;
-           stmt->errormsg = "Handle prepare error";
+           SC_set_error(stmt, STMT_EXEC_ERROR, "Handle prepare error");
            return SQL_ERROR;
        }
        SC_set_Result(stmt, res);
@@ -497,8 +486,7 @@ next_param_row:
    if (stmt->options.cursor_type != cursor_type ||
        stmt->options.scroll_concurrency != scroll_concurrency)
    {
-       stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
-       stmt->errormsg = "cursor updatability changed";
+       SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed");
        return SQL_SUCCESS_WITH_INFO;
    }
    else 
@@ -553,8 +541,7 @@ PGAPI_Transact(
        stmt_string = "ROLLBACK";
    else
    {
-       conn->errornumber = CONN_INVALID_ARGUMENT_NO;
-       conn->errormsg = "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter";
+       CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter");
        CC_log_error(func, "", conn);
        return SQL_ERROR;
    }
@@ -693,8 +680,7 @@ PGAPI_NativeSql(
    ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL);
    if (!ptr)
    {
-       conn->errornumber = CONN_NO_MEMORY_ERROR;
-       conn->errormsg = "No memory available to store native sql string";
+       CC_set_error(conn, CONN_NO_MEMORY_ERROR, "No memory available to store native sql string");
        CC_log_error(func, "", conn);
        return SQL_ERROR;
    }
@@ -709,8 +695,7 @@ PGAPI_NativeSql(
        if (len >= cbSqlStrMax)
        {
            result = SQL_SUCCESS_WITH_INFO;
-           conn->errornumber = STMT_TRUNCATED;
-           conn->errormsg = "The buffer was too small for the NativeSQL.";
+           CC_set_error(conn, STMT_TRUNCATED, "The buffer was too small for the NativeSQL.");
        }
    }
 
@@ -755,16 +740,14 @@ PGAPI_ParamData(
 
    if (stmt->data_at_exec < 0)
    {
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
-       stmt->errormsg = "No execution-time parameters for this statement";
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "No execution-time parameters for this statement");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (stmt->data_at_exec > opts->allocated)
    {
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
-       stmt->errormsg = "Too many execution-time parameters were present";
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Too many execution-time parameters were present");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -779,8 +762,7 @@ PGAPI_ParamData(
        {
            if (!CC_commit(stmt->hdbc))
            {
-               stmt->errormsg = "Could not commit (in-line) a transaction";
-               stmt->errornumber = STMT_EXEC_ERROR;
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
            }
@@ -888,8 +870,7 @@ PGAPI_PutData(
    opts = SC_get_APD(stmt);
    if (stmt->current_exec_param < 0)
    {
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
-       stmt->errormsg = "Previous call was not SQLPutData or SQLParamData";
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Previous call was not SQLPutData or SQLParamData");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -905,8 +886,7 @@ PGAPI_PutData(
        current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD));
        if (!current_param->EXEC_used)
        {
-           stmt->errornumber = STMT_NO_MEMORY_ERROR;
-           stmt->errormsg = "Out of memory in PGAPI_PutData (1)";
+           SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (1)");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -924,8 +904,7 @@ PGAPI_PutData(
            {
                if (!CC_begin(stmt->hdbc))
                {
-                   stmt->errormsg = "Could not begin (in-line) a transaction";
-                   stmt->errornumber = STMT_EXEC_ERROR;
+                   SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction");
                    SC_log_error(func, "", stmt);
                    return SQL_ERROR;
                }
@@ -935,8 +914,7 @@ PGAPI_PutData(
            current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
            if (current_param->lobj_oid == 0)
            {
-               stmt->errornumber = STMT_EXEC_ERROR;
-               stmt->errormsg = "Couldnt create large object.";
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt create large object.");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
            }
@@ -951,8 +929,7 @@ PGAPI_PutData(
            stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE);
            if (stmt->lobj_fd < 0)
            {
-               stmt->errornumber = STMT_EXEC_ERROR;
-               stmt->errormsg = "Couldnt open large object for writing.";
+               SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for writing.");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
            }
@@ -976,8 +953,7 @@ PGAPI_PutData(
                current_param->EXEC_buffer = strdup(rgbValue);
                if (!current_param->EXEC_buffer)
                {
-                   stmt->errornumber = STMT_NO_MEMORY_ERROR;
-                   stmt->errormsg = "Out of memory in PGAPI_PutData (2)";
+                   SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
                    SC_log_error(func, "", stmt);
                    return SQL_ERROR;
                }
@@ -993,8 +969,7 @@ PGAPI_PutData(
                    current_param->EXEC_buffer = malloc(cbValue + 1);
                    if (!current_param->EXEC_buffer)
                    {
-                       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-                       stmt->errormsg = "Out of memory in PGAPI_PutData (2)";
+                       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
                        SC_log_error(func, "", stmt);
                        return SQL_ERROR;
                    }
@@ -1008,8 +983,7 @@ PGAPI_PutData(
                    current_param->EXEC_buffer = malloc(used);
                    if (!current_param->EXEC_buffer)
                    {
-                       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-                       stmt->errormsg = "Out of memory in PGAPI_PutData (2)";
+                       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)");
                        SC_log_error(func, "", stmt);
                        return SQL_ERROR;
                    }
@@ -1066,8 +1040,7 @@ PGAPI_PutData(
                buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
                if (!buffer)
                {
-                   stmt->errornumber = STMT_NO_MEMORY_ERROR;
-                   stmt->errormsg = "Out of memory in PGAPI_PutData (3)";
+                   SC_set_error(stmt, STMT_NO_MEMORY_ERROR,"Out of memory in PGAPI_PutData (3)");
                    SC_log_error(func, "", stmt);
                    return SQL_ERROR;
                }
diff --git a/info.c b/info.c
index 73dd27f12ef31c92be45c223f25ca4d42c461b73..1d757c869c6640432641d8177b21504e89823fda 100644 (file)
--- a/info.c
+++ b/info.c
@@ -27,6 +27,7 @@
 
 #include "tuple.h"
 #include "pgtypes.h"
+#include "dlg_specific.h"
 
 #include "environ.h"
 #include "connection.h"
@@ -602,7 +603,9 @@ PGAPI_GetInfo(
        case SQL_SCROLL_OPTIONS:        /* ODBC 1.0 */
            len = 4;
            value = SQL_SO_FORWARD_ONLY;
+#ifdef DECLAREFETCH_FORWARDONLY
            if (!ci->drivers.use_declarefetch)
+#endif /* DECLAREFETCH_FORWARDONLY */
                value |= SQL_SO_STATIC;
            if (ci->updatable_cursors)
                value |= SQL_SO_KEYSET_DRIVEN;
@@ -711,8 +714,7 @@ PGAPI_GetInfo(
 
        default:
            /* unrecognized key */
-           conn->errormsg = "Unrecognized key passed to PGAPI_GetInfo.";
-           conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
+           CC_set_error(conn, CONN_NOT_IMPLEMENTED_ERROR, "Unrecognized key passed to PGAPI_GetInfo.");
            return SQL_ERROR;
    }
 
@@ -745,8 +747,7 @@ PGAPI_GetInfo(
            if (len >= cbInfoValueMax)
            {
                result = SQL_SUCCESS_WITH_INFO;
-               conn->errornumber = CONN_TRUNCATED;
-               conn->errormsg = "The buffer was too small for tthe InfoValue.";
+               CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for tthe InfoValue.");
            }
        }
    }
@@ -972,7 +973,10 @@ PGAPI_GetFunctions(
            pfExists[SQL_API_SQLNUMPARAMS] = TRUE;
            pfExists[SQL_API_SQLPARAMOPTIONS] = TRUE;
            pfExists[SQL_API_SQLPRIMARYKEYS] = TRUE;
-           pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
+           if (PG_VERSION_LT(conn, 6.5))
+               pfExists[SQL_API_SQLPROCEDURECOLUMNS] = FALSE;
+           else
+               pfExists[SQL_API_SQLPROCEDURECOLUMNS] = TRUE;
            if (PG_VERSION_LT(conn, 6.5))
                pfExists[SQL_API_SQLPROCEDURES] = FALSE;
            else
@@ -1148,7 +1152,10 @@ PGAPI_GetFunctions(
                    *pfExists = TRUE;
                    break;
                case SQL_API_SQLPROCEDURECOLUMNS:
-                   *pfExists = FALSE;
+                   if (PG_VERSION_LT(conn, 6.5))
+                       *pfExists = FALSE;
+                   else
+                       *pfExists = TRUE;
                    break;
                case SQL_API_SQLPROCEDURES:
                    if (PG_VERSION_LT(conn, 6.5))
@@ -1227,8 +1234,7 @@ PGAPI_Tables(
    result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-       stmt->errormsg = "Couldn't allocate statement for PGAPI_Tables result.";
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Tables result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1265,7 +1271,7 @@ PGAPI_Tables(
    strcpy(prefixes, ci->drivers.extra_systable_prefixes);
    i = 0;
    prefix[i] = strtok(prefixes, ";");
-   while (prefix[i] && i < 32)
+   while (prefix[i] && i < sizeof(prefix))
        prefix[++i] = strtok(NULL, ";");
 
    /* Parse the desired table types to return */
@@ -1336,8 +1342,7 @@ PGAPI_Tables(
    result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = SC_create_errormsg(htbl_stmt);
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_full_error_copy(stmt, htbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1347,8 +1352,7 @@ PGAPI_Tables(
                           table_name, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = tbl_stmt->errormsg;
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_error_copy(stmt, tbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1358,8 +1362,7 @@ PGAPI_Tables(
                           table_owner, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = tbl_stmt->errormsg;
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_error_copy(stmt, tbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1368,8 +1371,7 @@ PGAPI_Tables(
                           relkind_or_hasrules, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = tbl_stmt->errormsg;
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_error_copy(stmt, tbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1377,8 +1379,7 @@ PGAPI_Tables(
 
    if (res = QR_Constructor(), !res)
    {
-       stmt->errormsg = "Couldn't allocate memory for PGAPI_Tables result.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       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;
@@ -1472,12 +1473,11 @@ PGAPI_Tables(
            if (conn->schema_support)
                set_tuplefield_string(&row->tuple[1], GET_SCHEMA_NAME(table_owner));
            else
-               /* set_tuplefield_string(&row->tuple[1], ""); */
                set_tuplefield_null(&row->tuple[1]);
            set_tuplefield_string(&row->tuple[2], table_name);
            set_tuplefield_string(&row->tuple[3], systable ? "SYSTEM TABLE" : (view ? "VIEW" : "TABLE"));
-           /*set_tuplefield_string(&row->tuple[4], "");*/
-           set_tuplefield_string(&row->tuple[4], "TABLE");
+           set_tuplefield_string(&row->tuple[4], "");
+           /*** set_tuplefield_string(&row->tuple[4], "TABLE"); ***/
 
            QR_add_tuple(res, row);
        }
@@ -1485,8 +1485,7 @@ PGAPI_Tables(
    }
    if (result != SQL_NO_DATA_FOUND)
    {
-       stmt->errormsg = SC_create_errormsg(htbl_stmt);
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_full_error_copy(stmt, htbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1683,8 +1682,7 @@ PGAPI_Columns(
    result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-       stmt->errormsg = "Couldn't allocate statement for PGAPI_Columns result.";
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_Columns result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1696,8 +1694,7 @@ PGAPI_Columns(
                              strlen(columns_query));
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = SC_create_errormsg(hcol_stmt);
-       stmt->errornumber = col_stmt->errornumber;
+       SC_full_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1707,8 +1704,7 @@ PGAPI_Columns(
                           table_owner, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1718,8 +1714,7 @@ PGAPI_Columns(
                           table_name, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1729,8 +1724,7 @@ PGAPI_Columns(
                           field_name, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1740,8 +1734,7 @@ PGAPI_Columns(
                           &field_type, 4, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1751,8 +1744,7 @@ PGAPI_Columns(
                           field_type_name, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1762,8 +1754,7 @@ PGAPI_Columns(
                           &field_number, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1773,8 +1764,7 @@ PGAPI_Columns(
                           &field_length, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1784,8 +1774,7 @@ PGAPI_Columns(
                           &mod_length, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1795,8 +1784,7 @@ PGAPI_Columns(
                           not_null, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1806,8 +1794,7 @@ PGAPI_Columns(
                           relhasrules, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -1815,8 +1802,7 @@ PGAPI_Columns(
 
    if (res = QR_Constructor(), !res)
    {
-       stmt->errormsg = "Couldn't allocate memory for PGAPI_Columns result.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Columns result.");
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -2035,8 +2021,7 @@ PGAPI_Columns(
    }
    if (result != SQL_NO_DATA_FOUND)
    {
-       stmt->errormsg = SC_create_errormsg(hcol_stmt);
-       stmt->errornumber = col_stmt->errornumber;
+       SC_full_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -2163,8 +2148,7 @@ PGAPI_SpecialColumns(
    result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-       stmt->errormsg = "Couldn't allocate statement for SQLSpecialColumns result.";
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for SQLSpecialColumns result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2176,8 +2160,7 @@ PGAPI_SpecialColumns(
                              strlen(columns_query));
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = SC_create_errormsg(hcol_stmt);
-       stmt->errornumber = col_stmt->errornumber;
+       SC_full_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -2187,8 +2170,7 @@ PGAPI_SpecialColumns(
                           relhasrules, MAX_INFO_STRING, NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -2357,8 +2339,7 @@ PGAPI_Statistics(
 
    if (res = QR_Constructor(), !res)
    {
-       stmt->errormsg = "Couldn't allocate memory for PGAPI_Statistics result.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Statistics result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2395,8 +2376,7 @@ PGAPI_Statistics(
    table_name = make_string(szTableName, cbTableName, NULL);
    if (!table_name)
    {
-       stmt->errormsg = "No table name passed to PGAPI_Statistics.";
-       stmt->errornumber = STMT_INTERNAL_ERROR;
+       SC_set_error(stmt, STMT_INTERNAL_ERROR, "No table name passed to PGAPI_Statistics.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2411,8 +2391,7 @@ PGAPI_Statistics(
    result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in PGAPI_Statistics for columns.");
        goto SEEYA;
    }
 
@@ -2432,9 +2411,7 @@ PGAPI_Statistics(
 
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;    /* "SQLColumns failed in
-                                                * SQLStatistics."; */
-       stmt->errornumber = col_stmt->errornumber;      /* STMT_EXEC_ERROR; */
+       SC_error_copy(stmt, col_stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        goto SEEYA;
    }
@@ -2442,8 +2419,7 @@ PGAPI_Statistics(
                         column_name, sizeof(column_name), &column_name_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = col_stmt->errormsg;
-       stmt->errornumber = col_stmt->errornumber;
+       SC_error_copy(stmt, col_stmt);
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        goto SEEYA;
 
@@ -2468,10 +2444,9 @@ PGAPI_Statistics(
 
    if (result != SQL_NO_DATA_FOUND || total_columns == 0)
    {
-       stmt->errormsg = SC_create_errormsg(hcol_stmt); /* "Couldn't get column
+       SC_full_error_copy(stmt, col_stmt); /* "Couldn't get column
                                                         * names in
                                                         * SQLStatistics."; */
-       stmt->errornumber = col_stmt->errornumber;
        PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
        goto SEEYA;
 
@@ -2483,8 +2458,7 @@ PGAPI_Statistics(
    result = PGAPI_AllocStmt(stmt->hdbc, &hindx_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = "PGAPI_AllocStmt failed in SQLStatistics for indices.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in SQLStatistics for indices.");
        goto SEEYA;
 
    }
@@ -2524,9 +2498,7 @@ PGAPI_Statistics(
         * "Couldn't execute index query (w/SQLExecDirect) in
         * SQLStatistics.";
         */
-       stmt->errormsg = SC_create_errormsg(hindx_stmt);
-
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_full_error_copy(stmt, indx_stmt);
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
    }
@@ -2536,21 +2508,19 @@ PGAPI_Statistics(
                           index_name, MAX_INFO_STRING, &index_name_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = indx_stmt->errormsg;   /* "Couldn't bind column
-                                                * in SQLStatistics."; */
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column 
+                       * in SQLStatistics."; */
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
 
    }
    /* bind the vector column */
    result = PGAPI_BindCol(hindx_stmt, 2, SQL_C_DEFAULT,
-               fields_vector, INDEX_KEYS_STORAGE_COUNT * 2, &fields_vector_len);
+           fields_vector, INDEX_KEYS_STORAGE_COUNT * 2, &fields_vector_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = indx_stmt->errormsg;   /* "Couldn't bind column
-                                                * in SQLStatistics."; */
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column 
+                        * in SQLStatistics."; */
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
 
@@ -2560,9 +2530,8 @@ PGAPI_Statistics(
                           isunique, sizeof(isunique), NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = indx_stmt->errormsg;   /* "Couldn't bind column
-                                                * in SQLStatistics."; */
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column 
+                        * in SQLStatistics."; */
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
    }
@@ -2572,9 +2541,8 @@ PGAPI_Statistics(
                           isclustered, sizeof(isclustered), NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = indx_stmt->errormsg;   /* "Couldn't bind column
-                                                * in SQLStatistics."; */
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column *
+                        * in SQLStatistics."; */
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
 
@@ -2585,9 +2553,8 @@ PGAPI_Statistics(
                           ishash, sizeof(ishash), NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = indx_stmt->errormsg;   /* "Couldn't bind column
-                                                * in SQLStatistics."; */
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_error_copy(stmt, indx_stmt); /* "Couldn't bind column * 
+                        * in SQLStatistics."; */
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
 
@@ -2597,8 +2564,7 @@ PGAPI_Statistics(
                    relhasrules, sizeof(relhasrules), NULL);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = indx_stmt->errormsg;
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_error_copy(stmt, indx_stmt);
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
    }
@@ -2708,8 +2674,7 @@ PGAPI_Statistics(
    if (result != SQL_NO_DATA_FOUND)
    {
        /* "SQLFetch failed in SQLStatistics."; */
-       stmt->errormsg = SC_create_errormsg(hindx_stmt);
-       stmt->errornumber = indx_stmt->errornumber;
+       SC_full_error_copy(stmt, indx_stmt);
        PGAPI_FreeStmt(hindx_stmt, SQL_DROP);
        goto SEEYA;
    }
@@ -2767,8 +2732,7 @@ PGAPI_ColumnPrivileges(
 
    /* Neither Access or Borland care about this. */
 
-   stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-   stmt->errormsg = "not implemented";
+   SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "not implemented");
    SC_log_error(func, "Function not implemented", stmt);
    return SQL_ERROR;
 }
@@ -2819,8 +2783,7 @@ PGAPI_PrimaryKeys(
 
    if (res = QR_Constructor(), !res)
    {
-       stmt->errormsg = "Couldn't allocate memory for PGAPI_PrimaryKeys result.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_PrimaryKeys result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2848,8 +2811,7 @@ PGAPI_PrimaryKeys(
    result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-       stmt->errormsg = "Couldn't allocate statement for Primary Key result.";
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for Primary Key result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2860,8 +2822,7 @@ PGAPI_PrimaryKeys(
    make_string(szTableName, cbTableName, pktab);
    if (pktab[0] == '\0')
    {
-       stmt->errormsg = "No Table specified to PGAPI_PrimaryKeys.";
-       stmt->errornumber = STMT_INTERNAL_ERROR;
+       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;
@@ -2874,8 +2835,7 @@ PGAPI_PrimaryKeys(
                           attname, MAX_INFO_STRING, &attname_len);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errormsg = tbl_stmt->errormsg;
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_error_copy(stmt, tbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -2952,8 +2912,7 @@ PGAPI_PrimaryKeys(
        result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = SC_create_errormsg(htbl_stmt);
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_full_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -2991,8 +2950,7 @@ PGAPI_PrimaryKeys(
 
    if (result != SQL_NO_DATA_FOUND)
    {
-       stmt->errormsg = SC_create_errormsg(htbl_stmt);
-       stmt->errornumber = tbl_stmt->errornumber;
+       SC_full_error_copy(stmt, htbl_stmt);
        SC_log_error(func, "", stmt);
        PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
        return SQL_ERROR;
@@ -3318,8 +3276,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
 
    if (res = QR_Constructor(), !res)
    {
-       stmt->errormsg = "Couldn't allocate memory for PGAPI_ForeignKeys result.";
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ForeignKeys result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -3373,8 +3330,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
    result = PGAPI_AllocStmt(stmt->hdbc, &htbl_stmt);
    if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
    {
-       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-       stmt->errormsg = "Couldn't allocate statement for PGAPI_ForeignKeys result.";
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate statement for PGAPI_ForeignKeys result.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -3483,8 +3439,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
 
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = SC_create_errormsg(htbl_stmt);
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_full_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3494,8 +3449,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                               trig_args, sizeof(trig_args), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3505,8 +3459,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                               &trig_nargs, 0, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3516,8 +3469,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                         trig_deferrable, sizeof(trig_deferrable), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3527,8 +3479,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                     trig_initdeferred, sizeof(trig_initdeferred), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3538,8 +3489,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                               upd_rule, sizeof(upd_rule), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3549,8 +3499,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                               del_rule, sizeof(del_rule), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3560,8 +3509,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                               &relid1, sizeof(relid1), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3570,8 +3518,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                               &relid2, sizeof(relid2), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3580,8 +3527,7 @@ char      schema_fetched[SCHEMA_NAME_STORAGE_LEN + 1];
                    pk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3593,8 +3539,7 @@ if (conn->schema_support)
                    schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3607,8 +3552,7 @@ if (conn->schema_support)
 
        if (result != SQL_SUCCESS)
        {
-           stmt->errormsg = SC_create_errormsg(htbl_stmt);
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_full_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3617,8 +3561,7 @@ if (conn->schema_support)
        keyresult = PGAPI_AllocStmt(stmt->hdbc, &hpkey_stmt);
        if ((keyresult != SQL_SUCCESS) && (keyresult != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errornumber = STMT_NO_MEMORY_ERROR;
-           stmt->errormsg = "Couldn't allocate statement for PGAPI_ForeignKeys (pkeys) result.";
+           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;
        }
@@ -3627,8 +3570,7 @@ if (conn->schema_support)
                                  pkey, sizeof(pkey), NULL);
        if (keyresult != SQL_SUCCESS)
        {
-           stmt->errornumber = STMT_NO_MEMORY_ERROR;
-           stmt->errormsg = "Couldn't bindcol for primary keys for PGAPI_ForeignKeys result.";
+           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;
@@ -3655,8 +3597,7 @@ if (conn->schema_support)
            keyresult = PGAPI_PrimaryKeys(hpkey_stmt, NULL, 0, schema_fetched, SQL_NTS, pk_table_fetched, SQL_NTS);
            if (keyresult != SQL_SUCCESS)
            {
-               stmt->errornumber = STMT_NO_MEMORY_ERROR;
-               stmt->errormsg = "Couldn't get primary keys for PGAPI_ForeignKeys result.";
+               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;
@@ -3882,8 +3823,7 @@ if (conn->schema_support)
        result = PGAPI_ExecDirect(htbl_stmt, tables_query, strlen(tables_query));
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = SC_create_errormsg(htbl_stmt);
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3893,8 +3833,7 @@ if (conn->schema_support)
                               trig_args, sizeof(trig_args), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3904,8 +3843,7 @@ if (conn->schema_support)
                               &trig_nargs, 0, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3915,8 +3853,7 @@ if (conn->schema_support)
                         trig_deferrable, sizeof(trig_deferrable), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3926,8 +3863,7 @@ if (conn->schema_support)
                     trig_initdeferred, sizeof(trig_initdeferred), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3937,8 +3873,7 @@ if (conn->schema_support)
                               upd_rule, sizeof(upd_rule), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3948,8 +3883,7 @@ if (conn->schema_support)
                               del_rule, sizeof(del_rule), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3959,8 +3893,7 @@ if (conn->schema_support)
                        &relid1, sizeof(relid1), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3969,8 +3902,7 @@ if (conn->schema_support)
                        &relid2, sizeof(relid2), NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -3979,26 +3911,24 @@ if (conn->schema_support)
                    fk_table_fetched, TABLE_NAME_STORAGE_LEN, NULL);
        if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
        }
 
-if (conn->schema_support)
-{
-       result = PGAPI_BindCol(htbl_stmt, 10, SQL_C_CHAR,
-                   schema_fetched, SCHEMA_NAME_STORAGE_LEN, NULL);
-       if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+       if (conn->schema_support)
        {
-           stmt->errormsg = tbl_stmt->errormsg;
-           stmt->errornumber = tbl_stmt->errornumber;
-           SC_log_error(func, "", stmt);
-           PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
-           return SQL_ERROR;
+           result = PGAPI_BindCol(htbl_stmt, 10, SQL_C_CHAR,
+                   schema_fetched, SCHEMA_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;
+           }
        }
-}
 
        result = PGAPI_Fetch(htbl_stmt);
        if (result == SQL_NO_DATA_FOUND)
@@ -4006,8 +3936,7 @@ if (conn->schema_support)
 
        if (result != SQL_SUCCESS)
        {
-           stmt->errormsg = SC_create_errormsg(htbl_stmt);
-           stmt->errornumber = tbl_stmt->errornumber;
+           SC_full_error_copy(stmt, tbl_stmt);
            SC_log_error(func, "", stmt);
            PGAPI_FreeStmt(htbl_stmt, SQL_DROP);
            return SQL_ERROR;
@@ -4126,8 +4055,7 @@ if (conn->schema_support)
    }
    else
    {
-       stmt->errormsg = "No tables specified to PGAPI_ForeignKeys.";
-       stmt->errornumber = STMT_INTERNAL_ERROR;
+       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;
@@ -4160,13 +4088,179 @@ PGAPI_ProcedureColumns(
 {
    static char *func = "PGAPI_ProcedureColumns";
    StatementClass  *stmt = (StatementClass *) hstmt;
+   ConnectionClass *conn = SC_get_conn(stmt);
+   char        proc_query[INFO_INQUIRY_LEN];
+   Int2        result_cols;
+   TupleNode   *row;
+   char        *schema_name, *procname, *params;
+   QResultClass *res, *tres;
+   Int4        tcount, paramcount, i, j, pgtype;
 
    mylog("%s: entering...\n", func);
 
-   stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-   stmt->errormsg = "not implemented";
-   SC_log_error(func, "Function not implemented", stmt);
-   return SQL_ERROR;
+   if (PG_VERSION_LT(conn, 6.5))
+   {
+       SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old");
+       SC_log_error(func, "Function not implemented", stmt);
+       return SQL_ERROR;
+   }
+   if (!SC_recycle_statement(stmt))
+       return SQL_ERROR;
+   if (conn->schema_support)
+   {
+       strcpy(proc_query, "select proname, proretset, prorettype, "
+               "pronargs, proargtypes, nspname from "
+               "pg_namespace, pg_proc where "
+               "pg_proc.pronamespace = pg_namespace.oid "
+               "and (not proretset)");
+       schema_strcat(proc_query, " and nspname like '%.*s'", szProcOwner, cbProcOwner, szProcName, cbProcName, conn);
+       my_strcat(proc_query, " and proname like '%.*s'", szProcName, cbProcName);
+       strcat(proc_query, " order by nspname, proname, proretset");
+   }
+   else
+   {
+       strcpy(proc_query, "select proname, proretset, prorettype, "
+               "pronargs, proargtypes from pg_proc where "
+               "(not proretset)");
+       my_strcat(proc_query, " and proname like '%.*s'", szProcName, cbProcName);
+       strcat(proc_query, " order by proname, proretset");
+   }
+   if (tres = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !tres)
+   {
+       SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_ProcedureColumns query error");
+       return SQL_ERROR;
+   }
+
+   stmt->manual_result = TRUE;
+   stmt->errormsg_created = TRUE;
+   if (res = QR_Constructor(), !res)
+   {
+       SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_ProcedureColumns result.");
+       SC_log_error(func, "", stmt);
+       return SQL_ERROR;
+   }
+   SC_set_Result(stmt, res);
+
+   /*
+    * the binding structure for a statement is not set up until
+    * a statement is actually executed, so we'll have to do this
+    * ourselves.
+    */
+#if (ODBCVER >= 0x0300)
+   result_cols = 19;
+#else
+   result_cols = 13;
+#endif /* ODBCVER */
+   extend_column_bindings(SC_get_ARD(stmt), result_cols);
+
+   /* set the field names */
+   QR_set_num_fields(res, result_cols);
+   QR_set_field_info(res, 0, "PROCEDURE_CAT", PG_TYPE_TEXT, MAX_INFO_STRING);
+   QR_set_field_info(res, 1, "PROCEDUR_SCHEM", PG_TYPE_TEXT, MAX_INFO_STRING);
+   QR_set_field_info(res, 2, "PROCEDURE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+   QR_set_field_info(res, 3, "COLUMN_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+   QR_set_field_info(res, 4, "COLUMN_TYPE", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 5, "DATA_TYPE", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 6, "TYPE_NAME", PG_TYPE_TEXT, MAX_INFO_STRING);
+   QR_set_field_info(res, 7, "COLUMN_SIZE", PG_TYPE_INT4, 4);
+   QR_set_field_info(res, 8, "BUFFER_LENGTH", PG_TYPE_INT4, 4);
+   QR_set_field_info(res, 9, "DECIMAL_DIGITS", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 10, "NUM_PREC_RADIX", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 11, "NULLABLE", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 12, "REMARKS", PG_TYPE_TEXT, MAX_INFO_STRING);
+#if (ODBCVER >= 0x0300)
+   QR_set_field_info(res, 13, "COLUMN_DEF", PG_TYPE_TEXT, MAX_INFO_STRING);
+   QR_set_field_info(res, 14, "SQL_DATA_TYPE", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 15, "SQL_DATATIME_SUB", PG_TYPE_INT2, 2);
+   QR_set_field_info(res, 16, "CHAR_OCTET_LENGTH", PG_TYPE_INT4, 4);
+   QR_set_field_info(res, 17, "ORIDINAL_POSITION", PG_TYPE_INT4, 4);
+   QR_set_field_info(res, 18, "IS_NULLABLE", PG_TYPE_TEXT, MAX_INFO_STRING);
+#endif   /* ODBCVER >= 0x0300 */
+
+   if (0 == cbColumnName || !szColumnName || !szColumnName[0])
+       tcount = QR_get_num_total_tuples(tres);
+   else
+       tcount = 0;
+   for (i = 0; i < tcount; i++)
+   {
+       if (conn->schema_support)
+           schema_name = GET_SCHEMA_NAME(QR_get_value_backend_row(tres, i, 5));
+       else
+           schema_name = NULL;
+       procname = QR_get_value_backend_row(tres, i, 0);
+       pgtype = atoi(QR_get_value_backend_row(tres, i, 2));
+       if (pgtype != 0)
+       {
+           row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
+           set_tuplefield_null(&row->tuple[0]);
+           set_nullfield_string(&row->tuple[1], schema_name);
+           set_tuplefield_string(&row->tuple[2], procname);
+           set_tuplefield_string(&row->tuple[3], "");
+           set_tuplefield_int2(&row->tuple[4], SQL_RETURN_VALUE);
+           set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype));
+           set_tuplefield_string(&row->tuple[6], pgtype_to_name(stmt, pgtype));
+           set_nullfield_int4(&row->tuple[7], pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC));
+           set_tuplefield_int4(&row->tuple[8], pgtype_buffer_length(stmt, pgtype, PG_STATIC, PG_STATIC));
+           set_nullfield_int2(&row->tuple[9], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
+           set_nullfield_int2(&row->tuple[10], pgtype_radix(stmt, pgtype));
+           set_tuplefield_int2(&row->tuple[11], SQL_NULLABLE_UNKNOWN);
+           set_tuplefield_null(&row->tuple[12]);
+#if (ODBCVER >= 0x0300)
+           set_tuplefield_null(&row->tuple[13]);
+           set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype));
+           set_nullfield_int2(&row->tuple[15], pgtype_to_datetime_sub(stmt, pgtype));
+           set_nullfield_int4(&row->tuple[16], pgtype_transfer_octet_length(stmt, pgtype, PG_STATIC, PG_STATIC));
+           set_tuplefield_int4(&row->tuple[17], 0);
+           set_tuplefield_string(&row->tuple[18], "");
+#endif   /* ODBCVER >= 0x0300 */
+           QR_add_tuple(res, row);
+       }
+       paramcount = atoi(QR_get_value_backend_row(tres, i, 3));
+       params = QR_get_value_backend_row(tres, i, 4);
+       for (j = 0; j < paramcount; j++)
+       {
+           while (isspace(*params))
+               params++;
+           sscanf(params, "%d", &pgtype);
+           row = (TupleNode *) malloc(sizeof(TupleNode) + (result_cols - 1) *sizeof(TupleField));
+           set_tuplefield_null(&row->tuple[0]);
+           set_nullfield_string(&row->tuple[1], schema_name);
+           set_tuplefield_string(&row->tuple[2], procname);
+           set_tuplefield_string(&row->tuple[3], "");
+           set_tuplefield_int2(&row->tuple[4], SQL_PARAM_INPUT);
+           set_tuplefield_int2(&row->tuple[5], pgtype_to_concise_type(stmt, pgtype));
+           set_tuplefield_string(&row->tuple[6], pgtype_to_name(stmt, pgtype));
+           set_nullfield_int4(&row->tuple[7], pgtype_column_size(stmt, pgtype, PG_STATIC, PG_STATIC));
+           set_tuplefield_int4(&row->tuple[8], pgtype_buffer_length(stmt, pgtype, PG_STATIC, PG_STATIC));
+           set_nullfield_int2(&row->tuple[9], pgtype_decimal_digits(stmt, pgtype, PG_STATIC));
+           set_nullfield_int2(&row->tuple[10], pgtype_radix(stmt, pgtype));
+           set_tuplefield_int2(&row->tuple[11], SQL_NULLABLE_UNKNOWN);
+           set_tuplefield_null(&row->tuple[12]);
+#if (ODBCVER >= 0x0300)
+           set_tuplefield_null(&row->tuple[13]);
+           set_nullfield_int2(&row->tuple[14], pgtype_to_sqldesctype(stmt, pgtype));
+           set_nullfield_int2(&row->tuple[15], pgtype_to_datetime_sub(stmt, pgtype));
+           set_nullfield_int4(&row->tuple[16], pgtype_transfer_octet_length(stmt, pgtype, PG_STATIC, PG_STATIC));
+           set_tuplefield_int4(&row->tuple[17], j + 1);
+           set_tuplefield_string(&row->tuple[18], "");
+#endif   /* ODBCVER >= 0x0300 */
+           QR_add_tuple(res, row);
+           while (isdigit(*params))
+               params++;
+       } 
+   }
+   QR_Destructor(tres);
+   /*
+    * 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;
+   stmt->current_col = -1;
+
+   return SQL_SUCCESS;
 }
 
 
@@ -4190,8 +4284,7 @@ PGAPI_Procedures(
 
    if (PG_VERSION_LT(conn, 6.5))
    {
-       stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-       stmt->errormsg = "Version is too old";
+       SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Version is too old");
        SC_log_error(func, "Function not implemented", stmt);
        return SQL_ERROR;
    }
@@ -4202,30 +4295,29 @@ PGAPI_Procedures(
     * The following seems the simplest implementation
     */
    if (conn->schema_support)
+   {
        strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", nspname as " "PROCEDURE_SCHEM" ","
        " proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
           " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
           " '' as " "REMARKS" ","
-          " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_namespace, pg_proc where");
+          " case when prorettype = 0 then 1::int2 else 2::int2 end as "          "PROCEDURE_TYPE" " from pg_namespace, pg_proc"
+         " where pg_proc.pronamespace = pg_namespace.oid");
+       schema_strcat(proc_query, " and nspname like '%.*s'", szProcOwner, cbProcOwner, szProcName, cbProcName, conn);
+       my_strcat(proc_query, " and proname like '%.*s'", szProcName, cbProcName);
+   }
    else
+   {
        strcpy(proc_query, "select '' as " "PROCEDURE_CAT" ", '' as " "PROCEDURE_SCHEM" ","
        " proname as " "PROCEDURE_NAME" ", '' as " "NUM_INPUT_PARAMS" ","
           " '' as " "NUM_OUTPUT_PARAMS" ", '' as " "NUM_RESULT_SETS" ","
           " '' as " "REMARKS" ","
           " case when prorettype = 0 then 1::int2 else 2::int2 end as " "PROCEDURE_TYPE" " from pg_proc");
-   if (conn->schema_support)
-   {
-       strcat(proc_query, " where pg_proc.pronamespace = pg_namespace.oid");
-       schema_strcat(proc_query, " and nspname like '%.*s'", szProcOwner, cbProcOwner, szProcName, cbProcName, conn);
-       my_strcat(proc_query, " and proname like '%.*s'", szProcName, cbProcName);
-   }
-   else
        my_strcat(proc_query, " where proname like '%.*s'", szProcName, cbProcName);
+   }
 
    if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
    {
-       stmt->errornumber = STMT_EXEC_ERROR;
-       stmt->errormsg = "PGAPI_Procedures query error";
+       SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_Procedures query error");
        return SQL_ERROR;
    }
    SC_set_Result(stmt, res);
@@ -4377,8 +4469,7 @@ PGAPI_TablePrivileges(
    strcat(proc_query, " pg_user.usesysid = relowner"); 
    if (res = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !res)
    {
-       stmt->errornumber = STMT_EXEC_ERROR;
-       stmt->errormsg = "PGAPI_TablePrivileges query error";
+       SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error");
        return SQL_ERROR;
    }
    strncpy_null(proc_query, "select usename, usesysid, usesuper from pg_user", sizeof(proc_query));
@@ -4386,8 +4477,7 @@ PGAPI_TablePrivileges(
    if (allures = CC_send_query(conn, proc_query, NULL, CLEAR_RESULT_ON_ABORT), !allures)
    {
        QR_Destructor(res);
-       stmt->errornumber = STMT_EXEC_ERROR;
-       stmt->errormsg = "PGAPI_TablePrivileges query error";
+       SC_set_error(stmt, STMT_EXEC_ERROR, "PGAPI_TablePrivileges query error");
        return SQL_ERROR;
    }
    usercount = QR_get_num_backend_tuples(allures);
index 5e5b8346901322942ebfae1db912148b461bd364..90072239435d06cc92eb3a72df8f95622ba7e60f 100644 (file)
--- a/info30.c
+++ b/info30.c
@@ -346,8 +346,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
            len = 0;
        default:
            /* unrecognized key */
-           conn->errormsg = "Unrecognized key passed to SQLGetInfo30.";
-           conn->errornumber = CONN_NOT_IMPLEMENTED_ERROR;
+           CC_set_error(conn, CONN_NOT_IMPLEMENTED_ERROR, "Unrecognized key passed to SQLGetInfo30.");
            CC_log_error(func, "", conn);
            return SQL_ERROR;
    }
@@ -373,8 +372,7 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
            if (len >= cbInfoValueMax)
            {
                result = SQL_SUCCESS_WITH_INFO;
-               conn->errornumber = CONN_TRUNCATED;
-               conn->errormsg = "The buffer was too small for tthe InfoValue.";
+               CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for tthe InfoValue.");
            }
        }
    }
diff --git a/misc.c b/misc.c
index 9a10c951e0fba03fbd66622c35bfbb9b58b05c89..ea8f2563a1f1523e12b5dad8406ebfd249d825fc 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -59,6 +59,9 @@ generate_filename(const char *dirname, const char *prefix, char *filename)
    return;
 }
 
+#ifdef WIN_MULTITHREAD_SUPPORT
+CRITICAL_SECTION   qlog_cs, mylog_cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
 static int mylog_on = 0,
            qlog_on = 0;
 void
@@ -69,6 +72,8 @@ logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
                qlog_on_count = 0,
                qlog_off_count = 0;
 
+   ENTER_MYLOG_CS;
+   ENTER_QLOG_CS;
    if (mylog_onoff)
        mylog_on_count += cnopen;
    else
@@ -89,6 +94,8 @@ logs_on_off(int cnopen, int mylog_onoff, int qlog_onoff)
        qlog_on = 0;
    else
        qlog_on = globals.commlog;
+   LEAVE_QLOG_CS;
+   LEAVE_MYLOG_CS;
 }
 
 #ifdef MY_LOG
@@ -99,6 +106,7 @@ mylog(char *fmt,...)
    char        filebuf[80];
    static FILE *LOGFP = NULL;
 
+   ENTER_MYLOG_CS;
    if (mylog_on)
    {
        va_start(args, fmt);
@@ -110,11 +118,18 @@ mylog(char *fmt,...)
            setbuf(LOGFP, NULL);
        }
 
+#ifdef WIN_MULTITHREAD_SUPPORT
+#ifdef WIN32
+       if (LOGFP)
+           fprintf(LOGFP, "[%d]", GetCurrentThreadId());
+#endif /* WIN32 */
+#endif /* WIN_MULTITHREAD_SUPPORT */
        if (LOGFP)
            vfprintf(LOGFP, fmt, args);
 
        va_end(args);
    }
+   LEAVE_MYLOG_CS;
 }
 #else
 void
@@ -132,6 +147,7 @@ qlog(char *fmt,...)
    char        filebuf[80];
    static FILE *LOGFP = NULL;
 
+   ENTER_QLOG_CS;
    if (qlog_on)
    {
        va_start(args, fmt);
@@ -148,6 +164,7 @@ qlog(char *fmt,...)
 
        va_end(args);
    }
+   LEAVE_QLOG_CS;
 }
 #endif
 
diff --git a/misc.h b/misc.h
index e2e34ce956b635671795d7b094d056808d9b8f9e..e55b91ad07b8cdf5471900542a8675295ed78155 100644 (file)
--- a/misc.h
+++ b/misc.h
 */
 #define Q_LOG
 
+#ifdef WIN_MULTITHREAD_SUPPORT
+#define    INIT_QLOG_CS    InitializeCriticalSection(&qlog_cs)
+#define    ENTER_QLOG_CS   EnterCriticalSection(&qlog_cs)
+#define    LEAVE_QLOG_CS   LeaveCriticalSection(&qlog_cs)
+#define    DELETE_QLOG_CS  DeleteCriticalSection(&qlog_cs)
+#define    INIT_MYLOG_CS   InitializeCriticalSection(&mylog_cs)
+#define    ENTER_MYLOG_CS  EnterCriticalSection(&mylog_cs)
+#define    LEAVE_MYLOG_CS  LeaveCriticalSection(&mylog_cs)
+#define    DELETE_MYLOG_CS DeleteCriticalSection(&mylog_cs)
+#else
+#define    INIT_QLOG_CS
+#define    ENTER_QLOG_CS
+#define    LEAVE_QLOG_CS
+#define    DELETE_QLOG_CS
+#define    INIT_MYLOG_CS
+#define    ENTER_MYLOG_CS
+#define    LEAVE_MYLOG_CS
+#define    DELETE_MYLOG_CS
+#endif /* WIN_MULTITHREAD_SUPPORT */
 
 #ifdef MY_LOG
 #define MYLOGFILE          "mylog_"
@@ -39,7 +58,7 @@
 #endif /* WIN32 */
 extern void mylog(char *fmt,...);
 
-#else
+#else /* MY_LOG */
 #ifndef WIN32
 #define mylog(args...)         /* GNU convention for variable arguments */
 #else
index 8c8c9f01a45d1aee56e87556f2c7110c557ce44f..28d396d945e9055116f2e31073a43e1f72de5560 100644 (file)
@@ -422,8 +422,7 @@ CC_lookup_characterset(ConnectionClass *self)
        if (stricmp(pg_CS_name(self->ccsc), encstr))
        {
            qlog(" Client encoding = '%s' and %s\n", self->client_encoding, pg_CS_name(self->ccsc));
-           self->errornumber = CONN_VALUE_OUT_OF_RANGE;  
-           self->errormsg = "client encoding mismatch"; 
+           CC_set_error(self, CONN_VALUE_OUT_OF_RANGE, "client encoding mismatch"); 
        }
    }
    else
index 6a4a618b38a233ec86f22144d0b1b2e022899146..b1f64ce2eb8dad4b2dc00bff72dba6c71833fb5a 100644 (file)
--- a/odbcapi.c
+++ b/odbcapi.c
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #include "pgapifunc.h"
+#include "environ.h"
 #include "connection.h"
 #include "statement.h"
 
@@ -38,24 +39,37 @@ RETCODE     SQL_API
 SQLAllocConnect(HENV EnvironmentHandle,
                HDBC FAR * ConnectionHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLAllocConnect]");
-   return PGAPI_AllocConnect(EnvironmentHandle, ConnectionHandle);
+   ENTER_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   ret = PGAPI_AllocConnect(EnvironmentHandle, ConnectionHandle);
+   LEAVE_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLAllocEnv(HENV FAR * EnvironmentHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLAllocEnv]");
-   return PGAPI_AllocEnv(EnvironmentHandle);
+   ret = PGAPI_AllocEnv(EnvironmentHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLAllocStmt(HDBC ConnectionHandle,
             HSTMT *StatementHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLAllocStmt]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
-   return PGAPI_AllocStmt(ConnectionHandle, StatementHandle);
+   ret = PGAPI_AllocStmt(ConnectionHandle, StatementHandle);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -64,10 +78,15 @@ SQLBindCol(HSTMT StatementHandle,
           PTR TargetValue, SQLINTEGER BufferLength,
           SQLINTEGER *StrLen_or_Ind)
 {
+   RETCODE ret;
+
    mylog("[SQLBindCol]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_BindCol(StatementHandle, ColumnNumber,
+   ret = PGAPI_BindCol(StatementHandle, ColumnNumber,
                   TargetType, TargetValue, BufferLength, StrLen_or_Ind);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -85,11 +104,16 @@ SQLColumns(HSTMT StatementHandle,
           SQLCHAR *TableName, SQLSMALLINT NameLength3,
           SQLCHAR *ColumnName, SQLSMALLINT NameLength4)
 {
+   RETCODE ret;
+
    mylog("[SQLColumns]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_Columns(StatementHandle, CatalogName, NameLength1,
+   ret = PGAPI_Columns(StatementHandle, CatalogName, NameLength1,
                    SchemaName, NameLength2, TableName, NameLength3,
                    ColumnName, NameLength4, 0);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 
@@ -99,10 +123,15 @@ SQLConnect(HDBC ConnectionHandle,
           SQLCHAR *UserName, SQLSMALLINT NameLength2,
           SQLCHAR *Authentication, SQLSMALLINT NameLength3)
 {
+   RETCODE ret;
+
    mylog("[SQLConnect]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
-   return PGAPI_Connect(ConnectionHandle, ServerName, NameLength1,
+   ret = PGAPI_Connect(ConnectionHandle, ServerName, NameLength1,
                     UserName, NameLength2, Authentication, NameLength3);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -115,10 +144,15 @@ SQLDriverConnect(HDBC hdbc,
                 SWORD FAR * pcbConnStrOut,
                 UWORD fDriverCompletion)
 {
+   RETCODE ret;
+
    mylog("[SQLDriverConnect]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    CC_clear_error((ConnectionClass *) hdbc);
-   return PGAPI_DriverConnect(hdbc, hwnd, szConnStrIn, cbConnStrIn,
+   ret = PGAPI_DriverConnect(hdbc, hwnd, szConnStrIn, cbConnStrIn,
        szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
+   return ret;
 }
 RETCODE        SQL_API
 SQLBrowseConnect(
@@ -129,10 +163,15 @@ SQLBrowseConnect(
                 SQLSMALLINT cbConnStrOutMax,
                 SQLSMALLINT *pcbConnStrOut)
 {
+   RETCODE ret;
+
    mylog("[SQLBrowseConnect]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    CC_clear_error((ConnectionClass *) hdbc);
-   return PGAPI_BrowseConnect(hdbc, szConnStrIn, cbConnStrIn,
+   ret = PGAPI_BrowseConnect(hdbc, szConnStrIn, cbConnStrIn,
                           szConnStrOut, cbConnStrOutMax, pcbConnStrOut);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -159,19 +198,29 @@ SQLDescribeCol(HSTMT StatementHandle,
               SQLSMALLINT *DataType, SQLUINTEGER *ColumnSize,
               SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable)
 {
+   RETCODE ret;
+
    mylog("[SQLDescribeCol]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_DescribeCol(StatementHandle, ColumnNumber,
+   ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
                             ColumnName, BufferLength, NameLength,
                          DataType, ColumnSize, DecimalDigits, Nullable);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLDisconnect(HDBC ConnectionHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLDisconnect]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
-   return PGAPI_Disconnect(ConnectionHandle);
+   ret = PGAPI_Disconnect(ConnectionHandle);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -181,93 +230,134 @@ SQLError(HENV EnvironmentHandle,
         SQLCHAR *MessageText, SQLSMALLINT BufferLength,
         SQLSMALLINT *TextLength)
 {
+   RETCODE ret;
+
    mylog("[SQLError]");
-   return PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
+   if (NULL != EnvironmentHandle)
+       ENTER_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   ret = PGAPI_Error(EnvironmentHandle, ConnectionHandle, StatementHandle,
           Sqlstate, NativeError, MessageText, BufferLength,
        TextLength);
+   if (NULL != EnvironmentHandle)
+       LEAVE_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLExecDirect(HSTMT StatementHandle,
              SQLCHAR *StatementText, SQLINTEGER TextLength)
 {
+   RETCODE ret;
+
    mylog("[SQLExecDirect]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_ExecDirect(StatementHandle, StatementText, TextLength);
+   ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLExecute(HSTMT StatementHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLExecute]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_Execute(StatementHandle);
+   ret = PGAPI_Execute(StatementHandle);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLFetch(HSTMT StatementHandle)
 {
    static char *func = "SQLFetch";
-
-#if (ODBCVER >= 0x0300)
+   RETCODE ret;
    StatementClass *stmt = (StatementClass *) StatementHandle;
-   ConnectionClass *conn = SC_get_conn(stmt);
 
+   ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   if (conn->driver_version >= 0x0300)
+#if (ODBCVER >= 0x0300)
+   if (SC_get_conn(stmt)->driver_version >= 0x0300)
    {
        IRDFields   *irdopts = SC_get_IRD(stmt);
        SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
        SQLINTEGER *pcRow = irdopts->rowsFetched;
 
        mylog("[[%s]]", func);
-       return PGAPI_ExtendedFetch(StatementHandle, SQL_FETCH_NEXT, 0,
+       ret = PGAPI_ExtendedFetch(StatementHandle, SQL_FETCH_NEXT, 0,
                                   pcRow, rowStatusArray, 0);
    }
+   else
 #endif
-   mylog("[%s]", func);
-   return PGAPI_Fetch(StatementHandle);
+   {
+       mylog("[%s]", func);
+       ret = PGAPI_Fetch(StatementHandle);
+   }
+   LEAVE_STMT_CS(stmt);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLFreeConnect(HDBC ConnectionHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLFreeConnect]");
-   return PGAPI_FreeConnect(ConnectionHandle);
+   ret = PGAPI_FreeConnect(ConnectionHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLFreeEnv(HENV EnvironmentHandle)
 {
+   RETCODE ret;
+
    mylog("[SQLFreeEnv]");
-   return PGAPI_FreeEnv(EnvironmentHandle);
+   ret = PGAPI_FreeEnv(EnvironmentHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLFreeStmt(HSTMT StatementHandle,
            SQLUSMALLINT Option)
 {
+   RETCODE ret;
+
    mylog("[SQLFreeStmt]");
-   return PGAPI_FreeStmt(StatementHandle, Option);
+   ret = PGAPI_FreeStmt(StatementHandle, Option);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLGetConnectOption(HDBC ConnectionHandle,
                    SQLUSMALLINT Option, PTR Value)
 {
+   RETCODE ret;
+
    mylog("[SQLGetConnectOption]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
-   return PGAPI_GetConnectOption(ConnectionHandle, Option, Value);
+   ret = PGAPI_GetConnectOption(ConnectionHandle, Option, Value);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 RETCODE        SQL_API
 SQLGetCursorName(HSTMT StatementHandle,
                 SQLCHAR *CursorName, SQLSMALLINT BufferLength,
                 SQLSMALLINT *NameLength)
 {
+   RETCODE ret;
+
    mylog("[SQLGetCursorName]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_GetCursorName(StatementHandle, CursorName, BufferLength,
+   ret = PGAPI_GetCursorName(StatementHandle, CursorName, BufferLength,
                               NameLength);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -276,23 +366,36 @@ SQLGetData(HSTMT StatementHandle,
           PTR TargetValue, SQLINTEGER BufferLength,
           SQLINTEGER *StrLen_or_Ind)
 {
+   RETCODE ret;
+
    mylog("[SQLGetData]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_GetData(StatementHandle, ColumnNumber, TargetType,
+   ret = PGAPI_GetData(StatementHandle, ColumnNumber, TargetType,
                         TargetValue, BufferLength, StrLen_or_Ind);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLGetFunctions(HDBC ConnectionHandle,
                SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported)
 {
+   RETCODE ret;
+
    mylog("[SQLGetFunctions]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
 #if (ODBCVER >= 0x0300)
    if (FunctionId == SQL_API_ODBC3_ALL_FUNCTIONS)
-       return PGAPI_GetFunctions30(ConnectionHandle, FunctionId, Supported);
+       ret = PGAPI_GetFunctions30(ConnectionHandle, FunctionId, Supported);
+   else
 #endif
-   return PGAPI_GetFunctions(ConnectionHandle, FunctionId, Supported);
+   {
+       ret = PGAPI_GetFunctions(ConnectionHandle, FunctionId, Supported);
+   }
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 RETCODE        SQL_API
 SQLGetInfo(HDBC ConnectionHandle,
@@ -302,6 +405,7 @@ SQLGetInfo(HDBC ConnectionHandle,
    RETCODE     ret;
    ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error(conn);
 #if (ODBCVER >= 0x0300)
    mylog("[SQLGetInfo(30)]");
@@ -323,6 +427,7 @@ SQLGetInfo(HDBC ConnectionHandle,
            BufferLength, StringLength), SQL_ERROR == ret)
        CC_log_error("PGAPI_GetInfo", "", conn);
 #endif
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
    return ret;
 }
 
@@ -330,81 +435,126 @@ RETCODE      SQL_API
 SQLGetStmtOption(HSTMT StatementHandle,
                 SQLUSMALLINT Option, PTR Value)
 {
+   RETCODE ret;
+
    mylog("[SQLGetStmtOption]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_GetStmtOption(StatementHandle, Option, Value);
+   ret = PGAPI_GetStmtOption(StatementHandle, Option, Value);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLGetTypeInfo(HSTMT StatementHandle,
               SQLSMALLINT DataType)
 {
+   RETCODE ret;
+
    mylog("[SQLGetTypeInfo]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_GetTypeInfo(StatementHandle, DataType);
+   ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLNumResultCols(HSTMT StatementHandle,
                 SQLSMALLINT *ColumnCount)
 {
+   RETCODE ret;
+
    mylog("[SQLNumResultCols]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_NumResultCols(StatementHandle, ColumnCount);
+   ret = PGAPI_NumResultCols(StatementHandle, ColumnCount);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLParamData(HSTMT StatementHandle,
             PTR *Value)
 {
+   RETCODE ret;
+
    mylog("[SQLParamData]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_ParamData(StatementHandle, Value);
+   ret = PGAPI_ParamData(StatementHandle, Value);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLPrepare(HSTMT StatementHandle,
           SQLCHAR *StatementText, SQLINTEGER TextLength)
 {
+   RETCODE ret;
+
    mylog("[SQLPrepare]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_Prepare(StatementHandle, StatementText, TextLength);
+   ret = PGAPI_Prepare(StatementHandle, StatementText, TextLength);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLPutData(HSTMT StatementHandle,
           PTR Data, SQLINTEGER StrLen_or_Ind)
 {
+   RETCODE ret;
+
    mylog("[SQLPutData]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_PutData(StatementHandle, Data, StrLen_or_Ind);
+   ret = PGAPI_PutData(StatementHandle, Data, StrLen_or_Ind);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLRowCount(HSTMT StatementHandle,
            SQLINTEGER *RowCount)
 {
+   RETCODE ret;
+
    mylog("[SQLRowCount]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_RowCount(StatementHandle, RowCount);
+   ret = PGAPI_RowCount(StatementHandle, RowCount);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLSetConnectOption(HDBC ConnectionHandle,
                    SQLUSMALLINT Option, SQLUINTEGER Value)
 {
+   RETCODE ret;
+
    mylog("[SQLSetConnectionOption]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
-   return PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
+   ret = PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLSetCursorName(HSTMT StatementHandle,
                 SQLCHAR *CursorName, SQLSMALLINT NameLength)
 {
+   RETCODE ret;
+
    mylog("[SQLSetCursorName]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_SetCursorName(StatementHandle, CursorName, NameLength);
+   ret = PGAPI_SetCursorName(StatementHandle, CursorName, NameLength);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -429,9 +579,14 @@ RETCODE        SQL_API
 SQLSetStmtOption(HSTMT StatementHandle,
                 SQLUSMALLINT Option, SQLUINTEGER Value)
 {
+   RETCODE ret;
+
    mylog("[SQLSetStmtOption]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_SetStmtOption(StatementHandle, Option, Value);
+   ret = PGAPI_SetStmtOption(StatementHandle, Option, Value);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -442,11 +597,16 @@ SQLSpecialColumns(HSTMT StatementHandle,
                  SQLSMALLINT NameLength3, SQLUSMALLINT Scope,
                  SQLUSMALLINT Nullable)
 {
+   RETCODE ret;
+
    mylog("[SQLSpecialColumns]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_SpecialColumns(StatementHandle, IdentifierType, CatalogName,
+   ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, CatalogName,
            NameLength1, SchemaName, NameLength2, TableName, NameLength3,
                                Scope, Nullable);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -456,11 +616,16 @@ SQLStatistics(HSTMT StatementHandle,
              SQLCHAR *TableName, SQLSMALLINT NameLength3,
              SQLUSMALLINT Unique, SQLUSMALLINT Reserved)
 {
+   RETCODE ret;
+
    mylog("[SQLStatistics]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_Statistics(StatementHandle, CatalogName, NameLength1,
+   ret = PGAPI_Statistics(StatementHandle, CatalogName, NameLength1,
                 SchemaName, NameLength2, TableName, NameLength3, Unique,
                            Reserved);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -470,19 +635,35 @@ SQLTables(HSTMT StatementHandle,
          SQLCHAR *TableName, SQLSMALLINT NameLength3,
          SQLCHAR *TableType, SQLSMALLINT NameLength4)
 {
+   RETCODE ret;
+
    mylog("[SQLTables]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_Tables(StatementHandle, CatalogName, NameLength1,
+   ret = PGAPI_Tables(StatementHandle, CatalogName, NameLength1,
                        SchemaName, NameLength2, TableName, NameLength3,
                        TableType, NameLength4);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLTransact(HENV EnvironmentHandle,
            HDBC ConnectionHandle, SQLUSMALLINT CompletionType)
 {
+   RETCODE ret;
+
    mylog("[SQLTransact]");
-   return PGAPI_Transact(EnvironmentHandle, ConnectionHandle, CompletionType);
+   if (NULL != EnvironmentHandle)
+       ENTER_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   else
+       ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
+   ret = PGAPI_Transact(EnvironmentHandle, ConnectionHandle, CompletionType);
+   if (NULL != EnvironmentHandle)
+       LEAVE_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   else
+       LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -495,10 +676,15 @@ SQLColAttributes(
                 SQLSMALLINT *pcbDesc,
                 SQLINTEGER *pfDesc)
 {
+   RETCODE ret;
+
    mylog("[SQLColAttributes]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
+   ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
                               cbDescMax, pcbDesc, pfDesc);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -513,11 +699,16 @@ SQLColumnPrivileges(
                    SQLCHAR *szColumnName,
                    SQLSMALLINT cbColumnName)
 {
+   RETCODE ret;
+
    mylog("[SQLColumnPrivileges]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_ColumnPrivileges(hstmt, szCatalogName, cbCatalogName,
+   ret = PGAPI_ColumnPrivileges(hstmt, szCatalogName, cbCatalogName,
                    szSchemaName, cbSchemaName, szTableName, cbTableName,
                                  szColumnName, cbColumnName);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -529,10 +720,15 @@ SQLDescribeParam(
                 SQLSMALLINT *pibScale,
                 SQLSMALLINT *pfNullable)
 {
+   RETCODE ret;
+
    mylog("[SQLDescribeParam]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_DescribeParam(hstmt, ipar, pfSqlType, pcbParamDef,
+   ret = PGAPI_DescribeParam(hstmt, ipar, pfSqlType, pcbParamDef,
                               pibScale, pfNullable);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -543,9 +739,14 @@ SQLExtendedFetch(
                 SQLUINTEGER *pcrow,
                 SQLUSMALLINT *rgfRowStatus)
 {
+   RETCODE ret;
+
    mylog("[SQLExtendedFetch]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_ExtendedFetch(hstmt, fFetchType, irow, pcrow, rgfRowStatus, 0);
+   ret = PGAPI_ExtendedFetch(hstmt, fFetchType, irow, pcrow, rgfRowStatus, 0);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -564,20 +765,29 @@ SQLForeignKeys(
               SQLCHAR *szFkTableName,
               SQLSMALLINT cbFkTableName)
 {
+   RETCODE ret;
+
    mylog("[SQLForeignKeys]");
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_ForeignKeys(hstmt, szPkCatalogName, cbPkCatalogName,
+   ret = PGAPI_ForeignKeys(hstmt, szPkCatalogName, cbPkCatalogName,
                           szPkSchemaName, cbPkSchemaName, szPkTableName,
                         cbPkTableName, szFkCatalogName, cbFkCatalogName,
           szFkSchemaName, cbFkSchemaName, szFkTableName, cbFkTableName);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
 SQLMoreResults(HSTMT hstmt)
 {
+   RETCODE ret;
+
    mylog("[SQLMoreResults]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_MoreResults(hstmt);
+   ret = PGAPI_MoreResults(hstmt);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -589,10 +799,15 @@ SQLNativeSql(
             SQLINTEGER cbSqlStrMax,
             SQLINTEGER *pcbSqlStr)
 {
+   RETCODE ret;
+
    mylog("[SQLNativeSql]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    CC_clear_error((ConnectionClass *) hdbc);
-   return PGAPI_NativeSql(hdbc, szSqlStrIn, cbSqlStrIn, szSqlStr,
+   ret = PGAPI_NativeSql(hdbc, szSqlStrIn, cbSqlStrIn, szSqlStr,
                           cbSqlStrMax, pcbSqlStr);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -600,9 +815,14 @@ SQLNumParams(
             HSTMT hstmt,
             SQLSMALLINT *pcpar)
 {
+   RETCODE ret;
+
    mylog("[SQLNumParams]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_NumParams(hstmt, pcpar);
+   ret = PGAPI_NumParams(hstmt, pcpar);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -611,9 +831,14 @@ SQLParamOptions(
                SQLUINTEGER crow,
                SQLUINTEGER *pirow)
 {
+   RETCODE ret;
+
    mylog("[SQLParamOptions]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_ParamOptions(hstmt, crow, pirow);
+   ret = PGAPI_ParamOptions(hstmt, crow, pirow);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -626,10 +851,15 @@ SQLPrimaryKeys(
               SQLCHAR *szTableName,
               SQLSMALLINT cbTableName)
 {
+   RETCODE ret;
+
    mylog("[SQLPrimaryKeys]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_PrimaryKeys(hstmt, szCatalogName, cbCatalogName,
+   ret = PGAPI_PrimaryKeys(hstmt, szCatalogName, cbCatalogName,
                   szSchemaName, cbSchemaName, szTableName, cbTableName);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -644,11 +874,16 @@ SQLProcedureColumns(
                    SQLCHAR *szColumnName,
                    SQLSMALLINT cbColumnName)
 {
+   RETCODE ret;
+
    mylog("[SQLProcedureColumns]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_ProcedureColumns(hstmt, szCatalogName, cbCatalogName,
+   ret = PGAPI_ProcedureColumns(hstmt, szCatalogName, cbCatalogName,
                      szSchemaName, cbSchemaName, szProcName, cbProcName,
                                  szColumnName, cbColumnName);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -661,10 +896,15 @@ SQLProcedures(
              SQLCHAR *szProcName,
              SQLSMALLINT cbProcName)
 {
+   RETCODE ret;
+
    mylog("[SQLProcedures]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_Procedures(hstmt, szCatalogName, cbCatalogName,
+   ret = PGAPI_Procedures(hstmt, szCatalogName, cbCatalogName,
                     szSchemaName, cbSchemaName, szProcName, cbProcName);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -674,9 +914,14 @@ SQLSetPos(
          SQLUSMALLINT fOption,
          SQLUSMALLINT fLock)
 {
+   RETCODE ret;
+
    mylog("[SQLSetPos]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_SetPos(hstmt, irow, fOption, fLock);
+   ret = PGAPI_SetPos(hstmt, irow, fOption, fLock);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -689,10 +934,15 @@ SQLTablePrivileges(
                   SQLCHAR *szTableName,
                   SQLSMALLINT cbTableName)
 {
+   RETCODE ret;
+
    mylog("[SQLTablePrivileges]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName,
+   ret = PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName,
                   szSchemaName, cbSchemaName, szTableName, cbTableName, 0);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
 
 RETCODE        SQL_API
@@ -708,9 +958,14 @@ SQLBindParameter(
                 SQLINTEGER cbValueMax,
                 SQLINTEGER *pcbValue)
 {
+   RETCODE ret;
+
    mylog("[SQLBindParameter]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
-   return PGAPI_BindParameter(hstmt, ipar, fParamType, fCType,
+   ret = PGAPI_BindParameter(hstmt, ipar, fParamType, fCType,
                       fSqlType, cbColDef, ibScale, rgbValue, cbValueMax,
                               pcbValue);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
+   return ret;
 }
index cf73924065e3237b60c1392f84c72c867f2929e8..6cd70ced10c937475de4f7b8b923371b6b056b90 100644 (file)
@@ -35,19 +35,28 @@ RETCODE     SQL_API
 SQLAllocHandle(SQLSMALLINT HandleType,
               SQLHANDLE InputHandle, SQLHANDLE * OutputHandle)
 {
+   RETCODE     ret;
    mylog("[[SQLAllocHandle]]");
    switch (HandleType)
    {
        case SQL_HANDLE_ENV:
-           return PGAPI_AllocEnv(OutputHandle);
+           ret = PGAPI_AllocEnv(OutputHandle);
+           break;
        case SQL_HANDLE_DBC:
-           return PGAPI_AllocConnect(InputHandle, OutputHandle);
+           ENTER_ENV_CS((EnvironmentClass *) InputHandle);
+           ret = PGAPI_AllocConnect(InputHandle, OutputHandle);
+           LEAVE_ENV_CS((EnvironmentClass *) InputHandle);
+           break;
        case SQL_HANDLE_STMT:
-           return PGAPI_AllocStmt(InputHandle, OutputHandle);
+           ENTER_CONN_CS((ConnectionClass *) InputHandle);
+           ret = PGAPI_AllocStmt(InputHandle, OutputHandle);
+           LEAVE_CONN_CS((ConnectionClass *) InputHandle);
+           break;
        default:
+           ret = SQL_ERROR;
            break;
    }
-   return SQL_ERROR;
+   return ret;
 }
 
 /* SQLBindParameter/SQLSetParam -> SQLBindParam */
@@ -58,20 +67,29 @@ SQLBindParam(HSTMT StatementHandle,
             SQLSMALLINT ParameterScale, PTR ParameterValue,
             SQLINTEGER *StrLen_or_Ind)
 {
+   RETCODE         ret;
    int         BufferLength = 512;     /* Is it OK ? */
 
    mylog("[[SQLBindParam]]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_BindParameter(StatementHandle, ParameterNumber, SQL_PARAM_INPUT, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, BufferLength, StrLen_or_Ind);
+   ret = PGAPI_BindParameter(StatementHandle, ParameterNumber, SQL_PARAM_INPUT, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, BufferLength, StrLen_or_Ind);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 /* New function */
 RETCODE        SQL_API
 SQLCloseCursor(HSTMT StatementHandle)
 {
+   RETCODE ret;
+
    mylog("[[SQLCloseCursor]]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_FreeStmt(StatementHandle, SQL_CLOSE);
+   ret = PGAPI_FreeStmt(StatementHandle, SQL_CLOSE);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 /* SQLColAttributes -> SQLColAttribute */
@@ -81,11 +99,16 @@ SQLColAttribute(HSTMT StatementHandle,
                PTR CharacterAttribute, SQLSMALLINT BufferLength,
                SQLSMALLINT *StringLength, PTR NumericAttribute)
 {
+   RETCODE ret;
+
    mylog("[[SQLColAttribute]]");
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_ColAttributes(StatementHandle, ColumnNumber,
+   ret = PGAPI_ColAttributes(StatementHandle, ColumnNumber,
                       FieldIdentifier, CharacterAttribute, BufferLength,
                               StringLength, NumericAttribute);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 static HSTMT
@@ -137,18 +160,27 @@ RETCODE       SQL_API
 SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle,
           SQLSMALLINT CompletionType)
 {
+   RETCODE ret;
+
    mylog("[[SQLEndTran]]");
    switch (HandleType)
    {
        case SQL_HANDLE_ENV:
-           return PGAPI_Transact(Handle, SQL_NULL_HDBC, CompletionType);
+           ENTER_ENV_CS((EnvironmentClass *) Handle);
+           ret = PGAPI_Transact(Handle, SQL_NULL_HDBC, CompletionType);
+           LEAVE_ENV_CS((EnvironmentClass *) Handle);
+           break;
        case SQL_HANDLE_DBC:
+           ENTER_CONN_CS((ConnectionClass *) Handle);
            CC_clear_error((ConnectionClass *) Handle);
-           return PGAPI_Transact(SQL_NULL_HENV, Handle, CompletionType);
+           ret = PGAPI_Transact(SQL_NULL_HENV, Handle, CompletionType);
+           LEAVE_CONN_CS((ConnectionClass *) Handle);
+           break;
        default:
+           ret = SQL_ERROR;
            break;
    }
-   return SQL_ERROR;
+   return ret;
 }
 
 /* SQLExtendedFetch -> SQLFetchScroll */
@@ -158,12 +190,13 @@ SQLFetchScroll(HSTMT StatementHandle,
 {
    static char *func = "SQLFetchScroll";
    StatementClass *stmt = (StatementClass *) StatementHandle;
-   RETCODE     ret;
+   RETCODE     ret = SQL_SUCCESS;
    IRDFields   *irdopts = SC_get_IRD(stmt);
    SQLUSMALLINT *rowStatusArray = irdopts->rowStatusArray;
    SQLINTEGER *pcRow = irdopts->rowsFetched, bkmarkoff = 0;
 
    mylog("[[%s]] %d,%d\n", func, FetchOrientation, FetchOffset);
+   ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
    if (FetchOrientation == SQL_FETCH_BOOKMARK)
    {
@@ -175,14 +208,15 @@ mylog("bookmark=%u FetchOffset = %d\n", FetchOffset, bkmarkoff);
        }
        else
        {
-           stmt->errornumber = STMT_SEQUENCE_ERROR;
-           stmt->errormsg = "Bookmark isn't specifed yet";
+           SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Bookmark isn't specifed yet");
            SC_log_error(func, "", stmt);
-           return SQL_ERROR;
+           ret = SQL_ERROR;
        }
    }
-   ret = PGAPI_ExtendedFetch(StatementHandle, FetchOrientation, FetchOffset,
+   if (SQL_SUCCESS == ret)
+       ret = PGAPI_ExtendedFetch(StatementHandle, FetchOrientation, FetchOffset,
                pcRow, rowStatusArray, bkmarkoff);
+   LEAVE_STMT_CS(stmt);
    if (ret != SQL_SUCCESS)
        mylog("%s return = %d\n", func, ret);
    return ret;
@@ -192,19 +226,24 @@ mylog("bookmark=%u FetchOffset = %d\n", FetchOffset, bkmarkoff);
 RETCODE        SQL_API
 SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)
 {
+   RETCODE     ret;
    mylog("[[SQLFreeHandle]]");
    switch (HandleType)
    {
        case SQL_HANDLE_ENV:
-           return PGAPI_FreeEnv(Handle);
+           ret = PGAPI_FreeEnv(Handle);
+           break;
        case SQL_HANDLE_DBC:
-           return PGAPI_FreeConnect(Handle);
+           ret = PGAPI_FreeConnect(Handle);
+           break;
        case SQL_HANDLE_STMT:
-           return PGAPI_FreeStmt(Handle, SQL_DROP);
+           ret = PGAPI_FreeStmt(Handle, SQL_DROP);
+           break;
        default:
+           ret = SQL_ERROR;
            break;
    }
-   return SQL_ERROR;
+   return ret;
 }
 
 /* new function */
@@ -214,9 +253,12 @@ SQLGetDescField(SQLHDESC DescriptorHandle,
                PTR Value, SQLINTEGER BufferLength,
                SQLINTEGER *StringLength)
 {
+   RETCODE ret;
+
    mylog("[[SQLGetDescField]]\n");
-   return PGAPI_GetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
+   ret = PGAPI_GetDescField(DescriptorHandle, RecNumber, FieldIdentifier,
            Value, BufferLength, StringLength);
+   return ret;
 }
 
 /* new function */
@@ -240,9 +282,12 @@ SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                PTR DiagInfo, SQLSMALLINT BufferLength,
                SQLSMALLINT *StringLength)
 {
+   RETCODE ret;
+
    mylog("[[SQLGetDiagField]] Handle=(%u,%x) Rec=%d Id=%d\n", HandleType, Handle, RecNumber, DiagIdentifier);
-   return PGAPI_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier,
+   ret = PGAPI_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier,
                DiagInfo, BufferLength, StringLength);
+   return ret;
 }
 
 /* SQLError -> SQLDiagRec */
@@ -252,9 +297,12 @@ SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
              SQLINTEGER *NativeError, SQLCHAR *MessageText,
              SQLSMALLINT BufferLength, SQLSMALLINT *TextLength)
 {
+   RETCODE ret;
+
    mylog("[[SQLGetDiagRec]]\n");
-   return PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
+   ret = PGAPI_GetDiagRec(HandleType, Handle, RecNumber, Sqlstate,
            NativeError, MessageText, BufferLength, TextLength);
+   return ret;
 }
 
 /* new function */
@@ -263,13 +311,16 @@ SQLGetEnvAttr(HENV EnvironmentHandle,
              SQLINTEGER Attribute, PTR Value,
              SQLINTEGER BufferLength, SQLINTEGER *StringLength)
 {
+   RETCODE ret;
    EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle;
 
    mylog("[[SQLGetEnvAttr]] %d\n", Attribute);
+   ENTER_ENV_CS(env);
+   ret = SQL_SUCCESS;
    switch (Attribute)
    {
        case SQL_ATTR_CONNECTION_POOLING:
-           *((unsigned int *) Value) = SQL_CP_OFF;
+           *((unsigned int *) Value) = EN_is_pooling(env) ? SQL_CP_ONE_PER_DRIVER : SQL_CP_OFF;
            break;
        case SQL_ATTR_CP_MATCH:
            *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH;
@@ -282,9 +333,10 @@ SQLGetEnvAttr(HENV EnvironmentHandle,
            break;
        default:
            env->errornumber = CONN_INVALID_ARGUMENT_NO;
-           return SQL_ERROR;
+           ret = SQL_ERROR;
    }
-   return SQL_SUCCESS;
+   LEAVE_ENV_CS(env);
+   return ret;
 }
 
 /* SQLGetConnectOption -> SQLGetconnectAttr */
@@ -293,10 +345,15 @@ SQLGetConnectAttr(HDBC ConnectionHandle,
                  SQLINTEGER Attribute, PTR Value,
                  SQLINTEGER BufferLength, SQLINTEGER *StringLength)
 {
+   RETCODE ret;
+
    mylog("[[SQLGetConnectAttr]] %d\n", Attribute);
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    CC_clear_error((ConnectionClass *) ConnectionHandle);
-   return PGAPI_GetConnectAttr(ConnectionHandle, Attribute,Value,
+   ret = PGAPI_GetConnectAttr(ConnectionHandle, Attribute,Value,
            BufferLength, StringLength);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   return ret;
 }
 
 /* SQLGetStmtOption -> SQLGetStmtAttr */
@@ -305,12 +362,16 @@ SQLGetStmtAttr(HSTMT StatementHandle,
               SQLINTEGER Attribute, PTR Value,
               SQLINTEGER BufferLength, SQLINTEGER *StringLength)
 {
+   RETCODE ret;
    static char *func = "SQLGetStmtAttr";
 
    mylog("[[%s]] Handle=%u %d\n", func, StatementHandle, Attribute);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    SC_clear_error((StatementClass *) StatementHandle);
-   return PGAPI_GetStmtAttr(StatementHandle, Attribute, Value,
+   ret = PGAPI_GetStmtAttr(StatementHandle, Attribute, Value,
            BufferLength, StringLength);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
 
 /* SQLSetConnectOption -> SQLSetConnectAttr */
@@ -319,12 +380,16 @@ SQLSetConnectAttr(HDBC ConnectionHandle,
                  SQLINTEGER Attribute, PTR Value,
                  SQLINTEGER StringLength)
 {
+   RETCODE ret;
    ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[[SQLSetConnectAttr]] %d\n", Attribute);
+   ENTER_CONN_CS(conn);
    CC_clear_error(conn);
-   return PGAPI_SetConnectAttr(ConnectionHandle, Attribute, Value,
+   ret = PGAPI_SetConnectAttr(ConnectionHandle, Attribute, Value,
                  StringLength);
+   LEAVE_CONN_CS(conn);
+   return ret;
 }
 
 /* new function */
@@ -363,36 +428,59 @@ SQLSetEnvAttr(HENV EnvironmentHandle,
              SQLINTEGER Attribute, PTR Value,
              SQLINTEGER StringLength)
 {
+   RETCODE ret;
    EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle;
 
    mylog("[[SQLSetEnvAttr]] att=%d,%u\n", Attribute, Value);
+   ENTER_ENV_CS(env);
    switch (Attribute)
    {
        case SQL_ATTR_CONNECTION_POOLING:
-           if ((SQLUINTEGER) Value == SQL_CP_OFF)
-               return SQL_SUCCESS;
+           switch ((SQLUINTEGER) Value)
+           {
+               case SQL_CP_OFF:
+                   EN_unset_pooling(env);
+                   ret = SQL_SUCCESS;
+                   break;
+#ifdef WIN_MULTITHREAD_SUPPORT
+               case SQL_CP_ONE_PER_DRIVER:
+                   EN_set_pooling(env);
+                   ret = SQL_SUCCESS;
+                   break;
+#endif /* WIN_MULTITHREAD_SUPPORT */
+               default:
+                   ret = SQL_SUCCESS_WITH_INFO;
+           }
            break;
        case SQL_ATTR_CP_MATCH:
            /* *((unsigned int *) Value) = SQL_CP_RELAXED_MATCH; */
-           return SQL_SUCCESS;
+           ret = SQL_SUCCESS;
+           break;
        case SQL_ATTR_ODBC_VERSION:
            if ((SQLUINTEGER) Value == SQL_OV_ODBC2)
                EN_set_odbc2(env);
            else
                EN_set_odbc3(env);
-           return SQL_SUCCESS;
+           ret = SQL_SUCCESS;
            break;
        case SQL_ATTR_OUTPUT_NTS:
            if ((SQLUINTEGER) Value == SQL_TRUE)
-               return SQL_SUCCESS;
+               ret = SQL_SUCCESS;
+           else
+               ret = SQL_SUCCESS_WITH_INFO;
+   
            break;
        default:
            env->errornumber = CONN_INVALID_ARGUMENT_NO;
-           return SQL_ERROR;
+           ret = SQL_ERROR;
+   }
+   if (SQL_SUCCESS_WITH_INFO == ret)
+   {
+       env->errornumber = CONN_OPTION_VALUE_CHANGED;
+       env->errormsg = "SetEnv changed to ";
    }
-   env->errornumber = CONN_OPTION_VALUE_CHANGED;
-   env->errormsg = "SetEnv changed to ";
-   return SQL_SUCCESS_WITH_INFO;
+   LEAVE_ENV_CS(env);
+   return ret;
 }
 
 /* SQLSet(Param/Scroll/Stmt)Option -> SQLSetStmtAttr */
@@ -403,10 +491,14 @@ SQLSetStmtAttr(HSTMT StatementHandle,
 {
    static char *func = "SQLSetStmtAttr";
    StatementClass *stmt = (StatementClass *) StatementHandle;
+   RETCODE ret;
 
    mylog("[[%s]] Handle=%u %d,%u\n", func, StatementHandle, Attribute, Value);
+   ENTER_STMT_CS(stmt);
    SC_clear_error(stmt);
-   return PGAPI_SetStmtAttr(StatementHandle, Attribute, Value, StringLength);
+   ret = PGAPI_SetStmtAttr(StatementHandle, Attribute, Value, StringLength);
+   LEAVE_STMT_CS(stmt);
+   return ret;
 }
 
 #define SQL_FUNC_ESET(pfExists, uwAPI) \
@@ -491,8 +583,7 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
    SQL_FUNC_ESET(pfExists, SQL_API_SQLNUMPARAMS);      /* 63 */
    /* SQL_FUNC_ESET(pfExists, SQL_API_SQLPARAMOPTIONS); 64 deprecated */
    SQL_FUNC_ESET(pfExists, SQL_API_SQLPRIMARYKEYS);    /* 65 */
-   if (ci->drivers.lie)
-       SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS); /* 66 not implemeted yet */ 
+   SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURECOLUMNS);   /* 66 */ 
    SQL_FUNC_ESET(pfExists, SQL_API_SQLPROCEDURES);     /* 67 */
    SQL_FUNC_ESET(pfExists, SQL_API_SQLSETPOS);     /* 68 */
    /* SQL_FUNC_ESET(pfExists, SQL_API_SQLSETSCROLLOPTIONS); 69 deprecated */
@@ -535,16 +626,21 @@ PGAPI_GetFunctions30(HDBC hdbc, UWORD fFunction, UWORD FAR * pfExists)
 RETCODE    SQL_API
 SQLBulkOperations(HSTMT hstmt, SQLSMALLINT operation)
 {
+   RETCODE ret;
    static char *func = "SQLBulkOperations";
-#ifndef    DRIVER_CURSOR_IMPLEMENT
    StatementClass  *stmt = (StatementClass *) hstmt;
+
+   ENTER_STMT_CS(stmt);
+#ifndef    DRIVER_CURSOR_IMPLEMENT
    stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
    stmt->errormsg = "driver must be compiled with the DRIVER_CURSOR_IMPLEMENT option";
    SC_log_error(func, "", stmt);
-   return SQL_ERROR;
+   ret = SQL_ERROR;
 #else
    mylog("[[%s]] Handle=%u %d\n", func, hstmt, operation);
    SC_clear_error((StatementClass *) hstmt);
-   return  PGAPI_BulkOperations(hstmt, operation);
+   ret = PGAPI_BulkOperations(hstmt, operation);
 #endif /* DRIVER_CURSOR_IMPLEMENT */
+   LEAVE_STMT_CS(stmt);
+   return ret;
 }  
index 8992353b315afb7e0e0ac8c280272d652cb9a815..cf86135c091148a17cf6ffe702e978da86492225 100644 (file)
@@ -30,9 +30,11 @@ RETCODE  SQL_API SQLGetStmtAttrW(SQLHSTMT hstmt,
    RETCODE ret;
 
    mylog("[SQLGetStmtAttrW]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
    ret = PGAPI_GetStmtAttr(hstmt, fAttribute, rgbValue,
        cbValueMax, pcbValue);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    return ret;
 }
 
@@ -44,9 +46,11 @@ RETCODE SQL_API  SQLSetStmtAttrW(SQLHSTMT hstmt,
    RETCODE ret;
 
    mylog("[SQLSetStmtAttrW]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
    ret = PGAPI_SetStmtAttr(hstmt, fAttribute, rgbValue,
        cbValueMax);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    return ret;
 }
 
@@ -59,9 +63,11 @@ RETCODE SQL_API  SQLGetConnectAttrW(HDBC hdbc,
    RETCODE ret;
 
    mylog("[SQLGetConnectAttrW]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    CC_clear_error((ConnectionClass *) hdbc);
    ret = PGAPI_GetConnectAttr(hdbc, fAttribute, rgbValue,
        cbValueMax, pcbValue);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
    return ret;
 }
 
@@ -73,9 +79,11 @@ RETCODE SQL_API  SQLSetConnectAttrW(HDBC hdbc,
    RETCODE ret;
 
    mylog("[SQLSetConnectAttrW]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    CC_clear_error((ConnectionClass *) hdbc);
    ret = PGAPI_SetConnectAttr(hdbc, fAttribute, rgbValue,
        cbValue);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
    return ret;
 }
 
@@ -233,6 +241,7 @@ RETCODE SQL_API SQLColAttributeW(
         char    *rgbD = NULL;
 
    mylog("[SQLColAttributeW]");
+   ENTER_STMT_CS((StatementClass *) hstmt);
    SC_clear_error((StatementClass *) hstmt);
    switch (fDescType)
    { 
@@ -270,13 +279,13 @@ RETCODE SQL_API SQLColAttributeW(
            StatementClass  *stmt = (StatementClass *) hstmt;
 
            ret = SQL_SUCCESS_WITH_INFO;
-           stmt->errornumber = STMT_TRUNCATED;
-           stmt->errormsg = "The buffer was too small for the rgbDesc.";
+           SC_set_error(stmt, STMT_TRUNCATED, "The buffer was too small for the rgbDesc.");
        }
        if (pcbDesc)
            *pcbDesc = blen * 2;
        free(rgbD);
    }
+   LEAVE_STMT_CS((StatementClass *) hstmt);
 
    return ret;
 }
index ac1e3f28f4e9e8099d4bbdcb724488b1d6f888a6..96bb7b0a2f3429daef74fe6341a81588c21aa8c7 100644 (file)
@@ -40,9 +40,11 @@ RETCODE  SQL_API SQLColumnsW(HSTMT StatementHandle,
    scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2);
    tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3);
    clName = ucs2_to_utf8(ColumnName, NameLength4, &nmlen4);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_Columns(StatementHandle, ctName, (SWORD) nmlen1,
                scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3,
                clName, (SWORD) nmlen4, 0);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (ctName)
        free(ctName);
    if (scName);
@@ -65,12 +67,14 @@ RETCODE  SQL_API SQLConnectW(HDBC ConnectionHandle,
    RETCODE ret;
    
    mylog("[SQLConnectW]");
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    ((ConnectionClass *) ConnectionHandle)->unicode = 1;
    svName = ucs2_to_utf8(ServerName, NameLength1, &nmlen1);
    usName = ucs2_to_utf8(UserName, NameLength2, &nmlen2);
    auth = ucs2_to_utf8(Authentication, NameLength3, &nmlen3);
    ret = PGAPI_Connect(ConnectionHandle, svName, (SWORD) nmlen1,
                usName, (SWORD) nmlen2, auth, (SWORD) nmlen3);
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
    if (svName);
        free(svName);
    if (usName);
@@ -95,12 +99,14 @@ RETCODE SQL_API SQLDriverConnectW(HDBC hdbc,
    RETCODE ret;
 
    mylog("[SQLDriverConnectW]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    ((ConnectionClass *) hdbc)->unicode = 1;
    szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen);
    obuflen = cbConnStrOutMax + 1;
    szOut = malloc(obuflen);
    ret = PGAPI_DriverConnect(hdbc, hwnd, szIn, (SWORD) inlen,
        szOut, cbConnStrOutMax, &olen, fDriverCompletion);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
    if (ret != SQL_ERROR)
    {
        UInt4 outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
@@ -126,12 +132,14 @@ RETCODE SQL_API SQLBrowseConnectW(
    RETCODE ret;
 
    mylog("[SQLBrowseConnectW]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    ((ConnectionClass *) hdbc)->unicode = 1;
    szIn = ucs2_to_utf8(szConnStrIn, cbConnStrIn, &inlen);
    obuflen = cbConnStrOutMax + 1;
    szOut = malloc(obuflen);
    ret = PGAPI_BrowseConnect(hdbc, szIn, (SWORD) inlen,
        szOut, cbConnStrOutMax, &olen);
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
    if (ret != SQL_ERROR)
    {
        UInt4   outlen = utf8_to_ucs2(szOut, olen, szConnStrOut, cbConnStrOutMax);
@@ -172,6 +180,7 @@ RETCODE  SQL_API SQLDescribeColW(HSTMT StatementHandle,
    mylog("[SQLDescribeColW]");
    buflen = BufferLength * 3 + 1;
    clName = malloc(buflen);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
        clName, buflen, &nmlen, DataType, ColumnSize,
        DecimalDigits, Nullable);
@@ -182,12 +191,12 @@ RETCODE  SQL_API SQLDescribeColW(HSTMT StatementHandle,
        {
            StatementClass  *stmt = (StatementClass *) StatementHandle;
            ret = SQL_SUCCESS_WITH_INFO;
-           stmt->errornumber = STMT_TRUNCATED;
-           stmt->errormsg = "Column name too large";
+           SC_set_error(stmt, STMT_TRUNCATED, "Column name too large");
        }
        if (NameLength)
            *NameLength = nmcount;
    }
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    free(clName); 
    return ret;
 }
@@ -201,7 +210,9 @@ RETCODE  SQL_API SQLExecDirectW(HSTMT StatementHandle,
 
    mylog("[SQLExecDirectW]");
    stxt = ucs2_to_utf8(StatementText, TextLength, &slen);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_ExecDirect(StatementHandle, stxt, slen);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (stxt);
        free(stxt);
    return ret;
@@ -218,6 +229,7 @@ RETCODE  SQL_API SQLGetCursorNameW(HSTMT StatementHandle,
    mylog("[SQLGetCursorNameW]");
    buflen = BufferLength * 3 + 1;
    crName = malloc(buflen);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_GetCursorName(StatementHandle, crName, buflen, &clen);
    if (ret == SQL_SUCCESS) 
    {
@@ -226,12 +238,12 @@ RETCODE  SQL_API SQLGetCursorNameW(HSTMT StatementHandle,
        {
            StatementClass *stmt = (StatementClass *) StatementHandle;
            ret = SQL_SUCCESS_WITH_INFO;
-           stmt->errornumber = STMT_TRUNCATED;
-           stmt->errormsg = "Cursor name too large";
+           SC_set_error(stmt, STMT_TRUNCATED, "Cursor name too large");
        }
        if (NameLength)
            *NameLength = utf8_to_ucs2(crName, (Int4) clen, CursorName, BufferLength);
    }
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    free(crName);
    return ret;
 }
@@ -243,6 +255,7 @@ RETCODE  SQL_API SQLGetInfoW(HDBC ConnectionHandle,
    ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
    RETCODE ret;
 
+   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
    conn->unicode = 1;
    CC_clear_error(conn);
 #if (ODBCVER >= 0x0300)
@@ -266,6 +279,7 @@ RETCODE  SQL_API SQLGetInfoW(HDBC ConnectionHandle,
    if (SQL_ERROR == ret)
        CC_log_error("SQLGetInfoW", "", conn);
 #endif
+   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
    return ret;
 }
 
@@ -278,7 +292,9 @@ RETCODE  SQL_API SQLPrepareW(HSTMT StatementHandle,
 
    mylog("[SQLPrepareW]");
    stxt = ucs2_to_utf8(StatementText, TextLength, &slen);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_Prepare(StatementHandle, stxt, slen);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (stxt);
        free(stxt);
    return ret;
@@ -293,7 +309,9 @@ RETCODE  SQL_API SQLSetCursorNameW(HSTMT StatementHandle,
 
    mylog("[SQLSetCursorNameW]");
    crName = ucs2_to_utf8(CursorName, NameLength, &nlen);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_SetCursorName(StatementHandle, crName, (SWORD) nlen);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (crName);
        free(crName);
    return ret;
@@ -314,9 +332,11 @@ RETCODE  SQL_API SQLSpecialColumnsW(HSTMT StatementHandle,
    ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1);
    scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2);
    tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3);
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, ctName,
            (SWORD) nmlen1, scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3,
        Scope, Nullable);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (ctName);
        free(ctName);
    if (scName);
@@ -340,9 +360,11 @@ RETCODE  SQL_API SQLStatisticsW(HSTMT StatementHandle,
    ctName = ucs2_to_utf8(CatalogName, NameLength1, &nmlen1);
    scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2);
    tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3);
-   return PGAPI_Statistics(StatementHandle, ctName, (SWORD) nmlen1,
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
+   ret = PGAPI_Statistics(StatementHandle, ctName, (SWORD) nmlen1,
            scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, Unique,
        Reserved);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (ctName);
        free(ctName);
    if (scName);
@@ -367,9 +389,11 @@ RETCODE  SQL_API SQLTablesW(HSTMT StatementHandle,
    scName = ucs2_to_utf8(SchemaName, NameLength2, &nmlen2);
    tbName = ucs2_to_utf8(TableName, NameLength3, &nmlen3);
    tbType = ucs2_to_utf8(TableType, NameLength4, &nmlen4);
-   return PGAPI_Tables(StatementHandle, ctName, (SWORD) nmlen1,
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
+   ret = PGAPI_Tables(StatementHandle, ctName, (SWORD) nmlen1,
            scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3,
            tbType, (SWORD) nmlen4);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
    if (ctName);
        free(ctName);
    if (scName);
@@ -401,9 +425,11 @@ RETCODE SQL_API SQLColumnPrivilegesW(
    scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2);
    tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3);
    clName = ucs2_to_utf8(szColumnName, cbColumnName, &nmlen4);
+   ENTER_STMT_CS((StatementClass *) hstmt);
    ret = PGAPI_ColumnPrivileges(hstmt, ctName, (SWORD) nmlen1,
        scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3,
        clName, (SWORD) nmlen4);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    if (ctName);
        free(ctName);
    if (scName);
@@ -441,10 +467,12 @@ RETCODE SQL_API SQLForeignKeysW(
    fkctName = ucs2_to_utf8(szFkCatalogName, cbFkCatalogName, &nmlen4);
    fkscName = ucs2_to_utf8(szFkSchemaName, cbFkSchemaName, &nmlen5);
    fktbName = ucs2_to_utf8(szFkTableName, cbFkTableName, &nmlen6);
+   ENTER_STMT_CS((StatementClass *) hstmt);
    ret = PGAPI_ForeignKeys(hstmt, ctName, (SWORD) nmlen1,
        scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3,
        fkctName, (SWORD) nmlen4, fkscName, (SWORD) nmlen5,
        fktbName, (SWORD) nmlen6);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    if (ctName);
        free(ctName);
    if (scName);
@@ -474,6 +502,7 @@ RETCODE SQL_API SQLNativeSqlW(
    SQLINTEGER  buflen, olen;
 
    mylog("[SQLNativeSqlW]");
+   ENTER_CONN_CS((ConnectionClass *) hdbc);
    ((ConnectionClass *) hdbc)->unicode = 1;
    szIn = ucs2_to_utf8(szSqlStrIn, cbSqlStrIn, &slen);
    buflen = 3 * cbSqlStrMax + 1;
@@ -490,12 +519,12 @@ RETCODE SQL_API SQLNativeSqlW(
            ConnectionClass *conn = (ConnectionClass *) hdbc;
 
            ret = SQL_SUCCESS_WITH_INFO;
-           conn->errornumber = CONN_TRUNCATED;
-           conn->errormsg = "Sql string too large";
+           CC_set_error(conn, CONN_TRUNCATED, "Sql string too large");
        }
        if (pcbSqlStr)
            *pcbSqlStr = szcount;
    }
+   LEAVE_CONN_CS((ConnectionClass *) hdbc);
    free(szOut);
    return ret;
 }
@@ -517,8 +546,10 @@ RETCODE SQL_API SQLPrimaryKeysW(
    ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1);
    scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2);
    tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3);
-   return PGAPI_PrimaryKeys(hstmt, ctName, (SWORD) nmlen1,
+   ENTER_STMT_CS((StatementClass *) hstmt);
+   ret = PGAPI_PrimaryKeys(hstmt, ctName, (SWORD) nmlen1,
        scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    if (ctName);
        free(ctName);
    if (scName);
@@ -548,9 +579,11 @@ RETCODE SQL_API SQLProcedureColumnsW(
    scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2);
    prName = ucs2_to_utf8(szProcName, cbProcName, &nmlen3);
    clName = ucs2_to_utf8(szColumnName, cbColumnName, &nmlen4);
+   ENTER_STMT_CS((StatementClass *) hstmt);
    ret = PGAPI_ProcedureColumns(hstmt, ctName, (SWORD) nmlen1,
        scName, (SWORD) nmlen2, prName, (SWORD) nmlen3,
        clName, (SWORD) nmlen4);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    if (ctName);
        free(ctName);
    if (scName);
@@ -579,8 +612,10 @@ RETCODE SQL_API SQLProceduresW(
    ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1);
    scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2);
    prName = ucs2_to_utf8(szProcName, cbProcName, &nmlen3);
+   ENTER_STMT_CS((StatementClass *) hstmt);
    ret = PGAPI_Procedures(hstmt, ctName, (SWORD) nmlen1,
        scName, (SWORD) nmlen2, prName, (SWORD) nmlen3);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    if (ctName);
        free(ctName);
    if (scName);
@@ -607,8 +642,10 @@ RETCODE SQL_API SQLTablePrivilegesW(
    ctName = ucs2_to_utf8(szCatalogName, cbCatalogName, &nmlen1);
    scName = ucs2_to_utf8(szSchemaName, cbSchemaName, &nmlen2);
    tbName = ucs2_to_utf8(szTableName, cbTableName, &nmlen3);
+   ENTER_STMT_CS((StatementClass *) hstmt);
    ret = PGAPI_TablePrivileges(hstmt, ctName, (SWORD) nmlen1,
        scName, (SWORD) nmlen2, tbName, (SWORD) nmlen3, 0);
+   LEAVE_STMT_CS((StatementClass *) hstmt);
    if (ctName);
        free(ctName);
    if (scName);
@@ -622,5 +659,10 @@ RETCODE SQL_API    SQLGetTypeInfoW(
        SQLHSTMT    StatementHandle,
        SQLSMALLINT DataType)
 {
-   return PGAPI_GetTypeInfo(StatementHandle, DataType);
+   RETCODE ret;
+
+   ENTER_STMT_CS((StatementClass *) StatementHandle);
+   ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
+   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   return ret;
 }
index f4a510a58731d3d840b6ee998d1f372e79b08608..207aa6063ec752ae70fb23e393e73ee3d3af2787 100644 (file)
--- a/options.c
+++ b/options.c
@@ -91,8 +91,10 @@ set_statement_option(ConnectionClass *conn,
            setval = SQL_CURSOR_FORWARD_ONLY;
            if (ci->drivers.lie)
                setval = vParam;
+#ifdef DECLAREFETCH_FORWARDONLY
            else if (ci->drivers.use_declarefetch)
                ;
+#endif /* DECLAREFETCH_FORWARDONLY */
            else if (SQL_CURSOR_STATIC == vParam)
                setval = vParam;
            else if (SQL_CURSOR_KEYSET_DRIVEN == vParam)
@@ -194,14 +196,12 @@ set_statement_option(ConnectionClass *conn,
        case SQL_SIMULATE_CURSOR:       /* NOT SUPPORTED */
            if (stmt)
            {
-               stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-               stmt->errormsg = "Simulated positioned update/delete not supported.  Use the cursor library.";
+               SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Simulated positioned update/delete not supported.  Use the cursor library.");
                SC_log_error(func, "", stmt);
            }
            if (conn)
            {
-               conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-               conn->errormsg = "Simulated positioned update/delete not supported.  Use the cursor library.";
+               CC_set_error(conn, STMT_NOT_IMPLEMENTED_ERROR, "Simulated positioned update/delete not supported.  Use the cursor library.");
                CC_log_error(func, "", conn);
            }
            return SQL_ERROR;
@@ -217,13 +217,11 @@ set_statement_option(ConnectionClass *conn,
        case 1228:
            if (stmt)
            {
-               stmt->errornumber = STMT_OPTION_NOT_FOR_THE_DRIVER;
-               stmt->errormsg = "The option may be for MS SQL Server(Set)";
+               SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "The option may be for MS SQL Server(Set)");
            }
            else if (conn)
            {
-               conn->errornumber = STMT_OPTION_NOT_FOR_THE_DRIVER;
-               conn->errormsg = "The option may be for MS SQL Server(Set)";
+               CC_set_error(conn, STMT_OPTION_NOT_FOR_THE_DRIVER, "The option may be for MS SQL Server(Set)");
            }
            return SQL_ERROR;
        default:
@@ -232,15 +230,13 @@ set_statement_option(ConnectionClass *conn,
 
                if (stmt)
                {
-                   stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-                   stmt->errormsg = "Unknown statement option (Set)";
+                   SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Unknown statement option (Set)");
                    sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
                    SC_log_error(func, option, stmt);
                }
                if (conn)
                {
-                   conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-                   conn->errormsg = "Unknown statement option (Set)";
+                   CC_set_error(conn, STMT_NOT_IMPLEMENTED_ERROR, "Unknown statement option (Set)");
                    sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
                    CC_log_error(func, option, conn);
                }
@@ -253,13 +249,11 @@ set_statement_option(ConnectionClass *conn,
    {
        if (stmt)
        {
-           stmt->errormsg = "Requested value changed.";
-           stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
+           SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "Requested value changed.");
        }
        if (conn)
        {
-           conn->errormsg = "Requested value changed.";
-           conn->errornumber = STMT_OPTION_VALUE_CHANGED;
+           CC_set_error(conn, STMT_OPTION_VALUE_CHANGED, "Requested value changed.");
        }
        return SQL_SUCCESS_WITH_INFO;
    }
@@ -356,8 +350,7 @@ PGAPI_SetConnectOption(
                    break;
 
                default:
-                   conn->errormsg = "Illegal parameter value for SQL_AUTOCOMMIT";
-                   conn->errornumber = CONN_INVALID_ARGUMENT_NO;
+                   CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "Illegal parameter value for SQL_AUTOCOMMIT");
                    CC_log_error(func, "", conn);
                    return SQL_ERROR;
            }
@@ -379,8 +372,7 @@ PGAPI_SetConnectOption(
            retval = SQL_SUCCESS;
                         if (CC_is_in_trans(conn))
            {
-               conn->errormsg = "Cannot switch isolation level while a transaction is in progress";
-               conn->errornumber = CONN_TRANSACT_IN_PROGRES;
+               CC_set_error(conn, CONN_TRANSACT_IN_PROGRES, "Cannot switch isolation level while a transaction is in progress");
                CC_log_error(func, "", conn);
                return SQL_ERROR;
            }
@@ -402,8 +394,7 @@ PGAPI_SetConnectOption(
            }
            if (SQL_ERROR == retval)
            {
-               conn->errornumber = CONN_INVALID_ARGUMENT_NO;
-               conn->errormsg = "Illegal parameter value for SQL_TXN_ISOLATION";
+               CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "Illegal parameter value for SQL_TXN_ISOLATION");
                CC_log_error(func, "", conn);
                return SQL_ERROR;
            }
@@ -425,8 +416,7 @@ PGAPI_SetConnectOption(
                    QR_Destructor(res);
                if (SQL_ERROR == retval)
                {
-                   conn->errornumber = STMT_EXEC_ERROR;
-                   conn->errormsg = "ISOLATION change request to the server error";
+                   CC_set_error(conn, STMT_EXEC_ERROR, "ISOLATION change request to the server error");
                    return SQL_ERROR;
                }
            }
@@ -445,8 +435,7 @@ PGAPI_SetConnectOption(
            {
                char        option[64];
 
-               conn->errormsg = "Unknown connect option (Set)";
-               conn->errornumber = CONN_UNSUPPORTED_OPTION;
+               CC_set_error(conn, CONN_UNSUPPORTED_OPTION, "Unknown connect option (Set)");
                sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
                if (fOption == 30002 && vParam)
                {
@@ -465,7 +454,7 @@ PGAPI_SetConnectOption(
                    if (0 == cmp)
                    {
                        mylog("Microsoft Jet !!!!\n");
-                       conn->errornumber = 0;
+                       CC_set_errornumber(conn, 0);
                        conn->ms_jet = 1;
                        return SQL_SUCCESS;
                    }
@@ -477,8 +466,7 @@ PGAPI_SetConnectOption(
 
    if (changed)
    {
-       conn->errornumber = CONN_OPTION_VALUE_CHANGED;
-       conn->errormsg = "Requested value changed.";
+       CC_set_error(conn, CONN_OPTION_VALUE_CHANGED, "Requested value changed.");
        return SQL_SUCCESS_WITH_INFO;
    }
    else
@@ -551,8 +539,7 @@ PGAPI_GetConnectOption(
            {
                char        option[64];
 
-               conn->errormsg = "Unknown connect option (Get)";
-               conn->errornumber = CONN_UNSUPPORTED_OPTION;
+               CC_set_error(conn, CONN_UNSUPPORTED_OPTION, "Unknown connect option (Get)");
                sprintf(option, "fOption=%d", fOption);
                CC_log_error(func, option, conn);
                return SQL_ERROR;
@@ -627,8 +614,7 @@ PGAPI_GetStmtOption(
                if ((stmt->currTuple < 0) ||
                    (stmt->currTuple >= QR_get_num_backend_tuples(res)))
                {
-                   stmt->errormsg = "Not positioned on a valid row.";
-                   stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
+                   SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row.");
                    SC_log_error(func, "", stmt);
                    return SQL_ERROR;
                }
@@ -637,8 +623,7 @@ PGAPI_GetStmtOption(
            {
                if (stmt->currTuple == -1 || !res || !res->tupleField)
                {
-                   stmt->errormsg = "Not positioned on a valid row.";
-                   stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
+                   SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row.");
                    SC_log_error(func, "", stmt);
                    return SQL_ERROR;
                }
@@ -646,8 +631,7 @@ PGAPI_GetStmtOption(
 
            if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF)
            {
-               stmt->errormsg = "Operation invalid because use bookmarks not enabled.";
-               stmt->errornumber = STMT_OPERATION_INVALID;
+               SC_set_error(stmt, STMT_OPERATION_INVALID, "Operation invalid because use bookmarks not enabled.");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
            }
@@ -716,8 +700,7 @@ PGAPI_GetStmtOption(
            {
                char        option[64];
 
-               stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-               stmt->errormsg = "Unknown statement option (Get)";
+               SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Unknown statement option (Get)");
                sprintf(option, "fOption=%d", fOption);
                SC_log_error(func, option, stmt);
                return SQL_ERROR;
diff --git a/parse.c b/parse.c
index a61b75e90cf0d8eb5883a2d5a9fe10e52aa8da2d..8d52341181e18f58e4f0f8719f0a6cb8e1ea2a99 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -839,8 +839,7 @@ parse_statement(StatementClass *stmt)
                        else
                        {
                            stmt->parse_status = STMT_PARSE_FATAL;
-                           stmt->errornumber = STMT_EXEC_ERROR;
-                           stmt->errormsg = "duplicated Table name";
+                           SC_set_error(stmt, STMT_EXEC_ERROR, "duplicated Table name");
                            stmt->updatable = FALSE;
                            return FALSE;
                        }
@@ -951,8 +950,7 @@ parse_statement(StatementClass *stmt)
                    if (!tblFound)
                    {
                        stmt->parse_status = STMT_PARSE_FATAL;
-                       stmt->errornumber = STMT_EXEC_ERROR;
-                       stmt->errormsg = "Table not found";
+                       SC_set_error(stmt, STMT_EXEC_ERROR, "Table not found");
                        stmt->updatable = FALSE;
                        return FALSE;
                    }
@@ -992,8 +990,7 @@ parse_statement(StatementClass *stmt)
            result = PGAPI_AllocStmt(stmt->hdbc, &hcol_stmt);
            if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
            {
-               stmt->errormsg = "PGAPI_AllocStmt failed in parse_statement for columns.";
-               stmt->errornumber = STMT_NO_MEMORY_ERROR;
+               SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "PGAPI_AllocStmt failed in parse_statement for columns.");
                stmt->parse_status = STMT_PARSE_FATAL;
                return FALSE;
            }
index 7fd6c9ac1c5c55f0d78c63f117a10325a31b3c13..24552a81fc11c59d9ed772ea0e3551dc5d61ea43 100644 (file)
--- a/pgapi30.c
+++ b/pgapi30.c
@@ -371,8 +371,7 @@ PGAPI_GetConnectAttr(HDBC ConnectionHandle,
            *((SQLUINTEGER *) Value) = 0;
            break;
        case SQL_ATTR_METADATA_ID:
-           conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-           conn->errormsg = "Unsupported connect attribute (Get)";
+           CC_set_error(conn, STMT_INVALID_OPTION_IDENTIFIER, "Unsupported connect attribute (Get)");
            CC_log_error(func, "", conn);
            return SQL_ERROR;
        default:
@@ -429,8 +428,7 @@ void    Desc_set_error(SQLHDESC hdesc, int errornumber, const char *errormsg)
    if (!hstmt)
        return;
    stmt = (StatementClass *) hstmt;
-   stmt->errornumber = errornumber;
-   stmt->errormsg = errormsg; /* should be static */
+   SC_set_error(stmt, errornumber, errormsg);
 }
 
 static  void column_bindings_set(ARDFields *opts, int cols, BOOL maxset)
@@ -530,8 +528,7 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
            if (Value != tptr)
            {
                ret = SQL_ERROR;
-               stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; 
-               stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; 
+               SC_set_error(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR"); 
            }
            break;
        case SQL_DESC_OCTET_LENGTH_PTR:
@@ -572,7 +569,7 @@ ARDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_LENGTH:
        case SQL_DESC_NUM_PREC_RADIX:
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    return ret;
 }
@@ -662,8 +659,7 @@ APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                Value != opts->parameters[RecNumber - 1].used)
            {
                ret = SQL_ERROR;
-               stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER; 
-               stmt->errormsg = "INDICATOR != OCTET_LENGTH_PTR"; 
+               SC_set_error(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER, "INDICATOR != OCTET_LENGTH_PTR"); 
            }
            break;
        case SQL_DESC_OCTET_LENGTH:
@@ -690,7 +686,7 @@ APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_LENGTH:
        case SQL_DESC_NUM_PREC_RADIX:
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    return ret;
 }
@@ -744,7 +740,7 @@ IRDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_UNSIGNED: /* read-only */
        case SQL_DESC_UPDATABLE: /* read-only */
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    return ret;
 }
@@ -769,7 +765,7 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
            if (SQL_UNNAMED !=  (SQLUINTEGER) Value)
            {
                ret = SQL_ERROR;
-               stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER;
+               SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER);
            }
            break;
        case SQL_DESC_TYPE:
@@ -829,7 +825,7 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_TYPE_NAME: /* read-only */
        case SQL_DESC_UNSIGNED: /* read-only */
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    return ret;
 }
@@ -951,7 +947,7 @@ ARDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_DATETIME_INTERVAL_PRECISION:
        case SQL_DESC_LENGTH:
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    switch (rettype)
    {
@@ -1065,7 +1061,7 @@ APDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_DATETIME_INTERVAL_PRECISION:
        case SQL_DESC_LENGTH:
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    switch (rettype)
    {
@@ -1148,7 +1144,7 @@ IRDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
            bCallColAtt = TRUE;
            break; 
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    if (bCallColAtt)
    {
@@ -1278,7 +1274,7 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        case SQL_DESC_TYPE_NAME: /* read-only */
        case SQL_DESC_UNSIGNED: /* read-only */
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INVALID_DESCRIPTOR_IDENTIFIER
+           SC_set_errornumber(stmt, STMT_INVALID_DESCRIPTOR_IDENTIFIER)
    }
    switch (rettype)
    {
@@ -1379,8 +1375,7 @@ PGAPI_GetStmtAttr(HSTMT StatementHandle,
             * case SQL_ATTR_PREDICATE_PTR: case
             * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
             */
-           stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-           stmt->errormsg = "Unsupported statement option (Get)";
+           SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Get)");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        default:
@@ -1409,8 +1404,7 @@ PGAPI_SetConnectAttr(HDBC ConnectionHandle,
        case SQL_ATTR_CONNECTION_DEAD:
        case SQL_ATTR_CONNECTION_TIMEOUT:
        case SQL_ATTR_METADATA_ID:
-           conn->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-           conn->errormsg = "Unsupported connect attribute (Set)";
+           CC_set_error(conn, STMT_INVALID_OPTION_IDENTIFIER, "Unsupported connect attribute (Set)");
            return SQL_ERROR;
        default:
            ret = PGAPI_SetConnectOption(ConnectionHandle, (UWORD) Attribute, (UDWORD) Value);
@@ -1450,13 +1444,12 @@ PGAPI_GetDescField(SQLHDESC DescriptorHandle,
            ret = IPDGetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
            break;
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INTERNAL_ERROR; 
-           stmt->errormsg = "Error not implemented";
+           SC_set_error(stmt, STMT_INTERNAL_ERROR, "Error not implemented");
    }
    if (ret == SQL_ERROR)
    {
-       if (!stmt->errormsg && stmt->errornumber == STMT_INVALID_DESCRIPTOR_IDENTIFIER) 
-           stmt->errormsg = "can't SQLGetDescField for this descriptor identifier"
+       if (!SC_get_errormsg(stmt) && SC_get_errornumber(stmt) == STMT_INVALID_DESCRIPTOR_IDENTIFIER)
+           SC_set_errormsg(stmt, "can't SQLGetDescField for this descriptor identifier")
        SC_log_error(func, "", stmt);
    }
    return ret;
@@ -1493,13 +1486,12 @@ PGAPI_SetDescField(SQLHDESC DescriptorHandle,
            ret = IPDSetField(stmt, RecNumber, FieldIdentifier, Value, BufferLength);
            break;
        default:ret = SQL_ERROR;
-           stmt->errornumber = STMT_INTERNAL_ERROR; 
-           stmt->errormsg = "Error not implemented";
+           SC_set_error(stmt, STMT_INTERNAL_ERROR, "Error not implemented");
    }
    if (ret == SQL_ERROR)
    {
-       if (!stmt->errormsg && stmt->errornumber == STMT_INVALID_DESCRIPTOR_IDENTIFIER) 
-           stmt->errormsg = "can't SQLSetDescField for this descriptor identifier"
+       if (!SC_get_errormsg(stmt) && SC_get_errornumber(stmt) == STMT_INVALID_DESCRIPTOR_IDENTIFIER) 
+           SC_set_errormsg(stmt, "can't SQLSetDescField for this descriptor identifier")
        SC_log_error(func, "", stmt);
    }
    return ret;
@@ -1534,8 +1526,7 @@ PGAPI_SetStmtAttr(HSTMT StatementHandle,
             * case SQL_ATTR_PREDICATE_PTR: case
             * SQL_ATTR_PREDICATE_OCTET_LENGTH_PTR:
             */
-           stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-           stmt->errormsg = "Unsupported statement option (Set)";
+           SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "Unsupported statement option (Set)");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
 
@@ -1609,8 +1600,7 @@ PGAPI_BulkOperations(HSTMT hstmt, SQLSMALLINT operation)
    {
        if (bmark = (UInt4 *) opts->bookmark->buffer, !bmark)
        {
-           stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-           stmt->errormsg = "bookmark isn't specified";
+           SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "bookmark isn't specified");
            return SQL_ERROR;
        }
        bmark += (offset >> 4);
index fa9c7ae87c9153f641dcf2fd7a948e4280f441c0..57a34bd1c3d11be6d66e710e4f63623b260bd7af 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
@@ -459,6 +459,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
 char *
 pgtype_to_name(StatementClass *stmt, Int4 type)
 {
+   ConnectionClass *conn = SC_get_conn(stmt);
    switch (type)
    {
        case PG_TYPE_CHAR:
@@ -498,9 +499,12 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
        case PG_TYPE_ABSTIME:
            return "abstime";
        case PG_TYPE_DATETIME:
-           return "datetime";
+           if (PG_VERSION_GE(conn, 7.0))
+               return "timestamp with time zone";
+           else
+               return "datetime";
        case PG_TYPE_TIMESTAMP_NO_TMZONE:
-           return "timestamp_nozone";
+           return "timestamp without time zone";
        case PG_TYPE_TIMESTAMP:
            return "timestamp";
        case PG_TYPE_MONEY:
@@ -537,7 +541,7 @@ getNumericDecimalDigits(StatementClass *stmt, Int4 type, int col)
    mylog("getNumericDecimalDigits: type=%d, col=%d\n", type, col);
 
    if (col < 0)
-       return PG_NUMERIC_MAX_SCALE;
+       return default_decimal_digits;
 
    result = SC_get_Curres(stmt);
 
@@ -583,7 +587,7 @@ getNumericColumnSize(StatementClass *stmt, Int4 type, int col)
    mylog("getNumericColumnSize: type=%d, col=%d\n", type, col);
 
    if (col < 0)
-       return max_column_size;
+       return default_column_size;
 
    result = SC_get_Curres(stmt);
 
index cc8d8b7bfb474c4944c9597640742dbf1a3e13ae..86d9a80e5142d93fb72a24dcb01155ed3b7c4eaf 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "psqlodbc.h"
 #include "dlg_specific.h"
+#include "environ.h"
 
 #ifdef WIN32
 #include <winsock.h>
@@ -26,6 +27,9 @@ RETCODE SQL_API SQLDummyOrdinal(void);
 
 #ifdef WIN32
 HINSTANCE NEAR s_hModule;      /* Saved module handle. */
+#ifdef WIN_MULTITHREAD_SUPPORT
+extern CRITICAL_SECTION    qlog_cs, mylog_cs, conns_cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
 
 /* This is where the Driver Manager attaches to this Driver */
 BOOL       WINAPI
@@ -53,6 +57,9 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
                return FALSE;
            }
 
+           INIT_QLOG_CS;
+           INIT_MYLOG_CS;
+           INIT_CONNS_CS;
            getCommonDefaults(DBMS_NAME, ODBCINST_INI, NULL);
            break;
 
@@ -60,6 +67,9 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
            break;
 
        case DLL_PROCESS_DETACH:
+           DELETE_CONNS_CS;
+           DELETE_QLOG_CS;
+           DELETE_MYLOG_CS;
            WSACleanup();
            return TRUE;
 
index cc37d9f06a6464498e555fe1689d614ca64fe418..68365cd748f70b57f9426c0afba05785a78bf646 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.70 2002/09/06 05:51:45 hinoue Exp $
+ * $Id: psqlodbc.h,v 1.71 2002/09/23 08:08:21 hinoue Exp $
  *
  */
 
@@ -34,6 +34,9 @@
 #endif   /* NAMEDATALEN */
 
 
+#ifndef    WIN32
+#undef WIN_MULTITHREAD_SUPPORT
+#endif
 #if defined(WIN32) || defined(WITH_UNIXODBC) || defined(WITH_IODBC)
 #include <sql.h>
 #include <sqlext.h>
@@ -89,7 +92,11 @@ typedef UInt4 Oid;
 #define DRIVERNAME                 "PostgreSQL ODBC"
 #if (ODBCVER >= 0x0300)
 #define DRIVER_ODBC_VER                "03.00"
-#define DBMS_NAME                  "PostgreSQL30"
+#ifdef UNICODE_SUPPORT
+#define DBMS_NAME              "PostgreSQL+ Unicode (Beta)"
+#else
+#define DBMS_NAME              "PostgreSQL+ (Beta)"
+#endif /* UNICODE_SUPPORT */
 #else
 #define DRIVER_ODBC_VER                "02.50"
 #define DBMS_NAME                  "PostgreSQL"
index 8c978b6414815c422d1559de3db7824f16203611..a12e7edb65bb4f58a8e4d2b5dc977356d0496936 100644 (file)
--- a/qresult.c
+++ b/qresult.c
@@ -170,6 +170,10 @@ QR_Destructor(QResultClass *self)
    if (self->command)
        free(self->command);
 
+   /* Free message info (this is from strdup()) */
+   if (self->message)
+       free(self->message);
+
    /* Free notice info (this is from strdup()) */
    if (self->notice)
        free(self->notice);
@@ -184,7 +188,7 @@ QR_Destructor(QResultClass *self)
 
 
 void
-QR_set_command(QResultClass *self, char *msg)
+QR_set_command(QResultClass *self, const char *msg)
 {
    if (self->command)
        free(self->command);
@@ -194,7 +198,17 @@ QR_set_command(QResultClass *self, char *msg)
 
 
 void
-QR_set_notice(QResultClass *self, char *msg)
+QR_set_message(QResultClass *self, const char *msg)
+{
+   if (self->message)
+       free(self->message);
+
+   self->message = msg ? strdup(msg) : NULL;
+}
+
+
+void
+QR_set_notice(QResultClass *self, const char *msg)
 {
    if (self->notice)
        free(self->notice);
@@ -449,7 +463,7 @@ QR_next_tuple(QResultClass *self)
    TupleField *the_tuples = self->backend_tuples;
 
    /* ERROR_MSG_LENGTH is sufficient */
-   static char msgbuffer[ERROR_MSG_LENGTH + 1];
+   char msgbuffer[ERROR_MSG_LENGTH + 1];
 
    /* QR_set_command() dups this string so doesn't need static */
    char        cmdbuffer[ERROR_MSG_LENGTH + 1];
@@ -610,10 +624,40 @@ inolog("clear obsolete %d tuples\n", num_backend_rows);
        switch (id)
        {
 
-           case 'T':           /* Tuples within tuples cannot be handled */
-               self->status = PGRES_BAD_RESPONSE;
-               QR_set_message(self, "Tuples within tuples cannot be handled");
-               return FALSE;
+           case 'P':
+               mylog("Portal name within tuples ?? just ignore\n");
+               SOCK_get_string(sock, msgbuffer, ERROR_MSG_LENGTH);
+               break;
+           case 'T':
+               mylog("Tuples within tuples ?? OK try to handle them\n");
+               self->inTuples = FALSE;
+               if (self->num_total_rows > 0)
+               {
+                   mylog("fetched %d rows\n", self->num_total_rows);
+                   /* set to first row */
+                   self->tupleField = self->backend_tuples + (offset * self->num_fields);
+               }
+               else
+               {
+                   mylog("    [ fetched 0 rows ]\n");
+               }
+               /* add new Result class */
+               self->next = QR_Constructor();
+               if (!self->next)
+               {
+                   CC_set_error(self->conn, CONNECTION_COULD_NOT_RECEIVE, "Could not create result info in send_query.");
+                   CC_on_abort(self->conn, NO_TRANS | CONN_DEAD);
+                   return FALSE;
+               }
+               QR_set_cache_size(self->next, self->cache_size);
+               self = self->next;
+               if (!QR_fetch_tuples(self, self->conn, NULL))
+               {
+                   CC_set_error(self->conn, CONNECTION_COULD_NOT_RECEIVE, QR_get_message(self));
+                   return FALSE;
+               }
+
+               return TRUE;
            case 'B':           /* Tuples in binary format */
            case 'D':           /* Tuples in ASCII format  */
 
index 03c4ed35fb746b239d2538591c4dd9655bd0f177..01c8e2fd1bf0491a8ceb0daee502a7d6c69ea500 100644 (file)
--- a/qresult.h
+++ b/qresult.h
@@ -113,7 +113,6 @@ struct QResultClass_
 #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_message(self, message_)     ( self->message = message_)
 #define QR_set_aborted(self, aborted_)     ( self->aborted = aborted_)
 #define QR_set_haskeyset(self)     (self->haskeyset = TRUE)
 
@@ -133,8 +132,9 @@ int         QR_next_tuple(QResultClass *self);
 int            QR_close(QResultClass *self);
 char       QR_fetch_tuples(QResultClass *self, ConnectionClass *conn, char *cursor);
 void       QR_free_memory(QResultClass *self);
-void       QR_set_command(QResultClass *self, char *msg);
-void       QR_set_notice(QResultClass *self, char *msg);
+void       QR_set_command(QResultClass *self, const char *msg);
+void       QR_set_message(QResultClass *self, const char *msg);
+void       QR_set_notice(QResultClass *self, const char *msg);
 
 void       QR_set_num_fields(QResultClass *self, int new_num_fields);  /* manual result only */
 
index 28af870746a245564a1790857f0fc1d92005047a..e0a363dfe6988f10e210a9d28bf7fd2110a398f9 100644 (file)
--- a/results.c
+++ b/results.c
@@ -62,8 +62,7 @@ PGAPI_RowCount(
    {
        if (stmt->status != STMT_FINISHED)
        {
-           stmt->errornumber = STMT_SEQUENCE_ERROR;
-           stmt->errormsg = "Can't get row count while statement is still executing.";
+           SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't get row count while statement is still executing.");
            SC_log_error(func, "", stmt);
            return  SQL_ERROR;
        }
@@ -82,7 +81,7 @@ PGAPI_RowCount(
        }
    }
 
-   stmt->errornumber = STMT_SEQUENCE_ERROR;
+   SC_set_errornumber(stmt, STMT_SEQUENCE_ERROR);
    SC_log_error(func, "Bad return value", stmt);
    return SQL_ERROR;
 }
@@ -139,8 +138,7 @@ PGAPI_NumResultCols(
        if ((!result) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
        {
            /* no query has been executed on this statement */
-           stmt->errornumber = STMT_SEQUENCE_ERROR;
-           stmt->errormsg = "No query has been executed with that handle";
+           SC_set_error(stmt, STMT_SEQUENCE_ERROR, "No query has been executed with that handle");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -244,8 +242,7 @@ PGAPI_DescribeCol(
        {
            if (icol >= irdflds->nfields)
            {
-               stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
-               stmt->errormsg = "Invalid column number in DescribeCol.";
+               SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number in DescribeCol.");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
            }
@@ -280,16 +277,14 @@ PGAPI_DescribeCol(
        if ((NULL == res) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
        {
            /* no query has been executed on this statement */
-           stmt->errornumber = STMT_SEQUENCE_ERROR;
-           stmt->errormsg = "No query has been assigned to this statement.";
+           SC_set_error(stmt, STMT_SEQUENCE_ERROR, "No query has been assigned to this statement.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
 
        if (icol >= QR_NumResultCols(res))
        {
-           stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
-           stmt->errormsg = "Invalid column number in DescribeCol.";
+           SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number in DescribeCol.");
            sprintf(buf, "Col#=%d, #Cols=%d", icol, QR_NumResultCols(res));
            SC_log_error(func, buf, stmt);
            return SQL_ERROR;
@@ -324,8 +319,7 @@ PGAPI_DescribeCol(
        if (len >= cbColNameMax)
        {
            result = SQL_SUCCESS_WITH_INFO;
-           stmt->errornumber = STMT_TRUNCATED;
-           stmt->errormsg = "The buffer was too small for the colName.";
+           SC_set_error(stmt, STMT_TRUNCATED, "The buffer was too small for the colName.");
        }
    }
 
@@ -482,8 +476,7 @@ PGAPI_ColAttributes(
        {
            if (col_idx >= cols)
            {
-               stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
-               stmt->errormsg = "Invalid column number in ColAttributes.";
+               SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number in ColAttributes.");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
            }
@@ -506,8 +499,7 @@ PGAPI_ColAttributes(
 
        if ((NULL == SC_get_Curres(stmt)) || ((stmt->status != STMT_FINISHED) && (stmt->status != STMT_PREMATURE)))
        {
-           stmt->errormsg = "Can't get column attributes: no result found.";
-           stmt->errornumber = STMT_SEQUENCE_ERROR;
+           SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't get column attributes: no result found.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -532,8 +524,7 @@ PGAPI_ColAttributes(
 
        if (col_idx >= cols)
        {
-           stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
-           stmt->errormsg = "Invalid column number in ColAttributes.";
+           SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number in ColAttributes.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -741,12 +732,10 @@ inolog("COLUMN_TYPE=%d\n", value);
            break;
 #endif /* ODBCVER */
        case 1212:
-           stmt->errornumber = STMT_OPTION_NOT_FOR_THE_DRIVER;
-           stmt->errormsg = "this request may be for MS SQL Server";
+           SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "this request may be for MS SQL Server");
            return SQL_ERROR;
        default:
-           stmt->errornumber = STMT_INVALID_OPTION_IDENTIFIER;
-           stmt->errormsg = "ColAttribute for this type not implemented yet";
+           SC_set_error(stmt, STMT_INVALID_OPTION_IDENTIFIER, "ColAttribute for this type not implemented yet");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
    }
@@ -764,8 +753,7 @@ inolog("COLUMN_TYPE=%d\n", value);
            if (len >= cbDescMax)
            {
                result = SQL_SUCCESS_WITH_INFO;
-               stmt->errornumber = STMT_TRUNCATED;
-               stmt->errormsg = "The buffer was too small for the rgbDesc.";
+               SC_set_error(stmt, STMT_TRUNCATED, "The buffer was too small for the rgbDesc.");
            }
        }
 
@@ -816,16 +804,14 @@ PGAPI_GetData(
 
    if (STMT_EXECUTING == stmt->status)
    {
-       stmt->errormsg = "Can't get data while statement is still executing.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't get data while statement is still executing.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (stmt->status != STMT_FINISHED)
    {
-       stmt->errornumber = STMT_STATUS_ERROR;
-       stmt->errormsg = "GetData can only be called after the successful execution on a SQL statement";
+       SC_set_error(stmt, STMT_STATUS_ERROR, "GetData can only be called after the successful execution on a SQL statement");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -834,8 +820,7 @@ PGAPI_GetData(
    {
        if (stmt->options.use_bookmarks == SQL_UB_OFF)
        {
-           stmt->errornumber = STMT_COLNUM_ERROR;
-           stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
+           SC_set_error(stmt, STMT_COLNUM_ERROR, "Attempt to retrieve bookmark with bookmark usage disabled");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -849,9 +834,8 @@ PGAPI_GetData(
 #endif /* ODBCVER */
                break;
            default:
-               stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
-               inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
-               stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
+inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
+               SC_set_error(stmt, STMT_PROGRAM_TYPE_OUT_OF_RANGE, "Column 0 is not of type SQL_C_BOOKMARK");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;
        }
@@ -867,8 +851,7 @@ PGAPI_GetData(
        num_cols = QR_NumResultCols(res);
        if (icol >= num_cols)
        {
-           stmt->errormsg = "Invalid column number.";
-           stmt->errornumber = STMT_INVALID_COLUMN_NUMBER_ERROR;
+           SC_set_error(stmt, STMT_INVALID_COLUMN_NUMBER_ERROR, "Invalid column number.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -881,8 +864,7 @@ PGAPI_GetData(
        if ((stmt->currTuple < 0) ||
            (stmt->currTuple >= num_rows))
        {
-           stmt->errormsg = "Not positioned on a valid row for GetData.";
-           stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
+           SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row for GetData.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -907,8 +889,7 @@ PGAPI_GetData(
        /* it's a SOCKET result (backend data) */
        if (stmt->currTuple == -1 || !res || !res->tupleField)
        {
-           stmt->errormsg = "Not positioned on a valid row for GetData.";
-           stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
+           SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row for GetData.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -946,20 +927,17 @@ PGAPI_GetData(
            return SQL_SUCCESS;
 
        case COPY_UNSUPPORTED_TYPE:
-           stmt->errormsg = "Received an unsupported type from Postgres.";
-           stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
+           SC_set_error(stmt, STMT_RESTRICTED_DATA_TYPE_ERROR, "Received an unsupported type from Postgres.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
 
        case COPY_UNSUPPORTED_CONVERSION:
-           stmt->errormsg = "Couldn't handle the necessary data type conversion.";
-           stmt->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
+           SC_set_error(stmt, STMT_RESTRICTED_DATA_TYPE_ERROR, "Couldn't handle the necessary data type conversion.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
 
        case COPY_RESULT_TRUNCATED:
-           stmt->errornumber = STMT_TRUNCATED;
-           stmt->errormsg = "The buffer was too small for the GetData.";
+           SC_set_error(stmt, STMT_TRUNCATED, "The buffer was too small for the GetData.");
            return SQL_SUCCESS_WITH_INFO;
 
        case COPY_GENERAL_ERROR:        /* error msg already filled in */
@@ -971,8 +949,7 @@ PGAPI_GetData(
            return SQL_NO_DATA_FOUND;
 
        default:
-           stmt->errormsg = "Unrecognized return value from copy_and_convert_field.";
-           stmt->errornumber = STMT_INTERNAL_ERROR;
+           SC_set_error(stmt, STMT_INTERNAL_ERROR, "Unrecognized return value from copy_and_convert_field.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
    }
@@ -1004,8 +981,7 @@ PGAPI_Fetch(
 
    if (!(res = SC_get_Curres(stmt)))
    {
-       stmt->errormsg = "Null statement result in PGAPI_Fetch.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Null statement result in PGAPI_Fetch.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1014,24 +990,21 @@ PGAPI_Fetch(
    opts = SC_get_ARD(stmt);
    if (opts->bookmark->buffer)
    {
-       stmt->errornumber = STMT_COLNUM_ERROR;
-       stmt->errormsg = "Not allowed to bind a bookmark column when using PGAPI_Fetch";
+       SC_set_error(stmt, STMT_COLNUM_ERROR, "Not allowed to bind a bookmark column when using PGAPI_Fetch");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (stmt->status == STMT_EXECUTING)
    {
-       stmt->errormsg = "Can't fetch while statement is still executing.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't fetch while statement is still executing.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (stmt->status != STMT_FINISHED)
    {
-       stmt->errornumber = STMT_STATUS_ERROR;
-       stmt->errormsg = "Fetch can only be called after the successful execution on a SQL statement";
+       SC_set_error(stmt, STMT_STATUS_ERROR, "Fetch can only be called after the successful execution on a SQL statement");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1040,8 +1013,7 @@ PGAPI_Fetch(
    {
        /* just to avoid a crash if the user insists on calling this */
        /* function even if SQL_ExecDirect has reported an Error */
-       stmt->errormsg = "Bindings were not allocated properly.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Bindings were not allocated properly.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1176,8 +1148,7 @@ PGAPI_ExtendedFetch(
    {
        if (fFetchType != SQL_FETCH_NEXT)
        {
-           stmt->errornumber = STMT_FETCH_OUT_OF_RANGE;
-           stmt->errormsg = "The fetch type for PGAPI_ExtendedFetch isn't allowed with ForwardOnly cursor.";
+           SC_set_error(stmt, STMT_FETCH_OUT_OF_RANGE, "The fetch type for PGAPI_ExtendedFetch isn't allowed with ForwardOnly cursor.");
            return SQL_ERROR;
        }
    }
@@ -1186,8 +1157,7 @@ PGAPI_ExtendedFetch(
 
    if (!(res = SC_get_Curres(stmt)))
    {
-       stmt->errormsg = "Null statement result in PGAPI_ExtendedFetch.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Null statement result in PGAPI_ExtendedFetch.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1199,24 +1169,21 @@ PGAPI_ExtendedFetch(
     */
    if (opts->bookmark->buffer && stmt->options.use_bookmarks == SQL_UB_OFF)
    {
-       stmt->errornumber = STMT_COLNUM_ERROR;
-       stmt->errormsg = "Attempt to retrieve bookmark with bookmark usage disabled";
+       SC_set_error(stmt, STMT_COLNUM_ERROR, "Attempt to retrieve bookmark with bookmark usage disabled");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (stmt->status == STMT_EXECUTING)
    {
-       stmt->errormsg = "Can't fetch while statement is still executing.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't fetch while statement is still executing.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (stmt->status != STMT_FINISHED)
    {
-       stmt->errornumber = STMT_STATUS_ERROR;
-       stmt->errormsg = "ExtendedFetch can only be called after the successful execution on a SQL statement";
+       SC_set_error(stmt, STMT_STATUS_ERROR, "ExtendedFetch can only be called after the successful execution on a SQL statement");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1225,8 +1192,7 @@ PGAPI_ExtendedFetch(
    {
        /* just to avoid a crash if the user insists on calling this */
        /* function even if SQL_ExecDirect has reported an Error */
-       stmt->errormsg = "Bindings were not allocated properly.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Bindings were not allocated properly.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -1299,8 +1265,7 @@ PGAPI_ExtendedFetch(
            {
                if (opts->rowset_size > num_tuples)
                {
-                   stmt->errornumber = STMT_POS_BEFORE_RECORDSET;
-                   stmt->errormsg = "fetch prior from eof and before the beggining";
+                   SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior from eof and before the beggining");
                }
                stmt->rowset_start = num_tuples <= 0 ? 0 : (num_tuples - opts->rowset_size);
 
@@ -1310,8 +1275,7 @@ PGAPI_ExtendedFetch(
 #ifdef DRIVER_CURSOR_IMPLEMENT
                if (i = getNthValid(res, stmt->rowset_start - 1, SQL_FETCH_PRIOR, opts->rowset_size, &stmt->rowset_start), i < -1)
                {
-                   stmt->errormsg = "fetch prior and before the beggining";
-                   stmt->errornumber = STMT_POS_BEFORE_RECORDSET;
+                   SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior and before the beggining");
                    stmt->rowset_start = 0;
                }
                else if (i <= 0)
@@ -1321,8 +1285,7 @@ PGAPI_ExtendedFetch(
 #else
                if (stmt->rowset_start < opts->rowset_size)
                {
-                   stmt->errormsg = "fetch prior and before the beggining";
-                   stmt->errornumber = STMT_POS_BEFORE_RECORDSET;
+                   SC_set_error(stmt, STMT_POS_BEFORE_RECORDSET, "fetch prior and before the beggining");
                    stmt->rowset_start = 0;
                }
                else
@@ -1557,7 +1520,7 @@ PGAPI_ExtendedFetch(
        return SQL_ERROR;
    else if (truncated)
        return SQL_SUCCESS_WITH_INFO;
-   else if (stmt->errornumber == STMT_POS_BEFORE_RECORDSET)
+   else if (SC_get_errornumber(stmt) == STMT_POS_BEFORE_RECORDSET)
        return SQL_SUCCESS_WITH_INFO;
    else
        return SQL_SUCCESS;
@@ -1919,8 +1882,7 @@ SC_pos_reload(StatementClass *stmt, UDWORD global_ridx, UWORD *count, BOOL logCh
        }
        else
        {
-           stmt->errornumber = STMT_ROW_VERSION_CHANGED;
-           stmt->errormsg = "the content was deleted after last fetch";
+           SC_set_error(stmt, STMT_ROW_VERSION_CHANGED, "the content was deleted after last fetch");
            ret = SQL_SUCCESS_WITH_INFO;
            if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
            {
@@ -1929,8 +1891,8 @@ SC_pos_reload(StatementClass *stmt, UDWORD global_ridx, UWORD *count, BOOL logCh
        }
        QR_Destructor(qres);
    }
-   else if (stmt->errornumber == 0)
-       stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
+   else if (SC_get_errornumber(stmt) == 0)
+       SC_set_errornumber(stmt, STMT_ERROR_TAKEN_FROM_BACKEND);
    if (count)
        *count = rcnt;
    return ret;
@@ -2147,8 +2109,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, BOOL tidRef)
                        res->num_fields * sizeof(TupleField) * tuple_size);
                    if (!res->backend_tuples)
                    {
-                       stmt->errornumber = res->status = PGRES_FATAL_ERROR;
-                       stmt->errormsg = "Out of memory while reading tuples.";
+                       SC_set_error(stmt, res->status = PGRES_FATAL_ERROR, "Out of memory while reading tuples.");
                        QR_Destructor(qres);
                        return SQL_ERROR;
                    }
@@ -2176,8 +2137,7 @@ SC_pos_newload(StatementClass *stmt, UInt4 oid, BOOL tidRef)
            ret = SQL_NO_DATA_FOUND;
        else
        {
-           stmt->errornumber = STMT_ROW_VERSION_CHANGED;
-           stmt->errormsg = "the driver cound't identify inserted rows";
+           SC_set_error(stmt, STMT_ROW_VERSION_CHANGED, "the driver cound't identify inserted rows");
            ret = SQL_ERROR;
        }
        QR_Destructor(qres);
@@ -2201,8 +2161,7 @@ irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow
                ret = SC_pos_reload(stmt, global_ridx, (UWORD *) 0, TRUE);
            else if (updcnt == 0)
            {
-               stmt->errornumber = STMT_ROW_VERSION_CHANGED;
-               stmt->errormsg = "the content was changed before updation";
+               SC_set_error(stmt, STMT_ROW_VERSION_CHANGED, "the content was changed before updation");
                ret = SQL_ERROR;
                if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
                    SC_pos_reload(stmt, global_ridx, (UWORD *) 0, FALSE);
@@ -2212,10 +2171,9 @@ irow_update(RETCODE ret, StatementClass *stmt, StatementClass *ustmt, UWORD irow
        }
        else
            ret = SQL_ERROR;
-       if (ret == SQL_ERROR && stmt->errornumber == 0)
+       if (ret == SQL_ERROR && SC_get_errornumber(stmt) == 0)
        {
-           stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
-           stmt->errormsg = "SetPos update return error";
+           SC_set_error(stmt, STMT_ERROR_TAKEN_FROM_BACKEND, "SetPos update return error");
        }
    }
    return ret;
@@ -2251,7 +2209,7 @@ SC_pos_update(StatementClass *stmt,
    }
    if (!(oid = getOid(res, global_ridx)))
    {
-       stmt->errormsg = "The row is already deleted";
+       SC_set_errormsg(stmt, "The row is already deleted");
        return SQL_ERROR;
    }
    getTid(res, global_ridx, &blocknum, &pgoffset);
@@ -2333,14 +2291,12 @@ SC_pos_update(StatementClass *stmt,
        ret = PGAPI_ExecDirect(hstmt, updstr, strlen(updstr));
        if (ret == SQL_ERROR)
        {
-           stmt->errornumber = qstmt->errornumber;
-           stmt->errormsg = qstmt->errormsg;
+           SC_error_copy(stmt, qstmt);
        }
        else if (ret == SQL_NEED_DATA)  /* must be fixed */
        {
            stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
-           stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
-           stmt->errormsg = "SetPos with data_at_exec not yet supported";
+           SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "SetPos with data_at_exec not yet supported");
            ret = SQL_ERROR;
        }
        ret = irow_update(ret, stmt, qstmt, irow, global_ridx);
@@ -2349,7 +2305,7 @@ SC_pos_update(StatementClass *stmt,
    else
    {
        ret = SQL_SUCCESS_WITH_INFO;
-       stmt->errormsg = "update list null";
+       SC_set_errormsg(stmt, "update list null");
    }
    if (SQL_SUCCESS == ret && res->keyset)
    {
@@ -2402,7 +2358,7 @@ SC_pos_delete(StatementClass *stmt,
    }
    if (!(oid = getOid(res, global_ridx)))
    {
-       stmt->errormsg = "The row is already deleted";
+       SC_set_errormsg(stmt, "The row is already deleted");
        return SQL_ERROR;
    }
    getTid(res, global_ridx, &blocknum, &offset);
@@ -2433,8 +2389,7 @@ SC_pos_delete(StatementClass *stmt,
                SC_pos_reload(stmt, global_ridx, (UWORD *) 0, TRUE);
            else if (dltcnt == 0)
            {
-               stmt->errornumber = STMT_ROW_VERSION_CHANGED;
-               stmt->errormsg = "the content was changed before deletion";
+               SC_set_error(stmt, STMT_ROW_VERSION_CHANGED, "the content was changed before deletion");
                ret = SQL_ERROR;
                if (stmt->options.cursor_type == SQL_CURSOR_KEYSET_DRIVEN)
                    SC_pos_reload(stmt, global_ridx, (UWORD *) 0, FALSE);
@@ -2447,10 +2402,9 @@ SC_pos_delete(StatementClass *stmt,
    }
    else
        ret = SQL_ERROR;
-   if (ret == SQL_ERROR && stmt->errornumber == 0)
+   if (ret == SQL_ERROR && SC_get_errornumber(stmt) == 0)
    {
-       stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
-       stmt->errormsg = "SetPos delete return error";
+       SC_set_error(stmt, STMT_ERROR_TAKEN_FROM_BACKEND, "SetPos delete return error");
    }
    if (qres)
        QR_Destructor(qres);
@@ -2526,8 +2480,7 @@ irow_insert(RETCODE ret, StatementClass *stmt, StatementClass *istmt, int addpos
        }
        else
        {
-           stmt->errornumber = STMT_ERROR_TAKEN_FROM_BACKEND;
-           stmt->errormsg = "SetPos insert return error";
+           SC_set_error(stmt, STMT_ERROR_TAKEN_FROM_BACKEND, "SetPos insert return error");
        }
    }
    return ret;
@@ -2630,14 +2583,12 @@ SC_pos_add(StatementClass *stmt,
        ret = PGAPI_ExecDirect(hstmt, addstr, strlen(addstr));
        if (ret == SQL_ERROR)
        {
-           stmt->errornumber = qstmt->errornumber;
-           stmt->errormsg = qstmt->errormsg;
+           SC_error_copy(stmt, qstmt);
        }
        else if (ret == SQL_NEED_DATA)      /* must be fixed */
        {
            stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
-           stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
-           stmt->errormsg = "SetPos with data_at_exec not yet supported";
+           SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "SetPos with data_at_exec not yet supported");
            ret = SQL_ERROR;
        }
        brow_save = stmt->bind_row; 
@@ -2648,7 +2599,7 @@ SC_pos_add(StatementClass *stmt,
    else
    {
        ret = SQL_SUCCESS_WITH_INFO;
-       stmt->errormsg = "insert list null";
+       SC_set_errormsg(stmt, "insert list null");
    }
    PGAPI_FreeStmt(hstmt, SQL_DROP);
    if (SQL_SUCCESS == ret && res->keyset)
@@ -2768,16 +2719,14 @@ PGAPI_SetPos(
 #endif   /* DRIVER_CURSOR_IMPLEMENT */
    if (fOption != SQL_POSITION && fOption != SQL_REFRESH)
    {
-       stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-       stmt->errormsg = "Only SQL_POSITION/REFRESH is supported for PGAPI_SetPos";
+       SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Only SQL_POSITION/REFRESH is supported for PGAPI_SetPos");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
 
    if (!(res = SC_get_Curres(stmt)))
    {
-       stmt->errormsg = "Null statement result in PGAPI_SetPos.";
-       stmt->errornumber = STMT_SEQUENCE_ERROR;
+       SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Null statement result in PGAPI_SetPos.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2786,8 +2735,7 @@ PGAPI_SetPos(
    {
        if (SQL_POSITION == fOption)
        {
-           stmt->errornumber = STMT_INVALID_CURSOR_POSITION;
-           stmt->errormsg = "Bulk Position operations not allowed.";
+           SC_set_error(stmt, STMT_INVALID_CURSOR_POSITION, "Bulk Position operations not allowed.");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -2798,8 +2746,7 @@ PGAPI_SetPos(
    {
        if (irow > stmt->last_fetch_count)
        {
-           stmt->errornumber = STMT_ROW_OUT_OF_RANGE;
-           stmt->errormsg = "Row value out of range";
+           SC_set_error(stmt, STMT_ROW_OUT_OF_RANGE, "Row value out of range");
            SC_log_error(func, "", stmt);
            return SQL_ERROR;
        }
@@ -2906,8 +2853,7 @@ PGAPI_SetScrollOptions( HSTMT hstmt,
 
    mylog("PGAPI_SetScrollOptions fConcurrency=%d crowKeyset=%d crowRowset=%d\n",
          fConcurrency, crowKeyset, crowRowset);
-   stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
-   stmt->errormsg = "SetScroll option not implemeted";
+   SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "SetScroll option not implemeted");
 
    SC_log_error(func, "Function not implemented", hstmt);
    return SQL_ERROR;
@@ -2937,8 +2883,7 @@ PGAPI_SetCursorName(
 
    if (len <= 0 || len > sizeof(stmt->cursor_name) - 1)
    {
-       stmt->errornumber = STMT_INVALID_CURSOR_NAME;
-       stmt->errormsg = "Invalid Cursor Name";
+       SC_set_error(stmt, STMT_INVALID_CURSOR_NAME, "Invalid Cursor Name");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2971,8 +2916,7 @@ PGAPI_GetCursorName(
 
    if (stmt->cursor_name[0] == '\0')
    {
-       stmt->errornumber = STMT_NO_CURSOR_NAME;
-       stmt->errormsg = "No Cursor name available";
+       SC_set_error(stmt, STMT_NO_CURSOR_NAME, "No Cursor name available");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -2987,8 +2931,7 @@ PGAPI_GetCursorName(
        if (len >= cbCursorMax)
        {
            result = SQL_SUCCESS_WITH_INFO;
-           stmt->errornumber = STMT_TRUNCATED;
-           stmt->errormsg = "The buffer was too small for the GetCursorName.";
+           SC_set_error(stmt, STMT_TRUNCATED, "The buffer was too small for the GetCursorName.");
        }
    }
 
index c8742a6cd36a51698b5fb35277ba9adbffa5f919..10b536c041c7d1ae9234231cad9c5001d1297d9a 100644 (file)
@@ -99,8 +99,7 @@ PGAPI_AllocStmt(HDBC hdbc,
 
    if (!stmt)
    {
-       conn->errornumber = CONN_STMT_ALLOC_ERROR;
-       conn->errormsg = "No more memory to allocate a further SQL-statement";
+       CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "No more memory to allocate a further SQL-statement");
        *phstmt = SQL_NULL_HSTMT;
        CC_log_error(func, "", conn);
        return SQL_ERROR;
@@ -108,8 +107,7 @@ PGAPI_AllocStmt(HDBC hdbc,
 
    if (!CC_add_statement(conn, stmt))
    {
-       conn->errormsg = "Maximum number of connections exceeded.";
-       conn->errornumber = CONN_STMT_ALLOC_ERROR;
+       CC_set_error(conn, CONN_STMT_ALLOC_ERROR, "Maximum number of connections exceeded.");
        CC_log_error(func, "", conn);
        SC_Destructor(stmt);
        *phstmt = SQL_NULL_HSTMT;
@@ -158,8 +156,7 @@ PGAPI_FreeStmt(HSTMT hstmt,
        {
            if (!CC_remove_statement(conn, stmt))
            {
-               stmt->errornumber = STMT_SEQUENCE_ERROR;
-               stmt->errormsg = "Statement is currently executing a transaction.";
+               SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
                SC_log_error(func, "", stmt);
                return SQL_ERROR;       /* stmt may be executing a
                                         * transaction */
@@ -195,8 +192,7 @@ PGAPI_FreeStmt(HSTMT hstmt,
        SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
    else
    {
-       stmt->errormsg = "Invalid option passed to PGAPI_FreeStmt.";
-       stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR;
+       SC_set_error(stmt, STMT_OPTION_OUT_OF_RANGE_ERROR, "Invalid option passed to PGAPI_FreeStmt.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
@@ -261,8 +257,8 @@ SC_Constructor(void)
        rv->status = STMT_ALLOCATED;
        rv->internal = FALSE;
 
-       rv->errormsg = NULL;
-       rv->errornumber = 0;
+       rv->__error_message = NULL;
+       rv->__error_number = 0;
        rv->errormsg_created = FALSE;
 
        rv->statement = NULL;
@@ -306,6 +302,7 @@ SC_Constructor(void)
        rv->updatable = FALSE;
        rv->error_recsize = -1;
        rv->diag_row_count = 0;
+       INIT_STMT_CS(rv);
    }
    return rv;
 }
@@ -366,8 +363,7 @@ SC_Destructor(StatementClass *self)
    SC_clear_error(self);
    if (STMT_EXECUTING == self->status)
    {
-       self->errornumber = STMT_SEQUENCE_ERROR;
-       self->errormsg = "Statement is currently executing a transaction.";
+       SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
        return FALSE;
    }
 
@@ -408,6 +404,9 @@ SC_Destructor(StatementClass *self)
    IRDFields_free(&(self->irdopts));
    IPDFields_free(&(self->ipdopts));
    
+   if (self->__error_message)
+       free(self->__error_message);
+   DELETE_STMT_CS(self);
    free(self);
 
    mylog("SC_Destructor: EXIT\n");
@@ -470,8 +469,7 @@ SC_recycle_statement(StatementClass *self)
    /* This would not happen */
    if (self->status == STMT_EXECUTING)
    {
-       self->errornumber = STMT_SEQUENCE_ERROR;
-       self->errormsg = "Statement is currently executing a transaction.";
+       SC_set_error(self, STMT_SEQUENCE_ERROR, "Statement is currently executing a transaction.");
        return FALSE;
    }
 
@@ -503,8 +501,7 @@ SC_recycle_statement(StatementClass *self)
            break;
 
        default:
-           self->errormsg = "An internal error occured while recycling statements";
-           self->errornumber = STMT_INTERNAL_ERROR;
+           SC_set_error(self, STMT_INTERNAL_ERROR, "An internal error occured while recycling statements");
            return FALSE;
    }
 
@@ -545,8 +542,8 @@ SC_recycle_statement(StatementClass *self)
    self->bind_row = 0;
    self->last_fetch_count = self->last_fetch_count_include_ommitted = 0;
 
-   self->errormsg = NULL;
-   self->errornumber = 0;
+   self->__error_message = NULL;
+   self->__error_number = 0;
    self->errormsg_created = FALSE;
 
    self->lobj_fd = -1;
@@ -624,8 +621,10 @@ SC_unbind_cols(StatementClass *self)
 void
 SC_clear_error(StatementClass *self)
 {
-   self->errornumber = 0;
-   self->errormsg = NULL;
+   self->__error_number = 0;
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_message = NULL;
    self->errormsg_created = FALSE;
    self->errorpos = 0;
    self->error_recsize = -1;
@@ -638,23 +637,23 @@ SC_clear_error(StatementClass *self)
  * of the result, statement, connection, and socket messages.
  */
 char *
-SC_create_errormsg(StatementClass *self)
+SC_create_errormsg(const StatementClass *self)
 {
    QResultClass *res = SC_get_Curres(self);
    ConnectionClass *conn = self->hdbc;
    int         pos;
    BOOL            detailmsg = FALSE;
-   static char msg[4096];
+   char             msg[4096];
 
    msg[0] = '\0';
 
    if (res && res->message)
    {
-       strcpy(msg, res->message);
+       strncpy(msg, res->message, sizeof(msg));
        detailmsg = TRUE;
    }
-   else if (self->errormsg)
-       strcpy(msg, self->errormsg);
+   else if (SC_get_errormsg(self))
+       strncpy(msg, SC_get_errormsg(self), sizeof(msg));
 
    if (!msg[0] && res && QR_get_notice(res))
    {
@@ -666,16 +665,16 @@ SC_create_errormsg(StatementClass *self)
            msg[len] = '\0';
        }
        else
-           return notice;
+           return strdup(notice);
    }
    if (conn)
    {
        SocketClass *sock = conn->sock;
 
-       if (!detailmsg && conn->errormsg && conn->errormsg[0] != '\0')
+       if (!detailmsg && CC_get_errormsg(conn) && (CC_get_errormsg(conn))[0] != '\0')
        {
            pos = strlen(msg);
-           sprintf(&msg[pos], ";\n%s", conn->errormsg);
+           sprintf(&msg[pos], ";\n%s", CC_get_errormsg(conn));
        }
 
        if (sock && sock->errormsg && sock->errormsg[0] != '\0')
@@ -684,31 +683,73 @@ SC_create_errormsg(StatementClass *self)
            sprintf(&msg[pos], ";\n%s", sock->errormsg);
        }
    }
-   return msg;
+   return msg[0] ? strdup(msg) : NULL;
 }
 
 
+void
+SC_set_error(StatementClass *self, int number, const char *message)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_number = number;
+   self->__error_message = message ? strdup(message) : NULL;
+}
+
+
+void
+SC_set_errormsg(StatementClass *self, const char *message)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_message = message ? strdup(message) : NULL;
+}
+
+
+void
+SC_error_copy(StatementClass *self, const StatementClass *from)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_number = from->__error_number;
+   self->__error_message = from->__error_message ? strdup(from->__error_message) : NULL;
+}
+
+
+void
+SC_full_error_copy(StatementClass *self, const StatementClass *from)
+{
+   if (self->__error_message)
+       free(self->__error_message);
+   self->__error_number = from->__error_number;
+   self->__error_message = SC_create_errormsg(from);
+   self->errormsg_created = TRUE;
+}
+
 char
 SC_get_error(StatementClass *self, int *number, char **message)
 {
-   char        rv;
+   char    rv, *msgcrt;
 
    /* Create a very informative errormsg if it hasn't been done yet. */
    if (!self->errormsg_created)
    {
-       self->errormsg = SC_create_errormsg(self);
+       msgcrt = SC_create_errormsg(self);
+       if (self->__error_message)
+           free(self->__error_message);
+       self->__error_message = msgcrt; 
        self->errormsg_created = TRUE;
        self->errorpos = 0;
        self->error_recsize = -1;
    }
 
-   if (self->errornumber)
+   if (SC_get_errornumber(self))
    {
-       *number = self->errornumber;
-       *message = self->errormsg;
+       *number = SC_get_errornumber(self);
+       *message = self->__error_message;
    }
 
-   rv = (self->errornumber != 0);
+   rv = (SC_get_errornumber(self) != 0);
 
    return rv;
 }
@@ -779,8 +820,7 @@ SC_fetch(StatementClass *self)
        else
        {
            mylog("SC_fetch: error\n");
-           self->errornumber = STMT_EXEC_ERROR;
-           self->errormsg = "Error fetching next row";
+           SC_set_error(self, STMT_EXEC_ERROR, "Error fetching next row");
            SC_log_error(func, "", self);
            return SQL_ERROR;
        }
@@ -872,22 +912,19 @@ SC_fetch(StatementClass *self)
                    break;      /* OK, do next bound column */
 
                case COPY_UNSUPPORTED_TYPE:
-                   self->errormsg = "Received an unsupported type from Postgres.";
-                   self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
+                   SC_set_error(self, STMT_RESTRICTED_DATA_TYPE_ERROR, "Received an unsupported type from Postgres.");
                    SC_log_error(func, "", self);
                    result = SQL_ERROR;
                    break;
 
                case COPY_UNSUPPORTED_CONVERSION:
-                   self->errormsg = "Couldn't handle the necessary data type conversion.";
-                   self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
+                   SC_set_error(self, STMT_RESTRICTED_DATA_TYPE_ERROR, "Couldn't handle the necessary data type conversion.");
                    SC_log_error(func, "", self);
                    result = SQL_ERROR;
                    break;
 
                case COPY_RESULT_TRUNCATED:
-                   self->errornumber = STMT_TRUNCATED;
-                   self->errormsg = "Fetched item was truncated.";
+                   SC_set_error(self, STMT_TRUNCATED, "Fetched item was truncated.");
                    qlog("The %dth item was truncated\n", lf + 1);
                    qlog("The buffer size = %d", opts->bindings[lf].buflen);
                    qlog(" and the value is '%s'\n", value);
@@ -905,8 +942,7 @@ SC_fetch(StatementClass *self)
                    break;
 
                default:
-                   self->errormsg = "Unrecognized return value from copy_and_convert_field.";
-                   self->errornumber = STMT_INTERNAL_ERROR;
+                   SC_set_error(self, STMT_INTERNAL_ERROR, "Unrecognized return value from copy_and_convert_field.");
                    SC_log_error(func, "", self);
                    result = SQL_ERROR;
                    break;
@@ -931,6 +967,7 @@ SC_execute(StatementClass *self)
    QueryInfo   qi;
    ConnInfo   *ci;
    UDWORD      qflag = 0;
+   BOOL        auto_begin = FALSE, is_in_trans;
 
 
    conn = SC_get_conn(self);
@@ -946,17 +983,18 @@ SC_execute(StatementClass *self)
     * 2) we are in autocommit off state and the statement isn't of type
     * OTHER.
     */
-   if (!self->internal && !CC_is_in_trans(conn) &&
+   is_in_trans = CC_is_in_trans(conn);
+   if (!self->internal && !is_in_trans &&
        (SC_is_fetchcursor(self) ||
         (!CC_is_in_autocommit(conn) && self->statement_type != STMT_TYPE_OTHER)))
    {
        mylog("   about to begin a transaction on statement = %u\n", self);
+       auto_begin = TRUE;
        if (PG_VERSION_GE(conn, 7.1))
            qflag |= GO_INTO_TRANSACTION;
                 else if (!CC_begin(conn))
                 {
-                        self->errormsg = "Could not begin a transaction";
-                        self->errornumber = STMT_EXEC_ERROR;
+           SC_set_error(self, STMT_EXEC_ERROR, "Could not begin a transaction");
                         SC_log_error(func, "", self);
                         return SQL_ERROR;
                 }
@@ -1024,8 +1062,13 @@ SC_execute(StatementClass *self)
         * Above seems wrong. Even in case of autocommit, started
         * transactions must be committed. (Hiroshi, 02/11/2001)
         */
-       if (!self->internal && CC_is_in_autocommit(conn) && CC_is_in_trans(conn))
-           CC_commit(conn);
+       if (CC_is_in_trans(conn))
+       {
+           if (!is_in_trans)
+               CC_set_in_manual_trans(conn);
+           if (!self->internal && CC_is_in_autocommit(conn) && !CC_is_in_manual_trans(conn))
+               CC_commit(conn);
+       }
    }
 
    conn->status = oldstatus;
@@ -1038,9 +1081,9 @@ SC_execute(StatementClass *self)
        was_nonfatal = QR_command_nonfatal(res);
 
        if (was_ok)
-           self->errornumber = STMT_OK;
+           SC_set_errornumber(self, STMT_OK);
        else
-           self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;
+           SC_set_errornumber(self, was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND);
 
        /* set cursor before the first tuple in the list */
        self->currTuple = -1;
@@ -1065,8 +1108,7 @@ SC_execute(StatementClass *self)
                if (opts->bindings == NULL)
                {
                    QR_Destructor(res);
-                   self->errornumber = STMT_NO_MEMORY_ERROR;
-                   self->errormsg = "Could not get enough free memory to store the binding information";
+                   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;
                }
@@ -1078,8 +1120,7 @@ SC_execute(StatementClass *self)
        /* Bad Error -- The error message will be in the Connection */
        if (self->statement_type == STMT_TYPE_CREATE)
        {
-           self->errornumber = STMT_CREATE_TABLE_ERROR;
-           self->errormsg = "Error creating the table";
+           SC_set_error(self, STMT_CREATE_TABLE_ERROR, "Error creating the table");
 
            /*
             * This would allow the table to already exists, thus
@@ -1090,8 +1131,7 @@ SC_execute(StatementClass *self)
        }
        else
        {
-           self->errornumber = STMT_EXEC_ERROR;
-           self->errormsg = conn->errormsg;
+           SC_set_error(self, STMT_EXEC_ERROR, CC_get_errormsg(conn));
        }
 
        if (!self->internal)
@@ -1109,8 +1149,8 @@ SC_execute(StatementClass *self)
 
    apdopts = SC_get_APD(self);
    if (self->statement_type == STMT_TYPE_PROCCALL &&
-       (self->errornumber == STMT_OK ||
-        self->errornumber == STMT_INFO_ONLY) &&
+       (SC_get_errornumber(self) == STMT_OK ||
+        SC_get_errornumber(self) == STMT_INFO_ONLY) &&
        apdopts->parameters &&
        apdopts->parameters[0].buffer &&
        apdopts->parameters[0].paramType == SQL_PARAM_OUTPUT)
@@ -1125,24 +1165,22 @@ SC_execute(StatementClass *self)
            ret = PGAPI_GetData(hstmt, 1, apdopts->parameters[0].CType, apdopts->parameters[0].buffer, apdopts->parameters[0].buflen, apdopts->parameters[0].used);
            if (ret != SQL_SUCCESS)
            {
-               self->errornumber = STMT_EXEC_ERROR;
-               self->errormsg = "GetData to Procedure return failed.";
+               SC_set_error(self, STMT_EXEC_ERROR, "GetData to Procedure return failed.");
            }
        }
        else
        {
-           self->errornumber = STMT_EXEC_ERROR;
-           self->errormsg = "SC_fetch to get a Procedure return failed.";
+           SC_set_error(self, STMT_EXEC_ERROR, "SC_fetch to get a Procedure return failed.");
        }
    }
-   if (self->errornumber == STMT_OK)
+   if (SC_get_errornumber(self) == STMT_OK)
        return SQL_SUCCESS;
-   else if (self->errornumber == STMT_INFO_ONLY)
+   else if (SC_get_errornumber(self) == STMT_INFO_ONLY)
        return SQL_SUCCESS_WITH_INFO;
    else
    {
-       if (!self->errormsg || !self->errormsg[0])
-           self->errormsg = "Error while executing the query";
+       if (!SC_get_errormsg(self) || !SC_get_errormsg(self)[0])
+           SC_set_errormsg(self, "Error while executing the query");
        SC_log_error(func, "", self);
        return SQL_ERROR;
    }
@@ -1161,8 +1199,8 @@ SC_log_error(const char *func, const char *desc, const StatementClass *self)
        const ARDFields *opts = SC_get_ARD(self);
        const APDFields *apdopts = SC_get_APD(self);
 
-       qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
-       mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->errornumber, nullcheck(self->errormsg));
+       qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
+       mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'\n", func, desc, self->__error_number, nullcheck(self->__error_message));
        qlog("                 ------------------------------------------------------------\n");
        qlog("                 hdbc=%u, stmt=%u, result=%u\n", self->hdbc, self, res);
        qlog("                 manual_result=%d, prepare=%d, internal=%d\n", self->manual_result, self->prepare, self->internal);
index fd220671e5911baae1a1010422e3fc5193580ccc..7b17250f1c5ba6f410989d9ab2541ef7d57fafdc 100644 (file)
@@ -136,8 +136,8 @@ struct StatementClass_
    IPDFields ipdopts;
 
    STMT_Status status;
-   char       *errormsg;
-   int         errornumber;
+   char       *__error_message;
+   int         __error_number;
 
    Int4        currTuple;      /* current absolute row number (GetData,
                                 * SetPos, SQLFetch) */
@@ -198,6 +198,10 @@ struct StatementClass_
    Int4        from_pos;   
    Int4        where_pos;
    Int4        last_fetch_count_include_ommitted;
+#ifdef WIN_MULTITHREAD_SUPPORT
+   CRITICAL_SECTION    cs;
+#endif /* WIN_MULTITHREAD_SUPPORT */
+
 };
 
 #define SC_get_conn(a)   (a->hdbc)
@@ -210,6 +214,10 @@ struct StatementClass_
 #define SC_get_IRD(a)  (&(a->irdopts))
 #define SC_get_IPD(a)  (&(a->ipdopts))
 
+#define    SC_get_errornumber(a) (a->__error_number)
+#define    SC_set_errornumber(a, n) (a->__error_number = n)
+#define    SC_get_errormsg(a) (a->__error_message)
+
 /* options for SC_free_params() */
 #define STMT_FREE_PARAMS_ALL               0
 #define STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY 1
@@ -222,6 +230,18 @@ struct StatementClass_
 #define SC_no_fetchcursor(a)   (a->miscinfo &= ~2L)
 #define SC_is_fetchcursor(a)   ((a->miscinfo & 2L) != 0)
 
+/* For Multi-thread */
+#ifdef WIN_MULTITHREAD_SUPPORT
+#define INIT_STMT_CS(x)        InitializeCriticalSection(&((x)->cs))
+#define ENTER_STMT_CS(x)   EnterCriticalSection(&((x)->cs))
+#define LEAVE_STMT_CS(x)   LeaveCriticalSection(&((x)->cs))
+#define DELETE_STMT_CS(x)  DeleteCriticalSection(&((x)->cs))
+#else
+#define INIT_STMT_CS(x)
+#define ENTER_STMT_CS(x)
+#define LEAVE_STMT_CS(x)
+#define DELETE_STMT_CS(x)
+#endif /* WIN_MULTITHREAD_SUPPORT */
 /* Statement prototypes */
 StatementClass *SC_Constructor(void);
 void       InitializeStatementOptions(StatementOptions *opt);
@@ -233,8 +253,12 @@ char       SC_unbind_cols(StatementClass *self);
 char       SC_recycle_statement(StatementClass *self);
 
 void       SC_clear_error(StatementClass *self);
+void       SC_set_error(StatementClass *self, int errnum, const char *msg);
+void       SC_set_errormsg(StatementClass *self, const char *msg);
+void       SC_error_copy(StatementClass *self, const StatementClass *from);
+void       SC_full_error_copy(StatementClass *self, const StatementClass *from);
 char       SC_get_error(StatementClass *self, int *number, char **message);
-char      *SC_create_errormsg(StatementClass *self);
+char       *SC_create_errormsg(const StatementClass *self);
 RETCODE        SC_execute(StatementClass *self);
 RETCODE        SC_fetch(StatementClass *self);
 void       SC_free_params(StatementClass *self, char option);
index 88516a768f398035f302bc4335e0eec6fe871293..89bb5df3bb643096d93a664fcba8f3cc6c3ad793 100644 (file)
--- a/version.h
+++ b/version.h
@@ -9,8 +9,8 @@
 #ifndef __VERSION_H__
 #define __VERSION_H__
 
-#define POSTGRESDRIVERVERSION      "07.02.0002"
-#define POSTGRES_RESOURCE_VERSION  "07.02.0002\0"
-#define PG_DRVFILE_VERSION     7,2,0,02
+#define POSTGRESDRIVERVERSION      "07.02.0003"
+#define POSTGRES_RESOURCE_VERSION  "07.02.0003\0"
+#define PG_DRVFILE_VERSION     7,2,0,03
 
 #endif