From a0a6c0e33bcaeb9c952261f21dab99147615edfc Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 6 Feb 2015 20:49:38 +0100 Subject: [PATCH 1/3] Add MD5() to sqlite and oracle --- lib/private/db/adapteroci8.php | 1 + lib/private/db/sqlitesessioninit.php | 3 +++ tests/lib/db.php | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/lib/private/db/adapteroci8.php b/lib/private/db/adapteroci8.php index 970d3eefa4d5..590f4d2f3655 100644 --- a/lib/private/db/adapteroci8.php +++ b/lib/private/db/adapteroci8.php @@ -45,6 +45,7 @@ public function fixupStatement($statement) { $statement = str_replace('`', '"', $statement); $statement = str_ireplace('NOW()', 'CURRENT_TIMESTAMP', $statement); $statement = str_ireplace('UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement); + $statement = preg_replace('/MD5\(([^)]+)\)/i', 'LOWER(DBMS_OBFUSCATION_TOOLKIT.md5 (input => UTL_RAW.cast_to_raw($1)))', $statement); return $statement; } } diff --git a/lib/private/db/sqlitesessioninit.php b/lib/private/db/sqlitesessioninit.php index 0683c47d08e5..39b40cc7fb9d 100644 --- a/lib/private/db/sqlitesessioninit.php +++ b/lib/private/db/sqlitesessioninit.php @@ -57,6 +57,9 @@ public function postConnect(ConnectionEventArgs $args) { $sensitive = ($this->caseSensitiveLike) ? 'true' : 'false'; $args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = ' . $sensitive); $args->getConnection()->executeUpdate('PRAGMA journal_mode = ' . $this->journalMode); + /** @var \PDO $pdo */ + $pdo = $args->getConnection()->getWrappedConnection(); + $pdo->sqliteCreateFunction('md5', 'md5', 1); } public function getSubscribedEvents() { diff --git a/tests/lib/db.php b/tests/lib/db.php index 88c9ee75b3be..7db65c4c713c 100644 --- a/tests/lib/db.php +++ b/tests/lib/db.php @@ -386,4 +386,15 @@ public function testILIKEWildcard() { $result = $query->execute(array('%ba%')); $this->assertCount(1, $result->fetchAll()); } + + public function testMD5() { + $table = "*PREFIX*{$this->table2}"; + + $query = OC_DB::prepare("INSERT INTO `$table` (`fullname`, `uri`, `carddata`) VALUES (?, ?, ?)"); + $query->execute(array('foobar', 'foo', 'bar')); + + $query = OC_DB::prepare("SELECT MD5(`fullname`) FROM `$table` WHERE `fullname` LIKE ?"); + $result = $query->execute(array('foobar')); + $this->assertEquals(md5('foobar'), $result->fetchOne()); + } } From f70589c0813877e173e70b6a3ff7d9d5f5d7017e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 6 Feb 2015 20:49:49 +0100 Subject: [PATCH 2/3] Add CONCAT() to sqlite --- lib/private/db/adaptersqlite.php | 1 + tests/lib/files/cache/cache.php | 32 +++++++++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/private/db/adaptersqlite.php b/lib/private/db/adaptersqlite.php index d7769238abca..e3171471b8c5 100644 --- a/lib/private/db/adaptersqlite.php +++ b/lib/private/db/adaptersqlite.php @@ -33,6 +33,7 @@ public function fixupStatement($statement) { $statement = str_replace( '`', '"', $statement ); $statement = str_ireplace( 'NOW()', 'datetime(\'now\')', $statement ); $statement = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement ); + $statement = preg_replace('/CONCAT\(([^)]+?), ?([^)]+?)\)/i', '$1 || $2', $statement); return $statement; } diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 54aa7ad789a6..197744494cae 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -109,8 +109,8 @@ public function testPartial() { * @dataProvider folderDataProvider */ public function testFolder($folder) { - $file2 = $folder.'/bar'; - $file3 = $folder.'/foo'; + $file2 = $folder . '/bar'; + $file3 = $folder . '/foo'; $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); $fileData = array(); $fileData['bar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); @@ -129,7 +129,7 @@ public function testFolder($folder) { } } - $file4 = $folder.'/unkownSize'; + $file4 = $folder . '/unkownSize'; $fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file'); $this->cache->put($file4, $fileData['unkownSize']); @@ -146,8 +146,8 @@ public function testFolder($folder) { $this->assertEquals(0, $this->cache->calculateFolderSize($folder)); $this->cache->remove($folder); - $this->assertFalse($this->cache->inCache($folder.'/foo')); - $this->assertFalse($this->cache->inCache($folder.'/bar')); + $this->assertFalse($this->cache->inCache($folder . '/foo')); + $this->assertFalse($this->cache->inCache($folder . '/bar')); } public function testRemoveRecursive() { @@ -156,7 +156,7 @@ public function testRemoveRecursive() { $folders = ['folder', 'folder/subfolder', 'folder/sub2', 'folder/sub2/sub3']; $files = ['folder/foo.txt', 'folder/bar.txt', 'folder/subfolder/asd.txt', 'folder/sub2/qwerty.txt', 'folder/sub2/sub3/foo.txt']; - foreach($folders as $folder){ + foreach ($folders as $folder) { $this->cache->put($folder, $folderData); } foreach ($files as $file) { @@ -351,7 +351,9 @@ function testSearchByTag() { $this->assertEquals(2, count($results)); - usort($results, function($value1, $value2) { return $value1['name'] >= $value2['name']; }); + usort($results, function ($value1, $value2) { + return $value1['name'] >= $value2['name']; + }); $this->assertEquals('folder', $results[0]['name']); $this->assertEquals('foo', $results[1]['name']); @@ -359,11 +361,15 @@ function testSearchByTag() { // use tag id $tags = $tagManager->getTagsForUser($userId); $this->assertNotEmpty($tags); - $tags = array_filter($tags, function($tag) { return $tag->getName() === 'tag2'; }); + $tags = array_filter($tags, function ($tag) { + return $tag->getName() === 'tag2'; + }); $results = $this->cache->searchByTag(current($tags)->getId(), $userId); $this->assertEquals(3, count($results)); - usort($results, function($value1, $value2) { return $value1['name'] >= $value2['name']; }); + usort($results, function ($value1, $value2) { + return $value1['name'] >= $value2['name']; + }); $this->assertEquals('folder', $results[0]['name']); $this->assertEquals('foo2', $results[1]['name']); @@ -399,8 +405,16 @@ function testMove() { $this->cache2->put($file4, $data); $this->cache2->put($file5, $data); + $id1 = (int)$this->cache->getId('folder/foo/1'); + $id2 = (int)$this->cache->getId('folder/foo/2'); + $this->cache->move('folder/foo', 'folder/foobar'); + $this->assertEquals('folder/foobar/1', $this->cache->get($id1)['path']); + $this->assertEquals('folder/foobar/2', $this->cache->get($id2)['path']); + $this->assertEquals(md5('folder/foobar/1'), $this->cache->get($id1)['path_hash']); + $this->assertEquals(md5('folder/foobar/2'), $this->cache->get($id2)['path_hash']); + $this->assertFalse($this->cache->inCache('folder/foo')); $this->assertFalse($this->cache->inCache('folder/foo/1')); $this->assertFalse($this->cache->inCache('folder/foo/2')); From 1c0903fab1cf4aaddcb677c22b2121a83a523cf3 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 6 Feb 2015 20:50:05 +0100 Subject: [PATCH 3/3] Move all children of a folder in a single query --- lib/private/files/cache/cache.php | 32 +++++++++++++------------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 53467c278d2f..b83ac5b41959 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -122,7 +122,7 @@ public function get($file) { $where = 'WHERE `fileid` = ?'; $params = array($file); } - $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, + $sql = 'SELECT `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `storage_mtime`, `encrypted`, `etag`, `permissions`, `checksum` FROM `*PREFIX*filecache` ' . $where; $result = $this->connection->executeQuery($sql, $params); @@ -505,27 +505,21 @@ public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) { list($sourceStorageId, $sourcePath) = $sourceCache->getMoveInfo($sourcePath); list($targetStorageId, $targetPath) = $this->getMoveInfo($targetPath); - // sql for final update - $moveSql = 'UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` =? WHERE `fileid` = ?'; - + $this->connection->beginTransaction(); if ($sourceData['mimetype'] === 'httpd/unix-directory') { - //find all child entries - $sql = 'SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path` LIKE ?'; - $result = $this->connection->executeQuery($sql, [$sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']); - $childEntries = $result->fetchAll(); + //update all child entries $sourceLength = strlen($sourcePath); - $this->connection->beginTransaction(); - $query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ? WHERE `fileid` = ?'); - - foreach ($childEntries as $child) { - $newTargetPath = $targetPath . substr($child['path'], $sourceLength); - $query->execute([$targetStorageId, $newTargetPath, md5($newTargetPath), $child['fileid']]); - } - $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]); - $this->connection->commit(); - } else { - $this->connection->executeQuery($moveSql, [$targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId]); + $query = $this->connection->prepare('UPDATE `*PREFIX*filecache` SET + `storage` = ?, + `path_hash` = MD5(CONCAT(?, SUBSTR(`path`, ?))), + `path` = CONCAT(?, SUBSTR(`path`, ?)) + WHERE `storage` = ? AND `path` LIKE ?'); + $query->execute([$targetStorageId, $targetPath, $sourceLength + 1,$targetPath, $sourceLength + 1, $sourceStorageId, $this->connection->escapeLikeParameter($sourcePath) . '/%']); } + + $sql = 'UPDATE `*PREFIX*filecache` SET `storage` = ?, `path` = ?, `path_hash` = ?, `name` = ?, `parent` = ? WHERE `fileid` = ?'; + $this->connection->executeQuery($sql, array($targetStorageId, $targetPath, md5($targetPath), basename($targetPath), $newParentId, $sourceId)); + $this->connection->commit(); } else { $this->moveFromCacheFallback($sourceCache, $sourcePath, $targetPath); }