Optimize header fetching of multi-folder searches with natural (UID) sorting

pull/175/head
Thomas Bruederli 11 years ago
parent 518963d1d4
commit 1883048720

@ -955,6 +955,14 @@ class rcube_imap extends rcube_storage
$sort_field = $this->sort_field; $sort_field = $this->sort_field;
$search_set = $this->search_set; $search_set = $this->search_set;
// prepare paging
$cnt = $search_set->count();
$from = ($page-1) * $page_size;
$to = $from + $page_size;
$slice_length = min($page_size, $cnt - $from);
// fetch resultset headers, sort and slice them
if (!empty($sort_field)) {
$this->sort_field = null; $this->sort_field = null;
$this->page_size = 1000; // fetch up to 1000 matching messages per folder $this->page_size = 1000; // fetch up to 1000 matching messages per folder
$this->threading = false; $this->threading = false;
@ -968,13 +976,8 @@ class rcube_imap extends rcube_storage
} }
} }
// do sorting and paging
$cnt = $search_set->count();
$from = ($page-1) * $page_size;
$to = $from + $page_size;
// sort headers // sort headers
if (!$this->threading && !empty($a_msg_headers)) { if (!empty($a_msg_headers)) {
$a_msg_headers = $this->conn->sortHeaders($a_msg_headers, $sort_field, $this->sort_order); $a_msg_headers = $this->conn->sortHeaders($a_msg_headers, $sort_field, $this->sort_order);
} }
@ -982,8 +985,22 @@ class rcube_imap extends rcube_storage
$search_set->set_message_index($a_msg_headers, $sort_field, $this->sort_order); $search_set->set_message_index($a_msg_headers, $sort_field, $this->sort_order);
// only return the requested part of the set // only return the requested part of the set
$slice_length = min($page_size, $cnt - $from);
$a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length); $a_msg_headers = array_slice(array_values($a_msg_headers), $from, $slice_length);
}
else {
// slice resultset first...
$fetch = array();
foreach (array_slice($search_set->get(), $from, $slice_length) as $msg_id) {
list($uid, $folder) = explode('-', $msg_id, 2);
$fetch[$folder][] = $uid;
}
// ... and fetch the requested set of headers
$a_msg_headers = array();
foreach ($fetch as $folder => $a_index) {
$a_msg_headers = array_merge($a_msg_headers, array_values($this->fetch_headers($folder, $a_index)));
}
}
if ($slice) { if ($slice) {
$a_msg_headers = array_slice($a_msg_headers, -$slice, $slice); $a_msg_headers = array_slice($a_msg_headers, -$slice, $slice);

@ -168,6 +168,21 @@ class rcube_result_multifolder
} }
} }
/**
* Slices data set.
*
* @param $offset Offset (as for PHP's array_slice())
* @param $length Number of elements (as for PHP's array_slice())
*
*/
public function slice($offset, $length)
{
$data = array_slice($this->get(), $offset, $length);
$this->index = $data;
$this->meta['count'] = count($data);
}
/** /**
* Filters data set. Removes elements not listed in $ids list. * Filters data set. Removes elements not listed in $ids list.
* *

@ -108,7 +108,8 @@ if (!empty($subject)) {
// search all, current or subfolders folders // search all, current or subfolders folders
if ($scope == 'all') { if ($scope == 'all') {
$mboxes = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail'); $mboxes = $RCMAIL->storage->list_folders_subscribed('', '*', 'mail', null, true);
natcasesort($mboxes); // we want natural alphabetic sorting of folders in the result set
} }
else if ($scope == 'sub') { else if ($scope == 'sub') {
$mboxes = $RCMAIL->storage->list_folders_subscribed($mbox, '*', 'mail'); $mboxes = $RCMAIL->storage->list_folders_subscribed($mbox, '*', 'mail');

Loading…
Cancel
Save