Add check for SQL_NO_TOTAL for SQLBindParameter out parameter.

This commit is contained in:
v-dareck 2017-02-16 11:50:24 -08:00
parent c6157b0f79
commit 98fd299a31
2 changed files with 463 additions and 0 deletions

View file

@ -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);

View file

@ -0,0 +1,454 @@
--TEST--
Verify the Binary and Char encoding output when binding output string with SQLSTYPE option with different size
--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;
// with unixODBC 2.3.4 + connection pooling the NVARCHAR(1) section below may seg fault
$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