Skip to content

Pipeline tests part 2 #14951

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 65 commits into
base: cheryllin/ppl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
bd0ce8f
create main branch of ppl
cherylEnkidu Feb 27, 2025
84691ab
Add stage API
cherylEnkidu Feb 27, 2025
8519a5e
Add stage API
cherylEnkidu Mar 3, 2025
454893b
Add stage API
cherylEnkidu Mar 7, 2025
ed1a19b
API changes
cherylEnkidu Mar 12, 2025
819853c
Add cpp stages and expressions
wu-hui Mar 11, 2025
1be141b
Add more APIs
cherylEnkidu Mar 18, 2025
8fd5f8a
add Field
cherylEnkidu Mar 18, 2025
039b919
merge in main branch
cherylEnkidu Mar 19, 2025
5127bd0
Add UserDataReader support for constant and expr in pipelines
wu-hui Mar 17, 2025
14d2e5c
Add bridge
cherylEnkidu Mar 20, 2025
9895936
merge in push-pqrpmwtupmwv
cherylEnkidu Mar 20, 2025
5d701f8
Add UserDataReader support for constant and expr in pipelines
wu-hui Mar 17, 2025
b2af1c6
solve merge conflicts
cherylEnkidu Mar 20, 2025
cec7f6b
Fix merge conflicts
cherylEnkidu Mar 20, 2025
30b9251
solve conflicts
cherylEnkidu Mar 20, 2025
1ad093a
format and fix conflicts
cherylEnkidu Mar 20, 2025
b59a4fd
Remove placeholder for the test case
cherylEnkidu Mar 21, 2025
7d73155
Support tests
cherylEnkidu Mar 25, 2025
828bb12
Fix bug in decoding
cherylEnkidu Mar 27, 2025
d1d0aa4
Add some convert functions
cherylEnkidu Apr 1, 2025
113da45
add tests
cherylEnkidu Apr 2, 2025
39803e5
replace Any with sendable
cherylEnkidu Apr 2, 2025
6c78523
Update PipelineResult
cherylEnkidu Apr 3, 2025
9598764
add expression and stages
cherylEnkidu Apr 14, 2025
5a7f61f
merge changes
cherylEnkidu Apr 17, 2025
a5f558f
add tests
cherylEnkidu Apr 17, 2025
be5b0b2
change implementation details
cherylEnkidu Apr 24, 2025
e699c17
Add get for ppl result
cherylEnkidu Apr 24, 2025
daf1b68
revert test settings
cherylEnkidu Apr 24, 2025
5b2bd88
Change cmake version
cherylEnkidu Apr 25, 2025
04a16e2
merge in cmake settings
cherylEnkidu Apr 25, 2025
d324c5d
Merge branch 'cheryllin/ppl' into cheryllin/pplapi
cherylEnkidu Apr 26, 2025
23305c0
remove unused variable
cherylEnkidu Apr 28, 2025
6dd3515
revert settinggs
cherylEnkidu Apr 28, 2025
8ff71c2
add expressions
cherylEnkidu May 6, 2025
2372405
Add documentation to Pipeline.swift
cherylEnkidu May 6, 2025
c7ff4b7
merge in main
cherylEnkidu May 6, 2025
d5be6a0
Merge branch 'cheryllin/ppl' into cheryllin/pplapi
cherylEnkidu May 6, 2025
591816b
Fix replace with
cherylEnkidu May 7, 2025
0098829
change tests
cherylEnkidu May 8, 2025
4fb738d
Address feebacks 2
cherylEnkidu May 12, 2025
6ec8b6c
Address feedbacks 3
cherylEnkidu May 13, 2025
fd51b7b
change mutating fields
cherylEnkidu May 13, 2025
469b768
[Firestore] On SPM, import FirebaseFirestoreInternalWrapper (#14848)
ncooke3 May 13, 2025
ba94c32
add version restrictions
cherylEnkidu May 13, 2025
d1d1a89
Fix CI tests
cherylEnkidu May 15, 2025
65475b6
enable nightly build
cherylEnkidu May 15, 2025
f4b00ab
revert settings
cherylEnkidu May 15, 2025
f066ded
add tests and fix bugs
cherylEnkidu May 23, 2025
2437141
merge in base branch
cherylEnkidu May 23, 2025
71820c7
fix warning
cherylEnkidu May 23, 2025
8ce2a65
change addStage to rawStage
cherylEnkidu Jun 6, 2025
96c1710
fix build error
cherylEnkidu Jun 6, 2025
3e4d71a
remove local time
cherylEnkidu Jun 11, 2025
51086da
Add Constant tests
cherylEnkidu Jun 10, 2025
0f7d8ec
add more tests
cherylEnkidu Jun 11, 2025
38b89eb
add more tests
cherylEnkidu Jun 11, 2025
3a5ce84
More tests, some error is waiting for fix
cherylEnkidu Jun 11, 2025
69e9255
fix replacewith bug
cherylEnkidu Jun 11, 2025
5a2a98f
fix union stage
cherylEnkidu Jun 12, 2025
990c698
fix bugs in raw stage and unnest stage
cherylEnkidu Jun 16, 2025
aad77ae
Move test helper and fix raw stage test
cherylEnkidu Jun 17, 2025
be45ad4
add more tests
cherylEnkidu Jun 17, 2025
236b7b8
merge
cherylEnkidu Jun 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Firestore/Example/Firestore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,7 @@
A7309DAD4A3B5334536ECA46 /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; };
A7399FB3BEC50BBFF08EC9BA /* mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3068AA9DFBBA86C1FE2A946E /* mutation_queue_test.cc */; };
A7669E72BCED7FBADA4B1314 /* thread_safe_memoizer_testing_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EA10515F99A42D71DA2D2841 /* thread_safe_memoizer_testing_test.cc */; };
A78366DBE0BFDE42474A728A /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */; };
A80D38096052F928B17E1504 /* user_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = CCC9BD953F121B9E29F9AA42 /* user_test.cc */; };
A833A216988ADFD4876763CD /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C8FB22BCB9F454DA44BA80C8 /* Validation_BloomFilterTest_MD5_50000_01_membership_test_result.json */; };
A841EEB5A94A271523EAE459 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = A5D9044B72061CAF284BC9E4 /* Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json */; };
Expand Down Expand Up @@ -1172,6 +1173,7 @@
ACC9369843F5ED3BD2284078 /* timestamp_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABF6506B201131F8005F2C74 /* timestamp_test.cc */; };
AD00D000A63837FB47291BFE /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 4B59C0A7B2A4548496ED4E7D /* Validation_BloomFilterTest_MD5_1_0001_bloom_filter_proto.json */; };
AD12205540893CEB48647937 /* filesystem_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA02DA2FCD0001CFC6EB08DA /* filesystem_testing.cc */; };
AD34726BFD3461FF64BBD56D /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */; };
AD35AA07F973934BA30C9000 /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; };
AD3C26630E33BE59C49BEB0D /* grpc_unary_call_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D964942163E63900EB9CFB /* grpc_unary_call_test.cc */; };
AD74843082C6465A676F16A7 /* async_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB467B208E9A8200554BA2 /* async_queue_test.cc */; };
Expand Down Expand Up @@ -1572,6 +1574,7 @@
ED9DF1EB20025227B38736EC /* message_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = CE37875365497FFA8687B745 /* message_test.cc */; };
EDF35B147B116F659D0D2CA8 /* Validation_BloomFilterTest_MD5_1_0001_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = C939D1789E38C09F9A0C1157 /* Validation_BloomFilterTest_MD5_1_0001_membership_test_result.json */; };
EE470CC3C8FBCDA5F70A8466 /* local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 307FF03D0297024D59348EBD /* local_store_test.cc */; };
EE4C4BE7F93366AE6368EE02 /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */; };
EE6DBFB0874A50578CE97A7F /* leveldb_remote_document_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */; };
EECC1EC64CA963A8376FA55C /* persistence_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9113B6F513D0473AEABBAF1F /* persistence_testing.cc */; };
EF3518F84255BAF3EBD317F6 /* exponential_backoff_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D1B68420E2AB1A00B35856 /* exponential_backoff_test.cc */; };
Expand Down Expand Up @@ -1739,6 +1742,7 @@
062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncAwaitIntegrationTests.swift; sourceTree = "<group>"; };
0840319686A223CC4AD3FAB1 /* leveldb_remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_remote_document_cache_test.cc; sourceTree = "<group>"; };
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>"; };
0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TestHelper.swift; path = TestHelper/TestHelper.swift; sourceTree = "<group>"; };
0EE5300F8233D14025EF0456 /* string_apple_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_test.mm; sourceTree = "<group>"; };
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>"; };
1235769122B7E915007DDFA9 /* EncodableFieldValueTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodableFieldValueTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2599,6 +2603,7 @@
544A20ED20F6C046004E52CD /* API */,
5495EB012040E90200EBA509 /* Codable */,
124C932A22C1635300CA8C2D /* Integration */,
C7D3D622BB13EB3C3301DA4F /* TestHelper */,
620C1427763BA5D3CCFB5A1F /* BridgingHeader.h */,
54C9EDF52040E16300A969CD /* Info.plist */,
);
Expand Down Expand Up @@ -2978,6 +2983,14 @@
path = core;
sourceTree = "<group>";
};
C7D3D622BB13EB3C3301DA4F /* TestHelper */ = {
isa = PBXGroup;
children = (
0E73D03B9C02CAC7BEBAFA86 /* TestHelper.swift */,
);
name = TestHelper;
sourceTree = "<group>";
};
DAFF0CF621E64AC30062958F /* macOS */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -4699,6 +4712,7 @@
655F8647F57E5F2155DFF7B5 /* PipelineTests.swift in Sources */,
621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
1CFBD4563960D8A20C4679A3 /* SnapshotListenerSourceTests.swift in Sources */,
EE4C4BE7F93366AE6368EE02 /* TestHelper.swift in Sources */,
EFF22EAC2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
4D42E5C756229C08560DD731 /* XCTestCase+Await.mm in Sources */,
09BE8C01EC33D1FD82262D5D /* aggregate_query_test.cc in Sources */,
Expand Down Expand Up @@ -4951,6 +4965,7 @@
C8C2B945D84DD98391145F3F /* PipelineTests.swift in Sources */,
621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
A0BC30D482B0ABD1A3A24CDC /* SnapshotListenerSourceTests.swift in Sources */,
A78366DBE0BFDE42474A728A /* TestHelper.swift in Sources */,
EFF22EAB2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
736C4E82689F1CA1859C4A3F /* XCTestCase+Await.mm in Sources */,
412BE974741729A6683C386F /* aggregate_query_test.cc in Sources */,
Expand Down Expand Up @@ -5458,6 +5473,7 @@
E04CB0D580980748D5DC453F /* PipelineTests.swift in Sources */,
621D620A28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */,
B00F8D1819EE20C45B660940 /* SnapshotListenerSourceTests.swift in Sources */,
AD34726BFD3461FF64BBD56D /* TestHelper.swift in Sources */,
EFF22EAA2C5060A4009A369B /* VectorIntegrationTests.swift in Sources */,
5492E0442021457E00B64F25 /* XCTestCase+Await.mm in Sources */,
B04E4FE20930384DF3A402F9 /* aggregate_query_test.cc in Sources */,
Expand Down
114 changes: 84 additions & 30 deletions Firestore/Source/API/FIRPipelineBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -710,9 +710,11 @@ - (id)initWithPercentage:(double)percentage {
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
if (!isUserDataRead) {
if ([type isEqualToString:@"count"]) {
cpp_sample = std::make_shared<Sample>("count", _count, 0);
cpp_sample =
std::make_shared<Sample>(Sample::SampleMode(Sample::SampleMode::DOCUMENTS), _count, 0);
} else {
cpp_sample = std::make_shared<Sample>("percentage", 0, _percentage);
cpp_sample =
std::make_shared<Sample>(Sample::SampleMode(Sample::SampleMode::PERCENT), 0, _percentage);
}
}

Expand Down Expand Up @@ -750,30 +752,35 @@ - (id)initWithOther:(FIRPipelineBridge *)other {

@implementation FIRUnnestStageBridge {
FIRExprBridge *_field;
NSString *_Nullable _indexField;
FIRExprBridge *_Nullable _index_field;
FIRExprBridge *_alias;
Boolean isUserDataRead;
std::shared_ptr<Unnest> cpp_unnest;
}

- (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)indexField {
- (id)initWithField:(FIRExprBridge *)field
alias:(FIRExprBridge *)alias
indexField:(FIRExprBridge *_Nullable)index_field {
self = [super init];
if (self) {
_field = field;
_indexField = indexField;
_alias = alias;
_index_field = index_field;
isUserDataRead = NO;
}
return self;
}

- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
if (!isUserDataRead) {
absl::optional<std::string> cpp_index_field;
if (_indexField != nil) {
cpp_index_field = MakeString(_indexField);
absl::optional<std::shared_ptr<Expr>> cpp_index_field;
if (_index_field != nil) {
cpp_index_field = [_index_field cppExprWithReader:reader];
} else {
cpp_index_field = absl::nullopt;
}
cpp_unnest = std::make_shared<Unnest>([_field cppExprWithReader:reader], cpp_index_field);
cpp_unnest = std::make_shared<Unnest>([_field cppExprWithReader:reader],
[_alias cppExprWithReader:reader], cpp_index_field);
}

isUserDataRead = YES;
Expand All @@ -784,14 +791,14 @@ - (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)index

@implementation FIRRawStageBridge {
NSString *_name;
NSArray<FIRExprBridge *> *_params;
NSArray<id> *_params;
NSDictionary<NSString *, FIRExprBridge *> *_Nullable _options;
Boolean isUserDataRead;
std::shared_ptr<RawStage> cpp_generic_stage;
}

- (id)initWithName:(NSString *)name
params:(NSArray<FIRExprBridge *> *)params
params:(NSArray<id> *)params
options:(NSDictionary<NSString *, FIRExprBridge *> *_Nullable)options {
self = [super init];
if (self) {
Expand All @@ -803,12 +810,51 @@ - (id)initWithName:(NSString *)name
return self;
}

- (firebase::firestore::google_firestore_v1_Value)convertIdToV1Value:(id)value
reader:(FSTUserDataReader *)reader {
if ([value isKindOfClass:[FIRExprBridge class]]) {
return [((FIRExprBridge *)value) cppExprWithReader:reader]->to_proto();
} else if ([value isKindOfClass:[FIRAggregateFunctionBridge class]]) {
return [((FIRAggregateFunctionBridge *)value) cppExprWithReader:reader]->to_proto();
} else if ([value isKindOfClass:[NSDictionary class]]) {
NSDictionary<NSString *, id> *dictionary = (NSDictionary<NSString *, id> *)value;

std::unordered_map<std::string, firebase::firestore::google_firestore_v1_Value> cpp_dictionary;
for (NSString *key in dictionary) {
if ([dictionary[key] isKindOfClass:[FIRExprBridge class]]) {
cpp_dictionary[MakeString(key)] =
[((FIRExprBridge *)dictionary[key]) cppExprWithReader:reader]->to_proto();
} else if ([dictionary[key] isKindOfClass:[FIRAggregateFunctionBridge class]]) {
cpp_dictionary[MakeString(key)] =
[((FIRAggregateFunctionBridge *)dictionary[key]) cppExprWithReader:reader]->to_proto();
} else {
ThrowInvalidArgument(
"Dictionary value must be an FIRExprBridge or FIRAggregateFunctionBridge.");
}
}

firebase::firestore::google_firestore_v1_Value result;
result.which_value_type = google_firestore_v1_Value_map_value_tag;

nanopb::SetRepeatedField(
&result.map_value.fields, &result.map_value.fields_count, cpp_dictionary,
[](const std::pair<std::string, firebase::firestore::google_firestore_v1_Value> &entry) {
return firebase::firestore::_google_firestore_v1_MapValue_FieldsEntry{
nanopb::MakeBytesArray(entry.first), entry.second};
});
return result;
} else {
ThrowInvalidArgument("Invalid value to convert to google_firestore_v1_Value.");
}
}

- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
if (!isUserDataRead) {
std::vector<std::shared_ptr<Expr>> cpp_params;
for (FIRExprBridge *param in _params) {
cpp_params.push_back([param cppExprWithReader:reader]);
std::vector<firebase::firestore::google_firestore_v1_Value> cpp_params;
for (id param in _params) {
cpp_params.push_back([self convertIdToV1Value:param reader:reader]);
}

std::unordered_map<std::string, std::shared_ptr<Expr>> cpp_options;
if (_options) {
for (NSString *key in _options) {
Expand Down Expand Up @@ -928,7 +974,9 @@ - (id)initWithCppResult:(api::PipelineResult)result db:(std::shared_ptr<api::Fir
FSTUserDataWriter *dataWriter =
[[FSTUserDataWriter alloc] initWithFirestore:_db
serverTimestampBehavior:serverTimestampBehavior];
return [dataWriter convertedValue:*data];
NSDictionary<NSString *, id> *dictionary = [dataWriter convertedValue:*data];
NSLog(@"Dictionary contents: %@", dictionary);
return dictionary;
}

- (nullable id)get:(id)field {
Expand Down Expand Up @@ -959,35 +1007,41 @@ - (nullable id)get:(id)field
@implementation FIRPipelineBridge {
NSArray<FIRStageBridge *> *_stages;
FIRFirestore *firestore;
Boolean isUserDataRead;
std::shared_ptr<Pipeline> cpp_pipeline;
}

- (id)initWithStages:(NSArray<FIRStageBridge *> *)stages db:(FIRFirestore *)db {
_stages = stages;
firestore = db;
isUserDataRead = NO;
return [super init];
}

- (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge *_Nullable result,
NSError *_Nullable error))completion {
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
for (FIRStageBridge *stage in _stages) {
cpp_stages.push_back([stage cppStageWithReader:firestore.dataReader]);
}
cpp_pipeline = std::make_shared<Pipeline>(cpp_stages, firestore.wrapped);

cpp_pipeline->execute([completion](StatusOr<api::PipelineSnapshot> maybe_value) {
if (maybe_value.ok()) {
__FIRPipelineSnapshotBridge *bridge = [[__FIRPipelineSnapshotBridge alloc]
initWithCppSnapshot:std::move(maybe_value).ValueOrDie()];
completion(bridge, nil);
} else {
completion(nil, MakeNSError(std::move(maybe_value).status()));
}
});
[self cppPipelineWithReader:firestore.dataReader]->execute(
[completion](StatusOr<api::PipelineSnapshot> maybe_value) {
if (maybe_value.ok()) {
__FIRPipelineSnapshotBridge *bridge = [[__FIRPipelineSnapshotBridge alloc]
initWithCppSnapshot:std::move(maybe_value).ValueOrDie()];
completion(bridge, nil);
} else {
completion(nil, MakeNSError(std::move(maybe_value).status()));
}
});
}

- (std::shared_ptr<api::Pipeline>)cppPipelineWithReader:(FSTUserDataReader *)reader {
if (!isUserDataRead) {
std::vector<std::shared_ptr<firebase::firestore::api::Stage>> cpp_stages;
for (FIRStageBridge *stage in _stages) {
cpp_stages.push_back([stage cppStageWithReader:firestore.dataReader]);
}
cpp_pipeline = std::make_shared<Pipeline>(cpp_stages, firestore.wrapped);
}

isUserDataRead = YES;
return cpp_pipeline;
}

Expand Down
6 changes: 4 additions & 2 deletions Firestore/Source/Public/FirebaseFirestore/FIRPipelineBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,16 @@ NS_SWIFT_NAME(UnionStageBridge)
NS_SWIFT_SENDABLE
NS_SWIFT_NAME(UnnestStageBridge)
@interface FIRUnnestStageBridge : FIRStageBridge
- (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)indexField;
- (id)initWithField:(FIRExprBridge *)field
alias:(FIRExprBridge *)alias
indexField:(FIRExprBridge *_Nullable)index_field;
@end

NS_SWIFT_SENDABLE
NS_SWIFT_NAME(RawStageBridge)
@interface FIRRawStageBridge : FIRStageBridge
- (id)initWithName:(NSString *)name
params:(NSArray<FIRExprBridge *> *)params
params:(NSArray<id> *)params
options:(NSDictionary<NSString *, FIRExprBridge *> *_Nullable)options;
@end

Expand Down
45 changes: 38 additions & 7 deletions Firestore/Swift/Source/Helper/PipelineHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@
// limitations under the License.

enum Helper {
static func sendableToExpr(_ value: Sendable) -> Expr {
static func sendableToExpr(_ value: Sendable?) -> Expr {
guard let value = value else {
return Constant.nil
}

if value is Expr {
return value as! Expr
} else if value is [String: Sendable] {
return map(value as! [String: Sendable])
} else if value is [Sendable] {
return array(value as! [Sendable])
} else if value is [String: Sendable?] {
return map(value as! [String: Sendable?])
} else if value is [Sendable?] {
return array(value as! [Sendable?])
} else {
return Constant(value)
}
Expand All @@ -33,7 +37,7 @@ enum Helper {
return exprMap
}

static func map(_ elements: [String: Sendable]) -> FunctionExpr {
static func map(_ elements: [String: Sendable?]) -> FunctionExpr {
var result: [Expr] = []
for (key, value) in elements {
result.append(Constant(key))
Expand All @@ -42,10 +46,37 @@ enum Helper {
return FunctionExpr("map", result)
}

static func array(_ elements: [Sendable]) -> FunctionExpr {
static func array(_ elements: [Sendable?]) -> FunctionExpr {
let transformedElements = elements.map { element in
sendableToExpr(element)
}
return FunctionExpr("array", transformedElements)
}

// This function is used to convert Swift type into Objective-C type.
static func sendableToAnyObjectForRawStage(_ value: Sendable?) -> AnyObject {
guard let value = value else {
return Constant.nil.bridge
}

guard !(value is NSNull) else {
return Constant.nil.bridge
}

if value is Expr {
return (value as! Expr).toBridge()
} else if value is AggregateFunction {
return (value as! AggregateFunction).toBridge()
} else if value is [String: Sendable?] {
let mappedValue: [String: Sendable?] = (value as! [String: Sendable?]).mapValues {
if $0 is AggregateFunction {
return ($0 as! AggregateFunction).toBridge()
}
return sendableToExpr($0).toBridge()
}
return mappedValue as NSDictionary
} else {
return Constant(value).bridge
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

extension AggregateFunction {
func toBridge() -> AggregateFunctionBridge {
return (self as AggregateBridgeWrapper).bridge
}
}

public class AggregateFunction: AggregateBridgeWrapper, @unchecked Sendable {
let bridge: AggregateFunctionBridge

Expand Down
Loading
Loading