aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2023-07-17 11:26:00 +0200
committerGitHub <noreply@github.com>2023-07-17 11:26:00 +0200
commit83f7ea01cd1bd30b2bba5d304ae6c2279f68d6f8 (patch)
tree0e815d5b40fa445e628aa39645e794cfab29e2d9
parent31f07f31926a061268c28055dbde74f9dc058b6d (diff)
parent18db96c304c2b2d93c3effc2c1d5b9320fe78ce1 (diff)
downloadnextcloud-server-83f7ea01cd1bd30b2bba5d304ae6c2279f68d6f8.tar.gz
nextcloud-server-83f7ea01cd1bd30b2bba5d304ae6c2279f68d6f8.zip
Merge pull request #39396 from nextcloud/backport/39389/stable27
-rw-r--r--apps/settings/lib/Controller/CheckSetupController.php23
-rw-r--r--apps/settings/tests/Controller/CheckSetupControllerTest.php8
-rw-r--r--core/Command/Db/AddMissingIndices.php34
-rw-r--r--core/register_command.php2
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/public/DB/Events/AddMissingIndicesEvent.php59
-rw-r--r--lib/public/IDBConnection.php5
8 files changed, 128 insertions, 5 deletions
diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php
index be0abe0d75c..a0c52f6e13d 100644
--- a/apps/settings/lib/Controller/CheckSetupController.php
+++ b/apps/settings/lib/Controller/CheckSetupController.php
@@ -72,7 +72,9 @@ use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\RedirectResponse;
+use OCP\DB\Events\AddMissingIndicesEvent;
use OCP\DB\Types;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
@@ -102,6 +104,8 @@ class CheckSetupController extends Controller {
private $checker;
/** @var LoggerInterface */
private $logger;
+ /** @var IEventDispatcher */
+ private $eventDispatcher;
/** @var EventDispatcherInterface */
private $dispatcher;
/** @var Connection */
@@ -135,6 +139,7 @@ class CheckSetupController extends Controller {
IL10N $l10n,
Checker $checker,
LoggerInterface $logger,
+ IEventDispatcher $eventDispatcher,
EventDispatcherInterface $dispatcher,
Connection $db,
ILockingProvider $lockingProvider,
@@ -155,6 +160,7 @@ class CheckSetupController extends Controller {
$this->l10n = $l10n;
$this->checker = $checker;
$this->logger = $logger;
+ $this->eventDispatcher = $eventDispatcher;
$this->dispatcher = $dispatcher;
$this->db = $db;
$this->lockingProvider = $lockingProvider;
@@ -551,10 +557,27 @@ Raw output
protected function hasMissingIndexes(): array {
$indexInfo = new MissingIndexInformation();
+
// Dispatch event so apps can also hint for pending index updates if needed
$event = new GenericEvent($indexInfo);
$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_INDEXES_EVENT, $event);
+ $event = new AddMissingIndicesEvent();
+ $this->eventDispatcher->dispatchTyped($event);
+ $missingIndices = $event->getMissingIndices();
+
+ if ($missingIndices !== []) {
+ $schema = new SchemaWrapper(\OCP\Server::get(Connection::class));
+ foreach ($missingIndices as $missingIndex) {
+ if ($schema->hasTable($missingIndex['tableName'])) {
+ $table = $schema->getTable($missingIndex['tableName']);
+ if (!$table->hasIndex($missingIndex['indexName'])) {
+ $indexInfo->addHintForMissingSubject($missingIndex['tableName'], $missingIndex['indexName']);
+ }
+ }
+ }
+ }
+
return $indexInfo->getListOfMissingIndexes();
}
diff --git a/apps/settings/tests/Controller/CheckSetupControllerTest.php b/apps/settings/tests/Controller/CheckSetupControllerTest.php
index 2b074d24c39..390166cb947 100644
--- a/apps/settings/tests/Controller/CheckSetupControllerTest.php
+++ b/apps/settings/tests/Controller/CheckSetupControllerTest.php
@@ -47,6 +47,7 @@ use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\RedirectResponse;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Http\Client\IClientService;
use OCP\IConfig;
use OCP\IDateTimeFormatter;
@@ -87,6 +88,8 @@ class CheckSetupControllerTest extends TestCase {
private $logger;
/** @var Checker|\PHPUnit\Framework\MockObject\MockObject */
private $checker;
+ /** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
+ private $eventDispatcher;
/** @var EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject */
private $dispatcher;
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject */
@@ -137,6 +140,7 @@ class CheckSetupControllerTest extends TestCase {
->willReturnCallback(function ($message, array $replace) {
return vsprintf($message, $replace);
});
+ $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)
->disableOriginalConstructor()->getMock();
$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
@@ -167,6 +171,7 @@ class CheckSetupControllerTest extends TestCase {
$this->l10n,
$this->checker,
$this->logger,
+ $this->eventDispatcher,
$this->dispatcher,
$this->db,
$this->lockingProvider,
@@ -676,6 +681,7 @@ class CheckSetupControllerTest extends TestCase {
$this->l10n,
$this->checker,
$this->logger,
+ $this->eventDispatcher,
$this->dispatcher,
$this->db,
$this->lockingProvider,
@@ -1440,6 +1446,7 @@ Array
$this->l10n,
$this->checker,
$this->logger,
+ $this->eventDispatcher,
$this->dispatcher,
$this->db,
$this->lockingProvider,
@@ -1494,6 +1501,7 @@ Array
$this->l10n,
$this->checker,
$this->logger,
+ $this->eventDispatcher,
$this->dispatcher,
$this->db,
$this->lockingProvider,
diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php
index f0b4c14e15c..1044cea5547 100644
--- a/core/Command/Db/AddMissingIndices.php
+++ b/core/Command/Db/AddMissingIndices.php
@@ -36,6 +36,8 @@ namespace OC\Core\Command\Db;
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
use OC\DB\Connection;
use OC\DB\SchemaWrapper;
+use OCP\DB\Events\AddMissingIndicesEvent;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\IDBConnection;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
@@ -54,12 +56,14 @@ use Symfony\Component\EventDispatcher\GenericEvent;
*/
class AddMissingIndices extends Command {
private Connection $connection;
+ private IEventDispatcher $eventDispatcher;
private EventDispatcherInterface $dispatcher;
- public function __construct(Connection $connection, EventDispatcherInterface $dispatcher) {
+ public function __construct(Connection $connection, IEventDispatcher $eventDispatcher, EventDispatcherInterface $dispatcher) {
parent::__construct();
$this->connection = $connection;
+ $this->eventDispatcher = $eventDispatcher;
$this->dispatcher = $dispatcher;
}
@@ -71,11 +75,37 @@ class AddMissingIndices extends Command {
}
protected function execute(InputInterface $input, OutputInterface $output): int {
- $this->addCoreIndexes($output, $input->getOption('dry-run'));
+ $dryRun = $input->getOption('dry-run');
+
+ $this->addCoreIndexes($output, $dryRun);
// Dispatch event so apps can also update indexes if needed
$event = new GenericEvent($output);
$this->dispatcher->dispatch(IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);
+
+ $event = new AddMissingIndicesEvent();
+ $this->eventDispatcher->dispatchTyped($event);
+
+ $missingIndices = $event->getMissingIndices();
+ if ($missingIndices !== []) {
+ $schema = new SchemaWrapper($this->connection);
+
+ foreach ($missingIndices as $missingIndex) {
+ if ($schema->hasTable($missingIndex['tableName'])) {
+ $table = $schema->getTable($missingIndex['tableName']);
+ if (!$table->hasIndex($missingIndex['indexName'])) {
+ $output->writeln('<info>Adding additional ' . $missingIndex['indexName'] . ' index to the ' . $table->getName() . ' table, this can take some time...</info>');
+ $table->addIndex($missingIndex['columns'], $missingIndex['indexName']);
+ $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
+ if ($dryRun && $sqlQueries !== null) {
+ $output->writeln($sqlQueries);
+ }
+ $output->writeln('<info>' . $table->getName() . ' table updated successfully.</info>');
+ }
+ }
+ }
+ }
+
return 0;
}
diff --git a/core/register_command.php b/core/register_command.php
index 8f600d7b894..32cd4099618 100644
--- a/core/register_command.php
+++ b/core/register_command.php
@@ -109,7 +109,7 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) {
$application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig())));
$application->add(new OC\Core\Command\Db\ConvertMysqlToMB4(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection(), \OC::$server->getURLGenerator(), \OC::$server->get(LoggerInterface::class)));
$application->add(new OC\Core\Command\Db\ConvertFilecacheBigInt(\OC::$server->get(\OC\DB\Connection::class)));
- $application->add(new OC\Core\Command\Db\AddMissingIndices(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher()));
+ $application->add(\OCP\Server::get(\OC\Core\Command\Db\AddMissingIndices::class));
$application->add(new OC\Core\Command\Db\AddMissingColumns(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher()));
$application->add(new OC\Core\Command\Db\AddMissingPrimaryKeys(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher()));
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 83fae3cfcc1..e53b4fe94c6 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -202,6 +202,7 @@ return array(
'OCP\\Contacts\\ContactsMenu\\IProvider' => $baseDir . '/lib/public/Contacts/ContactsMenu/IProvider.php',
'OCP\\Contacts\\Events\\ContactInteractedWithEvent' => $baseDir . '/lib/public/Contacts/Events/ContactInteractedWithEvent.php',
'OCP\\Contacts\\IManager' => $baseDir . '/lib/public/Contacts/IManager.php',
+ 'OCP\\DB\\Events\\AddMissingIndicesEvent' => $baseDir . '/lib/public/DB/Events/AddMissingIndicesEvent.php',
'OCP\\DB\\Exception' => $baseDir . '/lib/public/DB/Exception.php',
'OCP\\DB\\IPreparedStatement' => $baseDir . '/lib/public/DB/IPreparedStatement.php',
'OCP\\DB\\IResult' => $baseDir . '/lib/public/DB/IResult.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 34cc99747ca..58bdace5dcb 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -235,6 +235,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\Contacts\\ContactsMenu\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IProvider.php',
'OCP\\Contacts\\Events\\ContactInteractedWithEvent' => __DIR__ . '/../../..' . '/lib/public/Contacts/Events/ContactInteractedWithEvent.php',
'OCP\\Contacts\\IManager' => __DIR__ . '/../../..' . '/lib/public/Contacts/IManager.php',
+ 'OCP\\DB\\Events\\AddMissingIndicesEvent' => __DIR__ . '/../../..' . '/lib/public/DB/Events/AddMissingIndicesEvent.php',
'OCP\\DB\\Exception' => __DIR__ . '/../../..' . '/lib/public/DB/Exception.php',
'OCP\\DB\\IPreparedStatement' => __DIR__ . '/../../..' . '/lib/public/DB/IPreparedStatement.php',
'OCP\\DB\\IResult' => __DIR__ . '/../../..' . '/lib/public/DB/IResult.php',
diff --git a/lib/public/DB/Events/AddMissingIndicesEvent.php b/lib/public/DB/Events/AddMissingIndicesEvent.php
new file mode 100644
index 00000000000..139b776b136
--- /dev/null
+++ b/lib/public/DB/Events/AddMissingIndicesEvent.php
@@ -0,0 +1,59 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2023 Julius Härtl <jus@bitgrid.net
+ *
+ * @author Julius Härtl <jus@bitgrid.net
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCP\DB\Events;
+
+/**
+ * Event to allow apps to register information about missing database indices
+ *
+ * This event will be dispatched for checking on the admin settings and when running
+ * occ db:add-missing-indices which will then create those indices
+ *
+ * @since 28.0.0
+ */
+class AddMissingIndicesEvent extends \OCP\EventDispatcher\Event {
+ /** @var array<array-key, array{tableName: string, indexName: string, columns: string[]}> */
+ private array $missingIndices = [];
+
+ /**
+ * @param string[] $columns
+ * @since 28.0.0
+ */
+ public function addMissingIndex(string $tableName, string $indexName, array $columns): void {
+ $this->missingIndices[] = [
+ 'tableName' => $tableName,
+ 'indexName' => $indexName,
+ 'columns' => $columns
+ ];
+ }
+
+ /**
+ * @since 28.0.0
+ * @return array<array-key, array{tableName: string, indexName: string, columns: string[]}>
+ */
+ public function getMissingIndices(): array {
+ return $this->missingIndices;
+ }
+}
diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php
index 69ede2c8438..bfc63b2aab0 100644
--- a/lib/public/IDBConnection.php
+++ b/lib/public/IDBConnection.php
@@ -34,6 +34,7 @@
namespace OCP;
use Doctrine\DBAL\Schema\Schema;
+use OCP\DB\Events\AddMissingIndicesEvent;
use OCP\DB\Exception;
use OCP\DB\IPreparedStatement;
use OCP\DB\IResult;
@@ -46,12 +47,12 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
*/
interface IDBConnection {
/**
- * @deprecated 22.0.0 this is an internal event
+ * @deprecated 22.0.0 this is an internal event, use {@see AddMissingIndicesEvent} instead
*/
public const ADD_MISSING_INDEXES_EVENT = self::class . '::ADD_MISSING_INDEXES';
/**
- * @deprecated 22.0.0 this is an internal event
+ * @deprecated 22.0.0 this is an internal event, use {@see AddMissingIndicesEvent} instead
*/
public const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES';