From 0cbc00384c16c758239447a5eb708e28fb6c5c7b Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Wed, 27 Sep 2017 15:16:17 -0700 Subject: [PATCH] added more error checking when driver option is set --- source/pdo_sqlsrv/pdo_util.cpp | 4 ++++ source/shared/core_conn.cpp | 17 +++++++++++++++-- source/shared/core_sqlsrv.h | 1 + source/sqlsrv/util.cpp | 4 ++++ .../pdo_sqlsrv/pdo_connect_driver.phpt | 19 +++++++++++++++---- .../sqlsrv/sqlsrv_connect_driver.phpt | 18 +++++++++++++++--- 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/source/pdo_sqlsrv/pdo_util.cpp b/source/pdo_sqlsrv/pdo_util.cpp index 2c0d43e4..63cad9d2 100644 --- a/source/pdo_sqlsrv/pdo_util.cpp +++ b/source/pdo_sqlsrv/pdo_util.cpp @@ -405,6 +405,10 @@ pdo_error PDO_ERRORS[] = { SQLSRV_ERROR_CONNECT_INVALID_DRIVER, { IMSSP, (SQLCHAR*) "Invalid value %1!s! was specified for Driver option.", -79, true } }, + { + SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND, + { IMSSP, (SQLCHAR*) "The specified ODBC Driver is not found.", -80, false } + }, { UINT_MAX, {} } }; diff --git a/source/shared/core_conn.cpp b/source/shared/core_conn.cpp index 0875a102..ca0d2f5a 100644 --- a/source/shared/core_conn.cpp +++ b/source/shared/core_conn.cpp @@ -153,11 +153,17 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont if( conn->ce_option.enabled ) { // when AE is enabled, must use ODBC driver 17 if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) { - CHECK_CUSTOM_ERROR( conn->driver_version != ODBC_DRIVER_17, conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch()) { + CHECK_CUSTOM_ERROR( conn->driver_version != ODBC_DRIVER_17, conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch() ) { throw core::CoreException(); } r = core_odbc_connect( conn, conn_str, is_pooled ); + if( ! SQL_SUCCEEDED( r ) && core_compare_error_state( conn, r, "IM002" ) ) { + // sql state IM002 means that the specified ODBC driver is not installed + CHECK_CUSTOM_ERROR( true, conn, SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND, CONNECTION_STRING_DRIVER_NAME[ conn->driver_version ].c_str() ) { + throw core::CoreException(); + } + } } else { // driver not specified, so connect using ODBC 17 @@ -180,7 +186,7 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont if(! SQL_SUCCEEDED( r ) ) { // sql state IM002 means that the specified ODBC driver is not installed - CHECK_CUSTOM_ERROR( core_compare_error_state( conn, r, "IM002" ) , conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch()) { + CHECK_CUSTOM_ERROR( core_compare_error_state( conn, r, "IM002" ) , conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch() ) { throw core::CoreException(); } } @@ -190,6 +196,13 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont else { if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) { r = core_odbc_connect( conn, conn_str, is_pooled ); + + if( ! SQL_SUCCEEDED( r ) && core_compare_error_state( conn, r, "IM002" ) ) { + // sql state IM002 means that the specified ODBC driver is not installed + CHECK_CUSTOM_ERROR( true, conn, SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND, CONNECTION_STRING_DRIVER_NAME[ conn->driver_version ].c_str() ) { + throw core::CoreException(); + } + } } else { #ifndef _WIN32 diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h index 1b6dda41..7e8c79c4 100644 --- a/source/shared/core_sqlsrv.h +++ b/source/shared/core_sqlsrv.h @@ -1644,6 +1644,7 @@ enum SQLSRV_ERROR_CODES { SQLSRV_ERROR_DRIVER_NOT_INSTALLED, SQLSRV_ERROR_AE_DRIVER_REQUIRED, SQLSRV_ERROR_CONNECT_INVALID_DRIVER, + SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND, SQLSRV_ERROR_ZEND_HASH, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, diff --git a/source/sqlsrv/util.cpp b/source/sqlsrv/util.cpp index 0e527d0c..d282c9c0 100644 --- a/source/sqlsrv/util.cpp +++ b/source/sqlsrv/util.cpp @@ -404,6 +404,10 @@ ss_error SS_ERRORS[] = { SQLSRV_ERROR_CONNECT_INVALID_DRIVER, { IMSSP, (SQLCHAR*) "Invalid value %1!s! was specified for Driver option.", -106, true } }, + { + SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND, + { IMSSP, (SQLCHAR*) "The specified ODBC Driver is not found.", -107, false } + }, // terminate the list of errors/warnings { UINT_MAX, {} } }; diff --git a/test/functional/pdo_sqlsrv/pdo_connect_driver.phpt b/test/functional/pdo_sqlsrv/pdo_connect_driver.phpt index d000c101..6ce18fe3 100644 --- a/test/functional/pdo_sqlsrv/pdo_connect_driver.phpt +++ b/test/functional/pdo_sqlsrv/pdo_connect_driver.phpt @@ -24,7 +24,7 @@ $conn = null; // start test test_valid_values(); test_invalid_values(); -test_encrypted_with_odbc13(); +test_encrypted_with_odbc(); echo "Done"; // end test @@ -121,14 +121,25 @@ function test_invalid_values() connect_verify_output( $connectionOptions, $expected ); } -function test_encrypted_with_odbc13() +function test_encrypted_with_odbc() { + global $msodbcsql_maj; + $value = "ODBC Driver 13 for SQL Server"; - $connectionOptions = "Driver = $value; ColumnEncryption = Enabled;"; - + $connectionOptions = "Driver = $value; ColumnEncryption = Enabled;"; $expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server."; connect_verify_output( $connectionOptions, $expected ); + + $value = "ODBC Driver 11 for SQL Server"; + if ( $msodbcsql_maj == 17 || $msodbcsql_maj < 13 ) + { + $value = "ODBC Driver 13 for SQL Server"; + } + $connectionOptions = "Driver = $value;"; + $expected = "The specified ODBC Driver is not found"; + + connect_verify_output( $connectionOptions, $expected ); } ?> diff --git a/test/functional/sqlsrv/sqlsrv_connect_driver.phpt b/test/functional/sqlsrv/sqlsrv_connect_driver.phpt index 3f9daf7a..2c5db164 100644 --- a/test/functional/sqlsrv/sqlsrv_connect_driver.phpt +++ b/test/functional/sqlsrv/sqlsrv_connect_driver.phpt @@ -7,7 +7,7 @@ Test new connection keyword Driver with valid and invalid values sqlsrv_configure( 'WarningsReturnAsErrors', 0 ); require( 'MsSetup.inc' ); -$connectionOptions = array("Database"=>$database,"UID"=>$userName, "PWD"=>$userPassword); +$connectionOptions = array("Database"=>$database, "UID"=>$userName, "PWD"=>$userPassword); $conn = sqlsrv_connect($server, $connectionOptions); if ($conn === false) { @@ -20,7 +20,7 @@ sqlsrv_close($conn); // start test test_valid_values( $msodbcsql_maj, $server, $connectionOptions ); test_invalid_values( $msodbcsql_maj, $server, $connectionOptions ); -test_encrypted_with_odbc13( $server, $connectionOptions ); +test_encrypted_with_odbc( $msodbcsql_maj, $server, $connectionOptions ); echo "Done"; // end test @@ -109,7 +109,7 @@ function test_invalid_values( $msodbcsql_maj, $server, $connectionOptions ) connect_verify_output( $server, $connectionOptions, $expected ); } -function test_encrypted_with_odbc13( $server, $connectionOptions ) +function test_encrypted_with_odbc( $msodbcsql_maj, $server, $connectionOptions ) { $value = "ODBC Driver 13 for SQL Server"; $connectionOptions['Driver']=$value; @@ -118,6 +118,18 @@ function test_encrypted_with_odbc13( $server, $connectionOptions ) $expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server."; connect_verify_output( $server, $connectionOptions, $expected ); + + $value = "ODBC Driver 11 for SQL Server"; + if ( $msodbcsql_maj == 17 || $msodbcsql_maj < 13 ) + { + $value = "ODBC Driver 13 for SQL Server"; + } + + $connectionOptions['Driver']=$value; + $connectionOptions['ColumnEncryption']='Disabled'; + $expected = "The specified ODBC Driver is not found"; + + connect_verify_output( $server, $connectionOptions, $expected ); } ?>