Search in sources :

Example 26 with MutationBatch

use of com.google.firebase.firestore.model.mutation.MutationBatch in project firebase-android-sdk by firebase.

the class SQLiteMutationQueue method getAllMutationBatchesAffectingQuery.

@Override
public List<MutationBatch> getAllMutationBatchesAffectingQuery(Query query) {
    hardAssert(!query.isCollectionGroupQuery(), "CollectionGroup queries should be handled in LocalDocumentsView");
    // Use the query path as a prefix for testing if a document matches the query.
    ResourcePath prefix = query.getPath();
    int immediateChildrenPathLength = prefix.length() + 1;
    // Scan the document_mutations table looking for documents whose path has a prefix that matches
    // the query path.
    // 
    // The most obvious way to do this would be with a LIKE query with a trailing wildcard (e.g.
    // path LIKE 'foo/%'). Unfortunately SQLite does not convert a trailing wildcard like that into
    // the equivalent range scan so a LIKE query ends up being a table scan. The query below is
    // equivalent but hits the index on both uid and path, so it's much faster.
    // TODO: Actually implement a single-collection query
    // 
    // This is actually executing an ancestor query, traversing the whole subtree below the
    // collection which can be horrifically inefficient for some structures. The right way to
    // solve this is to implement the full value index, but that's not in the cards in the near
    // future so this is the best we can do for the moment.
    String prefixPath = EncodedPath.encode(prefix);
    String prefixSuccessorPath = EncodedPath.prefixSuccessor(prefixPath);
    List<MutationBatch> result = new ArrayList<>();
    db.query("SELECT dm.batch_id, dm.path, SUBSTR(m.mutations, 1, ?) " + "FROM document_mutations dm, mutations m " + "WHERE dm.uid = ? " + "AND dm.path >= ? " + "AND dm.path < ? " + "AND dm.uid = m.uid " + "AND dm.batch_id = m.batch_id " + "ORDER BY dm.batch_id").binding(BLOB_MAX_INLINE_LENGTH, uid, prefixPath, prefixSuccessorPath).forEach(row -> {
        // Ensure unique batches only. This works because the batches come out in order so
        // we only need to ensure that the batchId of this row is different from the
        // preceding one.
        int batchId = row.getInt(0);
        int size = result.size();
        if (size > 0 && batchId == result.get(size - 1).getBatchId()) {
            return;
        }
        // The query is actually returning any path that starts with the query path prefix
        // which may include documents in subcollections. For example, a query on 'rooms'
        // will return rooms/abc/messages/xyx but we shouldn't match it. Fix this by
        // discarding rows with document keys more than one segment longer than the query
        // path.
        ResourcePath path = EncodedPath.decodeResourcePath(row.getString(1));
        if (path.length() != immediateChildrenPathLength) {
            return;
        }
        result.add(decodeInlineMutationBatch(batchId, row.getBlob(2)));
    });
    return result;
}
Also used : ResourcePath(com.google.firebase.firestore.model.ResourcePath) MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) ArrayList(java.util.ArrayList) ByteString(com.google.protobuf.ByteString)

Example 27 with MutationBatch

use of com.google.firebase.firestore.model.mutation.MutationBatch in project firebase-android-sdk by firebase.

the class SQLiteOverlayMigrationManager method buildOverlays.

private void buildOverlays() {
    db.runTransaction("build overlays", () -> {
        if (!hasPendingOverlayMigration()) {
            return;
        }
        Set<String> userIds = getAllUserIds();
        RemoteDocumentCache remoteDocumentCache = db.getRemoteDocumentCache();
        for (String uid : userIds) {
            User user = new User(uid);
            MutationQueue mutationQueue = db.getMutationQueue(user, db.getIndexManager(user));
            // Get all document keys that have local mutations
            Set<DocumentKey> allDocumentKeys = new HashSet<>();
            List<MutationBatch> batches = mutationQueue.getAllMutationBatches();
            for (MutationBatch batch : batches) {
                allDocumentKeys.addAll(batch.getKeys());
            }
            // Recalculate and save overlays
            DocumentOverlayCache documentOverlayCache = db.getDocumentOverlayCache(user);
            LocalDocumentsView localView = new LocalDocumentsView(remoteDocumentCache, mutationQueue, documentOverlayCache, db.getIndexManager(user));
            localView.recalculateAndSaveOverlays(allDocumentKeys);
        }
        removePendingOverlayMigrations();
    });
}
Also used : User(com.google.firebase.firestore.auth.User) MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) DocumentKey(com.google.firebase.firestore.model.DocumentKey) HashSet(java.util.HashSet)

Example 28 with MutationBatch

use of com.google.firebase.firestore.model.mutation.MutationBatch in project firebase-android-sdk by firebase.

the class LocalStore method rejectBatch.

/**
 * Removes mutations from the MutationQueue for the specified batch. LocalDocuments will be
 * recalculated.
 *
 * @return The resulting (modified) documents.
 */
public ImmutableSortedMap<DocumentKey, Document> rejectBatch(int batchId) {
    return persistence.runTransaction("Reject batch", () -> {
        MutationBatch toReject = mutationQueue.lookupMutationBatch(batchId);
        hardAssert(toReject != null, "Attempt to reject nonexistent batch!");
        mutationQueue.removeMutationBatch(toReject);
        mutationQueue.performConsistencyCheck();
        documentOverlayCache.removeOverlaysForBatchId(batchId);
        localDocuments.recalculateAndSaveOverlays(toReject.getKeys());
        return localDocuments.getDocuments(toReject.getKeys());
    });
}
Also used : MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch)

Example 29 with MutationBatch

use of com.google.firebase.firestore.model.mutation.MutationBatch in project firebase-android-sdk by firebase.

the class MemoryMutationQueue method lookupMutationBatch.

@Nullable
@Override
public MutationBatch lookupMutationBatch(int batchId) {
    int index = indexOfBatchId(batchId);
    if (index < 0 || index >= queue.size()) {
        return null;
    }
    MutationBatch batch = queue.get(index);
    hardAssert(batch.getBatchId() == batchId, "If found batch must match");
    return batch;
}
Also used : MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) Nullable(androidx.annotation.Nullable)

Example 30 with MutationBatch

use of com.google.firebase.firestore.model.mutation.MutationBatch in project firebase-android-sdk by firebase.

the class MemoryMutationQueue method addMutationBatch.

@Override
public MutationBatch addMutationBatch(Timestamp localWriteTime, List<Mutation> baseMutations, List<Mutation> mutations) {
    hardAssert(!mutations.isEmpty(), "Mutation batches should not be empty");
    int batchId = nextBatchId;
    nextBatchId += 1;
    int size = queue.size();
    if (size > 0) {
        MutationBatch prior = queue.get(size - 1);
        hardAssert(prior.getBatchId() < batchId, "Mutation batchIds must be monotonically increasing order");
    }
    MutationBatch batch = new MutationBatch(batchId, localWriteTime, baseMutations, mutations);
    queue.add(batch);
    // Track references by document key and index collection parents.
    for (Mutation mutation : mutations) {
        batchesByDocumentKey = batchesByDocumentKey.insert(new DocumentReference(mutation.getKey(), batchId));
        indexManager.addToCollectionParentIndex(mutation.getKey().getCollectionPath());
    }
    return batch;
}
Also used : MutationBatch(com.google.firebase.firestore.model.mutation.MutationBatch) Mutation(com.google.firebase.firestore.model.mutation.Mutation)

Aggregations

MutationBatch (com.google.firebase.firestore.model.mutation.MutationBatch)40 Test (org.junit.Test)15 Mutation (com.google.firebase.firestore.model.mutation.Mutation)13 ArrayList (java.util.ArrayList)12 DocumentKey (com.google.firebase.firestore.model.DocumentKey)11 SetMutation (com.google.firebase.firestore.model.mutation.SetMutation)8 PatchMutation (com.google.firebase.firestore.model.mutation.PatchMutation)7 TestUtil.setMutation (com.google.firebase.firestore.testutil.TestUtil.setMutation)6 Write (com.google.firestore.v1.Write)5 ByteString (com.google.protobuf.ByteString)5 HashSet (java.util.HashSet)5 WriteBatch (com.google.firebase.firestore.proto.WriteBatch)4 TestUtil.patchMutation (com.google.firebase.firestore.testutil.TestUtil.patchMutation)4 MutableDocument (com.google.firebase.firestore.model.MutableDocument)3 Timestamp (com.google.firebase.Timestamp)2 ImmutableSortedMap (com.google.firebase.database.collection.ImmutableSortedMap)2 Query (com.google.firebase.firestore.core.Query)2 SnapshotVersion (com.google.firebase.firestore.model.SnapshotVersion)2 MutationBatchResult (com.google.firebase.firestore.model.mutation.MutationBatchResult)2 TestUtil.deleteMutation (com.google.firebase.firestore.testutil.TestUtil.deleteMutation)2