From 4d69d8f1cc46e2dfee7e818b2679dc76b757af66 Mon Sep 17 00:00:00 2001 From: Christian Kuhn <lolli@schwarzbu.ch> Date: Wed, 23 Sep 2020 18:17:48 +0200 Subject: [PATCH] [TASK] Drop reference index in workspace discard more effectively Dealing with workspace-discard, where rows are always fully dropped in DB, the expensive reference index operation does not need to be performed at all. It can be substituted with straight db-delete calls for affected sys_refindex rows. Change-Id: Iaa61ef2345c63394fa3286cc9d5dabc5b1a4bb55 Resolves: #92392 Releases: master, 10.4 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65841 Tested-by: Benni Mack <benni@typo3.org> Tested-by: TYPO3com <noreply@typo3.com> Tested-by: Oliver Bartsch <bo@cedev.de> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> Reviewed-by: Benni Mack <benni@typo3.org> Reviewed-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> --- .../core/Classes/DataHandling/DataHandler.php | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php index 4d1872724fa4..1b4ff291be87 100644 --- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php +++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php @@ -5395,7 +5395,7 @@ class DataHandler implements LoggerAwareInterface $this->discardRecordRelations($table, $versionRecord); $this->hardDeleteSingleRecord($table, (int)$versionRecord['uid']); $this->deletedRecords[$table][] = (int)$versionRecord['uid']; - $this->updateRefIndex($table, (int)$versionRecord['uid']); + $this->dropReferenceIndexRowsForRecord($table, (int)$versionRecord['uid']); $this->getRecordHistoryStore()->deleteRecord($table, (int)$versionRecord['uid'], $this->correlationId); $this->log( $table, @@ -5516,6 +5516,7 @@ class DataHandler implements LoggerAwareInterface $dbAnalysis->start($value, $allowedTables, $fieldConfig['MM'], (int)$record['uid'], $table, $fieldConfig); foreach ($dbAnalysis->itemArray as $relationRecord) { // @todo: Something should happen with these relations here ... + // @todo: Can't use dropReferenceIndexRowsForRecord() here, this would drop sys_refindex entries we want to keep $this->updateRefIndex($relationRecord['table'], (int)$relationRecord['id']); } } @@ -7277,6 +7278,35 @@ class DataHandler implements LoggerAwareInterface } } + /** + * Delete rows from sys_refindex a table / uid combination is involved in: + * Either on left side (tablename + recuid) OR right side (ref_table + ref_uid). + * Useful in scenarios like workspace-discard where parents or children are hard deleted: The + * expensive updateRefIndex() does not need to be called since we can just drop straight ahead. + * + * @param string $table Table name, used as tablename and ref_table + * @param int $uid Record uid, used as recuid and ref_uid + */ + protected function dropReferenceIndexRowsForRecord(string $table, int $uid): void + { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex'); + $queryBuilder->delete('sys_refindex') + ->where( + $queryBuilder->expr()->eq('workspace', $queryBuilder->createNamedParameter((int)$this->BE_USER->workspace, \PDO::PARAM_INT)), + $queryBuilder->expr()->orX( + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('tablename', $queryBuilder->createNamedParameter($table)), + $queryBuilder->expr()->eq('recuid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) + ), + $queryBuilder->expr()->andX( + $queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter($table)), + $queryBuilder->expr()->eq('ref_uid', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)) + ) + ) + ) + ->execute(); + } + /********************************************* * * Misc functions -- GitLab