[BUGFIX] get count consistent with execute for self written statements 14/55214/2
authorSebastian Hofer <sebastian.hofer@marit.ag>
Tue, 28 Nov 2017 21:31:34 +0000 (22:31 +0100)
committerBenni Mack <benni@typo3.org>
Wed, 27 Dec 2017 11:41:09 +0000 (12:41 +0100)
Fix wrong result for self written sql statements executing count
on the query result.

To get this consistent, check for statement also in
getObjectCountByQuery and run getObjectDataByQuery
for self written statements. After that count the
rows.

Wrapping the statement in a subselect will
may be break doLanguageAndWorkspaceOverlay
in getObjectDataByQuery.

This is just to be consistent. Normally it does not
make sense to call the count method on a self written
statement.

Releases: master, 8.7
Resolves: #82910
Change-Id: I8bddb1b20d062d9f46939c16885f1eb73df1e5f4
Reviewed-on: https://review.typo3.org/55214
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php

index d4db9f6..8fa24f2 100644 (file)
@@ -463,32 +463,40 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
             throw new BadConstraintException('Could not execute count on queries with a constraint of type TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Qom\\Statement', 1256661045);
         }
 
-        $queryParser = $this->objectManager->get(Typo3DbQueryParser::class);
-        $queryBuilder = $queryParser
-            ->convertQueryToDoctrineQueryBuilder($query)
-            ->resetQueryPart('orderBy');
-
-        if ($queryParser->isDistinctQuerySuggested()) {
-            $source = $queryBuilder->getQueryPart('from')[0];
-            // Tablename is already quoted for the DBMS, we need to treat table and field names separately
-            $tableName = $source['alias'] ?: $source['table'];
-            $fieldName = $queryBuilder->quoteIdentifier('uid');
-            $queryBuilder->resetQueryPart('groupBy')
-             ->selectLiteral(sprintf('COUNT(DISTINCT %s.%s)', $tableName, $fieldName));
+        $statement = $query->getStatement();
+        if ($statement instanceof Qom\Statement
+            && !$statement->getStatement() instanceof QueryBuilder
+        ) {
+            $rows = $this->getObjectDataByQuery($query);
+            $count = count($rows);
         } else {
-            $queryBuilder->count('*');
-        }
+            $queryParser  = $this->objectManager->get(Typo3DbQueryParser::class);
+            $queryBuilder = $queryParser
+                ->convertQueryToDoctrineQueryBuilder($query)
+                ->resetQueryPart('orderBy');
+
+            if ($queryParser->isDistinctQuerySuggested()) {
+                $source = $queryBuilder->getQueryPart('from')[0];
+                // Tablename is already quoted for the DBMS, we need to treat table and field names separately
+                $tableName = $source['alias'] ?: $source['table'];
+                $fieldName = $queryBuilder->quoteIdentifier('uid');
+                $queryBuilder->resetQueryPart('groupBy')
+                             ->selectLiteral(sprintf('COUNT(DISTINCT %s.%s)', $tableName, $fieldName));
+            } else {
+                $queryBuilder->count('*');
+            }
 
-        try {
-            $count = $queryBuilder->execute()->fetchColumn(0);
-        } catch (DBALException $e) {
-            throw new SqlErrorException($e->getPrevious()->getMessage(), 1472074379);
-        }
-        if ($query->getOffset()) {
-            $count -= $query->getOffset();
-        }
-        if ($query->getLimit()) {
-            $count = min($count, $query->getLimit());
+            try {
+                $count = $queryBuilder->execute()->fetchColumn(0);
+            } catch (DBALException $e) {
+                throw new SqlErrorException($e->getPrevious()->getMessage(), 1472074379);
+            }
+            if ($query->getOffset()) {
+                $count -= $query->getOffset();
+            }
+            if ($query->getLimit()) {
+                $count = min($count, $query->getLimit());
+            }
         }
         return (int)max(0, $count);
     }