also checked if ODBC driver is set when AE is enabled
This commit is contained in:
parent
7a10c1ce59
commit
256e712072
|
@ -398,7 +398,7 @@ pdo_error PDO_ERRORS[] = {
|
||||||
{ IMSSP, (SQLCHAR*) "Invalid value for loading a custom keystore provider.", -77, false}
|
{ IMSSP, (SQLCHAR*) "Invalid value for loading a custom keystore provider.", -77, false}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_AE_DRIVER_NOT_INSTALLED,
|
SQLSRV_ERROR_AE_DRIVER_REQUIRED,
|
||||||
{ IMSSP, (SQLCHAR*) "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.", -78, false }
|
{ IMSSP, (SQLCHAR*) "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.", -78, false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#endif
|
|
||||||
#include <odbcinst.h>
|
#include <odbcinst.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// *** internal variables and constants ***
|
// *** internal variables and constants ***
|
||||||
|
|
||||||
|
@ -150,67 +150,89 @@ 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 );
|
||||||
|
|
||||||
bool is_missing_driver = true;
|
if( conn->ce_option.enabled ) {
|
||||||
|
// when AE is enabled, must use ODBC driver 17
|
||||||
if ( conn->is_driver_set ) {
|
if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) {
|
||||||
r = core_odbc_connect( conn, conn_str, is_missing_driver, is_pooled );
|
CHECK_CUSTOM_ERROR( conn->driver_version != ODBC_DRIVER_17, conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch()) {
|
||||||
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
else if ( conn->ce_option.enabled ) {
|
|
||||||
#ifndef _WIN32
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
// In non-Windows environment, because different unixODBC versions return different error states,
|
|
||||||
// if it fails to connect it is unreliable to check for a certain sql state error. Thus,
|
|
||||||
// we will ignore the returned value of 'is_missing_driver' and simply throw an exception.
|
|
||||||
if( core_search_odbc_driver( 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_missing_driver, is_pooled );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_CUSTOM_ERROR( true, conn, SQLSRV_ERROR_AE_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
// 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
|
||||||
|
// 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.
|
||||||
|
if( core_search_odbc_driver_unix( 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 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CHECK_CUSTOM_ERROR( true, conn, SQLSRV_ERROR_AE_DRIVER_REQUIRED, get_processor_arch()) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
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_missing_driver, is_pooled );
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( is_missing_driver, conn, SQLSRV_ERROR_AE_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
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();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( conn->driver_version != ODBC_DRIVER_UNKNOWN ) {
|
||||||
|
r = core_odbc_connect( conn, conn_str, is_pooled );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
is_missing_driver = true;
|
DRIVER_VERSION odbc_version = ODBC_DRIVER_UNKNOWN;
|
||||||
for ( std::size_t i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
for ( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
||||||
if (i == DRIVER_VERSION::ODBC_DRIVER_11) // skip ODBC 11 in non-Windows environment
|
// skip ODBC 11 in a non-Windows environment -- only available in Red Hat / SUSE (preview)
|
||||||
|
// https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server#microsoft-odbc-driver-11-for-sql-server-on-linux
|
||||||
|
if (i == DRIVER_VERSION::ODBC_DRIVER_11)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if( core_search_odbc_driver( i ) ) {
|
if( core_search_odbc_driver_unix( DRIVER_VERSION( i ) ) ) {
|
||||||
std::string conn_str_driver = conn_str + CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION( i ) ];
|
odbc_version = DRIVER_VERSION( i );
|
||||||
r = core_odbc_connect( conn, conn_str_driver, is_missing_driver, is_pooled );
|
|
||||||
// simply check the connection succeeded or not and ignore the returned value of 'is_missing_driver'
|
|
||||||
if ( SQL_SUCCEEDED( r ) ) {
|
|
||||||
is_missing_driver = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
CHECK_CUSTOM_ERROR( odbc_version == ODBC_DRIVER_UNKNOWN, conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
||||||
CHECK_CUSTOM_ERROR( is_missing_driver, conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
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 );
|
||||||
#else
|
#else
|
||||||
for ( std::size_t i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
for ( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
||||||
is_missing_driver = false;
|
|
||||||
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_missing_driver, is_pooled );
|
r = core_odbc_connect( conn, conn_str_driver, is_pooled );
|
||||||
CHECK_CUSTOM_ERROR( is_missing_driver && ( i == DRIVER_VERSION::LAST ), conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
|
||||||
|
if( SQL_SUCCEEDED( r ) ) {
|
||||||
|
// successfully connected!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(! core_compare_error_state( conn, r, "IM002" ) ) {
|
||||||
|
// sql state IM002 means that the specified ODBC driver is not installed
|
||||||
|
// something went wrong other than missing the ODBC driver
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( i == DRIVER_VERSION::LAST ) {
|
||||||
|
// failed to connect even using the last valid ODBC driver
|
||||||
|
CHECK_CUSTOM_ERROR( true, conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
if ( !is_missing_driver) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} // for
|
} // for
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
}
|
||||||
} // else ce_option enabled
|
} // else ce_option enabled
|
||||||
|
|
||||||
CHECK_SQL_ERROR( r, conn ) {
|
CHECK_SQL_ERROR( r, conn ) {
|
||||||
|
@ -268,14 +290,37 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
return return_conn;
|
return return_conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// core_search_odbc_driver
|
// core_compare_error_state
|
||||||
|
// This method compares the error state to the one specified
|
||||||
|
// Parameters:
|
||||||
|
// conn - the connection structure on which we establish the connection
|
||||||
|
// rc - ODBC return code
|
||||||
|
// Return - a boolean flag that indicates if the error states are the same
|
||||||
|
|
||||||
|
bool core_compare_error_state( _In_ sqlsrv_conn* conn, _In_ SQLRETURN rc, _In_ const char* error_state )
|
||||||
|
{
|
||||||
|
if( SQL_SUCCEEDED( rc ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
|
||||||
|
SQLSMALLINT len;
|
||||||
|
SQLRETURN sr = SQLGetDiagField( SQL_HANDLE_DBC, conn->handle(), 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len );
|
||||||
|
|
||||||
|
bool same = false;
|
||||||
|
if( SQL_SUCCEEDED(sr) && ! strcmp(error_state, reinterpret_cast<char*>( state ) ) )
|
||||||
|
same = true;
|
||||||
|
|
||||||
|
return same;
|
||||||
|
}
|
||||||
|
|
||||||
|
// core_search_odbc_driver_unix
|
||||||
// This method is meant to be used in a non-Windows environment,
|
// This method is meant to be used in a non-Windows environment,
|
||||||
// searching for a particular ODBC driver name in the odbcinst.ini file
|
// searching for a particular ODBC driver name in the odbcinst.ini file
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// driver_version - a valid value in enum DRIVER_VERSION
|
// driver_version - a valid value in enum DRIVER_VERSION
|
||||||
// Return - a boolean flag that indicates if the specified driver version is found or not
|
// Return - a boolean flag that indicates if the specified driver version is found or not
|
||||||
|
|
||||||
bool core_search_odbc_driver( _In_ std::size_t driver_version )
|
bool core_search_odbc_driver_unix( _In_ DRIVER_VERSION driver_version )
|
||||||
{
|
{
|
||||||
char szBuf[DEFAULT_CONN_STR_LEN+1]; // use an arbitrary large enough buffer size
|
char szBuf[DEFAULT_CONN_STR_LEN+1]; // use an arbitrary large enough buffer size
|
||||||
WORD cbBufMax = DEFAULT_CONN_STR_LEN;
|
WORD cbBufMax = DEFAULT_CONN_STR_LEN;
|
||||||
|
@ -319,11 +364,10 @@ bool core_search_odbc_driver( _In_ std::size_t driver_version )
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// conn - The connection structure on which we establish the connection
|
// conn - The connection structure on which we establish the connection
|
||||||
// conn_str - Connection string
|
// conn_str - Connection string
|
||||||
// is_missing_driver - indicates whether odbc driver is installed on client machine
|
|
||||||
// is_pooled - indicate whether it is a pooled connection
|
// is_pooled - indicate whether it is a pooled connection
|
||||||
// Return - SQLRETURN status returned by SQLDriverConnect
|
// Return - SQLRETURN status returned by SQLDriverConnect
|
||||||
|
|
||||||
SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str, _Inout_ bool& is_missing_driver, _In_ bool is_pooled )
|
SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str, _In_ bool is_pooled )
|
||||||
{
|
{
|
||||||
SQLRETURN r = SQL_SUCCESS;
|
SQLRETURN r = SQL_SUCCESS;
|
||||||
sqlsrv_malloc_auto_ptr<SQLWCHAR> wconn_string;
|
sqlsrv_malloc_auto_ptr<SQLWCHAR> wconn_string;
|
||||||
|
@ -358,14 +402,6 @@ SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& con
|
||||||
memset( wconn_string, 0, wconn_len * sizeof( SQLWCHAR )); // wconn_len is the number of characters, not bytes
|
memset( wconn_string, 0, wconn_len * sizeof( SQLWCHAR )); // wconn_len is the number of characters, not bytes
|
||||||
conn_str.clear();
|
conn_str.clear();
|
||||||
|
|
||||||
if (!SQL_SUCCEEDED(r)) {
|
|
||||||
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
|
|
||||||
SQLSMALLINT len;
|
|
||||||
SQLRETURN sr = SQLGetDiagField( SQL_HANDLE_DBC, conn->handle(), 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len );
|
|
||||||
// sql state IM002, means that the specified ODBC driver is not installed
|
|
||||||
// might return IM003 in ODBC 17 (an issue that will be fixed)
|
|
||||||
is_missing_driver = ( SQL_SUCCEEDED(sr) && state[0] == 'I' && state[1] == 'M' && state[2] == '0' && state[3] == '0' && (state[4] == '2' || state[4] == '3'));
|
|
||||||
}
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -989,10 +1025,20 @@ void driver_set_func::func( _In_ connection_option const* option, _In_ zval* val
|
||||||
std::string driver_option( "" );
|
std::string driver_option( "" );
|
||||||
common_conn_str_append_func( option->odbc_name, val_str, val_len, driver_option TSRMLS_CC );
|
common_conn_str_append_func( option->odbc_name, val_str, val_len, driver_option TSRMLS_CC );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( std::find( CONNECTION_STRING_DRIVER_NAME.begin(), CONNECTION_STRING_DRIVER_NAME.end(), driver_option) == CONNECTION_STRING_DRIVER_NAME.end(), conn, SQLSRV_ERROR_CONNECT_INVALID_DRIVER, val_str){
|
conn->driver_version = ODBC_DRIVER_UNKNOWN;
|
||||||
|
for ( short i = DRIVER_VERSION::FIRST; i <= DRIVER_VERSION::LAST; ++i ) {
|
||||||
|
std::string driver_name = CONNECTION_STRING_DRIVER_NAME[ DRIVER_VERSION( i ) ];
|
||||||
|
|
||||||
|
if (! driver_name.compare( driver_option ) ) {
|
||||||
|
conn->driver_version = DRIVER_VERSION( i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_CUSTOM_ERROR( conn->driver_version == ODBC_DRIVER_UNKNOWN, conn, SQLSRV_ERROR_CONNECT_INVALID_DRIVER, val_str){
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
conn->is_driver_set = true;
|
|
||||||
conn_str += driver_option;
|
conn_str += driver_option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1039,7 +1039,8 @@ enum SERVER_VERSION {
|
||||||
|
|
||||||
// supported driver versions.
|
// supported driver versions.
|
||||||
// the latest RTWed ODBC is the first one
|
// the latest RTWed ODBC is the first one
|
||||||
enum DRIVER_VERSION : std::size_t{
|
enum DRIVER_VERSION {
|
||||||
|
ODBC_DRIVER_UNKNOWN = -1,
|
||||||
FIRST = 0,
|
FIRST = 0,
|
||||||
ODBC_DRIVER_13 = FIRST,
|
ODBC_DRIVER_13 = FIRST,
|
||||||
ODBC_DRIVER_11 = 1,
|
ODBC_DRIVER_11 = 1,
|
||||||
|
@ -1073,14 +1074,14 @@ struct sqlsrv_conn : public sqlsrv_context {
|
||||||
SERVER_VERSION server_version; // version of the server that we're connected to
|
SERVER_VERSION server_version; // version of the server that we're connected to
|
||||||
|
|
||||||
col_encryption_option ce_option; // holds the details of what are required to enable column encryption
|
col_encryption_option ce_option; // holds the details of what are required to enable column encryption
|
||||||
bool is_driver_set;
|
DRIVER_VERSION driver_version; // version of ODBC driver
|
||||||
|
|
||||||
// initialize with default values
|
// initialize with default values
|
||||||
sqlsrv_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_opt_ void* drv, _In_ SQLSRV_ENCODING encoding TSRMLS_DC ) :
|
sqlsrv_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_opt_ void* drv, _In_ SQLSRV_ENCODING encoding TSRMLS_DC ) :
|
||||||
sqlsrv_context( h, SQL_HANDLE_DBC, e, drv, encoding )
|
sqlsrv_context( h, SQL_HANDLE_DBC, e, drv, encoding )
|
||||||
{
|
{
|
||||||
server_version = SERVER_VERSION_UNKNOWN;
|
server_version = SERVER_VERSION_UNKNOWN;
|
||||||
is_driver_set = false;
|
driver_version = ODBC_DRIVER_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sqlsrv_conn has no destructor since its allocated using placement new, which requires that the destructor be
|
// sqlsrv_conn has no destructor since its allocated using placement new, which requires that the destructor be
|
||||||
|
@ -1235,7 +1236,7 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
_Inout_z_ const char* server, _Inout_opt_z_ const char* uid, _Inout_opt_z_ const char* pwd,
|
_Inout_z_ const char* server, _Inout_opt_z_ const char* uid, _Inout_opt_z_ const char* pwd,
|
||||||
_Inout_opt_ HashTable* options_ht, _In_ error_callback err, _In_ const connection_option valid_conn_opts[],
|
_Inout_opt_ HashTable* options_ht, _In_ error_callback err, _In_ const connection_option valid_conn_opts[],
|
||||||
_In_ void* driver, _In_z_ const char* driver_func TSRMLS_DC );
|
_In_ void* driver, _In_z_ const char* driver_func TSRMLS_DC );
|
||||||
SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str, _Inout_ bool& is_missing_driver, _In_ bool is_pooled );
|
SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str, _In_ bool is_pooled );
|
||||||
void core_sqlsrv_close( _Inout_opt_ sqlsrv_conn* conn TSRMLS_DC );
|
void core_sqlsrv_close( _Inout_opt_ sqlsrv_conn* conn TSRMLS_DC );
|
||||||
void core_sqlsrv_prepare( _Inout_ sqlsrv_stmt* stmt, _In_reads_bytes_(sql_len) const char* sql, _In_ SQLLEN sql_len TSRMLS_DC );
|
void core_sqlsrv_prepare( _Inout_ sqlsrv_stmt* stmt, _In_reads_bytes_(sql_len) const char* sql, _In_ SQLLEN sql_len TSRMLS_DC );
|
||||||
void core_sqlsrv_begin_transaction( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
|
void core_sqlsrv_begin_transaction( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
|
||||||
|
@ -1247,7 +1248,8 @@ void core_sqlsrv_get_client_info( _Inout_ sqlsrv_conn* conn, _Out_ zval *client_
|
||||||
bool core_is_conn_opt_value_escaped( _Inout_ const char* value, _Inout_ size_t value_len );
|
bool core_is_conn_opt_value_escaped( _Inout_ const char* value, _Inout_ size_t value_len );
|
||||||
size_t core_str_zval_is_true( _Inout_ zval* str_zval );
|
size_t core_str_zval_is_true( _Inout_ zval* str_zval );
|
||||||
bool core_is_authentication_option_valid( _In_z_ const char* value, _In_ size_t value_len );
|
bool core_is_authentication_option_valid( _In_z_ const char* value, _In_ size_t value_len );
|
||||||
bool core_search_odbc_driver( _In_ std::size_t driver_version );
|
bool core_search_odbc_driver_unix( _In_ DRIVER_VERSION driver_version );
|
||||||
|
bool core_compare_error_state( _In_ sqlsrv_conn* conn, _In_ SQLRETURN r, _In_ const char* error_state );
|
||||||
|
|
||||||
//*********************************************************************************************************************************
|
//*********************************************************************************************************************************
|
||||||
// Statement
|
// Statement
|
||||||
|
@ -1640,7 +1642,7 @@ enum SQLSRV_ERROR_CODES {
|
||||||
|
|
||||||
SQLSRV_ERROR_ODBC,
|
SQLSRV_ERROR_ODBC,
|
||||||
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
|
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
|
||||||
SQLSRV_ERROR_AE_DRIVER_NOT_INSTALLED,
|
SQLSRV_ERROR_AE_DRIVER_REQUIRED,
|
||||||
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
SQLSRV_ERROR_CONNECT_INVALID_DRIVER,
|
||||||
SQLSRV_ERROR_ZEND_HASH,
|
SQLSRV_ERROR_ZEND_HASH,
|
||||||
SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE,
|
SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE,
|
||||||
|
|
|
@ -397,7 +397,7 @@ ss_error SS_ERRORS[] = {
|
||||||
{ IMSSP, (SQLCHAR*) "Invalid value for loading a custom keystore provider.", -104, false}
|
{ IMSSP, (SQLCHAR*) "Invalid value for loading a custom keystore provider.", -104, false}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_AE_DRIVER_NOT_INSTALLED,
|
SQLSRV_ERROR_AE_DRIVER_REQUIRED,
|
||||||
{ IMSSP, (SQLCHAR*) "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.", -105, false }
|
{ IMSSP, (SQLCHAR*) "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.", -105, false }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue