/**
   * Removes revisions present in the datastore from the input map.
   *
   * @param revisions an multimap from document id to set of revisions. The map is modified in place
   *     for performance consideration.
   */
  void revsDiffBatch(Multimap<String, String> revisions) {

    final String sql =
        String.format(
            "SELECT docs.docid, revs.revid FROM docs, revs "
                + "WHERE docs.doc_id = revs.doc_id AND docs.docid IN (%s) AND revs.revid IN (%s) "
                + "ORDER BY docs.docid",
            SQLDatabaseUtils.makePlaceholders(revisions.keySet().size()),
            SQLDatabaseUtils.makePlaceholders(revisions.size()));

    String[] args = new String[revisions.keySet().size() + revisions.size()];
    String[] keys = revisions.keySet().toArray(new String[revisions.keySet().size()]);
    String[] values = revisions.values().toArray(new String[revisions.size()]);
    System.arraycopy(keys, 0, args, 0, revisions.keySet().size());
    System.arraycopy(values, 0, args, revisions.keySet().size(), revisions.size());

    Cursor cursor = null;
    try {
      cursor = this.sqlDb.rawQuery(sql, args);
      while (cursor.moveToNext()) {
        String docId = cursor.getString(0);
        String revId = cursor.getString(1);
        revisions.remove(docId, revId);
      }
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      DatabaseUtils.closeCursorQuietly(cursor);
    }
  }
 @Override
 public List<DocumentRevision> getDocumentsWithIds(List<String> docIds) {
   Preconditions.checkState(this.isOpen(), "Database is closed");
   Preconditions.checkNotNull(docIds, "Input document id list can not be null");
   String sql =
       String.format(
           "SELECT "
               + FULL_DOCUMENT_COLS
               + " FROM revs, docs"
               + " WHERE docid IN ( %1$s ) AND current = 1 AND docs.doc_id = revs.doc_id "
               + " ORDER BY docs.doc_id ",
           SQLDatabaseUtils.makePlaceholders(docIds.size()));
   String[] args = docIds.toArray(new String[docIds.size()]);
   List<DocumentRevision> docs = getRevisionsFromRawQuery(sql, args);
   // Sort in memory since seems not able to sort them using SQL
   return sortDocumentsAccordingToIdList(docIds, docs);
 }
  /**
   * Get list of documents for given list of numeric ids. The result list is ordered by sequence
   * number, and only the current revisions are returned.
   *
   * @param docIds given list of internal ids
   * @return list of documents ordered by sequence number
   */
  List<DocumentRevision> getDocumentsWithInternalIds(List<Long> docIds) {
    Preconditions.checkNotNull(docIds, "Input document internal id list can not be null");
    if (docIds.size() == 0) {
      return Collections.emptyList();
    }

    final String GET_DOCUMENTS_BY_INTERNAL_IDS =
        "SELECT "
            + FULL_DOCUMENT_COLS
            + " FROM revs, docs "
            + "WHERE revs.doc_id IN ( %s ) AND current = 1 AND docs.doc_id = revs.doc_id";

    // Split into batches because SQLite has a limit on the number
    // of placeholders we can use in a single query. 999 is the default
    // value, but it can be lower. It's hard to find this out from Java,
    // so we use a value much lower.
    List<DocumentRevision> result = new ArrayList<DocumentRevision>(docIds.size());

    List<List<Long>> batches = Lists.partition(docIds, SQLITE_QUERY_PLACEHOLDERS_LIMIT);
    for (List<Long> batch : batches) {
      String sql =
          String.format(
              GET_DOCUMENTS_BY_INTERNAL_IDS, SQLDatabaseUtils.makePlaceholders(batch.size()));
      String[] args = new String[batch.size()];
      for (int i = 0; i < batch.size(); i++) {
        args[i] = Long.toString(batch.get(i));
      }
      result.addAll(getRevisionsFromRawQuery(sql, args));
    }

    // Contract is to sort by sequence number, which we need to do
    // outside the sqlDb as we're batching requests.
    Collections.sort(
        result,
        new Comparator<DocumentRevision>() {
          @Override
          public int compare(
              DocumentRevision documentRevision, DocumentRevision documentRevision2) {
            long a = documentRevision.getSequence();
            long b = documentRevision2.getSequence();
            return (int) (a - b);
          }
        });

    return result;
  }