From ffbd2ea32b31a46a7bff475341dd9469677555bd Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Wed, 5 Aug 2020 18:20:16 -0700 Subject: [PATCH 1/2] Fixed get_field_as_string when using display size for large types --- source/shared/core_stmt.cpp | 8 ++- .../pdo_1170_direct_query_with_textsize.phpt | 71 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 test/functional/pdo_sqlsrv/pdo_1170_direct_query_with_textsize.phpt diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index cccee0a97..d82cd34ac 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -2590,9 +2590,11 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind break; } - // if this is a large type, then read the first few bytes to get the actual length from SQLGetData - if( sql_display_size == 0 || sql_display_size == INT_MAX || - sql_display_size == INT_MAX >> 1 || sql_display_size == UINT_MAX - 1 ) { + // If this is a large type, then read the first few bytes to get the actual length from SQLGetData + // The user may use "SET TEXTSIZE" to specify the size of varchar(max), nvarchar(max), + // varbinary(max), text, ntext, and image data returned by a SELECT statement. + // For varchar(max) and nvarchar(max), sql_display_size will be 0, regardless + if (sql_display_size == 0 || (sql_display_size > SQL_SERVER_MAX_FIELD_SIZE && (sql_field_type == SQL_WLONGVARCHAR || sql_field_type == SQL_LONGVARCHAR || sql_field_type == SQL_LONGVARBINARY))) { field_len_temp = intial_field_len; diff --git a/test/functional/pdo_sqlsrv/pdo_1170_direct_query_with_textsize.phpt b/test/functional/pdo_sqlsrv/pdo_1170_direct_query_with_textsize.phpt new file mode 100644 index 000000000..6ec78170c --- /dev/null +++ b/test/functional/pdo_sqlsrv/pdo_1170_direct_query_with_textsize.phpt @@ -0,0 +1,71 @@ +--TEST-- +GitHub issue 1170 - PDO::SQLSRV_ATTR_DIRECT_QUERY with SET TEXTSIZE +--DESCRIPTION-- +This test verifies that setting PDO::SQLSRV_ATTR_DIRECT_QUERY to true with a user defined TEXTSIZE will work +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- + true); + + $sql = "SET TEXTSIZE $size"; + $stmt = $conn->prepare($sql, $options); + $stmt->execute(); + unset($stmt); + + $sql = composeQuery($input, $type); + $stmt = $conn->prepare($sql, $options); + $stmt->execute(); + + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if ($row['C1'] != $input || !is_null($row['C2'])) { + var_dump($row); + } + unset($stmt); +} + +try { + $conn = connect(); + + $options = array(PDO::SQLSRV_ATTR_DIRECT_QUERY => true); + + runTest($conn, 'TEXT', 4800); + runTest($conn, 'NTEXT', 129024); + runTest($conn, 'IMAGE', 10000); + + unset($conn); + + echo "Done\n"; +} catch (PdoException $e) { + echo $e->getMessage() . PHP_EOL; +} + +?> +--EXPECT-- +Test with TEXT and 4800 +Test with NTEXT and 129024 +Test with IMAGE and 10000 +Done + From 3ff70fa109ae3c7536dee49b1780d08fb046dc72 Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Thu, 6 Aug 2020 09:09:18 -0700 Subject: [PATCH 2/2] Reverted some changes --- source/shared/core_stmt.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index d82cd34ac..649e1c3d4 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -2594,7 +2594,10 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind // The user may use "SET TEXTSIZE" to specify the size of varchar(max), nvarchar(max), // varbinary(max), text, ntext, and image data returned by a SELECT statement. // For varchar(max) and nvarchar(max), sql_display_size will be 0, regardless - if (sql_display_size == 0 || (sql_display_size > SQL_SERVER_MAX_FIELD_SIZE && (sql_field_type == SQL_WLONGVARCHAR || sql_field_type == SQL_LONGVARCHAR || sql_field_type == SQL_LONGVARBINARY))) { + if (sql_display_size == 0 || sql_display_size == INT_MAX || + sql_display_size == INT_MAX >> 1 || sql_display_size == UINT_MAX - 1 || + (sql_display_size > SQL_SERVER_MAX_FIELD_SIZE && + (sql_field_type == SQL_WLONGVARCHAR || sql_field_type == SQL_LONGVARCHAR || sql_field_type == SQL_LONGVARBINARY))) { field_len_temp = intial_field_len;