Passed
Push — master ( 3c693d...ccd5ca )
by Roeland
28:56 queued 14:09
created

AddMissingIndices::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @copyright Copyright (c) 2017 Bjoern Schiessle <[email protected]>
7
 *
8
 * @author Bjoern Schiessle <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Mario Danic <[email protected]>
11
 * @author Morris Jobke <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 * @author Thomas Citharel <[email protected]>
15
 *
16
 * @license GNU AGPL version 3 or any later version
17
 *
18
 * This program is free software: you can redistribute it and/or modify
19
 * it under the terms of the GNU Affero General Public License as
20
 * published by the Free Software Foundation, either version 3 of the
21
 * License, or (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU Affero General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU Affero General Public License
29
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30
 *
31
 */
32
33
namespace OC\Core\Command\Db;
34
35
use OC\DB\SchemaWrapper;
36
use OCP\IDBConnection;
37
use Symfony\Component\Console\Command\Command;
38
use Symfony\Component\Console\Input\InputInterface;
39
use Symfony\Component\Console\Output\OutputInterface;
40
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
41
use Symfony\Component\EventDispatcher\GenericEvent;
42
43
/**
44
 * Class AddMissingIndices
45
 *
46
 * if you added any new indices to the database, this is the right place to add
47
 * your update routine for existing instances
48
 *
49
 * @package OC\Core\Command\Db
50
 */
51
class AddMissingIndices extends Command {
52
53
	/** @var IDBConnection */
54
	private $connection;
55
56
	/** @var EventDispatcherInterface */
57
	private $dispatcher;
58
59
	public function __construct(IDBConnection $connection, EventDispatcherInterface $dispatcher) {
60
		parent::__construct();
61
62
		$this->connection = $connection;
63
		$this->dispatcher = $dispatcher;
64
	}
65
66
	protected function configure() {
67
		$this
68
			->setName('db:add-missing-indices')
69
			->setDescription('Add missing indices to the database tables');
70
	}
71
72
	protected function execute(InputInterface $input, OutputInterface $output): int {
73
		$this->addCoreIndexes($output);
74
75
		// Dispatch event so apps can also update indexes if needed
76
		$event = new GenericEvent($output);
77
		$this->dispatcher->dispatch(IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

77
		$this->dispatcher->/** @scrutinizer ignore-call */ 
78
                     dispatch(IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
78
		return 0;
79
	}
80
81
	/**
82
	 * add missing indices to the share table
83
	 *
84
	 * @param OutputInterface $output
85
	 * @throws \Doctrine\DBAL\Schema\SchemaException
86
	 */
87
	private function addCoreIndexes(OutputInterface $output) {
88
		$output->writeln('<info>Check indices of the share table.</info>');
89
90
		$schema = new SchemaWrapper($this->connection);
91
		$updated = false;
92
93
		if ($schema->hasTable('share')) {
94
			$table = $schema->getTable('share');
95
			if (!$table->hasIndex('share_with_index')) {
96
				$output->writeln('<info>Adding additional share_with index to the share table, this can take some time...</info>');
97
				$table->addIndex(['share_with'], 'share_with_index');
98
				$this->connection->migrateToSchema($schema->getWrappedSchema());
99
				$updated = true;
100
				$output->writeln('<info>Share table updated successfully.</info>');
101
			}
102
103
			if (!$table->hasIndex('parent_index')) {
104
				$output->writeln('<info>Adding additional parent index to the share table, this can take some time...</info>');
105
				$table->addIndex(['parent'], 'parent_index');
106
				$this->connection->migrateToSchema($schema->getWrappedSchema());
107
				$updated = true;
108
				$output->writeln('<info>Share table updated successfully.</info>');
109
			}
110
111
			if (!$table->hasIndex('owner_index')) {
112
				$output->writeln('<info>Adding additional owner index to the share table, this can take some time...</info>');
113
				$table->addIndex(['uid_owner'], 'owner_index');
114
				$this->connection->migrateToSchema($schema->getWrappedSchema());
115
				$updated = true;
116
				$output->writeln('<info>Share table updated successfully.</info>');
117
			}
118
119
			if (!$table->hasIndex('initiator_index')) {
120
				$output->writeln('<info>Adding additional initiator index to the share table, this can take some time...</info>');
121
				$table->addIndex(['uid_initiator'], 'initiator_index');
122
				$this->connection->migrateToSchema($schema->getWrappedSchema());
123
				$updated = true;
124
				$output->writeln('<info>Share table updated successfully.</info>');
125
			}
126
		}
127
128
		$output->writeln('<info>Check indices of the filecache table.</info>');
129
		if ($schema->hasTable('filecache')) {
130
			$table = $schema->getTable('filecache');
131
			if (!$table->hasIndex('fs_mtime')) {
132
				$output->writeln('<info>Adding additional mtime index to the filecache table, this can take some time...</info>');
133
				$table->addIndex(['mtime'], 'fs_mtime');
134
				$this->connection->migrateToSchema($schema->getWrappedSchema());
135
				$updated = true;
136
				$output->writeln('<info>Filecache table updated successfully.</info>');
137
			}
138
			if (!$table->hasIndex('fs_size')) {
139
				$output->writeln('<info>Adding additional size index to the filecache table, this can take some time...</info>');
140
				$table->addIndex(['size'], 'fs_size');
141
				$this->connection->migrateToSchema($schema->getWrappedSchema());
142
				$updated = true;
143
				$output->writeln('<info>Filecache table updated successfully.</info>');
144
			}
145
		}
146
147
		$output->writeln('<info>Check indices of the twofactor_providers table.</info>');
148
		if ($schema->hasTable('twofactor_providers')) {
149
			$table = $schema->getTable('twofactor_providers');
150
			if (!$table->hasIndex('twofactor_providers_uid')) {
151
				$output->writeln('<info>Adding additional twofactor_providers_uid index to the twofactor_providers table, this can take some time...</info>');
152
				$table->addIndex(['uid'], 'twofactor_providers_uid');
153
				$this->connection->migrateToSchema($schema->getWrappedSchema());
154
				$updated = true;
155
				$output->writeln('<info>Twofactor_providers table updated successfully.</info>');
156
			}
157
		}
158
159
		$output->writeln('<info>Check indices of the login_flow_v2 table.</info>');
160
		if ($schema->hasTable('login_flow_v2')) {
161
			$table = $schema->getTable('login_flow_v2');
162
			if (!$table->hasIndex('poll_token')) {
163
				$output->writeln('<info>Adding additional indeces to the login_flow_v2 table, this can take some time...</info>');
164
165
				foreach ($table->getIndexes() as $index) {
166
					$columns = $index->getColumns();
167
					if ($columns === ['poll_token'] ||
168
						$columns === ['login_token'] ||
169
						$columns === ['timestamp']) {
170
						$table->dropIndex($index->getName());
171
					}
172
				}
173
174
				$table->addUniqueIndex(['poll_token'], 'poll_token');
175
				$table->addUniqueIndex(['login_token'], 'login_token');
176
				$table->addIndex(['timestamp'], 'timestamp');
177
				$this->connection->migrateToSchema($schema->getWrappedSchema());
178
				$updated = true;
179
				$output->writeln('<info>login_flow_v2 table updated successfully.</info>');
180
			}
181
		}
182
183
		$output->writeln('<info>Check indices of the whats_new table.</info>');
184
		if ($schema->hasTable('whats_new')) {
185
			$table = $schema->getTable('whats_new');
186
			if (!$table->hasIndex('version')) {
187
				$output->writeln('<info>Adding version index to the whats_new table, this can take some time...</info>');
188
189
				foreach ($table->getIndexes() as $index) {
190
					if ($index->getColumns() === ['version']) {
191
						$table->dropIndex($index->getName());
192
					}
193
				}
194
195
				$table->addUniqueIndex(['version'], 'version');
196
				$this->connection->migrateToSchema($schema->getWrappedSchema());
197
				$updated = true;
198
				$output->writeln('<info>whats_new table updated successfully.</info>');
199
			}
200
		}
201
202
		$output->writeln('<info>Check indices of the cards table.</info>');
203
		$cardsUpdated = false;
204
		if ($schema->hasTable('cards')) {
205
			$table = $schema->getTable('cards');
206
207
			if ($table->hasIndex('addressbookid_uri_index')) {
208
				$output->writeln('<info>Renaming addressbookid_uri_index index to  to the cards table, this can take some time...</info>');
209
210
				foreach ($table->getIndexes() as $index) {
211
					if ($index->getColumns() === ['addressbookid', 'uri']) {
212
						$table->renameIndex('addressbookid_uri_index', 'cards_abiduri');
213
					}
214
				}
215
216
				$this->connection->migrateToSchema($schema->getWrappedSchema());
217
				$cardsUpdated = true;
218
			}
219
220
			if (!$table->hasIndex('cards_abid')) {
221
				$output->writeln('<info>Adding cards_abid index to the cards table, this can take some time...</info>');
222
223
				foreach ($table->getIndexes() as $index) {
224
					if ($index->getColumns() === ['addressbookid']) {
225
						$table->dropIndex($index->getName());
226
					}
227
				}
228
229
				$table->addIndex(['addressbookid'], 'cards_abid');
230
				$this->connection->migrateToSchema($schema->getWrappedSchema());
231
				$cardsUpdated = true;
232
			}
233
234
			if (!$table->hasIndex('cards_abiduri')) {
235
				$output->writeln('<info>Adding cards_abiduri index to the cards table, this can take some time...</info>');
236
237
				foreach ($table->getIndexes() as $index) {
238
					if ($index->getColumns() === ['addressbookid', 'uri']) {
239
						$table->dropIndex($index->getName());
240
					}
241
				}
242
243
				$table->addIndex(['addressbookid', 'uri'], 'cards_abiduri');
244
				$this->connection->migrateToSchema($schema->getWrappedSchema());
245
				$cardsUpdated = true;
246
			}
247
248
			if ($cardsUpdated) {
249
				$updated = true;
250
				$output->writeln('<info>cards table updated successfully.</info>');
251
			}
252
		}
253
254
		$output->writeln('<info>Check indices of the cards_properties table.</info>');
255
		if ($schema->hasTable('cards_properties')) {
256
			$table = $schema->getTable('cards_properties');
257
			if (!$table->hasIndex('cards_prop_abid')) {
258
				$output->writeln('<info>Adding cards_prop_abid index to the cards_properties table, this can take some time...</info>');
259
260
				foreach ($table->getIndexes() as $index) {
261
					if ($index->getColumns() === ['addressbookid']) {
262
						$table->dropIndex($index->getName());
263
					}
264
				}
265
266
				$table->addIndex(['addressbookid'], 'cards_prop_abid');
267
				$this->connection->migrateToSchema($schema->getWrappedSchema());
268
				$updated = true;
269
				$output->writeln('<info>cards_properties table updated successfully.</info>');
270
			}
271
		}
272
273
		$output->writeln('<info>Check indices of the calendarobjects_props table.</info>');
274
		if ($schema->hasTable('calendarobjects_props')) {
275
			$table = $schema->getTable('calendarobjects_props');
276
			if (!$table->hasIndex('calendarobject_calid_index')) {
277
				$output->writeln('<info>Adding calendarobject_calid_index index to the calendarobjects_props table, this can take some time...</info>');
278
279
				$table->addIndex(['calendarid', 'calendartype'], 'calendarobject_calid_index');
280
				$this->connection->migrateToSchema($schema->getWrappedSchema());
281
				$updated = true;
282
				$output->writeln('<info>calendarobjects_props table updated successfully.</info>');
283
			}
284
		}
285
286
		$output->writeln('<info>Check indices of the schedulingobjects table.</info>');
287
		if ($schema->hasTable('schedulingobjects')) {
288
			$table = $schema->getTable('schedulingobjects');
289
			if (!$table->hasIndex('schedulobj_principuri_index')) {
290
				$output->writeln('<info>Adding schedulobj_principuri_index index to the schedulingobjects table, this can take some time...</info>');
291
292
				$table->addIndex(['principaluri'], 'schedulobj_principuri_index');
293
				$this->connection->migrateToSchema($schema->getWrappedSchema());
294
				$updated = true;
295
				$output->writeln('<info>schedulingobjects table updated successfully.</info>');
296
			}
297
		}
298
299
		$output->writeln('<info>Check indices of the oc_properties table.</info>');
300
		if ($schema->hasTable('properties')) {
301
			$table = $schema->getTable('properties');
302
			if (!$table->hasIndex('properties_path_index')) {
303
				$output->writeln('<info>Adding properties_path_index index to the oc_properties table, this can take some time...</info>');
304
305
				$table->addIndex(['userid', 'propertypath'], 'properties_path_index');
306
				$this->connection->migrateToSchema($schema->getWrappedSchema());
307
				$updated = true;
308
				$output->writeln('<info>oc_properties table updated successfully.</info>');
309
			}
310
		}
311
312
		if (!$updated) {
313
			$output->writeln('<info>Done.</info>');
314
		}
315
	}
316
}
317