Skip to content

Commit

Permalink
For varchar(max) and the like, reset column size so that default_sql_…
Browse files Browse the repository at this point in the history
…size_and_scale() will be invoked
  • Loading branch information
yitam committed Feb 17, 2017
1 parent ff25f29 commit 909bcfe
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 0 deletions.
4 changes: 4 additions & 0 deletions source/shared/core_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALL
break;
case SQLSRV_PHPTYPE_STRING:
convert_to_string( param_z );
if (column_size == SQL_SS_LENGTH_UNLIMITED) {
column_size = SQLSRV_UNKNOWN_SIZE; // reset
}
break;
case SQLSRV_PHPTYPE_NULL:
case SQLSRV_PHPTYPE_DATETIME:
Expand Down Expand Up @@ -533,6 +536,7 @@ void core_sqlsrv_bind_param( sqlsrv_stmt* stmt, SQLUSMALLINT param_num, SQLSMALL
case SQL_VARBINARY:
case SQL_VARCHAR:
case SQL_WVARCHAR:
case SQL_SS_XML:
column_size = SQL_SS_LENGTH_UNLIMITED;
break;

Expand Down
204 changes: 204 additions & 0 deletions test/sqlsrv/srv_231_string_truncation_varchar_max.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
--TEST--
GitHub issue #231 - String truncation when binding varchar(max)
--SKIPIF--
--FILE--
<?php

sqlsrv_configure( 'WarningsReturnAsErrors', 1 );

require_once("autonomous_setup.php");

// Connect
$connectionInfo = array( "UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}

$tableName = "#testDataTypes_GH231";
$columnNames = array( "c1","c2" );

for ($k = 1; $k <= 8; $k++)
{
$sqlType = GetSqlType($k);
$dataType = "[$columnNames[0]] int, [$columnNames[1]] $sqlType";

$sql = "CREATE TABLE [$tableName] ($dataType)";
$stmt1 = sqlsrv_query($conn, $sql);
sqlsrv_free_stmt($stmt1);

$sql = "INSERT INTO [$tableName] ($columnNames[0], $columnNames[1]) VALUES (?, ?)";
$data = GetData($k);
$phpType = GetPhpType($k);
$driverType = GetDriverType($k, strlen($data));

$params = array($k, array($data, SQLSRV_PARAM_IN, $phpType, $driverType));
$stmt2 = sqlsrv_prepare($conn, $sql, $params);
sqlsrv_execute($stmt2);
sqlsrv_free_stmt($stmt2);

ExecProc($conn, $tableName, $columnNames, $k, $data, $sqlType);

$stmt3 = sqlsrv_query($conn, "DROP TABLE [$tableName]");
sqlsrv_free_stmt($stmt3);
}

sqlsrv_close($conn);


function ExecProc($conn, $tableName, $columnNames, $k, $data, $sqlType)
{
$driverType = GetDriverType($k, strlen($data));

$spArgs = "@p1 int, @p2 $sqlType OUTPUT";
$spCode = "SET @p2 = ( SELECT c2 FROM $tableName WHERE c1 = @p1 )";
$procName = "testBindOutSp";

$stmt1 = sqlsrv_query($conn, "CREATE PROC [$procName] ($spArgs) AS BEGIN $spCode END");
sqlsrv_free_stmt($stmt1);

$callArgs = "?, ?";

// Data to initialize $callResult variable. This variable should be shorter than inserted data in the table
$initData = "ShortString";
$callResult = $initData;

// Do not specify PHP type
$params = array( array( $k, SQLSRV_PARAM_IN ),
array( &$callResult, SQLSRV_PARAM_OUT, null, $driverType ));

echo "\nData Type: ".$sqlType."\n";
echo "Table data:\t$data\nInitial data:\t$initData\nInitial call result:\t$callResult\n";

$stmt2 = sqlsrv_query($conn, "{ CALL [$procName] ($callArgs)}", $params);

// $callResult should be updated to the value in the table
echo "New call result:\t$callResult\n\n";

if($stmt2 === false)
{
var_dump( sqlsrv_errors());
}
else
{
sqlsrv_free_stmt($stmt2);
}

$stmt3 = sqlsrv_query($conn, "DROP PROC [$procName]");
sqlsrv_free_stmt($stmt3);
}

function GetData($k)
{
$data = "LongStringForTesting";
if ($k == 8) {
$data = "<XmlTestData><Letters1>The quick brown fox jumps over the lazy dog</Letters1><Digits1>0123456789</Digits1></XmlTestData>";
}

return $data;
}

function GetPhpType($k)
{
$phpType = SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR);
if ($k == 7) {
$phpType = SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY);
}

return $phpType;
}

function GetSqlType($k)
{
switch ($k)
{
case 1: return ("char(512)");
case 2: return ("varchar(512)");
case 3: return ("varchar(max)");
case 4: return ("nchar(512)");
case 5: return ("nvarchar(512)");
case 6: return ("nvarchar(max)");
case 7: return ("varbinary(max)");
case 8: return ("xml");
default: break;
}
return ("udt");
}

function GetDriverType($k, $dataSize)
{
switch ($k)
{
case 1: return (SQLSRV_SQLTYPE_CHAR($dataSize));
case 2: return (SQLSRV_SQLTYPE_VARCHAR($dataSize));
case 3: return (SQLSRV_SQLTYPE_VARCHAR('max'));
case 4: return (SQLSRV_SQLTYPE_NCHAR($dataSize));
case 5: return (SQLSRV_SQLTYPE_NVARCHAR($dataSize));
case 6: return (SQLSRV_SQLTYPE_NVARCHAR('max'));
case 7: return (SQLSRV_SQLTYPE_VARBINARY('max'));
case 8: return (SQLSRV_SQLTYPE_XML);

default: break;
}
return (SQLSRV_SQLTYPE_UDT);
}

?>
--EXPECT--

Data Type: char(512)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: LongStringForTesting


Data Type: varchar(512)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: LongStringForTesting


Data Type: varchar(max)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: LongStringForTesting


Data Type: nchar(512)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: LongStringForTesting


Data Type: nvarchar(512)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: LongStringForTesting


Data Type: nvarchar(max)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: LongStringForTesting


Data Type: varbinary(max)
Table data: LongStringForTesting
Initial data: ShortString
Initial call result: ShortString
New call result: 4C6F6E67537472696E67466F7254657374696E67


Data Type: xml
Table data: <XmlTestData><Letters1>The quick brown fox jumps over the lazy dog</Letters1><Digits1>0123456789</Digits1></XmlTestData>
Initial data: ShortString
Initial call result: ShortString
New call result: <XmlTestData><Letters1>The quick brown fox jumps over the lazy dog</Letters1><Digits1>0123456789</Digits1></XmlTestData>


0 comments on commit 909bcfe

Please sign in to comment.