From 58ba2e8f758b00e9d89afb670cecdc4c7d02508f Mon Sep 17 00:00:00 2001 From: Hiroshi Inoue Date: Mon, 23 Sep 2002 08:08:22 +0000 Subject: [PATCH] 1) Removed most static variables for thread safety. 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. --- bind.c | 15 +- connection.c | 220 +++++++++++----------- connection.h | 36 +++- convert.c | 37 ++-- descriptor.h | 2 +- dlg_specific.h | 13 +- dlg_wingui.c | 3 +- drvconn.c | 3 +- environ.c | 17 +- environ.h | 27 +++ execute.c | 83 +++------ info.c | 488 +++++++++++++++++++++++++++++-------------------- info30.c | 6 +- misc.c | 17 ++ misc.h | 21 ++- multibyte.c | 3 +- odbcapi.c | 369 +++++++++++++++++++++++++++++++------ odbcapi30.c | 182 +++++++++++++----- odbcapi30w.c | 13 +- odbcapiw.c | 62 ++++++- options.c | 61 +++---- parse.c | 9 +- pgapi30.c | 56 +++--- pgtypes.c | 12 +- psqlodbc.c | 10 + psqlodbc.h | 11 +- qresult.c | 58 +++++- qresult.h | 6 +- results.c | 193 +++++++------------ statement.c | 178 +++++++++++------- statement.h | 30 ++- version.h | 6 +- 32 files changed, 1420 insertions(+), 827 deletions(-) diff --git a/bind.c b/bind.c index e6deeda..46a646e 100644 --- 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; } diff --git a/connection.c b/connection.c index ee3edc0..0cf0d72 100644 --- a/connection.c +++ b/connection.c @@ -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); diff --git a/connection.h b/connection.h index d9682d6..186fac5 100644 --- a/connection.h +++ b/connection.h @@ -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); diff --git a/convert.c b/convert.c index fb3e09c..c2f95d2 100644 --- 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; } } diff --git a/descriptor.h b/descriptor.h index 4abe0ec..abae3fd 100644 --- a/descriptor.h +++ b/descriptor.h @@ -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 $ * */ diff --git a/dlg_specific.h b/dlg_specific.h index 99005d3..370d936 100644 --- a/dlg_specific.h +++ b/dlg_specific.h @@ -32,9 +32,16 @@ #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 diff --git a/dlg_wingui.c b/dlg_wingui.c index 88c2e9f..1eb304a 100644 --- a/dlg_wingui.c +++ b/dlg_wingui.c @@ -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); diff --git a/drvconn.c b/drvconn.c index 6c08376..3dc772f 100644 --- 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."); } } diff --git a/environ.c b/environ.c index 9ac8f8e..9889c90 100644 --- 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; } diff --git a/environ.h b/environ.h index 24b456d..b2e0e38 100644 --- 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 diff --git a/execute.c b/execute.c index 598c2a2..3c0f52f 100644 --- 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 73dd27f..1d757c8 100644 --- 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); diff --git a/info30.c b/info30.c index 5e5b834..9007223 100644 --- 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 9a10c95..ea8f256 100644 --- 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 e2e34ce..e55b91a 100644 --- a/misc.h +++ b/misc.h @@ -29,6 +29,25 @@ */ #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 diff --git a/multibyte.c b/multibyte.c index 8c8c9f0..28d396d 100644 --- a/multibyte.c +++ b/multibyte.c @@ -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 diff --git a/odbcapi.c b/odbcapi.c index 6a4a618..b1f64ce 100644 --- a/odbcapi.c +++ b/odbcapi.c @@ -31,6 +31,7 @@ #include #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; } diff --git a/odbcapi30.c b/odbcapi30.c index cf73924..6cd70ce 100644 --- a/odbcapi30.c +++ b/odbcapi30.c @@ -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; } diff --git a/odbcapi30w.c b/odbcapi30w.c index 8992353..cf86135 100644 --- a/odbcapi30w.c +++ b/odbcapi30w.c @@ -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; } diff --git a/odbcapiw.c b/odbcapiw.c index ac1e3f2..96bb7b0 100644 --- a/odbcapiw.c +++ b/odbcapiw.c @@ -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; } diff --git a/options.c b/options.c index f4a510a..207aa60 100644 --- 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 a61b75e..8d52341 100644 --- 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; } diff --git a/pgapi30.c b/pgapi30.c index 7fd6c9a..24552a8 100644 --- 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); diff --git a/pgtypes.c b/pgtypes.c index fa9c7ae..57a34bd 100644 --- 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); diff --git a/psqlodbc.c b/psqlodbc.c index cc8d8b7..86d9a80 100644 --- a/psqlodbc.c +++ b/psqlodbc.c @@ -15,6 +15,7 @@ #include "psqlodbc.h" #include "dlg_specific.h" +#include "environ.h" #ifdef WIN32 #include @@ -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; diff --git a/psqlodbc.h b/psqlodbc.h index cc37d9f..68365cd 100644 --- a/psqlodbc.h +++ b/psqlodbc.h @@ -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 #include @@ -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" diff --git a/qresult.c b/qresult.c index 8c978b6..a12e7ed 100644 --- 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 */ diff --git a/qresult.h b/qresult.h index 03c4ed3..01c8e2f 100644 --- 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 */ diff --git a/results.c b/results.c index 28af870..e0a363d 100644 --- 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."); } } diff --git a/statement.c b/statement.c index c8742a6..10b536c 100644 --- a/statement.c +++ b/statement.c @@ -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); diff --git a/statement.h b/statement.h index fd22067..7b17250 100644 --- a/statement.h +++ b/statement.h @@ -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); diff --git a/version.h b/version.h index 88516a7..89bb5df 100644 --- 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 -- 2.39.5