Issue 937 - fixed ASSERT and added new tests (#940)
This commit is contained in:
parent
b1b7a40f70
commit
12d01c9189
|
@ -1029,20 +1029,28 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
|
|||
|
||||
try {
|
||||
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_get_col_meta: pdo_stmt object was null" );
|
||||
SQLSRV_ASSERT( stmt->columns != NULL, "pdo_sqlsrv_stmt_get_col_meta: columns are not available." );
|
||||
SQLSRV_ASSERT( Z_TYPE_P( return_value ) == IS_NULL, "Metadata already has value. Must be NULL." );
|
||||
|
||||
sqlsrv_malloc_auto_ptr<field_meta_data> core_meta_data;
|
||||
|
||||
sqlsrv_stmt* driver_stmt = static_cast<sqlsrv_stmt*>( stmt->driver_data );
|
||||
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_meta: stmt->driver_data was null");
|
||||
|
||||
SQLSRV_ASSERT( colno >= 0 && colno < stmt->column_count, "pdo_sqlsrv_stmt_get_col_meta: invalid column number." );
|
||||
// Based on PDOStatement::getColumnMeta API, this should return FALSE
|
||||
// if the requested column does not exist in the result set, or if
|
||||
// no result set exists. Thus, do not use SQLSRV_ASSERT, which causes
|
||||
// the script to fail right away. Instead, log this warning if logging
|
||||
// is enabled
|
||||
if (colno < 0 || colno >= stmt->column_count || stmt->columns == NULL) {
|
||||
LOG( SEV_WARNING, "Invalid column number %1!d!", colno );
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
core_meta_data = core_sqlsrv_field_metadata( driver_stmt, (SQLSMALLINT) colno TSRMLS_CC );
|
||||
// initialize the array to nothing, as PDO requires us to create it
|
||||
core::sqlsrv_array_init( *driver_stmt, return_value TSRMLS_CC );
|
||||
|
||||
sqlsrv_malloc_auto_ptr<field_meta_data> core_meta_data;
|
||||
|
||||
core_meta_data = core_sqlsrv_field_metadata( driver_stmt, (SQLSMALLINT) colno TSRMLS_CC );
|
||||
|
||||
// add the following fields: flags, native_type, driver:decl_type, table
|
||||
add_assoc_long( return_value, "flags", 0 );
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
122
test/functional/pdo_sqlsrv/pdo_937_metadata.phpt
Normal file
122
test/functional/pdo_sqlsrv/pdo_937_metadata.phpt
Normal file
|
@ -0,0 +1,122 @@
|
|||
--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. Instead, it should simply return FALSE because no result set exists.
|
||||
--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';
|
||||
|
||||
function checkMetaData($stmt)
|
||||
{
|
||||
$metadata = $stmt->getColumnMeta(0);
|
||||
if ($metadata !== FALSE) {
|
||||
echo "Expects FALSE because no result set exists!\n";
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
checkMetaData($stmt);
|
||||
|
||||
$tsql = "SELECT * FROM $tableName";
|
||||
$stmt = $conn->query($tsql);
|
||||
$numCol = $metadata = $stmt->columnCount();
|
||||
for ($i = 0; $i < $numCol; $i++) {
|
||||
$metadata = $stmt->getColumnMeta($i);
|
||||
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 "Number of columns after PROCEDURE: $numCol\n";
|
||||
echo "Value returned: $value\n";
|
||||
checkMetaData($stmt);
|
||||
|
||||
$query = "DELETE FROM $tableName WHERE name = 'updated'";
|
||||
$stmt = $conn->query($query);
|
||||
$numCol = $metadata = $stmt->columnCount();
|
||||
echo "Number of columns after DELETE: $numCol\n";
|
||||
checkMetaData($stmt);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
Number of columns after PROCEDURE: 0
|
||||
Value returned: updated
|
||||
Number of columns after DELETE: 0
|
|
@ -220,5 +220,4 @@ array(7) {
|
|||
|
||||
Warning: PDOStatement::getColumnMeta(): SQLSTATE[42P10]: Invalid column reference: column number must be non-negative in %s on line %x
|
||||
bool(false)
|
||||
|
||||
Fatal error: pdo_sqlsrv_stmt_get_col_meta: invalid column number. in %s on line %x
|
||||
bool(false)
|
||||
|
|
|
@ -259,5 +259,4 @@ array(7) {
|
|||
|
||||
Warning: PDOStatement::getColumnMeta(): SQLSTATE[42P10]: Invalid column reference: column number must be non-negative in %s on line %x
|
||||
bool(false)
|
||||
|
||||
Fatal error: pdo_sqlsrv_stmt_get_col_meta: invalid column number. in %s on line %x
|
||||
bool(false)
|
125
test/functional/sqlsrv/srv_937_metadata.phpt
Normal file
125
test/functional/sqlsrv/srv_937_metadata.phpt
Normal file
|
@ -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) {
|
||||
}
|
Loading…
Reference in a new issue