4.1.1. release

This commit is contained in:
Meet Bhagdev 2016-08-24 14:28:20 -07:00
parent 5ddaaeb728
commit 13d39ebefd
34 changed files with 319 additions and 193 deletions

View file

@ -10,50 +10,24 @@ The Microsoft Drivers for PHP for SQL Server Team
##Announcements
June 30, 2016 (4.0.6): The quality of SQLSRV and PDO_SQLSRV is improved and includes some memory leak fixes:
- Fixed a heap corruption when binding parameters in a prepare statement with error
- Fixed leaks in SQLSRV streams and output parameters handling
- Fixed leaks in SQLSRV fetch object
- Fixed leaks in SQLSRV binding object parameters
- Fixed leaks in SQLSRV buffered result set
- Fixed leaks in SQLSRV getting datetime and stream fields
- Fixed leaks in PDO_SQLSRV field cache
- Fixed leaks in PDO_SQLSRV construct when connecting with error
- Fixed leaks in PDO_SQLSRV exception handling
August 22, 2016 (4.1.1): Updated Windows drivers built and compiled with PHP 7.0.9 are available and include a couple of bug fixes:
June 13, 2016 (4.0.5): The quality of SQLSRV and PDO_SQLSRV is improved and includes some bug fixes:
- Added ability to connect to Microsoft ODBC Driver 13.
- Fixed some memory leaks in data retrieval.
- Fixed issue with error handling in bound stream parameters when send_stream_at_exec option is set to false.
- Fixed issue with when connecting twice when Sqlsrv_errors configured to only WARNINGS.
- Fixed issue with double and string as input-output parameters in PDO_SQLSRV driver.
- Fixed a heap corruption in PDO_SQLSRV connection.
- Fixed issue with storing integers in varchar field.
- Fixed issue with invalid connection handler if one connection fails.
- Fixed crash when emulate prepare is on.
May 3, 2016 (4.0.4): The quality of SQLSRV and PDO_SQLSRV is improved and includes some bug fixes:
- Fixed retrieving stream data and metadata.
- Fixed issue with bind stream parameters.
- Fixed issue with retrieval in error case when trying to retrieve a non-streamble data type with SQLSRV_SQLTYPE_STREAM option
- Fixed issue with querying after another query with empty array of parameters.
- Fixed issue with retrieving integers as output parameter in SQLSRV 64-bit.
- Fixed issue scrollable statement option in SQLSRV_PDO 64-bit.
- Improved handling closed connection and statement resources.
- Fixed issue with binding bit parameter.
- Fix for The $driver_options (for specifying encoding) is included in PDOStatement::bindParam is included in PHP 7.0.6 release.
April 12, 2016 (4.0.3): The PDO_SQLSRV driver (32-bit and 64-bit) is now available. For the SQLSRV driver, we also have a few bug fixes to share:
- Fixed ability to fetch a user defined object into a class
- Fixed issue with re-preparing the same statement with referenced datetime parameters
- Fixed issue with binding output parameters with php type string with binary and char encodings and sql types SQLSRV_SQLTYPE_NCHAR and SQLSRV_SQLTYPE_NVARCHAR
March 15, 2016 (4.0.2): 64-bit support is now available for the SQLSRV driver. We also have some additional minor improvements to share:
- Fixed the ability to retrieve strings as an output parameter
- Fixed a number of memory leaks in initialization
Feb 23, 2016 (4.0.1): Thanks to the communitys input, we have mostly been focusing on making updates to support native 64-bit and the PDO driver. We will be sharing these updates in the coming weeks once we have something functional. In the meantime, we have a couple of minor updates to the SQLSRV driver to share:
- Fixed the ability to bind parameters with datetime types
- Fixed output and bidirectional (input/output) parameters. Note to users: we determined that output and bidirectional parameters now need to be passed in by reference (i.e. &$var) so that they can be updated with the output data and added an error check for these cases.
- Updated refcounting to avoid unnecessary reference counting for scalar values
July 28, 2016 (4.1.0): Thanks to the community's input, this release expands drivers functionalities and also includes some bug fixes:
- `SQLSRV_ATTR_FETCHES_NUMERIC_TYPE` connection attribute flag is added to PDO_SQLSRV driver to handle numeric fetches from columns with numeric Sql types (only bit, integer, smallint, tinyint, float and real). This flag can be turned on by setting its value in `PDO::setAttribute` to `true`, For example,
`$conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE,true);`
If `SQLSRV_ATTR_FETCHES_NUMERIC_TYPE` is set to `true` the results from an integer column will be represented as an `int`, likewise, Sql types float and real will be represented as `float`.
Note for exceptions:
- When connection option flag `ATTR_STRINGIFY_FETCHES` is on, even when `SQLSRV_ATTR_FETCHES_NUMERIC_TYPE` is on, the return value will still be string.
- When the returned PDO type in bind column is `PDO_PARAM_INT`, the return value from a integer column will be int even if `SQLSRV_ATTR_FETCHES_NUMERIC_TYPE` is off.
- Fixed float truncation when using buffered query.
- Fixed handling of Unicode strings and binary when emulate prepare is on in `PDOStatement::bindParam`. To bind a unicode string, `PDO::SQLSRV_ENCODING_UTF8` should be set using `$driverOption`, and to bind a string to column of Sql type binary, `PDO::SQLSRV_ENCODING_BINARY` should be set.
- Fixed string truncation in bind output parameters when the size is not set and the length of initialized variable is less than the output.
- Fixed bind string parameters as bidirectional parameters (`PDO::PARAM_INPUT_OUTPUT `) in PDO_SQLSRV driver. Note for output or bidirectional parameters, `PDOStatement::closeCursor` should be called to get the output value.
## Build
@ -99,15 +73,13 @@ For samples, please see the sample folder. For setup instructions, see [here] [
## Limitations
This preview contains the PHP 7 port of the SQLSRV and PDO_SQLSRV drivers, and does not provide backwards compatibility with PHP 5. The following items have known issues:
SQLSRV:
- Memory management.
- This release contains the PHP 7 port of the SQLSRV and PDO_SQLSRV drivers, and does not provide backwards compatibility with PHP 5.
- Binding output parameter using emulate prepare is not supported.
## Known Issues
- User defined data types and SQL_VARIANT.
## Future Plans
- Linux Version
- Expand SQL 16 Feature Support (example: Always Encrypted)
- Build Verification/Fundamental Tests
- Bug Fixes

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +1 @@
Microsoft Drivers 4.0.0 for PHP for SQL Server (PDO driver)
Microsoft Drivers 4.1 for PHP for SQL Server (PDO driver)

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: common initialization routines shared by PDO and sqlsrv
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: Result sets
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -88,7 +88,25 @@ template <typename Char, typename Number>
SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& last_error )
{
// get to display size by removing the null terminator from buffer length
size_t display_size = ( buffer_length - sizeof( Char )) / sizeof( Char );
std::basic_ostringstream<Char> os;
// use the display size to determine the sql type. And if it is a double, set the precision accordingly
// the display sizes are set by the ODBC driver based on the precision of the sql type
// otherwise we can just use the default precision as long will not be truncated
size_t real_display_size = 14;
size_t float_display_size = 24;
size_t real_precision = 7;
size_t float_precision = 15;
// this is the case of sql type float(24) or real
if ( display_size == real_display_size ) {
os.precision( real_precision );
}
// this is the case of sql type float(53)
else if ( display_size == float_display_size ) {
os.precision( float_precision );
}
std::locale loc;
os.imbue( loc );
std::use_facet< std::num_put< Char > >( loc ).put( std::basic_ostream<Char>::_Iter( os.rdbuf() ), os, ' ', *number_data );
@ -100,13 +118,13 @@ SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buff
return SQL_ERROR;
}
if( str_num.size() * sizeof(Char) + sizeof(Char) > (size_t) buffer_length ) {
if( str_num.size() * sizeof(Char) > (size_t) buffer_length ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "HY090", (SQLCHAR*) "Buffer length too small to hold number as string", -1 );
return SQL_ERROR;
}
*out_buffer_length = str_num.size() * sizeof(Char) + sizeof(Char); // include NULL terminator
*out_buffer_length = str_num.size() * sizeof( Char ); // str_num.size() already include the NULL terminator
memcpy_s( buffer, buffer_length, str_num.c_str(), *out_buffer_length );
return SQL_SUCCESS;

View file

@ -6,7 +6,7 @@
//
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1276,7 +1276,7 @@ struct sqlsrv_stmt : public sqlsrv_context {
virtual ~sqlsrv_stmt( void );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream ) = 0;
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream, bool prefer_number_to_string = false ) = 0;
};
@ -1337,7 +1337,6 @@ void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, SQLLEN limit TSRMLS_DC );
void core_finalize_output_parameters(sqlsrv_stmt* stmt TSRMLS_DC);
//*********************************************************************************************************************************
@ -1613,7 +1612,7 @@ void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const co
const char* get_last_error_message( DWORD last_error = 0 );
// a wrapper around FormatMessage that can take variadic args rather than a a va_arg pointer
DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, const char* format, ... );
DWORD core_sqlsrv_format_message( char*& output_buffer, unsigned output_len, const char* format, ... );
// convenience functions that overload either a reference or a pointer so we can use
// either in the CHECK_* functions.

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1305,10 +1305,6 @@ bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC )
return true;
}
void core_finalize_output_parameters(sqlsrv_stmt* stmt TSRMLS_DC) {
finalize_output_parameters(stmt TSRMLS_CC);
}
void stmt_option_functor::operator()( sqlsrv_stmt* /*stmt*/, stmt_option const* /*opt*/, zval* /*value_z*/ TSRMLS_DC )
{
TSRMLS_C;
@ -1778,7 +1774,15 @@ SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval const* para
case IS_TRUE:
case IS_FALSE:
case IS_LONG:
sql_c_type = SQL_C_LONG;
//ODBC 64-bit long and integer type are 4 byte values.
if ( ( Z_LVAL_P( param_z ) < INT_MIN ) || ( Z_LVAL_P( param_z ) > INT_MAX ) )
{
sql_c_type = SQL_C_SBIGINT;
}
else
{
sql_c_type = SQL_C_SLONG;
}
break;
case IS_DOUBLE:
sql_c_type = SQL_C_DOUBLE;
@ -1841,7 +1845,16 @@ void default_sql_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval* param_z, SQLSRV
case IS_TRUE:
case IS_FALSE:
case IS_LONG:
sql_type = SQL_INTEGER;
//ODBC 64-bit long and integer type are 4 byte values.
if ( ( Z_LVAL_P( param_z ) < INT_MIN ) || ( Z_LVAL_P( param_z ) > INT_MAX ) )
{
sql_type = SQL_BIGINT;
}
else
{
sql_type = SQL_INTEGER;
}
break;
case IS_DOUBLE:
sql_type = SQL_FLOAT;
@ -1908,12 +1921,13 @@ void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval*
break;
case IS_STRING:
{
SQLULEN byte_len = Z_STRLEN_P( param_z ) * ((encoding == SQLSRV_ENCODING_UTF8) ? sizeof( wchar_t ) : sizeof( char ));
size_t char_size = ( encoding == SQLSRV_ENCODING_UTF8 ) ? sizeof( wchar_t ) : sizeof( char );
SQLULEN byte_len = Z_STRLEN_P( param_z ) * char_size;
if( byte_len > SQL_SERVER_MAX_FIELD_SIZE ) {
column_size = SQL_SERVER_MAX_TYPE_SIZE;
}
else {
column_size = Z_STRLEN_P( param_z );
column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size;
}
break;
}
@ -2096,8 +2110,8 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
calc_string_size( stmt, field_index, sql_field_type, sql_display_size TSRMLS_CC );
// if this is a large type, then read the first few bytes to get the actual length from SQLGetData
if( sql_display_size == 0 || sql_display_size == LONG_MAX ||
sql_display_size == LONG_MAX >> 1 || sql_display_size == ULONG_MAX - 1 ) {
if( sql_display_size == 0 || sql_display_size == INT_MAX ||
sql_display_size == INT_MAX >> 1 || sql_display_size == UINT_MAX - 1 ) {
field_len_temp = INITIAL_FIELD_STRING_LEN;

View file

@ -3,7 +3,7 @@
//
// Contents: Implementation of PHP streams for reading SQL Server data
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -306,12 +306,12 @@ void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const co
LOG( severity, "%1!s!: message = %2!s!", ctx.func(), formatted_error->native_message );
}
DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, const char* format, ... )
DWORD core_sqlsrv_format_message( char*& output_buffer, unsigned output_len, const char* format, ... )
{
va_list format_args;
va_start( format_args, format );
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, format, 0, 0, output_buffer, output_len, &format_args );
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, format, 0, 0, static_cast<LPSTR>(output_buffer), SQL_MAX_MESSAGE_LENGTH, &format_args );
va_end( format_args );

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDO object for PDO_SQLSRV
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -73,6 +73,7 @@ enum PDO_STMT_OPTIONS {
PDO_STMT_OPTION_CURSOR_SCROLL_TYPE,
PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE,
PDO_STMT_OPTION_EMULATE_PREPARES,
PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE,
};
// List of all the statement options supported by this driver.
@ -85,6 +86,7 @@ const stmt_option PDO_STMT_OPTS[] = {
{ NULL, 0, PDO_STMT_OPTION_CURSOR_SCROLL_TYPE, std::unique_ptr<stmt_option_cursor_scroll_type>( new stmt_option_cursor_scroll_type ) },
{ NULL, 0, PDO_STMT_OPTION_CLIENT_BUFFER_MAX_KB_SIZE, std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit ) },
{ NULL, 0, PDO_STMT_OPTION_EMULATE_PREPARES, std::unique_ptr<stmt_option_emulate_prepares>( new stmt_option_emulate_prepares ) },
{ NULL, 0, PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE, std::unique_ptr<stmt_option_fetch_numeric>( new stmt_option_fetch_numeric ) },
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} },
};
@ -362,11 +364,13 @@ struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
// constructor for the internal object for connections
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC ) :
sqlsrv_conn( h, e, driver, SQLSRV_ENCODING_UTF8 TSRMLS_CC ),
stmts( NULL ),
direct_query( false ),
query_timeout( QUERY_TIMEOUT_INVALID ),
client_buffer_max_size( PDO_SQLSRV_G( client_buffer_max_size ) )
sqlsrv_conn( h, e, driver, SQLSRV_ENCODING_UTF8 TSRMLS_CC ),
stmts( NULL ),
direct_query( false ),
query_timeout( QUERY_TIMEOUT_INVALID ),
client_buffer_max_size( PDO_SQLSRV_G( client_buffer_max_size )),
bind_param_encoding( SQLSRV_ENCODING_CHAR ),
fetch_numeric( false )
{
if( client_buffer_max_size < 0 ) {
client_buffer_max_size = sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_DEFAULT;
@ -465,7 +469,7 @@ int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
zend_string_release( Z_STR( server_z ));
}
dbh->error_mode = prev_err_mode; // reset the error mode
g_henv_cp->invalidate();
g_henv_cp->last_error().reset(); // reset the last error; callee will check if last_error exist before freeing it and setting it to NULL
return 0;
}
catch( ... ) {
@ -906,6 +910,10 @@ int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC
driver_dbh->client_buffer_max_size = Z_LVAL_P( val );
break;
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
driver_dbh->fetch_numeric = (zend_is_true(val)) ? true : false;
break;
// Not supported
case PDO_ATTR_FETCH_TABLE_NAMES:
case PDO_ATTR_FETCH_CATALOG_NAMES:
@ -1047,6 +1055,12 @@ int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, zend_long attr, zval *return_value
break;
}
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
{
ZVAL_BOOL( return_value, driver_dbh->fetch_numeric );
break;
}
default:
{
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_DBH_ATTR );
@ -1081,8 +1095,8 @@ int pdo_sqlsrv_dbh_return_error( pdo_dbh_t *dbh, pdo_stmt_t *stmt,
else {
ctx_error = static_cast<sqlsrv_conn*>( dbh->driver_data )->last_error();
}
pdo_sqlsrv_retrieve_context_error( ctx_error, info );
pdo_sqlsrv_retrieve_context_error( ctx_error, info );
return 1;
}
@ -1190,41 +1204,81 @@ char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, _Out_ size_t* l
int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_len, char **quoted, size_t* quoted_len,
enum pdo_param_type /*paramtype*/ TSRMLS_DC )
{
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN;
PDO_LOG_DBH_ENTRY;
// count the number of quotes needed
unsigned int quotes_needed = 2; // the initial start and end quotes of course
for(size_t index = 0; index < unquoted_len && unquoted[ index ] != '\0'; ++index ) {
if( unquoted[ index ] == '\'' ) {
++quotes_needed;
}
}
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
SQLSRV_ENCODING encoding = driver_dbh->bind_param_encoding;
*quoted_len = unquoted_len + quotes_needed; // length returned to the caller should not account for null terminator.
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 )); // include space for null terminator.
unsigned int out_current = 0;
if ( encoding == SQLSRV_ENCODING_BINARY ) {
// convert from char* to hex digits using os
std::basic_ostringstream<char> os;
for ( size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index ) {
os << std::hex << ( int )unquoted[index];
}
std::basic_string<char> str_hex = os.str();
// each character is represented by 2 digits of hex
size_t unquoted_str_len = unquoted_len * 2; // length returned should not account for null terminator
char* unquoted_str = reinterpret_cast<char*>( sqlsrv_malloc( unquoted_str_len, sizeof( char ), 1 )); // include space for null terminator
strcpy_s( unquoted_str, unquoted_str_len + 1 /* include null terminator*/, str_hex.c_str());
// include length of '0x' in the binary string
*quoted_len = unquoted_str_len + 2;
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 ));
unsigned int out_current = 0;
// insert '0x'
( *quoted )[out_current++] = '0';
( *quoted )[out_current++] = 'x';
for ( size_t index = 0; index < unquoted_str_len && unquoted_str[index] != '\0'; ++index ) {
( *quoted )[out_current++] = unquoted_str[index];
}
// null terminator
( *quoted )[out_current] = '\0';
sqlsrv_free( unquoted_str );
return 1;
}
else {
// count the number of quotes needed
unsigned int quotes_needed = 2; // the initial start and end quotes of course
// include the N proceeding the initial quote if encoding is UTF8
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
quotes_needed = 3;
}
// insert initial quote
(*quoted)[ out_current++ ] ='\'';
for ( size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index ) {
if ( unquoted[index] == '\'' ) {
++quotes_needed;
}
}
for(size_t index = 0; index < unquoted_len && unquoted[ index ] != '\0'; ++index ) {
*quoted_len = unquoted_len + quotes_needed; // length returned to the caller should not account for null terminator.
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 )); // include space for null terminator.
unsigned int out_current = 0;
if( unquoted[ index ] == '\'' ) {
(*quoted)[ out_current++ ] = '\'';
(*quoted)[ out_current++ ] = '\'';
}
else {
(*quoted)[ out_current++ ] = unquoted[ index ];
}
}
// insert N if the encoding is UTF8
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
( *quoted )[out_current++] = 'N';
}
// insert initial quote
( *quoted )[out_current++] = '\'';
// trailing quote and null terminator
(*quoted)[ out_current++ ] ='\'';
(*quoted)[ out_current ] = '\0';
for ( size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index ) {
return 1;
if ( unquoted[index] == '\'' ) {
( *quoted )[out_current++] = '\'';
( *quoted )[out_current++] = '\'';
}
else {
( *quoted )[out_current++] = unquoted[index];
}
}
// trailing quote and null terminator
( *quoted )[out_current++] = '\'';
( *quoted )[out_current] = '\0';
return 1;
}
}
// This method is not implemented by this driver.
@ -1283,6 +1337,9 @@ void add_stmt_option_key( sqlsrv_context& ctx, size_t key, HashTable* options_ht
option_key = PDO_STMT_OPTION_EMULATE_PREPARES;
break;
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
option_key = PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE;
default:
CHECK_CUSTOM_ERROR( true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION ) {
throw core::CoreException();

View file

@ -3,7 +3,7 @@
//
// Contents: initialization routines for PDO_SQLSRV
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -372,14 +372,15 @@ namespace {
}
// array of pdo constants.
sqlsrv_attr_pdo_constant pdo_attr_constants[] = {
sqlsrv_attr_pdo_constant pdo_attr_constants[] = {
// driver specific attributes
{ "SQLSRV_ATTR_ENCODING" , SQLSRV_ATTR_ENCODING },
{ "SQLSRV_ATTR_QUERY_TIMEOUT" , SQLSRV_ATTR_QUERY_TIMEOUT },
{ "SQLSRV_ATTR_DIRECT_QUERY" , SQLSRV_ATTR_DIRECT_QUERY },
{ "SQLSRV_ATTR_CURSOR_SCROLL_TYPE" , SQLSRV_ATTR_CURSOR_SCROLL_TYPE },
{ "SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE", SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE },
// driver specific attributes
{ "SQLSRV_ATTR_ENCODING" , SQLSRV_ATTR_ENCODING },
{ "SQLSRV_ATTR_QUERY_TIMEOUT" , SQLSRV_ATTR_QUERY_TIMEOUT },
{ "SQLSRV_ATTR_DIRECT_QUERY" , SQLSRV_ATTR_DIRECT_QUERY },
{ "SQLSRV_ATTR_CURSOR_SCROLL_TYPE" , SQLSRV_ATTR_CURSOR_SCROLL_TYPE },
{ "SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE", SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE },
{ "SQLSRV_ATTR_FETCHES_NUMERIC_TYPE", SQLSRV_ATTR_FETCHES_NUMERIC_TYPE },
// used for the size for output parameters: PDO::PARAM_INT and PDO::PARAM_BOOL use the default size of int,
// PDO::PARAM_STR uses the size of the string in the variable

View file

@ -5,7 +5,7 @@
//
// Copyright Microsoft Corporation
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -6,7 +6,7 @@
//
// Contents: Declarations for the extension
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -48,6 +48,7 @@ enum PDO_SQLSRV_ATTR {
SQLSRV_ATTR_DIRECT_QUERY,
SQLSRV_ATTR_CURSOR_SCROLL_TYPE,
SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE,
SQLSRV_ATTR_FETCHES_NUMERIC_TYPE,
};
// valid set of values for TransactionIsolation connection option
@ -176,6 +177,8 @@ struct pdo_sqlsrv_dbh : public sqlsrv_conn {
bool direct_query;
long query_timeout;
zend_long client_buffer_max_size;
SQLSRV_ENCODING bind_param_encoding;
bool fetch_numeric;
pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC );
};
@ -210,6 +213,10 @@ struct stmt_option_emulate_prepares : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
};
struct stmt_option_fetch_numeric : public stmt_option_functor {
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
};
extern struct pdo_stmt_methods pdo_sqlsrv_stmt_methods;
// a core layer pdo stmt object. This object inherits and overrides the callbacks necessary
@ -220,17 +227,19 @@ struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
direct_query( false ),
direct_query_subst_string( NULL ),
direct_query_subst_string_len( 0 ),
bound_column_param_types( NULL )
bound_column_param_types( NULL ),
fetch_numeric( false )
{
pdo_sqlsrv_dbh* db = static_cast<pdo_sqlsrv_dbh*>( c );
direct_query = db->direct_query;
fetch_numeric = db->fetch_numeric;
}
virtual ~pdo_sqlsrv_stmt( void );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
// for PDO, everything is a string, so we return SQLSRV_PHPTYPE_STRING for all SQL types
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream );
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream, bool prefer_number_to_string );
bool direct_query; // flag set if the query should be executed directly or prepared
const char* direct_query_subst_string; // if the query is direct, hold the substitution string if using named parameters
@ -239,6 +248,7 @@ struct pdo_sqlsrv_stmt : public sqlsrv_stmt {
// meta data for current result set
std::vector<field_meta_data*, sqlsrv_allocator< field_meta_data* > > current_meta_data;
pdo_param_type* bound_column_param_types;
bool fetch_numeric;
};

View file

@ -3,7 +3,7 @@
//
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -223,7 +223,7 @@ zval convert_to_zval( SQLSRV_PHPTYPE sqlsrv_php_type, void** in_val, SQLLEN fiel
else {
if( sqlsrv_php_type == SQLSRV_PHPTYPE_INT ) {
ZVAL_LONG( &out_zval, **( reinterpret_cast<long**>( in_val )));
ZVAL_LONG( &out_zval, **( reinterpret_cast<int**>( in_val )));
}
else {
ZVAL_DOUBLE( &out_zval, **( reinterpret_cast<double**>( in_val )));
@ -330,6 +330,12 @@ void stmt_option_emulate_prepares:: operator()( sqlsrv_stmt* stmt, stmt_option c
pdo_stmt->supports_placeholders = ( zend_is_true( value_z )) ? PDO_PLACEHOLDER_NONE : PDO_PLACEHOLDER_POSITIONAL;
}
void stmt_option_fetch_numeric:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
{
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt );
pdo_stmt->fetch_numeric = ( zend_is_true( value_z )) ? true : false;
}
// log a function entry point
#define PDO_LOG_STMT_ENTRY \
@ -700,8 +706,9 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
sqlsrv_phptype sqlsrv_php_type;
SQLSRV_ASSERT( colno >= 0 && colno < static_cast<int>( driver_stmt->current_meta_data.size()),
"Invalid column number in pdo_sqlsrv_stmt_get_col_data" );
sqlsrv_php_type = driver_stmt->sql_type_to_php_type(static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_type ),
static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_size ), true );
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_type ),
static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_size ),
true, driver_stmt->fetch_numeric );
// set the encoding if the user specified one via bindColumn, otherwise use the statement's encoding
sqlsrv_php_type.typeinfo.encoding = driver_stmt->encoding();
@ -748,11 +755,6 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
SQLSRV_PHPTYPE sqlsrv_phptype_out = SQLSRV_PHPTYPE_INVALID;
core_sqlsrv_get_field( driver_stmt, colno, sqlsrv_php_type, false, *(reinterpret_cast<void**>(ptr)),
reinterpret_cast<SQLLEN*>( len ), true, &sqlsrv_phptype_out TSRMLS_CC );
// if the current column is the last fetch column, finalize output params
if ( stmt->column_count == colno + 1 ) {
core_finalize_output_parameters( driver_stmt TSRMLS_CC );
}
zval* zval_ptr = ( zval* )( sqlsrv_malloc( sizeof( zval )));
*zval_ptr = convert_to_zval( sqlsrv_phptype_out, reinterpret_cast<void**>( ptr ), *len );
@ -785,6 +787,7 @@ int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_
PDO_VALIDATE_STMT;
PDO_LOG_STMT_ENTRY;
pdo_sqlsrv_stmt* pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
sqlsrv_stmt* driver_stmt = static_cast<sqlsrv_stmt*>( stmt->driver_data );
try {
@ -815,6 +818,10 @@ int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_
core_sqlsrv_set_buffered_query_limit( driver_stmt, val TSRMLS_CC );
break;
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
pdo_stmt->fetch_numeric = ( zend_is_true( val )) ? true : false;
break;
default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
break;
@ -890,6 +897,12 @@ int pdo_sqlsrv_stmt_get_attr( pdo_stmt_t *stmt, zend_long attr, zval *return_val
break;
}
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
{
ZVAL_BOOL( return_value, driver_stmt->fetch_numeric );
break;
}
default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
break;
@ -1064,6 +1077,11 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
// since the param isn't reliable, we don't do anything here
case PDO_PARAM_EVT_ALLOC:
// if emulate prepare is on, set the bind_param_encoding so it can be used in PDO::quote when binding parameters on the client side
if ( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE ) {
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( stmt->dbh->driver_data );
driver_dbh->bind_param_encoding = static_cast<SQLSRV_ENCODING>( Z_LVAL( param->driver_params ));
}
break;
case PDO_PARAM_EVT_FREE:
break;
@ -1252,7 +1270,7 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
// Returns a sqlsrv_phptype for a given SQL Server data type.
sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_over_stream )
sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_over_stream, bool prefer_number_to_string )
{
sqlsrv_phptype sqlsrv_phptype;
int local_encoding = this->encoding();
@ -1264,15 +1282,31 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUI
}
switch( sql_type ) {
case SQL_BIT:
case SQL_INTEGER:
case SQL_SMALLINT:
case SQL_TINYINT:
case SQL_BIT:
case SQL_INTEGER:
case SQL_SMALLINT:
case SQL_TINYINT:
if ( prefer_number_to_string ) {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_INT;
}
else {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
sqlsrv_phptype.typeinfo.encoding = local_encoding;
}
break;
case SQL_FLOAT:
case SQL_REAL:
if ( prefer_number_to_string ) {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_FLOAT;
}
else {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
sqlsrv_phptype.typeinfo.encoding = local_encoding;
}
break;
case SQL_BIGINT:
case SQL_CHAR:
case SQL_DECIMAL:
case SQL_FLOAT:
case SQL_REAL:
case SQL_GUID:
case SQL_NUMERIC:
case SQL_WCHAR:

View file

@ -3,7 +3,7 @@
//
// Contents: Utility functions used by both connection or statement functions
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -460,8 +460,7 @@ bool pdo_sqlsrv_handle_dbh_error( sqlsrv_context& ctx, unsigned int sqlsrv_error
if( !warning ) {
size_t msg_len = strlen( reinterpret_cast<const char*>( error->native_message )) + SQL_SQLSTATE_BUFSIZE
+ MAX_DIGITS + 1;
sqlsrv_malloc_auto_ptr<char> msg;
msg = static_cast<char*>( sqlsrv_malloc( msg_len ));
char* msg = static_cast<char*>( sqlsrv_malloc( msg_len ));
core_sqlsrv_format_message( msg, static_cast<unsigned int>( msg_len ), WARNING_TEMPLATE, error->sqlstate, error->native_code,
error->native_message );
php_error( E_WARNING, msg );
@ -513,8 +512,7 @@ bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_erro
if( !warning ) {
size_t msg_len = strlen( reinterpret_cast<const char*>( error->native_message )) + SQL_SQLSTATE_BUFSIZE
+ MAX_DIGITS + 1;
sqlsrv_malloc_auto_ptr<char> msg;
msg = static_cast<char*>( sqlsrv_malloc( msg_len ));
char* msg = static_cast<char*>( sqlsrv_malloc(SQL_MAX_MESSAGE_LENGTH+1));
core_sqlsrv_format_message( msg, static_cast<unsigned int>( msg_len ), WARNING_TEMPLATE, error->sqlstate, error->native_code,
error->native_message );
php_error( E_WARNING, msg );
@ -548,11 +546,6 @@ void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pd
add_next_index_long( pdo_zval, last_error->native_code );
add_next_index_string( pdo_zval, reinterpret_cast<char*>( last_error->native_message ));
}
else {
add_next_index_null( pdo_zval ); /* native code */
add_next_index_null( pdo_zval ); /* native message */
}
}
// Formats the error message and writes to the php error log.

View file

@ -2,7 +2,7 @@
// File: version.h
// Contents: Version number constants
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -16,10 +16,10 @@
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#define VER_FILEVERSION_STR "4.0.0.0"
#define _FILEVERSION 4,0,0,0
#define VER_FILEVERSION_STR "4.1.0.0"
#define _FILEVERSION 4,1,0,0
#define SQLVERSION_MAJOR 4
#define SQLVERSION_MINOR 0
#define SQLVERSION_MINOR 1
#define SQLVERSION_MMDD 0
#define SQLVERSION_REVISION 0

View file

@ -1 +1 @@
Microsoft Drivers 4.0.0 for PHP for SQL Server (PDO driver)
Microsoft Drivers 4.1 for PHP for SQL Server (PDO driver)

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use connection handles
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1192,7 +1192,7 @@ void add_stmt_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
{
int option_key = ::get_stmt_option_key( key, key_len TSRMLS_CC );
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, key ) {
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, ZSTR_VAL( key ) ) {
throw ss::SSException();
}
@ -1221,7 +1221,6 @@ void add_conn_option_key( sqlsrv_context& ctx, zend_string* key, size_t key_len,
void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht TSRMLS_DC )
{
try {
if( stmt_options ) {
HashTable* options_ht = Z_ARRVAL_P( stmt_options );
@ -1234,16 +1233,14 @@ void validate_stmt_options( sqlsrv_context& ctx, zval* stmt_options, _Inout_ Has
zval* conn_opt = NULL;
int result = 0;
key_len = ZSTR_LEN( key ) + 1;
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
if( type != HASH_KEY_IS_STRING ) {
std::ostringstream itoa;
itoa << int_key;
CHECK_CUSTOM_ERROR( true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, itoa.str() ) {
if (type != HASH_KEY_IS_STRING) {
CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str() ) {
throw core::CoreException();
}
}
key_len = ZSTR_LEN(key) + 1;
add_stmt_option_key( ctx, key, key_len, ss_stmt_options_ht, data TSRMLS_CC );
} ZEND_HASH_FOREACH_END();
}

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: common initialization routines shared by PDO and sqlsrv
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -3,7 +3,7 @@
//
// Contents: Result sets
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -88,7 +88,25 @@ template <typename Char, typename Number>
SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buffer_length, _Out_ SQLLEN* out_buffer_length,
sqlsrv_error_auto_ptr& last_error )
{
// get to display size by removing the null terminator from buffer length
size_t display_size = ( buffer_length - sizeof( Char )) / sizeof( Char );
std::basic_ostringstream<Char> os;
// use the display size to determine the sql type. And if it is a double, set the precision accordingly
// the display sizes are set by the ODBC driver based on the precision of the sql type
// otherwise we can just use the default precision as long will not be truncated
size_t real_display_size = 14;
size_t float_display_size = 24;
size_t real_precision = 7;
size_t float_precision = 15;
// this is the case of sql type float(24) or real
if ( display_size == real_display_size ) {
os.precision( real_precision );
}
// this is the case of sql type float(53)
else if ( display_size == float_display_size ) {
os.precision( float_precision );
}
std::locale loc;
os.imbue( loc );
std::use_facet< std::num_put< Char > >( loc ).put( std::basic_ostream<Char>::_Iter( os.rdbuf() ), os, ' ', *number_data );
@ -100,13 +118,13 @@ SQLRETURN number_to_string( Number* number_data, _Out_ void* buffer, SQLLEN buff
return SQL_ERROR;
}
if( str_num.size() * sizeof(Char) + sizeof(Char) > (size_t) buffer_length ) {
if( str_num.size() * sizeof(Char) > (size_t) buffer_length ) {
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error(
(SQLCHAR*) "HY090", (SQLCHAR*) "Buffer length too small to hold number as string", -1 );
return SQL_ERROR;
}
*out_buffer_length = str_num.size() * sizeof(Char) + sizeof(Char); // include NULL terminator
*out_buffer_length = str_num.size() * sizeof( Char ); // str_num.size() already include the NULL terminator
memcpy_s( buffer, buffer_length, str_num.c_str(), *out_buffer_length );
return SQL_SUCCESS;

View file

@ -6,7 +6,7 @@
//
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1276,7 +1276,7 @@ struct sqlsrv_stmt : public sqlsrv_context {
virtual ~sqlsrv_stmt( void );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream ) = 0;
virtual sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream, bool prefer_number_to_string = false ) = 0;
};
@ -1337,7 +1337,6 @@ void core_sqlsrv_set_send_at_exec( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, zval* value_z TSRMLS_DC );
void core_sqlsrv_set_buffered_query_limit( sqlsrv_stmt* stmt, SQLLEN limit TSRMLS_DC );
void core_finalize_output_parameters(sqlsrv_stmt* stmt TSRMLS_DC);
//*********************************************************************************************************************************
@ -1613,7 +1612,7 @@ void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const co
const char* get_last_error_message( DWORD last_error = 0 );
// a wrapper around FormatMessage that can take variadic args rather than a a va_arg pointer
DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, const char* format, ... );
DWORD core_sqlsrv_format_message( char*& output_buffer, unsigned output_len, const char* format, ... );
// convenience functions that overload either a reference or a pointer so we can use
// either in the CHECK_* functions.

View file

@ -3,7 +3,7 @@
//
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -1305,10 +1305,6 @@ bool core_sqlsrv_send_stream_packet( sqlsrv_stmt* stmt TSRMLS_DC )
return true;
}
void core_finalize_output_parameters(sqlsrv_stmt* stmt TSRMLS_DC) {
finalize_output_parameters(stmt TSRMLS_CC);
}
void stmt_option_functor::operator()( sqlsrv_stmt* /*stmt*/, stmt_option const* /*opt*/, zval* /*value_z*/ TSRMLS_DC )
{
TSRMLS_C;
@ -1778,7 +1774,15 @@ SQLSMALLINT default_c_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval const* para
case IS_TRUE:
case IS_FALSE:
case IS_LONG:
sql_c_type = SQL_C_LONG;
//ODBC 64-bit long and integer type are 4 byte values.
if ( ( Z_LVAL_P( param_z ) < INT_MIN ) || ( Z_LVAL_P( param_z ) > INT_MAX ) )
{
sql_c_type = SQL_C_SBIGINT;
}
else
{
sql_c_type = SQL_C_SLONG;
}
break;
case IS_DOUBLE:
sql_c_type = SQL_C_DOUBLE;
@ -1841,7 +1845,16 @@ void default_sql_type( sqlsrv_stmt* stmt, SQLULEN paramno, zval* param_z, SQLSRV
case IS_TRUE:
case IS_FALSE:
case IS_LONG:
sql_type = SQL_INTEGER;
//ODBC 64-bit long and integer type are 4 byte values.
if ( ( Z_LVAL_P( param_z ) < INT_MIN ) || ( Z_LVAL_P( param_z ) > INT_MAX ) )
{
sql_type = SQL_BIGINT;
}
else
{
sql_type = SQL_INTEGER;
}
break;
case IS_DOUBLE:
sql_type = SQL_FLOAT;
@ -1908,12 +1921,13 @@ void default_sql_size_and_scale( sqlsrv_stmt* stmt, unsigned int paramno, zval*
break;
case IS_STRING:
{
SQLULEN byte_len = Z_STRLEN_P( param_z ) * ((encoding == SQLSRV_ENCODING_UTF8) ? sizeof( wchar_t ) : sizeof( char ));
size_t char_size = ( encoding == SQLSRV_ENCODING_UTF8 ) ? sizeof( wchar_t ) : sizeof( char );
SQLULEN byte_len = Z_STRLEN_P( param_z ) * char_size;
if( byte_len > SQL_SERVER_MAX_FIELD_SIZE ) {
column_size = SQL_SERVER_MAX_TYPE_SIZE;
}
else {
column_size = Z_STRLEN_P( param_z );
column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size;
}
break;
}
@ -2096,8 +2110,8 @@ void get_field_as_string( sqlsrv_stmt* stmt, SQLUSMALLINT field_index, sqlsrv_ph
calc_string_size( stmt, field_index, sql_field_type, sql_display_size TSRMLS_CC );
// if this is a large type, then read the first few bytes to get the actual length from SQLGetData
if( sql_display_size == 0 || sql_display_size == LONG_MAX ||
sql_display_size == LONG_MAX >> 1 || sql_display_size == ULONG_MAX - 1 ) {
if( sql_display_size == 0 || sql_display_size == INT_MAX ||
sql_display_size == INT_MAX >> 1 || sql_display_size == UINT_MAX - 1 ) {
field_len_temp = INITIAL_FIELD_STRING_LEN;

View file

@ -3,7 +3,7 @@
//
// Contents: Implementation of PHP streams for reading SQL Server data
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -306,12 +306,12 @@ void core_sqlsrv_format_driver_error( sqlsrv_context& ctx, sqlsrv_error_const co
LOG( severity, "%1!s!: message = %2!s!", ctx.func(), formatted_error->native_message );
}
DWORD core_sqlsrv_format_message( char* output_buffer, unsigned output_len, const char* format, ... )
DWORD core_sqlsrv_format_message( char*& output_buffer, unsigned output_len, const char* format, ... )
{
va_list format_args;
va_start( format_args, format );
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, format, 0, 0, output_buffer, output_len, &format_args );
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, format, 0, 0, static_cast<LPSTR>(output_buffer), SQL_MAX_MESSAGE_LENGTH, &format_args );
va_end( format_args );

View file

@ -2,7 +2,7 @@
// File: init.cpp
// Contents: initialization routines for the extension
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -8,7 +8,7 @@
//
// Comments: Also contains "internal" declarations shared across source files.
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -175,7 +175,7 @@ struct ss_sqlsrv_stmt : public sqlsrv_stmt {
void new_result_set( TSRMLS_D );
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream );
sqlsrv_phptype sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream, bool prefer_number_to_string );
bool prepared; // whether the statement has been prepared yet (used for error messages)
zend_ulong conn_index; // index into the connection hash that contains this statement structure

View file

@ -3,7 +3,7 @@
//
// Contents: Routines that use statement handles
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -164,7 +164,7 @@ void ss_sqlsrv_stmt::new_result_set( TSRMLS_D )
}
// 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( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream )
sqlsrv_phptype ss_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUINTEGER size, bool prefer_string_to_stream, bool prefer_number_to_string )
{
sqlsrv_phptype ss_phptype;
ss_phptype.typeinfo.type = SQLSRV_PHPTYPE_INVALID;

View file

@ -5,7 +5,7 @@
//
// Comments: Mostly error handling and some type handling
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License

View file

@ -2,7 +2,7 @@
// File: version.h
// Contents: Version number constants
//
// Microsoft Drivers 4.0 for PHP for SQL Server
// Microsoft Drivers 4.1 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
@ -16,10 +16,10 @@
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------
#define VER_FILEVERSION_STR "4.0.0.0"
#define _FILEVERSION 4,0,0,0
#define VER_FILEVERSION_STR "4.1.0.0"
#define _FILEVERSION 4,1,0,0
#define SQLVERSION_MAJOR 4
#define SQLVERSION_MINOR 0
#define SQLVERSION_MINOR 1
#define SQLVERSION_MMDD 0
#define SQLVERSION_REVISION 0