From d17f43ce3bf23a37dc01899fc7c29f11f3b67b65 Mon Sep 17 00:00:00 2001 From: dartcafe Date: Mon, 14 Aug 2023 00:57:38 +0200 Subject: [PATCH 1/5] change db and index commands Signed-off-by: dartcafe --- lib/Command/Command.php | 24 ++++-- lib/Command/Db/CleanMigrations.php | 18 +++-- lib/Command/Db/CreateIndices.php | 22 ++--- lib/Command/Db/Purge.php | 7 +- lib/Command/Db/Rebuild.php | 101 ++++++++--------------- lib/Command/Db/RemoveIndices.php | 28 +++---- lib/Command/Db/ResetWatch.php | 59 +++++--------- lib/Db/IndexManager.php | 17 ++-- lib/Db/TableManager.php | 125 +++++++++++++++-------------- 9 files changed, 182 insertions(+), 219 deletions(-) diff --git a/lib/Command/Command.php b/lib/Command/Command.php index 08057156c..4740f9a88 100644 --- a/lib/Command/Command.php +++ b/lib/Command/Command.php @@ -91,15 +91,27 @@ protected function setInput(InputInterface $input): void { $this->input = $input; } - protected function printInfo(string $message): void { - $this->output->writeln('' . $message . ''); - } - protected function printNewLine(): void { $this->output->writeln(''); } - protected function printComment(string $message): void { - $this->output->writeln('' . $message. ''); + protected function printInfo(string|array $messages, string $prefix = ''): void { + if (is_array($messages)) { + foreach ($messages as $message) { + $this->output->writeln('' . $prefix . $message . ''); + } + return; + } + $this->output->writeln('' . $prefix . $messages . ''); + } + + protected function printComment(string|array $messages, string $prefix = ''): void { + if (is_array($messages)) { + foreach ($messages as $message) { + $this->output->writeln('' . $prefix . $message . ''); + } + return; + } + $this->output->writeln('' . $prefix . $messages . ''); } } diff --git a/lib/Command/Db/CleanMigrations.php b/lib/Command/Db/CleanMigrations.php index c3102f606..3fef40683 100644 --- a/lib/Command/Db/CleanMigrations.php +++ b/lib/Command/Db/CleanMigrations.php @@ -23,8 +23,10 @@ namespace OCA\Polls\Command\Db; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Command\Command; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; class CleanMigrations extends Command { protected string $name = parent::NAME_PREFIX . 'db:clean-migrations'; @@ -34,17 +36,21 @@ class CleanMigrations extends Command { 'NO data migration will be executed, so make sure you have a backup of your database.', ]; - public function __construct(protected TableManager $tableManager) { + public function __construct( + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, + ) { parent::__construct(); } protected function runCommands(): int { - // remove constraints and indices - $this->printComment('Remove migration entries from migration table'); - // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); $this->tableManager->removeObsoleteMigrations(); - $this->tableManager->migrate(); + + $this->printComment('Remove migration entries from migration table'); + $this->connection->migrateToSchema($this->schema); return 0; } diff --git a/lib/Command/Db/CreateIndices.php b/lib/Command/Db/CreateIndices.php index c8f6a8442..1f52e7408 100644 --- a/lib/Command/Db/CreateIndices.php +++ b/lib/Command/Db/CreateIndices.php @@ -23,8 +23,10 @@ namespace OCA\Polls\Command\Db; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Command\Command; use OCA\Polls\Db\IndexManager; +use OCP\IDBConnection; class CreateIndices extends Command { protected string $name = parent::NAME_PREFIX . 'index:create'; @@ -34,17 +36,22 @@ class CreateIndices extends Command { 'NO data migration will be executed, so make sure you have a backup of your database.', ]; - public function __construct(private IndexManager $indexManager) { + public function __construct( + private IndexManager $indexManager, + private IDBConnection $connection, + private Schema $schema, + ) { parent::__construct(); } protected function runCommands(): int { // create indices and constraints // secure, that the schema is updated to the current status - $this->indexManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); $this->addForeignKeyConstraints(); $this->addIndices(); - $this->indexManager->migrate(); + $this->connection->migrateToSchema($this->schema); return 0; } @@ -55,10 +62,7 @@ protected function runCommands(): int { private function addForeignKeyConstraints(): void { $this->printComment('Add foreign key constraints'); $messages = $this->indexManager->createForeignKeyConstraints(); - - foreach ($messages as $message) { - $this->printInfo(' ' . $message); - } + $this->printInfo($messages, ' - '); } /** @@ -67,8 +71,6 @@ private function addForeignKeyConstraints(): void { private function addIndices(): void { $this->printComment('Add indices'); $messages = $this->indexManager->createIndices(); - foreach ($messages as $message) { - $this->printInfo(' ' . $message); - } + $this->printInfo($messages, ' - '); } } diff --git a/lib/Command/Db/Purge.php b/lib/Command/Db/Purge.php index 4a7a18a31..01341195b 100644 --- a/lib/Command/Db/Purge.php +++ b/lib/Command/Db/Purge.php @@ -26,6 +26,7 @@ use OCA\Polls\Command\Command; use OCA\Polls\Db\IndexManager; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; class Purge extends Command { protected string $name = parent::NAME_PREFIX . 'db:purge'; @@ -40,14 +41,16 @@ class Purge extends Command { ]; public function __construct( - private IndexManager $indexManager, + private IDBConnection $connection, private TableManager $tableManager ) { parent::__construct(); } protected function runCommands(): int { - $this->tableManager->purgeTables(); + $this->tableManager->setConnection($this->connection); + $messages = $this->tableManager->purgeTables(); + $this->printInfo($messages, ' - '); return 0; } } diff --git a/lib/Command/Db/Rebuild.php b/lib/Command/Db/Rebuild.php index 80d5ed579..5df4a5c49 100644 --- a/lib/Command/Db/Rebuild.php +++ b/lib/Command/Db/Rebuild.php @@ -23,9 +23,11 @@ namespace OCA\Polls\Command\Db; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\TableManager; use OCA\Polls\Db\IndexManager; use OCA\Polls\Command\Command; +use OCP\IDBConnection; class Rebuild extends Command { protected string $name = parent::NAME_PREFIX . 'db:rebuild'; @@ -38,48 +40,42 @@ class Rebuild extends Command { public function __construct( private TableManager $tableManager, private IndexManager $indexManager, + private IDBConnection $connection, + private Schema $schema, ) { parent::__construct(); } protected function runCommands(): int { - // remove constraints and indices + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); + $this->tableManager->setSchema($this->schema); + $this->printComment('Step 1. Remove all indices and foreign key constraints'); - // secure, that the schema is updated to the current status - $this->indexManager->refreshSchema(); $this->deleteForeignKeyConstraints(); $this->deleteGenericIndices(); $this->deleteUniqueIndices(); - $this->indexManager->migrate(); - // remove old tables and columns $this->printComment('Step 2. Remove all orphaned tables and columns'); - // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); $this->removeObsoleteTables(); $this->removeObsoleteColumns(); - $this->tableManager->migrate(); - // validate and fix/create current table layout + $this->connection->migrateToSchema($this->schema); + $this->printComment('Step 3. Create or update tables to current shema'); $this->createOrUpdateSchema(); - $this->tableManager->migrate(); - // validate and fix/create current table layout $this->printComment('Step 4. set hashes for votes and options'); $this->migrateOptionsToHash(); - // Remove orphaned records and duplicates $this->printComment('Step 5. Remove invalid records (orphaned and duplicates)'); $this->cleanTables(); - // recreate indices and constraints $this->printComment('Step 6. Recreate indices and foreign key constraints'); - // secure, that the schema is updated to the current status - $this->indexManager->refreshSchema(); $this->addForeignKeyConstraints(); $this->addIndices(); - $this->indexManager->migrate(); + + $this->connection->migrateToSchema($this->schema); return 0; } @@ -88,23 +84,18 @@ protected function runCommands(): int { * add an on delete fk contraint to all tables referencing the main polls table */ private function addForeignKeyConstraints(): void { - $this->printComment('- Add foreign key constraints'); + $this->printComment(' - Add foreign key constraints'); $messages = $this->indexManager->createForeignKeyConstraints(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** * Create index for $table */ private function addIndices(): void { - $this->printComment('- Add indices'); + $this->printComment(' - Add indices'); $messages = $this->indexManager->createIndices(); - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** @@ -112,42 +103,33 @@ private function addIndices(): void { * according to the schema */ private function createOrUpdateSchema(): void { - $this->printComment('- Set db structure'); + $this->printComment(' - Set db structure'); $messages = $this->tableManager->createTables(); - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** * Add or update hash for votes and options */ private function migrateOptionsToHash(): void { - $this->printComment('- add or update hashes'); + $this->printComment(' - Add or update hashes'); $messages = $this->tableManager->migrateOptionsToHash(); - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } private function removeObsoleteColumns(): void { - $this->printComment('- Drop orphaned columns'); + $this->printComment(' - Drop orphaned columns'); $messages = $this->tableManager->removeObsoleteColumns(); - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** * Remove obsolete tables if they still exist */ private function removeObsoleteTables(): void { - $this->printComment(' Drop orphaned tables'); + $this->printComment(' - Drop orphaned tables'); $messages = $this->tableManager->removeObsoleteTables(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** @@ -155,57 +137,42 @@ private function removeObsoleteTables(): void { */ public function resetLastInteraction(): void { $messages = $this->tableManager->resetLastInteraction(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** * Remove obsolete tables if they still exist */ private function cleanTables(): void { - $this->printComment(' Remove orphaned records'); + $this->printComment(' - Remove orphaned records'); $this->tableManager->removeOrphaned(); - $this->printComment(' Remove duplicates'); + $this->printComment(' - Remove duplicates'); $messages = $this->tableManager->deleteAllDuplicates(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } private function deleteForeignKeyConstraints(): void { - $this->printComment('- Remove foreign key constraints'); + $this->printComment(' - Remove foreign key constraints'); $messages = $this->indexManager->removeAllForeignKeyConstraints(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** * add an on delete fk contraint to all tables referencing the main polls table */ private function deleteGenericIndices(): void { - $this->printComment('- Remove generic indices'); + $this->printComment(' - Remove generic indices'); $messages = $this->indexManager->removeAllGenericIndices(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } /** * add an on delete fk contraint to all tables referencing the main polls table */ private function deleteUniqueIndices(): void { - $this->printComment('- Remove unique indices'); + $this->printComment(' - Remove unique indices'); $messages = $this->indexManager->removeAllUniqueIndices(); - - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' '); } } diff --git a/lib/Command/Db/RemoveIndices.php b/lib/Command/Db/RemoveIndices.php index 5b1923e20..a4948e1ee 100644 --- a/lib/Command/Db/RemoveIndices.php +++ b/lib/Command/Db/RemoveIndices.php @@ -23,8 +23,10 @@ namespace OCA\Polls\Command\Db; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Command\Command; use OCA\Polls\Db\IndexManager; +use OCP\IDBConnection; class RemoveIndices extends Command { protected string $name = parent::NAME_PREFIX . 'index:remove'; @@ -34,16 +36,22 @@ class RemoveIndices extends Command { 'NO data migration will be executed, so make sure you have a backup of your database.', ]; - public function __construct(private IndexManager $indexManager) { + public function __construct( + private IndexManager $indexManager, + private IDBConnection $connection, + private Schema $schema, + ) { parent::__construct(); } protected function runCommands(): int { // remove constraints and indices + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); $this->deleteForeignKeyConstraints(); $this->deleteGenericIndices(); $this->deleteUniqueIndices(); - $this->indexManager->migrate(); + $this->connection->migrateToSchema($this->schema); return 0; } @@ -53,10 +61,7 @@ protected function runCommands(): int { private function deleteForeignKeyConstraints(): void { $this->printComment('Remove foreign key constraints and generic indices'); $messages = $this->indexManager->removeAllForeignKeyConstraints(); - - foreach ($messages as $message) { - $this->printInfo(' ' . $message); - } + $this->printInfo($messages, ' - '); } /** @@ -65,10 +70,7 @@ private function deleteForeignKeyConstraints(): void { private function deleteGenericIndices(): void { $this->printComment('Remove generic indices'); $messages = $this->indexManager->removeAllGenericIndices(); - - foreach ($messages as $message) { - $this->printInfo(' ' . $message); - } + $this->printInfo($messages, ' - '); } /** @@ -77,9 +79,5 @@ private function deleteGenericIndices(): void { private function deleteUniqueIndices(): void { $this->printComment('Remove unique indices'); $messages = $this->indexManager->removeAllUniqueIndices(); - - foreach ($messages as $message) { - $this->printInfo(' ' . $message); - } - } + $this->printInfo($messages, ' - '); } } diff --git a/lib/Command/Db/ResetWatch.php b/lib/Command/Db/ResetWatch.php index d9befb4fa..0092435c9 100644 --- a/lib/Command/Db/ResetWatch.php +++ b/lib/Command/Db/ResetWatch.php @@ -23,11 +23,13 @@ namespace OCA\Polls\Command\Db; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Command\Command; use OCA\Polls\Db\IndexManager; use OCA\Polls\Db\TableManager; use OCA\Polls\Db\Watch; use OCA\Polls\Migration\TableSchema; +use OCP\IDBConnection; class ResetWatch extends Command { protected string $name = parent::NAME_PREFIX . 'db:reset-watch'; @@ -39,55 +41,32 @@ class ResetWatch extends Command { public function __construct( private IndexManager $indexManager, - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, ) { parent::__construct(); } protected function runCommands(): int { - $this->resetWatch(); - $this->tableManager->migrate(); - - $this->indexManager->refreshSchema(); - $this->createIndex(); - $this->indexManager->migrate(); + $tableName = Watch::TABLE; + $indexValues = TableSchema::UNIQUE_INDICES[$tableName]; + $columns = TableSchema::TABLES[$tableName]; - return 0; - } + $messages = $this->tableManager->removeWatch(); + $this->printInfo($messages, ' - '); - /** - * Iterate over tables and make sure, the are created or updated - * according to the schema - */ - private function resetWatch(): void { - $messages = []; + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); + $this->tableManager->setSchema($this->schema); - $this->printComment('- Reset Watch table'); - // Remove all indices - // drop and add watch with current schema - $messages = array_merge($messages, $this->tableManager->resetWatch()); + $messages = $this->tableManager->createTable($tableName, $columns); + $messages[] = $this->indexManager->createIndex($tableName, $indexValues['name'], $indexValues['columns'], $indexValues['unique']); - // add indices again - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } - } - /** - * Iterate over tables and make sure, the are created or updated - * according to the schema - */ - private function createIndex(): void { - $tableName = Watch::TABLE; - $values = TableSchema::UNIQUE_INDICES[$tableName]; - $messages = []; + $this->connection->migrateToSchema($this->schema); - $this->printComment('- Create watch index'); - // Remove all indices - $messages[] = $this->indexManager->createIndex($tableName, $values['name'], $values['columns'], $values['unique']); - - // add indices again - foreach ($messages as $message) { - $this->printInfo(' - ' . $message); - } + $this->printInfo($messages, ' - '); + return 0; } + } diff --git a/lib/Db/IndexManager.php b/lib/Db/IndexManager.php index df3dd8030..bcf14a848 100644 --- a/lib/Db/IndexManager.php +++ b/lib/Db/IndexManager.php @@ -30,26 +30,19 @@ use OCP\IDBConnection; class IndexManager { - private Schema $schema; + private string $dbPrefix; public function __construct( private IConfig $config, - protected IDBConnection $connection + private IDBConnection $connection, + private Schema $schema, ) { - $this->schema = $this->connection->createSchema(); $this->dbPrefix = $this->config->getSystemValue('dbtableprefix', 'oc_'); } - /** - * execute the migration - */ - public function migrate(): void { - $this->connection->migrateToSchema($this->schema); - } - - public function refreshSchema(): void { - $this->schema = $this->connection->createSchema(); + public function setSchema(Schema &$schema): void { + $this->schema = $schema; } /** diff --git a/lib/Db/TableManager.php b/lib/Db/TableManager.php index 02e496b8d..4c306cc87 100644 --- a/lib/Db/TableManager.php +++ b/lib/Db/TableManager.php @@ -36,7 +36,7 @@ use Psr\Log\LoggerInterface; class TableManager { - private Schema $schema; + private string $dbPrefix; public function __construct( @@ -45,22 +45,18 @@ public function __construct( private LoggerInterface $logger, private OptionMapper $optionMapper, private VoteMapper $voteMapper, + private Schema $schema, private WatchMapper $watchMapper, ) { - $this->schema = $this->connection->createSchema(); $this->dbPrefix = $this->config->getSystemValue('dbtableprefix', 'oc_'); } - /** - * execute the migration - */ - public function migrate(): void { - $this->connection->migrateToSchema($this->schema); + public function setSchema(Schema &$schema): void { + $this->schema = $schema; } - public function refreshSchema(): Schema { - $this->schema = $this->connection->createSchema(); - return $this->schema; + public function setConnection(IDBConnection &$connection): void { + $this->connection = $connection; } /** @@ -70,7 +66,6 @@ public function refreshSchema(): Schema { */ public function purgeTables(): array { $messages = []; - // drop all child tables foreach (TableSchema::FK_CHILD_TABLES as $tableName) { if ($this->connection->tableExists($tableName)) { @@ -118,7 +113,7 @@ public function purgeTables(): array { $messages[] = ''; $messages[] = 'Please call \'occ app:remove polls\' now!'; - $this->refreshSchema(); + // $this->refreshSchema(); return $messages; } @@ -133,13 +128,6 @@ public function resetWatch(): array { $tableName = $this->dbPrefix . Watch::TABLE; $columns = TableSchema::TABLES[Watch::TABLE]; - if ($this->connection->tableExists(Watch::TABLE)) { - $this->connection->dropTable(Watch::TABLE); - $messages[] = 'Dropped ' . $tableName; - } - - $this->refreshSchema(); - $table = $this->schema->createTable($tableName); $messages[] = 'Creating table ' . $tableName; @@ -157,43 +145,71 @@ public function resetWatch(): array { * * @psalm-return non-empty-list */ - public function createTables(): array { + public function removeWatch(): array { $messages = []; - - foreach (TableSchema::TABLES as $tableName => $columns) { - $tableName = $this->dbPrefix . $tableName; + $tableName = $this->dbPrefix . Watch::TABLE; - if ($this->schema->hasTable($tableName)) { - $table = $this->schema->getTable($tableName); - $messages[] = 'Validating table ' . $table->getName(); - $tableCreated = false; - } else { - $table = $this->schema->createTable($tableName); - $tableCreated = true; - $messages[] = 'Creating table ' . $table->getName(); - } + if ($this->connection->tableExists(Watch::TABLE)) { + $this->connection->dropTable(Watch::TABLE); + $messages[] = 'Dropped ' . $tableName; + } + return $messages; + } - foreach ($columns as $columnName => $columnDefinition) { - if ($table->hasColumn($columnName)) { - $column = $table->getColumn($columnName); - if ($column->getType()->getName() !== $columnDefinition['type']) { - $messages[] = 'Migrated type of ' . $table->getName() . '[\'' . $columnName . '\'] from ' . $column->getType()->getName() . ' to ' . $columnDefinition['type']; - $column->setType(Type::getType($columnDefinition['type'])); - } - $column->setOptions($columnDefinition['options']); + /** + * @return string[] + * + * @psalm-return non-empty-list + */ + public function createTable(string $tableName, array $columns): array { + $messages = []; + + $tableName = $this->dbPrefix . $tableName; - // force change to current options definition - $table->changeColumn($columnName, $columnDefinition['options']); - } else { - $table->addColumn($columnName, $columnDefinition['type'], $columnDefinition['options']); - $messages[] = 'Added ' . $table->getName() . ', ' . $columnName . ' (' . $columnDefinition['type'] . ')'; + if ($this->schema->hasTable($tableName)) { + $table = $this->schema->getTable($tableName); + $messages[] = 'Validating table ' . $table->getName(); + $tableCreated = false; + } else { + $table = $this->schema->createTable($tableName); + $tableCreated = true; + $messages[] = 'Creating table ' . $table->getName(); + } + + foreach ($columns as $columnName => $columnDefinition) { + if ($table->hasColumn($columnName)) { + $column = $table->getColumn($columnName); + if ($column->getType()->getName() !== $columnDefinition['type']) { + $messages[] = 'Migrated type of ' . $table->getName() . '[\'' . $columnName . '\'] from ' . $column->getType()->getName() . ' to ' . $columnDefinition['type']; + $column->setType(Type::getType($columnDefinition['type'])); } - } + $column->setOptions($columnDefinition['options']); - if ($tableCreated) { - $table->setPrimaryKey(['id']); + // force change to current options definition + $table->changeColumn($columnName, $columnDefinition['options']); + } else { + $table->addColumn($columnName, $columnDefinition['type'], $columnDefinition['options']); + $messages[] = 'Added ' . $table->getName() . ', ' . $columnName . ' (' . $columnDefinition['type'] . ')'; } } + + if ($tableCreated) { + $table->setPrimaryKey(['id']); + } + return $messages; + } + + /** + * @return string[] + * + * @psalm-return non-empty-list + */ + public function createTables(): array { + $messages = []; + + foreach (TableSchema::TABLES as $tableName => $columns) { + $messages = array_merge($messages, $this->createTable($tableName, $columns)); + } return $messages; } @@ -219,19 +235,6 @@ public function removeObsoleteTables(): array { return $messages; } - /** - * Remove obsolete tables if they still exist - */ - public function removeWatch(): array { - $tableName = Watch::TABLE; - $messages = []; - if ($this->connection->tableExists($tableName)) { - $this->connection->dropTable($tableName); - $messages[] = 'Dropped ' . $this->dbPrefix . $tableName; - } - return $messages; - } - public function removeObsoleteColumns(): array { $messages = []; $dropped = false; From ca88921cc045ea12fb99a543cb05d7e1e0ec3e49 Mon Sep 17 00:00:00 2001 From: dartcafe Date: Mon, 14 Aug 2023 01:14:52 +0200 Subject: [PATCH 2/5] chenge repair steps Signed-off-by: dartcafe --- lib/Migration/FixVotes.php | 13 ++++++++++--- lib/Migration/RepairSteps/CreateIndices.php | 10 ++++++++-- lib/Migration/RepairSteps/CreateTables.php | 13 ++++++++++--- .../RepairSteps/DeleteInvalidRecords.php | 10 +++++++--- .../RepairSteps/DropOrphanedColumns.php | 10 ++++++++-- .../RepairSteps/DropOrphanedTables.php | 12 ++++++++++-- lib/Migration/RepairSteps/Install.php | 12 +++++++++--- lib/Migration/RepairSteps/RemoveIndices.php | 19 +++++++++---------- .../RepairSteps/RemoveObsoleteMigrations.php | 11 +++++++---- lib/Migration/RepairSteps/UpdateHashes.php | 10 +++++++--- .../RepairSteps/UpdateInteraction.php | 6 +++++- 11 files changed, 90 insertions(+), 36 deletions(-) diff --git a/lib/Migration/FixVotes.php b/lib/Migration/FixVotes.php index aa3914118..498a1e924 100644 --- a/lib/Migration/FixVotes.php +++ b/lib/Migration/FixVotes.php @@ -24,12 +24,18 @@ namespace OCA\Polls\Migration; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class FixVotes implements IRepairStep { - public function __construct(private TableManager $tableManager) { + public function __construct( + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, + ) { } /* @@ -44,8 +50,9 @@ public function getName() { */ public function run(IOutput $output): void { // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); $this->tableManager->fixVotes(); - $this->tableManager->migrate(); + $this->connection->migrateToSchema($this->schema); } } diff --git a/lib/Migration/RepairSteps/CreateIndices.php b/lib/Migration/RepairSteps/CreateIndices.php index 08b70fbf6..40c9cb46d 100644 --- a/lib/Migration/RepairSteps/CreateIndices.php +++ b/lib/Migration/RepairSteps/CreateIndices.php @@ -24,13 +24,17 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\IndexManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class CreateIndices implements IRepairStep { public function __construct( private IndexManager $indexManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -41,11 +45,13 @@ public function getName() { public function run(IOutput $output): void { $messages = []; // secure, that the schema is updated to the current status - $this->indexManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); $messages = array_merge($messages, $this->indexManager->createForeignKeyConstraints()); $messages = array_merge($messages, $this->indexManager->createIndices()); - $this->indexManager->migrate(); + $this->connection->migrateToSchema($this->schema); + foreach ($messages as $message) { $output->info($message); } diff --git a/lib/Migration/RepairSteps/CreateTables.php b/lib/Migration/RepairSteps/CreateTables.php index 44a601001..269978b24 100644 --- a/lib/Migration/RepairSteps/CreateTables.php +++ b/lib/Migration/RepairSteps/CreateTables.php @@ -24,13 +24,17 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class CreateTables implements IRepairStep { public function __construct( - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -45,9 +49,12 @@ public function run(IOutput $output): void { $output->info($message); } // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); + $messages = $this->tableManager->createTables(); - $this->tableManager->migrate(); + + $this->connection->migrateToSchema($this->schema); foreach ($messages as $message) { $output->info($message); diff --git a/lib/Migration/RepairSteps/DeleteInvalidRecords.php b/lib/Migration/RepairSteps/DeleteInvalidRecords.php index 83733f7e3..231e6e80f 100644 --- a/lib/Migration/RepairSteps/DeleteInvalidRecords.php +++ b/lib/Migration/RepairSteps/DeleteInvalidRecords.php @@ -24,6 +24,7 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\Poll; use OCA\Polls\Db\TableManager; use OCA\Polls\Db\WatchMapper; @@ -39,7 +40,8 @@ class DeleteInvalidRecords implements IRepairStep { public function __construct( private IDBConnection $connection, private WatchMapper $watchMapper, - private TableManager $tableManager + private TableManager $tableManager, + private Schema $schema, ) { } @@ -49,12 +51,14 @@ public function getName():string { public function run(IOutput $output):void { if ($this->connection->tableExists(Poll::TABLE)) { - // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); $this->tableManager->removeOrphaned(); $this->tableManager->deleteAllDuplicates(); + $this->connection->migrateToSchema($this->schema); + $this->watchMapper->deleteOldEntries(time()); } } diff --git a/lib/Migration/RepairSteps/DropOrphanedColumns.php b/lib/Migration/RepairSteps/DropOrphanedColumns.php index 5a7e22eab..13623e2fe 100644 --- a/lib/Migration/RepairSteps/DropOrphanedColumns.php +++ b/lib/Migration/RepairSteps/DropOrphanedColumns.php @@ -24,13 +24,17 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class DropOrphanedColumns implements IRepairStep { public function __construct( - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -40,8 +44,10 @@ public function getName() { public function run(IOutput $output): void { // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); $messages = $this->tableManager->removeObsoleteColumns(); + $this->connection->migrateToSchema($this->schema); foreach ($messages as $message) { $output->info($message); diff --git a/lib/Migration/RepairSteps/DropOrphanedTables.php b/lib/Migration/RepairSteps/DropOrphanedTables.php index 59350b574..14b237a93 100644 --- a/lib/Migration/RepairSteps/DropOrphanedTables.php +++ b/lib/Migration/RepairSteps/DropOrphanedTables.php @@ -24,13 +24,17 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class DropOrphanedTables implements IRepairStep { public function __construct( - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -40,8 +44,12 @@ public function getName() { public function run(IOutput $output): void { // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); + $messages = $this->tableManager->removeObsoleteTables(); + + $this->connection->migrateToSchema($this->schema); foreach ($messages as $message) { $output->info($message); diff --git a/lib/Migration/RepairSteps/Install.php b/lib/Migration/RepairSteps/Install.php index ee6e756d6..be3b07832 100644 --- a/lib/Migration/RepairSteps/Install.php +++ b/lib/Migration/RepairSteps/Install.php @@ -24,13 +24,17 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\IndexManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class Install implements IRepairStep { public function __construct( private IndexManager $indexManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -40,12 +44,14 @@ public function getName() { public function run(IOutput $output): void { $messages = []; - // secure, that the schema is updated to the current status - $this->indexManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); $messages = array_merge($messages, $this->indexManager->createForeignKeyConstraints()); $messages = array_merge($messages, $this->indexManager->createIndices()); - $this->indexManager->migrate(); + + $this->connection->migrateToSchema($this->schema); + foreach ($messages as $message) { $output->info($message); } diff --git a/lib/Migration/RepairSteps/RemoveIndices.php b/lib/Migration/RepairSteps/RemoveIndices.php index 6ecce3f27..5cbec5ae0 100644 --- a/lib/Migration/RepairSteps/RemoveIndices.php +++ b/lib/Migration/RepairSteps/RemoveIndices.php @@ -23,7 +23,9 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\IndexManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; @@ -34,7 +36,9 @@ */ class RemoveIndices implements IRepairStep { public function __construct( - private IndexManager $indexManager + private IndexManager $indexManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -49,24 +53,19 @@ public function getName() { * @inheritdoc */ public function run(IOutput $output): void { - // secure, that the schema is updated to the current status - $this->indexManager->refreshSchema(); + $this->schema = $this->connection->createSchema(); + $this->indexManager->setSchema($this->schema); + $messages = $this->indexManager->removeAllForeignKeyConstraints(); foreach ($messages as $message) { $output->info($message); } - // $messages = $this->indexManager->removeAllGenericIndices(); - // foreach ($messages as $message) { - // $output->info($message); - // } - $messages = $this->indexManager->removeAllUniqueIndices(); foreach ($messages as $message) { $output->info($message); } - $this->indexManager->migrate(); - $this->indexManager->refreshSchema(); + $this->connection->migrateToSchema($this->schema); } } diff --git a/lib/Migration/RepairSteps/RemoveObsoleteMigrations.php b/lib/Migration/RepairSteps/RemoveObsoleteMigrations.php index 59fa6d72f..af15e9039 100644 --- a/lib/Migration/RepairSteps/RemoveObsoleteMigrations.php +++ b/lib/Migration/RepairSteps/RemoveObsoleteMigrations.php @@ -23,7 +23,9 @@ namespace OCA\Polls\Migration\RepairSteps; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; @@ -34,7 +36,9 @@ */ class RemoveObsoleteMigrations implements IRepairStep { public function __construct( - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -49,13 +53,12 @@ public function getName() { * @inheritdoc */ public function run(IOutput $output): void { - // secure, that the schema is updated to the current status - $this->tableManager->refreshSchema(); + $this->tableManager->setConnection($this->connection); + $messages = $this->tableManager->removeObsoleteMigrations(); foreach ($messages as $message) { $output->info($message); } - $this->tableManager->migrate(); } } diff --git a/lib/Migration/RepairSteps/UpdateHashes.php b/lib/Migration/RepairSteps/UpdateHashes.php index bd1705ce3..bd8c18a77 100644 --- a/lib/Migration/RepairSteps/UpdateHashes.php +++ b/lib/Migration/RepairSteps/UpdateHashes.php @@ -25,24 +25,28 @@ namespace OCA\Polls\Migration\RepairSteps; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class UpdateHashes implements IRepairStep { public function __construct( - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, ) { } public function getName() { - return 'Polls - Create hashes vor votes and options'; + return 'Polls - Create hashes for votes and options'; } public function run(IOutput $output): void { - // Add hashes to votes and options + $this->tableManager->setConnection($this->connection); + $messages = $this->tableManager->migrateOptionsToHash(); foreach ($messages as $message) { $output->info($message); } + } } diff --git a/lib/Migration/RepairSteps/UpdateInteraction.php b/lib/Migration/RepairSteps/UpdateInteraction.php index 4258694f5..3d267e52f 100644 --- a/lib/Migration/RepairSteps/UpdateInteraction.php +++ b/lib/Migration/RepairSteps/UpdateInteraction.php @@ -25,12 +25,14 @@ namespace OCA\Polls\Migration\RepairSteps; use OCA\Polls\Db\TableManager; +use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\IRepairStep; class UpdateInteraction implements IRepairStep { public function __construct( - private TableManager $tableManager + private TableManager $tableManager, + private IDBConnection $connection, ) { } @@ -39,6 +41,8 @@ public function getName() { } public function run(IOutput $output): void { + $this->tableManager->setConnection($this->connection); + $messages = $this->tableManager->resetLastInteraction(); foreach ($messages as $message) { $output->info($message); From 216ad8edadc7f563832b3438576ab48beec41b12 Mon Sep 17 00:00:00 2001 From: dartcafe Date: Mon, 14 Aug 2023 16:50:16 +0200 Subject: [PATCH 3/5] cs-fix Signed-off-by: dartcafe --- lib/Command/Db/Purge.php | 1 - lib/Command/Db/RemoveIndices.php | 3 ++- lib/Db/TableManager.php | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/Command/Db/Purge.php b/lib/Command/Db/Purge.php index 01341195b..aec8b4589 100644 --- a/lib/Command/Db/Purge.php +++ b/lib/Command/Db/Purge.php @@ -24,7 +24,6 @@ namespace OCA\Polls\Command\Db; use OCA\Polls\Command\Command; -use OCA\Polls\Db\IndexManager; use OCA\Polls\Db\TableManager; use OCP\IDBConnection; diff --git a/lib/Command/Db/RemoveIndices.php b/lib/Command/Db/RemoveIndices.php index a4948e1ee..4fc228919 100644 --- a/lib/Command/Db/RemoveIndices.php +++ b/lib/Command/Db/RemoveIndices.php @@ -79,5 +79,6 @@ private function deleteGenericIndices(): void { private function deleteUniqueIndices(): void { $this->printComment('Remove unique indices'); $messages = $this->indexManager->removeAllUniqueIndices(); - $this->printInfo($messages, ' - '); } + $this->printInfo($messages, ' - '); + } } diff --git a/lib/Db/TableManager.php b/lib/Db/TableManager.php index 4c306cc87..8f2609e98 100644 --- a/lib/Db/TableManager.php +++ b/lib/Db/TableManager.php @@ -142,8 +142,6 @@ public function resetWatch(): array { /** * @return string[] - * - * @psalm-return non-empty-list */ public function removeWatch(): array { $messages = []; From a55184ad8de442c040aed90ce8b635cfb20fc10f Mon Sep 17 00:00:00 2001 From: dartcafe Date: Mon, 14 Aug 2023 16:51:19 +0200 Subject: [PATCH 4/5] change migration Signed-off-by: dartcafe --- lib/Migration/Version050100Date20230515083001.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/Migration/Version050100Date20230515083001.php b/lib/Migration/Version050100Date20230515083001.php index 5a32d36eb..bda1f9aed 100644 --- a/lib/Migration/Version050100Date20230515083001.php +++ b/lib/Migration/Version050100Date20230515083001.php @@ -23,6 +23,7 @@ namespace OCA\Polls\Migration; +use Doctrine\DBAL\Schema\Schema; use OCA\Polls\Db\Poll; use OCA\Polls\Db\TableManager; use OCP\IDBConnection; @@ -38,7 +39,8 @@ class Version050100Date20230515083001 extends SimpleMigrationStep { public function __construct( private TableManager $tableManager, - private IDBConnection $db, + private IDBConnection $connection, + private Schema $schema, ) { } @@ -47,8 +49,12 @@ public function __construct( */ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { // Create tables, as defined in TableSchema or fix column definitions + $this->schema = $this->connection->createSchema(); + $this->tableManager->setSchema($this->schema); + $messages = $this->tableManager->createTables(); - $this->tableManager->migrate(); + + $this->connection->migrateToSchema($this->schema); foreach ($messages as $message) { $output->info('Polls - ' . $message); @@ -62,7 +68,7 @@ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $op */ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) { $now = time(); - $query = $this->db->getQueryBuilder(); + $query = $this->connection->getQueryBuilder(); $query->update(Poll::TABLE) ->set('last_interaction', $query->createNamedParameter($now)) ->where($query->expr()->eq('last_interaction', $query->createNamedParameter(0))); From 9fbfc754357715a8a814100284ce5c83f41f8d2a Mon Sep 17 00:00:00 2001 From: dartcafe Date: Mon, 14 Aug 2023 23:15:18 +0200 Subject: [PATCH 5/5] fix #2980 and fix rebuild Signed-off-by: dartcafe --- lib/Command/Db/Rebuild.php | 4 +- .../Version050100Date20230515083001.php | 76 ++++++++++++++++--- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/lib/Command/Db/Rebuild.php b/lib/Command/Db/Rebuild.php index 5df4a5c49..20e2abcf9 100644 --- a/lib/Command/Db/Rebuild.php +++ b/lib/Command/Db/Rebuild.php @@ -61,10 +61,12 @@ protected function runCommands(): int { $this->removeObsoleteColumns(); $this->connection->migrateToSchema($this->schema); - + $this->printComment('Step 3. Create or update tables to current shema'); $this->createOrUpdateSchema(); + $this->connection->migrateToSchema($this->schema); + $this->printComment('Step 4. set hashes for votes and options'); $this->migrateOptionsToHash(); diff --git a/lib/Migration/Version050100Date20230515083001.php b/lib/Migration/Version050100Date20230515083001.php index bda1f9aed..3eedefbcf 100644 --- a/lib/Migration/Version050100Date20230515083001.php +++ b/lib/Migration/Version050100Date20230515083001.php @@ -23,9 +23,10 @@ namespace OCA\Polls\Migration; -use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Types\Type; use OCA\Polls\Db\Poll; use OCA\Polls\Db\TableManager; +use OCP\DB\ISchemaWrapper; use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; @@ -37,10 +38,11 @@ * Version: jj = major version, mm = minor, pp = patch */ class Version050100Date20230515083001 extends SimpleMigrationStep { + private ISchemaWrapper $schema; + public function __construct( private TableManager $tableManager, private IDBConnection $connection, - private Schema $schema, ) { } @@ -48,19 +50,14 @@ public function __construct( * $schemaClosure The `\Closure` returns a `ISchemaWrapper` */ public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { - // Create tables, as defined in TableSchema or fix column definitions - $this->schema = $this->connection->createSchema(); - $this->tableManager->setSchema($this->schema); - - $messages = $this->tableManager->createTables(); - - $this->connection->migrateToSchema($this->schema); + $this->schema = $schemaClosure(); + $messages = $this->createTables(); foreach ($messages as $message) { $output->info('Polls - ' . $message); }; - return null; + return $this->schema; } /** @@ -74,4 +71,63 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array ->where($query->expr()->eq('last_interaction', $query->createNamedParameter(0))); $query->executeStatement(); } + + + /** + * @return string[] + * + * @psalm-return non-empty-list + */ + public function createTable(string $tableName, array $columns): array { + $messages = []; + + if ($this->schema->hasTable($tableName)) { + $table = $this->schema->getTable($tableName); + $messages[] = 'Validating table ' . $table->getName(); + $tableCreated = false; + } else { + $table = $this->schema->createTable($tableName); + $tableCreated = true; + $messages[] = 'Creating table ' . $table->getName(); + } + + foreach ($columns as $columnName => $columnDefinition) { + if ($table->hasColumn($columnName)) { + $column = $table->getColumn($columnName); + if ($column->getType()->getName() !== $columnDefinition['type']) { + $messages[] = 'Migrated type of ' . $table->getName() . '[\'' . $columnName . '\'] from ' . $column->getType()->getName() . ' to ' . $columnDefinition['type']; + $column->setType(Type::getType($columnDefinition['type'])); + } + $column->setOptions($columnDefinition['options']); + + // force change to current options definition + $table->changeColumn($columnName, $columnDefinition['options']); + } else { + $table->addColumn($columnName, $columnDefinition['type'], $columnDefinition['options']); + $messages[] = 'Added ' . $table->getName() . ', ' . $columnName . ' (' . $columnDefinition['type'] . ')'; + } + } + + if ($tableCreated) { + $table->setPrimaryKey(['id']); + } + return $messages; + } + + /** + * @return string[] + * + * @psalm-return non-empty-list + */ + public function createTables(): array { + $messages = []; + + foreach (TableSchema::TABLES as $tableName => $columns) { + $messages = array_merge($messages, $this->createTable($tableName, $columns)); + } + return $messages; + } + + + }