Skip to content

Commit

Permalink
Fixed the error in Issue 570 (#952)
Browse files Browse the repository at this point in the history
  • Loading branch information
yitam authored Mar 14, 2019
1 parent 1332e3b commit 840ebc2
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 1 deletion.
3 changes: 2 additions & 1 deletion source/shared/core_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ size_t sqlsrv_stream_read( _Inout_ php_stream* stream, _Out_writes_bytes_(count)
break;
}

SQLRETURN r = SQLGetData( ss->stmt->handle(), ss->field_index + 1, c_type, get_data_buffer, count /*BufferLength*/, &read );
// Warnings will be handled below
SQLRETURN r = ss->stmt->current_results->get_data(ss->field_index + 1, c_type, get_data_buffer, count /*BufferLength*/, &read, false /*handle_warning*/ TSRMLS_CC);

CHECK_SQL_ERROR( r, ss->stmt ) {
stream->eof = 1;
Expand Down
143 changes: 143 additions & 0 deletions test/functional/sqlsrv/srv_570_fetch_varbinary.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
--TEST--
GitHub issue #570 - fetching a varbinary field as a stream using client buffer
--DESCRIPTION--
Verifies that a varbinary field (with size or max) can be successfully fetched even when a client buffer is used. There is no more "Invalid cursor state" error.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php

function compareStreams($input, $result)
{
while (($line1 = fread($input, 80)) && ($line2 = fread($result, 80))) {
if ($line1 != $line2) {
echo "Stream not identical\n";
break;
}
}
}

function fetchData($stmt, $data, $buffered)
{
if ($buffered) {
$result = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
} else {
$result = sqlsrv_fetch($stmt);
}
if ($result === false) {
fatalError('Error when fetching data');
}

// Get image data as a binary stream
$image = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
if ($image === false) {
fatalError('Error in calling sqlsrv_get_field');
}

// Does the retrieved stream match with the original?
compareStreams($data, $image);

fclose($image);
}

function runQuery($conn, $data, $tsql, $buffered, $prepared)
{
if ($prepared) {
if ($buffered) {
// Pick a random size for the buffer large enough for this test
$stmt = sqlsrv_prepare($conn, $tsql, array(), array("Scrollable" => SQLSRV_CURSOR_CLIENT_BUFFERED, "ClientBufferMaxKBSize" => 51200));
} else {
$stmt = sqlsrv_prepare($conn, $tsql);
}
if ($stmt === false) {
fatalError("Error in preparing the query ($buffered).");
}

$result = sqlsrv_execute($stmt);
if ($result === false) {
fatalError("Error in executing the query ($buffered).");
}
} else {
if ($buffered) {
// Use the default buffer size in this case
$stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>SQLSRV_CURSOR_CLIENT_BUFFERED));
} else {
$stmt = sqlsrv_query($conn, $tsql);
}

if ($stmt === false) {
fatalError("Error in sqlsrv_query ($buffered).");
}
}

fetchData($stmt, $data, $buffered);
}

function runTest($conn, $columnType, $path)
{
$tableName = 'srvTestTable_570' . rand(0, 10);
dropTable($conn, $tableName);

// Create the test table with only one column
$tsql = "CREATE TABLE $tableName([picture] $columnType NOT NULL)";
$stmt = sqlsrv_query($conn, $tsql);
if (!$stmt) {
fatalError("Failed to create table $tableName\n");
}

// Insert php.gif as stream data
$tsql = "INSERT INTO $tableName (picture) VALUES (?)";

$data = fopen($path, 'rb');
if (!$data) {
fatalError('Could not open image for reading.');
}

$params = array($data, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
$stmt = sqlsrv_query($conn, $tsql, array($params));
if ($stmt === false) {
fatalError("Failed to insert image into $tableName");
}
do {
$read = sqlsrv_send_stream_data($stmt);
} while ($read);
sqlsrv_free_stmt($stmt);

// Start testing, with or without client buffer, using prepared statement or direct query
$tsql = "SELECT picture FROM $tableName";
runQuery($conn, $data, $tsql, false, true);
runQuery($conn, $data, $tsql, true, true);
runQuery($conn, $data, $tsql, false, false);
runQuery($conn, $data, $tsql, true, false);

// Clean up
fclose($data);

dropTable($conn, $tableName);
}

require_once('MsCommon.inc');

$conn = connect();
if ($conn === false) {
die(print_r(sqlsrv_errors(), true));
}

if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$pic = '\\php.gif';
} else { // other than Windows
$pic = '/php.gif';
}
$path = dirname($_SERVER['PHP_SELF']) . $pic;

runTest($conn, 'VARBINARY(MAX)', $path);
runTest($conn, 'VARBINARY(4096)', $path);

echo "Done\n";

sqlsrv_close($conn);
?>
--EXPECT--
Done

0 comments on commit 840ebc2

Please sign in to comment.