diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp
index 052884eeb..f9c854b27 100644
--- a/source/shared/core_stmt.cpp
+++ b/source/shared/core_stmt.cpp
@@ -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:
@@ -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;
diff --git a/test/sqlsrv/srv_231_string_truncation_varchar_max.phpt b/test/sqlsrv/srv_231_string_truncation_varchar_max.phpt
new file mode 100644
index 000000000..1720d353e
--- /dev/null
+++ b/test/sqlsrv/srv_231_string_truncation_varchar_max.phpt
@@ -0,0 +1,204 @@
+--TEST--
+GitHub issue #231 - String truncation when binding varchar(max)
+--SKIPIF--
+--FILE--
+$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 = "The quick brown fox jumps over the lazy dog0123456789";
+ }
+
+ 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: The quick brown fox jumps over the lazy dog0123456789
+Initial data: ShortString
+Initial call result: ShortString
+New call result: The quick brown fox jumps over the lazy dog0123456789
+
+