/** * 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; }