Passed
Push — master ( 3bae59...c1000f )
by Christoph
14:32 queued 16s
created

AddMissingIndices::execute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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

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

82
		$this->dispatcher->dispatch(/** @scrutinizer ignore-deprecated */ IDBConnection::ADD_MISSING_INDEXES_EVENT, $event);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
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

82
		$this->dispatcher->/** @scrutinizer ignore-call */ 
83
                     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...
83
		return 0;
84
	}
85
86
	/**
87
	 * add missing indices to the share table
88
	 *
89
	 * @param OutputInterface $output
90
	 * @param bool $dryRun If true, will return the sql queries instead of running them.
91
	 * @throws \Doctrine\DBAL\Schema\SchemaException
92
	 */
93
	private function addCoreIndexes(OutputInterface $output, bool $dryRun): void {
94
		$output->writeln('<info>Check indices of the share table.</info>');
95
96
		$schema = new SchemaWrapper($this->connection);
97
		$updated = false;
98
99
		if ($schema->hasTable('share')) {
100
			$table = $schema->getTable('share');
101
			if (!$table->hasIndex('share_with_index')) {
102
				$output->writeln('<info>Adding additional share_with index to the share table, this can take some time...</info>');
103
				$table->addIndex(['share_with'], 'share_with_index');
104
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
105
				if ($dryRun && $sqlQueries !== null) {
106
					$output->writeln($sqlQueries);
107
				}
108
				$updated = true;
109
				$output->writeln('<info>Share table updated successfully.</info>');
110
			}
111
112
			if (!$table->hasIndex('parent_index')) {
113
				$output->writeln('<info>Adding additional parent index to the share table, this can take some time...</info>');
114
				$table->addIndex(['parent'], 'parent_index');
115
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
116
				if ($dryRun && $sqlQueries !== null) {
117
					$output->writeln($sqlQueries);
118
				}
119
				$updated = true;
120
				$output->writeln('<info>Share table updated successfully.</info>');
121
			}
122
123
			if (!$table->hasIndex('owner_index')) {
124
				$output->writeln('<info>Adding additional owner index to the share table, this can take some time...</info>');
125
				$table->addIndex(['uid_owner'], 'owner_index');
126
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
127
				if ($dryRun && $sqlQueries !== null) {
128
					$output->writeln($sqlQueries);
129
				}
130
				$updated = true;
131
				$output->writeln('<info>Share table updated successfully.</info>');
132
			}
133
134
			if (!$table->hasIndex('initiator_index')) {
135
				$output->writeln('<info>Adding additional initiator index to the share table, this can take some time...</info>');
136
				$table->addIndex(['uid_initiator'], 'initiator_index');
137
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
138
				if ($dryRun && $sqlQueries !== null) {
139
					$output->writeln($sqlQueries);
140
				}
141
				$updated = true;
142
				$output->writeln('<info>Share table updated successfully.</info>');
143
			}
144
		}
145
146
		$output->writeln('<info>Check indices of the filecache table.</info>');
147
		if ($schema->hasTable('filecache')) {
148
			$table = $schema->getTable('filecache');
149
			if (!$table->hasIndex('fs_mtime')) {
150
				$output->writeln('<info>Adding additional mtime index to the filecache table, this can take some time...</info>');
151
				$table->addIndex(['mtime'], 'fs_mtime');
152
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
153
				if ($dryRun && $sqlQueries !== null) {
154
					$output->writeln($sqlQueries);
155
				}
156
				$updated = true;
157
				$output->writeln('<info>Filecache table updated successfully.</info>');
158
			}
159
			if (!$table->hasIndex('fs_size')) {
160
				$output->writeln('<info>Adding additional size index to the filecache table, this can take some time...</info>');
161
				$table->addIndex(['size'], 'fs_size');
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 table updated successfully.</info>');
168
			}
169
			if (!$table->hasIndex('fs_id_storage_size')) {
170
				$output->writeln('<info>Adding additional size index to the filecache table, this can take some time...</info>');
171
				$table->addIndex(['fileid', 'storage', 'size'], 'fs_id_storage_size');
172
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
173
				if ($dryRun && $sqlQueries !== null) {
174
					$output->writeln($sqlQueries);
175
				}
176
				$updated = true;
177
				$output->writeln('<info>Filecache table updated successfully.</info>');
178
			}
179
			if (!$table->hasIndex('fs_storage_path_prefix') && !$schema->getDatabasePlatform() instanceof PostgreSQL94Platform) {
180
				$output->writeln('<info>Adding additional path index to the filecache table, this can take some time...</info>');
181
				$table->addIndex(['storage', 'path'], 'fs_storage_path_prefix', [], ['lengths' => [null, 64]]);
182
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
183
				if ($dryRun && $sqlQueries !== null) {
184
					$output->writeln($sqlQueries);
185
				}
186
				$updated = true;
187
				$output->writeln('<info>Filecache table updated successfully.</info>');
188
			}
189
		}
190
191
		$output->writeln('<info>Check indices of the twofactor_providers table.</info>');
192
		if ($schema->hasTable('twofactor_providers')) {
193
			$table = $schema->getTable('twofactor_providers');
194
			if (!$table->hasIndex('twofactor_providers_uid')) {
195
				$output->writeln('<info>Adding additional twofactor_providers_uid index to the twofactor_providers table, this can take some time...</info>');
196
				$table->addIndex(['uid'], 'twofactor_providers_uid');
197
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
198
				if ($dryRun && $sqlQueries !== null) {
199
					$output->writeln($sqlQueries);
200
				}
201
				$updated = true;
202
				$output->writeln('<info>Twofactor_providers table updated successfully.</info>');
203
			}
204
		}
205
206
		$output->writeln('<info>Check indices of the login_flow_v2 table.</info>');
207
		if ($schema->hasTable('login_flow_v2')) {
208
			$table = $schema->getTable('login_flow_v2');
209
			if (!$table->hasIndex('poll_token')) {
210
				$output->writeln('<info>Adding additional indeces to the login_flow_v2 table, this can take some time...</info>');
211
212
				foreach ($table->getIndexes() as $index) {
213
					$columns = $index->getColumns();
214
					if ($columns === ['poll_token'] ||
215
						$columns === ['login_token'] ||
216
						$columns === ['timestamp']) {
217
						$table->dropIndex($index->getName());
218
					}
219
				}
220
221
				$table->addUniqueIndex(['poll_token'], 'poll_token');
222
				$table->addUniqueIndex(['login_token'], 'login_token');
223
				$table->addIndex(['timestamp'], 'timestamp');
224
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
225
				if ($dryRun && $sqlQueries !== null) {
226
					$output->writeln($sqlQueries);
227
				}
228
				$updated = true;
229
				$output->writeln('<info>login_flow_v2 table updated successfully.</info>');
230
			}
231
		}
232
233
		$output->writeln('<info>Check indices of the whats_new table.</info>');
234
		if ($schema->hasTable('whats_new')) {
235
			$table = $schema->getTable('whats_new');
236
			if (!$table->hasIndex('version')) {
237
				$output->writeln('<info>Adding version index to the whats_new table, this can take some time...</info>');
238
239
				foreach ($table->getIndexes() as $index) {
240
					if ($index->getColumns() === ['version']) {
241
						$table->dropIndex($index->getName());
242
					}
243
				}
244
245
				$table->addUniqueIndex(['version'], 'version');
246
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
247
				if ($dryRun && $sqlQueries !== null) {
248
					$output->writeln($sqlQueries);
249
				}
250
				$updated = true;
251
				$output->writeln('<info>whats_new table updated successfully.</info>');
252
			}
253
		}
254
255
		$output->writeln('<info>Check indices of the cards table.</info>');
256
		$cardsUpdated = false;
257
		if ($schema->hasTable('cards')) {
258
			$table = $schema->getTable('cards');
259
260
			if ($table->hasIndex('addressbookid_uri_index')) {
261
				$output->writeln('<info>Renaming addressbookid_uri_index index to  to the cards table, this can take some time...</info>');
262
263
				foreach ($table->getIndexes() as $index) {
264
					if ($index->getColumns() === ['addressbookid', 'uri']) {
265
						$table->renameIndex('addressbookid_uri_index', 'cards_abiduri');
266
					}
267
				}
268
269
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
270
				if ($dryRun && $sqlQueries !== null) {
271
					$output->writeln($sqlQueries);
272
				}
273
				$cardsUpdated = true;
274
			}
275
276
			if (!$table->hasIndex('cards_abid')) {
277
				$output->writeln('<info>Adding cards_abid index to the cards table, this can take some time...</info>');
278
279
				foreach ($table->getIndexes() as $index) {
280
					if ($index->getColumns() === ['addressbookid']) {
281
						$table->dropIndex($index->getName());
282
					}
283
				}
284
285
				$table->addIndex(['addressbookid'], 'cards_abid');
286
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
287
				if ($dryRun && $sqlQueries !== null) {
288
					$output->writeln($sqlQueries);
289
				}
290
				$cardsUpdated = true;
291
			}
292
293
			if (!$table->hasIndex('cards_abiduri')) {
294
				$output->writeln('<info>Adding cards_abiduri index to the cards table, this can take some time...</info>');
295
296
				foreach ($table->getIndexes() as $index) {
297
					if ($index->getColumns() === ['addressbookid', 'uri']) {
298
						$table->dropIndex($index->getName());
299
					}
300
				}
301
302
				$table->addIndex(['addressbookid', 'uri'], 'cards_abiduri');
303
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
304
				if ($dryRun && $sqlQueries !== null) {
305
					$output->writeln($sqlQueries);
306
				}
307
				$cardsUpdated = true;
308
			}
309
310
			if ($cardsUpdated) {
0 ignored issues
show
introduced by
The condition $cardsUpdated is always false.
Loading history...
311
				$updated = true;
312
				$output->writeln('<info>cards table updated successfully.</info>');
313
			}
314
		}
315
316
		$output->writeln('<info>Check indices of the cards_properties table.</info>');
317
		if ($schema->hasTable('cards_properties')) {
318
			$table = $schema->getTable('cards_properties');
319
			if (!$table->hasIndex('cards_prop_abid')) {
320
				$output->writeln('<info>Adding cards_prop_abid index to the cards_properties table, this can take some time...</info>');
321
322
				foreach ($table->getIndexes() as $index) {
323
					if ($index->getColumns() === ['addressbookid']) {
324
						$table->dropIndex($index->getName());
325
					}
326
				}
327
328
				$table->addIndex(['addressbookid'], 'cards_prop_abid');
329
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
330
				if ($dryRun && $sqlQueries !== null) {
331
					$output->writeln($sqlQueries);
332
				}
333
				$updated = true;
334
				$output->writeln('<info>cards_properties table updated successfully.</info>');
335
			}
336
		}
337
338
		$output->writeln('<info>Check indices of the calendarobjects_props table.</info>');
339
		if ($schema->hasTable('calendarobjects_props')) {
340
			$table = $schema->getTable('calendarobjects_props');
341
			if (!$table->hasIndex('calendarobject_calid_index')) {
342
				$output->writeln('<info>Adding calendarobject_calid_index index to the calendarobjects_props table, this can take some time...</info>');
343
344
				$table->addIndex(['calendarid', 'calendartype'], 'calendarobject_calid_index');
345
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
346
				if ($dryRun && $sqlQueries !== null) {
347
					$output->writeln($sqlQueries);
348
				}
349
				$updated = true;
350
				$output->writeln('<info>calendarobjects_props table updated successfully.</info>');
351
			}
352
		}
353
354
		$output->writeln('<info>Check indices of the schedulingobjects table.</info>');
355
		if ($schema->hasTable('schedulingobjects')) {
356
			$table = $schema->getTable('schedulingobjects');
357
			if (!$table->hasIndex('schedulobj_principuri_index')) {
358
				$output->writeln('<info>Adding schedulobj_principuri_index index to the schedulingobjects table, this can take some time...</info>');
359
360
				$table->addIndex(['principaluri'], 'schedulobj_principuri_index');
361
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
362
				if ($dryRun && $sqlQueries !== null) {
363
					$output->writeln($sqlQueries);
364
				}
365
				$updated = true;
366
				$output->writeln('<info>schedulingobjects table updated successfully.</info>');
367
			}
368
		}
369
370
		$output->writeln('<info>Check indices of the oc_properties table.</info>');
371
		if ($schema->hasTable('properties')) {
372
			$table = $schema->getTable('properties');
373
			$propertiesUpdated = false;
374
375
			if (!$table->hasIndex('properties_path_index')) {
376
				$output->writeln('<info>Adding properties_path_index index to the oc_properties table, this can take some time...</info>');
377
378
				$table->addIndex(['userid', 'propertypath'], 'properties_path_index');
379
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
380
				if ($dryRun && $sqlQueries !== null) {
381
					$output->writeln($sqlQueries);
382
				}
383
				$propertiesUpdated = true;
384
			}
385
			if (!$table->hasIndex('properties_pathonly_index')) {
386
				$output->writeln('<info>Adding properties_pathonly_index index to the oc_properties table, this can take some time...</info>');
387
388
				$table->addIndex(['propertypath'], 'properties_pathonly_index');
389
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
390
				if ($dryRun && $sqlQueries !== null) {
391
					$output->writeln($sqlQueries);
392
				}
393
				$propertiesUpdated = true;
394
			}
395
396
			if ($propertiesUpdated) {
0 ignored issues
show
introduced by
The condition $propertiesUpdated is always false.
Loading history...
397
				$updated = true;
398
				$output->writeln('<info>oc_properties table updated successfully.</info>');
399
			}
400
		}
401
402
		$output->writeln('<info>Check indices of the oc_jobs table.</info>');
403
		if ($schema->hasTable('jobs')) {
404
			$table = $schema->getTable('jobs');
405
			if (!$table->hasIndex('job_lastcheck_reserved')) {
406
				$output->writeln('<info>Adding job_lastcheck_reserved index to the oc_jobs table, this can take some time...</info>');
407
408
				$table->addIndex(['last_checked', 'reserved_at'], 'job_lastcheck_reserved');
409
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
410
				if ($dryRun && $sqlQueries !== null) {
411
					$output->writeln($sqlQueries);
412
				}
413
				$updated = true;
414
				$output->writeln('<info>oc_properties table updated successfully.</info>');
415
			}
416
		}
417
418
		$output->writeln('<info>Check indices of the oc_direct_edit table.</info>');
419
		if ($schema->hasTable('direct_edit')) {
420
			$table = $schema->getTable('direct_edit');
421
			if (!$table->hasIndex('direct_edit_timestamp')) {
422
				$output->writeln('<info>Adding direct_edit_timestamp index to the oc_direct_edit table, this can take some time...</info>');
423
424
				$table->addIndex(['timestamp'], 'direct_edit_timestamp');
425
				$sqlQueries = $this->connection->migrateToSchema($schema->getWrappedSchema(), $dryRun);
426
				if ($dryRun && $sqlQueries !== null) {
427
					$output->writeln($sqlQueries);
428
				}
429
				$updated = true;
430
				$output->writeln('<info>oc_direct_edit table updated successfully.</info>');
431
			}
432
		}
433
434
		if (!$updated) {
0 ignored issues
show
introduced by
The condition $updated is always false.
Loading history...
435
			$output->writeln('<info>Done.</info>');
436
		}
437
	}
438
}
439