updated to ODBC 13.1

This commit is contained in:
yitam 2017-05-05 17:17:52 -07:00
parent 7d8004bf5a
commit 28fc51df3d
2 changed files with 125 additions and 125 deletions

View file

@ -115,7 +115,7 @@ install:
#- echo Downloading PHP deps [%PHP_DEPSVER%] #- echo Downloading PHP deps [%PHP_DEPSVER%]
#- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/php-sdk/deps-' + ${env:PHP_DEPSVER} + '-vc' + ${env:PHP_VC} + '-' + ${env:BUILD_PLATFORM} + '.7z', ${env:APPVEYOR_BUILD_FOLDER} + '\..\deps.7z') #- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/php-sdk/deps-' + ${env:PHP_DEPSVER} + '-vc' + ${env:PHP_VC} + '-' + ${env:BUILD_PLATFORM} + '.7z', ${env:APPVEYOR_BUILD_FOLDER} + '\..\deps.7z')
- echo Downloading MSODBCSQL 13 - echo Downloading MSODBCSQL 13
- ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/1/E/7/1E7B1181-3974-4B29-9A47-CC857B271AA2/English/' + ${env:BUILD_PLATFORM} + '/msodbcsql.msi', 'msodbcsql.msi') - ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/' + ${env:BUILD_PLATFORM} + '/msodbcsql.msi', 'msodbcsql.msi')
- ps: msiexec /i msodbcsql.msi /quiet /qn /norestart - ps: msiexec /i msodbcsql.msi /quiet /qn /norestart
- cd .. - cd ..
- cd - cd

View file

@ -54,23 +54,23 @@ struct conn_char_set_func {
const char* encoding = Z_STRVAL_P( value ); const char* encoding = Z_STRVAL_P( value );
size_t encoding_len = Z_STRLEN_P( value ); size_t encoding_len = Z_STRLEN_P( value );
zend_ulong index = -1; zend_ulong index = -1;
zend_string* key = NULL; zend_string* key = NULL;
void* ss_encoding_temp = NULL; void* ss_encoding_temp = NULL;
ZEND_HASH_FOREACH_KEY_PTR( g_ss_encodings_ht, index, key, ss_encoding_temp ) { ZEND_HASH_FOREACH_KEY_PTR( g_ss_encodings_ht, index, key, ss_encoding_temp ) {
sqlsrv_encoding* ss_encoding = reinterpret_cast<sqlsrv_encoding*>( ss_encoding_temp ); sqlsrv_encoding* ss_encoding = reinterpret_cast<sqlsrv_encoding*>( ss_encoding_temp );
ss_encoding_temp = NULL; ss_encoding_temp = NULL;
if (!strnicmp( encoding, ss_encoding->iana, encoding_len )) { if (!strnicmp( encoding, ss_encoding->iana, encoding_len )) {
if ( ss_encoding->not_for_connection ) { if ( ss_encoding->not_for_connection ) {
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding ); THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
} }
conn->set_encoding( static_cast<SQLSRV_ENCODING>(ss_encoding->code_page )); conn->set_encoding( static_cast<SQLSRV_ENCODING>(ss_encoding->code_page ));
return; return;
} }
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding ); THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
} }
@ -134,8 +134,8 @@ struct bool_conn_attr_func {
static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC ) static void func( connection_option const* /*option*/, zval* value, sqlsrv_conn* conn, std::string& /*conn_str*/ TSRMLS_DC )
{ {
try { try {
core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)), core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)),
SQL_IS_UINTEGER TSRMLS_CC); SQL_IS_UINTEGER TSRMLS_CC);
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
@ -221,25 +221,25 @@ const stmt_option SS_STMT_OPTS[] = {
SSStmtOptionNames::QUERY_TIMEOUT, SSStmtOptionNames::QUERY_TIMEOUT,
sizeof( SSStmtOptionNames::QUERY_TIMEOUT ), sizeof( SSStmtOptionNames::QUERY_TIMEOUT ),
SQLSRV_STMT_OPTION_QUERY_TIMEOUT, SQLSRV_STMT_OPTION_QUERY_TIMEOUT,
std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout ) std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout )
}, },
{ {
SSStmtOptionNames::SEND_STREAMS_AT_EXEC, SSStmtOptionNames::SEND_STREAMS_AT_EXEC,
sizeof( SSStmtOptionNames::SEND_STREAMS_AT_EXEC ), sizeof( SSStmtOptionNames::SEND_STREAMS_AT_EXEC ),
SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC, SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC,
std::unique_ptr<stmt_option_send_at_exec>( new stmt_option_send_at_exec ) std::unique_ptr<stmt_option_send_at_exec>( new stmt_option_send_at_exec )
}, },
{ {
SSStmtOptionNames::SCROLLABLE, SSStmtOptionNames::SCROLLABLE,
sizeof( SSStmtOptionNames::SCROLLABLE ), sizeof( SSStmtOptionNames::SCROLLABLE ),
SQLSRV_STMT_OPTION_SCROLLABLE, SQLSRV_STMT_OPTION_SCROLLABLE,
std::unique_ptr<stmt_option_ss_scrollable>( new stmt_option_ss_scrollable ) std::unique_ptr<stmt_option_ss_scrollable>( new stmt_option_ss_scrollable )
}, },
{ {
SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE, SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE,
sizeof( SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE ), sizeof( SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE ),
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE, SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit ) std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit )
}, },
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} }, { NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} },
}; };
@ -283,15 +283,15 @@ const connection_option SS_CONN_OPTS[] = {
CONN_ATTR_STRING, CONN_ATTR_STRING,
conn_char_set_func::func conn_char_set_func::func
}, },
{ {
SSConnOptionNames::Authentication, SSConnOptionNames::Authentication,
sizeof( SSConnOptionNames::Authentication ), sizeof( SSConnOptionNames::Authentication ),
SQLSRV_CONN_OPTION_AUTHENTICATION, SQLSRV_CONN_OPTION_AUTHENTICATION,
ODBCConnOptions::Authentication, ODBCConnOptions::Authentication,
sizeof( ODBCConnOptions::Authentication ), sizeof( ODBCConnOptions::Authentication ),
CONN_ATTR_STRING, CONN_ATTR_STRING,
conn_str_append_func::func conn_str_append_func::func
}, },
{ {
SSConnOptionNames::ConnectionPooling, SSConnOptionNames::ConnectionPooling,
sizeof( SSConnOptionNames::ConnectionPooling ), sizeof( SSConnOptionNames::ConnectionPooling ),
@ -513,11 +513,11 @@ PHP_FUNCTION ( sqlsrv_connect )
// register the connection with the PHP runtime // register the connection with the PHP runtime
ss::zend_register_resource(conn_z, conn, ss_sqlsrv_conn::descriptor, ss_sqlsrv_conn::resource_name TSRMLS_CC); ss::zend_register_resource(conn_z, conn, ss_sqlsrv_conn::descriptor, ss_sqlsrv_conn::resource_name TSRMLS_CC);
conn->stmts = stmts; conn->stmts = stmts;
stmts.transferred(); stmts.transferred();
RETURN_RES( Z_RES(conn_z) ); RETURN_RES( Z_RES(conn_z) );
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
@ -617,7 +617,7 @@ PHP_FUNCTION( sqlsrv_close )
try { try {
// dummy context to pass to the error handler // dummy context to pass to the error handler
error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL ); error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
SET_FUNCTION_NAME( *error_ctx ); SET_FUNCTION_NAME( *error_ctx );
@ -628,7 +628,7 @@ PHP_FUNCTION( sqlsrv_close )
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) { CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
throw ss::SSException(); throw ss::SSException();
} }
// if sqlsrv_close was called on a non-existent connection then we just return success. // if sqlsrv_close was called on a non-existent connection then we just return success.
if( Z_TYPE_P( conn_r ) == IS_NULL ) { if( Z_TYPE_P( conn_r ) == IS_NULL ) {
RETURN_TRUE; RETURN_TRUE;
@ -640,31 +640,31 @@ PHP_FUNCTION( sqlsrv_close )
conn = static_cast<ss_sqlsrv_conn*>( zend_fetch_resource( Z_RES_P( conn_r ) TSRMLS_CC, ss_sqlsrv_conn::resource_name, ss_sqlsrv_conn::descriptor )); conn = static_cast<ss_sqlsrv_conn*>( zend_fetch_resource( Z_RES_P( conn_r ) TSRMLS_CC, ss_sqlsrv_conn::resource_name, ss_sqlsrv_conn::descriptor ));
// if sqlsrv_close was called on an already closed connection then we just return success. // if sqlsrv_close was called on an already closed connection then we just return success.
if ( Z_RES_TYPE_P( conn_r ) == RSRC_INVALID_TYPE) { if ( Z_RES_TYPE_P( conn_r ) == RSRC_INVALID_TYPE) {
RETURN_TRUE; RETURN_TRUE;
} }
CHECK_CUSTOM_ERROR(( conn == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) { CHECK_CUSTOM_ERROR(( conn == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
throw ss::SSException(); throw ss::SSException();
} }
SET_FUNCTION_NAME( *conn ); SET_FUNCTION_NAME( *conn );
// cause any variables still holding a reference to this to be invalid so they cause // cause any variables still holding a reference to this to be invalid so they cause
// an error when passed to a sqlsrv function. There's nothing we can do if the // an error when passed to a sqlsrv function. There's nothing we can do if the
// removal fails, so we just log it and move on. // removal fails, so we just log it and move on.
if( zend_list_close( Z_RES_P( conn_r ) ) == FAILURE ) { if( zend_list_close( Z_RES_P( conn_r ) ) == FAILURE ) {
LOG( SEV_ERROR, "Failed to remove connection resource %1!d!", Z_RES_HANDLE_P( conn_r )); LOG( SEV_ERROR, "Failed to remove connection resource %1!d!", Z_RES_HANDLE_P( conn_r ));
} }
ZVAL_NULL( conn_r ); ZVAL_NULL( conn_r );
RETURN_TRUE; RETURN_TRUE;
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
RETURN_FALSE; RETURN_FALSE;
} }
catch( ... ) { catch( ... ) {
@ -947,10 +947,10 @@ PHP_FUNCTION( sqlsrv_prepare )
core_sqlsrv_prepare( stmt, sql, sql_len TSRMLS_CC ); core_sqlsrv_prepare( stmt, sql, sql_len TSRMLS_CC );
if (params_z) { if (params_z) {
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval)); stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_COPY(stmt->params_z, params_z); ZVAL_COPY(stmt->params_z, params_z);
} }
stmt->prepared = true; stmt->prepared = true;
@ -1031,7 +1031,7 @@ PHP_FUNCTION( sqlsrv_query )
hash_auto_ptr ss_stmt_options_ht; hash_auto_ptr ss_stmt_options_ht;
size_t sql_len = 0; size_t sql_len = 0;
zval* options_z = NULL; zval* options_z = NULL;
zval* params_z = NULL; zval* params_z = NULL;
zval stmt_z; zval stmt_z;
ZVAL_UNDEF(&stmt_z); ZVAL_UNDEF(&stmt_z);
@ -1068,8 +1068,8 @@ PHP_FUNCTION( sqlsrv_query )
ss_error_handler, NULL TSRMLS_CC ) ); ss_error_handler, NULL TSRMLS_CC ) );
if( params_z ) { if( params_z ) {
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval)); stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
ZVAL_COPY(stmt->params_z, params_z); ZVAL_COPY(stmt->params_z, params_z);
} }
stmt->set_func( "sqlsrv_query" ); stmt->set_func( "sqlsrv_query" );
@ -1083,7 +1083,7 @@ PHP_FUNCTION( sqlsrv_query )
ss::zend_register_resource(stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name TSRMLS_CC); ss::zend_register_resource(stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name TSRMLS_CC);
// store the resource id with the connection so the connection // store the resource id with the connection so the connection
// can release this statement when it closes. // can release this statement when it closes.
zend_ulong next_index = zend_hash_next_free_element( conn->stmts ); zend_ulong next_index = zend_hash_next_free_element( conn->stmts );
core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z TSRMLS_CC); core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z TSRMLS_CC);
stmt->conn_index = next_index; stmt->conn_index = next_index;
@ -1113,7 +1113,7 @@ PHP_FUNCTION( sqlsrv_query )
void free_stmt_resource( zval* stmt_z TSRMLS_DC ) void free_stmt_resource( zval* stmt_z TSRMLS_DC )
{ {
if( FAILURE == zend_list_close( Z_RES_P( stmt_z ))) { if( FAILURE == zend_list_close( Z_RES_P( stmt_z ))) {
LOG(SEV_ERROR, "Failed to remove stmt resource %1!d!", Z_RES_HANDLE_P(stmt_z)); LOG(SEV_ERROR, "Failed to remove stmt resource %1!d!", Z_RES_HANDLE_P(stmt_z));
} }
ZVAL_NULL( stmt_z ); ZVAL_NULL( stmt_z );
@ -1137,31 +1137,31 @@ void sqlsrv_conn_close_stmts( ss_sqlsrv_conn* conn TSRMLS_DC )
// loop through the stmts hash table and destroy each stmt resource so we can close the // loop through the stmts hash table and destroy each stmt resource so we can close the
// ODBC connection // ODBC connection
zval* rsrc_ptr = NULL; zval* rsrc_ptr = NULL;
ZEND_HASH_FOREACH_VAL( conn->stmts, rsrc_ptr ) { ZEND_HASH_FOREACH_VAL( conn->stmts, rsrc_ptr ) {
try { try {
int zr = ( rsrc_ptr ) != NULL ? SUCCESS : FAILURE; int zr = ( rsrc_ptr ) != NULL ? SUCCESS : FAILURE;
CHECK_ZEND_ERROR( zr, *conn, SQLSRV_ERROR_ZEND_HASH ) { CHECK_ZEND_ERROR( zr, *conn, SQLSRV_ERROR_ZEND_HASH ) {
throw core::CoreException(); throw core::CoreException();
} }
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
DIE( "sqlsrv_conn_close_stmts: Failed to retrieve a statement resource from the connection" ); DIE( "sqlsrv_conn_close_stmts: Failed to retrieve a statement resource from the connection" );
} }
// see if the statement is still valid, and if not skip to the next one // see if the statement is still valid, and if not skip to the next one
// presumably this should never happen because if it's in the list, it should still be valid // presumably this should never happen because if it's in the list, it should still be valid
// by virtue that a statement resource should remove itself from its connection when it is // by virtue that a statement resource should remove itself from its connection when it is
// destroyed in sqlsrv_stmt_dtor. However, rather than die (assert), we simply skip this resource // destroyed in sqlsrv_stmt_dtor. However, rather than die (assert), we simply skip this resource
// and move to the next one. // and move to the next one.
ss_sqlsrv_stmt* stmt = NULL; ss_sqlsrv_stmt* stmt = NULL;
stmt = static_cast<ss_sqlsrv_stmt*>( Z_RES_VAL_P( rsrc_ptr )); stmt = static_cast<ss_sqlsrv_stmt*>( Z_RES_VAL_P( rsrc_ptr ));
if( stmt == NULL || Z_RES_TYPE_P( rsrc_ptr ) != ss_sqlsrv_stmt::descriptor ) { if( stmt == NULL || Z_RES_TYPE_P( rsrc_ptr ) != ss_sqlsrv_stmt::descriptor ) {
LOG( SEV_ERROR, "Non existent statement found in connection. Statements should remove themselves" LOG( SEV_ERROR, "Non existent statement found in connection. Statements should remove themselves"
" from the connection so this shouldn't be out of sync." ); " from the connection so this shouldn't be out of sync." );
continue; continue;
} }
// delete the statement by deleting it from Zend's resource list, which will force its destruction // delete the statement by deleting it from Zend's resource list, which will force its destruction
stmt->conn = NULL; stmt->conn = NULL;
// this would call the destructor on the statement. // this would call the destructor on the statement.
// There's nothing we can do if the removal fails, so we just log it and move on. // There's nothing we can do if the removal fails, so we just log it and move on.
@ -1216,15 +1216,15 @@ int get_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
throw ss::SSException(); throw ss::SSException();
} }
bool valid = true; bool valid = true;
if( stricmp( SS_CONN_OPTS[i].sqlsrv_name, ODBCConnOptions::Authentication ) == 0 ) { if( stricmp( SS_CONN_OPTS[i].sqlsrv_name, ODBCConnOptions::Authentication ) == 0 ) {
valid = core_is_authentication_option_valid( value, value_len ); valid = core_is_authentication_option_valid( value, value_len );
} }
CHECK_CUSTOM_ERROR( !valid, ctx, SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION, SS_CONN_OPTS[ i ].sqlsrv_name ) { CHECK_CUSTOM_ERROR( !valid, ctx, SS_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION, SS_CONN_OPTS[ i ].sqlsrv_name ) {
throw ss::SSException(); throw ss::SSException();
} }
break; break;
} }
@ -1284,23 +1284,23 @@ void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ Has
if( stmt_options ) { if( stmt_options ) {
HashTable* options_ht = Z_ARRVAL_P( stmt_options ); HashTable* options_ht = Z_ARRVAL_P( stmt_options );
zend_ulong int_key = -1; zend_ulong int_key = -1;
zend_string *key = NULL; zend_string *key = NULL;
zval* data = NULL; zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) { ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) {
int type = HASH_KEY_NON_EXISTENT; int type = HASH_KEY_NON_EXISTENT;
size_t key_len = 0; size_t key_len = 0;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG; type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
if (type != HASH_KEY_IS_STRING) { if (type != HASH_KEY_IS_STRING) {
CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str() ) { CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str() ) {
throw core::CoreException(); throw core::CoreException();
} }
} }
key_len = ZSTR_LEN(key) + 1; key_len = ZSTR_LEN(key) + 1;
add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC ); add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC );
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
} }
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
@ -1320,37 +1320,37 @@ void validate_conn_options( sqlsrv_context& ctx, zval* user_options_z, _Out_ cha
if( user_options_z ) { if( user_options_z ) {
HashTable* options_ht = Z_ARRVAL_P( user_options_z ); HashTable* options_ht = Z_ARRVAL_P( user_options_z );
zend_ulong int_key = -1; zend_ulong int_key = -1;
zend_string *key = NULL; zend_string *key = NULL;
zval* data = NULL; zval* data = NULL;
ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) { ZEND_HASH_FOREACH_KEY_VAL( options_ht, int_key, key, data ) {
int type = HASH_KEY_NON_EXISTENT; int type = HASH_KEY_NON_EXISTENT;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG; type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
CHECK_CUSTOM_ERROR(( Z_TYPE_P( data ) == IS_NULL || Z_TYPE_P( data ) == IS_UNDEF ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, key) { CHECK_CUSTOM_ERROR(( Z_TYPE_P( data ) == IS_NULL || Z_TYPE_P( data ) == IS_UNDEF ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, key) {
throw ss::SSException(); throw ss::SSException();
} }
CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_STRING ), ctx, SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY ) { CHECK_CUSTOM_ERROR(( type != HASH_KEY_IS_STRING ), ctx, SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY ) {
throw ss::SSException(); throw ss::SSException();
} }
// Length of the key string does not include the null terminator in PHP7, +1 has to be added // Length of the key string does not include the null terminator in PHP7, +1 has to be added
size_t key_len = ZSTR_LEN(key) + 1; size_t key_len = ZSTR_LEN(key) + 1;
if( key_len == sizeof(SSConnOptionNames::UID) && !stricmp(ZSTR_VAL(key), SSConnOptionNames::UID )) { if( key_len == sizeof(SSConnOptionNames::UID) && !stricmp(ZSTR_VAL(key), SSConnOptionNames::UID )) {
*uid = Z_STRVAL_P( data ); *uid = Z_STRVAL_P( data );
} }
else if( key_len == sizeof( SSConnOptionNames::PWD ) && !stricmp( ZSTR_VAL( key ), SSConnOptionNames::PWD )) { else if( key_len == sizeof( SSConnOptionNames::PWD ) && !stricmp( ZSTR_VAL( key ), SSConnOptionNames::PWD )) {
*pwd = Z_STRVAL_P( data ); *pwd = Z_STRVAL_P( data );
} }
else { else {
::add_conn_option_key( ctx, key, key_len, ss_conn_options_ht, data TSRMLS_CC ); ::add_conn_option_key( ctx, key, key_len, ss_conn_options_ht, data TSRMLS_CC );
} }
} ZEND_HASH_FOREACH_END(); } ZEND_HASH_FOREACH_END();
} }
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {