diff --git a/firebase-firestore/api.txt b/firebase-firestore/api.txt index cd59b8392fa..87c89e40a57 100644 --- a/firebase-firestore/api.txt +++ b/firebase-firestore/api.txt @@ -207,7 +207,6 @@ package com.google.firebase.firestore { method public com.google.firebase.firestore.LoadBundleTask loadBundle(java.io.InputStream); method public com.google.firebase.firestore.LoadBundleTask loadBundle(java.nio.ByteBuffer); method public com.google.firebase.firestore.PipelineSource pipeline(); - method public com.google.firebase.firestore.RealtimePipelineSource realtimePipeline(); method public com.google.android.gms.tasks.Task runBatch(com.google.firebase.firestore.WriteBatch.Function); method public com.google.android.gms.tasks.Task runTransaction(com.google.firebase.firestore.Transaction.Function); method public com.google.android.gms.tasks.Task runTransaction(com.google.firebase.firestore.TransactionOptions, com.google.firebase.firestore.Transaction.Function); @@ -613,19 +612,6 @@ package com.google.firebase.firestore { method public java.util.List toObjects(Class, com.google.firebase.firestore.DocumentSnapshot.ServerTimestampBehavior); } - public final class RealtimePipeline { - method public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(com.google.firebase.firestore.EventListener listener); - method public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(com.google.firebase.firestore.RealtimePipelineOptions options, com.google.firebase.firestore.EventListener listener); - method public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(java.util.concurrent.Executor executor, com.google.firebase.firestore.EventListener listener); - method public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(java.util.concurrent.Executor executor, com.google.firebase.firestore.RealtimePipelineOptions options, com.google.firebase.firestore.EventListener listener); - method public String canonicalId(); - method public com.google.firebase.firestore.RealtimePipeline limit(int limit); - method public kotlinx.coroutines.flow.Flow snapshots(); - method public kotlinx.coroutines.flow.Flow snapshots(com.google.firebase.firestore.RealtimePipelineOptions options); - method public com.google.firebase.firestore.RealtimePipeline sort(com.google.firebase.firestore.pipeline.Ordering order, com.google.firebase.firestore.pipeline.Ordering... additionalOrders); - method public com.google.firebase.firestore.RealtimePipeline where(com.google.firebase.firestore.pipeline.BooleanExpression condition); - } - public final class RealtimePipelineOptions { ctor public RealtimePipelineOptions(); method public com.google.firebase.firestore.RealtimePipelineOptions withMetadataChanges(com.google.firebase.firestore.MetadataChanges metadataChanges); @@ -646,13 +632,6 @@ package com.google.firebase.firestore { property public final java.util.List results; } - public final class RealtimePipelineSource { - method public com.google.firebase.firestore.RealtimePipeline collection(com.google.firebase.firestore.CollectionReference ref); - method public com.google.firebase.firestore.RealtimePipeline collection(String path); - method public com.google.firebase.firestore.RealtimePipeline collectionGroup(String collectionId); - method public com.google.firebase.firestore.RealtimePipeline convertFrom(com.google.firebase.firestore.Query query); - } - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) public @interface ServerTimestamp { } diff --git a/firebase-firestore/gradle.properties b/firebase-firestore/gradle.properties index e95453bed4d..ae1d78e56cf 100644 --- a/firebase-firestore/gradle.properties +++ b/firebase-firestore/gradle.properties @@ -1,2 +1,2 @@ -version=25.1.5 +version=99.0.0-pipeline.preview.1 latestReleasedVersion=25.1.4 diff --git a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java index 58354c82541..1275a5d8798 100644 --- a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java +++ b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/testutil/IntegrationTestUtil.java @@ -100,7 +100,7 @@ public enum TargetBackend { // Set this to the desired enum value to change the target backend when running tests locally. // Note: DO NOT change this variable except for local testing. - private static final TargetBackend backendForLocalTesting = TargetBackend.EMULATOR; + private static final TargetBackend backendForLocalTesting = TargetBackend.PROD; private static final TargetBackend backend = getTargetBackend(); private static final String EMULATOR_HOST = "10.0.2.2"; diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java index 08d5176dac3..0d7ae64a3e3 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/FirebaseFirestore.java @@ -911,7 +911,7 @@ public PipelineSource pipeline() { * @return {@code RealtimePipelineSource} for this Firestore instance. */ @NonNull - public RealtimePipelineSource realtimePipeline() { + RealtimePipelineSource realtimePipeline() { clientProvider.ensureConfigured(); return new RealtimePipelineSource(this); } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/RealtimePipeline.kt b/firebase-firestore/src/main/java/com/google/firebase/firestore/RealtimePipeline.kt index 1f7eacd9890..addda2fa644 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/RealtimePipeline.kt +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/RealtimePipeline.kt @@ -48,7 +48,8 @@ import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow -class RealtimePipelineSource internal constructor(private val firestore: FirebaseFirestore) { +internal class RealtimePipelineSource +internal constructor(private val firestore: FirebaseFirestore) { /** * Convert the given Query into an equivalent Pipeline. * @@ -127,7 +128,7 @@ class RealtimePipelineSource internal constructor(private val firestore: Firebas ) } -class RealtimePipeline +internal class RealtimePipeline internal constructor( // This is nullable because RealtimePipeline is also created from deserialization from persistent // cache. In that case, it is only used to facilitate remote store requests, and this field is diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/PipelineUtil.kt b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/PipelineUtil.kt index f8a07a2ca53..051fc719c17 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/PipelineUtil.kt +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/PipelineUtil.kt @@ -32,8 +32,8 @@ import com.google.firebase.firestore.util.Assert.hardAssert /** A class that wraps either a Query or a RealtimePipeline. */ sealed class QueryOrPipeline { - data class QueryWrapper(val query: Query) : QueryOrPipeline() - data class PipelineWrapper(val pipeline: RealtimePipeline) : QueryOrPipeline() + internal data class QueryWrapper(internal val query: Query) : QueryOrPipeline() + internal data class PipelineWrapper(internal val pipeline: RealtimePipeline) : QueryOrPipeline() val isQuery: Boolean get() = this is QueryWrapper @@ -45,7 +45,7 @@ sealed class QueryOrPipeline { return (this as QueryWrapper).query } - fun pipeline(): RealtimePipeline { + internal fun pipeline(): RealtimePipeline { return (this as PipelineWrapper).pipeline } @@ -102,7 +102,7 @@ sealed class QueryOrPipeline { /** A class that wraps either a Target or a RealtimePipeline. */ sealed class TargetOrPipeline { data class TargetWrapper(val target: Target) : TargetOrPipeline() - data class PipelineWrapper(val pipeline: RealtimePipeline) : TargetOrPipeline() + internal data class PipelineWrapper(val pipeline: RealtimePipeline) : TargetOrPipeline() val isTarget: Boolean get() = this is TargetWrapper @@ -114,7 +114,7 @@ sealed class TargetOrPipeline { return (this as TargetWrapper).target } - fun pipeline(): RealtimePipeline { + internal fun pipeline(): RealtimePipeline { return (this as PipelineWrapper).pipeline } @@ -178,7 +178,7 @@ enum class PipelineSourceType { } // Determines the flavor of the given pipeline based on its stages. -fun getPipelineFlavor(pipeline: RealtimePipeline): PipelineFlavor { +internal fun getPipelineFlavor(pipeline: RealtimePipeline): PipelineFlavor { // For now, it is only possible to construct RealtimePipeline that is kExact. // PORTING NOTE: the typescript implementation support other flavors already, // despite not being used. We can port that later. @@ -186,7 +186,7 @@ fun getPipelineFlavor(pipeline: RealtimePipeline): PipelineFlavor { } // Determines the source type of the given pipeline based on its first stage. -fun getPipelineSourceType(pipeline: RealtimePipeline): PipelineSourceType { +internal fun getPipelineSourceType(pipeline: RealtimePipeline): PipelineSourceType { hardAssert( !pipeline.stages.isEmpty(), "Pipeline must have at least one stage to determine its source.", @@ -202,7 +202,7 @@ fun getPipelineSourceType(pipeline: RealtimePipeline): PipelineSourceType { // Retrieves the collection group ID if the pipeline's source is a collection // group. -fun getPipelineCollectionGroup(pipeline: RealtimePipeline): String? { +internal fun getPipelineCollectionGroup(pipeline: RealtimePipeline): String? { if (getPipelineSourceType(pipeline) == PipelineSourceType.COLLECTION_GROUP) { hardAssert( !pipeline.stages.isEmpty(), @@ -217,7 +217,7 @@ fun getPipelineCollectionGroup(pipeline: RealtimePipeline): String? { } // Retrieves the collection path if the pipeline's source is a collection. -fun getPipelineCollection(pipeline: RealtimePipeline): String? { +internal fun getPipelineCollection(pipeline: RealtimePipeline): String? { if (getPipelineSourceType(pipeline) == PipelineSourceType.COLLECTION) { hardAssert( !pipeline.stages.isEmpty(), @@ -232,7 +232,7 @@ fun getPipelineCollection(pipeline: RealtimePipeline): String? { } // Retrieves the document pathes if the pipeline's source is a document source. -fun getPipelineDocuments(pipeline: RealtimePipeline): Array? { +internal fun getPipelineDocuments(pipeline: RealtimePipeline): Array? { if (getPipelineSourceType(pipeline) == PipelineSourceType.DOCUMENTS) { hardAssert( !pipeline.stages.isEmpty(), @@ -248,7 +248,7 @@ fun getPipelineDocuments(pipeline: RealtimePipeline): Array? { // Creates a new pipeline by replacing CollectionGroupSource stages with // CollectionSource stages using the provided path. -fun asCollectionPipelineAtPath( +internal fun asCollectionPipelineAtPath( pipeline: RealtimePipeline, path: ResourcePath, ): RealtimePipeline { @@ -271,7 +271,7 @@ fun asCollectionPipelineAtPath( ) } -fun getLastEffectiveLimit(pipeline: RealtimePipeline): Int? { +internal fun getLastEffectiveLimit(pipeline: RealtimePipeline): Int? { for (stagePtr in pipeline.rewrittenStages.asReversed()) { // Check if the stage is a LimitStage if (stagePtr is LimitStage) { diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/QueryListener.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/QueryListener.java index 5c8155c38f8..75d4cb831a6 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/QueryListener.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/QueryListener.java @@ -56,7 +56,9 @@ public QueryListener( if (query.isPipeline()) { this.query = new QueryOrPipeline.PipelineWrapper( - query.pipeline().withListenOptions$com_google_firebase_firebase_firestore(options)); + query + .pipeline$com_google_firebase_firebase_firestore() + .withListenOptions$com_google_firebase_firebase_firestore(options)); } else { this.query = query; } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/View.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/View.java index 057eb56e62e..89ed41ae156 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/View.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/View.java @@ -243,7 +243,9 @@ public DocumentChanges computeDocChanges( candidates.add((MutableDocument) doc); } List results = - this.query.pipeline().evaluate$com_google_firebase_firebase_firestore(candidates); + this.query + .pipeline$com_google_firebase_firebase_firestore() + .evaluate$com_google_firebase_firebase_firestore(candidates); DocumentSet newResults = DocumentSet.emptySet(query.comparator()); for (MutableDocument doc : results) { newResults = newResults.add(doc); @@ -501,7 +503,8 @@ private static int changeTypeOrder(DocumentViewChange change) { @Nullable private static Long getLimit(QueryOrPipeline query) { if (query.isPipeline()) { - Integer limit = getLastEffectiveLimit(query.pipeline()); + Integer limit = + getLastEffectiveLimit(query.pipeline$com_google_firebase_firebase_firestore()); if (limit == null) { return null; } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java index 9b88066022d..add4ef2d2eb 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalDocumentsView.java @@ -400,7 +400,7 @@ private ImmutableSortedMap getDocumentsMatchingCollection private ImmutableSortedMap getDocumentsMatchingPipeline( QueryOrPipeline queryOrPipeline, IndexOffset offset, @Nullable QueryContext context) { - RealtimePipeline pipeline = queryOrPipeline.pipeline(); + RealtimePipeline pipeline = queryOrPipeline.pipeline$com_google_firebase_firebase_firestore(); if (getPipelineSourceType(pipeline) == PipelineSourceType.COLLECTION_GROUP) { String collectionGroup = getPipelineCollectionGroup(pipeline); hardAssert( diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalSerializer.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalSerializer.java index b0015c48e9e..7afbc8637f4 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalSerializer.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalSerializer.java @@ -234,7 +234,7 @@ com.google.firebase.firestore.proto.Target encodeTargetData(TargetData targetDat com.google.firestore.v1.Target.PipelineQueryTarget.newBuilder() .setStructuredPipeline( target - .pipeline() + .pipeline$com_google_firebase_firebase_firestore() .toStructurePipelineProto$com_google_firebase_firebase_firestore())); } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/MemoryRemoteDocumentCache.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/MemoryRemoteDocumentCache.java index d15174cc9fe..31e529e3301 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/MemoryRemoteDocumentCache.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/MemoryRemoteDocumentCache.java @@ -112,7 +112,9 @@ public Map getDocumentsMatchingQuery( if (query.isQuery()) { path = query.query().getPath(); } else { - path = ResourcePath.fromString(getPipelineCollection(query.pipeline())); + path = + ResourcePath.fromString( + getPipelineCollection(query.pipeline$com_google_firebase_firebase_firestore())); } DocumentKey prefix = DocumentKey.fromPath(path.append("")); Iterator> iterator = docs.iteratorFrom(prefix); diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteRemoteDocumentCache.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteRemoteDocumentCache.java index 62d9fd35bb6..26d5075e95d 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteRemoteDocumentCache.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/local/SQLiteRemoteDocumentCache.java @@ -270,7 +270,8 @@ public Map getDocumentsMatchingQuery( if (query.isQuery()) { path = query.query().getPath(); } else { - String pathString = getPipelineCollection(query.pipeline()); + String pathString = + getPipelineCollection(query.pipeline$com_google_firebase_firebase_firestore()); hardAssert( pathString != null, "SQLiteRemoteDocumentCache.getDocumentsMatchingQuery receives pipeline without collection source."); diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/remote/RemoteSerializer.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/remote/RemoteSerializer.java index e7468a02a3b..1c82f0f9581 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/remote/RemoteSerializer.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/remote/RemoteSerializer.java @@ -511,7 +511,9 @@ public com.google.firestore.v1.Target encodeTarget(TargetData targetData) { PipelineQueryTarget.Builder pipelineBuilder = PipelineQueryTarget.newBuilder(); builder.setPipelineQuery( pipelineBuilder.setStructuredPipeline( - target.pipeline().toStructurePipelineProto$com_google_firebase_firebase_firestore())); + target + .pipeline$com_google_firebase_firebase_firestore() + .toStructurePipelineProto$com_google_firebase_firebase_firestore())); } else if (target.target().isDocumentQuery()) { builder.setDocuments(encodeDocumentsTarget(target.target())); } else { diff --git a/firebase-firestore/src/test/java/com/google/firebase/firestore/local/LocalSerializerTest.java b/firebase-firestore/src/test/java/com/google/firebase/firestore/local/LocalSerializerTest.java index 06714fb0ddf..15ab285d246 100644 --- a/firebase-firestore/src/test/java/com/google/firebase/firestore/local/LocalSerializerTest.java +++ b/firebase-firestore/src/test/java/com/google/firebase/firestore/local/LocalSerializerTest.java @@ -34,6 +34,7 @@ import com.google.firebase.Timestamp; import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.RealtimePipeline; +import com.google.firebase.firestore.RealtimePipelineSource; import com.google.firebase.firestore.bundle.BundledQuery; import com.google.firebase.firestore.core.Query; import com.google.firebase.firestore.core.Target; @@ -494,7 +495,7 @@ public void testEncodesLimitToLastQuery() { public void encodesTargetDataWithPipeline() { FirebaseFirestore db = com.google.firebase.firestore.TestUtil.firestore(); RealtimePipeline pipeline = - db.realtimePipeline() + new RealtimePipelineSource(db) .collection("rooms") .where(Expression.field("name").equal("test room")) .sort(Expression.field("age").descending()) diff --git a/firebase-firestore/src/test/java/com/google/firebase/firestore/local/SQLiteSchemaTest.java b/firebase-firestore/src/test/java/com/google/firebase/firestore/local/SQLiteSchemaTest.java index ceed4fa299b..05ecf357169 100644 --- a/firebase-firestore/src/test/java/com/google/firebase/firestore/local/SQLiteSchemaTest.java +++ b/firebase-firestore/src/test/java/com/google/firebase/firestore/local/SQLiteSchemaTest.java @@ -580,7 +580,11 @@ public void rewritesCanonicalIds() { String expectedCanonicalId = targetData.getTarget().isTarget() ? targetData.getTarget().target().getCanonicalId() - : targetData.getTarget().pipeline().toString(); + : targetData + .getTarget() + .pipeline$com_google_firebase_firebase_firestore() + .canonicalId$com_google_firebase_firebase_firestore() + .toString(); assertEquals(expectedCanonicalId, actualCanonicalId); } catch (InvalidProtocolBufferException e) { fail("Failed to decode Target data"); diff --git a/firebase-firestore/src/test/java/com/google/firebase/firestore/spec/SpecTestCase.java b/firebase-firestore/src/test/java/com/google/firebase/firestore/spec/SpecTestCase.java index 39652b04e14..64b4906e82f 100644 --- a/firebase-firestore/src/test/java/com/google/firebase/firestore/spec/SpecTestCase.java +++ b/firebase-firestore/src/test/java/com/google/firebase/firestore/spec/SpecTestCase.java @@ -1020,7 +1020,7 @@ private void assertEventMatches(JSONObject expected, QueryEvent actual) throws J if (usePipelineMode) { assertEquals( expectedQuery.toRealtimePipeline(db, new UserDataReader(databaseInfo.getDatabaseId())), - actual.queryOrPipeline.pipeline()); + actual.queryOrPipeline.pipeline$com_google_firebase_firebase_firestore()); } else { assertEquals(expectedQuery, actual.queryOrPipeline.query()); }