Skip to content

Commit 85aee5c

Browse files
committed
Firestore pipeline prototype
1 parent 7a4a98c commit 85aee5c

37 files changed

+1388
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <FirebaseFirestoreInternal/FIRPipelineBridge.h>

Firestore/Example/Firestore.xcodeproj/project.pbxproj

+10-2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@
127127
11F8EE69182C9699E90A9E3D /* database_info_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB38D92E20235D22000A432D /* database_info_test.cc */; };
128128
12158DFCEE09D24B7988A340 /* maybe_document.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE7E20B89AAC00B5BCE7 /* maybe_document.pb.cc */; };
129129
121F0FB9DCCBFB7573C7AF48 /* bundle_serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5C2A94EE24E60543F62CC35 /* bundle_serializer_test.cc */; };
130+
12260A2A2D56A3CE001766EB /* PipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12260A292D56A3CE001766EB /* PipelineTests.swift */; };
131+
12260A2B2D56A3CE001766EB /* PipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12260A292D56A3CE001766EB /* PipelineTests.swift */; };
132+
12260A2C2D56A3CE001766EB /* PipelineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12260A292D56A3CE001766EB /* PipelineTests.swift */; };
130133
124AAEE987451820F24EEA8E /* user_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = CCC9BD953F121B9E29F9AA42 /* user_test.cc */; };
131134
125B1048ECB755C2106802EB /* executor_std_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4687208F9B9100554BA2 /* executor_std_test.cc */; };
132135
1290FA77A922B76503AE407C /* lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */; };
@@ -1735,6 +1738,7 @@
17351738
0D964D4936953635AC7E0834 /* Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_01_bloom_filter_proto.json; sourceTree = "<group>"; };
17361739
0EE5300F8233D14025EF0456 /* string_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_test.mm; sourceTree = "<group>"; };
17371740
11984BA0A99D7A7ABA5B0D90 /* Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS/Pods-Firestore_Example_iOS-Firestore_SwiftTests_iOS.release.xcconfig"; sourceTree = "<group>"; };
1741+
12260A292D56A3CE001766EB /* PipelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineTests.swift; sourceTree = "<group>"; };
17381742
1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableFieldValueTests.swift; sourceTree = "<group>"; };
17391743
1235769422B86E65007DDFA9 /* FirestoreEncoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FirestoreEncoderTests.swift; sourceTree = "<group>"; };
17401744
124C932B22C1642C00CA8C2D /* CodableIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableIntegrationTests.swift; sourceTree = "<group>"; };
@@ -1797,7 +1801,7 @@
17971801
4334F87873015E3763954578 /* status_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = status_testing.h; sourceTree = "<group>"; };
17981802
4375BDCDBCA9938C7F086730 /* Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_5000_1_bloom_filter_proto.json; sourceTree = "<group>"; };
17991803
444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = hard_assert_test.cc; sourceTree = "<group>"; };
1800-
4564AD9C55EC39C080EB9476 /* globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; path = globals_cache_test.cc; sourceTree = "<group>"; };
1804+
4564AD9C55EC39C080EB9476 /* globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = globals_cache_test.cc; sourceTree = "<group>"; };
18011805
478DC75A0DCA6249A616DD30 /* Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_0001_membership_test_result.json; sourceTree = "<group>"; };
18021806
48D0915834C3D234E5A875A9 /* grpc_stream_tester.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = grpc_stream_tester.h; sourceTree = "<group>"; };
18031807
4B3E4A77493524333133C5DC /* Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_1_bloom_filter_proto.json; sourceTree = "<group>"; };
@@ -1915,7 +1919,7 @@
19151919
5B5414D28802BC76FDADABD6 /* stream_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = stream_test.cc; sourceTree = "<group>"; };
19161920
5B96CC29E9946508F022859C /* Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.json; sourceTree = "<group>"; };
19171921
5C68EE4CB94C0DD6E333F546 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_1_01_membership_test_result.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_1_01_membership_test_result.json; sourceTree = "<group>"; };
1918-
5C6DEA63FBDE19D841291723 /* memory_globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; path = memory_globals_cache_test.cc; sourceTree = "<group>"; };
1922+
5C6DEA63FBDE19D841291723 /* memory_globals_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = memory_globals_cache_test.cc; sourceTree = "<group>"; };
19191923
5C7942B6244F4C416B11B86C /* leveldb_mutation_queue_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_mutation_queue_test.cc; sourceTree = "<group>"; };
19201924
5CAE131920FFFED600BE9A4A /* Firestore_Benchmarks_iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Firestore_Benchmarks_iOS.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
19211925
5CAE131D20FFFED600BE9A4A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -2296,6 +2300,7 @@
22962300
124C932B22C1642C00CA8C2D /* CodableIntegrationTests.swift */,
22972301
3355BE9391CC4857AF0BDAE3 /* DatabaseTests.swift */,
22982302
62E54B832A9E910A003347C8 /* IndexingTests.swift */,
2303+
12260A292D56A3CE001766EB /* PipelineTests.swift */,
22992304
621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */,
23002305
4D65F6E69993611D47DC8E7C /* SnapshotListenerSourceTests.swift */,
23012306
EFF22EA92C5060A4009A369B /* VectorIntegrationTests.swift */,
@@ -4685,6 +4690,7 @@
46854690
432056C4D1259F76C80FC2A8 /* FSTUserDataReaderTests.mm in Sources */,
46864691
3B1E27D951407FD237E64D07 /* FirestoreEncoderTests.swift in Sources */,
46874692
62E54B862A9E910B003347C8 /* IndexingTests.swift in Sources */,
4693+
12260A2C2D56A3CE001766EB /* PipelineTests.swift in Sources */,
46884694
621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
46894695
1CFBD4563960D8A20C4679A3 /* SnapshotListenerSourceTests.swift in Sources */,
46904696
EFF22EAC2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
@@ -4935,6 +4941,7 @@
49354941
75A176239B37354588769206 /* FSTUserDataReaderTests.mm in Sources */,
49364942
5E89B1A5A5430713C79C4854 /* FirestoreEncoderTests.swift in Sources */,
49374943
62E54B852A9E910B003347C8 /* IndexingTests.swift in Sources */,
4944+
12260A2B2D56A3CE001766EB /* PipelineTests.swift in Sources */,
49384945
621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
49394946
A0BC30D482B0ABD1A3A24CDC /* SnapshotListenerSourceTests.swift in Sources */,
49404947
EFF22EAB2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
@@ -5440,6 +5447,7 @@
54405447
F5BDECEB3B43BD1591EEADBD /* FSTUserDataReaderTests.mm in Sources */,
54415448
6F45846C159D3C063DBD3CBE /* FirestoreEncoderTests.swift in Sources */,
54425449
62E54B842A9E910B003347C8 /* IndexingTests.swift in Sources */,
5450+
12260A2A2D56A3CE001766EB /* PipelineTests.swift in Sources */,
54435451
621D620A28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
54445452
B00F8D1819EE20C45B660940 /* SnapshotListenerSourceTests.swift in Sources */,
54455453
EFF22EAA2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,

Firestore/Source/API/FIRFirestore+Internal.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 Google
2+
* Copyright 2025 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "FIRPipelineBridge.h"
18+
19+
#include <memory>
20+
21+
#include "Firestore/core/src/api/expressions.h"
22+
#include "Firestore/core/src/api/pipeline.h"
23+
#include "Firestore/core/src/api/stages.h"
24+
25+
@class FIRFilter;
26+
27+
namespace api = firebase::firestore::api;
28+
29+
NS_ASSUME_NONNULL_BEGIN
30+
31+
@interface FIRExprBridge (Internal)
32+
33+
- (std::shared_ptr<api::Expr>)cpp_expr;
34+
35+
@end
36+
37+
@interface FIRStageBridge (Internal)
38+
39+
- (std::shared_ptr<api::Stage>)cpp_stage;
40+
41+
@end
42+
43+
@interface __FIRPipelineSnapshotBridge (Internal)
44+
45+
- (id)initWithCppSnapshot:(api::PipelineSnapshot)snapshot;
46+
47+
@end
48+
49+
NS_ASSUME_NONNULL_END
+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import "FIRPipelineBridge.h"
18+
19+
#include <memory>
20+
21+
#import "Firestore/Source/API/FIRFirestore+Internal.h"
22+
#import "Firestore/Source/API/FIRPipelineBridge+Internal.h"
23+
24+
#include "Firestore/core/src/api/expressions.h"
25+
#include "Firestore/core/src/api/pipeline.h"
26+
#include "Firestore/core/src/api/pipeline_result.h"
27+
#include "Firestore/core/src/api/pipeline_snapshot.h"
28+
#include "Firestore/core/src/api/stages.h"
29+
#include "Firestore/core/src/util/error_apple.h"
30+
#include "Firestore/core/src/util/status.h"
31+
#include "Firestore/core/src/util/string_apple.h"
32+
33+
using firebase::firestore::api::CollectionSource;
34+
using firebase::firestore::api::Constant;
35+
using firebase::firestore::api::Expr;
36+
using firebase::firestore::api::Field;
37+
using firebase::firestore::api::FunctionExpr;
38+
using firebase::firestore::api::Pipeline;
39+
using firebase::firestore::api::Where;
40+
using firebase::firestore::util::MakeCallback;
41+
using firebase::firestore::util::MakeString;
42+
43+
NS_ASSUME_NONNULL_BEGIN
44+
45+
@implementation FIRExprBridge
46+
@end
47+
48+
@implementation FIRFieldBridge {
49+
std::shared_ptr<Field> field;
50+
}
51+
52+
- (id)init:(NSString *)name {
53+
self = [super init];
54+
if (self) {
55+
field = std::make_shared<Field>(MakeString(name));
56+
}
57+
return self;
58+
}
59+
60+
- (std::shared_ptr<api::Expr>)cpp_expr {
61+
return field;
62+
}
63+
64+
@end
65+
66+
@implementation FIRConstantBridge {
67+
std::shared_ptr<Constant> constant;
68+
}
69+
- (id)init:(NSNumber *)value {
70+
self = [super init];
71+
if (self) {
72+
constant = std::make_shared<Constant>(value.doubleValue);
73+
}
74+
return self;
75+
}
76+
77+
- (std::shared_ptr<api::Expr>)cpp_expr {
78+
return constant;
79+
}
80+
81+
@end
82+
83+
@implementation FIRFunctionExprBridge {
84+
std::shared_ptr<FunctionExpr> eq;
85+
}
86+
87+
- (nonnull id)initWithName:(NSString *)name Args:(nonnull NSArray<FIRExprBridge *> *)args {
88+
self = [super init];
89+
if (self) {
90+
std::vector<std::shared_ptr<Expr>> cpp_args;
91+
for (FIRExprBridge *arg in args) {
92+
cpp_args.push_back(arg.cpp_expr);
93+
}
94+
95+
eq = std::make_shared<FunctionExpr>(MakeString(name), std::move(cpp_args));
96+
}
97+
return self;
98+
}
99+
100+
- (std::shared_ptr<api::Expr>)cpp_expr {
101+
return eq;
102+
}
103+
104+
@end
105+
106+
@implementation FIRStageBridge
107+
@end
108+
109+
@implementation FIRCollectionSourceStageBridge {
110+
std::shared_ptr<CollectionSource> collection_source;
111+
}
112+
113+
- (id)initWithPath:(NSString *)path {
114+
self = [super init];
115+
if (self) {
116+
collection_source = std::make_shared<CollectionSource>(MakeString(path));
117+
}
118+
return self;
119+
}
120+
121+
- (std::shared_ptr<api::Stage>)cpp_stage {
122+
return collection_source;
123+
}
124+
125+
@end
126+
127+
@implementation FIRWhereStageBridge {
128+
std::shared_ptr<Where> where;
129+
}
130+
131+
- (id)initWithExpr:(FIRExprBridge *)expr {
132+
self = [super init];
133+
if (self) {
134+
where = std::make_shared<Where>(expr.cpp_expr);
135+
}
136+
return self;
137+
}
138+
139+
- (std::shared_ptr<api::Stage>)cpp_stage {
140+
return where;
141+
}
142+
143+
@end
144+
145+
@implementation __FIRPipelineSnapshotBridge {
146+
absl::optional<api::PipelineSnapshot> pipeline;
147+
}
148+
149+
- (id)initWithCppSnapshot:(api::PipelineSnapshot)snapshot {
150+
self = [super init];
151+
if (self) {
152+
pipeline = std::move(snapshot);
153+
}
154+
155+
return self;
156+
}
157+
158+
@end
159+
160+
@implementation FIRPipelineBridge {
161+
std::shared_ptr<Pipeline> pipeline;
162+
}
163+
164+
- (id)initWithStages:(NSArray<FIRStageBridge *> *)stages db:(FIRFirestore *)db {
165+
self = [super init];
166+
if (self) {
167+
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
168+
for (FIRStageBridge *stage in stages) {
169+
cpp_stages.push_back(stage.cpp_stage);
170+
}
171+
pipeline = std::make_shared<Pipeline>(cpp_stages, db.wrapped);
172+
}
173+
return self;
174+
}
175+
176+
- (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge *_Nullable result,
177+
NSError *_Nullable error))completion {
178+
pipeline->execute([completion](StatusOr<api::PipelineSnapshot> maybe_value) {
179+
if (maybe_value.ok()) {
180+
__FIRPipelineSnapshotBridge *bridge = [[__FIRPipelineSnapshotBridge alloc]
181+
initWithCppSnapshot:std::move(maybe_value).ValueOrDie()];
182+
completion(bridge, nil);
183+
} else {
184+
completion(nil, MakeNSError(std::move(maybe_value).status()));
185+
}
186+
});
187+
}
188+
189+
@end
190+
191+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)