Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIGINT as an output param no longer results in value out of range exception when the returned value is larger than a maximum integer #567

Merged
merged 28 commits into from
Oct 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a0e8862
convert long output param to string, then convert back to long if les…
yukiwongky Oct 12, 2017
c30f2d6
change encoding to SYSTEM when converting int to string for inout and…
yukiwongky Oct 12, 2017
628e04e
fix spacing in expected output in pdo_bigint_outparam.phpt and sqlsrv…
yukiwongky Oct 12, 2017
b5a0d1f
cosmetic changes
yukiwongky Oct 13, 2017
83ca7b4
add comment do pdo_bigint_outparam.phpt and sqlsrv_bitint_outparam.phpt
yukiwongky Oct 13, 2017
e190bca
fix bigint input in sqlsrv_bigint_outparam.phpt
yukiwongky Oct 16, 2017
fd5c2b9
Merge remote-tracking branch 'upstream/dev' into bigintOutput
yukiwongky Oct 17, 2017
9b12fe3
detect Appveyor problem
yukiwongky Oct 17, 2017
e3651e5
detect appveyor problem
yukiwongky Oct 17, 2017
a195e85
detect appveyor problem
yukiwongky Oct 17, 2017
acee5c4
detect appveyor problem
yukiwongky Oct 17, 2017
8397f7b
detect appveyor problem
yukiwongky Oct 17, 2017
98edd5d
detect appveyor problem
yukiwongky Oct 17, 2017
3e247c6
detect appveyor problem
yukiwongky Oct 17, 2017
597d544
detect appveyor problem
yukiwongky Oct 17, 2017
6b223a7
detect appveyor problem
yukiwongky Oct 17, 2017
9e847c1
detect appveyor problem
yukiwongky Oct 17, 2017
f67240e
change encoding to converting from long to string to UTF8
yukiwongky Oct 17, 2017
d7212e6
change output biging to encoding utf8
yukiwongky Oct 17, 2017
a5125df
undo changes in appveyor.yml
yukiwongky Oct 17, 2017
68df220
undo changes in appveyor.yml
yukiwongky Oct 17, 2017
3f17147
add contrinue_after_cpp_exception option to OpenCppCoverage
yukiwongky Oct 18, 2017
b73539c
remove setting encoding in core_stmt.cpp
yukiwongky Oct 18, 2017
f4c736a
only change encoding if it is invalid
yukiwongky Oct 18, 2017
f2f3bc1
change encoding
yukiwongky Oct 18, 2017
02b3d6d
change appveyor SQL2016 to run on x86 platform
yukiwongky Oct 18, 2017
78da835
move opencppcoverage.exe down in appveyor.xml
yukiwongky Oct 18, 2017
6a4f625
change encoding
yukiwongky Oct 18, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ environment:
PHP_DEPSVER: 7.0
PHP_SDK: c:\projects\php
matrix:
- BUILD_PLATFORM: x86
TEST_PHP_SQL_SERVER: (local)\SQL2016
SQL_INSTANCE: SQL2016
PHP_VC: 14
PHP_MAJOR_VER: 7.1
PHP_MINOR_VER: latest
PHP_SDK_DIR: c:\projects\php\x86
PHP_INSTALL_DIR: c:\projects\php\x86\bin
platform: x86
- BUILD_PLATFORM: x64
TEST_PHP_SQL_SERVER: (local)\SQL2012SP1
SQL_INSTANCE: SQL2012SP1
Expand All @@ -37,15 +46,6 @@ environment:
PHP_SDK_DIR: c:\projects\php\x86
PHP_INSTALL_DIR: c:\projects\php\x86\bin
platform: x86
- BUILD_PLATFORM: x64
TEST_PHP_SQL_SERVER: (local)\SQL2016
SQL_INSTANCE: SQL2016
PHP_VC: 14
PHP_MAJOR_VER: 7.1
PHP_MINOR_VER: latest
PHP_SDK_DIR: c:\projects\php\x64
PHP_INSTALL_DIR: c:\projects\php\x64\bin
platform: x64
- BUILD_PLATFORM: x86
TEST_PHP_SQL_SERVER: (local)\SQL2008R2SP2
SQL_INSTANCE: SQL2008R2SP2
Expand Down Expand Up @@ -190,8 +190,8 @@ test_script:
- ps: $outfiles = Get-ChildItem pdo_sqlsrv\*.out
- ps: foreach($file in $difffiles){ls $file; more $file}
- ps: foreach($file in $outfiles){ls $file; more $file}
- cd %PHP_INSTALL_DIR%
- OpenCppCoverage.exe --sources %PHP_SDK_DIR%\php-%PHP_VERSION%-src\ext\pdo_sqlsrv --sources %PHP_SDK_DIR%\php-%PHP_VERSION%-src\ext\sqlsrv --modules *sqlsrv*.dll --export_type=cobertura:.\coverage.xml --cover_children --quiet --optimized_build -- .\php.exe .\run-tests.php -P %APPVEYOR_BUILD_FOLDER%\test\functional\
- cd %PHP_INSTALL_DIR%
- OpenCppCoverage.exe --sources %PHP_SDK_DIR%\php-%PHP_VERSION%-src\ext\pdo_sqlsrv --sources %PHP_SDK_DIR%\php-%PHP_VERSION%-src\ext\sqlsrv --modules *sqlsrv*.dll --export_type=cobertura:.\coverage.xml --cover_children --quiet --continue_after_cpp_exception --optimized_build -- .\php.exe .\run-tests.php -P %APPVEYOR_BUILD_FOLDER%\test\functional\
- ls
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\cleanup_dbs.py -dbname %SQLSRV_DBNAME%
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\cleanup_dbs.py -dbname %PDOSQLSRV_DBNAME%
Expand Down
10 changes: 6 additions & 4 deletions source/shared/core_sqlsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1322,10 +1322,11 @@ struct sqlsrv_output_param {
SQLUSMALLINT param_num; // used to index into the ind_or_len of the statement
SQLLEN original_buffer_len; // used to make sure the returned length didn't overflow the buffer
bool is_bool;
bool is_long;

// string output param constructor
sqlsrv_output_param( _In_ zval* p_z, _In_ SQLSRV_ENCODING enc, _In_ int num, _In_ SQLUINTEGER buffer_len ) :
param_z( p_z ), encoding( enc ), param_num( num ), original_buffer_len( buffer_len ), is_bool( false )
sqlsrv_output_param( _In_ zval* p_z, _In_ SQLSRV_ENCODING enc, _In_ int num, _In_ SQLUINTEGER buffer_len, _In_ bool is_long ) :
param_z( p_z ), encoding( enc ), param_num( num ), original_buffer_len( buffer_len ), is_bool( false ), is_long( is_long )
{
}

Expand All @@ -1335,7 +1336,8 @@ struct sqlsrv_output_param {
encoding( SQLSRV_ENCODING_INVALID ),
param_num( num ),
original_buffer_len( -1 ),
is_bool( is_bool )
is_bool( is_bool ),
is_long( false )
{
}
};
Expand Down Expand Up @@ -1431,7 +1433,7 @@ typedef sqlsrv_stmt* (*driver_stmt_factory)( sqlsrv_conn* conn, SQLHANDLE h, err
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, _In_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size,
_In_ SQLSRV_PHPTYPE php_out_type, _Inout_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size,
_Inout_ SQLSMALLINT decimal_digits TSRMLS_DC );
SQLRETURN core_sqlsrv_execute( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_reads_bytes_(sql_len) const char* sql = NULL, _In_ int sql_len = 0 );
field_meta_data* core_sqlsrv_field_metadata( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT colno TSRMLS_DC );
Expand Down
35 changes: 31 additions & 4 deletions source/shared/core_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ sqlsrv_stmt* core_sqlsrv_create_stmt( _Inout_ sqlsrv_conn* conn, _In_ driver_stm
// The sql type is given as a hint if the driver provides it.

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, _In_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size,
_In_ SQLSRV_PHPTYPE php_out_type, _Inout_ SQLSRV_ENCODING encoding, _Inout_ SQLSMALLINT sql_type, _Inout_ SQLULEN column_size,
_Inout_ SQLSMALLINT decimal_digits TSRMLS_DC )
{
SQLSMALLINT c_type;
Expand Down Expand Up @@ -373,6 +373,7 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
}
bool zval_was_null = ( Z_TYPE_P( param_z ) == IS_NULL );
bool zval_was_bool = ( Z_TYPE_P( param_z ) == IS_TRUE || Z_TYPE_P( param_z ) == IS_FALSE );
bool zval_was_long = ( Z_TYPE_P( param_z ) == IS_LONG && php_out_type == SQLSRV_PHPTYPE_INT && (sql_type == SQL_BIGINT || sql_type == SQL_UNKNOWN_TYPE ));
// if the user asks for for a specific type for input and output, make sure the data type we send matches the data we
// type we expect back, since we can only send and receive the same type. Anything can be converted to a string, so
// we always let that match if they want a string back.
Expand All @@ -383,7 +384,16 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
if( zval_was_null || zval_was_bool ) {
convert_to_long( param_z );
}
match = Z_TYPE_P( param_z ) == IS_LONG;
if( zval_was_long ){
convert_to_string( param_z );
if ( encoding != SQLSRV_ENCODING_SYSTEM && encoding != SQLSRV_ENCODING_UTF8 && encoding != SQLSRV_ENCODING_BINARY ) {
encoding = SQLSRV_ENCODING_SYSTEM;
}
match = Z_TYPE_P( param_z ) == IS_STRING;
}
else {
match = Z_TYPE_P( param_z ) == IS_LONG;
}
break;
case SQLSRV_PHPTYPE_FLOAT:
if( zval_was_null ) {
Expand Down Expand Up @@ -415,7 +425,15 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
if( direction == SQL_PARAM_OUTPUT ) {
switch( php_out_type ) {
case SQLSRV_PHPTYPE_INT:
convert_to_long( param_z );
if( zval_was_long ){
convert_to_string( param_z );
if ( encoding != SQLSRV_ENCODING_SYSTEM && encoding != SQLSRV_ENCODING_UTF8 && encoding != SQLSRV_ENCODING_BINARY ) {
encoding = SQLSRV_ENCODING_SYSTEM;
}
}
else {
convert_to_long( param_z );
}
break;
case SQLSRV_PHPTYPE_FLOAT:
convert_to_double( param_z );
Expand Down Expand Up @@ -551,7 +569,7 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
buffer, buffer_len TSRMLS_CC );

// save the parameter to be adjusted and/or converted after the results are processed
sqlsrv_output_param output_param( param_ref, encoding, param_num, static_cast<SQLUINTEGER>( buffer_len ));
sqlsrv_output_param output_param( param_ref, encoding, param_num, static_cast<SQLUINTEGER>( buffer_len ), zval_was_long );

save_output_param_for_later( stmt, output_param TSRMLS_CC );

Expand Down Expand Up @@ -2127,6 +2145,15 @@ void finalize_output_parameters( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
else {
core::sqlsrv_zval_stringl(value_z, str, str_len);
}
if ( output_param->is_long ) {
zval* value_z_temp = ( zval * )sqlsrv_malloc( sizeof( zval ));
ZVAL_COPY( value_z_temp, value_z );
convert_to_double( value_z_temp );
if ( Z_DVAL_P( value_z_temp ) > INT_MIN && Z_DVAL_P( value_z_temp ) < INT_MAX ) {
convert_to_long( value_z );
}
sqlsrv_free( value_z_temp );
}
}
break;
case IS_LONG:
Expand Down
82 changes: 82 additions & 0 deletions test/functional/pdo_sqlsrv/pdo_bigint_outparam.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
--TEST--
Test for binding bigint output and inout parameters
--SKIPIF--
<?php require('skipif_mid-refactor.inc'); ?>
--FILE--
<?php
require_once("MsCommon_mid-refactor.inc");

$conn = connect();

// Create the table
$tbname = "bigint_table";
createTable($conn, $tbname, array("c1_bigint" => "bigint"));

// Create a Stored Procedure
$spname = "selectBigint";
$spSql = "CREATE PROCEDURE $spname (@c1_bigint bigint OUTPUT) AS
SELECT @c1_bigint = c1_bigint FROM $tbname";
$conn->query($spSql);

// Insert a large bigint
insertRow($conn, $tbname, array("c1_bigint" => 922337203685479936));

// Call stored procedure with output
$outSql = "{CALL $spname (?)}";
$bigintOut = 0;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $bigintOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("Large bigint output:\n" );
var_dump($bigintOut);
printf("\n");

// Call stored procedure with inout
$bigintOut = 0;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $bigintOut, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("Large bigint inout:\n" );
var_dump($bigintOut);
printf("\n");

$conn->exec("TRUNCATE TABLE $tbname");

// Insert a random small value truncated from the bigint input
insertRow($conn, $tbname, array("c1_bigint" => 922337203));

// Call stored procedure with output
$bigintOut = 0;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $bigintOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("Small bigint output:\n" );
var_dump($bigintOut);
printf("\n");

// Call stored procedure with inout
$bigintOut = 0;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $bigintOut, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("Small bigint inout:\n" );
var_dump($bigintOut);
printf("\n");

dropProc($conn, $spname);
dropTable($conn, $tbname);
unset($stmt);
unset($conn);
?>
--EXPECT--
Large bigint output:
string(18) "922337203685479936"

Large bigint inout:
string(18) "922337203685479936"

Small bigint output:
int(922337203)

Small bigint inout:
int(922337203)
82 changes: 82 additions & 0 deletions test/functional/pdo_sqlsrv/pdo_bool_outparam.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
--TEST--
Test for binding boolean output and inout parameters
--SKIPIF--
<?php require('skipif_mid-refactor.inc'); ?>
--FILE--
<?php
require_once("MsCommon_mid-refactor.inc");

$conn = connect();

// Create the table
$tbname = "bool_table";
createTable($conn, $tbname, array("c1_bool" => "int"));

// Create a Stored Procedure
$spname = "selectBool";
$spSql = "CREATE PROCEDURE $spname (@c1_bool int OUTPUT) AS
SELECT @c1_bool = c1_bool FROM $tbname";
$conn->query($spSql);

// Insert 1
insertRow($conn, $tbname, array("c1_bool" => 1));

// Call stored procedure with output
$outSql = "{CALL $spname (?)}";
$boolOut = false;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $boolOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("True bool output:\n" );
var_dump($boolOut);
printf("\n");

// Call stored procedure with inout
$boolOut = false;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $boolOut, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("True bool inout:\n" );
var_dump($boolOut);
printf("\n");

$conn->exec("TRUNCATE TABLE $tbname");

// Insert 0
insertRow($conn, $tbname, array("c1_bool" => 0));

// Call stored procedure with output
$boolOut = true;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $boolOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("True bool output:\n" );
var_dump($boolOut);
printf("\n");

// Call stored procedure with inout
$boolOut = true;
$stmt = $conn->prepare($outSql);
$stmt->bindParam(1, $boolOut, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
printf("True bool inout:\n" );
var_dump($boolOut);
printf("\n");

dropProc($conn, $spname);
dropTable($conn, $tbname);
unset($stmt);
unset($conn);
?>
--EXPECT--
True bool output:
int(1)

True bool inout:
int(1)

True bool output:
int(0)

True bool inout:
int(0)
1 change: 1 addition & 0 deletions test/functional/sqlsrv/MsHelper.inc
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ function connect($options = array(), $disableCE = false)
*/
function createTable($conn, $tbname, $columnMetaArr)
{
require_once("MsCommon.inc");
dropTable($conn, $tbname);
$colDef = "";
foreach ($columnMetaArr as $meta) {
Expand Down
Loading