From 5d1153d7d4957b944a3d1c3db621c12cbac31b6d Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Mon, 20 Aug 2018 12:29:09 -0700 Subject: [PATCH 1/2] Made error handling more flexible --- source/shared/core_sqlsrv.h | 14 ++++++++++---- source/shared/core_util.cpp | 30 ++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h index 7d7466cb8..b5ae9ef6f 100644 --- a/source/shared/core_sqlsrv.h +++ b/source/shared/core_sqlsrv.h @@ -175,7 +175,7 @@ const int SQL_SERVER_MAX_TYPE_SIZE = 0; const int SQL_SERVER_MAX_PARAMS = 2100; // increase the maximum message length to accommodate for the long error returned for operand type clash // or for conversion of a long string -const int SQL_MAX_ERROR_MESSAGE_LENGTH = SQL_MAX_MESSAGE_LENGTH * 8; +const int SQL_MAX_ERROR_MESSAGE_LENGTH = SQL_MAX_MESSAGE_LENGTH * 2; // max size of a date time string when converting from a DateTime object to a string const int MAX_DATETIME_STRING_LEN = 256; @@ -1889,14 +1889,20 @@ namespace core { // and return a more helpful message prepended to the ODBC errors if that error occurs if( !SQL_SUCCEEDED( r )) { - SQLCHAR err_msg[SQL_MAX_ERROR_MESSAGE_LENGTH + 1] = {'\0'}; + SQLCHAR err_msg[SQL_MAX_MESSAGE_LENGTH + 1] = {'\0'}; SQLSMALLINT len = 0; SQLRETURN rtemp = ::SQLGetDiagField( stmt->handle_type(), stmt->handle(), 1, SQL_DIAG_MESSAGE_TEXT, - err_msg, SQL_MAX_ERROR_MESSAGE_LENGTH, &len ); + err_msg, SQL_MAX_MESSAGE_LENGTH, &len ); + if (rtemp == SQL_SUCCESS_WITH_INFO && len > SQL_MAX_MESSAGE_LENGTH) { + // if the error message is this long, then it must not be the mars message + // defined as ODBC_CONNECTION_BUSY_ERROR -- so return here and continue the + // regular error handling + return; + } CHECK_SQL_ERROR_OR_WARNING( rtemp, stmt ) { - + throw CoreException(); } diff --git a/source/shared/core_util.cpp b/source/shared/core_util.cpp index 075db3416..58bec157c 100644 --- a/source/shared/core_util.cpp +++ b/source/shared/core_util.cpp @@ -265,10 +265,36 @@ bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_nu // We need to calculate number of characters SQLINTEGER wsqlstate_len = sizeof( wsqlstate ) / sizeof( SQLWCHAR ); SQLLEN sqlstate_len = 0; - convert_string_from_utf16(enc, wsqlstate, wsqlstate_len, (char**)&error->sqlstate, sqlstate_len); + convert_string_from_utf16(enc, wsqlstate, wsqlstate_len, (char**)&error->sqlstate, sqlstate_len); + SQLLEN message_len = 0; - convert_string_from_utf16(enc, wnative_message, wmessage_len, (char**)&error->native_message, message_len); + if (r == SQL_SUCCESS_WITH_INFO && wmessage_len > SQL_MAX_ERROR_MESSAGE_LENGTH) { + // note that wmessage_len is the number of characters required for the error message -- + // create a new buffer big enough for this lengthy error message + sqlsrv_malloc_auto_ptr wnative_message_str; + + SQLSMALLINT expected_len = wmessage_len * sizeof(SQLWCHAR); + SQLSMALLINT returned_len = 0; + + wnative_message_str = reinterpret_cast(sqlsrv_malloc(expected_len)); + memset(wnative_message_str, '\0', expected_len); + + SQLRETURN rtemp = ::SQLGetDiagFieldW(h_type, h, record_number, SQL_DIAG_MESSAGE_TEXT, wnative_message_str, wmessage_len + 1, &returned_len); + if (!SQL_SUCCEEDED(rtemp) || returned_len != expected_len) { + // something went wrong + return false; + } + + convert_string_from_utf16(enc, wnative_message_str, wmessage_len, (char**)&error->native_message, message_len); + } else { + convert_string_from_utf16(enc, wnative_message, wmessage_len, (char**)&error->native_message, message_len); + } + + if (message_len == 0 && error->native_message == NULL) { + // something went wrong + return false; + } break; } From 2685f0a7e3a18eaffa57e18f8bc3c89c0f6428e9 Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Mon, 20 Aug 2018 13:09:34 -0700 Subject: [PATCH 2/2] Fixed a minor issue with a test --- source/shared/core_util.cpp | 2 +- .../sqlsrv/sqlsrv_ae_type_conversion_select.phpt | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/shared/core_util.cpp b/source/shared/core_util.cpp index 58bec157c..04f131ccd 100644 --- a/source/shared/core_util.cpp +++ b/source/shared/core_util.cpp @@ -280,7 +280,7 @@ bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_nu wnative_message_str = reinterpret_cast(sqlsrv_malloc(expected_len)); memset(wnative_message_str, '\0', expected_len); - SQLRETURN rtemp = ::SQLGetDiagFieldW(h_type, h, record_number, SQL_DIAG_MESSAGE_TEXT, wnative_message_str, wmessage_len + 1, &returned_len); + SQLRETURN rtemp = ::SQLGetDiagFieldW(h_type, h, record_number, SQL_DIAG_MESSAGE_TEXT, wnative_message_str, wmessage_len, &returned_len); if (!SQL_SUCCEEDED(rtemp) || returned_len != expected_len) { // something went wrong return false; diff --git a/test/functional/sqlsrv/sqlsrv_ae_type_conversion_select.phpt b/test/functional/sqlsrv/sqlsrv_ae_type_conversion_select.phpt index ba48e9f67..d4ea1c940 100644 --- a/test/functional/sqlsrv/sqlsrv_ae_type_conversion_select.phpt +++ b/test/functional/sqlsrv/sqlsrv_ae_type_conversion_select.phpt @@ -29,8 +29,10 @@ function checkErrors(&$convError) $convError[0][1] != '8114' and $convError[0][1] != '8169') { print_r($convError); - fatalError("Conversion failed with unexpected error message. i=$i, j=$j, v=$v\n"); - } + return false; + } + + return true; } // Build the select queries. We want every combination of types for conversion @@ -202,7 +204,9 @@ for ($v = 0; $v < sizeof($values); ++$v) { if ($stmt == false) { $convError = sqlsrv_errors(); - checkErrors($convError); + if (!checkErrors($convError)) { + fatalError("Conversion failed with unexpected error message. i=$i, j=$j, v=$v\n"); + } if (AE\isDataEncrypted()) { $stmtAE = sqlsrv_query($conn, $selectQueryAE[$i][$j]);