2222
2323use Doctrine \DBAL \Platforms \OraclePlatform ;
2424use Doctrine \DBAL \Platforms \MySqlPlatform ;
25+ use Doctrine \DBAL \Platforms \SqlitePlatform ;
26+ use Doctrine \DBAL \Platforms \MySQL80Platform ;
27+ use Doctrine \DBAL \Platforms \MariaDb1027Platform ;
2528use OCP \Files \Folder ;
2629use OCP \IDBConnection ;
2730use OCP \DB \QueryBuilder \IQueryBuilder ;
@@ -101,13 +104,32 @@ public function process(bool $all = false, int $chunkSize = 1000, \Closure $prog
101104 private function queryPreviewsToDelete (int $ startFileId = 0 , int $ chunkSize = 1000 ): array {
102105 $ dbPlatform = $ this ->connection ->getDatabasePlatform ();
103106 $ isOracle = ($ dbPlatform instanceof OraclePlatform);
107+ $ isOldMysql = ($ dbPlatform instanceof MySqlPlatform && !($ dbPlatform instanceof MySQL80Platform || $ dbPlatform instanceof MariaDb1027Platform));
104108
105- $ castTo = 'BIGINT ' ;
109+ $ castToInt = 'BIGINT ' ;
110+ $ castToVchar = 'VARCHAR(250) ' ;
106111 if ($ dbPlatform instanceof MySqlPlatform) {
107112 // for MySQL we need to cast to "signed" instead
108- $ castTo = 'SIGNED ' ;
113+ $ castToInt = 'SIGNED ' ;
114+ $ castToVchar = 'CHAR ' ;
109115 } elseif ($ isOracle ) {
110- $ castTo = 'NUMBER ' ;
116+ $ castToInt = 'NUMBER ' ;
117+ $ castToVchar = 'VARCHAR2(250) ' ;
118+ }
119+
120+ // The cast condition will be applied to all DB except sqlite (which doesn't
121+ // have the regexp_replace function as built-in and requires extensions).
122+ // If the name contains only digits, the name will be casted to an integer;
123+ // otherwise, the name will be replaced with the fileid. This is intended
124+ // because we want to exclude those rows from the final result.
125+ $ castCondition = "CAST(REGEXP_REPLACE(`thumb`.`name`, '(^.*[^[:digit:]]+.*$|^$)', CAST(`thumb`.`fileid` AS {$ castToVchar })) AS {$ castToInt }) " ;
126+ if ($ dbPlatform instanceof SqlitePlatform || $ isOldMysql ) {
127+ // For sqlite, the cast function seems to return 0 if the value can't be
128+ // casted properly. We'll use that instead the regexp.
129+ // Note that casting "123explode" to bigint will return the 123 integer,
130+ // not the 0 we want. We'll rely on the "parent" condition (in the sql
131+ // statement) to deal with these false positives.
132+ $ castCondition = "COALESCE(NULLIF(CAST(`thumb`.`name` AS {$ castToInt }), 0), `thumb`.`fileid`) " ;
111133 }
112134
113135 // for the path_hash -> 3b8779ba05b8f0aed49650f3ff8beb4b = MD5('thumbnails')
@@ -128,7 +150,7 @@ private function queryPreviewsToDelete(int $startFileId = 0, int $chunkSize = 10
128150AND NOT EXISTS (
129151 SELECT 1
130152 FROM `*PREFIX*filecache`
131- WHERE `fileid` = CAST(`thumb`.`name` AS $ {castTo} )
153+ WHERE `fileid` = { $ castCondition }
132154)
133155AND `fileid` > ?
134156ORDER BY `storage` " ;
0 commit comments