Merge pull request #292 from v-dareck/bindparam_out_string_fault
Add check for SQL_NO_TOTAL for SQLBindParameter out parameter
This commit is contained in:
commit
cc925ad9b3
|
@ -2030,6 +2030,15 @@ void finalize_output_parameters( sqlsrv_stmt* stmt TSRMLS_DC )
|
|||
throw core::CoreException();
|
||||
}
|
||||
|
||||
// For ODBC 11+ see https://msdn.microsoft.com/en-us/library/jj219209.aspx
|
||||
// A length value of SQL_NO_TOTAL for SQLBindParameter indicates that the buffer contains up to
|
||||
// output_param->original_buffer_len data and is NULL terminated.
|
||||
// The IF statement can be true when using connection pooling with unixODBC 2.3.4.
|
||||
if ( str_len == SQL_NO_TOTAL )
|
||||
{
|
||||
str_len = output_param->original_buffer_len - null_size;
|
||||
}
|
||||
|
||||
// if it's not in the 8 bit encodings, then it's in UTF-16
|
||||
if( output_param->encoding != SQLSRV_ENCODING_CHAR && output_param->encoding != SQLSRV_ENCODING_BINARY ) {
|
||||
bool converted = convert_zval_string_from_utf16(output_param->encoding, value_z, str_len);
|
||||
|
|
459
test/sqlsrv/sqlsrv_bind_param_out_string.phpt
Normal file
459
test/sqlsrv/sqlsrv_bind_param_out_string.phpt
Normal file
|
@ -0,0 +1,459 @@
|
|||
--TEST--
|
||||
Verify the Binary and Char encoding output when binding output string with SQLSTYPE option with different size.
|
||||
--DESCRIPTION--
|
||||
Tests different sizes of output string which may cause ODBC to return trunc error info.
|
||||
With unixODBC 2.3.4, when connection pooling is enabled, error information maybe returned differently
|
||||
than older versions (or with pooling disabled).
|
||||
The NVARCHAR(1) section would cause an ODBC call to return an errorinfo to the driver causing the statement to fail.
|
||||
With unixODBC 2.3.4 + pooling the statement executes without error.
|
||||
--FILE--
|
||||
|
||||
<?php
|
||||
require_once("autonomous_setup.php");
|
||||
|
||||
$connectionInfo = array("UID"=>"$username", "PWD"=>"$password");
|
||||
$conn = sqlsrv_connect($serverName, $connectionInfo);
|
||||
if( $conn === false ) {
|
||||
die( print_r( sqlsrv_errors(), true ));
|
||||
}
|
||||
$conn = null;
|
||||
|
||||
$conn = sqlsrv_connect($serverName, $connectionInfo);
|
||||
if( $conn === false ) {
|
||||
die( print_r( sqlsrv_errors(), true ));
|
||||
}
|
||||
|
||||
|
||||
$bindtable = "#BindStringTest";
|
||||
$sproc = "#uspPerson";
|
||||
|
||||
// Create table
|
||||
$stmt = sqlsrv_query( $conn, "CREATE TABLE $bindtable (PersonID int, Name nvarchar(50))" );
|
||||
if( $stmt === false ) {
|
||||
die( print_r( sqlsrv_errors(), true ));
|
||||
}
|
||||
|
||||
$stmt = sqlsrv_query( $conn, "INSERT INTO $bindtable (PersonID, Name) VALUES (10, N'Miller')" );
|
||||
if( $stmt === false ) {
|
||||
die( print_r( sqlsrv_errors(), true ));
|
||||
}
|
||||
|
||||
$stmt = sqlsrv_query( $conn, "INSERT INTO $bindtable (PersonID, Name) VALUES (11, N'JSmith')" );
|
||||
if( $stmt === false ) {
|
||||
die( print_r( sqlsrv_errors(), true ));
|
||||
}
|
||||
|
||||
$tsql_createSP = "CREATE PROCEDURE $sproc
|
||||
@id int, @return nvarchar(50) OUTPUT
|
||||
AS
|
||||
BEGIN
|
||||
SET NOCOUNT ON;
|
||||
SET @return = (SELECT Name FROM $bindtable WHERE PersonID = @id)
|
||||
END";
|
||||
|
||||
$stmt = sqlsrv_query( $conn, $tsql_createSP);
|
||||
if( $stmt === false )
|
||||
{
|
||||
echo "Error in executing statement 2.\n";
|
||||
die( print_r( sqlsrv_errors(), true));
|
||||
}
|
||||
|
||||
$tsql_callSP = "{call $sproc( ? , ?)}";
|
||||
|
||||
|
||||
//***********************************************************************************************
|
||||
|
||||
echo "NVARCHAR(32)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NVARCHAR(32)
|
||||
));
|
||||
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 6;
|
||||
$expectedValue = "Miller";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NVARCHAR(32)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 12;
|
||||
$expectedValue = "M\0i\0l\0l\0e\0r\0";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
//***********************************************************************************************
|
||||
echo "\n\n";
|
||||
echo "NVARCHAR(50)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NVARCHAR(50)
|
||||
));
|
||||
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 6;
|
||||
$expectedValue = "Miller";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NVARCHAR(50)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 12;
|
||||
$expectedValue = "M\0i\0l\0l\0e\0r\0";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
//***********************************************************************************************
|
||||
echo "\n\n";
|
||||
echo "NVARCHAR(1)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
|
||||
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NVARCHAR(1)
|
||||
));
|
||||
|
||||
// with unixODBC 2.3.4 connection pooling the statement may not fail.
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
echo "Statement should fail\n";
|
||||
}
|
||||
|
||||
$expectedLength = 1;
|
||||
$expectedValue = "M";
|
||||
$actualValue = $return;
|
||||
$actualLength = strlen($return);
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NVARCHAR(1)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
echo "Statement should fail\n";
|
||||
}
|
||||
|
||||
$expectedLength = 2;
|
||||
$expectedValue = "M\0";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
//***********************************************************************************************
|
||||
echo "\n\n";
|
||||
echo "NCHAR(32)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NCHAR(32)
|
||||
));
|
||||
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 32;
|
||||
$expectedValue = "Miller ";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NCHAR(32)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 64;
|
||||
$expectedValue = "M\0i\0l\0l\0e\0r\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
//***********************************************************************************************
|
||||
echo "\n\n";
|
||||
echo "NCHAR(0)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NCHAR(0)
|
||||
));
|
||||
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
echo "Statement should fail\n";
|
||||
}
|
||||
|
||||
$expectedLength = 0;
|
||||
$expectedValue = "";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NCHAR(0)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
echo "Statement should fail\n";
|
||||
}
|
||||
|
||||
$expectedLength = 0;
|
||||
$expectedValue = "";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
//***********************************************************************************************
|
||||
echo "\n\n";
|
||||
echo "NCHAR(50)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NCHAR(50)
|
||||
));
|
||||
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 50;
|
||||
$expectedValue = "Miller ";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NCHAR(50)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 100;
|
||||
$expectedValue = "M\0i\0l\0l\0e\0r\0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0";
|
||||
$actualLength = strlen($return);
|
||||
$actualValue = $return;
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
//***********************************************************************************************
|
||||
// NCHAR 1: less than length of the returned value
|
||||
echo "\n\n";
|
||||
echo "NCHAR(1)\n";
|
||||
echo "---------Encoding char-----------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
|
||||
SQLSRV_SQLTYPE_NCHAR(1)
|
||||
));
|
||||
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) === false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 1;
|
||||
$expectedValue = "M";
|
||||
$actualValue = $return;
|
||||
$actualLength = strlen($return);
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
echo "---------Encoding binary---------\n";
|
||||
$id = 10;
|
||||
$return = "";
|
||||
$params = array(
|
||||
array($id, SQLSRV_PARAM_IN),
|
||||
array(&$return, SQLSRV_PARAM_OUT,
|
||||
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
|
||||
SQLSRV_SQLTYPE_NCHAR(1)
|
||||
));
|
||||
if( $stmt = sqlsrv_query($conn, $tsql_callSP, $params) == false)
|
||||
{
|
||||
print_r( sqlsrv_errors(), true);
|
||||
}
|
||||
|
||||
$expectedLength = 2;
|
||||
$expectedValue = "M\0";
|
||||
$actualValue = $return;
|
||||
$actualLength = strlen($return);
|
||||
compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue );
|
||||
|
||||
sqlsrv_close($conn);
|
||||
|
||||
$status = true;
|
||||
|
||||
/**
|
||||
* Compares actual output to expected one
|
||||
* @param $expectedLength The length of the expected value
|
||||
* @param $expectedValue The expected value
|
||||
* @param $actualLength The length of the actual value
|
||||
* @param $actualValue The actual value
|
||||
*/
|
||||
function compareResults ( $expectedLength, $expectedValue, $actualLength, $actualValue )
|
||||
{
|
||||
$match = false;
|
||||
if ( $expectedLength == $actualLength)
|
||||
{
|
||||
if ( strncmp ( $actualValue, $expectedValue, $expectedLength ) == 0 )
|
||||
{
|
||||
$match = true;
|
||||
}
|
||||
}
|
||||
if ( !$match )
|
||||
{
|
||||
echo "The actual result is different from the expected one \n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "The actual result is the same as the expected one \n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
NVARCHAR(32)
|
||||
---------Encoding char-----------
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
The actual result is the same as the expected one
|
||||
|
||||
|
||||
NVARCHAR(50)
|
||||
---------Encoding char-----------
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
The actual result is the same as the expected one
|
||||
|
||||
|
||||
NVARCHAR(1)
|
||||
---------Encoding char-----------
|
||||
Statement should fail
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
Statement should fail
|
||||
The actual result is the same as the expected one
|
||||
|
||||
|
||||
NCHAR(32)
|
||||
---------Encoding char-----------
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
The actual result is the same as the expected one
|
||||
|
||||
|
||||
NCHAR(0)
|
||||
---------Encoding char-----------
|
||||
Statement should fail
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
Statement should fail
|
||||
The actual result is the same as the expected one
|
||||
|
||||
|
||||
NCHAR(50)
|
||||
---------Encoding char-----------
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
The actual result is the same as the expected one
|
||||
|
||||
|
||||
NCHAR(1)
|
||||
---------Encoding char-----------
|
||||
The actual result is the same as the expected one
|
||||
---------Encoding binary---------
|
||||
The actual result is the same as the expected one
|
Loading…
Reference in a new issue