From 2eded24eff5f3f0c911ffbd5841178030c8f9363 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 19 Jul 2023 22:36:59 +0200 Subject: [PATCH 1/7] feat(dispatcher): Add typed event for "db:add-missing-columns" Signed-off-by: Joas Schilling --- .../lib/Controller/CheckSetupController.php | 23 ++++++- core/Command/Db/AddMissingColumns.php | 52 +++++++++++++--- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + .../DB/Events/AddMissingColumnsEvent.php | 60 +++++++++++++++++++ .../DB/Events/AddMissingIndicesEvent.php | 4 +- lib/public/IDBConnection.php | 5 +- 7 files changed, 130 insertions(+), 16 deletions(-) create mode 100644 lib/public/DB/Events/AddMissingColumnsEvent.php diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php index 07fb627dbd8..170c6a3870a 100644 --- a/apps/settings/lib/Controller/CheckSetupController.php +++ b/apps/settings/lib/Controller/CheckSetupController.php @@ -74,6 +74,7 @@ use OCP\AppFramework\Http\Attribute\IgnoreOpenAPI; use OCP\AppFramework\Http\DataDisplayResponse; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\RedirectResponse; +use OCP\DB\Events\AddMissingColumnsEvent; use OCP\DB\Events\AddMissingIndicesEvent; use OCP\DB\Types; use OCP\EventDispatcher\IEventDispatcher; @@ -583,12 +584,28 @@ Raw output } protected function hasMissingColumns(): array { - $indexInfo = new MissingColumnInformation(); + $columnInfo = new MissingColumnInformation(); // Dispatch event so apps can also hint for pending index updates if needed - $event = new GenericEvent($indexInfo); + $event = new GenericEvent($columnInfo); $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_COLUMNS_EVENT, $event); - return $indexInfo->getListOfMissingColumns(); + $event = new AddMissingColumnsEvent(); + $this->eventDispatcher->dispatchTyped($event); + $missingColumns = $event->getMissingColumns(); + + if (!empty($missingColumns)) { + $schema = new SchemaWrapper(\OCP\Server::get(Connection::class)); + foreach ($missingColumns as $missingColumn) { + if ($schema->hasTable($missingColumn['tableName'])) { + $table = $schema->getTable($missingColumn['tableName']); + if (!$table->hasColumn($missingColumn['columnName'])) { + $columnInfo->addHintForMissingColumn($missingColumn['tableName'], $missingColumn['columnName']); + } + } + } + } + + return $columnInfo->getListOfMissingColumns(); } protected function isSqliteUsed() { diff --git a/core/Command/Db/AddMissingColumns.php b/core/Command/Db/AddMissingColumns.php index 8e6f439e0c4..93e346e498c 100644 --- a/core/Command/Db/AddMissingColumns.php +++ b/core/Command/Db/AddMissingColumns.php @@ -28,6 +28,9 @@ namespace OC\Core\Command\Db; use OC\DB\Connection; use OC\DB\SchemaWrapper; +use OCP\DB\Events\AddMissingColumnsEvent; +use OCP\DB\Types; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -47,7 +50,8 @@ use Symfony\Component\EventDispatcher\GenericEvent; class AddMissingColumns extends Command { public function __construct( private Connection $connection, - private EventDispatcherInterface $dispatcher, + private EventDispatcherInterface $legacyDispatcher, + private IEventDispatcher $dispatcher, ) { parent::__construct(); } @@ -60,22 +64,54 @@ class AddMissingColumns extends Command { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->addCoreColumns($output, $input->getOption('dry-run')); + $dryRun = $input->getOption('dry-run'); + + $updated = $this->addCoreColumns($output, $dryRun); // Dispatch event so apps can also update columns if needed $event = new GenericEvent($output); - $this->dispatcher->dispatch(IDBConnection::ADD_MISSING_COLUMNS_EVENT, $event); + $this->legacyDispatcher->dispatch(IDBConnection::ADD_MISSING_COLUMNS_EVENT, $event); + + $event = new AddMissingColumnsEvent(); + $this->dispatcher->dispatchTyped($event); + $missingColumns = $event->getMissingColumns(); + + if (!empty($missingColumns)) { + $schema = new SchemaWrapper($this->connection); + + foreach ($missingColumns as $missingColumn) { + if ($schema->hasTable($missingColumn['tableName'])) { + $table = $schema->getTable($missingColumn['tableName']); + if (!$table->hasColumn($missingColumn['columnName'])) { + $output->writeln('Adding additional ' . $missingColumn['columnName'] . ' column to the ' . $missingColumn['tableName'] . ' table, this can take some time...'); + $table->addColumn($missingColumn['columnName'], $missingColumn['typeName'], $missingColumn['options']); + $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); + if ($dryRun && $sqlQueries !== null) { + $output->writeln($sqlQueries); + } + $updated = true; + $output->writeln('' . $missingColumn['tableName'] . ' table updated successfully.'); + } + } + } + } + + if (!$updated) { + $output->writeln('Done.'); + } + return 0; } /** - * add missing indices to the share table + * Add missing column for core tables * * @param OutputInterface $output * @param bool $dryRun If true, will return the sql queries instead of running them. + * @return bool True when the schema changed * @throws \Doctrine\DBAL\Schema\SchemaException */ - private function addCoreColumns(OutputInterface $output, bool $dryRun): void { + private function addCoreColumns(OutputInterface $output, bool $dryRun): bool { $output->writeln('Check columns of the comments table.'); $schema = new SchemaWrapper($this->connection); @@ -85,7 +121,7 @@ class AddMissingColumns extends Command { $table = $schema->getTable('comments'); if (!$table->hasColumn('reference_id')) { $output->writeln('Adding additional reference_id column to the comments table, this can take some time...'); - $table->addColumn('reference_id', 'string', [ + $table->addColumn('reference_id', Types::STRING, [ 'notnull' => false, 'length' => 64, ]); @@ -98,8 +134,6 @@ class AddMissingColumns extends Command { } } - if (!$updated) { - $output->writeln('Done.'); - } + return $updated; } } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index fcd1020be10..5b89d45cdfb 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -210,6 +210,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\\AddMissingColumnsEvent' => $baseDir . '/lib/public/DB/Events/AddMissingColumnsEvent.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', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 783e63550c0..2b71939fa6f 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -243,6 +243,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\\AddMissingColumnsEvent' => __DIR__ . '/../../..' . '/lib/public/DB/Events/AddMissingColumnsEvent.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', diff --git a/lib/public/DB/Events/AddMissingColumnsEvent.php b/lib/public/DB/Events/AddMissingColumnsEvent.php new file mode 100644 index 00000000000..1fb44e86842 --- /dev/null +++ b/lib/public/DB/Events/AddMissingColumnsEvent.php @@ -0,0 +1,60 @@ + + * + * @author Joas Schilling + * + * @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 . + * + */ + +namespace OCP\DB\Events; + +/** + * Event to allow apps to register information about missing database columns + * + * This event will be dispatched for checking on the admin settings and when running + * occ db:add-missing-columns which will then create those columns + * + * @since 28.0.0 + */ +class AddMissingColumnsEvent extends \OCP\EventDispatcher\Event { + /** @var array */ + private array $missingColumns = []; + + /** + * @param mixed[] $options + * @since 28.0.0 + */ + public function addMissingColumn(string $tableName, string $columnName, string $typeName, array $options): void { + $this->missingColumns[] = [ + 'tableName' => $tableName, + 'columnName' => $columnName, + 'typeName' => $typeName, + 'options' => $options, + ]; + } + + /** + * @since 28.0.0 + * @return array + */ + public function getMissingColumns(): array { + return $this->missingColumns; + } +} diff --git a/lib/public/DB/Events/AddMissingIndicesEvent.php b/lib/public/DB/Events/AddMissingIndicesEvent.php index 139b776b136..58ba6b34a59 100644 --- a/lib/public/DB/Events/AddMissingIndicesEvent.php +++ b/lib/public/DB/Events/AddMissingIndicesEvent.php @@ -2,9 +2,9 @@ declare(strict_types=1); /** - * @copyright Copyright (c) 2023 Julius Härtl * - * @author Julius Härtl * * @license GNU AGPL version 3 or any later version * diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index bfc63b2aab0..bee2edad130 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\AddMissingColumnsEvent; use OCP\DB\Events\AddMissingIndicesEvent; use OCP\DB\Exception; use OCP\DB\IPreparedStatement; @@ -67,12 +68,12 @@ interface IDBConnection { public const CHECK_MISSING_PRIMARY_KEYS_EVENT = self::class . '::CHECK_MISSING_PRIMARY_KEYS'; /** - * @deprecated 22.0.0 this is an internal event + * @deprecated 22.0.0 this is an internal event, use {@see AddMissingColumnsEvent} instead */ public const ADD_MISSING_COLUMNS_EVENT = self::class . '::ADD_MISSING_COLUMNS'; /** - * @deprecated 22.0.0 this is an internal event + * @deprecated 22.0.0 this is an internal event, use {@see AddMissingColumnsEvent} instead */ public const CHECK_MISSING_COLUMNS_EVENT = self::class . '::CHECK_MISSING_COLUMNS'; From bd0a149a4ffa2a2e398dddb99f4b0d486bfc2cb7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 19 Jul 2023 23:01:13 +0200 Subject: [PATCH 2/7] feat(dispatcher): Add typed event for "db:add-missing-primary-keys" Signed-off-by: Joas Schilling --- .../lib/Controller/CheckSetupController.php | 17 ++++++ core/Command/Db/AddMissingPrimaryKeys.php | 55 ++++++++++++++--- lib/composer/composer/autoload_classmap.php | 1 + lib/composer/composer/autoload_static.php | 1 + .../DB/Events/AddMissingPrimaryKeyEvent.php | 60 +++++++++++++++++++ lib/public/IDBConnection.php | 5 +- 6 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 lib/public/DB/Events/AddMissingPrimaryKeyEvent.php diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php index 170c6a3870a..5d7989f0256 100644 --- a/apps/settings/lib/Controller/CheckSetupController.php +++ b/apps/settings/lib/Controller/CheckSetupController.php @@ -76,6 +76,7 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\RedirectResponse; use OCP\DB\Events\AddMissingColumnsEvent; use OCP\DB\Events\AddMissingIndicesEvent; +use OCP\DB\Events\AddMissingPrimaryKeyEvent; use OCP\DB\Types; use OCP\EventDispatcher\IEventDispatcher; use OCP\Http\Client\IClientService; @@ -580,6 +581,22 @@ Raw output $event = new GenericEvent($info); $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_PRIMARY_KEYS_EVENT, $event); + $event = new AddMissingPrimaryKeyEvent(); + $this->eventDispatcher->dispatchTyped($event); + $missingKeys = $event->getMissingPrimaryKeys(); + + if (!empty($missingKeys)) { + $schema = new SchemaWrapper(\OCP\Server::get(Connection::class)); + foreach ($missingKeys as $missingKey) { + if ($schema->hasTable($missingKey['tableName'])) { + $table = $schema->getTable($missingKey['tableName']); + if (!$table->hasPrimaryKey()) { + $info->addHintForMissingSubject($missingKey['tableName']); + } + } + } + } + return $info->getListOfMissingPrimaryKeys(); } diff --git a/core/Command/Db/AddMissingPrimaryKeys.php b/core/Command/Db/AddMissingPrimaryKeys.php index a11be78ccfc..6ace85d785b 100644 --- a/core/Command/Db/AddMissingPrimaryKeys.php +++ b/core/Command/Db/AddMissingPrimaryKeys.php @@ -28,6 +28,9 @@ namespace OC\Core\Command\Db; use OC\DB\Connection; use OC\DB\SchemaWrapper; +use OCP\DB\Events\AddMissingColumnsEvent; +use OCP\DB\Events\AddMissingPrimaryKeyEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; @@ -35,6 +38,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\GenericEvent; +use function Symfony\Component\Translation\t; /** * Class AddMissingPrimaryKeys @@ -47,7 +51,8 @@ use Symfony\Component\EventDispatcher\GenericEvent; class AddMissingPrimaryKeys extends Command { public function __construct( private Connection $connection, - private EventDispatcherInterface $dispatcher, + private EventDispatcherInterface $legacyDispatcher, + private IEventDispatcher $dispatcher, ) { parent::__construct(); } @@ -60,11 +65,48 @@ class AddMissingPrimaryKeys extends Command { } protected function execute(InputInterface $input, OutputInterface $output): int { - $this->addCorePrimaryKeys($output, $input->getOption('dry-run')); + $dryRun = $input->getOption('dry-run'); + + $updated = $this->addCorePrimaryKeys($output, $dryRun); // Dispatch event so apps can also update indexes if needed $event = new GenericEvent($output); - $this->dispatcher->dispatch(IDBConnection::ADD_MISSING_PRIMARY_KEYS_EVENT, $event); + $this->legacyDispatcher->dispatch(IDBConnection::ADD_MISSING_PRIMARY_KEYS_EVENT, $event); + + $event = new AddMissingPrimaryKeyEvent(); + $this->dispatcher->dispatchTyped($event); + $missingKeys = $event->getMissingPrimaryKeys(); + + if (!empty($missingKeys)) { + $schema = new SchemaWrapper($this->connection); + + foreach ($missingKeys as $missingKey) { + if ($schema->hasTable($missingKey['tableName'])) { + $table = $schema->getTable($missingKey['tableName']); + if (!$table->hasPrimaryKey()) { + $output->writeln('Adding primary key to the ' . $missingKey['tableName'] . ' table, this can take some time...'); + $table->setPrimaryKey($missingKey['columns'], $missingKey['primaryKeyName']); + + if ($missingKey['formerIndex'] && $table->hasIndex($missingKey['formerIndex'])) { + $table->dropIndex($missingKey['formerIndex']); + } + + $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); + if ($dryRun && $sqlQueries !== null) { + $output->writeln($sqlQueries); + } + + $updated = true; + $output->writeln('' . $missingKey['tableName'] . ' table updated successfully.'); + } + } + } + } + + if (!$updated) { + $output->writeln('Done.'); + } + return 0; } @@ -73,9 +115,10 @@ class AddMissingPrimaryKeys extends Command { * * @param OutputInterface $output * @param bool $dryRun If true, will return the sql queries instead of running them. + * @return bool True when the schema changed * @throws \Doctrine\DBAL\Schema\SchemaException */ - private function addCorePrimaryKeys(OutputInterface $output, bool $dryRun): void { + private function addCorePrimaryKeys(OutputInterface $output, bool $dryRun): bool { $output->writeln('Check primary keys.'); $schema = new SchemaWrapper($this->connection); @@ -183,8 +226,6 @@ class AddMissingPrimaryKeys extends Command { } } - if (!$updated) { - $output->writeln('Done.'); - } + return $updated; } } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 5b89d45cdfb..89ae83e83e4 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -212,6 +212,7 @@ return array( 'OCP\\Contacts\\IManager' => $baseDir . '/lib/public/Contacts/IManager.php', 'OCP\\DB\\Events\\AddMissingColumnsEvent' => $baseDir . '/lib/public/DB/Events/AddMissingColumnsEvent.php', 'OCP\\DB\\Events\\AddMissingIndicesEvent' => $baseDir . '/lib/public/DB/Events/AddMissingIndicesEvent.php', + 'OCP\\DB\\Events\\AddMissingPrimaryKeyEvent' => $baseDir . '/lib/public/DB/Events/AddMissingPrimaryKeyEvent.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 2b71939fa6f..0480448a1b8 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -245,6 +245,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Contacts\\IManager' => __DIR__ . '/../../..' . '/lib/public/Contacts/IManager.php', 'OCP\\DB\\Events\\AddMissingColumnsEvent' => __DIR__ . '/../../..' . '/lib/public/DB/Events/AddMissingColumnsEvent.php', 'OCP\\DB\\Events\\AddMissingIndicesEvent' => __DIR__ . '/../../..' . '/lib/public/DB/Events/AddMissingIndicesEvent.php', + 'OCP\\DB\\Events\\AddMissingPrimaryKeyEvent' => __DIR__ . '/../../..' . '/lib/public/DB/Events/AddMissingPrimaryKeyEvent.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/AddMissingPrimaryKeyEvent.php b/lib/public/DB/Events/AddMissingPrimaryKeyEvent.php new file mode 100644 index 00000000000..ace55d7538b --- /dev/null +++ b/lib/public/DB/Events/AddMissingPrimaryKeyEvent.php @@ -0,0 +1,60 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCP\DB\Events; + +/** + * Event to allow apps to register information about missing database primary keys + * + * This event will be dispatched for checking on the admin settings and when running + * occ db:add-missing-primary-keys which will then create those keys + * + * @since 28.0.0 + */ +class AddMissingPrimaryKeyEvent extends \OCP\EventDispatcher\Event { + /** @var array */ + private array $missingPrimaryKeys = []; + + /** + * @param string[] $columns + * @since 28.0.0 + */ + public function addMissingPrimaryKey(string $tableName, string $primaryKeyName, array $columns, ?string $formerIndex = null): void { + $this->missingPrimaryKeys[] = [ + 'tableName' => $tableName, + 'primaryKeyName' => $primaryKeyName, + 'columns' => $columns, + 'formerIndex' => $formerIndex, + ]; + } + + /** + * @since 28.0.0 + * @return array + */ + public function getMissingPrimaryKeys(): array { + return $this->missingPrimaryKeys; + } +} diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index bee2edad130..7ce2537cb65 100644 --- a/lib/public/IDBConnection.php +++ b/lib/public/IDBConnection.php @@ -36,6 +36,7 @@ namespace OCP; use Doctrine\DBAL\Schema\Schema; use OCP\DB\Events\AddMissingColumnsEvent; use OCP\DB\Events\AddMissingIndicesEvent; +use OCP\DB\Events\AddMissingPrimaryKeyEvent; use OCP\DB\Exception; use OCP\DB\IPreparedStatement; use OCP\DB\IResult; @@ -58,12 +59,12 @@ interface IDBConnection { public const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES'; /** - * @deprecated 22.0.0 this is an internal event + * @deprecated 22.0.0 this is an internal event, use {@see AddMissingPrimaryKeyEvent} instead */ public const ADD_MISSING_PRIMARY_KEYS_EVENT = self::class . '::ADD_MISSING_PRIMARY_KEYS'; /** - * @deprecated 22.0.0 this is an internal event + * @deprecated 22.0.0 this is an internal event, use {@see AddMissingPrimaryKeyEvent} instead */ public const CHECK_MISSING_PRIMARY_KEYS_EVENT = self::class . '::CHECK_MISSING_PRIMARY_KEYS'; From 77c2b169a5da0d7cbb8269f8b240fa47edff90b7 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 19 Jul 2023 23:10:13 +0200 Subject: [PATCH 3/7] fix(db): Move missing core primary keys to typed event Signed-off-by: Joas Schilling --- core/Application.php | 100 ++++++++---------- core/Command/Db/AddMissingPrimaryKeys.php | 122 +--------------------- core/register_command.php | 2 +- 3 files changed, 46 insertions(+), 178 deletions(-) diff --git a/core/Application.php b/core/Application.php index 592e0929666..d6f0f959964 100644 --- a/core/Application.php +++ b/core/Application.php @@ -54,6 +54,7 @@ use OC\Metadata\FileEventListener; use OC\TagManager; use OCP\AppFramework\App; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; +use OCP\DB\Events\AddMissingPrimaryKeyEvent; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Events\Node\NodeDeletedEvent; use OCP\Files\Events\Node\NodeWrittenEvent; @@ -253,62 +254,49 @@ class Application extends App { } ); - $oldEventDispatcher->addListener(IDBConnection::CHECK_MISSING_PRIMARY_KEYS_EVENT, - function (GenericEvent $event) use ($container) { - /** @var MissingPrimaryKeyInformation $subject */ - $subject = $event->getSubject(); - - $schema = new SchemaWrapper($container->query(Connection::class)); - - if ($schema->hasTable('federated_reshares')) { - $table = $schema->getTable('federated_reshares'); - - if (!$table->hasPrimaryKey()) { - $subject->addHintForMissingSubject($table->getName()); - } - } - - if ($schema->hasTable('systemtag_object_mapping')) { - $table = $schema->getTable('systemtag_object_mapping'); - - if (!$table->hasPrimaryKey()) { - $subject->addHintForMissingSubject($table->getName()); - } - } - - if ($schema->hasTable('comments_read_markers')) { - $table = $schema->getTable('comments_read_markers'); - - if (!$table->hasPrimaryKey()) { - $subject->addHintForMissingSubject($table->getName()); - } - } - - if ($schema->hasTable('collres_resources')) { - $table = $schema->getTable('collres_resources'); - - if (!$table->hasPrimaryKey()) { - $subject->addHintForMissingSubject($table->getName()); - } - } - - if ($schema->hasTable('collres_accesscache')) { - $table = $schema->getTable('collres_accesscache'); - - if (!$table->hasPrimaryKey()) { - $subject->addHintForMissingSubject($table->getName()); - } - } - - if ($schema->hasTable('filecache_extended')) { - $table = $schema->getTable('filecache_extended'); - - if (!$table->hasPrimaryKey()) { - $subject->addHintForMissingSubject($table->getName()); - } - } - } - ); + $eventDispatcher->addListener(AddMissingPrimaryKeyEvent::class, function (AddMissingPrimaryKeyEvent $event) { + $event->addMissingPrimaryKey( + 'federated_reshares', + 'federated_res_pk', + ['share_id'], + 'share_id_index' + ); + + $event->addMissingPrimaryKey( + 'systemtag_object_mapping', + 'som_pk', + ['objecttype', 'objectid', 'systemtagid'], + 'mapping' + ); + + $event->addMissingPrimaryKey( + 'comments_read_markers', + 'crm_pk', + ['user_id', 'object_type', 'object_id'], + 'comments_marker_index' + ); + + $event->addMissingPrimaryKey( + 'collres_resources', + 'crr_pk', + ['collection_id', 'resource_type', 'resource_id'], + 'collres_unique_res' + ); + + $event->addMissingPrimaryKey( + 'collres_accesscache', + 'cra_pk', + ['user_id', 'collection_id', 'resource_type', 'resource_id'], + 'collres_unique_user' + ); + + $event->addMissingPrimaryKey( + 'filecache_extended', + 'fce_pk', + ['fileid'], + 'fce_fileid_idx' + ); + }); $oldEventDispatcher->addListener(IDBConnection::CHECK_MISSING_COLUMNS_EVENT, function (GenericEvent $event) use ($container) { diff --git a/core/Command/Db/AddMissingPrimaryKeys.php b/core/Command/Db/AddMissingPrimaryKeys.php index 6ace85d785b..b7435144933 100644 --- a/core/Command/Db/AddMissingPrimaryKeys.php +++ b/core/Command/Db/AddMissingPrimaryKeys.php @@ -67,8 +67,6 @@ class AddMissingPrimaryKeys extends Command { protected function execute(InputInterface $input, OutputInterface $output): int { $dryRun = $input->getOption('dry-run'); - $updated = $this->addCorePrimaryKeys($output, $dryRun); - // Dispatch event so apps can also update indexes if needed $event = new GenericEvent($output); $this->legacyDispatcher->dispatch(IDBConnection::ADD_MISSING_PRIMARY_KEYS_EVENT, $event); @@ -76,6 +74,7 @@ class AddMissingPrimaryKeys extends Command { $event = new AddMissingPrimaryKeyEvent(); $this->dispatcher->dispatchTyped($event); $missingKeys = $event->getMissingPrimaryKeys(); + $updated = false; if (!empty($missingKeys)) { $schema = new SchemaWrapper($this->connection); @@ -109,123 +108,4 @@ class AddMissingPrimaryKeys extends Command { return 0; } - - /** - * add missing indices to the share table - * - * @param OutputInterface $output - * @param bool $dryRun If true, will return the sql queries instead of running them. - * @return bool True when the schema changed - * @throws \Doctrine\DBAL\Schema\SchemaException - */ - private function addCorePrimaryKeys(OutputInterface $output, bool $dryRun): bool { - $output->writeln('Check primary keys.'); - - $schema = new SchemaWrapper($this->connection); - $updated = false; - - if ($schema->hasTable('federated_reshares')) { - $table = $schema->getTable('federated_reshares'); - if (!$table->hasPrimaryKey()) { - $output->writeln('Adding primary key to the federated_reshares table, this can take some time...'); - $table->setPrimaryKey(['share_id'], 'federated_res_pk'); - if ($table->hasIndex('share_id_index')) { - $table->dropIndex('share_id_index'); - } - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('federated_reshares table updated successfully.'); - } - } - - if ($schema->hasTable('systemtag_object_mapping')) { - $table = $schema->getTable('systemtag_object_mapping'); - if (!$table->hasPrimaryKey()) { - $output->writeln('Adding primary key to the systemtag_object_mapping table, this can take some time...'); - $table->setPrimaryKey(['objecttype', 'objectid', 'systemtagid'], 'som_pk'); - if ($table->hasIndex('mapping')) { - $table->dropIndex('mapping'); - } - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('systemtag_object_mapping table updated successfully.'); - } - } - - if ($schema->hasTable('comments_read_markers')) { - $table = $schema->getTable('comments_read_markers'); - if (!$table->hasPrimaryKey()) { - $output->writeln('Adding primary key to the comments_read_markers table, this can take some time...'); - $table->setPrimaryKey(['user_id', 'object_type', 'object_id'], 'crm_pk'); - if ($table->hasIndex('comments_marker_index')) { - $table->dropIndex('comments_marker_index'); - } - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('comments_read_markers table updated successfully.'); - } - } - - if ($schema->hasTable('collres_resources')) { - $table = $schema->getTable('collres_resources'); - if (!$table->hasPrimaryKey()) { - $output->writeln('Adding primary key to the collres_resources table, this can take some time...'); - $table->setPrimaryKey(['collection_id', 'resource_type', 'resource_id'], 'crr_pk'); - if ($table->hasIndex('collres_unique_res')) { - $table->dropIndex('collres_unique_res'); - } - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('collres_resources table updated successfully.'); - } - } - - if ($schema->hasTable('collres_accesscache')) { - $table = $schema->getTable('collres_accesscache'); - if (!$table->hasPrimaryKey()) { - $output->writeln('Adding primary key to the collres_accesscache table, this can take some time...'); - $table->setPrimaryKey(['user_id', 'collection_id', 'resource_type', 'resource_id'], 'cra_pk'); - if ($table->hasIndex('collres_unique_user')) { - $table->dropIndex('collres_unique_user'); - } - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('collres_accesscache table updated successfully.'); - } - } - - if ($schema->hasTable('filecache_extended')) { - $table = $schema->getTable('filecache_extended'); - if (!$table->hasPrimaryKey()) { - $output->writeln('Adding primary key to the filecache_extended table, this can take some time...'); - $table->setPrimaryKey(['fileid'], 'fce_pk'); - if ($table->hasIndex('fce_fileid_idx')) { - $table->dropIndex('fce_fileid_idx'); - } - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('filecache_extended table updated successfully.'); - } - } - - return $updated; - } } diff --git a/core/register_command.php b/core/register_command.php index 32cd4099618..8d57641db9c 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -110,8 +110,8 @@ if (\OC::$server->getConfig()->getSystemValue('installed', false)) { $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(\OCP\Server::get(\OC\Core\Command\Db\AddMissingIndices::class)); + $application->add(\OCP\Server::get(\OC\Core\Command\Db\AddMissingPrimaryKeys::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())); if (\OC::$server->getConfig()->getSystemValueBool('debug', false)) { $application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->get(\OC\DB\Connection::class))); From f73f14207c6c0792396a2cab92ff33b806500867 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 19 Jul 2023 23:14:43 +0200 Subject: [PATCH 4/7] fix(db): Move missing core columns to typed event Signed-off-by: Joas Schilling --- core/Application.php | 29 ++++++++++----------- core/Command/Db/AddMissingColumns.php | 37 +-------------------------- core/register_command.php | 2 +- 3 files changed, 15 insertions(+), 53 deletions(-) diff --git a/core/Application.php b/core/Application.php index d6f0f959964..b29d8cce022 100644 --- a/core/Application.php +++ b/core/Application.php @@ -54,7 +54,9 @@ use OC\Metadata\FileEventListener; use OC\TagManager; use OCP\AppFramework\App; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; +use OCP\DB\Events\AddMissingColumnsEvent; use OCP\DB\Events\AddMissingPrimaryKeyEvent; +use OCP\DB\Types; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Events\Node\NodeDeletedEvent; use OCP\Files\Events\Node\NodeWrittenEvent; @@ -298,22 +300,17 @@ class Application extends App { ); }); - $oldEventDispatcher->addListener(IDBConnection::CHECK_MISSING_COLUMNS_EVENT, - function (GenericEvent $event) use ($container) { - /** @var MissingColumnInformation $subject */ - $subject = $event->getSubject(); - - $schema = new SchemaWrapper($container->query(Connection::class)); - - if ($schema->hasTable('comments')) { - $table = $schema->getTable('comments'); - - if (!$table->hasColumn('reference_id')) { - $subject->addHintForMissingColumn($table->getName(), 'reference_id'); - } - } - } - ); + $eventDispatcher->addListener(AddMissingColumnsEvent::class, function (AddMissingColumnsEvent $event) { + $event->addMissingColumn( + 'comments', + 'reference_id', + Types::STRING, + [ + 'notnull' => false, + 'length' => 64, + ] + ); + }); $eventDispatcher->addServiceListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); $eventDispatcher->addServiceListener(RemoteWipeStarted::class, RemoteWipeActivityListener::class); diff --git a/core/Command/Db/AddMissingColumns.php b/core/Command/Db/AddMissingColumns.php index 93e346e498c..46642f7d0d4 100644 --- a/core/Command/Db/AddMissingColumns.php +++ b/core/Command/Db/AddMissingColumns.php @@ -66,8 +66,6 @@ class AddMissingColumns extends Command { protected function execute(InputInterface $input, OutputInterface $output): int { $dryRun = $input->getOption('dry-run'); - $updated = $this->addCoreColumns($output, $dryRun); - // Dispatch event so apps can also update columns if needed $event = new GenericEvent($output); $this->legacyDispatcher->dispatch(IDBConnection::ADD_MISSING_COLUMNS_EVENT, $event); @@ -75,6 +73,7 @@ class AddMissingColumns extends Command { $event = new AddMissingColumnsEvent(); $this->dispatcher->dispatchTyped($event); $missingColumns = $event->getMissingColumns(); + $updated = false; if (!empty($missingColumns)) { $schema = new SchemaWrapper($this->connection); @@ -102,38 +101,4 @@ class AddMissingColumns extends Command { return 0; } - - /** - * Add missing column for core tables - * - * @param OutputInterface $output - * @param bool $dryRun If true, will return the sql queries instead of running them. - * @return bool True when the schema changed - * @throws \Doctrine\DBAL\Schema\SchemaException - */ - private function addCoreColumns(OutputInterface $output, bool $dryRun): bool { - $output->writeln('Check columns of the comments table.'); - - $schema = new SchemaWrapper($this->connection); - $updated = false; - - if ($schema->hasTable('comments')) { - $table = $schema->getTable('comments'); - if (!$table->hasColumn('reference_id')) { - $output->writeln('Adding additional reference_id column to the comments table, this can take some time...'); - $table->addColumn('reference_id', Types::STRING, [ - 'notnull' => false, - 'length' => 64, - ]); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Comments table updated successfully.'); - } - } - - return $updated; - } } diff --git a/core/register_command.php b/core/register_command.php index 8d57641db9c..df39ad4484c 100644 --- a/core/register_command.php +++ b/core/register_command.php @@ -109,9 +109,9 @@ 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(\OCP\Server::get(\OC\Core\Command\Db\AddMissingColumns::class)); $application->add(\OCP\Server::get(\OC\Core\Command\Db\AddMissingIndices::class)); $application->add(\OCP\Server::get(\OC\Core\Command\Db\AddMissingPrimaryKeys::class)); - $application->add(new OC\Core\Command\Db\AddMissingColumns(\OC::$server->get(\OC\DB\Connection::class), \OC::$server->getEventDispatcher())); if (\OC::$server->getConfig()->getSystemValueBool('debug', false)) { $application->add(new OC\Core\Command\Db\Migrations\StatusCommand(\OC::$server->get(\OC\DB\Connection::class))); From 00d483585bf7bdfced0c78f35603266c628d683a Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 19 Jul 2023 23:19:35 +0200 Subject: [PATCH 5/7] fix: Add options to support all used features by core Signed-off-by: Joas Schilling --- core/Command/Db/AddMissingIndices.php | 18 ++++++++++++- .../DB/Events/AddMissingIndicesEvent.php | 27 ++++++++++++++++--- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php index dee9796a569..6c22557e3ff 100644 --- a/core/Command/Db/AddMissingIndices.php +++ b/core/Command/Db/AddMissingIndices.php @@ -91,7 +91,23 @@ class AddMissingIndices extends Command { $table = $schema->getTable($missingIndex['tableName']); if (!$table->hasIndex($missingIndex['indexName'])) { $output->writeln('Adding additional ' . $missingIndex['indexName'] . ' index to the ' . $table->getName() . ' table, this can take some time...'); - $table->addIndex($missingIndex['columns'], $missingIndex['indexName']); + + if ($missingIndex['dropUnnamedIndex']) { + foreach ($table->getIndexes() as $index) { + $columns = $index->getColumns(); + if ($columns === $missingIndex['columns']) { + $table->dropIndex($index->getName()); + } + } + } + + if ($missingIndex['uniqueIndex']) { + $table->addUniqueIndex($missingIndex['columns'], $missingIndex['indexName'], $missingIndex['options']); + } else { + $table->addIndex($missingIndex['columns'], $missingIndex['indexName'], [], $missingIndex['options']); + } + + $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); if ($dryRun && $sqlQueries !== null) { $output->writeln($sqlQueries); diff --git a/lib/public/DB/Events/AddMissingIndicesEvent.php b/lib/public/DB/Events/AddMissingIndicesEvent.php index 58ba6b34a59..dc942f3d63e 100644 --- a/lib/public/DB/Events/AddMissingIndicesEvent.php +++ b/lib/public/DB/Events/AddMissingIndicesEvent.php @@ -2,8 +2,10 @@ declare(strict_types=1); /** + * @copyright Copyright (c) 2023 Joas Schilling * @copyright Copyright (c) 2023 Julius Härtl * + * @author Joas Schilling * @author Julius Härtl * * @license GNU AGPL version 3 or any later version @@ -34,24 +36,41 @@ namespace OCP\DB\Events; * @since 28.0.0 */ class AddMissingIndicesEvent extends \OCP\EventDispatcher\Event { - /** @var array */ + /** @var array */ private array $missingIndices = []; /** * @param string[] $columns * @since 28.0.0 */ - public function addMissingIndex(string $tableName, string $indexName, array $columns): void { + public function addMissingIndex(string $tableName, string $indexName, array $columns, array $options = [], bool $dropUnnamedIndex = false): void { $this->missingIndices[] = [ 'tableName' => $tableName, 'indexName' => $indexName, - 'columns' => $columns + 'columns' => $columns, + 'options' => $options, + 'dropUnnamedIndex' => $dropUnnamedIndex, + 'uniqueIndex' => false, + ]; + } + /** + * @param string[] $columns + * @since 28.0.0 + */ + public function addMissingUniqueIndex(string $tableName, string $indexName, array $columns, array $options = [], bool $dropUnnamedIndex = false): void { + $this->missingIndices[] = [ + 'tableName' => $tableName, + 'indexName' => $indexName, + 'columns' => $columns, + 'options' => $options, + 'dropUnnamedIndex' => $dropUnnamedIndex, + 'uniqueIndex' => true, ]; } /** * @since 28.0.0 - * @return array + * @return array */ public function getMissingIndices(): array { return $this->missingIndices; From 86310a35b25d22ff81aa6ca4ee0c52c769e3d359 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 19 Jul 2023 23:48:11 +0200 Subject: [PATCH 6/7] fix(db): Move missing core indices to typed event Signed-off-by: Joas Schilling --- core/Application.php | 348 ++++++++++----------- core/Command/Db/AddMissingIndices.php | 416 -------------------------- 2 files changed, 176 insertions(+), 588 deletions(-) diff --git a/core/Application.php b/core/Application.php index b29d8cce022..307d839f07c 100644 --- a/core/Application.php +++ b/core/Application.php @@ -32,7 +32,6 @@ */ namespace OC\Core; -use Doctrine\DBAL\Platforms\PostgreSQL94Platform; use OC\Authentication\Events\RemoteWipeFinished; use OC\Authentication\Events\RemoteWipeStarted; use OC\Authentication\Listeners\RemoteWipeActivityListener; @@ -45,28 +44,22 @@ use OC\Authentication\Listeners\UserDeletedWebAuthnCleanupListener; use OC\Authentication\Notifications\Notifier as AuthenticationNotifier; use OC\Core\Listener\BeforeTemplateRenderedListener; use OC\Core\Notification\CoreNotifier; -use OC\DB\Connection; -use OC\DB\MissingColumnInformation; -use OC\DB\MissingIndexInformation; -use OC\DB\MissingPrimaryKeyInformation; -use OC\DB\SchemaWrapper; use OC\Metadata\FileEventListener; use OC\TagManager; use OCP\AppFramework\App; use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent; use OCP\DB\Events\AddMissingColumnsEvent; +use OCP\DB\Events\AddMissingIndicesEvent; use OCP\DB\Events\AddMissingPrimaryKeyEvent; use OCP\DB\Types; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Events\Node\NodeDeletedEvent; use OCP\Files\Events\Node\NodeWrittenEvent; use OCP\Files\Events\NodeRemovedFromCache; -use OCP\IDBConnection; use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\UserDeletedEvent; use OCP\Util; use OCP\IConfig; -use Symfony\Component\EventDispatcher\GenericEvent; /** * Class Application @@ -91,170 +84,181 @@ class Application extends App { $notificationManager->registerNotifierService(CoreNotifier::class); $notificationManager->registerNotifierService(AuthenticationNotifier::class); - $oldEventDispatcher = $server->getEventDispatcher(); - - $oldEventDispatcher->addListener(IDBConnection::CHECK_MISSING_INDEXES_EVENT, - function (GenericEvent $event) use ($container) { - /** @var MissingIndexInformation $subject */ - $subject = $event->getSubject(); - - $schema = new SchemaWrapper($container->query(Connection::class)); - - if ($schema->hasTable('share')) { - $table = $schema->getTable('share'); - - if (!$table->hasIndex('share_with_index')) { - $subject->addHintForMissingSubject($table->getName(), 'share_with_index'); - } - if (!$table->hasIndex('parent_index')) { - $subject->addHintForMissingSubject($table->getName(), 'parent_index'); - } - if (!$table->hasIndex('owner_index')) { - $subject->addHintForMissingSubject($table->getName(), 'owner_index'); - } - if (!$table->hasIndex('initiator_index')) { - $subject->addHintForMissingSubject($table->getName(), 'initiator_index'); - } - } - - if ($schema->hasTable('filecache')) { - $table = $schema->getTable('filecache'); - - if (!$table->hasIndex('fs_mtime')) { - $subject->addHintForMissingSubject($table->getName(), 'fs_mtime'); - } - - if (!$table->hasIndex('fs_size')) { - $subject->addHintForMissingSubject($table->getName(), 'fs_size'); - } - - if (!$table->hasIndex('fs_id_storage_size')) { - $subject->addHintForMissingSubject($table->getName(), 'fs_id_storage_size'); - } - - if (!$table->hasIndex('fs_storage_path_prefix') && !$schema->getDatabasePlatform() instanceof PostgreSQL94Platform) { - $subject->addHintForMissingSubject($table->getName(), 'fs_storage_path_prefix'); - } - - if (!$table->hasIndex('fs_parent')) { - $subject->addHintForMissingSubject($table->getName(), 'fs_parent'); - } - } - - if ($schema->hasTable('twofactor_providers')) { - $table = $schema->getTable('twofactor_providers'); - - if (!$table->hasIndex('twofactor_providers_uid')) { - $subject->addHintForMissingSubject($table->getName(), 'twofactor_providers_uid'); - } - } - - if ($schema->hasTable('login_flow_v2')) { - $table = $schema->getTable('login_flow_v2'); - - if (!$table->hasIndex('poll_token')) { - $subject->addHintForMissingSubject($table->getName(), 'poll_token'); - } - if (!$table->hasIndex('login_token')) { - $subject->addHintForMissingSubject($table->getName(), 'login_token'); - } - if (!$table->hasIndex('timestamp')) { - $subject->addHintForMissingSubject($table->getName(), 'timestamp'); - } - } - - if ($schema->hasTable('whats_new')) { - $table = $schema->getTable('whats_new'); - - if (!$table->hasIndex('version')) { - $subject->addHintForMissingSubject($table->getName(), 'version'); - } - } - - if ($schema->hasTable('cards')) { - $table = $schema->getTable('cards'); - - if (!$table->hasIndex('cards_abid')) { - $subject->addHintForMissingSubject($table->getName(), 'cards_abid'); - } - - if (!$table->hasIndex('cards_abiduri')) { - $subject->addHintForMissingSubject($table->getName(), 'cards_abiduri'); - } - } - - if ($schema->hasTable('cards_properties')) { - $table = $schema->getTable('cards_properties'); - - if (!$table->hasIndex('cards_prop_abid')) { - $subject->addHintForMissingSubject($table->getName(), 'cards_prop_abid'); - } - } - - if ($schema->hasTable('calendarobjects_props')) { - $table = $schema->getTable('calendarobjects_props'); - - if (!$table->hasIndex('calendarobject_calid_index')) { - $subject->addHintForMissingSubject($table->getName(), 'calendarobject_calid_index'); - } - } - - if ($schema->hasTable('schedulingobjects')) { - $table = $schema->getTable('schedulingobjects'); - if (!$table->hasIndex('schedulobj_principuri_index')) { - $subject->addHintForMissingSubject($table->getName(), 'schedulobj_principuri_index'); - } - } - - if ($schema->hasTable('properties')) { - $table = $schema->getTable('properties'); - if (!$table->hasIndex('properties_path_index')) { - $subject->addHintForMissingSubject($table->getName(), 'properties_path_index'); - } - if (!$table->hasIndex('properties_pathonly_index')) { - $subject->addHintForMissingSubject($table->getName(), 'properties_pathonly_index'); - } - } - - if ($schema->hasTable('jobs')) { - $table = $schema->getTable('jobs'); - if (!$table->hasIndex('job_lastcheck_reserved')) { - $subject->addHintForMissingSubject($table->getName(), 'job_lastcheck_reserved'); - } - } - - if ($schema->hasTable('direct_edit')) { - $table = $schema->getTable('direct_edit'); - if (!$table->hasIndex('direct_edit_timestamp')) { - $subject->addHintForMissingSubject($table->getName(), 'direct_edit_timestamp'); - } - } - - if ($schema->hasTable('preferences')) { - $table = $schema->getTable('preferences'); - if (!$table->hasIndex('preferences_app_key')) { - $subject->addHintForMissingSubject($table->getName(), 'preferences_app_key'); - } - } - - if ($schema->hasTable('mounts')) { - $table = $schema->getTable('mounts'); - if (!$table->hasIndex('mounts_class_index')) { - $subject->addHintForMissingSubject($table->getName(), 'mounts_class_index'); - } - if (!$table->hasIndex('mounts_user_root_path_index')) { - $subject->addHintForMissingSubject($table->getName(), 'mounts_user_root_path_index'); - } - } - - if ($schema->hasTable('systemtag_object_mapping')) { - $table = $schema->getTable('systemtag_object_mapping'); - if (!$table->hasIndex('systag_by_tagid')) { - $subject->addHintForMissingSubject($table->getName(), 'systag_by_tagid'); - } - } - } - ); + $eventDispatcher->addListener(AddMissingIndicesEvent::class, function (AddMissingIndicesEvent $event) { + $event->addMissingIndex( + 'share', + 'share_with_index', + ['share_with'] + ); + $event->addMissingIndex( + 'share', + 'parent_index', + ['parent'] + ); + $event->addMissingIndex( + 'share', + 'owner_index', + ['uid_owner'] + ); + $event->addMissingIndex( + 'share', + 'initiator_index', + ['uid_initiator'] + ); + + $event->addMissingIndex( + 'filecache', + 'fs_mtime', + ['mtime'] + ); + $event->addMissingIndex( + 'filecache', + 'fs_size', + ['size'] + ); + $event->addMissingIndex( + 'filecache', + 'fs_id_storage_size', + ['fileid', 'storage', 'size'] + ); + $event->addMissingIndex( + 'filecache', + 'fs_storage_path_prefix', + ['storage', 'path'], + ['lengths' => [null, 64]] + ); + $event->addMissingIndex( + 'filecache', + 'fs_parent', + ['parent'] + ); + + $event->addMissingIndex( + 'twofactor_providers', + 'twofactor_providers_uid', + ['uid'] + ); + + $event->addMissingUniqueIndex( + 'login_flow_v2', + 'poll_token', + ['poll_token'], + [], + true + ); + $event->addMissingUniqueIndex( + 'login_flow_v2', + 'login_token', + ['login_token'], + [], + true + ); + $event->addMissingIndex( + 'login_flow_v2', + 'timestamp', + ['timestamp'], + [], + true + ); + + $event->addMissingIndex( + 'whats_new', + 'version', + ['version'], + [], + true + ); + + $event->addMissingIndex( + 'cards', + 'cards_abiduri', + ['addressbookid', 'uri'], + [], + true + ); + $event->addMissingIndex( + 'cards', + 'cards_abid', + ['addressbookid'], + [], + true + ); + $event->addMissingIndex( + 'cards', + 'cards_abiduri', + ['addressbookid', 'uri'], + [], + true + ); + + $event->addMissingIndex( + 'cards_properties', + 'cards_prop_abid', + ['addressbookid'], + [], + true + ); + + $event->addMissingIndex( + 'calendarobjects_props', + 'calendarobject_calid_index', + ['calendarid', 'calendartype'] + ); + + $event->addMissingIndex( + 'schedulingobjects', + 'schedulobj_principuri_index', + ['principaluri'] + ); + + $event->addMissingIndex( + 'properties', + 'properties_path_index', + ['userid', 'propertypath'] + ); + $event->addMissingIndex( + 'properties', + 'properties_pathonly_index', + ['propertypath'] + ); + + + $event->addMissingIndex( + 'jobs', + 'job_lastcheck_reserved', + ['last_checked', 'reserved_at'] + ); + + $event->addMissingIndex( + 'direct_edit', + 'direct_edit_timestamp', + ['timestamp'] + ); + + $event->addMissingIndex( + 'preferences', + 'preferences_app_key', + ['appid', 'configkey'] + ); + + $event->addMissingIndex( + 'mounts', + 'mounts_class_index', + ['mount_provider_class'] + ); + $event->addMissingIndex( + 'mounts', + 'mounts_user_root_path_index', + ['user_id', 'root_id', 'mount_point'], + ['lengths' => [null, null, 128]] + ); + + $event->addMissingIndex( + 'systemtag_object_mapping', + 'systag_by_tagid', + ['systemtagid', 'objecttype'] + ); + }); $eventDispatcher->addListener(AddMissingPrimaryKeyEvent::class, function (AddMissingPrimaryKeyEvent $event) { $event->addMissingPrimaryKey( diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php index 6c22557e3ff..f05be314e08 100644 --- a/core/Command/Db/AddMissingIndices.php +++ b/core/Command/Db/AddMissingIndices.php @@ -73,8 +73,6 @@ class AddMissingIndices extends Command { protected function execute(InputInterface $input, OutputInterface $output): int { $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); @@ -120,418 +118,4 @@ class AddMissingIndices extends Command { return 0; } - - /** - * add missing indices to the share table - * - * @param OutputInterface $output - * @param bool $dryRun If true, will return the sql queries instead of running them. - * @throws \Doctrine\DBAL\Schema\SchemaException - */ - private function addCoreIndexes(OutputInterface $output, bool $dryRun): void { - $output->writeln('Check indices of the share table.'); - - $schema = new SchemaWrapper($this->connection); - $updated = false; - - if ($schema->hasTable('share')) { - $table = $schema->getTable('share'); - if (!$table->hasIndex('share_with_index')) { - $output->writeln('Adding additional share_with index to the share table, this can take some time...'); - $table->addIndex(['share_with'], 'share_with_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Share table updated successfully.'); - } - - if (!$table->hasIndex('parent_index')) { - $output->writeln('Adding additional parent index to the share table, this can take some time...'); - $table->addIndex(['parent'], 'parent_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Share table updated successfully.'); - } - - if (!$table->hasIndex('owner_index')) { - $output->writeln('Adding additional owner index to the share table, this can take some time...'); - $table->addIndex(['uid_owner'], 'owner_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Share table updated successfully.'); - } - - if (!$table->hasIndex('initiator_index')) { - $output->writeln('Adding additional initiator index to the share table, this can take some time...'); - $table->addIndex(['uid_initiator'], 'initiator_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Share table updated successfully.'); - } - } - - $output->writeln('Check indices of the filecache table.'); - if ($schema->hasTable('filecache')) { - $table = $schema->getTable('filecache'); - if (!$table->hasIndex('fs_mtime')) { - $output->writeln('Adding additional mtime index to the filecache table, this can take some time...'); - $table->addIndex(['mtime'], 'fs_mtime'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Filecache table updated successfully.'); - } - if (!$table->hasIndex('fs_size')) { - $output->writeln('Adding additional size index to the filecache table, this can take some time...'); - $table->addIndex(['size'], 'fs_size'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Filecache table updated successfully.'); - } - if (!$table->hasIndex('fs_id_storage_size')) { - $output->writeln('Adding additional size index to the filecache table, this can take some time...'); - $table->addIndex(['fileid', 'storage', 'size'], 'fs_id_storage_size'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Filecache table updated successfully.'); - } - if (!$table->hasIndex('fs_storage_path_prefix') && !$schema->getDatabasePlatform() instanceof PostgreSQL94Platform) { - $output->writeln('Adding additional path index to the filecache table, this can take some time...'); - $table->addIndex(['storage', 'path'], 'fs_storage_path_prefix', [], ['lengths' => [null, 64]]); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Filecache table updated successfully.'); - } - if (!$table->hasIndex('fs_parent')) { - $output->writeln('Adding additional parent index to the filecache table, this can take some time...'); - $table->addIndex(['parent'], 'fs_parent'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Filecache table updated successfully.'); - } - } - - $output->writeln('Check indices of the twofactor_providers table.'); - if ($schema->hasTable('twofactor_providers')) { - $table = $schema->getTable('twofactor_providers'); - if (!$table->hasIndex('twofactor_providers_uid')) { - $output->writeln('Adding additional twofactor_providers_uid index to the twofactor_providers table, this can take some time...'); - $table->addIndex(['uid'], 'twofactor_providers_uid'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('Twofactor_providers table updated successfully.'); - } - } - - $output->writeln('Check indices of the login_flow_v2 table.'); - if ($schema->hasTable('login_flow_v2')) { - $table = $schema->getTable('login_flow_v2'); - if (!$table->hasIndex('poll_token')) { - $output->writeln('Adding additional indeces to the login_flow_v2 table, this can take some time...'); - - foreach ($table->getIndexes() as $index) { - $columns = $index->getColumns(); - if ($columns === ['poll_token'] || - $columns === ['login_token'] || - $columns === ['timestamp']) { - $table->dropIndex($index->getName()); - } - } - - $table->addUniqueIndex(['poll_token'], 'poll_token'); - $table->addUniqueIndex(['login_token'], 'login_token'); - $table->addIndex(['timestamp'], 'timestamp'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('login_flow_v2 table updated successfully.'); - } - } - - $output->writeln('Check indices of the whats_new table.'); - if ($schema->hasTable('whats_new')) { - $table = $schema->getTable('whats_new'); - if (!$table->hasIndex('version')) { - $output->writeln('Adding version index to the whats_new table, this can take some time...'); - - foreach ($table->getIndexes() as $index) { - if ($index->getColumns() === ['version']) { - $table->dropIndex($index->getName()); - } - } - - $table->addUniqueIndex(['version'], 'version'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('whats_new table updated successfully.'); - } - } - - $output->writeln('Check indices of the cards table.'); - $cardsUpdated = false; - if ($schema->hasTable('cards')) { - $table = $schema->getTable('cards'); - - if ($table->hasIndex('addressbookid_uri_index')) { - if ($table->hasIndex('cards_abiduri')) { - $table->dropIndex('addressbookid_uri_index'); - } else { - $output->writeln('Renaming addressbookid_uri_index index to cards_abiduri in the cards table, this can take some time...'); - - foreach ($table->getIndexes() as $index) { - if ($index->getColumns() === ['addressbookid', 'uri']) { - $table->renameIndex('addressbookid_uri_index', 'cards_abiduri'); - } - } - } - - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $cardsUpdated = true; - } - - if (!$table->hasIndex('cards_abid')) { - $output->writeln('Adding cards_abid index to the cards table, this can take some time...'); - - foreach ($table->getIndexes() as $index) { - if ($index->getColumns() === ['addressbookid']) { - $table->dropIndex($index->getName()); - } - } - - $table->addIndex(['addressbookid'], 'cards_abid'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $cardsUpdated = true; - } - - if (!$table->hasIndex('cards_abiduri')) { - $output->writeln('Adding cards_abiduri index to the cards table, this can take some time...'); - - foreach ($table->getIndexes() as $index) { - if ($index->getColumns() === ['addressbookid', 'uri']) { - $table->dropIndex($index->getName()); - } - } - - $table->addIndex(['addressbookid', 'uri'], 'cards_abiduri'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $cardsUpdated = true; - } - - if ($cardsUpdated) { - $updated = true; - $output->writeln('cards table updated successfully.'); - } - } - - $output->writeln('Check indices of the cards_properties table.'); - if ($schema->hasTable('cards_properties')) { - $table = $schema->getTable('cards_properties'); - if (!$table->hasIndex('cards_prop_abid')) { - $output->writeln('Adding cards_prop_abid index to the cards_properties table, this can take some time...'); - - foreach ($table->getIndexes() as $index) { - if ($index->getColumns() === ['addressbookid']) { - $table->dropIndex($index->getName()); - } - } - - $table->addIndex(['addressbookid'], 'cards_prop_abid'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('cards_properties table updated successfully.'); - } - } - - $output->writeln('Check indices of the calendarobjects_props table.'); - if ($schema->hasTable('calendarobjects_props')) { - $table = $schema->getTable('calendarobjects_props'); - if (!$table->hasIndex('calendarobject_calid_index')) { - $output->writeln('Adding calendarobject_calid_index index to the calendarobjects_props table, this can take some time...'); - - $table->addIndex(['calendarid', 'calendartype'], 'calendarobject_calid_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('calendarobjects_props table updated successfully.'); - } - } - - $output->writeln('Check indices of the schedulingobjects table.'); - if ($schema->hasTable('schedulingobjects')) { - $table = $schema->getTable('schedulingobjects'); - if (!$table->hasIndex('schedulobj_principuri_index')) { - $output->writeln('Adding schedulobj_principuri_index index to the schedulingobjects table, this can take some time...'); - - $table->addIndex(['principaluri'], 'schedulobj_principuri_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('schedulingobjects table updated successfully.'); - } - } - - $output->writeln('Check indices of the oc_properties table.'); - if ($schema->hasTable('properties')) { - $table = $schema->getTable('properties'); - $propertiesUpdated = false; - - if (!$table->hasIndex('properties_path_index')) { - $output->writeln('Adding properties_path_index index to the oc_properties table, this can take some time...'); - - $table->addIndex(['userid', 'propertypath'], 'properties_path_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $propertiesUpdated = true; - } - if (!$table->hasIndex('properties_pathonly_index')) { - $output->writeln('Adding properties_pathonly_index index to the oc_properties table, this can take some time...'); - - $table->addIndex(['propertypath'], 'properties_pathonly_index'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $propertiesUpdated = true; - } - - if ($propertiesUpdated) { - $updated = true; - $output->writeln('oc_properties table updated successfully.'); - } - } - - $output->writeln('Check indices of the oc_jobs table.'); - if ($schema->hasTable('jobs')) { - $table = $schema->getTable('jobs'); - if (!$table->hasIndex('job_lastcheck_reserved')) { - $output->writeln('Adding job_lastcheck_reserved index to the oc_jobs table, this can take some time...'); - - $table->addIndex(['last_checked', 'reserved_at'], 'job_lastcheck_reserved'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('oc_properties table updated successfully.'); - } - } - - $output->writeln('Check indices of the oc_direct_edit table.'); - if ($schema->hasTable('direct_edit')) { - $table = $schema->getTable('direct_edit'); - if (!$table->hasIndex('direct_edit_timestamp')) { - $output->writeln('Adding direct_edit_timestamp index to the oc_direct_edit table, this can take some time...'); - - $table->addIndex(['timestamp'], 'direct_edit_timestamp'); - $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun); - if ($dryRun && $sqlQueries !== null) { - $output->writeln($sqlQueries); - } - $updated = true; - $output->writeln('oc_direct_edit table updated successfully.'); - } - } - - $output->writeln('Check indices of the oc_preferences table.'); - if ($schema->hasTable('preferences')) { - $table = $schema->getTable('preferences'); - if (!$table->hasIndex('preferences_app_key')) { - $output->writeln('Adding preferences_app_key index to the oc_preferences table, this can take some time...'); - - $table->addIndex(['appid', 'configkey'], 'preferences_app_key'); - $this->connection->migrateToSchema($schema->getWrappedSchema()); - $updated = true; - $output->writeln('oc_properties table updated successfully.'); - } - } - - $output->writeln('Check indices of the oc_mounts table.'); - if ($schema->hasTable('mounts')) { - $table = $schema->getTable('mounts'); - if (!$table->hasIndex('mounts_class_index')) { - $output->writeln('Adding mounts_class_index index to the oc_mounts table, this can take some time...'); - - $table->addIndex(['mount_provider_class'], 'mounts_class_index'); - $this->connection->migrateToSchema($schema->getWrappedSchema()); - $updated = true; - $output->writeln('oc_mounts table updated successfully.'); - } - if (!$table->hasIndex('mounts_user_root_path_index')) { - $output->writeln('Adding mounts_user_root_path_index index to the oc_mounts table, this can take some time...'); - - $table->addIndex(['user_id', 'root_id', 'mount_point'], 'mounts_user_root_path_index', [], ['lengths' => [null, null, 128]]); - $this->connection->migrateToSchema($schema->getWrappedSchema()); - $updated = true; - $output->writeln('oc_mounts table updated successfully.'); - } - } - - $output->writeln('Check indices of the oc_systemtag_object_mapping table.'); - if ($schema->hasTable('systemtag_object_mapping')) { - $table = $schema->getTable('systemtag_object_mapping'); - if (!$table->hasIndex('systag_by_tagid')) { - $output->writeln('Adding systag_by_tagid index to the oc_systemtag_object_mapping table, this can take some time...'); - - $table->addIndex(['systemtagid', 'objecttype'], 'systag_by_tagid'); - $this->connection->migrateToSchema($schema->getWrappedSchema()); - $updated = true; - $output->writeln('oc_systemtag_object_mapping table updated successfully.'); - } - } - - if (!$updated) { - $output->writeln('Done.'); - } - } } From ab70bbd3ffbc3788035588c86984f9508db8edbe Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 20 Jul 2023 00:05:59 +0200 Subject: [PATCH 7/7] fix(db)!: Remove private legacy event because we can not keep it Signed-off-by: Joas Schilling --- .../lib/Controller/CheckSetupController.php | 27 ++++----------- .../Controller/CheckSetupControllerTest.php | 11 +------ core/Command/Db/AddMissingColumns.php | 8 ----- core/Command/Db/AddMissingIndices.php | 12 ++----- core/Command/Db/AddMissingPrimaryKeys.php | 9 ----- lib/public/IDBConnection.php | 33 ------------------- 6 files changed, 9 insertions(+), 91 deletions(-) diff --git a/apps/settings/lib/Controller/CheckSetupController.php b/apps/settings/lib/Controller/CheckSetupController.php index 5d7989f0256..4a1913cedfe 100644 --- a/apps/settings/lib/Controller/CheckSetupController.php +++ b/apps/settings/lib/Controller/CheckSetupController.php @@ -92,8 +92,6 @@ use OCP\Lock\ILockingProvider; use OCP\Notification\IManager; use OCP\Security\ISecureRandom; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\GenericEvent; #[IgnoreOpenAPI] class CheckSetupController extends Controller { @@ -110,8 +108,6 @@ class CheckSetupController extends Controller { /** @var LoggerInterface */ private $logger; /** @var IEventDispatcher */ - private $eventDispatcher; - /** @var EventDispatcherInterface */ private $dispatcher; /** @var Connection */ private $db; @@ -144,8 +140,7 @@ class CheckSetupController extends Controller { IL10N $l10n, Checker $checker, LoggerInterface $logger, - IEventDispatcher $eventDispatcher, - EventDispatcherInterface $dispatcher, + IEventDispatcher $dispatcher, Connection $db, ILockingProvider $lockingProvider, IDateTimeFormatter $dateTimeFormatter, @@ -165,7 +160,6 @@ 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; @@ -553,11 +547,8 @@ Raw output $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); + $this->dispatcher->dispatchTyped($event); $missingIndices = $event->getMissingIndices(); if ($missingIndices !== []) { @@ -577,12 +568,9 @@ Raw output protected function hasMissingPrimaryKeys(): array { $info = new MissingPrimaryKeyInformation(); - // Dispatch event so apps can also hint for pending index updates if needed - $event = new GenericEvent($info); - $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_PRIMARY_KEYS_EVENT, $event); - + // Dispatch event so apps can also hint for pending key updates if needed $event = new AddMissingPrimaryKeyEvent(); - $this->eventDispatcher->dispatchTyped($event); + $this->dispatcher->dispatchTyped($event); $missingKeys = $event->getMissingPrimaryKeys(); if (!empty($missingKeys)) { @@ -602,12 +590,9 @@ Raw output protected function hasMissingColumns(): array { $columnInfo = new MissingColumnInformation(); - // Dispatch event so apps can also hint for pending index updates if needed - $event = new GenericEvent($columnInfo); - $this->dispatcher->dispatch(IDBConnection::CHECK_MISSING_COLUMNS_EVENT, $event); - + // Dispatch event so apps can also hint for pending column updates if needed $event = new AddMissingColumnsEvent(); - $this->eventDispatcher->dispatchTyped($event); + $this->dispatcher->dispatchTyped($event); $missingColumns = $event->getMissingColumns(); if (!empty($missingColumns)) { diff --git a/apps/settings/tests/Controller/CheckSetupControllerTest.php b/apps/settings/tests/Controller/CheckSetupControllerTest.php index 3fc4f930321..564c1cbb62d 100644 --- a/apps/settings/tests/Controller/CheckSetupControllerTest.php +++ b/apps/settings/tests/Controller/CheckSetupControllerTest.php @@ -62,7 +62,6 @@ use OCP\Notification\IManager; use PHPUnit\Framework\MockObject\MockObject; use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Test\TestCase; /** @@ -89,8 +88,6 @@ class CheckSetupControllerTest extends TestCase { /** @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 */ private $db; @@ -140,9 +137,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->dispatcher = $this->createMock(IEventDispatcher::class); $this->checker = $this->getMockBuilder('\OC\IntegrityCheck\Checker') ->disableOriginalConstructor()->getMock(); $this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); @@ -171,7 +166,6 @@ class CheckSetupControllerTest extends TestCase { $this->l10n, $this->checker, $this->logger, - $this->eventDispatcher, $this->dispatcher, $this->db, $this->lockingProvider, @@ -681,7 +675,6 @@ class CheckSetupControllerTest extends TestCase { $this->l10n, $this->checker, $this->logger, - $this->eventDispatcher, $this->dispatcher, $this->db, $this->lockingProvider, @@ -1409,7 +1402,6 @@ Array $this->l10n, $this->checker, $this->logger, - $this->eventDispatcher, $this->dispatcher, $this->db, $this->lockingProvider, @@ -1464,7 +1456,6 @@ Array $this->l10n, $this->checker, $this->logger, - $this->eventDispatcher, $this->dispatcher, $this->db, $this->lockingProvider, diff --git a/core/Command/Db/AddMissingColumns.php b/core/Command/Db/AddMissingColumns.php index 46642f7d0d4..07763c66154 100644 --- a/core/Command/Db/AddMissingColumns.php +++ b/core/Command/Db/AddMissingColumns.php @@ -29,15 +29,11 @@ namespace OC\Core\Command\Db; use OC\DB\Connection; use OC\DB\SchemaWrapper; use OCP\DB\Events\AddMissingColumnsEvent; -use OCP\DB\Types; use OCP\EventDispatcher\IEventDispatcher; -use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\GenericEvent; /** * Class AddMissingColumns @@ -50,7 +46,6 @@ use Symfony\Component\EventDispatcher\GenericEvent; class AddMissingColumns extends Command { public function __construct( private Connection $connection, - private EventDispatcherInterface $legacyDispatcher, private IEventDispatcher $dispatcher, ) { parent::__construct(); @@ -67,9 +62,6 @@ class AddMissingColumns extends Command { $dryRun = $input->getOption('dry-run'); // Dispatch event so apps can also update columns if needed - $event = new GenericEvent($output); - $this->legacyDispatcher->dispatch(IDBConnection::ADD_MISSING_COLUMNS_EVENT, $event); - $event = new AddMissingColumnsEvent(); $this->dispatcher->dispatchTyped($event); $missingColumns = $event->getMissingColumns(); diff --git a/core/Command/Db/AddMissingIndices.php b/core/Command/Db/AddMissingIndices.php index f05be314e08..56dbf8ce8d9 100644 --- a/core/Command/Db/AddMissingIndices.php +++ b/core/Command/Db/AddMissingIndices.php @@ -33,18 +33,14 @@ declare(strict_types=1); */ 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; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\GenericEvent; /** * Class AddMissingIndices @@ -57,8 +53,7 @@ use Symfony\Component\EventDispatcher\GenericEvent; class AddMissingIndices extends Command { public function __construct( private Connection $connection, - private IEventDispatcher $eventDispatcher, - private EventDispatcherInterface $dispatcher, + private IEventDispatcher $dispatcher, ) { parent::__construct(); } @@ -74,11 +69,8 @@ class AddMissingIndices extends Command { $dryRun = $input->getOption('dry-run'); // 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); + $this->dispatcher->dispatchTyped($event); $missingIndices = $event->getMissingIndices(); if ($missingIndices !== []) { diff --git a/core/Command/Db/AddMissingPrimaryKeys.php b/core/Command/Db/AddMissingPrimaryKeys.php index b7435144933..658eb0b0f5a 100644 --- a/core/Command/Db/AddMissingPrimaryKeys.php +++ b/core/Command/Db/AddMissingPrimaryKeys.php @@ -28,17 +28,12 @@ namespace OC\Core\Command\Db; use OC\DB\Connection; use OC\DB\SchemaWrapper; -use OCP\DB\Events\AddMissingColumnsEvent; use OCP\DB\Events\AddMissingPrimaryKeyEvent; use OCP\EventDispatcher\IEventDispatcher; -use OCP\IDBConnection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\GenericEvent; -use function Symfony\Component\Translation\t; /** * Class AddMissingPrimaryKeys @@ -51,7 +46,6 @@ use function Symfony\Component\Translation\t; class AddMissingPrimaryKeys extends Command { public function __construct( private Connection $connection, - private EventDispatcherInterface $legacyDispatcher, private IEventDispatcher $dispatcher, ) { parent::__construct(); @@ -68,9 +62,6 @@ class AddMissingPrimaryKeys extends Command { $dryRun = $input->getOption('dry-run'); // Dispatch event so apps can also update indexes if needed - $event = new GenericEvent($output); - $this->legacyDispatcher->dispatch(IDBConnection::ADD_MISSING_PRIMARY_KEYS_EVENT, $event); - $event = new AddMissingPrimaryKeyEvent(); $this->dispatcher->dispatchTyped($event); $missingKeys = $event->getMissingPrimaryKeys(); diff --git a/lib/public/IDBConnection.php b/lib/public/IDBConnection.php index 7ce2537cb65..fe0267facc5 100644 --- a/lib/public/IDBConnection.php +++ b/lib/public/IDBConnection.php @@ -34,9 +34,6 @@ namespace OCP; use Doctrine\DBAL\Schema\Schema; -use OCP\DB\Events\AddMissingColumnsEvent; -use OCP\DB\Events\AddMissingIndicesEvent; -use OCP\DB\Events\AddMissingPrimaryKeyEvent; use OCP\DB\Exception; use OCP\DB\IPreparedStatement; use OCP\DB\IResult; @@ -48,36 +45,6 @@ use OCP\DB\QueryBuilder\IQueryBuilder; * @since 6.0.0 */ interface IDBConnection { - /** - * @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, use {@see AddMissingIndicesEvent} instead - */ - public const CHECK_MISSING_INDEXES_EVENT = self::class . '::CHECK_MISSING_INDEXES'; - - /** - * @deprecated 22.0.0 this is an internal event, use {@see AddMissingPrimaryKeyEvent} instead - */ - public const ADD_MISSING_PRIMARY_KEYS_EVENT = self::class . '::ADD_MISSING_PRIMARY_KEYS'; - - /** - * @deprecated 22.0.0 this is an internal event, use {@see AddMissingPrimaryKeyEvent} instead - */ - public const CHECK_MISSING_PRIMARY_KEYS_EVENT = self::class . '::CHECK_MISSING_PRIMARY_KEYS'; - - /** - * @deprecated 22.0.0 this is an internal event, use {@see AddMissingColumnsEvent} instead - */ - public const ADD_MISSING_COLUMNS_EVENT = self::class . '::ADD_MISSING_COLUMNS'; - - /** - * @deprecated 22.0.0 this is an internal event, use {@see AddMissingColumnsEvent} instead - */ - public const CHECK_MISSING_COLUMNS_EVENT = self::class . '::CHECK_MISSING_COLUMNS'; - /** * Gets the QueryBuilder for the connection. *