[BUGFIX] Superfluous SQL queries on copying records 10/31310/9
authorOliver Hader <oliver@typo3.org>
Thu, 3 Jul 2014 11:12:20 +0000 (13:12 +0200)
committerOliver Hader <oliver.hader@typo3.org>
Tue, 8 Jul 2014 10:48:47 +0000 (12:48 +0200)
On copying a page in the backend there are lots of superfluous
SQL queries containing "... WHERE uid=0". The reason for that
is, that DataHandler::recordInfo() is called for each field
which then tries to fetch the database record for the given
uid "NEW...". Casting the new record placeholder to an integer
value ends up with the "uid=0" condition.

In a test with copying a page with some sub-pages, there was a
total of about 1300 SQL queries, 300 of them have been those
superfluous "uid=0" SELECT statements.

Change-Id: Ib7006a7ceb52376032df8eaefaa918407718a482
Resolves: #58357
Releases: 6.2, 6.3
Reviewed-on: https://review.typo3.org/31310
Reviewed-by: Markus Klein
Tested-by: Markus Klein
Reviewed-by: Sascha Egerer
Tested-by: Sascha Egerer
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php
typo3/sysext/core/Classes/DataHandling/DataHandler.php

index 46b8c5f..1a876eb 100644 (file)
@@ -23,6 +23,7 @@ use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
+use TYPO3\CMS\Core\Database\DatabaseConnection;
 use TYPO3\CMS\Frontend\Page\PageRepository;
 
 /**
@@ -76,17 +77,20 @@ class BackendUtility {
         * @param string $fields List of fields to select
         * @param string $where Additional WHERE clause, eg. " AND blablabla = 0
         * @param boolean $useDeleteClause Use the deleteClause to check if a record is deleted (default TRUE)
-        * @return array Returns the row if found, otherwise nothing
+        * @return array|NULL Returns the row if found, otherwise NULL
         */
        static public function getRecord($table, $uid, $fields = '*', $where = '', $useDeleteClause = TRUE) {
-               if ($GLOBALS['TCA'][$table]) {
-                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fields, $table, 'uid=' . (int)$uid . ($useDeleteClause ? self::deleteClause($table) : '') . $where);
-                       $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
-                       $GLOBALS['TYPO3_DB']->sql_free_result($res);
+               // Ensure we have a valid uid (not 0 and not NEWxxxx) and a valid TCA
+               if ((int)$uid && !empty($GLOBALS['TCA'][$table])) {
+                       /** @var DatabaseConnection $db */
+                       $db = $GLOBALS['TYPO3_DB'];
+                       $where = 'uid=' . (int)$uid . ($useDeleteClause ? self::deleteClause($table) : '') . $where;
+                       $row = $db->exec_SELECTgetSingleRow($fields, $table, $where);
                        if ($row) {
                                return $row;
                        }
                }
+               return NULL;
        }
 
        /**
index ce8e676..2cd3954 100644 (file)
@@ -1354,7 +1354,7 @@ class BackendUtilityTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
        public function replaceL10nModeFieldsReplacesFields($table, $row, $tca, $originalRow, $expected) {
                $GLOBALS['TCA'] = $tca;
                $GLOBALS['TYPO3_DB'] = $this->getMock('TYPO3\\CMS\\Core\\Database\\DatabaseConnection');
-               $GLOBALS['TYPO3_DB']->expects($this->any())->method('sql_fetch_assoc')->will($this->returnValue($originalRow));
+               $GLOBALS['TYPO3_DB']->expects($this->any())->method('exec_SELECTgetSingleRow')->will($this->returnValue($originalRow));
 
                /** @var \PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface|\TYPO3\CMS\Backend\Utility\BackendUtility $subject */
                $subject = $this->getAccessibleMock('TYPO3\\CMS\\Backend\\Utility\\BackendUtility', array('dummy'));
index bf52978..6d469cf 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Core\DataHandling;
  */
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Database\DatabaseConnection;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Versioning\VersionState;
 
@@ -5835,18 +5836,20 @@ class DataHandler {
         * @param string $table Table name
         * @param integer $id UID of the record from $table
         * @param string $fieldList Field list for the SELECT query, eg. "*" or "uid,pid,...
-        * @return mixed Returns the selected record on success, otherwise FALSE.
-        * @todo Define visibility
+        * @return NULL|array Returns the selected record on success, otherwise NULL.
         */
        public function recordInfo($table, $id, $fieldList) {
-               if (is_array($GLOBALS['TCA'][$table])) {
-                       $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($fieldList, $table, 'uid=' . (int)$id);
-                       if ($GLOBALS['TYPO3_DB']->sql_num_rows($res)) {
-                               $result = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
-                               $GLOBALS['TYPO3_DB']->sql_free_result($res);
-                               return $result;
-                       }
+               // Skip, if searching for NEW records or there's no TCA table definition
+               if (!(int)$id || !isset($GLOBALS['TCA'][$table])) {
+                       return NULL;
+               }
+               /** @var DatabaseConnection $db */
+               $db = $GLOBALS['TYPO3_DB'];
+               $result = $db->exec_SELECTgetSingleRow($fieldList, $table, 'uid=' . (int)$id);
+               if ($result) {
+                       return $result;
                }
+               return NULL;
        }
 
        /**