Search in sources :

Example 36 with FieldIndex

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

the class SQLiteLocalStoreTest method testIndexesServerTimestamps.

@Test
public void testIndexesServerTimestamps() {
    FieldIndex index = fieldIndex("coll", 0, FieldIndex.INITIAL_STATE, "time", FieldIndex.Segment.Kind.ASCENDING);
    configureFieldIndexes(singletonList(index));
    writeMutation(setMutation("coll/a", map("time", FieldValue.serverTimestamp())));
    backfillIndexes();
    Query query = query("coll").orderBy(orderBy("time", "asc"));
    executeQuery(query);
    assertOverlaysRead(/* byKey= */
    1, /* byCollection= */
    0);
    assertQueryReturned("coll/a");
}
Also used : FieldIndex(com.google.firebase.firestore.model.FieldIndex) Query(com.google.firebase.firestore.core.Query) Test(org.junit.Test)

Example 37 with FieldIndex

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

the class SQLiteLocalStoreTest method testDoesNotResetIndexWhenSameIndexIsAdded.

@Test
public void testDoesNotResetIndexWhenSameIndexIsAdded() {
    FieldIndex indexA = fieldIndex("coll", 0, FieldIndex.INITIAL_STATE, "a", FieldIndex.Segment.Kind.ASCENDING);
    configureFieldIndexes(singletonList(indexA));
    Collection<FieldIndex> fieldIndexes = getFieldIndexes();
    assertThat(fieldIndexes).containsExactly(indexA);
    Query query = query("coll").filter(filter("a", "==", 1));
    int targetId = allocateQuery(query);
    applyRemoteEvent(addedRemoteEvent(doc("coll/a", 10, map("a", 1)), targetId));
    backfillIndexes();
    FieldIndex updatedIndexA = fieldIndex("coll", 0, FieldIndex.IndexState.create(1, version(10), key("coll/a"), -1), "a", FieldIndex.Segment.Kind.ASCENDING);
    fieldIndexes = getFieldIndexes();
    assertThat(fieldIndexes).containsExactly(updatedIndexA);
    // Re-add the same index. We do not reset the index to its initial state.
    configureFieldIndexes(singletonList(indexA));
    fieldIndexes = getFieldIndexes();
    assertThat(fieldIndexes).containsExactly(updatedIndexA);
}
Also used : FieldIndex(com.google.firebase.firestore.model.FieldIndex) Query(com.google.firebase.firestore.core.Query) Test(org.junit.Test)

Example 38 with FieldIndex

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

the class SQLiteLocalStoreTest method testRemovesIndexes.

@Test
public void testRemovesIndexes() {
    FieldIndex indexA = fieldIndex("coll", 0, FieldIndex.INITIAL_STATE, "a", FieldIndex.Segment.Kind.ASCENDING);
    FieldIndex indexB = fieldIndex("coll", 1, FieldIndex.INITIAL_STATE, "b", FieldIndex.Segment.Kind.DESCENDING);
    configureFieldIndexes(Arrays.asList(indexA, indexB));
    Collection<FieldIndex> fieldIndexes = getFieldIndexes();
    assertThat(fieldIndexes).containsExactly(indexA, indexB);
    configureFieldIndexes(singletonList(indexA));
    fieldIndexes = getFieldIndexes();
    assertThat(fieldIndexes).containsExactly(indexA);
}
Also used : FieldIndex(com.google.firebase.firestore.model.FieldIndex) Test(org.junit.Test)

Example 39 with FieldIndex

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

the class SQLiteLocalStoreTest method testDeletedDocumentRemovesIndex.

@Test
public void testDeletedDocumentRemovesIndex() {
    FieldIndex index = fieldIndex("coll", 0, FieldIndex.INITIAL_STATE, "matches", FieldIndex.Segment.Kind.ASCENDING);
    configureFieldIndexes(singletonList(index));
    Query query = query("coll").filter(filter("matches", "==", true));
    int targetId = allocateQuery(query);
    applyRemoteEvent(addedRemoteEvent(doc("coll/a", 10, map("matches", true)), targetId));
    // Add the document to the index
    backfillIndexes();
    executeQuery(query);
    assertRemoteDocumentsRead(/* byKey= */
    1, /* byQuery= */
    0);
    assertQueryReturned("coll/a");
    applyRemoteEvent(updateRemoteEvent(deletedDoc("coll/a", 0), singletonList(targetId), emptyList()));
    // No backfill needed for deleted document.
    executeQuery(query);
    assertRemoteDocumentsRead(/* byKey= */
    0, /* byQuery= */
    0);
    assertQueryReturned();
}
Also used : FieldIndex(com.google.firebase.firestore.model.FieldIndex) Query(com.google.firebase.firestore.core.Query) Test(org.junit.Test)

Example 40 with FieldIndex

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

the class SQLiteIndexManager method getDocumentsMatchingTarget.

@Override
public Set<DocumentKey> getDocumentsMatchingTarget(Target target) {
    hardAssert(started, "IndexManager not started");
    List<String> subQueries = new ArrayList<>();
    List<Object> bindings = new ArrayList<>();
    for (Target subTarget : getSubTargets(target)) {
        FieldIndex fieldIndex = getFieldIndex(subTarget);
        if (fieldIndex == null) {
            return null;
        }
        @Nullable List<Value> arrayValues = subTarget.getArrayValues(fieldIndex);
        @Nullable Collection<Value> notInValues = subTarget.getNotInValues(fieldIndex);
        @Nullable Bound lowerBound = subTarget.getLowerBound(fieldIndex);
        @Nullable Bound upperBound = subTarget.getUpperBound(fieldIndex);
        if (Logger.isDebugEnabled()) {
            Logger.debug(TAG, "Using index '%s' to execute '%s' (Arrays: %s, Lower bound: %s, Upper bound: %s)", fieldIndex, subTarget, arrayValues, lowerBound, upperBound);
        }
        Object[] lowerBoundEncoded = encodeBound(fieldIndex, subTarget, lowerBound);
        String lowerBoundOp = lowerBound != null && lowerBound.isInclusive() ? ">=" : ">";
        Object[] upperBoundEncoded = encodeBound(fieldIndex, subTarget, upperBound);
        String upperBoundOp = upperBound != null && upperBound.isInclusive() ? "<=" : "<";
        Object[] notInEncoded = encodeValues(fieldIndex, subTarget, notInValues);
        Object[] subQueryAndBindings = generateQueryAndBindings(subTarget, fieldIndex.getIndexId(), arrayValues, lowerBoundEncoded, lowerBoundOp, upperBoundEncoded, upperBoundOp, notInEncoded);
        subQueries.add(String.valueOf(subQueryAndBindings[0]));
        bindings.addAll(Arrays.asList(subQueryAndBindings).subList(1, subQueryAndBindings.length));
    }
    String queryString;
    if (subQueries.size() == 1) {
        // If there's only one subQuery, just execute the one subQuery.
        queryString = subQueries.get(0);
    } else {
        // Construct "SELECT * FROM (subQuery1 UNION subQuery2 UNION ...) LIMIT N"
        queryString = "SELECT * FROM (" + TextUtils.join(" UNION ", subQueries) + ")";
        if (target.getLimit() != -1) {
            queryString = queryString + " LIMIT " + target.getLimit();
        }
    }
    hardAssert(bindings.size() < 1000, "Cannot perform query with more than 999 bind elements");
    SQLitePersistence.Query query = db.query(queryString).binding(bindings.toArray());
    Set<DocumentKey> result = new HashSet<>();
    query.forEach(row -> result.add(DocumentKey.fromPath(ResourcePath.fromString(row.getString(0)))));
    Logger.debug(TAG, "Index scan returned %s documents", result.size());
    return result;
}
Also used : FieldIndex(com.google.firebase.firestore.model.FieldIndex) ArrayList(java.util.ArrayList) Bound(com.google.firebase.firestore.core.Bound) Target(com.google.firebase.firestore.core.Target) Value(com.google.firestore.v1.Value) DocumentKey(com.google.firebase.firestore.model.DocumentKey) Nullable(androidx.annotation.Nullable) HashSet(java.util.HashSet)

Aggregations

FieldIndex (com.google.firebase.firestore.model.FieldIndex)49 Test (org.junit.Test)32 Nullable (androidx.annotation.Nullable)8 Value (com.google.firestore.v1.Value)8 Query (com.google.firebase.firestore.core.Query)6 ArrayList (java.util.ArrayList)6 DocumentKey (com.google.firebase.firestore.model.DocumentKey)3 DirectionalIndexByteEncoder (com.google.firebase.firestore.index.DirectionalIndexByteEncoder)2 IndexByteEncoder (com.google.firebase.firestore.index.IndexByteEncoder)2 IndexEntry (com.google.firebase.firestore.index.IndexEntry)2 IndexOffset (com.google.firebase.firestore.model.FieldIndex.IndexOffset)2 HashMap (java.util.HashMap)2 VisibleForTesting (androidx.annotation.VisibleForTesting)1 Timestamp (com.google.firebase.Timestamp)1 ImmutableSortedMap (com.google.firebase.database.collection.ImmutableSortedMap)1 Bound (com.google.firebase.firestore.core.Bound)1 Target (com.google.firebase.firestore.core.Target)1 Document (com.google.firebase.firestore.model.Document)1 FieldPath (com.google.firebase.firestore.model.FieldPath)1 SnapshotVersion (com.google.firebase.firestore.model.SnapshotVersion)1