cleanUpOrphans($childTable, $parentTable, $parentId); $this->logger->debug(sprintf($logMessage, $orphanCount)); // Requeue if there might be more orphans if ($orphanCount >= self::BATCH_SIZE) { $this->jobList->add(self::class, $argument); } } private function cleanUpOrphans( string $childTable, string $parentTable, string $parentId, ): int { // We can't merge both queries into a single one here as DELETEing from a table while // SELECTing it in a sub query is not supported by Oracle DB. // Ref https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/delete.html#idm46006185488144 $selectQb = $this->connection->getQueryBuilder(); $selectQb->select('c.id') ->from($childTable, 'c') ->leftJoin('c', $parentTable, 'p', $selectQb->expr()->eq('c.' . $parentId, 'p.id')) ->where($selectQb->expr()->isNull('p.id')) ->setMaxResults(self::BATCH_SIZE); if (\in_array($parentTable, ['calendars', 'calendarsubscriptions'], true)) { $calendarType = $parentTable === 'calendarsubscriptions' ? CalDavBackend::CALENDAR_TYPE_SUBSCRIPTION : CalDavBackend::CALENDAR_TYPE_CALENDAR; $selectQb->andWhere($selectQb->expr()->eq('c.calendartype', $selectQb->createNamedParameter($calendarType, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); } $result = $selectQb->executeQuery(); $rows = $result->fetchAll(); $result->closeCursor(); if (empty($rows)) { return 0; } $orphanItems = array_map(static fn ($row) => $row['id'], $rows); $deleteQb = $this->connection->getQueryBuilder(); $deleteQb->delete($childTable) ->where($deleteQb->expr()->in('id', $deleteQb->createNamedParameter($orphanItems, IQueryBuilder::PARAM_INT_ARRAY))); $deleteQb->executeStatement(); return count($orphanItems); } }