php - 对于 ALTER INDEX all ON tbl REORGANIZE 查询,sqlsrv_query 返回什么?为什么 sqlsrv_num_rows 返回 FALSE?
问题描述
我创建了一个拉取请求来Database\ResultInterface::getNumRows()
向 CodeIgniter 4 添加一个函数。我所做的一些更改破坏了单元测试。具体来说,SQLSRV 表优化测试很麻烦,因为这个框架试图从 SQLSRV 响应中获取一个结果数组来响应这个表优化查询:
ALTER INDEX all ON db_job REORGANIZE
跟踪导致此问题的所有被调用代码也有点棘手,但这里有一个例外:
1) CodeIgniter\Database\Live\DbUtilsTest::testUtilsOptimizeDatabase
CodeIgniter\Database\Exceptions\DatabaseException: Error retrieving row count
/home/runner/work/CodeIgniter4/CodeIgniter4/system/Database/SQLSRV/Result.php:198
/home/runner/work/CodeIgniter4/CodeIgniter4/system/Database/BaseResult.php:193
/home/runner/work/CodeIgniter4/CodeIgniter4/system/Database/BaseUtils.php:177
/home/runner/work/CodeIgniter4/CodeIgniter4/tests/system/Database/Live/DbUtilsTest.php:105
剖析它,我们看到DBUtilsTest 第 105 行使用表名“db_job”调用BaseUtils::optimizeTable函数,并使用SQLSRV\Utils::optimizeTable
var 构造我在上面提供的查询。然后将此 sql 提供给一个 db 对象,该对象CodeIgniter\Database\SQLSRV\Connection::query()
通过继承和各种函数调用来调用该 SQL,通过BaseConnection::query()
该 SQL 将 sql 提供给该 sql,BaseConnection::simpleQuery
该 sqlSQLSRV\Connection::execute
最终将 sql 提供给该 sql,sqlsrv_query
并通过该函数返回该函数的结果。调用栈。所以我想这让我想到了我的第一个问题:
问题 1:$stmt
如果这个 ALTER 命令 a) 成功或 b) 失败,值是多少?:
$stmt = sqlsrv_query($connID, 'ALTER INDEX all ON db_job REORGANIZE');
根据sqlsrv_query 文档,这个函数:
成功时返回语句资源,如果发生错误则返回 false。
无论该值返回到调用堆栈的第 625 行BaseConnection::query
,如果成功,它将作为第二个参数存储$this->resultID
并作为第二个参数提供给第 676 行的构造函数,该构造函数有效地返回new SQLSRV\Result($this->connID, $this->resultID)
。需要明确的是,connID 指的是 SQLSRV 数据库连接,而 resultID 指的$stmt
是上面的 sqlsrv_query 调用返回的任何值。
结果$query
变量是此函数中 system\Database\SQLSRV\Result 的一个实例:
public function optimizeTable(string $tableName)
{
if ($this->optimizeTable === false)
{
if ($this->db->DBDebug)
{
throw new DatabaseException('Unsupported feature of the database platform you are using.');
}
return false;
}
$query = $this->db->query(sprintf($this->optimizeTable, $this->db->escapeIdentifiers($tableName)));
if ($query !== false)
{
$query = $query->getResultArray();
return current($query);
}
return false;
}
SQLSRV\Result 的实例不会为 false,因此代码将尝试SQLSRV\Result::getResultArray
通过继承调用调用 which BaseResult::getResultArray
。尝试从优化表的查询或任何类型的 ALTER 查询中获取结果数组似乎是错误的,但是 MySQL 服务器将返回一系列记录以响应 OPTIMIZE 查询。此外,我们刚刚运行的 sqlsrv_query 函数只是返回一些 sqlserver 语句或资源作为其结果。
我想这让我想到了第二个问题:
问题 2:如何从$stmt
sqlsrv_query 的结果中判断上面的 ALTER 语句是否成功?
奇怪的是,这些特性以前都没有引起任何问题。问题似乎已经出现,因为我已经弃用了一个从未在旧 getResultArray 代码中设置过的未使用的 BaseResult::numRows 属性,并用新的 getNumRows 方法替换了它以及对它的所有引用。在我的新BaseResult::getResultArray 函数中,我们现在检查 getNumRows 而不是 numRows。这适用于 MySQLi、SQLite3 和 PostGreSQL,但在 SQLSRV 中会出现问题,因为上述ALTER 语句的$stmt
结果被输入并返回,根据文档,这表示错误。这是函数的代码:sqlsrv_query
sqlsrv_num_rows
false
SQLSRV\Result::getNumRows
public function getNumRows() : int
{
// $this->resultID contains the sqlsrv_query result of our ALTER statement
// and $retval comes up false
$retval = sqlsrv_num_rows($this->resultID);
if ($retval === false)
{
throw new DatabaseException('Error retrieving row count');
}
return intval($retval);
}
这让我想到: 问题 3:尝试从 ALTER INDEX 查询的结果中获取结果或调用 sqlsrv_num_rows 是否有意义?
解决方案
推荐阅读
- php - 致命错误:未捕获错误:调用未定义函数 get_post_datetime()
- swift - 尝试使用 google Places API 获取某个位置附近的餐厅名称
- mysql - 根据左连接数重复行 X 次
- c++ - 考虑到 c++ 中的替代方案,函数 memcpy、memmove 和 memset 是否已经过时?
- java - 将英尺和英寸转换为英寸(多个输入为一个输入)
- julia - Julia 中的元素复合赋值运算符
- microsoft-translator - 防止某些词被翻译
- node.js - Sequelize 中的复合主键
- influxdb - 在命令提示符下一次将多个点插入 Influx DB
- javascript - 使用 Grunt-Babel 使 ES6 Internet Explorer 11 兼容