diff --git a/src/interfaces/odbc/environ.c b/src/interfaces/odbc/environ.c index 5a6b6b11a3bb56586c804ddb322e6d1f2a64ec75..506ca5cf7ba2b74d833d0a9ba61479db61253aad 100644 --- a/src/interfaces/odbc/environ.c +++ b/src/interfaces/odbc/environ.c @@ -91,12 +91,16 @@ SQLError( char *msg; int status; - mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u\n", henv, hdbc, hstmt); + mylog("**** SQLError: henv=%u, hdbc=%u, hstmt=%u <%d>\n", henv, hdbc, hstmt, cbErrorMsgMax); + if (cbErrorMsgMax < 0) + return SQL_ERROR; if (SQL_NULL_HSTMT != hstmt) { /* CC: return an error of a hstmt */ StatementClass *stmt = (StatementClass *) hstmt; + SWORD msglen; + BOOL once_again = FALSE; if (SC_get_error(stmt, &status, &msg)) { @@ -112,8 +116,18 @@ SQLError( return SQL_NO_DATA_FOUND; } + msglen = (SWORD) strlen(msg); if (NULL != pcbErrorMsg) - *pcbErrorMsg = (SWORD) strlen(msg); + { + *pcbErrorMsg = msglen; + if (cbErrorMsgMax == 0) + once_again = TRUE; + else if (msglen >= cbErrorMsgMax) + { + once_again = TRUE; + *pcbErrorMsg = cbErrorMsgMax - 1; + } + } if ((NULL != szErrorMsg) && (cbErrorMsgMax > 0)) strncpy_null(szErrorMsg, msg, cbErrorMsgMax); @@ -238,7 +252,27 @@ SQLError( return SQL_NO_DATA_FOUND; } - return SQL_SUCCESS; + if (once_again) + { + int outlen; + stmt->errornumber = status; + if (cbErrorMsgMax > 0) + outlen = *pcbErrorMsg; + else + outlen = 0; + if (!stmt->errormsg_malloced || !stmt->errormsg) + { + stmt->errormsg = malloc(msglen - outlen + 1); + stmt->errormsg_malloced = TRUE; + } + memmove(stmt->errormsg, msg + outlen, msglen - outlen + 1); + } + else if (stmt->errormsg_malloced) + SC_clear_error(stmt); + if (cbErrorMsgMax == 0) + return SQL_SUCCESS_WITH_INFO; + else + return SQL_SUCCESS; } else if (SQL_NULL_HDBC != hdbc) { diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c index ba6ca3efbd4740d5128d52915279dd0c0fbc33cd..fd77eee6d6c90db4b50ef10c2f85d2161abf0070 100644 --- a/src/interfaces/odbc/statement.c +++ b/src/interfaces/odbc/statement.c @@ -248,6 +248,7 @@ SC_Constructor(void) rv->errormsg = NULL; rv->errornumber = 0; rv->errormsg_created = FALSE; + rv->errormsg_malloced = FALSE; rv->statement = NULL; rv->stmt_with_params = NULL; @@ -530,9 +531,12 @@ SC_recycle_statement(StatementClass *self) self->bind_row = 0; self->last_fetch_count = 0; + if (self->errormsg_malloced && self->errormsg) + free(self->errormsg); self->errormsg = NULL; self->errornumber = 0; self->errormsg_created = FALSE; + self->errormsg_malloced = FALSE; self->lobj_fd = -1; @@ -610,9 +614,12 @@ SC_unbind_cols(StatementClass *self) void SC_clear_error(StatementClass *self) { + if (self->errormsg_malloced && self->errormsg) + free(self->errormsg); self->errornumber = 0; self->errormsg = NULL; self->errormsg_created = FALSE; + self->errormsg_malloced = FALSE; } @@ -675,7 +682,8 @@ SC_get_error(StatementClass *self, int *number, char **message) { *number = self->errornumber; *message = self->errormsg; - self->errormsg = NULL; + if (!self->errormsg_malloced) + self->errormsg = NULL; } rv = (self->errornumber != 0); diff --git a/src/interfaces/odbc/statement.h b/src/interfaces/odbc/statement.h index fe0b4a0b720eb34cb4c5bce349599a0481f4fd33..3f2fef5db7dfe321e4c04540f60fd62321e120f5 100644 --- a/src/interfaces/odbc/statement.h +++ b/src/interfaces/odbc/statement.h @@ -218,6 +218,8 @@ struct StatementClass_ char pre_executing; /* This statement is prematurely executing */ char inaccurate_result; /* Current status is PREMATURE but * result is inaccurate */ + char errormsg_malloced; /* Current status is PREMATURE but + * result is inaccurate */ }; #define SC_get_conn(a) (a->hdbc)