Skip to content

Commit eb4a57c

Browse files
authored
Merge pull request #4214 from nextcloud/test/migration-safety
Harden Repairsteps and migration
2 parents e542172 + 616fc14 commit eb4a57c

42 files changed

Lines changed: 788 additions & 648 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

appinfo/info.xml

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<name>Polls</name>
55
<summary>A polls app, similar to Doodle/DuD-Poll with the possibility to restrict access.</summary>
66
<description>A polls app, similar to Doodle/DuD-Poll with the possibility to restrict access (members, certain groups/users, hidden and public).</description>
7-
<version>8.3.0-beta.1</version>
7+
<version>8.3.0-beta.3</version>
88
<licence>agpl</licence>
99
<author>Vinzenz Rosenkranz</author>
1010
<author>René Gieling</author>
@@ -31,25 +31,11 @@
3131
<job>OCA\Polls\Cron\JanitorCron</job>
3232
<job>OCA\Polls\Cron\AutoReminderCron</job>
3333
</background-jobs>
34-
<repair-steps>
35-
<pre-migration>
36-
<step>OCA\Polls\Migration\RepairSteps\RemoveObsoleteMigrations</step>
37-
</pre-migration>
38-
<post-migration>
39-
<step>OCA\Polls\Migration\RepairSteps\DropOrphanedTables</step>
40-
<step>OCA\Polls\Migration\RepairSteps\DropOrphanedColumns</step>
41-
<step>OCA\Polls\Migration\RepairSteps\DeleteInvalidRecords</step>
42-
<step>OCA\Polls\Migration\RepairSteps\UpdateHashes</step>
43-
<step>OCA\Polls\Migration\RepairSteps\CreateIndices</step>
44-
</post-migration>
45-
<install>
46-
<step>OCA\Polls\Migration\RepairSteps\Install</step>
47-
</install>
48-
</repair-steps>
4934
<commands>
5035
<command>OCA\Polls\Command\Db\CleanMigrations</command>
5136
<command>OCA\Polls\Command\Db\CreateIndices</command>
5237
<command>OCA\Polls\Command\Db\Purge</command>
38+
<command>OCA\Polls\Command\Db\FixDB</command>
5339
<command>OCA\Polls\Command\Db\Rebuild</command>
5440
<command>OCA\Polls\Command\Db\RemoveFKConstraints</command>
5541
<command>OCA\Polls\Command\Db\RemoveOptionalIndices</command>

lib/Command/Command.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Command extends \Symfony\Component\Console\Command\Command {
2424
protected string $description = '';
2525
protected array $operationHints = [];
2626
protected bool $defaultContinueAnswer = false;
27+
protected bool $skipQuestion = false;
2728
protected mixed $helper;
2829
protected InputInterface $input;
2930
protected OutputInterface $output;
@@ -56,6 +57,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5657
}
5758

5859
protected function requestConfirmation(InputInterface $input, OutputInterface $output): int {
60+
if ($this->skipQuestion) {
61+
return 0;
62+
}
63+
5964
if ($input->isInteractive()) {
6065
/** @var QuestionHelper */
6166
$this->helper = $this->getHelper('question');

lib/Command/Db/CleanMigrations.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use Doctrine\DBAL\Schema\Schema;
1212
use OCA\Polls\Command\Command;
13-
use OCA\Polls\Db\TableManager;
13+
use OCA\Polls\Db\V2\TableManager;
1414
use OCP\IDBConnection;
1515

1616
/**

lib/Command/Db/CreateIndices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use Doctrine\DBAL\Schema\Schema;
1212
use OCA\Polls\Command\Command;
13-
use OCA\Polls\Db\IndexManager;
13+
use OCA\Polls\Db\V2\IndexManager;
1414
use OCP\IDBConnection;
1515

1616
/**

lib/Command/Db/FixDB.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2021 Nextcloud contributors
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace OCA\Polls\Command\Db;
10+
11+
use Doctrine\DBAL\Schema\Schema;
12+
use OCA\Polls\Command\Command;
13+
use OCA\Polls\Db\V2\TableManager;
14+
use OCP\IDBConnection;
15+
16+
/**
17+
* @psalm-api
18+
*/
19+
class FixDB extends Command {
20+
protected string $name = parent::NAME_PREFIX . 'db:fix';
21+
protected string $description = 'Fix poll\'s table structure';
22+
protected array $operationHints = [
23+
'All polls tables will get checked and eventually updated against the current schema.',
24+
'',
25+
'Idices will not get updated, created or removed.',
26+
'Note: NO data migration will be executed, so make sure you have a backup of your database.',
27+
];
28+
29+
public function __construct(
30+
private TableManager $tableManager,
31+
private IDBConnection $connection,
32+
private Schema $schema,
33+
) {
34+
parent::__construct();
35+
}
36+
37+
protected function runCommands(): int {
38+
$this->schema = $this->connection->createSchema();
39+
$this->tableManager->setSchema($this->schema);
40+
41+
$this->createOrUpdateSchema();
42+
43+
$this->connection->migrateToSchema($this->schema);
44+
45+
return 0;
46+
}
47+
48+
/**
49+
* Iterate over tables and make sure, the are created or updated
50+
* according to the schema
51+
*/
52+
private function createOrUpdateSchema(): void {
53+
$this->printComment(' - Set db structure');
54+
$messages = $this->tableManager->createTables();
55+
$this->printInfo($messages, ' ');
56+
}
57+
}

lib/Command/Db/Purge.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
namespace OCA\Polls\Command\Db;
1010

1111
use OCA\Polls\Command\Command;
12-
use OCA\Polls\Db\TableManager;
12+
use OCA\Polls\Db\V2\TableManager;
1313
use OCP\IDBConnection;
1414

1515
/**

lib/Command/Db/Rebuild.php

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
namespace OCA\Polls\Command\Db;
1010

1111
use Doctrine\DBAL\Schema\Schema;
12-
use OCA\Polls\Db\TableManager;
13-
use OCA\Polls\Db\IndexManager;
12+
use OCA\Polls\Db\V2\TableManager;
13+
use OCA\Polls\Db\V2\IndexManager;
1414
use OCA\Polls\Command\Command;
1515
use OCP\IDBConnection;
1616

@@ -52,32 +52,33 @@ protected function runCommands(): int {
5252
$this->deleteGenericIndices();
5353
$this->deleteUniqueIndices();
5454
$this->deleteNamedIndices();
55-
56-
$this->printComment('Step 2. Remove all orphaned tables and columns');
57-
$this->removeObsoleteTables();
58-
$this->removeObsoleteColumns();
59-
6055
$this->connection->migrateToSchema($this->schema);
6156

57+
$this->printComment('Step 2. Tidy records before rebuilding the schema');
58+
$this->fixNullish();
59+
$this->cleanTables();
60+
6261
$this->printComment('Step 3. Create or update tables to current shema');
6362
$this->createOrUpdateSchema();
63+
$this->connection->migrateToSchema($this->schema);
6464

65+
$this->printComment('Step 4. Remove orphaned tables and columns');
66+
$this->dropObsoleteTables();
67+
$this->dropObsoleteColumns();
6568
$this->connection->migrateToSchema($this->schema);
6669

67-
$this->printComment('Step 4. set hashes for votes and options');
70+
$this->printComment('Step 5. Validate and fix records');
6871
$this->migrateOptionsToHash();
69-
70-
$this->printComment('Step 5. Remove invalid records (orphaned and duplicates)');
71-
$this->cleanTables();
72+
$this->setLastInteraction();
7273

7374
$this->printComment('Step 6. Recreate unique indices and foreign key constraints');
7475
$this->addForeignKeyConstraints();
7576
$this->addUniqueIndices();
77+
$this->connection->migrateToSchema($this->schema);
7678

79+
$this->printComment('Rebuild finished. The database structure is now up to date.');
7780
$this->printComment('Execute \'occ db:add-missing-indices\' to add missing optional indices');
7881

79-
$this->connection->migrateToSchema($this->schema);
80-
8182
return 0;
8283
}
8384

@@ -90,6 +91,14 @@ private function addForeignKeyConstraints(): void {
9091
$this->printInfo($messages, ' ');
9192
}
9293

94+
private function fixNullish(): void {
95+
$this->printComment(' - Fix nullish values');
96+
$messages = $this->tableManager->fixNullishShares();
97+
$this->printInfo($messages, ' ');
98+
99+
$messages = $this->tableManager->fixNullishPollGroupRelations();
100+
$this->printInfo($messages, ' ');
101+
}
93102
/**
94103
* Create index for $table
95104
*/
@@ -118,7 +127,7 @@ private function migrateOptionsToHash(): void {
118127
$this->printInfo($messages, ' ');
119128
}
120129

121-
private function removeObsoleteColumns(): void {
130+
private function dropObsoleteColumns(): void {
122131
$this->printComment(' - Drop orphaned columns');
123132
$messages = $this->tableManager->removeObsoleteColumns();
124133
$this->printInfo($messages, ' ');
@@ -127,7 +136,7 @@ private function removeObsoleteColumns(): void {
127136
/**
128137
* Remove obsolete tables if they still exist
129138
*/
130-
private function removeObsoleteTables(): void {
139+
private function dropObsoleteTables(): void {
131140
$this->printComment(' - Drop orphaned tables');
132141
$messages = $this->tableManager->removeObsoleteTables();
133142
$this->printInfo($messages, ' ');
@@ -136,8 +145,8 @@ private function removeObsoleteTables(): void {
136145
/**
137146
* Initialize last poll interactions timestamps
138147
*/
139-
public function resetLastInteraction(): void {
140-
$messages = $this->tableManager->resetLastInteraction();
148+
public function setLastInteraction(): void {
149+
$messages = $this->tableManager->setLastInteraction();
141150
$this->printInfo($messages, ' ');
142151
}
143152

@@ -146,9 +155,9 @@ public function resetLastInteraction(): void {
146155
*/
147156
private function cleanTables(): void {
148157
$this->printComment(' - Remove orphaned records');
149-
$orphaned = $this->tableManager->removeOrphaned();
150-
foreach ($orphaned as $table => $count) {
151-
$this->printInfo(" Removed $count orphaned records from $table");
158+
$messages = $this->tableManager->removeOrphaned();
159+
foreach ($messages as $message) {
160+
$this->printInfo(" $message");
152161
}
153162

154163
$this->printComment(' - Remove duplicates');
@@ -187,7 +196,7 @@ private function deleteUniqueIndices(): void {
187196
* remove all named indices
188197
*/
189198
private function deleteNamedIndices(): void {
190-
$this->printComment(' - Remove common indices');
199+
$this->printComment(' - Remove optional indices');
191200
$messages = $this->indexManager->removeNamedIndices();
192201
$this->printInfo($messages, ' - ');
193202
}

lib/Command/Db/RemoveFKConstraints.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use Doctrine\DBAL\Schema\Schema;
1212
use OCA\Polls\Command\Command;
13-
use OCA\Polls\Db\IndexManager;
13+
use OCA\Polls\Db\V2\IndexManager;
1414
use OCP\IDBConnection;
1515

1616
/**

lib/Command/Db/RemoveOptionalIndices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use Doctrine\DBAL\Schema\Schema;
1212
use OCA\Polls\Command\Command;
13-
use OCA\Polls\Db\IndexManager;
13+
use OCA\Polls\Db\V2\IndexManager;
1414
use OCP\IDBConnection;
1515

1616
/**

lib/Command/Db/RemoveUniqueIndices.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use Doctrine\DBAL\Schema\Schema;
1212
use OCA\Polls\Command\Command;
13-
use OCA\Polls\Db\IndexManager;
13+
use OCA\Polls\Db\V2\IndexManager;
1414
use OCP\IDBConnection;
1515

1616
/**

0 commit comments

Comments
 (0)