Skip to content

Commit

Permalink
Merge pull request #584 from yitam/textTypes
Browse files Browse the repository at this point in the history
Added error handling for LOB types as output parameters
  • Loading branch information
yitam authored Nov 3, 2017
2 parents 4543ed1 + ef14400 commit 628e0c9
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 2 deletions.
4 changes: 4 additions & 0 deletions source/pdo_sqlsrv/pdo_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ pdo_error PDO_ERRORS[] = {
PDO_SQLSRV_ERROR_CE_EMULATE_PREPARE_UNSUPPORTED,
{ IMSSP, (SQLCHAR*) "Parameterized statement with attribute PDO::ATTR_EMULATE_PREPARES is not supported in a Column Encryption enabled Connection.", -82, false }
},
{
SQLSRV_ERROR_OUTPUT_PARAM_TYPES_NOT_SUPPORTED,
{ IMSSP, (SQLCHAR*) "Stored Procedures do not support text, ntext or image as OUTPUT parameters.", -83, false }
},
{ UINT_MAX, {} }
};

Expand Down
1 change: 1 addition & 0 deletions source/shared/core_sqlsrv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,7 @@ enum SQLSRV_ERROR_CODES {
SQLSRV_ERROR_KEYSTORE_PATH_MISSING,
SQLSRV_ERROR_KEYSTORE_KEY_MISSING,
SQLSRV_ERROR_KEYSTORE_INVALID_VALUE,
SQLSRV_ERROR_OUTPUT_PARAM_TYPES_NOT_SUPPORTED,

// Driver specific error codes starts from here.
SQLSRV_ERROR_DRIVER_SPECIFIC = 1000,
Expand Down
11 changes: 9 additions & 2 deletions source/shared/core_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,15 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
}
}

// if it's an output parameter and the user asks for a certain type, we have to convert the zval to that type so
// when the buffer is filled, the type is correct
// If the user specifies a certain type for an output parameter, we have to convert the zval
// to that type so that when the buffer is filled, the type is correct. But first,
// should check if a LOB type is specified.
CHECK_CUSTOM_ERROR( direction != SQL_PARAM_INPUT && ( sql_type == SQL_LONGVARCHAR
|| sql_type == SQL_WLONGVARCHAR || sql_type == SQL_LONGVARBINARY ),
stmt, SQLSRV_ERROR_OUTPUT_PARAM_TYPES_NOT_SUPPORTED ){
throw core::CoreException();
}

if( direction == SQL_PARAM_OUTPUT ){
switch( php_out_type ) {
case SQLSRV_PHPTYPE_INT:
Expand Down
5 changes: 5 additions & 0 deletions source/sqlsrv/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ ss_error SS_ERRORS[] = {
SQLSRV_ERROR_SPECIFIED_DRIVER_NOT_FOUND,
{ IMSSP, (SQLCHAR*) "The specified ODBC Driver is not found.", -107, false }
},
{
SQLSRV_ERROR_OUTPUT_PARAM_TYPES_NOT_SUPPORTED,
{ IMSSP, (SQLCHAR*) "Stored Procedures do not support text, ntext or image as OUTPUT parameters.", -108, false }
},

// terminate the list of errors/warnings
{ UINT_MAX, {} }
};
Expand Down
134 changes: 134 additions & 0 deletions test/functional/sqlsrv/srv_231_string_truncation_text.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
--TEST--
GitHub issue #231 - String truncation when binding text/ntext/image to check error messages
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif_versions_old.inc'); ?>
--FILE--
<?php

sqlsrv_configure('WarningsReturnAsErrors', 1);

require_once("MsCommon.inc");

// connect
$conn = AE\connect();
if (!$conn) {
fatalError("Connection could not be established.\n");
}

$tableName = 'testLOBTypes_GH231';
$columnNames = array("c1", "c2");

for ($k = 1; $k <= 3; $k++) {
$sqlType = sqlType($k);
$columns = array(new AE\ColumnMeta('int', $columnNames[0]),
new AE\ColumnMeta($sqlType, $columnNames[1]));
AE\createTable($conn, $tableName, $columns);

$sql = "INSERT INTO [$tableName] ($columnNames[0], $columnNames[1]) VALUES (?, ?)";
$data = getData($k);

$phpType = SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR);
$sqlsrvSQLType = sqlsrvSqlType($k, strlen($data));

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

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

dropTable($conn, $tableName);
}

sqlsrv_close($conn);


function execProc($conn, $tableName, $columnNames, $k, $data, $sqlType)
{
$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);

echo "\nData Type: ".$sqlType." binding as \n";

$direction = SQLSRV_PARAM_OUT;
echo "Output parameter: ";
invokeProc($conn, $procName, $k, $direction, $data);

$direction = SQLSRV_PARAM_INOUT;
echo "InOut parameter: ";
invokeProc($conn, $procName, $k, $direction, $data);

dropProc($conn, $procName);
}

function invokeProc($conn, $procName, $k, $direction, $data)
{
$sqlsrvSQLType = sqlsrvSqlType($k, strlen($data));
$callArgs = "?, ?";

// Data to initialize $callResult variable
$initData = "ShortString";
$callResult = $initData;

// No need to specify the SQLSRV PHP type but must specify SQLSRV SQL Type
// when AE is enabled
$intType = AE\isColEncrypted()? SQLSRV_SQLTYPE_INT : null;
$params = array( array( $k, SQLSRV_PARAM_IN, null, $intType ),
array( &$callResult, $direction, null, $sqlsrvSQLType ));
$stmt = sqlsrv_query($conn, "{ CALL [$procName] ($callArgs)}", $params);
if ($stmt) {
fatalError("Expect this to fail!");
} else {
echo (sqlsrv_errors()[0]['message']) . PHP_EOL;
}
}

function getData($k)
{
$data = "LongStringForTesting";
return $data;
}

function sqlType($k)
{
switch ($k) {
case 1: return ("text");
case 2: return ("ntext");
case 3: return ("image");
default: break;
}
return ("udt");
}

function sqlsrvSqlType($k, $dataSize)
{
switch ($k) {
case 1: return (SQLSRV_SQLTYPE_TEXT);
case 2: return (SQLSRV_SQLTYPE_NTEXT);
case 3: return (SQLSRV_SQLTYPE_IMAGE);
default: break;
}
return (SQLSRV_SQLTYPE_UDT);
}

?>

--EXPECT--

Data Type: text binding as
Output parameter: Stored Procedures do not support text, ntext or image as OUTPUT parameters.
InOut parameter: Stored Procedures do not support text, ntext or image as OUTPUT parameters.

Data Type: ntext binding as
Output parameter: Stored Procedures do not support text, ntext or image as OUTPUT parameters.
InOut parameter: Stored Procedures do not support text, ntext or image as OUTPUT parameters.

Data Type: image binding as
Output parameter: Stored Procedures do not support text, ntext or image as OUTPUT parameters.
InOut parameter: Stored Procedures do not support text, ntext or image as OUTPUT parameters.

0 comments on commit 628e0c9

Please sign in to comment.