Commit 68f1f4a8 authored by Stefan Bürk's avatar Stefan Bürk Committed by Oliver Bartsch
Browse files

[BUGFIX] Avoid unreliable 'rowCount()' in IndexSearchRepository

rowCount() on result sets for SELECT queries are not reliable across
all DBMS, which doctrine/dbal comments in the docblock. See:

Because of "rowCount()"'s unreliable behaviour for some dbms like
sqlite, this should be avoided to ensure cross dbms support.

uses 'rowCount()' in 'doSearch()' which fails on sqlite, making it
impossible to get any result in the frontend search.

Doing a count() query as replacement is not possible and needs a
bigger architectural change, which is not feasable as bugfix.
Thus fallback to retrieve the result into an array and counting
the array is used as a intermediate solution to ensure index_search
is working across all supported database systems.

The architectural change will be done in a dedicated patch.

Resolves: #97460
Releases: main, 11.5
Change-Id: Id7afa9f95fefbba07acb7c0dda1267dd2fce92db

Tested-by: core-ci's avatarcore-ci <>
Tested-by: Benni Mack's avatarBenni Mack <>
Tested-by: Oliver Bartsch's avatarOliver Bartsch <>
Reviewed-by: Benni Mack's avatarBenni Mack <>
Reviewed-by: Oliver Bartsch's avatarOliver Bartsch <>
parent 6f7514f5
......@@ -181,6 +181,8 @@ class IndexSearchRepository
$useMysqlFulltext = (bool)GeneralUtility::makeInstance(ExtensionConfiguration::class)->get('indexed_search', 'useMysqlFulltext');
// Getting SQL result pointer:
$this->getTimeTracker()->push('Searching result');
// @todo Change hook and method signatures to return the QueryBuilder instead the Result. Consider to move
// from hook to a proper PSR-14 event.
if ($hookObj = $this->hookRequest('getResultRows_SQLpointer')) {
$result = $hookObj->getResultRows_SQLpointer($searchWords, $freeIndexUid);
} elseif ($useMysqlFulltext) {
......@@ -191,8 +193,14 @@ class IndexSearchRepository
// Organize and process result:
if ($result) {
// We need the result row count beforehand for the pointer calculation. Using $result->rowCount() for
// select queries is not reliable across dbms systems, and in case of sqlite this will return 0 here,
// even if there is a result set, we need to retrieve all rows and doing a count on the array.
// @todo Change this to second count() query call, after getResultRows_SQLpointer() signatures/hook has
// been changed to return QueryBuilder instead of the Result.
$rows = $result->fetchAllAssociative();
// Total search-result count
$count = $result->rowCount();
$count = count($rows);
// The pointer is set to the result page that is currently being viewed
$pointer = MathUtility::forceIntegerInRange($this->resultpagePointer, 0, (int)floor($count / $this->numberOfResults));
// Initialize result accumulation variables:
......@@ -209,7 +217,9 @@ class IndexSearchRepository
// Now, traverse result and put the rows to be displayed into an array
// Each row should contain the fields from 'ISEC.*, IP.*' combined
// + artificial fields "show_resume" (bool) and "result_number" (counter)
while ($row = $result->fetchAssociative()) {
// @todo Change this back to while($row = $result->fetchAssociative()) after changing
// getResultRows_SQLpointer() returning QueryBuilder instead of a Result.
foreach ($rows as $row) {
// Set first row
if (!$c) {
$firstRow = $row;
......@@ -253,8 +263,6 @@ class IndexSearchRepository
return [
'resultRows' => $resultRows,
'firstRow' => $firstRow,
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment