diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 96b0c413e4db5..9e9de89b34852 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -1015,7 +1015,6 @@ public function calculateFolderSize($path, $entry = null) { /** * inner function because we can't add new params to the public function without breaking any child classes * - * @param string $path * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown * @return int|float @@ -1029,7 +1028,19 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i $id = $entry['fileid']; $query = $this->getQueryBuilder(); - $query->select('size', 'unencrypted_size') + $sizeCol = $query->getColumnName('size'); + $unencryptedSizeCol = $query->getColumnName('unencrypted_size'); + $query->selectAlias($query->func()->sum('size'), 'size_sum') + ->selectAlias($query->func()->min('size'), 'size_min') + ->selectAlias($query->func()->max('unencrypted_size'), 'unencrypted_max') + ->selectAlias( + $query->createFunction("SUM(CASE WHEN $unencryptedSizeCol > 0 THEN $unencryptedSizeCol ELSE $sizeCol END)"), + 'unencrypted_sum' + ) + ->selectAlias( + $query->createFunction("MIN(CASE WHEN $unencryptedSizeCol > 0 THEN $unencryptedSizeCol ELSE $sizeCol END)"), + 'unencrypted_min' + ) ->from('filecache') ->whereStorageId($this->getNumericStorageId()) ->whereParent($id); @@ -1038,34 +1049,24 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i } $result = $query->executeQuery(); - $rows = $result->fetchAll(); + $agg = $result->fetch(); $result->closeCursor(); - if ($rows) { - $sizes = array_map(function (array $row) { - return Util::numericToNumber($row['size']); - }, $rows); - $unencryptedOnlySizes = array_map(function (array $row) { - return Util::numericToNumber($row['unencrypted_size']); - }, $rows); - $unencryptedSizes = array_map(function (array $row) { - return Util::numericToNumber(($row['unencrypted_size'] > 0) ? $row['unencrypted_size'] : $row['size']); - }, $rows); - - $sum = array_sum($sizes); - $min = min($sizes); - - $unencryptedSum = array_sum($unencryptedSizes); - $unencryptedMin = min($unencryptedSizes); - $unencryptedMax = max($unencryptedOnlySizes); + // SUM() returns NULL on empty set + if ($agg && $agg['size_sum'] !== null) { + $sum = Util::numericToNumber($agg['size_sum']); + $min = Util::numericToNumber($agg['size_min']); + $unencryptedMax = Util::numericToNumber($agg['unencrypted_max'] ?? 0); + $unencryptedSum = Util::numericToNumber($agg['unencrypted_sum'] ?? 0); + $unencryptedMin = Util::numericToNumber($agg['unencrypted_min'] ?? 0); $sum = 0 + $sum; $min = 0 + $min; - if ($min === -1) { - $totalSize = $min; - } else { - $totalSize = $sum; - } + $unencryptedSum = 0 + $unencryptedSum; + $unencryptedMin = 0 + $unencryptedMin; + + $totalSize = ($min === -1) ? $min : $sum; + if ($unencryptedMin === -1 || $min === -1) { $unencryptedTotal = $unencryptedMin; } else { @@ -1077,15 +1078,16 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i $unencryptedMax = 0; } - // only set unencrypted size for a folder if any child entries have it set, or the folder is empty + // only set unencrypted size for a folder if any child entries have it set + // or if the folder is empty $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || ($entry['unencrypted_size'] ?? 0) > 0; if ($entry['size'] !== $totalSize || (($entry['unencrypted_size'] ?? 0) !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) { if ($shouldWriteUnEncryptedSize) { - // if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes + // if all children have an unencrypted size of 0 + // just set the folder unencrypted size to 0 instead of summing the sizes if ($unencryptedMax === 0) { $unencryptedTotal = 0; } - $this->update($id, [ 'size' => $totalSize, 'unencrypted_size' => $unencryptedTotal, diff --git a/lib/private/Files/Cache/Propagator.php b/lib/private/Files/Cache/Propagator.php index 38d8ccee6410b..10cb3e502947c 100644 --- a/lib/private/Files/Cache/Propagator.php +++ b/lib/private/Files/Cache/Propagator.php @@ -218,29 +218,32 @@ public function commitBatch(): void { $query = $this->connection->getQueryBuilder(); $query->update('filecache') ->set('mtime', $query->func()->greatest('mtime', $query->createParameter('time'))) - ->set('etag', $query->expr()->literal(uniqid())) + ->set('etag', $query->createParameter('etag')) ->where($query->expr()->eq('storage', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) ->andWhere($query->expr()->eq('fileid', $query->createParameter('fileid'))); $queryWithSize = $this->connection->getQueryBuilder(); $queryWithSize->update('filecache') ->set('mtime', $queryWithSize->func()->greatest('mtime', $queryWithSize->createParameter('time'))) - ->set('etag', $queryWithSize->expr()->literal(uniqid())) + ->set('etag', $queryWithSize->createParameter('etag')) ->set('size', $queryWithSize->func()->add('size', $queryWithSize->createParameter('size'))) ->where($queryWithSize->expr()->eq('storage', $queryWithSize->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) ->andWhere($queryWithSize->expr()->eq('fileid', $queryWithSize->createParameter('fileid'))); while ($row = $result->fetchAssociative()) { $item = $this->batch[$row['path']]; + $newEtag = uniqid(); if ($item['size'] && $row['size'] > -1) { $queryWithSize->setParameter('fileid', $row['fileid'], IQueryBuilder::PARAM_INT) ->setParameter('size', $item['size'], IQueryBuilder::PARAM_INT) ->setParameter('time', $item['time'], IQueryBuilder::PARAM_INT) - ->executeStatement(); + ->setParameter('etag', $newEtag, IQueryBuilder::PARAM_STR); + $queryWithSize->executeStatement(); } else { $query->setParameter('fileid', $row['fileid'], IQueryBuilder::PARAM_INT) ->setParameter('time', $item['time'], IQueryBuilder::PARAM_INT) - ->executeStatement(); + ->setParameter('etag', $newEtag, IQueryBuilder::PARAM_STR); + $query->executeStatement(); } } } @@ -249,28 +252,31 @@ public function commitBatch(): void { $query = $this->connection->getQueryBuilder(); $query->update('filecache') ->set('mtime', $query->func()->greatest('mtime', $query->createParameter('time'))) - ->set('etag', $query->expr()->literal(uniqid())) + ->set('etag', $query->createParameter('etag')) ->where($query->expr()->eq('storage', $query->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) ->andWhere($query->expr()->eq('path_hash', $query->createParameter('hash'))); $queryWithSize = $this->connection->getQueryBuilder(); $queryWithSize->update('filecache') ->set('mtime', $queryWithSize->func()->greatest('mtime', $queryWithSize->createParameter('time'))) - ->set('etag', $queryWithSize->expr()->literal(uniqid())) + ->set('etag', $queryWithSize->createParameter('etag')) ->set('size', $queryWithSize->func()->add('size', $queryWithSize->createParameter('size'))) ->where($queryWithSize->expr()->eq('storage', $queryWithSize->createNamedParameter($storageId, IQueryBuilder::PARAM_INT))) ->andWhere($queryWithSize->expr()->eq('path_hash', $queryWithSize->createParameter('hash'))); foreach ($this->batch as $item) { + $newEtag = uniqid(); if ($item['size']) { $queryWithSize->setParameter('hash', $item['hash'], IQueryBuilder::PARAM_STR) ->setParameter('time', $item['time'], IQueryBuilder::PARAM_INT) ->setParameter('size', $item['size'], IQueryBuilder::PARAM_INT) - ->executeStatement(); + ->setParameter('etag', $newEtag, IQueryBuilder::PARAM_STR); + $queryWithSize->executeStatement(); } else { $query->setParameter('hash', $item['hash'], IQueryBuilder::PARAM_STR) ->setParameter('time', $item['time'], IQueryBuilder::PARAM_INT) - ->executeStatement(); + ->setParameter('etag', $newEtag, IQueryBuilder::PARAM_STR); + $query->executeStatement(); } } }