diff --git a/appinfo/info.xml b/appinfo/info.xml index 2e73f5125..1141c153b 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -9,7 +9,7 @@ Photos Your memories under your control Your memories under your control - 3.0.1 + 3.0.2 agpl John Molakvoæ Photos @@ -22,7 +22,6 @@ https://github.com/nextcloud/photos https://github.com/nextcloud/photos/issues https://github.com/nextcloud/photos.git - diff --git a/lib/Migration/Version30000Date20240417075404.php b/lib/Migration/Version30000Date20240417075405.php similarity index 75% rename from lib/Migration/Version30000Date20240417075404.php rename to lib/Migration/Version30000Date20240417075405.php index 2ec038d22..ed3c59b9a 100644 --- a/lib/Migration/Version30000Date20240417075404.php +++ b/lib/Migration/Version30000Date20240417075405.php @@ -11,6 +11,7 @@ use Closure; use OCP\DB\ISchemaWrapper; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\Migration\IOutput; use OCP\Migration\SimpleMigrationStep; @@ -18,7 +19,7 @@ /** * Migrate the photosSourceFolder user config to photosSourceFolders */ -class Version30000Date20240417075404 extends SimpleMigrationStep { +class Version30000Date20240417075405 extends SimpleMigrationStep { public function __construct( private IDBConnection $db, ) { @@ -36,13 +37,26 @@ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array ->where($select->expr()->eq('appid', $select->expr()->literal('photos'))) ->andWhere($select->expr()->eq('configkey', $select->expr()->literal('photosSourceFolders'))); + $result = $select->executeQuery(); + $alreadyMigrated = array_map(static fn (array $row) => $row['userid'], $result->fetchAll()); + $result->closeCursor(); + // Remove old entries for users who already have the new one $delete = $this->db->getQueryBuilder(); $delete->delete('preferences') ->where($delete->expr()->eq('appid', $delete->expr()->literal('photos'))) ->andWhere($delete->expr()->eq('configkey', $delete->expr()->literal('photosSourceFolder'))) - ->andWhere($delete->expr()->in('userid', $delete->createFunction($select->getSQL()))) - ->executeStatement(); + ->andWhere($delete->expr()->in( + 'userid', + $delete->createParameter('chunk'), + IQueryBuilder::PARAM_STR + )); + + $chunks = array_chunk($alreadyMigrated, 1000); + foreach ($chunks as $chunk) { + $delete->setParameter('chunk', $chunk, IQueryBuilder::PARAM_STR_ARRAY); + $delete->executeStatement(); + } // Update remaining old entries to new ones $update = $this->db->getQueryBuilder(); diff --git a/tests/Migration/Version30000Date20240417075405Test.php b/tests/Migration/Version30000Date20240417075405Test.php new file mode 100644 index 000000000..4d0d73055 --- /dev/null +++ b/tests/Migration/Version30000Date20240417075405Test.php @@ -0,0 +1,102 @@ +connection = \OCP\Server::get(IDBConnection::class); + } + + protected function tearDown(): void { + $this->deleteTestEntries(); + parent::tearDown(); + } + + protected function deleteTestEntries(): void { + $delete = $this->connection->getQueryBuilder(); + $delete->delete('preferences') + ->where($delete->expr()->like('userid', $delete->createNamedParameter('Version30000Date20240417075405Test%'))); + $delete->executeStatement(); + } + + protected function createTestEntries(): void { + $this->deleteTestEntries(); + + $insert = $this->connection->getQueryBuilder(); + $insert->insert('preferences') + ->values([ + 'userid' => $insert->createParameter('userid'), + 'appid' => $insert->createNamedParameter('photos'), + 'configkey' => $insert->createParameter('configkey'), + 'configvalue' => $insert->createNamedParameter('value'), + ]); + + $this->connection->beginTransaction(); + for ($i = 1; $i <= 3000; $i++) { + $mod = $i % 3; + if ($mod !== 0) { + $insert->setParameter('userid', 'Version30000Date20240417075405Test#' . $i) + ->setParameter('configkey', 'photosSourceFolder'); + $insert->executeStatement(); + } + if ($mod !== 1) { + $insert->setParameter('userid', 'Version30000Date20240417075405Test#' . $i) + ->setParameter('configkey', 'photosSourceFolders'); + $insert->executeStatement(); + } + } + $this->connection->commit(); + } + + public function testPostSchemaChange(): void { + $migration = new Version30000Date20240417075405($this->connection); + + $this->createTestEntries(); + + + $migration->postSchemaChange( + $this->createMock(IOutput::class), + \Closure::fromCallable(fn () => false), + [] + ); + + $select = $this->connection->getQueryBuilder(); + $select->select($select->func()->count()) + ->from('preferences') + ->where($select->expr()->like('userid', $select->createNamedParameter('Version30000Date20240417075405Test%'))) + ->andWhere($select->expr()->eq('appid', $select->expr()->literal('photos'))) + ->andWhere($select->expr()->eq('configkey', $select->expr()->literal('photosSourceFolder'))); + $result = $select->executeQuery(); + $this->assertEquals(0, $result->fetchOne()); + $result->closeCursor(); + + $select = $this->connection->getQueryBuilder(); + $select->select($select->func()->count()) + ->from('preferences') + ->where($select->expr()->like('userid', $select->createNamedParameter('Version30000Date20240417075405Test%'))) + ->andWhere($select->expr()->eq('appid', $select->expr()->literal('photos'))) + ->andWhere($select->expr()->eq('configkey', $select->expr()->literal('photosSourceFolders'))); + $result = $select->executeQuery(); + $this->assertEquals(3000, $result->fetchOne()); + $result->closeCursor(); + } +}