/** * 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); } }
private DocumentRevisionTree getAllRevisionsOfDocument(long docNumericID) { String sql = "SELECT " + FULL_DOCUMENT_COLS + " FROM revs, docs " + "WHERE revs.doc_id=? AND revs.doc_id = docs.doc_id ORDER BY sequence ASC"; String[] args = {Long.toString(docNumericID)}; Cursor cursor = null; try { DocumentRevisionTree tree = new DocumentRevisionTree(); cursor = this.sqlDb.rawQuery(sql, args); while (cursor.moveToNext()) { DocumentRevision rev = SQLDatabaseUtils.getFullRevisionFromCurrentCursor(cursor); Log.v(LOG_TAG, "Rev: " + rev); tree.add(rev); } return tree; } catch (SQLException e) { Log.e(LOG_TAG, "Error getting all revisions of document", e); return null; } 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; }
private List<DocumentRevision> getRevisionsFromRawQuery(String sql, String[] args) { List<DocumentRevision> result = new ArrayList<DocumentRevision>(); Cursor cursor = null; try { cursor = this.sqlDb.rawQuery(sql, args); while (cursor.moveToNext()) { DocumentRevision row = SQLDatabaseUtils.getFullRevisionFromCurrentCursor(cursor); result.add(row); } } catch (SQLException e) { e .printStackTrace(); // To change bodyOne of catch statement use File | Settings | File // Templates. } finally { DatabaseUtils.closeCursorQuietly(cursor); } return result; }
@Override public BasicDocumentRevision getDocument(String id, String rev) { Preconditions.checkState(this.isOpen(), "Database is closed"); Preconditions.checkArgument( !Strings.isNullOrEmpty(id), "DocumentRevisionTree id can not be empty"); Cursor cursor = null; try { String[] args = (rev == null) ? new String[] {id} : new String[] {id, rev}; String sql = (rev == null) ? GET_DOCUMENT_CURRENT_REVISION : GET_DOCUMENT_GIVEN_REVISION; cursor = this.sqlDb.rawQuery(sql, args); if (cursor.moveToFirst()) { return SQLDatabaseUtils.getFullRevisionFromCurrentCursor(cursor); } else { return null; } } catch (SQLException e) { throw new SQLRuntimeException("Error getting document with id: " + id + "and rev" + rev, e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } }