@@ -1015,7 +1015,6 @@ public function calculateFolderSize($path, $entry = null) {
10151015 /**
10161016 * inner function because we can't add new params to the public function without breaking any child classes
10171017 *
1018- * @param string $path
10191018 * @param array|null|ICacheEntry $entry (optional) meta data of the folder
10201019 * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown
10211020 * @return int|float
@@ -1029,7 +1028,17 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i
10291028 $ id = $ entry ['fileid ' ];
10301029
10311030 $ query = $ this ->getQueryBuilder ();
1032- $ query ->select ('size ' , 'unencrypted_size ' )
1031+ // $effectiveSize is reused in both aggregates; Doctrine handles the duplicated parameter correctly
1032+ $ effectiveSize = $ query ->func ()->caseWhen (
1033+ $ query ->expr ()->gt ('unencrypted_size ' , $ query ->createNamedParameter (0 , IQueryBuilder::PARAM_INT )),
1034+ 'unencrypted_size ' ,
1035+ 'size '
1036+ );
1037+ $ query ->selectAlias ($ query ->func ()->sum ('size ' ), 'size_sum ' )
1038+ ->selectAlias ($ query ->func ()->min ('size ' ), 'size_min ' )
1039+ ->selectAlias ($ query ->func ()->max ('unencrypted_size ' ), 'unencrypted_max ' )
1040+ ->selectAlias ($ query ->func ()->sum ($ effectiveSize ), 'unencrypted_sum ' )
1041+ ->selectAlias ($ query ->func ()->min ($ effectiveSize ), 'unencrypted_min ' )
10331042 ->from ('filecache ' )
10341043 ->whereStorageId ($ this ->getNumericStorageId ())
10351044 ->whereParent ($ id );
@@ -1038,34 +1047,19 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i
10381047 }
10391048
10401049 $ result = $ query ->executeQuery ();
1041- $ rows = $ result ->fetchAll ();
1050+ $ agg = $ result ->fetch ();
10421051 $ result ->closeCursor ();
10431052
1044- if ($ rows ) {
1045- $ sizes = array_map (function (array $ row ) {
1046- return Util::numericToNumber ($ row ['size ' ]);
1047- }, $ rows );
1048- $ unencryptedOnlySizes = array_map (function (array $ row ) {
1049- return Util::numericToNumber ($ row ['unencrypted_size ' ]);
1050- }, $ rows );
1051- $ unencryptedSizes = array_map (function (array $ row ) {
1052- return Util::numericToNumber (($ row ['unencrypted_size ' ] > 0 ) ? $ row ['unencrypted_size ' ] : $ row ['size ' ]);
1053- }, $ rows );
1054-
1055- $ sum = array_sum ($ sizes );
1056- $ min = min ($ sizes );
1057-
1058- $ unencryptedSum = array_sum ($ unencryptedSizes );
1059- $ unencryptedMin = min ($ unencryptedSizes );
1060- $ unencryptedMax = max ($ unencryptedOnlySizes );
1061-
1062- $ sum = 0 + $ sum ;
1063- $ min = 0 + $ min ;
1064- if ($ min === -1 ) {
1065- $ totalSize = $ min ;
1066- } else {
1067- $ totalSize = $ sum ;
1068- }
1053+ // SUM() returns NULL on empty set
1054+ if ($ agg && $ agg ['size_sum ' ] !== null ) {
1055+ $ sum = Util::numericToNumber ($ agg ['size_sum ' ]);
1056+ $ min = Util::numericToNumber ($ agg ['size_min ' ]);
1057+ $ unencryptedMax = Util::numericToNumber ($ agg ['unencrypted_max ' ] ?? 0 );
1058+ $ unencryptedSum = Util::numericToNumber ($ agg ['unencrypted_sum ' ] ?? 0 );
1059+ $ unencryptedMin = Util::numericToNumber ($ agg ['unencrypted_min ' ] ?? 0 );
1060+
1061+ $ totalSize = ($ min === -1 ) ? $ min : $ sum ;
1062+
10691063 if ($ unencryptedMin === -1 || $ min === -1 ) {
10701064 $ unencryptedTotal = $ unencryptedMin ;
10711065 } else {
@@ -1077,15 +1071,16 @@ protected function calculateFolderSizeInner(string $path, $entry = null, bool $i
10771071 $ unencryptedMax = 0 ;
10781072 }
10791073
1080- // only set unencrypted size for a folder if any child entries have it set, or the folder is empty
1074+ // only set unencrypted size for a folder if any child entries have it set
1075+ // or if the folder is empty
10811076 $ shouldWriteUnEncryptedSize = $ unencryptedMax > 0 || $ totalSize === 0 || ($ entry ['unencrypted_size ' ] ?? 0 ) > 0 ;
10821077 if ($ entry ['size ' ] !== $ totalSize || (($ entry ['unencrypted_size ' ] ?? 0 ) !== $ unencryptedTotal && $ shouldWriteUnEncryptedSize )) {
10831078 if ($ shouldWriteUnEncryptedSize ) {
1084- // if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes
1079+ // if all children have an unencrypted size of 0
1080+ // just set the folder unencrypted size to 0 instead of summing the sizes
10851081 if ($ unencryptedMax === 0 ) {
10861082 $ unencryptedTotal = 0 ;
10871083 }
1088-
10891084 $ this ->update ($ id , [
10901085 'size ' => $ totalSize ,
10911086 'unencrypted_size ' => $ unencryptedTotal ,
0 commit comments