Include sql_variant type for buffered queries (#1080)
This commit is contained in:
parent
9c9c04a43d
commit
8d6ef75565
|
@ -20,10 +20,10 @@ env:
|
||||||
- TEST_PHP_SQL_PWD=Password123
|
- TEST_PHP_SQL_PWD=Password123
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- docker pull mcr.microsoft.com/mssql/server:2019-GA-ubuntu-16.04
|
- docker pull mcr.microsoft.com/mssql/server:2019-latest
|
||||||
|
|
||||||
install:
|
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 .
|
- docker build --build-arg PHPSQLDIR=$PHPSQLDIR -t msphpsql-dev -f Dockerfile-msphpsql .
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
|
|
@ -75,10 +75,12 @@ jobs:
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
sudo update-alternatives --set php /usr/bin/php$(phpver)
|
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 phar /usr/bin/phar$(phpver)
|
||||||
sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(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 php-cgi /usr/bin/php-cgi$(phpver)
|
||||||
sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(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
|
php -version
|
||||||
displayName: 'Use PHP version $(phpver)'
|
displayName: 'Use PHP version $(phpver)'
|
||||||
|
|
||||||
|
|
|
@ -508,6 +508,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
break;
|
break;
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
case SQL_VARCHAR:
|
case SQL_VARCHAR:
|
||||||
|
case SQL_SS_VARIANT:
|
||||||
if ( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
|
if ( meta[i].length == sqlsrv_buffered_result_set::meta_data::SIZE_UNKNOWN ) {
|
||||||
offset += sizeof( void* );
|
offset += sizeof( void* );
|
||||||
}
|
}
|
||||||
|
@ -610,6 +611,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
|
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
case SQL_VARCHAR:
|
case SQL_VARCHAR:
|
||||||
|
case SQL_SS_VARIANT:
|
||||||
case SQL_LONGVARCHAR:
|
case SQL_LONGVARCHAR:
|
||||||
// If encoding is set to UTF-8, the following types are not necessarily column size.
|
// 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.
|
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
|
||||||
|
|
|
@ -1707,19 +1707,21 @@ function CallProcEx($conn, $procName, $procPrefix, $procArgs, $procValues)
|
||||||
function CreateFunc($conn, $funcName, $funcArgs, $retType, $funcCode)
|
function CreateFunc($conn, $funcName, $funcArgs, $retType, $funcCode)
|
||||||
{
|
{
|
||||||
DropFunc($conn, $funcName);
|
DropFunc($conn, $funcName);
|
||||||
$stmt = sqlsrv_query($conn, "CREATE FUNCTION [$funcName] ($funcArgs) RETURNS $retType AS BEGIN $funcCode END");
|
try {
|
||||||
if ($stmt === false) {
|
$stmt = $conn->query("CREATE FUNCTION [$funcName] ($funcArgs) RETURNS $retType AS BEGIN $funcCode END");
|
||||||
FatalError("Failed to create test function");
|
} catch (PDOException $e) {
|
||||||
|
echo "Failed to create test function\n";
|
||||||
|
var_dump($e);
|
||||||
}
|
}
|
||||||
sqlsrv_free_stmt($stmt);
|
unset($stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DropFunc($conn, $funcName)
|
function DropFunc($conn, $funcName)
|
||||||
{
|
{
|
||||||
$stmt = sqlsrv_query($conn, "DROP FUNCTION [$funcName]");
|
try {
|
||||||
if ($stmt === false) {
|
$conn->query("DROP FUNCTION [$funcName]");
|
||||||
} else {
|
} catch (PDOException $e) {
|
||||||
sqlsrv_free_stmt($stmt);
|
; // do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsSetup.inc");
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
|
||||||
|
$funcName = 'PDO1079';
|
||||||
|
dropFunc($conn, $funcName);
|
||||||
|
|
||||||
|
$tsql = "CREATE FUNCTION [$funcName](@OP1 sql_variant, @OP2 sql_variant) RETURNS sql_variant AS
|
||||||
|
BEGIN DECLARE @Result sql_variant SET @Result = CASE WHEN @OP1 >= @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)
|
||||||
|
}
|
|
@ -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 {
|
try {
|
||||||
// insert column data from a row of the original table
|
// insert column data from a row of the original table
|
||||||
|
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");
|
$stmtOriginal = $conn->prepare("SELECT * FROM $tableName WHERE c1_int = :row");
|
||||||
|
}
|
||||||
|
|
||||||
for ($i = 1; $i <= $numRows; $i++) {
|
for ($i = 1; $i <= $numRows; $i++) {
|
||||||
$c1_int = $i;
|
$c1_int = $i;
|
||||||
|
@ -263,6 +267,7 @@ try {
|
||||||
|
|
||||||
$numCols = fetchBoundMixed($conn, $tableName, $numRows);
|
$numCols = fetchBoundMixed($conn, $tableName, $numRows);
|
||||||
fetchColumns($conn, $tableName, $numRows, $numCols);
|
fetchColumns($conn, $tableName, $numRows, $numCols);
|
||||||
|
fetchColumns($conn, $tableName, $numRows, $numCols, true);
|
||||||
|
|
||||||
dropTable($conn, $tableName);
|
dropTable($conn, $tableName);
|
||||||
unset($conn);
|
unset($conn);
|
||||||
|
@ -278,3 +283,7 @@ Insert all columns from row 1 into one column of type sql_variant
|
||||||
string(11) "sql_variant"
|
string(11) "sql_variant"
|
||||||
Insert all columns from row 2 into one column of type sql_variant
|
Insert all columns from row 2 into one column of type sql_variant
|
||||||
string(11) "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"
|
||||||
|
|
|
@ -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";
|
$query = "SELECT * FROM $tableName ORDER BY id";
|
||||||
|
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 = $conn->query($query);
|
||||||
|
}
|
||||||
|
|
||||||
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Food');
|
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Food');
|
||||||
while ($food = $stmt->fetch()) {
|
while ($food = $stmt->fetch()) {
|
||||||
|
@ -108,7 +113,7 @@ try {
|
||||||
|
|
||||||
updateID($conn, $tableName, 4, 'Milk', 'Diary Products');
|
updateID($conn, $tableName, 4, 'Milk', 'Diary Products');
|
||||||
|
|
||||||
fetchRows($conn, $tableName);
|
fetchRows($conn, $tableName, true);
|
||||||
|
|
||||||
updateFood($conn, $tableName, 4, 'Cheese', 'Diary Products');
|
updateFood($conn, $tableName, 4, 'Cheese', 'Diary Products');
|
||||||
|
|
||||||
|
@ -118,7 +123,7 @@ try {
|
||||||
insertData($conn, $tableName, 6, 'Salmon', 'Fish');
|
insertData($conn, $tableName, 6, 'Salmon', 'Fish');
|
||||||
insertData($conn, $tableName, 2, 'Broccoli', 'Vegetables');
|
insertData($conn, $tableName, 2, 'Broccoli', 'Vegetables');
|
||||||
|
|
||||||
fetchRows($conn, $tableName);
|
fetchRows($conn, $tableName, true);
|
||||||
|
|
||||||
dropTable($conn, $tableName);
|
dropTable($conn, $tableName);
|
||||||
unset($conn);
|
unset($conn);
|
||||||
|
|
|
@ -65,7 +65,8 @@ function insertData($conn, $tableName, $index)
|
||||||
function fetchData($conn, $tableName, $numRows)
|
function fetchData($conn, $tableName, $numRows)
|
||||||
{
|
{
|
||||||
$select = "SELECT * FROM $tableName ORDER BY c1_int";
|
$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);
|
$stmt2 = sqlsrv_query($conn, $select);
|
||||||
|
|
||||||
$metadata = sqlsrv_field_metadata($stmt);
|
$metadata = sqlsrv_field_metadata($stmt);
|
||||||
|
|
|
@ -39,7 +39,7 @@ function Fetch($conn, $tableName, $numRows)
|
||||||
{
|
{
|
||||||
$select = "SELECT * FROM $tableName ORDER BY c1_int";
|
$select = "SELECT * FROM $tableName ORDER BY c1_int";
|
||||||
$stmt = sqlsrv_query($conn, $select);
|
$stmt = sqlsrv_query($conn, $select);
|
||||||
$stmt2 = sqlsrv_query($conn, $select);
|
$stmt2 = sqlsrv_query($conn, $select, array(), array("Scrollable"=>"buffered"));
|
||||||
$stmt3 = sqlsrv_query($conn, $select);
|
$stmt3 = sqlsrv_query($conn, $select);
|
||||||
|
|
||||||
$metadata = sqlsrv_field_metadata($stmt);
|
$metadata = sqlsrv_field_metadata($stmt);
|
||||||
|
|
|
@ -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";
|
$select = "SELECT * FROM $tableName ORDER BY id";
|
||||||
|
|
||||||
|
if ($buffered) {
|
||||||
|
$stmt = sqlsrv_query($conn, $select, array(), array("Scrollable"=>"buffered"));
|
||||||
|
} else {
|
||||||
$stmt = sqlsrv_query($conn, $select);
|
$stmt = sqlsrv_query($conn, $select);
|
||||||
|
}
|
||||||
|
|
||||||
while ($country = sqlsrv_fetch_object($stmt, "Country")) {
|
while ($country = sqlsrv_fetch_object($stmt, "Country")) {
|
||||||
echo "\nID: " . $country->id . " ";
|
echo "\nID: " . $country->id . " ";
|
||||||
|
@ -125,13 +130,13 @@ try {
|
||||||
updateID($conn, $tableName, 4, 'Canada', 'North America');
|
updateID($conn, $tableName, 4, 'Canada', 'North America');
|
||||||
|
|
||||||
// Read data
|
// Read data
|
||||||
fetch($conn, $tableName);
|
fetch($conn, $tableName, true);
|
||||||
|
|
||||||
// Update country
|
// Update country
|
||||||
updateCountry($conn, $tableName, 4, 'Mexico', 'North America');
|
updateCountry($conn, $tableName, 4, 'Mexico', 'North America');
|
||||||
|
|
||||||
// Read data
|
// Read data
|
||||||
fetch($conn, $tableName);
|
fetch($conn, $tableName, true);
|
||||||
|
|
||||||
// Add two more countries
|
// Add two more countries
|
||||||
addCountry($conn, $tableName, 6, 'Brazil', 'South America');
|
addCountry($conn, $tableName, 6, 'Brazil', 'South America');
|
||||||
|
|
|
@ -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--
|
||||||
|
<?php require('skipif_versions_old.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once('MsCommon.inc');
|
||||||
|
|
||||||
|
$conn = AE\connect();
|
||||||
|
|
||||||
|
$funcName = 'SRV1079';
|
||||||
|
dropFunc($conn, $funcName);
|
||||||
|
|
||||||
|
$tsql = "CREATE FUNCTION [$funcName](@OP1 sql_variant, @OP2 sql_variant) RETURNS sql_variant AS
|
||||||
|
BEGIN DECLARE @Result sql_variant SET @Result = CASE WHEN @OP1 >= @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)
|
||||||
|
}
|
Loading…
Reference in a new issue