From 8d6ef75565e5dbc6cbbb25f06dc7e2bde0a00b79 Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Wed, 22 Jan 2020 08:01:59 -0800 Subject: [PATCH] Include sql_variant type for buffered queries (#1080) --- .travis.yml | 4 +- azure-pipelines.yml | 2 + source/shared/core_results.cpp | 2 + .../pdo_sqlsrv/MsCommon_mid-refactor.inc | 18 +++--- ...pdo_1079_sql_variant_buffered_queries.phpt | 59 ++++++++++++++++++ .../pdo_fetch_variants_diff_styles.phpt | 13 +++- .../pdo_simple_update_variants.phpt | 13 ++-- .../sqlsrv/sqlsrv_param_input_variants.phpt | 3 +- .../sqlsrv/sqlsrv_simple_fetch_variants.phpt | 2 +- .../sqlsrv/sqlsrv_simple_update_variants.phpt | 13 ++-- ...srv_1079_sql_variant_buffered_queries.phpt | 62 +++++++++++++++++++ 11 files changed, 169 insertions(+), 22 deletions(-) create mode 100644 test/functional/pdo_sqlsrv/pdo_1079_sql_variant_buffered_queries.phpt create mode 100644 test/functional/sqlsrv/srv_1079_sql_variant_buffered_queries.phpt diff --git a/.travis.yml b/.travis.yml index e368b84e..86cc31ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,10 +20,10 @@ env: - TEST_PHP_SQL_PWD=Password123 before_install: - - docker pull mcr.microsoft.com/mssql/server:2019-GA-ubuntu-16.04 + - docker pull mcr.microsoft.com/mssql/server:2019-latest install: - - docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password123' -p 1433:1433 --name=$TEST_PHP_SQL_SERVER -d mcr.microsoft.com/mssql/server:2019-CTP3.2-ubuntu + - docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password123' -p 1433:1433 --name=$TEST_PHP_SQL_SERVER -d mcr.microsoft.com/mssql/server:2019-latest - docker build --build-arg PHPSQLDIR=$PHPSQLDIR -t msphpsql-dev -f Dockerfile-msphpsql . before_script: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b4acecbf..68c85525 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -75,10 +75,12 @@ jobs: - script: | sudo update-alternatives --set php /usr/bin/php$(phpver) + sudo update-alternatives --set phpize /usr/bin/phpize$(phpver) sudo update-alternatives --set phar /usr/bin/phar$(phpver) sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpver) sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpver) sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpver) + sudo update-alternatives --set php-config /usr/bin/php-config$(phpver) php -version displayName: 'Use PHP version $(phpver)' diff --git a/source/shared/core_results.cpp b/source/shared/core_results.cpp index 1fbe005f..5141ecc9 100644 --- a/source/shared/core_results.cpp +++ b/source/shared/core_results.cpp @@ -508,6 +508,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm break; case SQL_CHAR: case SQL_VARCHAR: + case SQL_SS_VARIANT: if ( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) { offset += sizeof( void* ); } @@ -610,6 +611,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm case SQL_CHAR: case SQL_VARCHAR: + case SQL_SS_VARIANT: 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. diff --git a/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc b/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc index 969d1446..1f5d997b 100644 --- a/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc +++ b/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc @@ -1707,19 +1707,21 @@ function CallProcEx($conn, $procName, $procPrefix, $procArgs, $procValues) function CreateFunc($conn, $funcName, $funcArgs, $retType, $funcCode) { DropFunc($conn, $funcName); - $stmt = sqlsrv_query($conn, "CREATE FUNCTION [$funcName] ($funcArgs) RETURNS $retType AS BEGIN $funcCode END"); - if ($stmt === false) { - FatalError("Failed to create test function"); + try { + $stmt = $conn->query("CREATE FUNCTION [$funcName] ($funcArgs) RETURNS $retType AS BEGIN $funcCode END"); + } catch (PDOException $e) { + echo "Failed to create test function\n"; + var_dump($e); } - sqlsrv_free_stmt($stmt); + unset($stmt); } function DropFunc($conn, $funcName) { - $stmt = sqlsrv_query($conn, "DROP FUNCTION [$funcName]"); - if ($stmt === false) { - } else { - sqlsrv_free_stmt($stmt); + try { + $conn->query("DROP FUNCTION [$funcName]"); + } catch (PDOException $e) { + ; // do nothing } } diff --git a/test/functional/pdo_sqlsrv/pdo_1079_sql_variant_buffered_queries.phpt b/test/functional/pdo_sqlsrv/pdo_1079_sql_variant_buffered_queries.phpt new file mode 100644 index 00000000..1ba60606 --- /dev/null +++ b/test/functional/pdo_sqlsrv/pdo_1079_sql_variant_buffered_queries.phpt @@ -0,0 +1,59 @@ +--TEST-- +GitHub issue 1079 - fetching sql_variant types using client buffers +--DESCRIPTION-- +This test verifies that fetching sql_variant types using client buffers is supported. +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- += @OP2 THEN @OP1 ELSE @OP2 END RETURN @Result END"; + + $conn->exec($tsql); + + $tsql = "SELECT [dbo].[$funcName](5, 6) AS RESULT"; + $stmt = $conn->prepare($tsql, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED)); + $stmt->execute(); + + $metadata = $stmt->getColumnMeta(0); + var_dump($metadata); + + dropFunc($conn, $funcName); + + unset($stmt); + unset($conn); +} catch (PdoException $e) { + echo $e->getMessage() . PHP_EOL; +} + +?> +--EXPECT-- +array(8) { + ["flags"]=> + int(0) + ["sqlsrv:decl_type"]=> + string(11) "sql_variant" + ["native_type"]=> + string(6) "string" + ["table"]=> + string(0) "" + ["pdo_type"]=> + int(2) + ["name"]=> + string(6) "RESULT" + ["len"]=> + int(10) + ["precision"]=> + int(0) +} \ No newline at end of file diff --git a/test/functional/pdo_sqlsrv/pdo_fetch_variants_diff_styles.phpt b/test/functional/pdo_sqlsrv/pdo_fetch_variants_diff_styles.phpt index e99aae85..954efbdc 100644 --- a/test/functional/pdo_sqlsrv/pdo_fetch_variants_diff_styles.phpt +++ b/test/functional/pdo_sqlsrv/pdo_fetch_variants_diff_styles.phpt @@ -170,11 +170,15 @@ function doValuesMatched($value1, $value2, $row, $col) } } -function fetchColumns($conn, $tableName, $numRows, $numCols) +function fetchColumns($conn, $tableName, $numRows, $numCols, $buffered = false) { try { // insert column data from a row of the original table - $stmtOriginal = $conn->prepare("SELECT * FROM $tableName WHERE c1_int = :row"); + if ($buffered) { + $stmtOriginal = $conn->prepare("SELECT * FROM $tableName WHERE c1_int = :row", array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED)); + } else { + $stmtOriginal = $conn->prepare("SELECT * FROM $tableName WHERE c1_int = :row"); + } for ($i = 1; $i <= $numRows; $i++) { $c1_int = $i; @@ -263,6 +267,7 @@ try { $numCols = fetchBoundMixed($conn, $tableName, $numRows); fetchColumns($conn, $tableName, $numRows, $numCols); + fetchColumns($conn, $tableName, $numRows, $numCols, true); dropTable($conn, $tableName); unset($conn); @@ -278,3 +283,7 @@ Insert all columns from row 1 into one column of type sql_variant string(11) "sql_variant" Insert all columns from row 2 into one column of type sql_variant string(11) "sql_variant" +Insert all columns from row 1 into one column of type sql_variant +string(11) "sql_variant" +Insert all columns from row 2 into one column of type sql_variant +string(11) "sql_variant" diff --git a/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt b/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt index 866c5e2c..86c5e3a7 100644 --- a/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt +++ b/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt @@ -76,10 +76,15 @@ function updateFood($conn, $tableName, $id, $food, $category) } } -function fetchRows($conn, $tableName) +function fetchRows($conn, $tableName, $buffered = false) { $query = "SELECT * FROM $tableName ORDER BY id"; - $stmt = $conn->query($query); + if ($buffered) { + $stmt = $conn->prepare($query, array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE => PDO::SQLSRV_CURSOR_BUFFERED)); + $stmt->execute(); + } else { + $stmt = $conn->query($query); + } $stmt->setFetchMode(PDO::FETCH_CLASS, 'Food'); while ($food = $stmt->fetch()) { @@ -108,7 +113,7 @@ try { updateID($conn, $tableName, 4, 'Milk', 'Diary Products'); - fetchRows($conn, $tableName); + fetchRows($conn, $tableName, true); updateFood($conn, $tableName, 4, 'Cheese', 'Diary Products'); @@ -118,7 +123,7 @@ try { insertData($conn, $tableName, 6, 'Salmon', 'Fish'); insertData($conn, $tableName, 2, 'Broccoli', 'Vegetables'); - fetchRows($conn, $tableName); + fetchRows($conn, $tableName, true); dropTable($conn, $tableName); unset($conn); diff --git a/test/functional/sqlsrv/sqlsrv_param_input_variants.phpt b/test/functional/sqlsrv/sqlsrv_param_input_variants.phpt index ee5dbcde..8adc251c 100644 --- a/test/functional/sqlsrv/sqlsrv_param_input_variants.phpt +++ b/test/functional/sqlsrv/sqlsrv_param_input_variants.phpt @@ -65,7 +65,8 @@ function insertData($conn, $tableName, $index) function fetchData($conn, $tableName, $numRows) { $select = "SELECT * FROM $tableName ORDER BY c1_int"; - $stmt = sqlsrv_query($conn, $select); + + $stmt = sqlsrv_query($conn, $select, array(), array("Scrollable"=>"buffered")); $stmt2 = sqlsrv_query($conn, $select); $metadata = sqlsrv_field_metadata($stmt); diff --git a/test/functional/sqlsrv/sqlsrv_simple_fetch_variants.phpt b/test/functional/sqlsrv/sqlsrv_simple_fetch_variants.phpt index 07a59820..0022509b 100644 --- a/test/functional/sqlsrv/sqlsrv_simple_fetch_variants.phpt +++ b/test/functional/sqlsrv/sqlsrv_simple_fetch_variants.phpt @@ -39,7 +39,7 @@ function Fetch($conn, $tableName, $numRows) { $select = "SELECT * FROM $tableName ORDER BY c1_int"; $stmt = sqlsrv_query($conn, $select); - $stmt2 = sqlsrv_query($conn, $select); + $stmt2 = sqlsrv_query($conn, $select, array(), array("Scrollable"=>"buffered")); $stmt3 = sqlsrv_query($conn, $select); $metadata = sqlsrv_field_metadata($stmt); diff --git a/test/functional/sqlsrv/sqlsrv_simple_update_variants.phpt b/test/functional/sqlsrv/sqlsrv_simple_update_variants.phpt index 70fa7955..b4b3b66b 100644 --- a/test/functional/sqlsrv/sqlsrv_simple_update_variants.phpt +++ b/test/functional/sqlsrv/sqlsrv_simple_update_variants.phpt @@ -89,10 +89,15 @@ function updateCountry($conn, $tableName, $id, $country, $continent) } } -function fetch($conn, $tableName) +function fetch($conn, $tableName, $buffered = false) { $select = "SELECT * FROM $tableName ORDER BY id"; - $stmt = sqlsrv_query($conn, $select); + + if ($buffered) { + $stmt = sqlsrv_query($conn, $select, array(), array("Scrollable"=>"buffered")); + } else { + $stmt = sqlsrv_query($conn, $select); + } while ($country = sqlsrv_fetch_object($stmt, "Country")) { echo "\nID: " . $country->id . " "; @@ -125,13 +130,13 @@ try { updateID($conn, $tableName, 4, 'Canada', 'North America'); // Read data - fetch($conn, $tableName); + fetch($conn, $tableName, true); // Update country updateCountry($conn, $tableName, 4, 'Mexico', 'North America'); // Read data - fetch($conn, $tableName); + fetch($conn, $tableName, true); // Add two more countries addCountry($conn, $tableName, 6, 'Brazil', 'South America'); diff --git a/test/functional/sqlsrv/srv_1079_sql_variant_buffered_queries.phpt b/test/functional/sqlsrv/srv_1079_sql_variant_buffered_queries.phpt new file mode 100644 index 00000000..51a98553 --- /dev/null +++ b/test/functional/sqlsrv/srv_1079_sql_variant_buffered_queries.phpt @@ -0,0 +1,62 @@ +--TEST-- +GitHub issue 1079 - fetching sql_variant types using client buffers +--DESCRIPTION-- +This test verifies that fetching sql_variant types using client buffers is supported. +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- += @OP2 THEN @OP1 ELSE @OP2 END RETURN @Result END"; + +$stmt = sqlsrv_query($conn, $tsql); +if (!$stmt) { + fatalError('Could not create function\n'); +} + +$tsql = "SELECT [dbo].[$funcName](5, 6) AS RESULT"; +$stmt = sqlsrv_prepare($conn, $tsql, array(), array("Scrollable" => SQLSRV_CURSOR_CLIENT_BUFFERED, "ClientBufferMaxKBSize" => 1000)); + +if (!$stmt) { + fatalError('Could not prepare query\n'); +} + +$result = sqlsrv_execute($stmt); +if (!$result) { + fatalError('Executing the query failed\n'); +} + +foreach (sqlsrv_field_metadata($stmt) as $fieldMetadata) { + var_dump($fieldMetadata); +} + +dropFunc($conn, $funcName); + +sqlsrv_free_stmt($stmt); +sqlsrv_close($conn); + +?> +--EXPECT-- +array(6) { + ["Name"]=> + string(6) "RESULT" + ["Type"]=> + int(-150) + ["Size"]=> + int(10) + ["Precision"]=> + NULL + ["Scale"]=> + NULL + ["Nullable"]=> + int(1) +} \ No newline at end of file