44
44
/** A mutation queue for a specific user, backed by SQLite. */
45
45
final class SQLiteMutationQueue implements MutationQueue {
46
46
47
+ /**
48
+ * On Android, SQLite Cursors are limited reading no more than 2 MB per row (despite being able to
49
+ * write very large values). All reads of the mutations column in the mutations table need to read
50
+ * in chunks with SUBSTR to avoid going over this limit.
51
+ *
52
+ * <p>The value here has to be 2 MB or smaller, while allowing for all possible other values that
53
+ * might be selected out along with the mutations column in any given result set. Nearly 1 MB is
54
+ * conservative, but allows all combinations of document paths and batch ids without needing to
55
+ * figure out if the row has gotten too large.
56
+ */
47
57
private static final int BLOB_MAX_INLINE_LENGTH = 1000000 ;
48
58
49
59
private final SQLitePersistence db ;
@@ -216,9 +226,9 @@ public MutationBatch getNextMutationBatchAfterBatchId(int batchId) {
216
226
int nextBatchId = batchId + 1 ;
217
227
218
228
return db .query (
219
- "SELECT m. batch_id, SUBSTR(m. mutations, 1, ?) FROM mutations m "
220
- + "WHERE m. uid = ? AND m. batch_id >= ? "
221
- + "ORDER BY m. batch_id ASC LIMIT 1" )
229
+ "SELECT batch_id, SUBSTR(mutations, 1, ?) FROM mutations "
230
+ + "WHERE uid = ? AND batch_id >= ? "
231
+ + "ORDER BY batch_id ASC LIMIT 1" )
222
232
.binding (BLOB_MAX_INLINE_LENGTH , uid , nextBatchId )
223
233
.firstValue (row -> decodeInlineMutationBatch (row .getInt (0 ), row .getBlob (1 )));
224
234
}
@@ -227,8 +237,8 @@ public MutationBatch getNextMutationBatchAfterBatchId(int batchId) {
227
237
public List <MutationBatch > getAllMutationBatches () {
228
238
List <MutationBatch > result = new ArrayList <>();
229
239
db .query (
230
- "SELECT m. batch_id, SUBSTR(m. mutations, 1, ?) "
231
- + "FROM mutations m "
240
+ "SELECT batch_id, SUBSTR(mutations, 1, ?) "
241
+ + "FROM mutations "
232
242
+ "WHERE uid = ? ORDER BY batch_id ASC" )
233
243
.binding (BLOB_MAX_INLINE_LENGTH , uid )
234
244
.forEach (row -> result .add (decodeInlineMutationBatch (row .getInt (0 ), row .getBlob (1 ))));
@@ -407,7 +417,7 @@ public void performConsistencyCheck() {
407
417
}
408
418
409
419
/**
410
- * Decodes mutation batch bytes obtained via substring. If the blob is too smaller than
420
+ * Decodes mutation batch bytes obtained via substring. If the blob is smaller than
411
421
* BLOB_MAX_INLINE_LENGTH, executes additional queries to load the rest of the blob.
412
422
*
413
423
* @param batchId The batch ID of the row containing the bytes, for fallback lookup if the value
0 commit comments