// Keep in mind we do not keep local document revision history private BasicDocumentRevision doGetLocalDocument(String docId, String revId) { assert !Strings.isNullOrEmpty(docId); Cursor cursor = null; try { String[] args = {docId}; cursor = this.sqlDb.rawQuery("SELECT revid, json FROM localdocs WHERE docid=?", args); if (cursor.moveToFirst()) { String gotRevID = cursor.getString(0); if (revId != null && !revId.equals(gotRevID)) { // throw new DocumentNotFoundException("No local document found with // id: " + docId + ", revId: " + revId); return null; } byte[] json = cursor.getBlob(1); DocumentRevisionBuilder builder = new DocumentRevisionBuilder() .setDocId(docId) .setRevId(gotRevID) .setBody(BasicDocumentBody.bodyWith(json)); return builder.buildBasicDBObjectLocalDocument(); } else { return null; } } catch (SQLException e) { throw new SQLRuntimeException("Error getting local document with id: " + docId, e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } }
@Override public Iterator<String> getConflictedDocumentIds() { // the "SELECT DISTINCT ..." subquery selects all the parent // sequence, and so the outer "SELECT ..." practically selects // all the leaf nodes. The "GROUP BY" and "HAVING COUNT(*) > 1" // make sure only those document with more than one leafs are // returned. final String sql = "SELECT docs.docid, COUNT(*) FROM docs,revs " + "WHERE revs.doc_id = docs.doc_id " + "AND deleted = 0 AND revs.sequence NOT IN " + "(SELECT DISTINCT parent FROM revs WHERE parent NOT NULL) " + "GROUP BY docs.docid HAVING COUNT(*) > 1"; List<String> conflicts = new ArrayList<String>(); Cursor cursor = null; try { cursor = this.sqlDb.rawQuery(sql, new String[] {}); while (cursor.moveToNext()) { String docId = cursor.getString(0); conflicts.add(docId); } } catch (SQLException e) { Log.e(LOG_TAG, "Error getting conflicted document: ", e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } return conflicts.iterator(); }
@Override public Changes changes(long since, int limit) { Preconditions.checkState(this.isOpen(), "Database is closed"); Preconditions.checkArgument(limit > 0, "Limit must be positive number"); since = since >= 0 ? since : 0; String[] args = {Long.toString(since), Long.toString(since + limit)}; Cursor cursor = null; try { Long lastSequence = since; List<Long> ids = new ArrayList<Long>(); cursor = this.sqlDb.rawQuery(SQL_CHANGE_IDS_SINCE_LIMIT, args); while (cursor.moveToNext()) { ids.add(cursor.getLong(0)); lastSequence = Math.max(lastSequence, cursor.getLong(1)); } List<DocumentRevision> results = this.getDocumentsWithInternalIds(ids); if (results.size() != ids.size()) { throw new IllegalStateException( "The number of document does not match number of ids, " + "something must be wrong here."); } return new Changes(lastSequence, results); } catch (SQLException e) { throw new IllegalStateException( "Error querying all changes since: " + since + ", limit: " + limit, e); } 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); } }
/** * 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); } }
static BasicDocumentRevision getFullRevisionFromCurrentCursor(Cursor cursor) { String docId = cursor.getString(0); long internalId = cursor.getLong(1); String revId = cursor.getString(2); long sequence = cursor.getLong(3); byte[] json = cursor.getBlob(4); boolean current = cursor.getInt(5) > 0; boolean deleted = cursor.getInt(6) > 0; long parent = -1L; if (cursor.columnType(7) == Cursor.FIELD_TYPE_INTEGER) { parent = cursor.getLong(7); } else if (cursor.columnType(7) == Cursor.FIELD_TYPE_NULL) { } else { throw new IllegalArgumentException("Unexpected type: " + cursor.columnType(7)); } DocumentRevisionBuilder builder = new DocumentRevisionBuilder() .setDocId(docId) .setRevId(revId) .setBody(BasicDocumentBody.bodyWith(json)) .setDeleted(deleted) .setSequence(sequence) .setInternalId(internalId) .setCurrnet(current) .setParent(parent); return builder.buildBasicDBObject(); }
public static Set<String> getAllTableNames(SQLDatabase db) throws SQLException { Cursor cursor = null; try { cursor = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", new String[] {}); Set<String> tables = new HashSet<String>(); while (cursor.moveToNext()) { tables.add(cursor.getString(0)); } return tables; } finally { } }
public static Set<String> getCompileOptions(SQLDatabase db) throws SQLException { Cursor cursor = null; Set<String> compileOptions = new HashSet<String>(); try { cursor = db.rawQuery("PRAGMA compile_options", new String[] {}); while (cursor.moveToNext()) { compileOptions.add(cursor.getString(0)); } } finally { if (cursor != null) { cursor.close(); } } return compileOptions; }
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 long getDocNumericId(String docId) { Preconditions.checkState(this.isOpen(), "Database is closed"); Preconditions.checkArgument( !Strings.isNullOrEmpty(docId), "Input document id can not be empty"); Cursor cursor = null; try { cursor = this.sqlDb.rawQuery("SELECT doc_id FROM docs WHERE docid = ?", new String[] {docId}); if (cursor.moveToFirst()) { return cursor.getLong(0); } } catch (SQLException e) { Log.e(LOG_TAG, "Error getting doc numeric id", e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } return -1; }
@Override public int getDocumentCount() { Preconditions.checkState(this.isOpen(), "Database is closed"); String sql = "SELECT COUNT(DISTINCT doc_id) FROM revs WHERE current=1 AND deleted=0"; Cursor cursor = null; int result = 0; try { cursor = this.sqlDb.rawQuery(sql, null); if (cursor.moveToFirst()) { result = cursor.getInt(0); } } catch (SQLException e) { Log.e(LOG_TAG, "Error getting document count", e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } return result; }
@Override public String getPublicIdentifier() { Preconditions.checkState(this.isOpen(), "Database is closed"); Cursor cursor = null; try { cursor = this.sqlDb.rawQuery("SELECT value FROM info WHERE key='publicUUID'", null); if (cursor.moveToFirst()) { return "touchdb_" + cursor.getString(0); } else { throw new IllegalStateException( "Error querying PublicUUID, " + "it is probably because the sqlDatabase is not probably initialized."); } } catch (SQLException e) { throw new SQLRuntimeException("Error querying publicUUID: ", e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } }
@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); } }
@Override public long getLastSequence() { Preconditions.checkState(this.isOpen(), "Database is closed"); String sql = "SELECT MAX(sequence) FROM revs"; Cursor cursor = null; long result = 0; try { cursor = this.sqlDb.rawQuery(sql, null); if (cursor.moveToFirst()) { if (cursor.columnType(0) == Cursor.FIELD_TYPE_INTEGER) { result = cursor.getLong(0); } else if (cursor.columnType(0) == Cursor.FIELD_TYPE_NULL) { result = SEQUENCE_NUMBER_START; } else { throw new IllegalStateException("SQLite return an unexpected value."); } } } catch (SQLException e) { Log.e(LOG_TAG, "Error getting last sequence", e); } finally { DatabaseUtils.closeCursorQuietly(cursor); } return result; }