diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 23b9d72c5..6212ef3ff 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -2,7 +2,7 @@ # https://aka.ms/yaml variables: - phpVersion: 7.3 + phpVersion: 7.4 server: 'localhost,1433' host: 'sql1' sqlsrv_db: 'sqlsrv_testdb' @@ -70,7 +70,7 @@ jobs: inputs: versionSpec: '3.6' architecture: 'x64' - + - script: | sudo update-alternatives --set php /usr/bin/php$(phpVersion) sudo update-alternatives --set phar /usr/bin/phar$(phpVersion) @@ -109,13 +109,13 @@ jobs: sudo sed -i 's/# en_US ISO-8859-1/en_US ISO-8859-1/g' /etc/locale.gen sudo locale-gen en_US sudo locale-gen en_US.UTF-8 - export LANG='en_US.UTF-8' - export LANGUAGE='en_US:en' + export LANG='en_US.UTF-8' + export LANGUAGE='en_US:en' export LC_ALL='en_US.UTF-8' displayName: 'Generate locales for testing' - script: | - echo setting env variables + echo setting env variables export TEST_PHP_SQL_SERVER='$(server)' export TEST_PHP_SQL_UID='$(uid)' export TEST_PHP_SQL_PWD='$(pwd)' @@ -132,7 +132,7 @@ jobs: ./packagize.sh dest=`php --ini | grep "Scan for additional .ini files" | sudo sed -e "s|.*:\s*||"`/ - + cd $(Build.SourcesDirectory)/source/sqlsrv ls -al phpize && ./configure && make && sudo make install @@ -141,7 +141,7 @@ jobs: echo copying sqlsrv to $dest sudo cp 20-sqlsrv.ini $dest - + cd $(Build.SourcesDirectory)/source/pdo_sqlsrv ls -al phpize && ./configure && make && sudo make install @@ -160,7 +160,7 @@ jobs: sed -i -e 's/TARGET_SERVER/'"$(server)"'/g' MsSetup.inc sed -i -e 's/TARGET_DATABASE/'"$(sqlsrv_db)"'/g' MsSetup.inc sed -i -e 's/TARGET_USERNAME/'"$(uid)"'/g' MsSetup.inc - sed -i -e 's/TARGET_PASSWORD/'"$(pwd)"'/g' MsSetup.inc + sed -i -e 's/TARGET_PASSWORD/'"$(pwd)"'/g' MsSetup.inc php run-tests.php -P ./*.phpt 2>&1 | tee ../sqlsrv.log displayName: 'Run sqlsrv functional tests' @@ -170,7 +170,7 @@ jobs: sed -i -e 's/TARGET_SERVER/'"$(server)"'/g' MsSetup.inc sed -i -e 's/TARGET_DATABASE/'"$(pdo_sqlsrv_db)"'/g' MsSetup.inc sed -i -e 's/TARGET_USERNAME/'"$(uid)"'/g' MsSetup.inc - sed -i -e 's/TARGET_PASSWORD/'"$(pwd)"'/g' MsSetup.inc + sed -i -e 's/TARGET_PASSWORD/'"$(pwd)"'/g' MsSetup.inc php run-tests.php -P ./*.phpt 2>&1 | tee ../pdo_sqlsrv.log displayName: 'Run pdo_sqlsrv functional tests' @@ -194,7 +194,7 @@ jobs: docker stop $(host) docker rm $(host) displayName: 'Stop SQL Server for Linux' - condition: always() + condition: always() - job: Windows pool: @@ -249,7 +249,7 @@ jobs: - script: msiexec /i "msodbcsql_13.1.msi" /q IACCEPTMSODBCSQLLICENSETERMS=YES ADDLOCAL=ALL condition: false - # FOR SOME REASON the set up did not set the PATH + # FOR SOME REASON the set up did not set the PATH - script: | msiexec /i "MsSqlCmdLnUtils.msi" /qn IACCEPTMSSQLCMDLNUTILSLICENSETERMS=YES displayName: 'Install SQL command line utilities version 15' @@ -260,7 +260,7 @@ jobs: $client.Headers.Add("user-agent", "azure pipeline build") $client.DownloadFile("https://windows.php.net/downloads/releases/sha256sum.txt", "sha256sum.txt") $env:VERSION=type sha256sum.txt | where { $_ -match "php-($(phpVersion)\.\d+)-src" } | foreach { $matches[1] } - Write-Host "Latest PHP $(phpVersion) is ${env:VERSION}" + Write-Host "Latest PHP $(phpVersion) is ${env:VERSION}" cd $(Build.SourcesDirectory)/buildscripts/ python builddrivers.py --PHPVER=${env:VERSION} --DRIVER=sqlsrv --ARCH=x64 --THREAD=nts --SOURCE=$(Build.SourcesDirectory)/source --TESTING --NO_RENAME dir *sqlsrv*.dll @@ -270,7 +270,7 @@ jobs: dir *sqlsrv*.dll cp *sqlsrv*.dll C:\tools\php\ext\ displayName: 'Build drivers (separately) for the latest version of PHP $(phpVersion)' - + - script: | echo extension=php_sqlsrv.dll >> C:\tools\php\php.ini echo extension=php_pdo_sqlsrv.dll >> C:\tools\php\php.ini @@ -285,7 +285,7 @@ jobs: displayName: 'Run SQL Server for Windows Server' condition: false - - script: | + - script: | set path=C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;%path% sqlcmd -S $(host) -U $(uid) -P $(pwd) -Q "SELECT @@Version" set TEST_PHP_SQL_SERVER=$(host) @@ -309,4 +309,4 @@ jobs: docker stop sqlcontainer docker rm sqlcontainer displayName: 'Stop SQL Server for Windows Server' - condition: false \ No newline at end of file + condition: false diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h index be6ead07b..58ccccf93 100644 --- a/source/shared/core_sqlsrv.h +++ b/source/shared/core_sqlsrv.h @@ -10,13 +10,13 @@ // Copyright(c) Microsoft Corporation // All rights reserved. // MIT License -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""), -// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""), +// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, // and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //--------------------------------------------------------------------------------------------------------------------------------- @@ -28,7 +28,7 @@ #undef SQL_WCHART_CONVERT #endif #ifndef _WCHART_DEFINED -#define _WCHART_DEFINED +#define _WCHART_DEFINED #endif #include "php.h" @@ -54,8 +54,6 @@ #define PHP_SQLSRV_API #endif -// #define MultiByteToWideChar SystemLocale::ToUtf16 - #define stricmp strcasecmp #define strnicmp strncasecmp #define strnlen_s(s) strnlen_s(s, INT_MAX) @@ -103,10 +101,10 @@ extern "C" { #endif #if _MSC_VER >= 1400 -// typedef and macro to prevent a conflict between php.h and ws2tcpip.h. -// php.h defines this constant as unsigned int which causes a compile error +// typedef and macro to prevent a conflict between php.h and ws2tcpip.h. +// php.h defines this constant as unsigned int which causes a compile error // in ws2tcpip.h. Fortunately php.h allows an override by defining -// HAVE_SOCKLEN_T. Since ws2tcpip.h isn't included until later, we define +// HAVE_SOCKLEN_T. Since ws2tcpip.h isn't included until later, we define // socklen_t here and override the php.h version. typedef int socklen_t; #define HAVE_SOCKLEN_T @@ -142,7 +140,7 @@ OACR_WARNING_POP #define WC_ERR_INVALID_CHARS 0x00000080 // error for invalid chars #endif -// PHP defines inline as __forceinline, which in debug mode causes a warning to be emitted when +// PHP defines inline as __forceinline, which in debug mode causes a warning to be emitted when // we use std::copy, which causes compilation to fail since we compile with warnings as errors. #if defined(ZEND_DEBUG) && defined(inline) #undef inline @@ -190,7 +188,7 @@ const long ACTIVE_NUM_ROWS_INVALID = -99; const int SQL_SERVER_2005_DEFAULT_DATETIME_PRECISION = 23; const int SQL_SERVER_2005_DEFAULT_DATETIME_SCALE = 3; const int SQL_SERVER_2008_DEFAULT_DATETIME_PRECISION = 34; -const int SQL_SERVER_2008_DEFAULT_DATETIME_SCALE = 7; +const int SQL_SERVER_2008_DEFAULT_DATETIME_SCALE = 7; namespace AzureADOptions { const char AZURE_AUTH_SQL_PASSWORD[] = "SqlPassword"; @@ -215,7 +213,7 @@ enum SQLSRV_PHPTYPE { }; // encodings supported by this extension. These basically translate into the use of SQL_C_CHAR or SQL_C_BINARY when getting -// information as a string or a stream. +// information as a string or a stream. enum SQLSRV_ENCODING { SQLSRV_ENCODING_INVALID, // unknown or invalid encoding. Used to initialize variables. SQLSRV_ENCODING_DEFAULT, // use what is the connection's default for a statement, use system if a connection @@ -263,7 +261,7 @@ union sqlsrv_sqltype { // SQLSRV PHP types (as opposed to the Zend PHP type constants). Contains the type (see SQLSRV_PHPTYPE) -// and the encoding for strings and streams (see SQLSRV_ENCODING) +// and the encoding for strings and streams (see SQLSRV_ENCODING) union sqlsrv_phptype { @@ -325,8 +323,8 @@ void die( _In_opt_ const char* msg, ... ); #pragma push_macro( "max" ) #undef max -// new memory allocation/free debugging facilities to help us verify that all allocations are being -// released in a timely manner and not just at the end of the script. +// new memory allocation/free debugging facilities to help us verify that all allocations are being +// released in a timely manner and not just at the end of the script. // Zend has memory logging and checking, but it can generate a lot of noise for just one extension. // It's meant for internal use but might be useful for people adding features to our extension. // To use it, uncomment the #define below and compile in Debug NTS. All allocations and releases @@ -435,7 +433,7 @@ struct remove_const { // this allows us to use STL classes that still work with Zend objects template struct sqlsrv_allocator { - + // typedefs used by the STL classes typedef T value_type; typedef value_type* pointer; @@ -459,8 +457,8 @@ struct sqlsrv_allocator { // address (doesn't work if the class defines operator&) inline pointer address( _In_ reference r ) - { - return &r; + { + return &r; } inline const_pointer address( _In_ const_reference r ) @@ -469,20 +467,20 @@ struct sqlsrv_allocator { } // memory allocation/deallocation - inline pointer allocate( _In_ size_type cnt, + inline pointer allocate( _In_ size_type cnt, typename std::allocator::const_pointer = 0 ) { - return reinterpret_cast( sqlsrv_malloc(cnt, sizeof (T), 0)); + return reinterpret_cast( sqlsrv_malloc(cnt, sizeof (T), 0)); } - inline void deallocate( _Inout_ pointer p, size_type ) - { - sqlsrv_free(p); + inline void deallocate( _Inout_ pointer p, size_type ) + { + sqlsrv_free(p); } // size - inline size_type max_size( void ) const - { + inline size_type max_size( void ) const + { return std::numeric_limits::max() / sizeof(T); } @@ -507,11 +505,11 @@ struct sqlsrv_allocator { { return !operator==(a); } -}; +}; -// base class for auto_ptrs that we define below. It provides common operators and functions -// used by all the classes. +// base class for auto_ptrs that we define below. It provides common operators and functions +// used by all the classes. template class sqlsrv_auto_ptr { @@ -576,8 +574,8 @@ class sqlsrv_auto_ptr { return _ptr[index]; } - - #ifdef __WIN64 + + #ifdef __WIN64 // there are a number of places where we allocate a block intended to be accessed as // an array of elements, so this operator allows us to treat the memory as such. T& operator[]( _In_ std::size_t index ) const @@ -616,7 +614,7 @@ class sqlsrv_auto_ptr { protected: sqlsrv_auto_ptr( _In_opt_ T* ptr ) : - _ptr( ptr ) + _ptr( ptr ) { } @@ -637,7 +635,7 @@ class sqlsrv_auto_ptr { return ptr; } - T* _ptr; + T* _ptr; }; // an auto_ptr for sqlsrv_malloc/sqlsrv_free. When allocating a chunk of memory using sqlsrv_malloc, wrap that pointer @@ -684,13 +682,13 @@ class sqlsrv_malloc_auto_ptr : public sqlsrv_auto_ptr >::_ptr = reinterpret_cast( sqlsrv_realloc( sqlsrv_auto_ptr >::_ptr, new_size )); } }; -// auto ptr for Zend hash tables. Used to clean up a hash table allocated when +// auto ptr for Zend hash tables. Used to clean up a hash table allocated when // something caused an early exit from the function. This is used when the hash_table is // allocated in a zval that itself can't be released. Otherwise, use the zval_auto_ptr. @@ -726,8 +724,8 @@ class hash_auto_ptr : public sqlsrv_auto_ptr { }; -// an auto_ptr for zvals. When allocating a zval, wrap that pointer in a variable of zval_auto_ptr. -// zval_auto_ptr will "own" that zval and assure that it is freed when the variable is destroyed +// an auto_ptr for zvals. When allocating a zval, wrap that pointer in a variable of zval_auto_ptr. +// zval_auto_ptr will "own" that zval and assure that it is freed when the variable is destroyed // (out of scope) or ownership is transferred using the function "transferred". class zval_auto_ptr : public sqlsrv_auto_ptr { @@ -798,7 +796,7 @@ struct sqlsrv_error : public sqlsrv_error_const { native_code = code; format = printf_format; } - + sqlsrv_error( _In_ sqlsrv_error_const const& prototype ) { sqlsrv_error( prototype.sqlstate, prototype.native_message, prototype.native_code, prototype.format ); @@ -865,8 +863,8 @@ class sqlsrv_context; struct sqlsrv_conn; // error_callback -// a driver specific callback for processing errors. -// ctx - the context holding the handles +// a driver specific callback for processing errors. +// ctx - the context holding the handles // sqlsrv_error_code - specific error code to return. typedef bool (*error_callback)( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_error_code, _In_ bool error TSRMLS_DC, _In_opt_ va_list* print_args ); @@ -910,7 +908,7 @@ class sqlsrv_context { } virtual ~sqlsrv_context() - { + { } void set_func( _In_z_ const char* f ) @@ -927,7 +925,7 @@ class sqlsrv_context { { return last_error_; } - + // since the primary responsibility of a context is to hold an ODBC handle, we // provide these convenience operators for using them interchangeably operator SQLHANDLE ( void ) const @@ -997,7 +995,7 @@ class sqlsrv_context { error_callback err_; // driver error callback if error occurs in core layer void* driver_; // points back to the driver for PDO sqlsrv_error_auto_ptr last_error_; // last error that happened on this object - SQLSRV_ENCODING encoding_; // encoding of the context + SQLSRV_ENCODING encoding_; // encoding of the context }; // maps an IANA encoding to a code page @@ -1064,7 +1062,7 @@ enum DRIVER_VERSION { struct sqlsrv_stmt; struct stmt_option; -// This holds the various details of column encryption. +// This holds the various details of column encryption. struct col_encryption_option { bool enabled; // column encryption enabled, false by default SQLINTEGER akv_mode; @@ -1105,13 +1103,13 @@ struct sqlsrv_conn : public sqlsrv_context { 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 // called manually. Instead, we leave it to the allocator to invalidate the handle when an error occurs allocating // the sqlsrv_conn with a connection. }; enum SQLSRV_STMT_OPTIONS { - + SQLSRV_STMT_OPTION_INVALID, SQLSRV_STMT_OPTION_QUERY_TIMEOUT, SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC, @@ -1164,7 +1162,7 @@ const char SERVER[] = "Server"; } enum SQLSRV_CONN_OPTIONS { - + SQLSRV_CONN_OPTION_INVALID, SQLSRV_CONN_OPTION_APP, SQLSRV_CONN_OPTION_ACCESS_TOKEN, @@ -1200,7 +1198,7 @@ enum SQLSRV_CONN_OPTIONS { // Driver specific connection options SQLSRV_CONN_OPTION_DRIVER_SPECIFIC = 1000, - + }; @@ -1220,7 +1218,7 @@ struct connection_option { // the name of the option as passed in by the user const char * sqlsrv_name; unsigned int sqlsrv_len; - + unsigned int conn_option_key; // the name of the option in the ODBC connection string const char * odbc_name; @@ -1247,7 +1245,7 @@ struct column_encryption_set_func { static void func( _In_ connection_option const* option, _In_ zval* value, _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str TSRMLS_DC ); }; -struct driver_set_func { +struct driver_set_func { static void func( _In_ connection_option const* option, _In_ zval* value, _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str TSRMLS_DC ); }; @@ -1265,8 +1263,8 @@ typedef sqlsrv_conn* (*driver_conn_factory)( _In_ SQLHANDLE h, _In_ error_callba // *** connection functions *** sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_context& henv_ncp, _In_ driver_conn_factory conn_factory, - _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_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[], _In_ void* driver, _In_z_ const char* driver_func TSRMLS_DC ); 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 ); @@ -1332,9 +1330,9 @@ struct stmt_option { const char * name; // name of the statement option unsigned int name_len; // name length - unsigned int key; + unsigned int key; std::unique_ptr func; // callback that actually handles the work of the option - + }; // holds the stream param and the encoding that it was assigned @@ -1368,9 +1366,9 @@ extern php_stream_wrapper g_sqlsrv_stream_wrapper; // *** parameter metadata struct *** struct param_meta_data { - SQLSMALLINT sql_type; + SQLSMALLINT sql_type; SQLSMALLINT decimal_digits; - SQLSMALLINT nullable; + SQLSMALLINT nullable; SQLULEN column_size; param_meta_data() : sql_type(0), decimal_digits(0), column_size(0), nullable(0) @@ -1416,16 +1414,16 @@ struct sqlsrv_output_param { { } - void saveMetaData(SQLSMALLINT sql_type, SQLSMALLINT column_size, SQLSMALLINT decimal_digits, SQLSMALLINT nullable = SQL_NULLABLE) - { + void saveMetaData(SQLSMALLINT sql_type, SQLSMALLINT column_size, SQLSMALLINT decimal_digits, SQLSMALLINT nullable = SQL_NULLABLE) + { meta_data.sql_type = sql_type; meta_data.column_size = column_size; meta_data.decimal_digits = decimal_digits; meta_data.nullable = nullable; } - param_meta_data& getMetaData() - { + param_meta_data& getMetaData() + { return meta_data; } }; @@ -1472,13 +1470,13 @@ namespace data_classification { { } - ~column_sensitivity() + ~column_sensitivity() { label_info_pairs.clear(); } }; - struct sensitivity_metadata { + struct sensitivity_metadata { USHORT num_labels; std::vector> labels; USHORT num_infotypes; @@ -1491,7 +1489,7 @@ namespace data_classification { } ~sensitivity_metadata() - { + { reset(); } @@ -1503,7 +1501,7 @@ namespace data_classification { struct sqlsrv_result_set; struct field_meta_data; -// *** Statement resource structure *** +// *** Statement resource structure *** struct sqlsrv_stmt : public sqlsrv_context { void free_param_data( TSRMLS_D ); @@ -1513,13 +1511,13 @@ struct sqlsrv_stmt : public sqlsrv_context { void clean_up_sensitivity_metadata(); sqlsrv_conn* conn; // Connection that created this statement - + bool executed; // Whether the statement has been executed yet (used for error messages) bool past_fetch_end; // Core_sqlsrv_fetch sets this field when the statement goes beyond the last row sqlsrv_result_set* current_results; // Current result set SQLULEN cursor_type; // Type of cursor for the current result set bool has_rows; // Has_rows is set if there are actual rows in the row set - bool fetch_called; // Used by core_sqlsrv_get_field to return an informative error if fetch not yet called + bool fetch_called; // Used by core_sqlsrv_get_field to return an informative error if fetch not yet called int last_field_index; // last field retrieved by core_sqlsrv_get_field bool past_next_result_end; // core_sqlsrv_next_result sets this to true when the statement goes beyond the last results short column_count; // Number of columns in the current result set obtained from SQLNumResultCols @@ -1529,7 +1527,7 @@ struct sqlsrv_stmt : public sqlsrv_context { bool date_as_string; // false by default but the user can set this to true to retrieve datetime values as strings bool format_decimals; // false by default but the user can set this to true to add the missing leading zeroes and/or control number of decimal digits to show short decimal_places; // indicates number of decimals shown in fetched results (-1 by default, which means no change to number of decimal digits) - bool data_classification; // false by default but the user can set this to true to retrieve data classification sensitivity metadata + bool data_classification; // false by default but the user can set this to true to retrieve data classification sensitivity metadata // holds output pointers for SQLBindParameter // We use a deque because it 1) provides the at/[] access in constant time, and 2) grows dynamically without moving @@ -1541,10 +1539,10 @@ struct sqlsrv_stmt : public sqlsrv_context { zval param_datetime_buffers; // datetime strings to be converted back to DateTime objects bool send_streams_at_exec; // send all stream data right after execution before returning sqlsrv_stream current_stream; // current stream sending data to the server as an input parameter - unsigned int current_stream_read; // # of bytes read so far. (if we read an empty PHP stream, we send an empty string + unsigned int current_stream_read; // # of bytes read so far. (if we read an empty PHP stream, we send an empty string // to the server) zval field_cache; // cache for a single row of fields, to allow multiple and out of order retrievals - zval col_cache; // Used by get_field_as_string not to call SQLColAttribute() after every fetch. + zval col_cache; // Used by get_field_as_string not to call SQLColAttribute() after every fetch. zval active_stream; // the currently active stream reading data from the database std::vector param_descriptions; @@ -1573,7 +1571,7 @@ struct field_meta_data { SQLSMALLINT field_type; SQLULEN field_size; SQLULEN field_precision; - SQLSMALLINT field_scale; + SQLSMALLINT field_scale; SQLSMALLINT field_is_nullable; bool field_is_money_type; sqlsrv_phptype sqlsrv_php_type; @@ -1584,7 +1582,7 @@ struct field_meta_data { reset_php_type(); } - ~field_meta_data() + ~field_meta_data() { } @@ -1614,7 +1612,7 @@ const size_t SQLSRV_CURSOR_BUFFERED = 0xfffffffeUL; // arbitrary number that doe typedef sqlsrv_stmt* (*driver_stmt_factory)( sqlsrv_conn* conn, SQLHANDLE h, error_callback e, void* drv TSRMLS_DC ); // *** statement functions *** -sqlsrv_stmt* core_sqlsrv_create_stmt( _Inout_ sqlsrv_conn* conn, _In_ driver_stmt_factory stmt_factory, _In_opt_ HashTable* options_ht, +sqlsrv_stmt* core_sqlsrv_create_stmt( _Inout_ sqlsrv_conn* conn, _In_ driver_stmt_factory stmt_factory, _In_opt_ HashTable* options_ht, _In_opt_ const stmt_option valid_stmt_opts[], _In_ error_callback const err, _In_opt_ void* driver TSRMLS_DC ); void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_num, _In_ SQLSMALLINT direction, _Inout_ zval* param_z, _In_ SQLSRV_PHPTYPE php_out_type, _Inout_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size, @@ -1660,7 +1658,7 @@ struct sqlsrv_result_set { virtual SQLRETURN get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type, _Out_writes_bytes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length, bool handle_warning TSRMLS_DC )= 0; - virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, + virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, _Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length, _Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC ) = 0; virtual sqlsrv_error* get_diag_rec( _In_ SQLSMALLINT record_number ) = 0; @@ -1677,7 +1675,7 @@ struct sqlsrv_odbc_result_set : public sqlsrv_result_set { virtual SQLRETURN get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type, _Out_writes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length, _In_ bool handle_warning TSRMLS_DC ); - virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, + virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, _Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length, _Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC ); virtual sqlsrv_error* get_diag_rec( _In_ SQLSMALLINT record_number ); @@ -1715,13 +1713,13 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set { virtual SQLRETURN get_data( _In_ SQLUSMALLINT field_index, _In_ SQLSMALLINT target_type, _Out_writes_bytes_opt_(buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length, bool handle_warning TSRMLS_DC ); - virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, + virtual SQLRETURN get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, _Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length, _Inout_ SQLSMALLINT* out_buffer_length TSRMLS_DC ); virtual sqlsrv_error* get_diag_rec( _In_ SQLSMALLINT record_number ); virtual SQLLEN row_count( TSRMLS_D ); - // buffered result set specific + // buffered result set specific SQLSMALLINT column_count( void ) { return col_count; @@ -1758,7 +1756,7 @@ struct sqlsrv_buffered_result_set : public sqlsrv_result_set { // string conversion functions SQLRETURN binary_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length ); - SQLRETURN binary_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, + SQLRETURN binary_to_system_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length ); SQLRETURN system_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length ); @@ -1839,7 +1837,7 @@ enum SQLSRV_ERROR_CODES { SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE, SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE, - SQLSRV_ERROR_ZEND_STREAM, + SQLSRV_ERROR_ZEND_STREAM, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE, SQLSRV_ERROR_UNKNOWN_SERVER_VERSION, SQLSRV_ERROR_FETCH_PAST_END, @@ -1910,11 +1908,11 @@ enum error_handling_flags { // 2/code) driver specific error code // 3/message) driver specific error message // The fetch type determines if the indices are numeric, associative, or both. -bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_number, _Inout_ sqlsrv_error_auto_ptr& error, +bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_number, _Inout_ sqlsrv_error_auto_ptr& error, _In_ logging_severity severity TSRMLS_DC ); // format and return a driver specfic error -void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_error_const const* custom_error, +void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_error_const const* custom_error, _Out_ sqlsrv_error_auto_ptr& formatted_error, _In_ logging_severity severity TSRMLS_DC, _In_opt_ va_list* args ); @@ -1949,19 +1947,19 @@ inline bool call_error_handler( _Inout_ sqlsrv_context* ctx, _In_ unsigned long // we don't want on a web server #define SQLSRV_ASSERT( condition, msg, ...) if( !(condition)) DIE( msg, ## __VA_ARGS__ ); - -#if defined( PHP_DEBUG ) + +#if defined( PHP_DEBUG ) #define DEBUG_SQLSRV_ASSERT( condition, msg, ... ) \ if( !(condition)) { \ DIE (msg, ## __VA_ARGS__ ); \ - } + } #else #define DEBUG_SQLSRV_ASSERT( condition, msg, ... ) ((void)0) -#endif +#endif // check to see if the sqlstate is 01004, truncated field retrieved. Used for retrieving large fields. inline bool is_truncated_warning( _In_ SQLCHAR* state ) @@ -1984,7 +1982,7 @@ inline bool is_truncated_warning( _In_ SQLCHAR* state ) ignored##unique = call_error_handler( context, ssphp TSRMLS_CC, /*warning*/false, ## __VA_ARGS__ ); \ } \ if( !ignored##unique ) - + #define CHECK_ERROR_UNIQUE( unique, condition, context, ssphp, ...) \ CHECK_ERROR_EX( unique, condition, context, ssphp, ## __VA_ARGS__ ) @@ -2003,11 +2001,11 @@ inline bool is_truncated_warning( _In_ SQLCHAR* state ) if( condition ) { \ ignored##unique = call_error_handler( context, ssphp TSRMLS_CC, /*warning*/true, ## __VA_ARGS__ ); \ } \ - if( !ignored##unique ) + if( !ignored##unique ) #define CHECK_SQL_WARNING_AS_ERROR( result, context, ... ) \ CHECK_WARNING_AS_ERROR_UNIQUE( __COUNTER__,( result == SQL_SUCCESS_WITH_INFO ), context, SQLSRV_ERROR_ODBC, ## __VA_ARGS__ ) - + #define CHECK_SQL_WARNING( result, context, ... ) \ if( result == SQL_SUCCESS_WITH_INFO ) { \ (void)call_error_handler( context, 0 TSRMLS_CC, /*warning*/ true, ## __VA_ARGS__ ); \ @@ -2015,7 +2013,7 @@ inline bool is_truncated_warning( _In_ SQLCHAR* state ) #define CHECK_CUSTOM_WARNING_AS_ERROR( condition, context, ssphp, ... ) \ CHECK_WARNING_AS_ERROR_UNIQUE( __COUNTER__, condition, context, ssphp, ## __VA_ARGS__ ) - + #define CHECK_ZEND_ERROR( zr, ctx, error, ... ) \ CHECK_ERROR_UNIQUE( __COUNTER__, ( zr == FAILURE ), ctx, error, ## __VA_ARGS__ ) \ @@ -2029,7 +2027,7 @@ inline bool is_truncated_warning( _In_ SQLCHAR* state ) ignored = call_error_handler( context, SQLSRV_ERROR_ODBC TSRMLS_CC, true TSRMLS_CC, ##__VA_ARGS__ ); \ } \ if( !ignored ) - + // throw an exception after it has been hooked into the custom error handler #define THROW_CORE_ERROR( ctx, custom, ... ) \ (void)call_error_handler( ctx, custom TSRMLS_CC, /*warning*/ false, ## __VA_ARGS__ ); \ @@ -2051,25 +2049,25 @@ namespace core { inline void check_for_mars_error( _Inout_ sqlsrv_stmt* stmt, _In_ SQLRETURN r TSRMLS_DC ) { - // Skip this if not SQL_ERROR - + // Skip this if not SQL_ERROR - // We check for the 'connection busy' error caused by having MultipleActiveResultSets off // and return a more helpful message prepended to the ODBC errors if that error occurs if (r == SQL_ERROR) { 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, + + SQLRETURN rtemp = ::SQLGetDiagField( stmt->handle_type(), stmt->handle(), 1, SQL_DIAG_MESSAGE_TEXT, 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 + // 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(); } @@ -2078,7 +2076,7 @@ namespace core { const std::string returned_error( reinterpret_cast( err_msg )); if(( returned_error.find( connection_busy_error ) != std::string::npos )) { - + THROW_CORE_ERROR( stmt, SQLSRV_ERROR_MARS_OFF ); } } @@ -2092,11 +2090,11 @@ namespace core { // These functions take the sqlsrv_context type. However, since the error handling code can alter // the context to hold the error, they are not passed as const. - inline SQLRETURN SQLGetDiagField( _Inout_ sqlsrv_context* ctx, _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, + inline SQLRETURN SQLGetDiagField( _Inout_ sqlsrv_context* ctx, _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier, _Out_writes_opt_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length, _Out_opt_ SQLSMALLINT* out_buffer_length TSRMLS_DC ) { - SQLRETURN r = ::SQLGetDiagField( ctx->handle_type(), ctx->handle(), record_number, diag_identifier, + SQLRETURN r = ::SQLGetDiagField( ctx->handle_type(), ctx->handle(), record_number, diag_identifier, diag_info_buffer, buffer_length, out_buffer_length ); CHECK_SQL_ERROR_OR_WARNING( r, ctx ) { @@ -2106,7 +2104,7 @@ namespace core { return r; } - inline void SQLAllocHandle( _In_ SQLSMALLINT HandleType, _Inout_ sqlsrv_context& InputHandle, + inline void SQLAllocHandle( _In_ SQLSMALLINT HandleType, _Inout_ sqlsrv_context& InputHandle, _Out_ SQLHANDLE* OutputHandlePtr TSRMLS_DC ) { SQLRETURN r; @@ -2116,7 +2114,7 @@ namespace core { } } - inline void SQLBindParameter( _Inout_ sqlsrv_stmt* stmt, + inline void SQLBindParameter( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT ParameterNumber, _In_ SQLSMALLINT InputOutputType, _In_ SQLSMALLINT ValueType, @@ -2129,9 +2127,9 @@ namespace core { TSRMLS_DC ) { SQLRETURN r; - r = ::SQLBindParameter( stmt->handle(), ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize, + r = ::SQLBindParameter( stmt->handle(), ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, StrLen_Or_IndPtr ); - + CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw CoreException(); } @@ -2146,7 +2144,7 @@ namespace core { } } - inline void SQLColAttribute( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLUSMALLINT field_identifier, + inline void SQLColAttribute( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLUSMALLINT field_identifier, _Out_writes_bytes_opt_(buffer_length) SQLPOINTER field_type_char, _In_ SQLSMALLINT buffer_length, _Out_opt_ SQLSMALLINT* out_buffer_length, _Out_opt_ SQLLEN* field_type_num TSRMLS_DC ) { @@ -2175,9 +2173,9 @@ namespace core { _Out_opt_ SQLSMALLINT* decimal_digits, _Out_opt_ SQLSMALLINT* nullable TSRMLS_DC ) { SQLRETURN r; - r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out, + r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out, data_type, col_size, decimal_digits, nullable); - + CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw CoreException(); } @@ -2220,17 +2218,17 @@ namespace core { inline void SQLEndTran( _In_ SQLSMALLINT handleType, _Inout_ sqlsrv_conn* conn, _In_ SQLSMALLINT completionType TSRMLS_DC ) { SQLRETURN r = ::SQLEndTran( handleType, conn->handle(), completionType ); - + CHECK_SQL_ERROR_OR_WARNING( r, conn ) { throw CoreException(); } } - // SQLExecDirect returns the status code since it returns either SQL_NEED_DATA or SQL_NO_DATA besides just errors/success + // SQLExecDirect returns the status code since it returns either SQL_NEED_DATA or SQL_NO_DATA besides just errors/success inline SQLRETURN SQLExecDirect( _Inout_ sqlsrv_stmt* stmt, _In_ char* sql TSRMLS_DC ) { SQLRETURN r = ::SQLExecDirect( stmt->handle(), reinterpret_cast( sql ), SQL_NTS ); - + check_for_mars_error( stmt, r TSRMLS_CC ); CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { @@ -2258,7 +2256,7 @@ namespace core { { SQLRETURN r; r = ::SQLExecute( stmt->handle() ); - + check_for_mars_error( stmt, r TSRMLS_CC ); CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { @@ -2271,7 +2269,7 @@ namespace core { inline SQLRETURN SQLFetchScroll( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orientation, _In_ SQLLEN fetch_offset TSRMLS_DC ) { SQLRETURN r = ::SQLFetchScroll( stmt->handle(), fetch_orientation, fetch_offset ); - + CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw CoreException(); } @@ -2304,7 +2302,7 @@ namespace core { if( r == SQL_NO_DATA ) return r; - + CHECK_SQL_ERROR( r, stmt ) { throw CoreException(); } @@ -2318,13 +2316,13 @@ namespace core { return r; } - + inline void SQLGetInfo( _Inout_ sqlsrv_conn* conn, _In_ SQLUSMALLINT info_type, _Out_writes_bytes_opt_(buffer_len) SQLPOINTER info_value, _In_ SQLSMALLINT buffer_len, _Out_opt_ SQLSMALLINT* str_len TSRMLS_DC ) { SQLRETURN r; r = ::SQLGetInfo( conn->handle(), info_type, info_value, buffer_len, str_len ); - + CHECK_SQL_ERROR_OR_WARNING( r, conn ) { throw CoreException(); } @@ -2335,7 +2333,7 @@ namespace core { { SQLRETURN r; r = ::SQLGetTypeInfo( stmt->handle(), data_type ); - + CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw CoreException(); } @@ -2363,7 +2361,7 @@ namespace core { CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw CoreException(); } - + return num_cols; } @@ -2405,14 +2403,14 @@ namespace core { SQLLEN rows_affected; r = ::SQLRowCount( stmt->handle(), &rows_affected ); - + // On Linux platform // DriverName: libmsodbcsql-13.0.so.0.0 // DriverODBCVer: 03.52 // DriverVer: 13.00.0000 // unixODBC: 2.3.1 - // r = ::SQLRowCount( stmt->handle(), &rows_affected ); - // returns r=-1 for an empty result set. + // r = ::SQLRowCount( stmt->handle(), &rows_affected ); + // returns r=-1 for an empty result set. #ifndef _WIN32 if( r == -1 && rows_affected == -1 ) return 0; @@ -2430,7 +2428,7 @@ namespace core { { SQLRETURN r; r = ::SQLSetConnectAttr( ctx.handle(), attr, value_ptr, str_len ); - + CHECK_SQL_ERROR_OR_WARNING( r, ctx ) { throw CoreException(); } @@ -2460,13 +2458,13 @@ namespace core { inline void SQLSetConnectAttr( _Inout_ sqlsrv_conn* conn, _In_ SQLINTEGER attribute, _In_reads_bytes_opt_(value_len) SQLPOINTER value_ptr, _In_ SQLINTEGER value_len TSRMLS_DC ) { - SQLRETURN r = ::SQLSetConnectAttr( conn->handle(), attribute, value_ptr, value_len ); - + SQLRETURN r = ::SQLSetConnectAttr( conn->handle(), attribute, value_ptr, value_len ); + CHECK_SQL_ERROR_OR_WARNING( r, conn ) { throw CoreException(); } } - + inline void SQLSetStmtAttr( _Inout_ sqlsrv_stmt* stmt, _In_ SQLINTEGER attr, _In_reads_(str_len) SQLPOINTER value_ptr, _In_ SQLINTEGER str_len TSRMLS_DC ) { SQLRETURN r; @@ -2505,7 +2503,7 @@ namespace core { // If there is a zend function in the source that isn't found here, it is because it returns void and there is no error // that can be thrown from it. - inline void sqlsrv_add_index_zval( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array, _In_ zend_ulong index, _In_ zval* value TSRMLS_DC) + inline void sqlsrv_add_index_zval( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array, _In_ zend_ulong index, _In_ zval* value TSRMLS_DC) { int zr = add_index_zval( array, index, value ); CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) { @@ -2513,7 +2511,7 @@ namespace core { } } - inline void sqlsrv_add_next_index_zval( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array, _In_ zval* value TSRMLS_DC) + inline void sqlsrv_add_next_index_zval( _Inout_ sqlsrv_context& ctx, _Inout_ zval* array, _In_ zval* value TSRMLS_DC) { int zr = add_next_index_zval( array, value ); CHECK_ZEND_ERROR( zr, ctx, SQLSRV_ERROR_ZEND_HASH ) { @@ -2556,7 +2554,7 @@ namespace core { } } - inline void sqlsrv_array_init( _Inout_ sqlsrv_context& ctx, _Out_ zval* new_array TSRMLS_DC) + inline void sqlsrv_array_init( _Inout_ sqlsrv_context& ctx, _Out_ zval* new_array TSRMLS_DC) { #if PHP_VERSION_ID < 70300 CHECK_ZEND_ERROR(::array_init(new_array), ctx, SQLSRV_ERROR_ZEND_HASH) { @@ -2599,7 +2597,7 @@ namespace core { throw CoreException(); } } - + inline void sqlsrv_zend_hash_index_update( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zend_ulong index, _In_ zval* data_z TSRMLS_DC ) { int zr = (data_z = ::zend_hash_index_update(ht, index, data_z)) != NULL ? SUCCESS : FAILURE; @@ -2624,7 +2622,7 @@ namespace core { throw CoreException(); } } - + inline void sqlsrv_zend_hash_next_index_insert( _Inout_ sqlsrv_context& ctx, _Inout_ HashTable* ht, _In_ zval* data TSRMLS_DC ) { int zr = (data = ::zend_hash_next_index_insert(ht, data)) != NULL ? SUCCESS : FAILURE; @@ -2648,7 +2646,7 @@ namespace core { throw CoreException(); } } - + inline void sqlsrv_zend_hash_init(sqlsrv_context& ctx, _Inout_ HashTable* ht, _Inout_ uint32_t initial_size, _In_ dtor_func_t dtor_fn, _In_ zend_bool persistent TSRMLS_DC ) { diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index 090322a5f..d2502c81c 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -329,7 +329,7 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( _Inout_ sqlsrv_conn* conn, _In_ driver_stm } // The query timeout setting is inherited from the corresponding connection attribute, but - // the user may override that the query timeout setting using the statement option. + // the user may override that the query timeout setting using the statement option. // In any case, set query timeout using the latest value stmt->set_query_timeout(); @@ -850,7 +850,7 @@ bool core_sqlsrv_fetch( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orient CHECK_CUSTOM_ERROR( stmt->past_fetch_end, stmt, SQLSRV_ERROR_FETCH_PAST_END ) { throw core::CoreException(); } - + // First time only if ( !stmt->fetch_called ) { SQLSMALLINT has_fields; @@ -860,7 +860,7 @@ bool core_sqlsrv_fetch( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orient has_fields = core::SQLNumResultCols( stmt TSRMLS_CC ); stmt->column_count = has_fields; } - + CHECK_CUSTOM_ERROR( has_fields == 0, stmt, SQLSRV_ERROR_NO_FIELDS ) { throw core::CoreException(); } @@ -1009,7 +1009,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) } // Reference: https://docs.microsoft.com/sql/connect/odbc/data-classification - // To retrieve sensitivity classfication data, the first step is to retrieve the IRD(Implementation Row Descriptor) handle by + // To retrieve sensitivity classfication data, the first step is to retrieve the IRD(Implementation Row Descriptor) handle by // calling SQLGetStmtAttr with SQL_ATTR_IMP_ROW_DESC statement attribute r = ::SQLGetStmtAttr(stmt->handle(), SQL_ATTR_IMP_ROW_DESC, (SQLPOINTER)&ird, SQL_IS_POINTER, 0); CHECK_SQL_ERROR_OR_WARNING(r, stmt) { @@ -1074,7 +1074,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) CHECK_CUSTOM_ERROR(dcptr != dcend, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "Metadata parsing ends unexpectedly") { throw core::CoreException(); } - + stmt->current_sensitivity_metadata = sensitivity_meta; sensitivity_meta.transferred(); } catch (core::CoreException& e) { @@ -1172,7 +1172,7 @@ void core_sqlsrv_get_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i // use the previously saved php type sqlsrv_php_type = stmt->current_meta_data[field_index]->sqlsrv_php_type; } - } + } // Verify that we have an acceptable type to convert. CHECK_CUSTOM_ERROR(!is_valid_sqlsrv_phptype(sqlsrv_php_type), stmt, SQLSRV_ERROR_INVALID_TYPE) { @@ -1209,7 +1209,7 @@ bool core_sqlsrv_has_any_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) { SQLSMALLINT num_cols; SQLLEN rows_affected; - + if (stmt->column_count != ACTIVE_NUM_COLS_INVALID) { num_cols = stmt->column_count; } @@ -1218,7 +1218,7 @@ bool core_sqlsrv_has_any_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) num_cols = core::SQLNumResultCols( stmt TSRMLS_CC ); stmt->column_count = num_cols; } - + if (stmt->row_count != ACTIVE_NUM_ROWS_INVALID) { rows_affected = stmt->row_count; } @@ -1227,7 +1227,7 @@ bool core_sqlsrv_has_any_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) rows_affected = core::SQLRowCount( stmt TSRMLS_CC ); stmt->row_count = rows_affected; } - + return (num_cols != 0) || (rows_affected > 0); } @@ -1266,7 +1266,7 @@ void core_sqlsrv_next_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_ bool fin if( r == SQL_NO_DATA ) { - if( &(stmt->output_params) && finalize_output_params ) { + if( finalize_output_params ) { // if we're finished processing result sets, handle the output parameters finalize_output_parameters( stmt TSRMLS_CC ); } @@ -1416,7 +1416,7 @@ void core_sqlsrv_set_decimal_places(_Inout_ sqlsrv_stmt* stmt, _In_ zval* value_ } stmt->decimal_places = static_cast(decimal_places); - } + } catch( core::CoreException& ) { throw; } @@ -1858,7 +1858,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i // Reference: https://docs.microsoft.com/sql/odbc/reference/appendixes/sql-to-c-timestamp // Retrieve the datetime data as a string, which may be cached for later use. - // The string is converted to a DateTime object only when it is required to + // The string is converted to a DateTime object only when it is required to // be returned as a zval. case SQLSRV_PHPTYPE_DATETIME: { @@ -1885,7 +1885,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i break; } - + // create a stream wrapper around the field and return that object to the PHP script. calls to fread // on the stream will result in calls to SQLGetData. This is handled in stream.cpp. See that file // for how these fields are used. @@ -2012,7 +2012,7 @@ bool convert_input_param_to_utf16( _In_ zval* input_param_z, _Inout_ zval* conve // conversion, to avoid the performance penalty of calling ToUtf16 wchar_size = buffer_len; #else - // Calculate the size of the necessary buffer from the length of the string - + // Calculate the size of the necessary buffer from the length of the string - // no performance penalty because MultiByteToWidechar is highly optimised wchar_size = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, reinterpret_cast( buffer ), static_cast( buffer_len ), NULL, 0 ); #endif // !_WIN32 @@ -2275,7 +2275,7 @@ void format_decimal_numbers(_In_ SQLSMALLINT decimals_places, _In_ SQLSMALLINT f // number of decimals adheres to the column field scale. If smaller, the output value may be rounded up. // // Note: it's possible that the decimal data does not contain a decimal dot because the field scale is 0. - // Thus, first check if the decimal dot exists. If not, no formatting necessary, regardless of + // Thus, first check if the decimal dot exists. If not, no formatting necessary, regardless of // format_decimals and decimals_places // std::string str = field_value; @@ -2292,8 +2292,8 @@ void format_decimal_numbers(_In_ SQLSMALLINT decimals_places, _In_ SQLSMALLINT f } // We want the rounding to be consistent with php number_format(), http://php.net/manual/en/function.number-format.php - // as well as SQL Server Management studio, such that the least significant digit will be rounded up if it is - // followed by 5 or above. + // as well as SQL Server Management studio, such that the least significant digit will be rounded up if it is + // followed by 5 or above. bool isNegative = false; @@ -2313,16 +2313,16 @@ void format_decimal_numbers(_In_ SQLSMALLINT decimals_places, _In_ SQLSMALLINT f str = oss.str(); pos++; } - + if (num_decimals == NO_CHANGE_DECIMAL_PLACES) { // Add the minus sign back if negative if (isNegative) { std::ostringstream oss; oss << '-' << str.substr(0); str = oss.str(); - } + } } else { - // Start formatting + // Start formatting size_t last = 0; if (num_decimals == 0) { // Chop all decimal digits, including the decimal dot @@ -2532,7 +2532,7 @@ void finalize_output_parameters( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) throw core::CoreException(); } } - // if the output param is a boolean, still convert to + // if the output param is a boolean, still convert to // a long integer first to take care of rounding convert_to_long(value_z); if (output_param->is_bool) { @@ -2911,9 +2911,9 @@ void resize_output_buffer_if_necessary( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* // account for the NULL terminator returned by ODBC and needed by Zend to avoid a "String not null terminated" debug warning SQLULEN field_size = column_size; - // with AE on, when column_size is retrieved from SQLDescribeParam, column_size + // with AE on, when column_size is retrieved from SQLDescribeParam, column_size // does not include the negative sign or decimal place for numeric values - // VSO Bug 2913: without AE, the same can happen as well, in particular to decimals + // VSO Bug 2913: without AE, the same can happen as well, in particular to decimals // and numerics with precision/scale specified if (sql_type == SQL_DECIMAL || sql_type == SQL_NUMERIC || sql_type == SQL_BIGINT || sql_type == SQL_INTEGER || sql_type == SQL_SMALLINT) { // include the possible negative sign @@ -2948,8 +2948,8 @@ void resize_output_buffer_if_necessary( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* // A zval string len doesn't include the null. This calculates the length it should be // regardless of whether the ODBC type contains the NULL or not. - // initialize the newly allocated space - char *p = ZSTR_VAL(param_z_string); + // initialize the newly allocated space + char *p = ZSTR_VAL(param_z_string); p = p + original_len; memset(p, '\0', expected_len - original_len); ZVAL_NEW_STR(param_z, param_z_string); diff --git a/source/sqlsrv/stmt.cpp b/source/sqlsrv/stmt.cpp index b67af51a7..ff72a6fa9 100644 --- a/source/sqlsrv/stmt.cpp +++ b/source/sqlsrv/stmt.cpp @@ -7,13 +7,13 @@ // Copyright(c) Microsoft Corporation // All rights reserved. // MIT License -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""), -// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""), +// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, // and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //--------------------------------------------------------------------------------------------------------------------------------- @@ -85,11 +85,6 @@ const char* NULLABLE = "Nullable"; } -// warning message printed when a parameter variable is not passed by reference -const char SS_SQLSRV_WARNING_PARAM_VAR_NOT_REF[] = "Variable parameter %d not passed by reference (prefaced with an &). " - "Variable parameters passed to sqlsrv_prepare or sqlsrv_query should be passed by reference, not by value. " - "For more information, see sqlsrv_prepare or sqlsrv_query in the API Reference section of the product documentation."; - /* internal functions */ void convert_to_zval( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSRV_PHPTYPE sqlsrv_php_type, _In_opt_ void* in_val, _In_ SQLLEN field_len, _Inout_ zval& out_zval ); @@ -103,7 +98,7 @@ void determine_stmt_has_rows( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC ); bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type ); bool is_valid_sqlsrv_sqltype( _In_ sqlsrv_sqltype type ); void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ulong index, _Out_ SQLSMALLINT& direction, - _Out_ SQLSRV_PHPTYPE& php_out_type, _Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type, + _Out_ SQLSRV_PHPTYPE& php_out_type, _Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type, _Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC ); void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ); void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ); @@ -156,7 +151,7 @@ ss_sqlsrv_stmt::~ss_sqlsrv_stmt( void ) if( fetch_field_names != NULL ) { for( int i=0; i < fetch_fields_count; ++i ) { - + sqlsrv_free( fetch_field_names[i].name ); } sqlsrv_free( fetch_field_names ); @@ -165,16 +160,16 @@ ss_sqlsrv_stmt::~ss_sqlsrv_stmt( void ) zval_ptr_dtor( params_z ); sqlsrv_free(params_z); } -} +} // to be called whenever a new result set is created, such as after an // execute or next_result. Resets the state variables and calls the subclass. -void ss_sqlsrv_stmt::new_result_set( TSRMLS_D ) +void ss_sqlsrv_stmt::new_result_set( TSRMLS_D ) { if( fetch_field_names != NULL ) { for( int i=0; i < fetch_fields_count; ++i ) { - + sqlsrv_free( fetch_field_names[i].name ); } sqlsrv_free( fetch_field_names ); @@ -185,7 +180,7 @@ void ss_sqlsrv_stmt::new_result_set( TSRMLS_D ) sqlsrv_stmt::new_result_set( TSRMLS_C ); } -// Returns a php type for a given sql type. Also sets the encoding wherever applicable. +// Returns a php type for a given sql type. Also sets the encoding wherever applicable. sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream ) { sqlsrv_phptype ss_phptype; @@ -299,13 +294,13 @@ void ss_sqlsrv_stmt::set_query_timeout() } // sqlsrv_execute( resource $stmt ) -// +// // Executes a previously prepared statement. See sqlsrv_prepare for information // on preparing a statement for execution. -// +// // This function is ideal for executing a prepared statement multiple times with // different parameter values. See the MSDN documentation -// +// // Parameters // $stmt: A resource specifying the statement to be executed. For more // information about how to create a statement resource, see sqlsrv_prepare. @@ -316,12 +311,12 @@ void ss_sqlsrv_stmt::set_query_timeout() PHP_FUNCTION( sqlsrv_execute ) { LOG_FUNCTION( "sqlsrv_execute" ); - + ss_sqlsrv_stmt* stmt = NULL; - + try { - PROCESS_PARAMS( stmt, "r", _FN_, 0 ); + PROCESS_PARAMS( stmt, "r", _FN_, 0 ); CHECK_CUSTOM_ERROR(( !stmt->prepared ), stmt, SS_SQLSRV_ERROR_STATEMENT_NOT_PREPARED ) { throw ss::SSException(); } @@ -340,11 +335,11 @@ PHP_FUNCTION( sqlsrv_execute ) bind_params( stmt TSRMLS_CC ); core_sqlsrv_execute( stmt TSRMLS_CC ); - + RETURN_TRUE; } catch( core::CoreException& ) { - + RETURN_FALSE; } catch( ... ) { @@ -382,8 +377,8 @@ PHP_FUNCTION( sqlsrv_fetch ) PROCESS_PARAMS( stmt, "r|ll", _FN_, 2, &fetch_style, &fetch_offset ); try { - - CHECK_CUSTOM_ERROR(( fetch_style < SQL_FETCH_NEXT || fetch_style > SQL_FETCH_RELATIVE ), stmt, + + CHECK_CUSTOM_ERROR(( fetch_style < SQL_FETCH_NEXT || fetch_style > SQL_FETCH_RELATIVE ), stmt, SS_SQLSRV_ERROR_INVALID_FETCH_STYLE ) { throw ss::SSException(); } @@ -406,7 +401,7 @@ PHP_FUNCTION( sqlsrv_fetch ) } // sqlsrv_fetch_array( resource $stmt [, int $fetchType] ) -// +// // Retrieves the next row of data as an array. // // Parameters @@ -425,7 +420,7 @@ PHP_FUNCTION( sqlsrv_fetch ) PHP_FUNCTION( sqlsrv_fetch_array ) { LOG_FUNCTION( "sqlsrv_fetch_array" ); - + ss_sqlsrv_stmt* stmt = NULL; zend_long fetch_type = SQLSRV_FETCH_BOTH; // default value for parameter if one isn't supplied zend_long fetch_style = SQL_FETCH_NEXT; // default value for parameter if one isn't supplied @@ -436,13 +431,13 @@ PHP_FUNCTION( sqlsrv_fetch_array ) PROCESS_PARAMS( stmt, "r|lll", _FN_, 3, &fetch_type, &fetch_style, &fetch_offset ); try { - - CHECK_CUSTOM_ERROR(( fetch_type < MIN_SQLSRV_FETCH || fetch_type > MAX_SQLSRV_FETCH ), stmt, + + CHECK_CUSTOM_ERROR(( fetch_type < MIN_SQLSRV_FETCH || fetch_type > MAX_SQLSRV_FETCH ), stmt, SS_SQLSRV_ERROR_INVALID_FETCH_TYPE ) { throw ss::SSException(); } - CHECK_CUSTOM_ERROR(( fetch_style < SQL_FETCH_NEXT || fetch_style > SQL_FETCH_RELATIVE ), stmt, + CHECK_CUSTOM_ERROR(( fetch_style < SQL_FETCH_NEXT || fetch_style > SQL_FETCH_RELATIVE ), stmt, SS_SQLSRV_ERROR_INVALID_FETCH_STYLE ) { throw ss::SSException(); } @@ -467,7 +462,7 @@ PHP_FUNCTION( sqlsrv_fetch_array ) } // sqlsrv_field_metadata( resource $stmt ) -// +// // Retrieves metadata for the fields of a prepared statement. For information // about preparing a statement, see sqlsrv_query or sqlsrv_prepare. Note that // sqlsrv_field_metadata can be called on any prepared statement, pre- or @@ -477,7 +472,7 @@ PHP_FUNCTION( sqlsrv_fetch_array ) // $stmt: A statement resource for which field metadata is sought. // // Return Value -// retrieve an array of metadata for the current result set on a statement. Each element of the +// retrieve an array of metadata for the current result set on a statement. Each element of the // array is a sub-array containing 5 elements accessed by key: // name - name of the field. // type - integer of the type. Can be compared against the SQLSRV_SQLTYPE constants. @@ -507,10 +502,10 @@ PHP_FUNCTION( sqlsrv_field_metadata ) zval result_meta_data; ZVAL_UNDEF( &result_meta_data ); core::sqlsrv_array_init( *stmt, &result_meta_data TSRMLS_CC ); - + for( SQLSMALLINT f = 0; f < num_cols; ++f ) { field_meta_data* core_meta_data = stmt->current_meta_data[f]; - + // initialize the array zval field_array; ZVAL_UNDEF( &field_array ); @@ -555,7 +550,7 @@ PHP_FUNCTION( sqlsrv_field_metadata ) // add the nullability to the array core::sqlsrv_add_assoc_long( *stmt, &field_array, FieldMetaData::NULLABLE, core_meta_data->field_is_nullable TSRMLS_CC ); - + if (stmt->data_classification) { data_classification::fill_column_sensitivity_array(stmt, f, &field_array TSRMLS_CC); } @@ -580,7 +575,7 @@ PHP_FUNCTION( sqlsrv_field_metadata ) // sqlsrv_next_result( resource $stmt ) -// +// // Makes the next result (result set, row count, or output parameter) of the // specified statement active. The first (or only) result returned by a batch // query or stored procedure is active without a call to sqlsrv_next_result. @@ -619,7 +614,7 @@ PHP_FUNCTION( sqlsrv_next_result ) RETURN_TRUE; } catch( core::CoreException& ) { - + RETURN_FALSE; } catch( ... ) { @@ -708,7 +703,7 @@ PHP_FUNCTION( sqlsrv_num_rows ) // make sure that the statement is scrollable and the cursor is not dynamic. // if the cursor is dynamic, then the number of rows returned is always -1. - CHECK_CUSTOM_ERROR( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY || stmt->cursor_type == SQL_CURSOR_DYNAMIC, stmt, + CHECK_CUSTOM_ERROR( stmt->cursor_type == SQL_CURSOR_FORWARD_ONLY || stmt->cursor_type == SQL_CURSOR_DYNAMIC, stmt, SS_SQLSRV_ERROR_STATEMENT_NOT_SCROLLABLE ) { throw ss::SSException(); } @@ -750,10 +745,10 @@ PHP_FUNCTION( sqlsrv_num_fields ) PROCESS_PARAMS( stmt, "r", _FN_, 0 ); try { - + // retrieve the number of columns from ODBC fields = core::SQLNumResultCols( stmt TSRMLS_CC ); - + RETURN_LONG( fields ); } @@ -768,7 +763,7 @@ PHP_FUNCTION( sqlsrv_num_fields ) } // sqlsrv_fetch_object( resource $stmt [, string $className [, array $ctorParams]]) -// +// // Retrieves the next row of data as a PHP object. // // Parameters @@ -801,7 +796,7 @@ PHP_FUNCTION( sqlsrv_num_fields ) // object and the result set value is applied to the property. For more // information about calling sqlsrv_fetch_object with the $className parameter, // see How to: Retrieve Data as an Object (Microsoft Drivers for PHP for SQL Server). -// +// // If a field with no name is returned, sqlsrv_fetch_object will discard the // field value and issue a warning. @@ -824,19 +819,19 @@ PHP_FUNCTION( sqlsrv_fetch_object ) // retrieve the statement resource and optional fetch type (see enum SQLSRV_FETCH_TYPE), // fetch style (see SQLSRV_SCROLL_* constants) and fetch offset - // we also use z! instead of s and a so that null may be passed in as valid values for + // we also use z! instead of s and a so that null may be passed in as valid values for // the class name and ctor params PROCESS_PARAMS( stmt, "r|z!z!ll", _FN_, 4, &class_name_z, &ctor_params_z, &fetch_style, &fetch_offset ); - + try { - - CHECK_CUSTOM_ERROR(( fetch_style < SQL_FETCH_NEXT || fetch_style > SQL_FETCH_RELATIVE ), stmt, + + CHECK_CUSTOM_ERROR(( fetch_style < SQL_FETCH_NEXT || fetch_style > SQL_FETCH_RELATIVE ), stmt, SS_SQLSRV_ERROR_INVALID_FETCH_STYLE ) { throw ss::SSException(); } if( class_name_z ) { - + CHECK_CUSTOM_ERROR(( Z_TYPE_P( class_name_z ) != IS_STRING ), stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) { throw ss::SSException(); } @@ -847,7 +842,7 @@ PHP_FUNCTION( sqlsrv_fetch_object ) if( ctor_params_z && Z_TYPE_P( ctor_params_z ) != IS_ARRAY ) { THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ); } - + // fetch the data bool result = core_sqlsrv_fetch( stmt, static_cast(fetch_style), fetch_offset TSRMLS_CC ); if( !result ) { @@ -855,8 +850,8 @@ PHP_FUNCTION( sqlsrv_fetch_object ) } fetch_fields_common( stmt, SQLSRV_FETCH_ASSOC, retval_z, false /*allow_empty_field_names*/ TSRMLS_CC ); - properties_ht = Z_ARRVAL( retval_z ); - + properties_ht = Z_ARRVAL( retval_z ); + // find the zend_class_entry of the class the user requested (stdClass by default) for use below zend_class_entry* class_entry = NULL; zend_string* class_name_str_z = zend_string_init( class_name, class_name_len, 0 ); @@ -885,13 +880,13 @@ PHP_FUNCTION( sqlsrv_fetch_object ) // find and call the object's constructor // The header files (zend.h and zend_API.h) declare - // these functions and structures, so by working with those, we were able to + // these functions and structures, so by working with those, we were able to // develop this as a suitable snippet for calling constructors. Some observations: // params must be an array of zval**, not a zval** to an array as we originally // thought. Also, a constructor doesn't show up in the function table, but // is put into the "magic methods" section of the class entry. - // - // The default values of the fci and fcic structures were determined by + // + // The default values of the fci and fcic structures were determined by // calling zend_fcall_info_init with a test callable. // if there is a constructor (e.g., stdClass doesn't have one) @@ -919,7 +914,7 @@ PHP_FUNCTION( sqlsrv_fetch_object ) i++; } ZEND_HASH_FOREACH_END(); } //if( !Z_ISUNDEF( ctor_params_z )) - + // call the constructor function itself. zend_fcall_info fci; zend_fcall_info_cache fcic; @@ -933,7 +928,7 @@ PHP_FUNCTION( sqlsrv_fetch_object ) fci.retval = &ctor_retval_z; fci.param_count = num_params; fci.params = params_m; // purposefully not transferred since ownership isn't actually transferred. - + fci.object = Z_OBJ_P( &retval_z ); memset( &fcic, 0, sizeof( fcic )); @@ -950,7 +945,7 @@ PHP_FUNCTION( sqlsrv_fetch_object ) throw ss::SSException(); } - } //if( class_entry->constructor ) + } //if( class_entry->constructor ) RETURN_ZVAL( &retval_z, 1, 1 ); } @@ -985,7 +980,7 @@ PHP_FUNCTION( sqlsrv_fetch_object ) // for using a function like this: // 1) To know if there are any actual rows, not just a result set (empty or not). Use sqlsrv_has_rows to determine this. // The guarantee is that if sqlsrv_has_rows returns true immediately after a query, that sqlsrv_fetch_* will return at least -// one row of data. +// one row of data. // 2) To know if there is any sort of result set, empty or not, that has to be bypassed to get to something else, such as // output parameters being returned. Use sqlsrv_num_fields > 0 to check if there is any result set that must be bypassed // until sqlsrv_fetch returns NULL. @@ -1048,8 +1043,8 @@ PHP_FUNCTION( sqlsrv_has_rows ) PHP_FUNCTION( sqlsrv_send_stream_data ) { sqlsrv_stmt* stmt = NULL; - - LOG_FUNCTION( "sqlsrv_send_stream_data" ); + + LOG_FUNCTION( "sqlsrv_send_stream_data" ); // get the statement resource that we've bound streams to PROCESS_PARAMS( stmt, "r", _FN_, 0 ); @@ -1079,14 +1074,14 @@ PHP_FUNCTION( sqlsrv_send_stream_data ) RETURN_FALSE; } catch( ... ) { - + DIE( "sqlsrv_send_stream_data: Unknown exception caught." ); } } // sqlsrv_get_field( resource $stmt, int $fieldIndex [, int $getAsType] ) -// +// // Retrieves data from the specified field of the current row. Field data must // be accessed in order. For example, data from the first field cannot be // accessed after data from the second field has been accessed. @@ -1111,7 +1106,7 @@ PHP_FUNCTION( sqlsrv_send_stream_data ) PHP_FUNCTION( sqlsrv_get_field ) { LOG_FUNCTION( "sqlsrv_get_field" ); - + ss_sqlsrv_stmt* stmt = NULL; sqlsrv_phptype sqlsrv_php_type; sqlsrv_php_type.typeinfo.type = SQLSRV_PHPTYPE_INVALID; @@ -1121,7 +1116,7 @@ PHP_FUNCTION( sqlsrv_get_field ) SQLLEN field_len = -1; zval retval_z; ZVAL_UNDEF(&retval_z); - + // get the statement, the field index and the optional type PROCESS_PARAMS( stmt, "rl|l", _FN_, 2, &field_index, &sqlsrv_php_type ); @@ -1136,7 +1131,7 @@ PHP_FUNCTION( sqlsrv_get_field ) core_sqlsrv_get_field( stmt, static_cast( field_index ), sqlsrv_php_type, false, field_value, &field_len, false/*cache_field*/, &sqlsrv_php_type_out TSRMLS_CC ); - convert_to_zval( stmt, sqlsrv_php_type_out, field_value, field_len, retval_z ); + convert_to_zval( stmt, sqlsrv_php_type_out, field_value, field_len, retval_z ); sqlsrv_free( field_value ); RETURN_ZVAL( &retval_z, 1, 1 ); } @@ -1232,9 +1227,9 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC ) stmt->executed = false; zval* params_z = stmt->params_z; - + HashTable* params_ht = Z_ARRVAL_P( params_z ); - + zend_ulong index = -1; zend_string *key = NULL; zval* param_z = NULL; @@ -1256,7 +1251,7 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC ) CHECK_CUSTOM_ERROR( type != HASH_KEY_IS_LONG, stmt, SS_SQLSRV_ERROR_PARAM_INVALID_INDEX ) { throw ss::SSException(); } - + // if it's a parameter array if( Z_TYPE_P( param_z ) == IS_ARRAY ) { @@ -1279,7 +1274,7 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC ) } // bind the parameter SQLSRV_ASSERT( value_z != NULL, "bind_params: value_z is null." ); - core_sqlsrv_bind_param( stmt, static_cast( index ), direction, value_z, php_out_type, encoding, sql_type, column_size, + core_sqlsrv_bind_param( stmt, static_cast( index ), direction, value_z, php_out_type, encoding, sql_type, column_size, decimal_digits TSRMLS_CC ); } ZEND_HASH_FOREACH_END(); @@ -1294,7 +1289,7 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC ) } // sqlsrv_cancel( resource $stmt ) -// +// // Cancels a statement. This means that any pending results for the statement // are discarded. After this function is called, the statement can be // re-executed if it was prepared with sqlsrv_prepare. Calling this function is @@ -1313,12 +1308,12 @@ PHP_FUNCTION( sqlsrv_cancel ) LOG_FUNCTION( "sqlsrv_cancel" ); ss_sqlsrv_stmt* stmt = NULL; PROCESS_PARAMS( stmt, "r", _FN_, 0 ); - + try { // close the stream to release the resource close_active_stream( stmt TSRMLS_CC ); - + SQLRETURN r = SQLCancel( stmt->handle() ); CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw ss::SSException(); @@ -1360,7 +1355,7 @@ void __cdecl sqlsrv_stmt_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC ) // cannot be used again after this function has been called. // // Parameters -// $stmt: The statement to be closed. +// $stmt: The statement to be closed. // // Return Value // The Boolean value true unless the function is called with an invalid @@ -1384,7 +1379,7 @@ PHP_FUNCTION( sqlsrv_free_stmt ) sqlsrv_context_auto_ptr error_ctx; reset_errors( TSRMLS_C ); - + try { // dummy context to pass to the error handler @@ -1393,14 +1388,14 @@ PHP_FUNCTION( sqlsrv_free_stmt ) // take only the statement resource if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "r", &stmt_r ) == FAILURE ) { - + // Check if it was a zval int zr = zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "z", &stmt_r ); CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) { throw ss::SSException(); - } - + } + if( Z_TYPE_P( stmt_r ) == IS_NULL ) { RETURN_TRUE; @@ -1413,19 +1408,19 @@ PHP_FUNCTION( sqlsrv_free_stmt ) // verify the resource so we know we're deleting a statement stmt = static_cast(zend_fetch_resource_ex(stmt_r TSRMLS_CC, ss_sqlsrv_stmt::resource_name, ss_sqlsrv_stmt::descriptor)); - + // if sqlsrv_free_stmt was called on an already closed statment then we just return success. // zend_list_close sets the type of the closed statment to -1. SQLSRV_ASSERT( stmt_r != NULL, "sqlsrv_free_stmt: stmt_r is null." ); if ( Z_RES_TYPE_P( stmt_r ) == RSRC_INVALID_TYPE ) { RETURN_TRUE; } - + if( stmt == NULL ) { THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ); } - + // delete the resource from Zend's master list, which will trigger the statement's destructor if( zend_list_close( Z_RES_P(stmt_r) ) == FAILURE ) { LOG( SEV_ERROR, "Failed to remove stmt resource %1!d!", Z_RES_P( stmt_r )->handle); @@ -1436,17 +1431,17 @@ PHP_FUNCTION( sqlsrv_free_stmt ) // zend_list_close only destroy the resource pointed to by Z_RES_P( stmt_r ), not the zend_resource itself Z_TRY_DELREF_P(stmt_r); ZVAL_NULL( stmt_r ); - + RETURN_TRUE; - + } catch( core::CoreException& ) { - + RETURN_FALSE; } - + catch( ... ) { - + DIE( "sqlsrv_free_stmt: Unknown exception caught." ); } } @@ -1456,16 +1451,16 @@ void stmt_option_ss_scrollable:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_opt CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_STRING ), stmt, SQLSRV_ERROR_INVALID_OPTION_SCROLLABLE ) { throw ss::SSException(); } - + const char* scroll_type = Z_STRVAL_P( value_z ); unsigned long cursor_type = -1; - + // find which cursor type they would like and set the ODBC statement attribute as such - if( !stricmp( scroll_type, SSCursorTypes::QUERY_OPTION_SCROLLABLE_STATIC )) { + if( !stricmp( scroll_type, SSCursorTypes::QUERY_OPTION_SCROLLABLE_STATIC )) { cursor_type = SQL_CURSOR_STATIC; } - + else if( !stricmp( scroll_type, SSCursorTypes::QUERY_OPTION_SCROLLABLE_DYNAMIC )) { cursor_type = SQL_CURSOR_DYNAMIC; @@ -1477,12 +1472,12 @@ void stmt_option_ss_scrollable:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_opt } else if( !stricmp( scroll_type, SSCursorTypes::QUERY_OPTION_SCROLLABLE_FORWARD )) { - + cursor_type = SQL_CURSOR_FORWARD_ONLY; } else if( !stricmp( scroll_type, SSCursorTypes::QUERY_OPTION_SCROLLABLE_BUFFERED )) { - + cursor_type = SQLSRV_CURSOR_BUFFERED; } @@ -1553,7 +1548,7 @@ void convert_to_zval( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSRV_PHPTYPE sqlsrv_php_ // put in the column size and scale/decimal digits of the sql server type // these values are taken from the MSDN page at http://msdn2.microsoft.com/en-us/library/ms711786(VS.85).aspx // for SQL_VARBINARY, SQL_VARCHAR, and SQL_WLONGVARCHAR types, see https://msdn.microsoft.com/en-CA/library/ms187993.aspx -bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, _In_ sqlsrv_sqltype sqlsrv_type, _Inout_ SQLULEN* column_size, +bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, _In_ sqlsrv_sqltype sqlsrv_type, _Inout_ SQLULEN* column_size, _Out_ SQLSMALLINT* decimal_digits ) { *decimal_digits = 0; @@ -1608,7 +1603,7 @@ bool determine_column_size_or_precision( sqlsrv_stmt const* stmt, _In_ sqlsrv_sq } break; case SQL_WCHAR: - case SQL_WVARCHAR: + case SQL_WVARCHAR: *column_size = sqlsrv_type.typeinfo.size; if( *column_size == SQLSRV_SIZE_MAX_TYPE ) { *column_size = SQL_SS_LENGTH_UNLIMITED; @@ -1731,7 +1726,7 @@ sqlsrv_phptype determine_sqlsrv_php_type( _In_ ss_sqlsrv_stmt const* stmt, _In_ case SQL_SS_TIME2: case SQL_TYPE_TIMESTAMP: { - if (stmt->date_as_string) { + if (stmt->date_as_string) { sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING; sqlsrv_phptype.typeinfo.encoding = stmt->encoding(); } @@ -1749,7 +1744,7 @@ sqlsrv_phptype determine_sqlsrv_php_type( _In_ ss_sqlsrv_stmt const* stmt, _In_ if( sqlsrv_phptype.typeinfo.encoding == SQLSRV_ENCODING_DEFAULT ) { sqlsrv_phptype.typeinfo.encoding = stmt->conn->encoding(); } - + return sqlsrv_phptype; } @@ -1793,9 +1788,9 @@ void determine_stmt_has_rows( _Inout_ ss_sqlsrv_stmt* stmt TSRMLS_DC ) } } else { - + // otherwise, we fetch the first row, but record that we did. sqlsrv_fetch checks this - // flag and simply skips the first fetch, knowing it was already done. It records its own + // flag and simply skips the first fetch, knowing it was already done. It records its own // flags to know if it should fetch on subsequent calls. r = core::SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 TSRMLS_CC ); @@ -1812,7 +1807,7 @@ SQLSMALLINT get_resultset_meta_data(_Inout_ sqlsrv_stmt * stmt) { // get the numer of columns in the result set SQLSMALLINT num_cols = -1; - + num_cols = stmt->current_meta_data.size(); bool getMetaData = false; @@ -1887,8 +1882,8 @@ void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_typ throw ss::SSException(); } #else - array_init(&fields); -#endif + array_init(&fields); +#endif for( int i = 0; i < num_cols; ++i ) { SQLLEN field_len = -1; @@ -1924,7 +1919,7 @@ void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_typ } } //only addref when the fetch_type is BOTH because this is the only case when fields(hashtable) - //has 2 elements pointing to field. Do not addref if the type is NUMERIC or ASSOC because + //has 2 elements pointing to field. Do not addref if the type is NUMERIC or ASSOC because //fields now only has 1 element pointing to field and we want the ref count to be only 1 if (fetch_type == SQLSRV_FETCH_BOTH) { Z_TRY_ADDREF(field); @@ -1934,7 +1929,7 @@ void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_typ } void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, zend_ulong index, _Out_ SQLSMALLINT& direction, - _Out_ SQLSRV_PHPTYPE& php_out_type, _Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type, + _Out_ SQLSRV_PHPTYPE& php_out_type, _Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type, _Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits TSRMLS_DC ) { @@ -1954,7 +1949,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, // handle the array parameters that contain the value/var, direction, php_type, sql_type zend_hash_internal_pointer_reset_ex( param_ht, &pos ); - if( zend_hash_has_more_elements_ex( param_ht, &pos ) == FAILURE || + if( zend_hash_has_more_elements_ex( param_ht, &pos ) == FAILURE || (var_or_val = zend_hash_get_current_data_ex(param_ht, &pos)) == NULL) { THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1 ); @@ -1977,7 +1972,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, CHECK_CUSTOM_ERROR( !Z_ISREF_P( var_or_val ) && ( direction == SQL_PARAM_OUTPUT || direction == SQL_PARAM_INPUT_OUTPUT ), stmt, SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF, index + 1 ) { throw ss::SSException(); } - + } else { direction = SQL_PARAM_INPUT; @@ -1986,7 +1981,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, // extract the php type and encoding from the 3rd parameter if ( zend_hash_move_forward_ex( param_ht, &pos ) == SUCCESS && ( temp = zend_hash_get_current_data_ex( param_ht, &pos )) != NULL && Z_TYPE_P( temp ) != IS_NULL ) { - + php_type_param_was_null = false; sqlsrv_phptype sqlsrv_phptype; @@ -1997,7 +1992,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, sqlsrv_phptype.value = Z_LVAL_P( temp ); - CHECK_CUSTOM_ERROR( !is_valid_sqlsrv_phptype( sqlsrv_phptype ), stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, + CHECK_CUSTOM_ERROR( !is_valid_sqlsrv_phptype( sqlsrv_phptype ), stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, index + 1 ) { throw ss::SSException(); @@ -2005,7 +2000,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, php_out_type = static_cast( sqlsrv_phptype.typeinfo.type ); encoding = ( SQLSRV_ENCODING ) sqlsrv_phptype.typeinfo.encoding; - // if the call has a SQLSRV_PHPTYPE_STRING/STREAM('default'), then the stream is in the encoding established + // if the call has a SQLSRV_PHPTYPE_STRING/STREAM('default'), then the stream is in the encoding established // by the connection if( encoding == SQLSRV_ENCODING_DEFAULT ) { encoding = stmt->conn->encoding(); @@ -2013,7 +2008,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, } // set default for php type and encoding if not supplied else { - + php_type_param_was_null = true; if ( Z_ISREF_P( var_or_val )){ @@ -2025,7 +2020,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, encoding = stmt->encoding(); if( encoding == SQLSRV_ENCODING_DEFAULT ) { encoding = stmt->conn->encoding(); - } + } } // get the server type, column size/precision and the decimal digits if provided @@ -2042,12 +2037,12 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, sqlsrv_sql_type.value = Z_LVAL_P( temp ); // since the user supplied this type, make sure it's valid - CHECK_CUSTOM_ERROR( !is_valid_sqlsrv_sqltype( sqlsrv_sql_type ), stmt, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, + CHECK_CUSTOM_ERROR( !is_valid_sqlsrv_sqltype( sqlsrv_sql_type ), stmt, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, index + 1 ) { throw ss::SSException(); - } - + } + bool size_okay = determine_column_size_or_precision( stmt, sqlsrv_sql_type, &column_size, &decimal_digits ); CHECK_CUSTOM_ERROR( !size_okay, stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_PRECISION, index + 1 ) { @@ -2076,7 +2071,7 @@ void parse_param_array( _Inout_ ss_sqlsrv_stmt* stmt, _Inout_ zval* param_array, sqlsrv_phptype sqlsrv_phptype; sqlsrv_phptype = determine_sqlsrv_php_type( stmt, sql_type, (SQLUINTEGER)column_size, true ); - + // we DIE here since everything should have been validated already and to return the user an error // for our own logic error would be confusing/misleading. SQLSRV_ASSERT( sqlsrv_phptype.typeinfo.type != PHPTYPE_INVALID, "An invalid php type was returned with (supposed) " @@ -2121,7 +2116,7 @@ bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type ) case SQLSRV_PHPTYPE_STRING: case SQLSRV_PHPTYPE_STREAM: { - if( type.typeinfo.encoding == SQLSRV_ENCODING_BINARY || type.typeinfo.encoding == SQLSRV_ENCODING_CHAR + if( type.typeinfo.encoding == SQLSRV_ENCODING_BINARY || type.typeinfo.encoding == SQLSRV_ENCODING_CHAR || type.typeinfo.encoding == CP_UTF8 || type.typeinfo.encoding == SQLSRV_ENCODING_DEFAULT ) { return true; } @@ -2152,7 +2147,7 @@ bool is_valid_sqlsrv_sqltype( _In_ sqlsrv_sqltype sql_type ) case SQL_BINARY: case SQL_CHAR: case SQL_WCHAR: - case SQL_WVARCHAR: + case SQL_WVARCHAR: case SQL_VARBINARY: case SQL_VARCHAR: case SQL_DECIMAL: @@ -2202,7 +2197,7 @@ void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) int size = 0; if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &size_p, &size_len ) == FAILURE ) { - + return; } if (size_p) { @@ -2226,7 +2221,7 @@ void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) } int max_size = SQL_SERVER_MAX_FIELD_SIZE; - // size is actually the number of characters, not the number of bytes, so if they ask for a + // size is actually the number of characters, not the number of bytes, so if they ask for a // 2 byte per character type, then we half the maximum size allowed. if( type == SQL_WVARCHAR || type == SQL_WCHAR ) { max_size >>= 1; @@ -2236,7 +2231,7 @@ void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) LOG( SEV_ERROR, "invalid size. size must be > 0 and <= %1!d! characters or 'max'", max_size ); size = SQLSRV_INVALID_SIZE; } - + sqlsrv_sqltype sql_type; sql_type.typeinfo.type = type; sql_type.typeinfo.size = size; @@ -2253,15 +2248,15 @@ void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) zend_long scale = SQLSRV_INVALID_SCALE; if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "|ll", &prec, &scale ) == FAILURE ) { - + return; } - + if( prec > SQL_SERVER_MAX_PRECISION ) { LOG( SEV_ERROR, "Invalid precision. Precision can't be > 38" ); prec = SQLSRV_INVALID_PRECISION; } - + if( prec < 0 ) { LOG( SEV_ERROR, "Invalid precision. Precision can't be negative" ); prec = SQLSRV_INVALID_PRECISION; @@ -2285,11 +2280,11 @@ void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) { - SQLSRV_ASSERT(( type == SQLSRV_PHPTYPE_STREAM || type == SQLSRV_PHPTYPE_STRING ), "type_and_encoding: Invalid type passed." ); + SQLSRV_ASSERT(( type == SQLSRV_PHPTYPE_STREAM || type == SQLSRV_PHPTYPE_STRING ), "type_and_encoding: Invalid type passed." ); char* encoding_param; size_t encoding_param_len = 0; - + // set the default encoding values to invalid so that // if the encoding isn't validated, it will return the invalid setting. sqlsrv_phptype sqlsrv_php_type; @@ -2297,7 +2292,7 @@ void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, _In_ int type ) sqlsrv_php_type.typeinfo.encoding = SQLSRV_ENCODING_INVALID; if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoding_param, &encoding_param_len ) == FAILURE ) { - + ZVAL_LONG( return_value, sqlsrv_php_type.value ); }