count correct array, then using 1000 as MAX_SQL_CHUNK_SIZE works as expected

This commit is contained in:
Jörn Friedrich Dreyer 2013-10-30 15:48:38 +01:00
parent 4750fbc226
commit 68e88b6e40
1 changed files with 42 additions and 38 deletions

View File

@ -228,69 +228,73 @@ class Shared_Cache extends Cache {
*/ */
public function search($pattern) { public function search($pattern) {
$where = '`name` LIKE ? AND ';
// normalize pattern // normalize pattern
$pattern = $this->normalize($pattern); $value = $this->normalize($pattern);
$ids = $this->getAll(); return $this->searchWithWhere($where, $value);
$files = array();
// divide into 1k chunks
$chunks = array_chunk($ids, 1000);
foreach ($chunks as $chunk) {
$placeholders = join(',', array_fill(0, count($chunk), '?'));
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
`encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `fileid` IN (' . $placeholders . ')';
$result = \OC_DB::executeAudited($sql, array_merge(array($pattern), $chunk));
while ($row = $result->fetchRow()) {
if (substr($row['path'], 0, 6)==='files/') {
$row['path'] = substr($row['path'],6); // remove 'files/' from path as it's relative to '/Shared'
}
$row['mimetype'] = $this->getMimetype($row['mimetype']);
$row['mimepart'] = $this->getMimetype($row['mimepart']);
$files[] = $row;
}
}
return $files;
} }
/** /**
* search for files by mimetype * search for files by mimetype
* *
* @param string $part1 * @param string $mimetype
* @param string $part2
* @return array * @return array
*/ */
public function searchByMime($mimetype) { public function searchByMime($mimetype) {
if (strpos($mimetype, '/')) { if (strpos($mimetype, '/')) {
$where = '`mimetype` = ?'; $where = '`mimetype` = ? AND ';
} else { } else {
$where = '`mimepart` = ?'; $where = '`mimepart` = ? AND ';
} }
$mimetype = $this->getMimetypeId($mimetype);
$value = $this->getMimetypeId($mimetype);
return $this->searchWithWhere($where, $value);
}
/**
* The maximum number of placeholders that can be used in an SQL query.
* Value MUST be <= 1000 for oracle:
* see ORA-01795 maximum number of expressions in a list is 1000
* FIXME we should get this from doctrine as other DBs allow a lot more placeholders
*/
const MAX_SQL_CHUNK_SIZE = 1000;
/**
* search for files with a custom where clause and value
* the $wherevalue will be array_merge()d with the file id chunks
*
* @param string $sqlwhere
* @param string $wherevalue
* @return array
*/
private function searchWithWhere($sqlwhere, $wherevalue, $chunksize = self::MAX_SQL_CHUNK_SIZE) {
$ids = $this->getAll(); $ids = $this->getAll();
$files = array(); $files = array();
// divide into 1k chunks // divide into chunks
$chunks = array_chunk($ids, 1000); $chunks = array_chunk($ids, $chunksize);
foreach ($chunks as $chunk) { foreach ($chunks as $chunk) {
$placeholders = join(',', array_fill(0, count($ids), '?')); $placeholders = join(',', array_fill(0, count($chunk), '?'));
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, $sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`,
`encrypted`, `unencrypted_size`, `etag` `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `fileid` IN (' . $placeholders . ')'; FROM `*PREFIX*filecache` WHERE ' . $sqlwhere . ' `fileid` IN (' . $placeholders . ')';
$result = \OC_DB::executeAudited($sql, array_merge(array($mimetype), $chunk)); $stmt = \OC_DB::prepare($sql);
$result = $stmt->execute(array_merge(array($wherevalue), $chunk));
while ($row = $result->fetchRow()) { while ($row = $result->fetchRow()) {
if (substr($row['path'], 0, 6)==='files/') { if (substr($row['path'], 0, 6) === 'files/') {
$row['path'] = substr($row['path'],6); // remove 'files/' from path as it's relative to '/Shared' $row['path'] = substr($row['path'], 6); // remove 'files/' from path as it's relative to '/Shared'
} }
$row['mimetype'] = $this->getMimetype($row['mimetype']); $row['mimetype'] = $this->getMimetype($row['mimetype']);
$row['mimepart'] = $this->getMimetype($row['mimepart']); $row['mimepart'] = $this->getMimetype($row['mimepart']);