Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue #270 fix #297

Merged
merged 9 commits into from
Feb 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions source/pdo_sqlsrv/pdo_stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,12 +721,10 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
sqlsrv_phptype sqlsrv_php_type;
SQLSRV_ASSERT( colno >= 0 && colno < static_cast<int>( driver_stmt->current_meta_data.size()),
"Invalid column number in pdo_sqlsrv_stmt_get_col_data" );
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_type ),
static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_size ),
true );

// set the encoding if the user specified one via bindColumn, otherwise use the statement's encoding
sqlsrv_php_type.typeinfo.encoding = driver_stmt->encoding();
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[colno]->field_type ),
static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[colno]->field_size ), true );

// if a column is bound to a type different than the column type, figure out a way to convert it to the
// type they want
Expand Down Expand Up @@ -1306,6 +1304,8 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUI
"Invalid encoding on the connection. Must not be invalid or default." );
}

sqlsrv_phptype.typeinfo.encoding = local_encoding;

switch( sql_type ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this change mean that each field can have its own encoding set via bindColumn?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it sets the encoding to stmt or conn encoding and in case of binary or invalid it is set to binary or invalid encoding respectively.

case SQL_BIT:
case SQL_INTEGER:
Expand All @@ -1316,7 +1316,6 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUI
}
else {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
sqlsrv_phptype.typeinfo.encoding = local_encoding;
}
break;
case SQL_FLOAT:
Expand All @@ -1326,7 +1325,6 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUI
}
else {
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
sqlsrv_phptype.typeinfo.encoding = local_encoding;
}
break;
case SQL_BIGINT:
Expand All @@ -1345,7 +1343,6 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( SQLINTEGER sql_type, SQLUI
case SQL_WLONGVARCHAR:
case SQL_SS_XML:
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
sqlsrv_phptype.typeinfo.encoding = local_encoding;
break;
case SQL_BINARY:
case SQL_LONGVARBINARY:
Expand Down
92 changes: 92 additions & 0 deletions test/pdo_sqlsrv/pdo_270_fetch_binary.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
--TEST--
Test fetch from binary, varbinary, varbinary(max), image columns, without setting binary encoding.
--DESCRIPTION--
Verifies GitHub issue 270 is fixed, users could not retrieve the data as inserted in binary columns without setting the binary encoding either on stmt or using bindCoulmn encoding.
This test verifies that the data inserted in binary columns can be retrieved using fetch, fetchColumn, fetchObject, and fetchAll functions.

--FILE--
<?php

require_once("autonomous_setup.php");

$tableName = 'test_binary'.rand();
$columns = array( 'col1', 'col2', 'col3', 'col4');

// Connect
$conn = new PDO( "sqlsrv:server=$serverName;Database=tempdb", $username, $password );

$sql = "CREATE TABLE $tableName ( $columns[0] binary(50), $columns[1] VARBINARY(50), $columns[2] VARBINARY(MAX), $columns[3] image)";
$conn->exec($sql);

$icon = base64_decode("This is some text to test retrieving from binary type columns");

// Insert data using bind parameters
$sql = "INSERT INTO $tableName($columns[0], $columns[1], $columns[2], $columns[3]) VALUES(?, ?, ?, ?)";
$stmt = $conn->prepare($sql);
$stmt->bindParam(1, $icon, PDO::PARAM_LOB, null, PDO::SQLSRV_ENCODING_BINARY);
$stmt->bindParam(2, $icon, PDO::PARAM_LOB, null, PDO::SQLSRV_ENCODING_BINARY);
$stmt->bindParam(3, $icon, PDO::PARAM_LOB, null, PDO::SQLSRV_ENCODING_BINARY);
$stmt->bindParam(4, $icon, PDO::PARAM_LOB, null, PDO::SQLSRV_ENCODING_BINARY);
$stmt->execute();

// loop through each column in the table
foreach ($columns as $col){
test_fetch($conn, $tableName, $col, $icon);
}
// DROP table
$conn->query("DROP TABLE $tableName") ?: die();

//free statement and connection
$stmt = null;
$conn = null;

print_r("Test finished successfully");

//calls various fetch methods
function test_fetch($conn, $tableName, $columnName, $input){

$len = strlen($input);
$result = "";
$sql = "SELECT $columnName from $tableName";

$stmt = $conn->query($sql);
$stmt->bindColumn(1, $result, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
//binary is fixed size, to evaluate output, compare it using strncmp
if( strncmp($result, $input, $len) !== 0){
print_r("\nRetrieving using bindColumn failed");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps testing equality like ($result === $input) is enough?

Copy link
Author

@Hadis-Knj Hadis-Knj Feb 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

binary column is fixed size (50), and input len is 36, so we don't care about the white spaces appended to the output and only compare the first 36 characters, this is just testing that value is not hex number anymore


$result = "";
$stmt = $conn->query($sql);
$stmt->bindColumn(1, $result, PDO::PARAM_LOB, 0 , PDO::SQLSRV_ENCODING_BINARY);
$stmt->fetch(PDO::FETCH_BOUND);
if( strncmp($result, $input, $len) !== 0){
print_r("\nRetrieving using bindColumn with encoding set failed");
}

$result = "";
$stmt = $conn->query($sql);
$result = $stmt->fetchColumn();
if( strncmp($result, $input, $len) !== 0){
print_r("\nRetrieving using fetchColumn failed");
}

$result = "";
$stmt = $conn->query($sql);
$result = $stmt->fetchObject();
if( strncmp($result->$columnName, $input, $len) !== 0){
print_r("\nRetrieving using fetchObject failed");
}

$result = "";
$stmt = $conn->query($sql);
$result = $stmt->fetchAll( PDO::FETCH_COLUMN );
if( strncmp($result[0], $input, $len) !== 0){
print_r("\nRetrieving using fetchAll failed");
}
}

?>
--EXPECT--
Test finished successfully