Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 937 - fixed ASSERT and added new tests #940

Merged
merged 3 commits into from
Feb 28, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/sqlsrv/stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1807,7 +1807,7 @@ SQLSMALLINT get_resultset_meta_data(_Inout_ sqlsrv_stmt * stmt)
throw;
}

SQLSRV_ASSERT(num_cols > 0 && stmt->current_meta_data.size() == num_cols, "Meta data vector out of sync" );
SQLSRV_ASSERT(stmt->current_meta_data.size() == num_cols, "Meta data vector out of sync" );

return num_cols;
}
Expand Down
115 changes: 115 additions & 0 deletions test/functional/pdo_sqlsrv/pdo_937_metadata.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
--TEST--
GitHub issue 937 - getting metadata will not fail after an UPDATE / DELETE statement
--DESCRIPTION--
Verifies that getColumnMeta will not fail after processing an UPDATE / DELETE query that returns no fields.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif_mid-refactor.inc'); ?>
--FILE--
<?php
require_once("MsSetup.inc");
require_once("MsCommon_mid-refactor.inc");

$tableName = 'pdoTestTable_938';
$procName = 'pdoTestProc_938';

try {
$conn = connect();

dropTable($conn, $tableName);
dropProc($conn, $procName);

$tsql = "CREATE TABLE $tableName([id] [int] NOT NULL, [name] [varchar](10) NOT NULL)";
$conn->query($tsql);

$id = 3;
$tsql = "INSERT INTO $tableName VALUES ($id, 'abcde')";
$conn->query($tsql);

$tsql = "UPDATE $tableName SET name = 'updated' WHERE id = $id";
$stmt = $conn->prepare($tsql);
$stmt->execute();
$numCol = $metadata = $stmt->columnCount();
echo "Number of columns after UPDATE: $numCol\n";

$tsql = "SELECT * FROM $tableName";
$stmt = $conn->query($tsql);
$numCol = $metadata = $stmt->columnCount();
for ($i = 0; $i < $numCol; $i++) {
$metadata = $stmt->getColumnMeta($i);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only place that getColumnMeta is called? In the sqlsrv test sqlsrv_field_metadata is called several times for both non-empty and empty result sets. Is it preferable to call columnCount first in PDO?

var_dump($metadata);
}

createProc($conn, $procName, "@id int, @val varchar(10) OUTPUT", "SELECT @val = name FROM $tableName WHERE id = @id");

$value = '';
$tsql = "{CALL [$procName] (?, ?)}";
$stmt = $conn->prepare($tsql);
$stmt->bindParam(1, $id, PDO::PARAM_INT);
$stmt->bindParam(2, $value, PDO::PARAM_STR, 10);
$stmt->execute();
$numCol = $metadata = $stmt->columnCount();
echo "After calling stored procedure\n";
echo "Number of columns: $numCol\n";
echo "Value returned: $value\n";

$query = "DELETE FROM $tableName WHERE name = 'updated'";
$stmt = $conn->query($query);
$numCol = $metadata = $stmt->columnCount();
echo "Number of columns after DELETE: $numCol\n";

} catch (PDOException $e) {
var_dump($e);
}

dropTable($conn, $tableName);
dropProc($conn, $procName);

unset($stmt);
unset($conn);

?>
--EXPECT--
Number of columns after UPDATE: 0
array(8) {
["flags"]=>
int(0)
["sqlsrv:decl_type"]=>
string(3) "int"
["native_type"]=>
string(6) "string"
["table"]=>
string(0) ""
["pdo_type"]=>
int(2)
["name"]=>
string(2) "id"
["len"]=>
int(10)
["precision"]=>
int(0)
}
array(8) {
["flags"]=>
int(0)
["sqlsrv:decl_type"]=>
string(7) "varchar"
["native_type"]=>
string(6) "string"
["table"]=>
string(0) ""
["pdo_type"]=>
int(2)
["name"]=>
string(4) "name"
["len"]=>
int(10)
["precision"]=>
int(0)
}
After calling stored procedure
Number of columns: 0
Value returned: updated
Number of columns after DELETE: 0

125 changes: 125 additions & 0 deletions test/functional/sqlsrv/srv_937_metadata.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
--TEST--
GitHub issue #937 - getting metadata will not fail after an UPDATE / DELETE statement
--DESCRIPTION--
Verifies that sqlsrv_field_metadata will return an empty array after processing an
UPDATE / DELETE query that returns no fields.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
require_once('MsCommon.inc');

$conn = connect();
if ($conn === false) {
die(print_r(sqlsrv_errors(), true));
}

$tableName = 'srvTestTable_938';
$procName = 'srvTestProc_938';

dropTable($conn, $tableName);
dropProc($conn, $procName);

// Create the test table
$tsql = "CREATE TABLE $tableName([id] [int] NOT NULL,
[dummyColumn] [varchar](10) NOT NULL
)";
$stmt = sqlsrv_query($conn, $tsql);
if (!$stmt) {
fatalError("Failed to create table $tableName\n");
}

$id = 5;
$tsql = "INSERT INTO $tableName VALUES ($id, 'dummy')";
$stmt = sqlsrv_query($conn, $tsql);
if (!$stmt) {
fatalError("Failed to insert a row into table $tableName\n");
}

$tsql = "SELECT * FROM $tableName";
$stmt = sqlsrv_query($conn, $tsql);
$fieldmeta = sqlsrv_field_metadata($stmt);
var_dump($fieldmeta);

$tsql = "UPDATE $tableName SET dummyColumn = 'updated' WHERE id = $id";
$stmt = sqlsrv_prepare($conn, $tsql);
sqlsrv_execute($stmt);
$fieldmeta = sqlsrv_field_metadata($stmt);
var_dump($fieldmeta);

createProc($conn, $procName, "@id int, @val varchar(10) OUTPUT", "SELECT @val = dummyColumn FROM $tableName WHERE id = @id");

$value = '';
$tsql = "{CALL [$procName] (?, ?)}";
$stmt = sqlsrv_prepare(
$conn,
$tsql,
array(array($id, SQLSRV_PARAM_IN),
array(&$value, SQLSRV_PARAM_OUT)
)
);
$result = sqlsrv_execute($stmt);
if (!$result) {
fatalError("Failed to invoke stored procedure $procName\n");
}

echo "The value returned: $value\n";

$fieldmeta = sqlsrv_field_metadata($stmt);
var_dump($fieldmeta);

$options = array("Scrollable" => "buffered");
$tsql = "DELETE FROM $tableName WHERE dummyColumn = 'updated'";
$stmt = sqlsrv_query($conn, $tsql, array(), $options);
$fieldmeta = sqlsrv_field_metadata($stmt);
var_dump($fieldmeta);

dropTable($conn, $tableName);
dropProc($conn, $procName);

sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);

?>
--EXPECT--
array(2) {
[0]=>
array(6) {
["Name"]=>
string(2) "id"
["Type"]=>
int(4)
["Size"]=>
NULL
["Precision"]=>
int(10)
["Scale"]=>
NULL
["Nullable"]=>
int(0)
}
[1]=>
array(6) {
["Name"]=>
string(11) "dummyColumn"
["Type"]=>
int(12)
["Size"]=>
int(10)
["Precision"]=>
NULL
["Scale"]=>
NULL
["Nullable"]=>
int(0)
}
}
array(0) {
}
The value returned: updated
array(0) {
}
array(0) {
}