@Test
  public void quick() throws Exception {
    Mailbox mbox =
        MailboxManager.getInstance().getMailboxByAccountId(MockProvisioning.DEFAULT_ACCOUNT_ID);

    Contact contact =
        mbox.createContact(
            null,
            new ParsedContact(
                Collections.singletonMap(ContactConstants.A_email, "*****@*****.**")),
            Mailbox.ID_FOLDER_CONTACTS,
            null);
    MailboxTestUtil.index(mbox);

    mbox.createContact(
        null,
        new ParsedContact(Collections.singletonMap(ContactConstants.A_email, "*****@*****.**")),
        Mailbox.ID_FOLDER_CONTACTS,
        null);

    SearchParams params = new SearchParams();
    params.setQueryString("test");
    params.setSortBy(SortBy.NONE);
    params.setTypes(EnumSet.of(MailItem.Type.CONTACT));
    params.setQuick(true);

    ZimbraQuery query =
        new ZimbraQuery(new OperationContext(mbox), SoapProtocol.Soap12, mbox, params);
    ZimbraQueryResults result = query.execute();
    Assert.assertTrue(result.hasNext());
    Assert.assertEquals(contact.getId(), result.getNext().getItemId());
    Assert.assertFalse(result.hasNext());
    Closeables.closeQuietly(result);
  }
  @Test
  public void suggest() throws Exception {
    Mailbox mbox =
        MailboxManager.getInstance().getMailboxByAccountId(MockProvisioning.DEFAULT_ACCOUNT_ID);
    DeliveryOptions dopt = new DeliveryOptions().setFolderId(Mailbox.ID_FOLDER_INBOX);
    Message msg =
        mbox.addMessage(
            null, new ParsedMessage("Subject: all hands meeting".getBytes(), false), dopt, null);
    MailboxTestUtil.index(mbox);

    SearchParams params = new SearchParams();
    params.setQueryString("all hands me");
    params.setSortBy(SortBy.NONE);
    params.setTypes(EnumSet.of(MailItem.Type.MESSAGE));
    params.setQuick(true);

    ZimbraQuery query =
        new ZimbraQuery(new OperationContext(mbox), SoapProtocol.Soap12, mbox, params);
    ZimbraQueryResults result = query.execute();
    Assert.assertEquals(msg.getId(), result.getNext().getItemId());
    Closeables.closeQuietly(result);
  }
  @Test
  public void mdate() throws Exception {
    Mailbox mbox =
        MailboxManager.getInstance().getMailboxByAccountId(MockProvisioning.DEFAULT_ACCOUNT_ID);

    DbConnection conn = DbPool.getConnection();
    DbUtil.executeUpdate(
        conn,
        "INSERT INTO mboxgroup1.mail_item "
            + "(mailbox_id, id, folder_id, type, flags, date, change_date, size, tags, mod_metadata, mod_content) "
            + "VALUES(?, ?, ?, ?, 0, ?, ?, 0, 0, 0, 0)",
        mbox.getId(),
        101,
        Mailbox.ID_FOLDER_INBOX,
        MailItem.Type.MESSAGE.toByte(),
        100,
        1000);
    DbUtil.executeUpdate(
        conn,
        "INSERT INTO mboxgroup1.mail_item "
            + "(mailbox_id, id, folder_id, type, flags, date, change_date, size, tags, mod_metadata, mod_content) "
            + "VALUES(?, ?, ?, ?, 0, ?, ?, 0, 0, 0, 0)",
        mbox.getId(),
        102,
        Mailbox.ID_FOLDER_INBOX,
        MailItem.Type.MESSAGE.toByte(),
        200,
        2000);
    DbUtil.executeUpdate(
        conn,
        "INSERT INTO mboxgroup1.mail_item "
            + "(mailbox_id, id, folder_id, type, flags, date, change_date, size, tags, mod_metadata, mod_content) "
            + "VALUES(?, ?, ?, ?, 0, ?, ?, 0, 0, 0, 0)",
        mbox.getId(),
        103,
        Mailbox.ID_FOLDER_INBOX,
        MailItem.Type.MESSAGE.toByte(),
        300,
        3000);
    DbUtil.executeUpdate(
        conn,
        "INSERT INTO mboxgroup1.mail_item "
            + "(mailbox_id, id, folder_id, type, flags, date, change_date, size, tags, mod_metadata, mod_content) "
            + "VALUES(?, ?, ?, ?, 0, ?, ?, 0, 0, 0, 0)",
        mbox.getId(),
        104,
        Mailbox.ID_FOLDER_INBOX,
        MailItem.Type.MESSAGE.toByte(),
        400,
        4000);
    DbUtil.executeUpdate(
        conn,
        "INSERT INTO mboxgroup1.mail_item "
            + "(mailbox_id, id, folder_id, type, flags, date, change_date, size, tags, mod_metadata, mod_content) "
            + "VALUES(?, ?, ?, ?, 0, ?, ?, 0, 0, 0, 0)",
        mbox.getId(),
        105,
        Mailbox.ID_FOLDER_INBOX,
        MailItem.Type.MESSAGE.toByte(),
        500,
        5000);
    conn.commit();
    conn.closeQuietly();

    SearchParams params = new SearchParams();
    params.setQueryString("mdate:>3000000");
    params.setSortBy(SortBy.DATE_ASC);
    params.setTypes(EnumSet.of(MailItem.Type.MESSAGE));
    params.setFetchMode(SearchParams.Fetch.IDS);

    ZimbraQuery query =
        new ZimbraQuery(new OperationContext(mbox), SoapProtocol.Soap12, mbox, params);
    Assert.assertEquals("ZQ: Q(DATE:MDATE,197001010050-196912312359)", query.toString());
    ZimbraQueryResults result = query.execute();
    Assert.assertEquals(104, result.getNext().getItemId());
    Assert.assertEquals(105, result.getNext().getItemId());
    Assert.assertEquals(null, result.getNext());
    Closeables.closeQuietly(result);
  }
 @Override
 public List<QueryInfo> getResultInfo() {
   return results.getResultInfo();
 }
 @Override
 public void close() throws IOException {
   results.close();
 }
  private void bufferAllHits() throws ServiceException {
    assert (mHitBuffer == null);
    mHitBuffer = new ArrayList<ZimbraHit>();

    // get the proper comparator
    Comparator<ZimbraHit> comp;
    switch (sort) {
      default:
      case TASK_DUE_ASC:
        comp =
            new Comparator<ZimbraHit>() {
              @Override
              public int compare(ZimbraHit lhs, ZimbraHit rhs) {
                return TaskHit.compareByDueDate(true, lhs, rhs);
              }
            };
        break;
      case TASK_DUE_DESC:
        comp =
            new Comparator<ZimbraHit>() {
              @Override
              public int compare(ZimbraHit lhs, ZimbraHit rhs) {
                return TaskHit.compareByDueDate(false, lhs, rhs);
              }
            };
        break;
      case TASK_STATUS_ASC:
        comp =
            new Comparator<ZimbraHit>() {
              @Override
              public int compare(ZimbraHit lhs, ZimbraHit rhs) {
                return TaskHit.compareByStatus(true, lhs, rhs);
              }
            };
        break;
      case TASK_STATUS_DESC:
        comp =
            new Comparator<ZimbraHit>() {
              @Override
              public int compare(ZimbraHit lhs, ZimbraHit rhs) {
                return TaskHit.compareByStatus(false, lhs, rhs);
              }
            };
        break;
      case TASK_PERCENT_COMPLETE_ASC:
        comp =
            new Comparator<ZimbraHit>() {
              @Override
              public int compare(ZimbraHit lhs, ZimbraHit rhs) {
                return TaskHit.compareByCompletionPercent(true, lhs, rhs);
              }
            };
        break;
      case TASK_PERCENT_COMPLETE_DESC:
        comp =
            new Comparator<ZimbraHit>() {
              @Override
              public int compare(ZimbraHit lhs, ZimbraHit rhs) {
                return TaskHit.compareByCompletionPercent(false, lhs, rhs);
              }
            };
        break;
      case NAME_LOCALIZED_ASC:
      case NAME_LOCALIZED_DESC:
        comp = sort.getHitComparator(params.getLocale());
        break;
    }

    int maxIfPresorted = MAX_BUFFERED_HITS;
    if (params != null && params.getCursor() == null) {
      maxIfPresorted = params.getLimit();
      if (maxIfPresorted > 0) {
        // 1 is added so that the 'more' setting will be correct.
        maxIfPresorted = maxIfPresorted + 1 + params.getOffset();
      }
    }
    ZimbraHit cur;
    while ((cur = results.getNext()) != null) {

      if (isTaskSort()) {
        if (!(cur instanceof TaskHit) && !(cur instanceof ProxiedHit)) {
          throw ServiceException.FAILURE("Invalid hit type, can only task-sort Tasks", null);
        }
      }

      boolean skipHit = false;

      boolean handleCursorFilteringForFirstHit = true;
      if (DebugConfig.enableContactLocalizedSort) {
        switch (sort) {
          case NAME_LOCALIZED_ASC:
          case NAME_LOCALIZED_DESC:
            handleCursorFilteringForFirstHit = false;
            break;
        }
      }

      // handle cursor filtering
      if (params != null && params.getCursor() != null) {
        ZimbraHit firstHit = null;
        if (params.getCursor().getSortValue() != null) {
          firstHit =
              new ResultsPager.CursorHit(
                  results,
                  params.getCursor().getSortValue(),
                  params.getCursor().getItemId().getId());
        }
        ZimbraHit endHit = null;
        if (params.getCursor().getEndSortValue() != null) {
          endHit = new ResultsPager.CursorHit(results, params.getCursor().getEndSortValue(), 0);
        }
        // fail if cur < first OR cur >= end
        if (handleCursorFilteringForFirstHit) {
          if (firstHit != null && comp.compare(cur, firstHit) < 0) {
            skipHit = true;
          }
        }
        if (endHit != null && comp.compare(cur, endHit) >= 0) {
          skipHit = true;
        }
      }

      if (!skipHit) {
        mHitBuffer.add(cur);
      }
      if (mHitBuffer.size() >= MAX_BUFFERED_HITS) {
        break;
      }
      // If it turns out that the results were sorted remotely, we can bail out early.
      if (results.isPreSorted() && mHitBuffer.size() >= maxIfPresorted) {
        break;
      }
    }

    if (!results.isPreSorted()) {
      Collections.sort(mHitBuffer, comp);
    }
  }
 @Override
 public boolean isPreSorted() {
   return results.isPreSorted();
 }