Skip to content

Commit

Permalink
Fixing the issue with buffered result sets, when connection option is…
Browse files Browse the repository at this point in the history
… set to utf8. See issue microsoft#192
  • Loading branch information
ulvii committed Dec 12, 2016
1 parent d3b4e38 commit 28bd839
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 12 deletions.
41 changes: 35 additions & 6 deletions pdo_sqlsrv/core_results.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::double_to_wide_string;
}

SQLSRV_ENCODING encoding = (( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() :
stmt->encoding());

// get the meta data and calculate the size of a row buffer
SQLULEN offset = null_bytes;
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
Expand All @@ -335,13 +338,30 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS
meta[i].length += sizeof( char ) + sizeof( SQLULEN ); // null terminator space
offset += meta[i].length;
break;
case SQL_CHAR:
case SQL_VARCHAR:
if ( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
}
else {
// If encoding is set to UTF-8, the following types are not necessarily column size.
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
if ( encoding == SQLSRV_ENCODING( CP_UTF8 )) {
meta[i].length *= sizeof( WCHAR );
meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space
offset += meta[i].length;
}
else {
meta[i].length += sizeof( SQLULEN ) + sizeof( char ); // length plus null terminator space
offset += meta[i].length;
}
}
break;

// these types are the column size
case SQL_BINARY:
case SQL_CHAR:
case SQL_SS_UDT:
case SQL_VARBINARY:
case SQL_VARCHAR:
// var* field types are length prefixed
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
Expand Down Expand Up @@ -408,21 +428,30 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS
switch( meta[i].type ) {

case SQL_BIGINT:
case SQL_CHAR:
case SQL_DATETIME:
case SQL_DECIMAL:
case SQL_GUID:
case SQL_NUMERIC:
case SQL_LONGVARCHAR:
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_SS_XML:
case SQL_TYPE_TIMESTAMP:
case SQL_VARCHAR:

meta[i].c_type = SQL_C_CHAR;
break;

case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
// If encoding is set to UTF-8, the following types are not necessarily column size.
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
if ( encoding == SQLSRV_ENCODING( CP_UTF8 )) {
meta[i].c_type = SQL_C_WCHAR;
}
else {
meta[i].c_type = SQL_C_CHAR;
}
break;
case SQL_SS_UDT:
case SQL_LONGVARBINARY:
case SQL_BINARY:
Expand Down
41 changes: 35 additions & 6 deletions sqlsrv/core_results.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS
conv_matrix[ SQL_C_DOUBLE ][ SQL_C_WCHAR ] = &sqlsrv_buffered_result_set::double_to_wide_string;
}

SQLSRV_ENCODING encoding = (( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() :
stmt->encoding());

// get the meta data and calculate the size of a row buffer
SQLULEN offset = null_bytes;
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
Expand All @@ -335,13 +338,30 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS
meta[i].length += sizeof( char ) + sizeof( SQLULEN ); // null terminator space
offset += meta[i].length;
break;
case SQL_CHAR:
case SQL_VARCHAR:
if ( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
}
else {
// If encoding is set to UTF-8, the following types are not necessarily column size.
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
if ( encoding == SQLSRV_ENCODING( CP_UTF8 )) {
meta[i].length *= sizeof( WCHAR );
meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space
offset += meta[i].length;
}
else {
meta[i].length += sizeof( SQLULEN ) + sizeof( char ); // length plus null terminator space
offset += meta[i].length;
}
}
break;

// these types are the column size
case SQL_BINARY:
case SQL_CHAR:
case SQL_SS_UDT:
case SQL_VARBINARY:
case SQL_VARCHAR:
// var* field types are length prefixed
if( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
offset += sizeof( void* );
Expand Down Expand Up @@ -408,21 +428,30 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS
switch( meta[i].type ) {

case SQL_BIGINT:
case SQL_CHAR:
case SQL_DATETIME:
case SQL_DECIMAL:
case SQL_GUID:
case SQL_NUMERIC:
case SQL_LONGVARCHAR:
case SQL_TYPE_DATE:
case SQL_SS_TIME2:
case SQL_SS_TIMESTAMPOFFSET:
case SQL_SS_XML:
case SQL_TYPE_TIMESTAMP:
case SQL_VARCHAR:

meta[i].c_type = SQL_C_CHAR;
break;

case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
// If encoding is set to UTF-8, the following types are not necessarily column size.
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
if ( encoding == SQLSRV_ENCODING( CP_UTF8 )) {
meta[i].c_type = SQL_C_WCHAR;
}
else {
meta[i].c_type = SQL_C_CHAR;
}
break;
case SQL_SS_UDT:
case SQL_LONGVARBINARY:
case SQL_BINARY:
Expand Down

0 comments on commit 28bd839

Please sign in to comment.