X Tutup
Skip to content

Commit b523ac5

Browse files
jvillafanezDeepDiver1975
authored andcommitted
Merge pull request #41051 from owncloud/preview_cleanup_fix_postgres3
Fix problem with postgresql complaining about a wrong cast
1 parent 18104d8 commit b523ac5

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

changelog/unreleased/41051

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Bugfix: Fix potential issue with the PreviewCleanup job in postgresql
2+
3+
One of the filters of the preview cleanup job requires casting a filename,
4+
which is supposed to contain only digits, to an integer. The expected execution
5+
of the DB query should have filtered the results so the condition above should
6+
be true, but the DB's query planner might choose to apply the filters in a
7+
different way, so we could potentially cast random strings to integer.
8+
For the case of postgresql, the cast function will cause an error if the string
9+
can't be casted to an integer (because it has non-digit chars, for example)
10+
11+
This situation is fixed for all the supported DBs, so we don't require the
12+
query planner to execute the query in any particular way.
13+
14+
https://github.com/owncloud/core/pull/41051

lib/private/PreviewCleanup.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
use Doctrine\DBAL\Platforms\OraclePlatform;
2424
use Doctrine\DBAL\Platforms\MySqlPlatform;
25+
use Doctrine\DBAL\Platforms\SqlitePlatform;
26+
use Doctrine\DBAL\Platforms\MySQL80Platform;
27+
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
2528
use OCP\Files\Folder;
2629
use OCP\IDBConnection;
2730
use 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
128150
AND NOT EXISTS (
129151
SELECT 1
130152
FROM `*PREFIX*filecache`
131-
WHERE `fileid` = CAST(`thumb`.`name` AS ${castTo})
153+
WHERE `fileid` = {$castCondition}
132154
)
133155
AND `fileid` > ?
134156
ORDER BY `storage`";

0 commit comments

Comments
 (0)
X Tutup