From 28bd83954c133d623e7eb6a487ed2e84936b4ae8 Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 12 Dec 2016 15:39:50 -0800 Subject: [PATCH 1/4] Fixing the issue with buffered result sets, when connection option is set to utf8. See issue #192 --- pdo_sqlsrv/core_results.cpp | 41 +++++++++++++++++++++++++++++++------ sqlsrv/core_results.cpp | 41 +++++++++++++++++++++++++++++++------ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/pdo_sqlsrv/core_results.cpp b/pdo_sqlsrv/core_results.cpp index a5471ac8..d01b2820 100644 --- a/pdo_sqlsrv/core_results.cpp +++ b/pdo_sqlsrv/core_results.cpp @@ -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 ) { @@ -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* ); @@ -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: diff --git a/sqlsrv/core_results.cpp b/sqlsrv/core_results.cpp index a5471ac8..d01b2820 100644 --- a/sqlsrv/core_results.cpp +++ b/sqlsrv/core_results.cpp @@ -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 ) { @@ -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* ); @@ -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: From 505aa310525f8658f210c90a63a40a882c281bf4 Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 12 Dec 2016 16:04:12 -0800 Subject: [PATCH 2/4] removing new lines --- pdo_sqlsrv/core_results.cpp | 3 ++- sqlsrv/core_results.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pdo_sqlsrv/core_results.cpp b/pdo_sqlsrv/core_results.cpp index d01b2820..7fde182c 100644 --- a/pdo_sqlsrv/core_results.cpp +++ b/pdo_sqlsrv/core_results.cpp @@ -437,9 +437,9 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS case SQL_SS_TIMESTAMPOFFSET: case SQL_SS_XML: case SQL_TYPE_TIMESTAMP: - meta[i].c_type = SQL_C_CHAR; break; + case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: @@ -452,6 +452,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS meta[i].c_type = SQL_C_CHAR; } break; + case SQL_SS_UDT: case SQL_LONGVARBINARY: case SQL_BINARY: diff --git a/sqlsrv/core_results.cpp b/sqlsrv/core_results.cpp index d01b2820..7fde182c 100644 --- a/sqlsrv/core_results.cpp +++ b/sqlsrv/core_results.cpp @@ -437,9 +437,9 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS case SQL_SS_TIMESTAMPOFFSET: case SQL_SS_XML: case SQL_TYPE_TIMESTAMP: - meta[i].c_type = SQL_C_CHAR; break; + case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: @@ -452,6 +452,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS meta[i].c_type = SQL_C_CHAR; } break; + case SQL_SS_UDT: case SQL_LONGVARBINARY: case SQL_BINARY: From 380931f5a6c007fbadf7cee003c900bc9e705ccf Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 12 Dec 2016 17:52:50 -0800 Subject: [PATCH 3/4] Replcaing SQLSRV_ENCODING ( CP_UTF8) with SQLSRV_ENCODING_UTF8 --- pdo_sqlsrv/core_results.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdo_sqlsrv/core_results.cpp b/pdo_sqlsrv/core_results.cpp index 7fde182c..91f05a11 100644 --- a/pdo_sqlsrv/core_results.cpp +++ b/pdo_sqlsrv/core_results.cpp @@ -346,7 +346,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS 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 )) { + if ( encoding == SQLSRV_ENCODING_UTF8 ) { meta[i].length *= sizeof( WCHAR ); meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space offset += meta[i].length; @@ -445,7 +445,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS 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 )) { + if ( encoding == SQLSRV_ENCODING_UTF8 ) { meta[i].c_type = SQL_C_WCHAR; } else { From 0b50a11ea38b91c49b7fe937b2dd7c751b94cc37 Mon Sep 17 00:00:00 2001 From: ulvii Date: Mon, 12 Dec 2016 17:57:03 -0800 Subject: [PATCH 4/4] Replcaing SQLSRV_ENCODING ( CP_UTF8) with SQLSRV_ENCODING_UTF8 --- sqlsrv/core_results.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sqlsrv/core_results.cpp b/sqlsrv/core_results.cpp index 7fde182c..91f05a11 100644 --- a/sqlsrv/core_results.cpp +++ b/sqlsrv/core_results.cpp @@ -346,7 +346,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS 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 )) { + if ( encoding == SQLSRV_ENCODING_UTF8 ) { meta[i].length *= sizeof( WCHAR ); meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space offset += meta[i].length; @@ -445,7 +445,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( sqlsrv_stmt* stmt TSRMLS 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 )) { + if ( encoding == SQLSRV_ENCODING_UTF8 ) { meta[i].c_type = SQL_C_WCHAR; } else {