Aleksander Machniak
2013-06-25 855c85377d44943ba307d083632c6c5a9f1c98ad
Performance improvement for searching in threaded mode. We can use
cached index now. Some other small improvements.
2 files modified
89 ■■■■■ changed files
program/lib/Roundcube/rcube_imap.php 84 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_imap_generic.php 5 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_imap.php
@@ -1189,11 +1189,13 @@
     * @param string $sort_field Sort column
     * @param string $sort_order Sort order [ASC, DESC]
     * @param bool   $no_threads Get not threaded index
     * @param bool   $no_search  Get index not limited to search result (optionally)
     *
     * @return rcube_result_index|rcube_result_thread List of messages (UIDs)
     */
    public function index($folder = '', $sort_field = NULL, $sort_order = NULL, $no_threads = false)
    {
    public function index($folder = '', $sort_field = NULL, $sort_order = NULL,
        $no_threads = false, $no_search = false
    ) {
        if (!$no_threads && $this->threading) {
            return $this->thread_index($folder, $sort_field, $sort_order);
        }
@@ -1207,46 +1209,49 @@
        // we have a saved search result, get index from there
        if ($this->search_string) {
            if ($this->search_set->is_empty()) {
                return new rcube_result_index();
                return new rcube_result_index($folder, '* SORT');
            }
            // disable threading temporarily
            $threading = $this->threading;
            $this->threading = false;
            if ($this->search_threads) {
                $index = $this->search_index($folder, $this->search_string, $this->search_charset, $this->sort_field);
            }
            else if ((!$this->sort_field && !$this->search_sorted) ||
                ($this->search_sorted && $this->search_sort_field == $this->sort_field)
            // search result is an index with the same sorting?
            if (($this->search_set instanceof rcube_result_index)
                && ((!$this->sort_field && !$this->search_sorted) ||
                    ($this->search_sorted && $this->search_sort_field == $this->sort_field))
            ) {
                $index = $this->search_set;
            }
            // $no_search is enabled when we are not interested in
            // fetching index for search result, e.g. to sort
            // threaded search result we can use full mailbox index.
            // This makes possible to use index from cache
            else if (!$no_search) {
                if (!$this->sort_field) {
                    // No sorting needed, just build index from the search result
                    // @TODO: do we need to sort by UID here?
                    $search = $this->search_set->get_compressed();
                    $index  = new rcube_result_index($folder, '* ESEARCH ALL ' . $search);
                }
            else {
                $search = 'UID ' . $this->search_set->get_compressed();
                $index  = $this->search_index($folder, $search, $this->search_charset, $this->sort_field);
                    $index = $this->index_direct($folder, $this->search_charset,
                        $this->sort_field, $this->search_set);
                }
            }
            if (isset($index)) {
            if ($this->sort_order != $index->get_parameters('ORDER')) {
                $index->revert();
            }
            $this->threading = $threading;
            return $index;
            }
        }
        // check local cache
        if ($mcache = $this->get_mcache_engine()) {
            $index = $mcache->get_index($folder, $this->sort_field, $this->sort_order);
        }
        // fetch from IMAP server
        else {
            $index = $this->index_direct(
                $folder, $this->sort_field, $this->sort_order);
            return $mcache->get_index($folder, $this->sort_field, $this->sort_order);
        }
        return $index;
        // fetch from IMAP server
        return $this->index_direct($folder, $this->sort_field, $this->sort_order);
    }
@@ -1257,15 +1262,21 @@
     * @param string $folder     Folder to get index from
     * @param string $sort_field Sort column
     * @param string $sort_order Sort order [ASC, DESC]
     * @param rcube_result_* $search     Optional messages set to limit the result
     *
     * @return rcube_result_index Sorted list of message UIDs
     */
    public function index_direct($folder, $sort_field = null, $sort_order = null)
    public function index_direct($folder, $sort_field = null, $sort_order = null, $search = null)
    {
        if (!empty($search)) {
            $search = $this->search_set->get_compressed();
        }
        // use message index sort as default sorting
        if (!$sort_field) {
            // use search result from count() if possible
            if ($this->options['skip_deleted'] && !empty($this->icache['undeleted_idx'])
            if (empty($search) && $this->options['skip_deleted']
                && !empty($this->icache['undeleted_idx'])
                && $this->icache['undeleted_idx']->get_parameters('ALL') !== null
                && $this->icache['undeleted_idx']->get_parameters('MAILBOX') == $folder
            ) {
@@ -1275,8 +1286,12 @@
                return new rcube_result_index();
            }
            else {
                $index = $this->conn->search($folder,
                    'ALL' .($this->options['skip_deleted'] ? ' UNDELETED' : ''), true);
                $query = $this->options['skip_deleted'] ? 'UNDELETED' : '';
                if ($search) {
                    $query = trim($query . ' UID ' . $search);
                }
                $index = $this->conn->search($folder, $query, true);
            }
        }
        else if (!$this->check_connection()) {
@@ -1285,13 +1300,18 @@
        // fetch complete message index
        else {
            if ($this->get_capability('SORT')) {
                $index = $this->conn->sort($folder, $sort_field,
                    $this->options['skip_deleted'] ? 'UNDELETED' : '', true);
                $query = $this->options['skip_deleted'] ? 'UNDELETED' : '';
                if ($search) {
                    $query = trim($query . ' UID ' . $search);
                }
                $index = $this->conn->sort($folder, $sort_field, $query, true);
            }
            if (empty($index) || $index->is_error()) {
                $index = $this->conn->index($folder, "1:*", $sort_field,
                    $this->options['skip_deleted'], false, true);
                $index = $this->conn->index($folder, $search ? $search : "1:*",
                    $sort_field, $this->options['skip_deleted'],
                    $search ? true : false, true);
            }
        }
@@ -1352,7 +1372,7 @@
        if ($this->get_capability('THREAD') != 'REFS') {
            $sortby = $this->sort_field ? $this->sort_field : 'date';
            $index  = $this->index($this->folder, $sortby, $this->sort_order, true);
            $index  = $this->index($this->folder, $sortby, $this->sort_order, true, true);
            if (!$index->is_empty()) {
                $threads->sort($index);
program/lib/Roundcube/rcube_imap_generic.php
@@ -1563,11 +1563,12 @@
        }
        // message IDs
        if (!empty($add))
        if (!empty($add)) {
            $add = $this->compressMessageSet($add);
        }
        list($code, $response) = $this->execute($return_uid ? 'UID SORT' : 'SORT',
            array("($field)", $encoding, 'ALL' . (!empty($add) ? ' '.$add : '')));
            array("($field)", $encoding, !empty($add) ? $add : 'ALL'));
        if ($code != self::ERROR_OK) {
            $response = null;