From 2248e465afd78d51f111eeb007a0eaf38b4c9cac Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Thu, 15 Jan 2015 17:26:12 +0100
Subject: [PATCH] Remove children from the cache in one query

---
 lib/private/files/cache/cache.php | 60 ++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 24 deletions(-)

diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index bf44cf48aa..8d0681ba93 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -73,12 +73,11 @@ class Cache {
 		}
 
 		if (!isset(self::$mimetypeIds[$mime])) {
-			try{
+			try {
 				$result = \OC_DB::executeAudited('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)', array($mime));
 				self::$mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes');
 				self::$mimetypes[self::$mimetypeIds[$mime]] = $mime;
-			}
-			catch (\Doctrine\DBAL\DBALException $e){
+			} catch (\Doctrine\DBAL\DBALException $e) {
 				\OC_Log::write('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OC_Log::DEBUG);
 				return -1;
 			}
@@ -95,20 +94,20 @@ class Cache {
 		return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null;
 	}
 
-	public function loadMimetypes(){
-			$result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array());
-			if ($result) {
-				while ($row = $result->fetchRow()) {
-					self::$mimetypeIds[$row['mimetype']] = $row['id'];
-					self::$mimetypes[$row['id']] = $row['mimetype'];
-				}
+	public function loadMimetypes() {
+		$result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array());
+		if ($result) {
+			while ($row = $result->fetchRow()) {
+				self::$mimetypeIds[$row['mimetype']] = $row['id'];
+				self::$mimetypes[$row['id']] = $row['mimetype'];
 			}
+		}
 	}
 
 	/**
 	 * get the stored metadata of a file or folder
 	 *
-	 * @param string/int $file
+	 * @param string /int $file
 	 * @return array|false
 	 */
 	public function get($file) {
@@ -135,7 +134,7 @@ class Cache {
 		}
 
 		//merge partial data
-		if (!$data and  is_string($file)) {
+		if (!$data and is_string($file)) {
 			if (isset($this->partial[$file])) {
 				$data = $this->partial[$file];
 			}
@@ -146,7 +145,7 @@ class Cache {
 			$data['mtime'] = (int)$data['mtime'];
 			$data['storage_mtime'] = (int)$data['storage_mtime'];
 			$data['encrypted'] = (bool)$data['encrypted'];
-            $data['unencrypted_size'] = 0 + $data['unencrypted_size'];
+			$data['unencrypted_size'] = 0 + $data['unencrypted_size'];
 			$data['storage'] = $this->storageId;
 			$data['mimetype'] = $this->getMimetype($data['mimetype']);
 			$data['mimepart'] = $this->getMimetype($data['mimepart']);
@@ -181,7 +180,7 @@ class Cache {
 			$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
 						   `storage_mtime`, `encrypted`, `unencrypted_size`, `etag`, `permissions`
 					FROM `*PREFIX*filecache` WHERE `parent` = ? ORDER BY `name` ASC';
-			$result = \OC_DB::executeAudited($sql,array($fileId));
+			$result = \OC_DB::executeAudited($sql, array($fileId));
 			$files = $result->fetchAll();
 			foreach ($files as &$file) {
 				$file['mimetype'] = $this->getMimetype($file['mimetype']);
@@ -255,12 +254,12 @@ class Cache {
 	 */
 	public function update($id, array $data) {
 
-		if(isset($data['path'])) {
+		if (isset($data['path'])) {
 			// normalize path
 			$data['path'] = $this->normalize($data['path']);
 		}
 
-		if(isset($data['name'])) {
+		if (isset($data['name'])) {
 			// normalize path
 			$data['name'] = $this->normalize($data['name']);
 		}
@@ -365,14 +364,26 @@ class Cache {
 	 */
 	public function remove($file) {
 		$entry = $this->get($file);
+		$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
+		\OC_DB::executeAudited($sql, array($entry['fileid']));
 		if ($entry['mimetype'] === 'httpd/unix-directory') {
-			$children = $this->getFolderContents($file);
-			foreach ($children as $child) {
-				$this->remove($child['path']);
-			}
+			$this->removeChildren($entry);
 		}
+	}
 
-		$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?';
+	private function getSubFolders($entry) {
+		$children = $this->getFolderContentsById($entry['fileid']);
+		return array_filter($children, function ($child) {
+			return $child['mimetype'] === 'httpd/unix-directory';
+		});
+	}
+
+	private function removeChildren($entry) {
+		$subFolders = $this->getSubFolders($entry);
+		foreach ($subFolders as $folder) {
+			$this->removeChildren($folder);
+		}
+		$sql = 'DELETE FROM `*PREFIX*filecache` WHERE `parent` = ?';
 		\OC_DB::executeAudited($sql, array($entry['fileid']));
 	}
 
@@ -520,12 +531,12 @@ class Cache {
 			'`*PREFIX*vcategory_to_object` `tagmap`, ' .
 			'`*PREFIX*vcategory` `tag` ' .
 			// JOIN filecache to vcategory_to_object
-			'WHERE `file`.`fileid` = `tagmap`.`objid` '.
+			'WHERE `file`.`fileid` = `tagmap`.`objid` ' .
 			// JOIN vcategory_to_object to vcategory
 			'AND `tagmap`.`type` = `tag`.`type` ' .
 			'AND `tagmap`.`categoryid` = `tag`.`id` ' .
 			// conditions
-			'AND `file`.`storage` = ? '.
+			'AND `file`.`storage` = ? ' .
 			'AND `tag`.`type` = \'files\' ' .
 			'AND `tag`.`uid` = ? ';
 		if (is_int($tag)) {
@@ -638,7 +649,7 @@ class Cache {
 	 */
 	public function getIncomplete() {
 		$query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache`'
-			. ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC',1);
+			. ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC', 1);
 		$result = \OC_DB::executeAudited($query, array($this->getNumericStorageId()));
 		if ($row = $result->fetchRow()) {
 			return $row['path'];
@@ -694,6 +705,7 @@ class Cache {
 
 	/**
 	 * normalize the given path
+	 *
 	 * @param string $path
 	 * @return string
 	 */
-- 
GitLab