From 0f8e4419d64c70920acdbe8da9245ef3a3ce5da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Wed, 19 Jul 2023 13:31:55 +0200 Subject: [PATCH] fix: Use simple query and chunk in PHP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reverts #4339 and #4539 except for the added tests and moves to plain PHP chunking to avoid issues with MySQL 8 Signed-off-by: Julius Härtl --- lib/Db/SessionMapper.php | 44 +++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/lib/Db/SessionMapper.php b/lib/Db/SessionMapper.php index c2710df3217..03ca252f65a 100644 --- a/lib/Db/SessionMapper.php +++ b/lib/Db/SessionMapper.php @@ -100,30 +100,36 @@ public function findAllInactive() { } public function deleteInactiveWithoutSteps(?int $documentId = null): int { - $selectSubQuery = $this->db->getQueryBuilder(); - $selectSubQuery->select('s.id') + $lastContact = time() - SessionService::SESSION_VALID_TIME; + + $inactiveSessionBuilder = $this->db->getQueryBuilder(); + $inactiveSessionBuilder->select('s.id') ->from('text_sessions', 's') - ->leftJoin('s', 'text_steps', 'st', $selectSubQuery->expr()->eq('st.session_id', 's.id')) - ->where($selectSubQuery->expr()->lt('last_contact', $selectSubQuery->createParameter('lastContact'))) - ->andWhere($selectSubQuery->expr()->isNull('st.id')); + ->leftJoin('s', 'text_steps', 'st', $inactiveSessionBuilder->expr()->eq('st.session_id', 's.id')) + ->where($inactiveSessionBuilder->expr()->lt('last_contact', $inactiveSessionBuilder->createNamedParameter($lastContact))) + ->andWhere($inactiveSessionBuilder->expr()->isNull('st.id')); if ($documentId !== null) { - $selectSubQuery->andWhere($selectSubQuery->expr()->eq('s.document_id', $selectSubQuery->createParameter('documentId'))); + $inactiveSessionBuilder->andWhere($inactiveSessionBuilder->expr()->eq('s.document_id', $inactiveSessionBuilder->createNamedParameter($documentId))); } + $result = $inactiveSessionBuilder->executeQuery(); + $documentIds = array_map(function ($row) { + return (int)$row['id']; + }, $result->fetchAll()); + $result->closeCursor(); - $qb = $this->db->getQueryBuilder(); - $qb->delete($this->getTableName()); - if ($documentId !== null) { - $qb->where($selectSubQuery->expr()->eq('document_id', $selectSubQuery->createParameter('documentId'))); - $qb->andWhere($qb->expr()->in('id', $qb->createFunction($selectSubQuery->getSQL()))); - } else { - $qb->where($qb->expr()->in('id', $qb->createFunction($selectSubQuery->getSQL()))); - } - $qb->setParameters([ - 'lastContact' => time() - SessionService::SESSION_VALID_TIME, - 'documentId' => $documentId, - ]); + $chunks = array_chunk($documentIds, 500); - return $qb->executeStatement(); + $deleteBuilder = $this->db->getQueryBuilder(); + $deleteBuilder->delete($this->getTableName()) + ->where($deleteBuilder->expr()->in('id', $deleteBuilder->createParameter('ids'), IQueryBuilder::PARAM_INT_ARRAY)); + + $deletedCount = 0; + foreach ($chunks as $ids) { + $deleteBuilder->setParameter('ids', $ids, IQueryBuilder::PARAM_INT_ARRAY); + + $deletedCount += $deleteBuilder->executeStatement(); + } + return $deletedCount; } public function deleteByDocumentId($documentId): int {