From 4fa0dbe22bbdaee7460a31f8c02d833298d83cf7 Mon Sep 17 00:00:00 2001
From: Claus Due <claus@namelesscoder.net>
Date: Mon, 21 Nov 2016 16:52:03 +0100
Subject: [PATCH] [BUGFIX] Avoid duplicate calls to update reference index

This patch adds a check when processing the update
reference index stack, in order to avoid calling the
update function more than once with the same input
arguments (which are $table and $uid).

Saves around 100 SQL queries when doing a standard
copy of 25 (nested) pages with 25 content elements.

Change-Id: If162218d4eabb749a92270e18c7c39108fd15f34
Resolves: #78761
Releases: master, 7.6
Reviewed-on: https://review.typo3.org/50724
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Stefan Neufeind <typo3.neufeind@speedpartner.de>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
---
 .../core/Classes/DataHandling/DataHandler.php     | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index 7d3cf1de134e..3430d2c842b6 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -5049,11 +5049,22 @@ class DataHandler
         }
         // Update reference index:
         $this->updateRefIndex($table, $uid);
+
+        // We track calls to update the reference index as to avoid calling it twice
+        // with the same arguments. This is done because reference indexing is quite
+        // costly and the update reference index stack usually contain duplicates.
+        // NB: also filled and checked in loop below. The initialisation prevents
+        // running the "root" record twice if it appears in the stack twice.
+        $updateReferenceIndexCalls = [[$table, $uid]];
+
         // If there are entries in the updateRefIndexStack
         if (is_array($this->updateRefIndexStack[$table]) && is_array($this->updateRefIndexStack[$table][$uid])) {
             while ($args = array_pop($this->updateRefIndexStack[$table][$uid])) {
-                // $args[0]: table, $args[1]: uid
-                $this->updateRefIndex($args[0], $args[1]);
+                if (!in_array($args, $updateReferenceIndexCalls, true)) {
+                    // $args[0]: table, $args[1]: uid
+                    $this->updateRefIndex($args[0], $args[1]);
+                    $updateReferenceIndexCalls[] = $args;
+                }
             }
             unset($this->updateRefIndexStack[$table][$uid]);
         }
-- 
GitLab