AddMissingPrimaryKeys.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * @copyright Copyright (c) 2017 Bjoern Schiessle <bjoern@schiessle.org>
  5. *
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Joas Schilling <coding@schilljs.com>
  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. namespace OC\Core\Command\Db;
  26. use OC\DB\Connection;
  27. use OC\DB\SchemaWrapper;
  28. use OCP\IDBConnection;
  29. use Symfony\Component\Console\Command\Command;
  30. use Symfony\Component\Console\Input\InputInterface;
  31. use Symfony\Component\Console\Input\InputOption;
  32. use Symfony\Component\Console\Output\OutputInterface;
  33. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  34. use Symfony\Component\EventDispatcher\GenericEvent;
  35. /**
  36. * Class AddMissingPrimaryKeys
  37. *
  38. * if you added primary keys to the database, this is the right place to add
  39. * your update routine for existing instances
  40. *
  41. * @package OC\Core\Command\Db
  42. */
  43. class AddMissingPrimaryKeys extends Command {
  44. public function __construct(
  45. private Connection $connection,
  46. private EventDispatcherInterface $dispatcher,
  47. ) {
  48. parent::__construct();
  49. }
  50. protected function configure() {
  51. $this
  52. ->setName('db:add-missing-primary-keys')
  53. ->setDescription('Add missing primary keys to the database tables')
  54. ->addOption('dry-run', null, InputOption::VALUE_NONE, "Output the SQL queries instead of running them.");
  55. }
  56. protected function execute(InputInterface $input, OutputInterface $output): int {
  57. $this->addCorePrimaryKeys($output, $input->getOption('dry-run'));
  58. // Dispatch event so apps can also update indexes if needed
  59. $event = new GenericEvent($output);
  60. $this->dispatcher->dispatch(IDBConnection::ADD_MISSING_PRIMARY_KEYS_EVENT, $event);
  61. return 0;
  62. }
  63. /**
  64. * add missing indices to the share table
  65. *
  66. * @param OutputInterface $output
  67. * @param bool $dryRun If true, will return the sql queries instead of running them.
  68. * @throws \Doctrine\DBAL\Schema\SchemaException
  69. */
  70. private function addCorePrimaryKeys(OutputInterface $output, bool $dryRun): void {
  71. $output->writeln('<info>Check primary keys.</info>');
  72. $schema = new SchemaWrapper($this->connection);
  73. $updated = false;
  74. if ($schema->hasTable('federated_reshares')) {
  75. $table = $schema->getTable('federated_reshares');
  76. if (!$table->hasPrimaryKey()) {
  77. $output->writeln('<info>Adding primary key to the federated_reshares table, this can take some time...</info>');
  78. $table->setPrimaryKey(['share_id'], 'federated_res_pk');
  79. if ($table->hasIndex('share_id_index')) {
  80. $table->dropIndex('share_id_index');
  81. }
  82. $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
  83. if ($dryRun && $sqlQueries !== null) {
  84. $output->writeln($sqlQueries);
  85. }
  86. $updated = true;
  87. $output->writeln('<info>federated_reshares table updated successfully.</info>');
  88. }
  89. }
  90. if ($schema->hasTable('systemtag_object_mapping')) {
  91. $table = $schema->getTable('systemtag_object_mapping');
  92. if (!$table->hasPrimaryKey()) {
  93. $output->writeln('<info>Adding primary key to the systemtag_object_mapping table, this can take some time...</info>');
  94. $table->setPrimaryKey(['objecttype', 'objectid', 'systemtagid'], 'som_pk');
  95. if ($table->hasIndex('mapping')) {
  96. $table->dropIndex('mapping');
  97. }
  98. $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
  99. if ($dryRun && $sqlQueries !== null) {
  100. $output->writeln($sqlQueries);
  101. }
  102. $updated = true;
  103. $output->writeln('<info>systemtag_object_mapping table updated successfully.</info>');
  104. }
  105. }
  106. if ($schema->hasTable('comments_read_markers')) {
  107. $table = $schema->getTable('comments_read_markers');
  108. if (!$table->hasPrimaryKey()) {
  109. $output->writeln('<info>Adding primary key to the comments_read_markers table, this can take some time...</info>');
  110. $table->setPrimaryKey(['user_id', 'object_type', 'object_id'], 'crm_pk');
  111. if ($table->hasIndex('comments_marker_index')) {
  112. $table->dropIndex('comments_marker_index');
  113. }
  114. $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
  115. if ($dryRun && $sqlQueries !== null) {
  116. $output->writeln($sqlQueries);
  117. }
  118. $updated = true;
  119. $output->writeln('<info>comments_read_markers table updated successfully.</info>');
  120. }
  121. }
  122. if ($schema->hasTable('collres_resources')) {
  123. $table = $schema->getTable('collres_resources');
  124. if (!$table->hasPrimaryKey()) {
  125. $output->writeln('<info>Adding primary key to the collres_resources table, this can take some time...</info>');
  126. $table->setPrimaryKey(['collection_id', 'resource_type', 'resource_id'], 'crr_pk');
  127. if ($table->hasIndex('collres_unique_res')) {
  128. $table->dropIndex('collres_unique_res');
  129. }
  130. $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
  131. if ($dryRun && $sqlQueries !== null) {
  132. $output->writeln($sqlQueries);
  133. }
  134. $updated = true;
  135. $output->writeln('<info>collres_resources table updated successfully.</info>');
  136. }
  137. }
  138. if ($schema->hasTable('collres_accesscache')) {
  139. $table = $schema->getTable('collres_accesscache');
  140. if (!$table->hasPrimaryKey()) {
  141. $output->writeln('<info>Adding primary key to the collres_accesscache table, this can take some time...</info>');
  142. $table->setPrimaryKey(['user_id', 'collection_id', 'resource_type', 'resource_id'], 'cra_pk');
  143. if ($table->hasIndex('collres_unique_user')) {
  144. $table->dropIndex('collres_unique_user');
  145. }
  146. $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
  147. if ($dryRun && $sqlQueries !== null) {
  148. $output->writeln($sqlQueries);
  149. }
  150. $updated = true;
  151. $output->writeln('<info>collres_accesscache table updated successfully.</info>');
  152. }
  153. }
  154. if ($schema->hasTable('filecache_extended')) {
  155. $table = $schema->getTable('filecache_extended');
  156. if (!$table->hasPrimaryKey()) {
  157. $output->writeln('<info>Adding primary key to the filecache_extended table, this can take some time...</info>');
  158. $table->setPrimaryKey(['fileid'], 'fce_pk');
  159. if ($table->hasIndex('fce_fileid_idx')) {
  160. $table->dropIndex('fce_fileid_idx');
  161. }
  162. $sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
  163. if ($dryRun && $sqlQueries !== null) {
  164. $output->writeln($sqlQueries);
  165. }
  166. $updated = true;
  167. $output->writeln('<info>filecache_extended table updated successfully.</info>');
  168. }
  169. }
  170. if (!$updated) {
  171. $output->writeln('<info>Done.</info>');
  172. }
  173. }
  174. }