Skip to content

Commit f9e5c3f

Browse files
committed
feat: Add public event for missing indices
Signed-off-by: Julius Härtl <jus@bitgrid.net>
1 parent 99aefbd commit f9e5c3f

8 files changed

Lines changed: 119 additions & 4 deletions

File tree

apps/settings/lib/Controller/CheckSetupController.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@
7474
use OCP\AppFramework\Http\DataDisplayResponse;
7575
use OCP\AppFramework\Http\DataResponse;
7676
use OCP\AppFramework\Http\RedirectResponse;
77+
use OCP\DB\Events\AddMissingIndicesEvent;
7778
use OCP\DB\Types;
79+
use OCP\EventDispatcher\IEventDispatcher;
7880
use OCP\Http\Client\IClientService;
7981
use OCP\IConfig;
8082
use OCP\IDateTimeFormatter;
@@ -105,6 +107,8 @@ class CheckSetupController extends Controller {
105107
private $checker;
106108
/** @var LoggerInterface */
107109
private $logger;
110+
/** @var IEventDispatcher */
111+
private $eventDispatcher;
108112
/** @var EventDispatcherInterface */
109113
private $dispatcher;
110114
/** @var Connection */
@@ -138,6 +142,7 @@ public function __construct($AppName,
138142
IL10N $l10n,
139143
Checker $checker,
140144
LoggerInterface $logger,
145+
IEventDispatcher $eventDispatcher,
141146
EventDispatcherInterface $dispatcher,
142147
Connection $db,
143148
ILockingProvider $lockingProvider,
@@ -158,6 +163,7 @@ public function __construct($AppName,
158163
$this->l10n = $l10n;
159164
$this->checker = $checker;
160165
$this->logger = $logger;
166+
$this->eventDispatcher = $eventDispatcher;
161167
$this->dispatcher = $dispatcher;
162168
$this->db = $db;
163169
$this->lockingProvider = $lockingProvider;
@@ -543,10 +549,27 @@ protected function hasFreeTypeSupport() {
543549

544550
protected function hasMissingIndexes(): array {
545551
$indexInfo = new MissingIndexInformation();
552+
546553
// Dispatch event so apps can also hint for pending index updates if needed
547554
$event = new GenericEvent($indexInfo);
548555
$this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_INDEXES_EVENT, $event);
549556

557+
$event = new AddMissingIndicesEvent();
558+
$this->eventDispatcher->dispatchTyped($event);
559+
$missingIndices = $event->getMissingIndices();
560+
561+
if ($missingIndices !== []) {
562+
$schema = new SchemaWrapper(\OCP\Server::get(Connection::class));
563+
foreach ($missingIndices as $missingIndex) {
564+
if ($schema->hasTable($missingIndex['tableName'])) {
565+
$table = $schema->getTable($missingIndex['tableName']);
566+
if (!$table->hasIndex($missingIndex['indexName'])) {
567+
$indexInfo->addHintForMissingSubject($missingIndex['tableName'], $missingIndex['indexName']);
568+
}
569+
}
570+
}
571+
}
572+
550573
return $indexInfo->getListOfMissingIndexes();
551574
}
552575

apps/settings/tests/Controller/CheckSetupControllerTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
use OCP\AppFramework\Http\DataDisplayResponse;
4848
use OCP\AppFramework\Http\DataResponse;
4949
use OCP\AppFramework\Http\RedirectResponse;
50+
use OCP\EventDispatcher\IEventDispatcher;
5051
use OCP\Http\Client\IClientService;
5152
use OCP\IConfig;
5253
use OCP\IDateTimeFormatter;
@@ -87,6 +88,8 @@ class CheckSetupControllerTest extends TestCase {
8788
private $logger;
8889
/** @var Checker|\PHPUnit\Framework\MockObject\MockObject */
8990
private $checker;
91+
/** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
92+
private $eventDispatcher;
9093
/** @var EventDispatcherInterface|\PHPUnit\Framework\MockObject\MockObject */
9194
private $dispatcher;
9295
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject */
@@ -137,6 +140,7 @@ protected function setUp(): void {
137140
->willReturnCallback(function ($message, array $replace) {
138141
return vsprintf($message, $replace);
139142
});
143+
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
140144
$this->dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)
141145
->disableOriginalConstructor()->getMock();
142146
$this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker')
@@ -167,6 +171,7 @@ protected function setUp(): void {
167171
$this->l10n,
168172
$this->checker,
169173
$this->logger,
174+
$this->eventDispatcher,
170175
$this->dispatcher,
171176
$this->db,
172177
$this->lockingProvider,
@@ -676,6 +681,7 @@ public function testGetCurlVersion() {
676681
$this->l10n,
677682
$this->checker,
678683
$this->logger,
684+
$this->eventDispatcher,
679685
$this->dispatcher,
680686
$this->db,
681687
$this->lockingProvider,
@@ -1403,6 +1409,7 @@ public function testIsMysqlUsedWithoutUTF8MB4(string $db, bool $useUTF8MB4, bool
14031409
$this->l10n,
14041410
$this->checker,
14051411
$this->logger,
1412+
$this->eventDispatcher,
14061413
$this->dispatcher,
14071414
$this->db,
14081415
$this->lockingProvider,
@@ -1457,6 +1464,7 @@ public function testIsEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(string $m
14571464
$this->l10n,
14581465
$this->checker,
14591466
$this->logger,
1467+
$this->eventDispatcher,
14601468
$this->dispatcher,
14611469
$this->db,
14621470
$this->lockingProvider,

core/Command/Db/AddMissingIndices.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
use Doctrine\DBAL\Platforms\PostgreSQL94Platform;
3737
use OC\DB\Connection;
3838
use OC\DB\SchemaWrapper;
39+
use OCP\DB\Events\AddMissingIndicesEvent;
40+
use OCP\EventDispatcher\IEventDispatcher;
3941
use OCP\IDBConnection;
4042
use Symfony\Component\Console\Command\Command;
4143
use Symfony\Component\Console\Input\InputOption;
@@ -55,6 +57,7 @@
5557
class AddMissingIndices extends Command {
5658
public function __construct(
5759
private Connection $connection,
60+
private IEventDispatcher $eventDispatcher,
5861
private EventDispatcherInterface $dispatcher,
5962
) {
6063
parent::__construct();
@@ -68,11 +71,37 @@ protected function configure() {
6871
}
6972

7073
protected function execute(InputInterface $input, OutputInterface $output): int {
71-
$this->addCoreIndexes($output, $input->getOption('dry-run'));
74+
$dryRun = $input->getOption('dry-run');
75+
76+
$this->addCoreIndexes($output, $dryRun);
7277

7378
// Dispatch event so apps can also update indexes if needed
7479
$event = new GenericEvent($output);
7580
$this->dispatcher->dispatch(IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);
81+
82+
$event = new AddMissingIndicesEvent();
83+
$this->eventDispatcher->dispatchTyped($event);
84+
85+
$missingIndices = $event->getMissingIndices();
86+
if ($missingIndices !== []) {
87+
$schema = new SchemaWrapper($this->connection);
88+
89+
foreach ($missingIndices as $missingIndex) {
90+
if ($schema->hasTable($missingIndex['tableName'])) {
91+
$table = $schema->getTable($missingIndex['tableName']);
92+
if (!$table->hasIndex($missingIndex['indexName'])) {
93+
$output->writeln('<info>Adding additional ' . $missingIndex['indexName'] . ' index to the ' . $table->getName() . ' table, this can take some time...</info>');
94+
$table->addIndex($missingIndex['columns'], $missingIndex['indexName']);
95+
$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
96+
if ($dryRun && $sqlQueries !== null) {
97+
$output->writeln($sqlQueries);
98+
}
99+
$output->writeln('<info>' . $table->getName() . ' table updated successfully.</info>');
100+
}
101+
}
102+
}
103+
}
104+
76105
return 0;
77106
}
78107

core/register_command.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@
109109
$application->add(new OC\Core\Command\Db\ConvertType(\OC::$server->getConfig(), new \OC\DB\ConnectionFactory(\OC::$server->getSystemConfig())));
110110
$application->add(new OC\Core\Command\Db\ConvertMysqlToMB4(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection(), \OC::$server->getURLGenerator(), \OC::$server->get(LoggerInterface::class)));
111111
$application->add(new OC\Core\Command\Db\ConvertFilecacheBigInt(\OC::$server->get(\OC\DB\Connection::class)));
112-
$application->add(new OC\Core\Command\Db\AddMissingIndices(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher()));
112+
$application->add(\OCP\Server::get(\OC\Core\Command\Db\AddMissingIndices::class));
113113
$application->add(new OC\Core\Command\Db\AddMissingColumns(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher()));
114114
$application->add(new OC\Core\Command\Db\AddMissingPrimaryKeys(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher()));
115115

lib/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@
209209
'OCP\\Contacts\\ContactsMenu\\IProvider' => $baseDir . '/lib/public/Contacts/ContactsMenu/IProvider.php',
210210
'OCP\\Contacts\\Events\\ContactInteractedWithEvent' => $baseDir . '/lib/public/Contacts/Events/ContactInteractedWithEvent.php',
211211
'OCP\\Contacts\\IManager' => $baseDir . '/lib/public/Contacts/IManager.php',
212+
'OCP\\DB\\Events\\AddMissingIndicesEvent' => $baseDir . '/lib/public/DB/Events/AddMissingIndicesEvent.php',
212213
'OCP\\DB\\Exception' => $baseDir . '/lib/public/DB/Exception.php',
213214
'OCP\\DB\\IPreparedStatement' => $baseDir . '/lib/public/DB/IPreparedStatement.php',
214215
'OCP\\DB\\IResult' => $baseDir . '/lib/public/DB/IResult.php',

lib/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
242242
'OCP\\Contacts\\ContactsMenu\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Contacts/ContactsMenu/IProvider.php',
243243
'OCP\\Contacts\\Events\\ContactInteractedWithEvent' => __DIR__ . '/../../..' . '/lib/public/Contacts/Events/ContactInteractedWithEvent.php',
244244
'OCP\\Contacts\\IManager' => __DIR__ . '/../../..' . '/lib/public/Contacts/IManager.php',
245+
'OCP\\DB\\Events\\AddMissingIndicesEvent' => __DIR__ . '/../../..' . '/lib/public/DB/Events/AddMissingIndicesEvent.php',
245246
'OCP\\DB\\Exception' => __DIR__ . '/../../..' . '/lib/public/DB/Exception.php',
246247
'OCP\\DB\\IPreparedStatement' => __DIR__ . '/../../..' . '/lib/public/DB/IPreparedStatement.php',
247248
'OCP\\DB\\IResult' => __DIR__ . '/../../..' . '/lib/public/DB/IResult.php',
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* @copyright Copyright (c) 2023 Julius Härtl <jus@bitgrid.net
6+
*
7+
* @author Julius Härtl <jus@bitgrid.net
8+
*
9+
* @license GNU AGPL version 3 or any later version
10+
*
11+
* This program is free software: you can redistribute it and/or modify
12+
* it under the terms of the GNU Affero General Public License as
13+
* published by the Free Software Foundation, either version 3 of the
14+
* License, or (at your option) any later version.
15+
*
16+
* This program is distributed in the hope that it will be useful,
17+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+
* GNU Affero General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Affero General Public License
22+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
23+
*
24+
*/
25+
26+
namespace OCP\DB\Events;
27+
28+
/**
29+
* Event to allow apps to register information about missing database indices
30+
*
31+
* This event will be dispatched for checking on the admin settings and when running
32+
* occ db:add-missing-indices which will then create those indices
33+
*
34+
* @since 28.0.0
35+
*/
36+
class AddMissingIndicesEvent extends \OCP\EventDispatcher\Event {
37+
private array $missingIndices = [];
38+
39+
/** @since 28.0.0 */
40+
public function addMissingIndex(string $tableName, string $indexName, array $columns): void {
41+
$this->missingIndices[] = [
42+
'tableName' => $tableName,
43+
'indexName' => $indexName,
44+
'columns' => $columns
45+
];
46+
}
47+
48+
/** @since 28.0.0 */
49+
public function getMissingIndices(): array {
50+
return $this->missingIndices;
51+
}
52+
}

lib/public/IDBConnection.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
namespace OCP;
3535

3636
use Doctrine\DBAL\Schema\Schema;
37+
use OCP\DB\Events\AddMissingIndicesEvent;
3738
use OCP\DB\Exception;
3839
use OCP\DB\IPreparedStatement;
3940
use OCP\DB\IResult;
@@ -46,12 +47,12 @@
4647
*/
4748
interface IDBConnection {
4849
/**
49-
* @deprecated 22.0.0 this is an internal event
50+
* @deprecated 22.0.0 this is an internal event, use {@see AddMissingIndicesEvent} instead
5051
*/
5152
public const ADD_MISSING_INDEXES_EVENT = self::class . '::ADD_MISSING_INDEXES';
5253

5354
/**
54-
* @deprecated 22.0.0 this is an internal event
55+
* @deprecated 22.0.0 this is an internal event, use {@see AddMissingIndicesEvent} instead
5556
*/
5657
public const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES';
5758

0 commit comments

Comments
 (0)