resumed error handling when driver option is set and added test cases
This commit is contained in:
parent
4bb6f4df2e
commit
76e628c963
|
@ -405,6 +405,10 @@ pdo_error PDO_ERRORS[] = {
|
||||||
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
||||||
{ IMSSP, (SQLCHAR*) "Invalid value %1!s! was specified for Driver option.", -79, true }
|
{ 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, {} }
|
{ UINT_MAX, {} }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,7 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
|
|
||||||
build_connection_string_and_set_conn_attr( conn, server, uid, pwd, options_ht, valid_conn_opts, driver, conn_str TSRMLS_CC );
|
build_connection_string_and_set_conn_attr( conn, server, uid, pwd, options_ht, valid_conn_opts, driver, conn_str TSRMLS_CC );
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
if( conn->ce_option.enabled ) {
|
if( conn->ce_option.enabled ) {
|
||||||
// when AE is enabled, must use ODBC driver 17
|
// when AE is enabled, must use ODBC driver 17
|
||||||
if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) {
|
if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) {
|
||||||
|
@ -157,15 +158,19 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if ODBC 17 actually exists, if not, throw an exception
|
||||||
|
CHECK_CUSTOM_ERROR( ! core_search_odbc_driver_unix( ODBC_DRIVER_17 ), conn, SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND ) {
|
||||||
|
throw core::CoreException();
|
||||||
|
}
|
||||||
|
|
||||||
r = core_odbc_connect( conn, conn_str, is_pooled );
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// driver not specified, so connect using ODBC 17
|
// driver not specified, so connect using ODBC 17
|
||||||
#ifndef _WIN32
|
|
||||||
// In non-Windows environment, unixODBC 2.3.4 and unixODBC 2.3.1 return different error states
|
// In non-Windows environment, unixODBC 2.3.4 and unixODBC 2.3.1 return different error states
|
||||||
// If it fails to connect using ODBC 17, it is unreliable to check for a certain sql state error.
|
// If it fails to connect using ODBC 17, it is unreliable to check for a certain sql state error.
|
||||||
// Thus, we will simply throw an exception.
|
// Thus, we will simply throw an exception.
|
||||||
if( core_search_odbc_driver_unix( DRIVER_VERSION::ODBC_DRIVER_17 ) ) {
|
if( core_search_odbc_driver_unix( ODBC_DRIVER_17 ) ) {
|
||||||
conn_str = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION::ODBC_DRIVER_17 ];
|
conn_str = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION::ODBC_DRIVER_17 ];
|
||||||
r = core_odbc_connect( conn, conn_str, is_pooled );
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
}
|
}
|
||||||
|
@ -174,25 +179,19 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
} // else driver_version not unknown
|
||||||
conn_str = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION::ODBC_DRIVER_17 ];
|
}
|
||||||
r = core_odbc_connect( conn, conn_str, is_pooled );
|
else {
|
||||||
|
// column encryption NOT enabled
|
||||||
if(! SQL_SUCCEEDED( r ) ) {
|
if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) {
|
||||||
// sql state IM002 means that the specified ODBC driver is not installed
|
// check if the ODBC driver actually exists, if not, throw an exception
|
||||||
CHECK_CUSTOM_ERROR( core_compare_error_state( conn, r, "IM002" ) , conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch() ) {
|
CHECK_CUSTOM_ERROR( ! core_search_odbc_driver_unix( conn->driver_version ), conn, SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND ) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif // !_WIN32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) {
|
|
||||||
r = core_odbc_connect( conn, conn_str, is_pooled );
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifndef _WIN32
|
|
||||||
DRIVER_VERSION odbc_version = ODBC_DRIVER_UNKNOWN;
|
DRIVER_VERSION odbc_version = ODBC_DRIVER_UNKNOWN;
|
||||||
for( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
for( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
||||||
// skip ODBC 11 in a non-Windows environment -- only available in Red Hat / SUSE (preview)
|
// skip ODBC 11 in a non-Windows environment -- only available in Red Hat / SUSE (preview)
|
||||||
|
@ -210,7 +209,51 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
}
|
}
|
||||||
std::string conn_str_driver = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION( odbc_version ) ];
|
std::string conn_str_driver = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION( odbc_version ) ];
|
||||||
r = core_odbc_connect( conn, conn_str_driver, is_pooled );
|
r = core_odbc_connect( conn, conn_str_driver, is_pooled );
|
||||||
|
} // else driver_version not unknown
|
||||||
|
} // else ce_option enabled
|
||||||
#else
|
#else
|
||||||
|
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() ) {
|
||||||
|
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 ) {
|
||||||
|
throw core::CoreException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// driver not specified, so connect using ODBC 17
|
||||||
|
conn_str = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION::ODBC_DRIVER_17 ];
|
||||||
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
|
|
||||||
|
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() ) {
|
||||||
|
throw core::CoreException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// column encryption NOT enabled
|
||||||
|
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 {
|
||||||
for( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
for( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
||||||
std::string conn_str_driver = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION(i) ];
|
std::string conn_str_driver = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION(i) ];
|
||||||
r = core_odbc_connect( conn, conn_str_driver, is_pooled );
|
r = core_odbc_connect( conn, conn_str_driver, is_pooled );
|
||||||
|
@ -231,9 +274,9 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // for
|
} // for
|
||||||
#endif // !_WIN32
|
|
||||||
}
|
}
|
||||||
} // else ce_option enabled
|
} // else ce_option enabled
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
CHECK_SQL_ERROR( r, conn ) {
|
CHECK_SQL_ERROR( r, conn ) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
|
|
|
@ -1644,6 +1644,7 @@ enum SQLSRV_ERROR_CODES {
|
||||||
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
|
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
|
||||||
SQLSRV_ERROR_AE_DRIVER_REQUIRED,
|
SQLSRV_ERROR_AE_DRIVER_REQUIRED,
|
||||||
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
||||||
|
SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND,
|
||||||
SQLSRV_ERROR_ZEND_HASH,
|
SQLSRV_ERROR_ZEND_HASH,
|
||||||
SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE,
|
SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE,
|
||||||
SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE,
|
SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE,
|
||||||
|
|
|
@ -404,6 +404,10 @@ ss_error SS_ERRORS[] = {
|
||||||
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
||||||
{ IMSSP, (SQLCHAR*) "Invalid value %1!s! was specified for Driver option.", -106, true }
|
{ 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
|
// terminate the list of errors/warnings
|
||||||
{ UINT_MAX, {} }
|
{ UINT_MAX, {} }
|
||||||
};
|
};
|
||||||
|
|
|
@ -124,36 +124,61 @@ function test_invalid_values()
|
||||||
|
|
||||||
function test_encrypted_with_odbc()
|
function test_encrypted_with_odbc()
|
||||||
{
|
{
|
||||||
global $msodbcsql_maj;
|
global $msodbcsql_maj, $server, $uid, $pwd;
|
||||||
|
|
||||||
$value = "ODBC Driver 13 for SQL Server";
|
$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.";
|
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
||||||
|
|
||||||
connect_verify_output( $connectionOptions, $expected );
|
connect_verify_output( $connectionOptions, $expected );
|
||||||
|
|
||||||
|
// TODO: the following block will change once ODBC 17 is officially released
|
||||||
|
$value = "ODBC Driver 17 for SQL Server";
|
||||||
|
$connectionOptions = "Driver = $value; ColumnEncryption = Enabled;";
|
||||||
|
|
||||||
|
$success = "Successfully connected with column encryption.";
|
||||||
|
$expected = "The specified ODBC Driver is not found.";
|
||||||
|
$message = $success;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$conn = new PDO( "sqlsrv:server = $server ; $connectionOptions", $uid, $pwd );
|
||||||
|
}
|
||||||
|
catch( PDOException $e )
|
||||||
|
{
|
||||||
|
$message = $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $msodbcsql_maj == 17 )
|
||||||
|
{
|
||||||
|
// this indicates that OCBC 17 is the only available driver
|
||||||
|
if ( strcmp( $message, $success ) )
|
||||||
|
print_r( $message );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OCBC 17 might or might not exist
|
||||||
|
if ( strcmp( $message, $success ) )
|
||||||
|
{
|
||||||
|
if ( strpos( $message, $expected ) === false )
|
||||||
|
print_r( $message );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_wrong_odbc()
|
function test_wrong_odbc()
|
||||||
{
|
{
|
||||||
global $msodbcsql_maj, $server, $uid, $pwd;
|
global $msodbcsql_maj;
|
||||||
|
|
||||||
|
// TODO: this will change once ODBC 17 is officially released
|
||||||
$value = "ODBC Driver 17 for SQL Server";
|
$value = "ODBC Driver 17 for SQL Server";
|
||||||
if ( $msodbcsql_maj == 17 || $msodbcsql_maj < 13 )
|
if ( $msodbcsql_maj == 17 || $msodbcsql_maj < 13 )
|
||||||
{
|
{
|
||||||
$value = "ODBC Driver 13 for SQL Server";
|
$value = "ODBC Driver 13 for SQL Server";
|
||||||
}
|
}
|
||||||
$connectionOptions = "Driver = $value;";
|
$connectionOptions = "Driver = $value;";
|
||||||
|
$expected = "The specified ODBC Driver is not found.";
|
||||||
|
|
||||||
try
|
connect_verify_output( $connectionOptions, $expected );
|
||||||
{
|
|
||||||
$conn = new PDO( "sqlsrv:server = $server ; $connectionOptions", $uid, $pwd );
|
|
||||||
|
|
||||||
echo "Should have caused an exception connecting with $value!\n";
|
|
||||||
}
|
|
||||||
catch( PDOException $e )
|
|
||||||
{
|
|
||||||
// do nothing here because this is expected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -119,10 +119,41 @@ function test_encrypted_with_odbc( $msodbcsql_maj, $server, $connectionOptions )
|
||||||
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
||||||
|
|
||||||
connect_verify_output( $server, $connectionOptions, $expected );
|
connect_verify_output( $server, $connectionOptions, $expected );
|
||||||
|
|
||||||
|
// TODO: the following block will change once ODBC 17 is officially released
|
||||||
|
$value = "ODBC Driver 17 for SQL Server";
|
||||||
|
$connectionOptions['Driver']=$value;
|
||||||
|
$connectionOptions['ColumnEncryption']='Enabled';
|
||||||
|
|
||||||
|
$success = "Successfully connected with column encryption.";
|
||||||
|
$expected = "The specified ODBC Driver is not found.";
|
||||||
|
$message = $success;
|
||||||
|
|
||||||
|
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||||
|
if ($conn === false)
|
||||||
|
$message = sqlsrv_errors($conn)[0]['message'];
|
||||||
|
|
||||||
|
if ( $msodbcsql_maj == 17 )
|
||||||
|
{
|
||||||
|
// this indicates that OCBC 17 is the only available driver
|
||||||
|
if ( strcmp( $message, $success ) )
|
||||||
|
print_r( $message );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OCBC 17 might or might not exist
|
||||||
|
if ( strcmp( $message, $success ) )
|
||||||
|
{
|
||||||
|
if ( strpos( $message, $expected ) === false )
|
||||||
|
print_r( $message );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_wrong_odbc( $msodbcsql_maj, $server, $connectionOptions )
|
function test_wrong_odbc( $msodbcsql_maj, $server, $connectionOptions )
|
||||||
{
|
{
|
||||||
|
// TODO: this will change once ODBC 17 is officially released
|
||||||
$value = "ODBC Driver 17 for SQL Server";
|
$value = "ODBC Driver 17 for SQL Server";
|
||||||
if ( $msodbcsql_maj == 17 || $msodbcsql_maj < 13 )
|
if ( $msodbcsql_maj == 17 || $msodbcsql_maj < 13 )
|
||||||
{
|
{
|
||||||
|
@ -130,12 +161,9 @@ function test_wrong_odbc( $msodbcsql_maj, $server, $connectionOptions )
|
||||||
}
|
}
|
||||||
|
|
||||||
$connectionOptions['Driver']=$value;
|
$connectionOptions['Driver']=$value;
|
||||||
|
$expected = "The specified ODBC Driver is not found.";
|
||||||
|
|
||||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
connect_verify_output( $server, $connectionOptions, $expected );
|
||||||
if ($conn != false)
|
|
||||||
{
|
|
||||||
echo "Expected errors connecting with $value!\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
Loading…
Reference in a new issue