Merge pull request #23928 from nextcloud/bugfix/oci/dont-leave-stray-cursors-on-mimetype-update

Fix repair mimetype step to not leave stray cursors
This commit is contained in:
Morris Jobke 2020-11-06 22:09:44 +01:00 committed by GitHub
commit 63f996408b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 54 deletions

View File

@ -146,7 +146,7 @@ class Repair implements IOutput {
public static function getRepairSteps() { public static function getRepairSteps() {
return [ return [
new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), \OC::$server->getDatabaseConnection(), false), new Collation(\OC::$server->getConfig(), \OC::$server->getLogger(), \OC::$server->getDatabaseConnection(), false),
new RepairMimeTypes(\OC::$server->getConfig()), new RepairMimeTypes(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()), new CleanTags(\OC::$server->getDatabaseConnection(), \OC::$server->getUserManager()),
new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()), new RepairInvalidShares(\OC::$server->getConfig(), \OC::$server->getDatabaseConnection()),
new MoveUpdaterStepFile(\OC::$server->getConfig()), new MoveUpdaterStepFile(\OC::$server->getConfig()),

View File

@ -33,84 +33,74 @@
namespace OC\Repair; namespace OC\Repair;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\Migration\IOutput; use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep; use OCP\Migration\IRepairStep;
class RepairMimeTypes implements IRepairStep { class RepairMimeTypes implements IRepairStep {
/** /** @var IConfig */
* @var \OCP\IConfig
*/
protected $config; protected $config;
/** @var IDBConnection */
protected $connection;
/** /** @var int */
* @var int
*/
protected $folderMimeTypeId; protected $folderMimeTypeId;
/** public function __construct(IConfig $config,
* @param \OCP\IConfig $config IDBConnection $connection) {
*/
public function __construct($config) {
$this->config = $config; $this->config = $config;
$this->connection = $connection;
} }
public function getName() { public function getName() {
return 'Repair mime types'; return 'Repair mime types';
} }
private static function existsStmt() {
return \OC_DB::prepare('
SELECT count(`mimetype`)
FROM `*PREFIX*mimetypes`
WHERE `mimetype` = ?
');
}
private static function getIdStmt() {
return \OC_DB::prepare('
SELECT `id`
FROM `*PREFIX*mimetypes`
WHERE `mimetype` = ?
');
}
private static function insertStmt() {
return \OC_DB::prepare('
INSERT INTO `*PREFIX*mimetypes` ( `mimetype` )
VALUES ( ? )
');
}
private static function updateByNameStmt() {
return \OC_DB::prepare('
UPDATE `*PREFIX*filecache`
SET `mimetype` = ?
WHERE `mimetype` <> ? AND `mimetype` <> ? AND `name` ILIKE ?
');
}
private function updateMimetypes($updatedMimetypes) { private function updateMimetypes($updatedMimetypes) {
$query = $this->connection->getQueryBuilder();
$query->select('id')
->from('mimetypes')
->where($query->expr()->eq('mimetype', $query->createParameter('mimetype'), IQueryBuilder::PARAM_INT));
$insert = $this->connection->getQueryBuilder();
$insert->insert('mimetypes')
->setValue('mimetype', $insert->createParameter('mimetype'));
if (empty($this->folderMimeTypeId)) { if (empty($this->folderMimeTypeId)) {
$result = \OC_DB::executeAudited(self::getIdStmt(), ['httpd/unix-directory']); $query->setParameter('mimetype', 'httpd/unix-directory');
$this->folderMimeTypeId = (int)$result->fetchOne(); $result = $query->execute();
$this->folderMimeTypeId = (int)$result->fetchColumn();
$result->closeCursor();
} }
$update = $this->connection->getQueryBuilder();
$update->update('filecache')
->set('mimetype', $update->createParameter('mimetype'))
->where($update->expr()->neq('mimetype', $update->createParameter('mimetype'), IQueryBuilder::PARAM_INT))
->andWhere($update->expr()->neq('mimetype', $update->createParameter('folder'), IQueryBuilder::PARAM_INT))
->andWhere($update->expr()->iLike('name', $update->createParameter('name')))
->setParameter('folder', $this->folderMimeTypeId);
$count = 0; $count = 0;
foreach ($updatedMimetypes as $extension => $mimetype) { foreach ($updatedMimetypes as $extension => $mimetype) {
$result = \OC_DB::executeAudited(self::existsStmt(), [$mimetype]); // get target mimetype id
$exists = $result->fetchOne(); $query->setParameter('mimetype', $mimetype);
$result = $query->execute();
$mimetypeId = (int)$result->fetchColumn();
$result->closeCursor();
if (!$exists) { if (!$mimetypeId) {
// insert mimetype // insert mimetype
\OC_DB::executeAudited(self::insertStmt(), [$mimetype]); $insert->setParameter('mimetype', $mimetype);
$insert->execute();
$mimetypeId = $insert->getLastInsertId();
} }
// get target mimetype id
$result = \OC_DB::executeAudited(self::getIdStmt(), [$mimetype]);
$mimetypeId = $result->fetchOne();
// change mimetype for files with x extension // change mimetype for files with x extension
$count += \OC_DB::executeAudited(self::updateByNameStmt(), [$mimetypeId, $this->folderMimeTypeId, $mimetypeId, '%.' . $extension]); $update->setParameter('mimetype', $mimetypeId)
->setParameter('name', '%' . $this->connection->escapeLikeParameter('.' . $extension));
$count += $update->execute();
} }
return $count; return $count;

View File

@ -50,7 +50,7 @@ class RepairMimeTypesTest extends \Test\TestCase {
$this->storage = new \OC\Files\Storage\Temporary([]); $this->storage = new \OC\Files\Storage\Temporary([]);
$this->repair = new \OC\Repair\RepairMimeTypes($config); $this->repair = new \OC\Repair\RepairMimeTypes($config, \OC::$server->getDatabaseConnection());
} }
protected function tearDown(): void { protected function tearDown(): void {