Skip to content

Commit 990c698

Browse files
committed
fix bugs in raw stage and unnest stage
1 parent 5a2a98f commit 990c698

File tree

10 files changed

+356
-115
lines changed

10 files changed

+356
-115
lines changed

Firestore/Source/API/FIRPipelineBridge.mm

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -710,9 +710,11 @@ - (id)initWithPercentage:(double)percentage {
710710
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
711711
if (!isUserDataRead) {
712712
if ([type isEqualToString:@"count"]) {
713-
cpp_sample = std::make_shared<Sample>("count", _count, 0);
713+
cpp_sample =
714+
std::make_shared<Sample>(Sample::SampleMode(Sample::SampleMode::DOCUMENTS), _count, 0);
714715
} else {
715-
cpp_sample = std::make_shared<Sample>("percentage", 0, _percentage);
716+
cpp_sample =
717+
std::make_shared<Sample>(Sample::SampleMode(Sample::SampleMode::PERCENT), 0, _percentage);
716718
}
717719
}
718720

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

751753
@implementation FIRUnnestStageBridge {
752754
FIRExprBridge *_field;
753-
NSString *_Nullable _indexField;
755+
FIRExprBridge *_Nullable _index_field;
756+
FIRExprBridge *_alias;
754757
Boolean isUserDataRead;
755758
std::shared_ptr<Unnest> cpp_unnest;
756759
}
757760

758-
- (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)indexField {
761+
- (id)initWithField:(FIRExprBridge *)field
762+
alias:(FIRExprBridge *)alias
763+
indexField:(FIRExprBridge *_Nullable)index_field {
759764
self = [super init];
760765
if (self) {
761766
_field = field;
762-
_indexField = indexField;
767+
_alias = alias;
768+
_index_field = index_field;
763769
isUserDataRead = NO;
764770
}
765771
return self;
766772
}
767773

768774
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
769775
if (!isUserDataRead) {
770-
absl::optional<std::string> cpp_index_field;
771-
if (_indexField != nil) {
772-
cpp_index_field = MakeString(_indexField);
776+
absl::optional<std::shared_ptr<Expr>> cpp_index_field;
777+
if (_index_field != nil) {
778+
cpp_index_field = [_index_field cppExprWithReader:reader];
773779
} else {
774780
cpp_index_field = absl::nullopt;
775781
}
776-
cpp_unnest = std::make_shared<Unnest>([_field cppExprWithReader:reader], cpp_index_field);
782+
cpp_unnest = std::make_shared<Unnest>([_field cppExprWithReader:reader],
783+
[_alias cppExprWithReader:reader], cpp_index_field);
777784
}
778785

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

785792
@implementation FIRRawStageBridge {
786793
NSString *_name;
787-
NSArray<FIRExprBridge *> *_params;
794+
NSArray<id> *_params;
788795
NSDictionary<NSString *, FIRExprBridge *> *_Nullable _options;
789796
Boolean isUserDataRead;
790797
std::shared_ptr<RawStage> cpp_generic_stage;
791798
}
792799

793800
- (id)initWithName:(NSString *)name
794-
params:(NSArray<FIRExprBridge *> *)params
801+
params:(NSArray<id> *)params
795802
options:(NSDictionary<NSString *, FIRExprBridge *> *_Nullable)options {
796803
self = [super init];
797804
if (self) {
@@ -803,12 +810,43 @@ - (id)initWithName:(NSString *)name
803810
return self;
804811
}
805812

813+
- (firebase::firestore::google_firestore_v1_Value)convertIdToV1Value:(id)value
814+
reader:(FSTUserDataReader *)reader {
815+
if ([value isKindOfClass:[FIRExprBridge class]]) {
816+
return [((FIRExprBridge *)value) cppExprWithReader:reader]->to_proto();
817+
} else if ([value isKindOfClass:[FIRAggregateFunctionBridge class]]) {
818+
return [((FIRAggregateFunctionBridge *)value) cppExprWithReader:reader]->to_proto();
819+
} else if ([value isKindOfClass:[NSDictionary class]]) {
820+
NSDictionary<NSString *, FIRExprBridge *> *dictionary =
821+
(NSDictionary<NSString *, FIRExprBridge *> *)value;
822+
823+
std::unordered_map<std::string, firebase::firestore::google_firestore_v1_Value> cpp_dictionary;
824+
for (NSString *key in dictionary) {
825+
cpp_dictionary[MakeString(key)] = [dictionary[key] cppExprWithReader:reader]->to_proto();
826+
}
827+
828+
firebase::firestore::google_firestore_v1_Value result;
829+
result.which_value_type = google_firestore_v1_Value_map_value_tag;
830+
831+
nanopb::SetRepeatedField(
832+
&result.map_value.fields, &result.map_value.fields_count, cpp_dictionary,
833+
[](const std::pair<std::string, firebase::firestore::google_firestore_v1_Value> &entry) {
834+
return firebase::firestore::_google_firestore_v1_MapValue_FieldsEntry{
835+
nanopb::MakeBytesArray(entry.first), entry.second};
836+
});
837+
return result;
838+
} else {
839+
ThrowInvalidArgument("Subscript key must be an NSString or FIRFieldPath.");
840+
}
841+
}
842+
806843
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
807844
if (!isUserDataRead) {
808-
std::vector<std::shared_ptr<Expr>> cpp_params;
809-
for (FIRExprBridge *param in _params) {
810-
cpp_params.push_back([param cppExprWithReader:reader]);
845+
std::vector<firebase::firestore::google_firestore_v1_Value> cpp_params;
846+
for (id param in _params) {
847+
cpp_params.push_back([self convertIdToV1Value:param reader:reader]);
811848
}
849+
812850
std::unordered_map<std::string, std::shared_ptr<Expr>> cpp_options;
813851
if (_options) {
814852
for (NSString *key in _options) {

Firestore/Source/Public/FirebaseFirestore/FIRPipelineBridge.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,16 @@ NS_SWIFT_NAME(UnionStageBridge)
191191
NS_SWIFT_SENDABLE
192192
NS_SWIFT_NAME(UnnestStageBridge)
193193
@interface FIRUnnestStageBridge : FIRStageBridge
194-
- (id)initWithField:(FIRExprBridge *)field indexField:(NSString *_Nullable)indexField;
194+
- (id)initWithField:(FIRExprBridge *)field
195+
alias:(FIRExprBridge *)alias
196+
indexField:(FIRExprBridge *_Nullable)index_field;
195197
@end
196198

197199
NS_SWIFT_SENDABLE
198200
NS_SWIFT_NAME(RawStageBridge)
199201
@interface FIRRawStageBridge : FIRStageBridge
200202
- (id)initWithName:(NSString *)name
201-
params:(NSArray<FIRExprBridge *> *)params
203+
params:(NSArray<id> *)params
202204
options:(NSDictionary<NSString *, FIRExprBridge *> *_Nullable)options;
203205
@end
204206

Firestore/Swift/Source/Helper/PipelineHelper.swift

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@
1414

1515
enum Helper {
1616
static func sendableToExpr(_ value: Sendable?) -> Expr {
17-
if value == nil {
17+
guard let value = value else {
1818
return Constant.nil
1919
}
2020

21-
if value! is Expr {
22-
return value! as! Expr
23-
} else if value! is [String: Sendable?] {
24-
return map(value! as! [String: Sendable?])
25-
} else if value! is [Sendable?] {
26-
return array(value! as! [Sendable?])
21+
if value is Expr {
22+
return value as! Expr
23+
} else if value is [String: Sendable?] {
24+
return map(value as! [String: Sendable?])
25+
} else if value is [Sendable?] {
26+
return array(value as! [Sendable?])
2727
} else {
28-
return Constant(value!)
28+
return Constant(value)
2929
}
3030
}
3131

@@ -52,4 +52,27 @@ enum Helper {
5252
}
5353
return FunctionExpr("array", transformedElements)
5454
}
55+
56+
// This function is used to convert Swift type into Objective-C type.
57+
static func sendableToAnyObjectForRawStage(_ value: Sendable?) -> AnyObject {
58+
guard let value = value else {
59+
return Constant.nil.bridge
60+
}
61+
62+
// Step 2: Check for NSNull.
63+
guard !(value is NSNull) else {
64+
return Constant.nil.bridge
65+
}
66+
67+
if value is Expr {
68+
return (value as! Expr).toBridge()
69+
} else if value is AggregateFunction {
70+
return (value as! AggregateFunction).toBridge()
71+
} else if value is [String: Sendable?] {
72+
let mappedValue = (value as! [String: Sendable?]).mapValues { sendableToExpr($0).toBridge() }
73+
return mappedValue as NSDictionary
74+
} else {
75+
return Constant(value).bridge
76+
}
77+
}
5578
}

Firestore/Swift/Source/SwiftAPI/Pipeline/Aggregation/AggregateFunction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
extension AggregateFunction {
16+
func toBridge() -> AggregateFunctionBridge {
17+
return (self as AggregateBridgeWrapper).bridge
18+
}
19+
}
20+
1521
public class AggregateFunction: AggregateBridgeWrapper, @unchecked Sendable {
1622
let bridge: AggregateFunctionBridge
1723

Firestore/Swift/Source/SwiftAPI/Pipeline/Pipeline.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ public struct Pipeline: @unchecked Sendable {
719719
/// - params: An array of ordered, `Sendable` parameters for the stage.
720720
/// - options: Optional dictionary of named, `Sendable` parameters.
721721
/// - Returns: A new `Pipeline` object with this stage appended.
722-
public func rawStage(name: String, params: [Sendable],
722+
public func rawStage(name: String, params: [Sendable?],
723723
options: [String: Sendable]? = nil) -> Pipeline {
724724
return Pipeline(
725725
stages: stages + [RawStage(name: name, params: params, options: options)],

Firestore/Swift/Source/SwiftAPI/Stages.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -327,15 +327,20 @@ class Union: Stage {
327327
class Unnest: Stage {
328328
let name: String = "unnest"
329329
let bridge: StageBridge
330-
private var field: Selectable
330+
private var alias: Expr
331+
private var field: Expr
331332
private var indexField: String?
332333

333334
init(field: Selectable, indexField: String? = nil) {
334-
self.field = field
335+
let seletable = field as! SelectableWrapper
336+
self.field = seletable.expr
337+
alias = Field(seletable.alias)
335338
self.indexField = indexField
339+
336340
bridge = UnnestStageBridge(
337-
field: Helper.sendableToExpr(field).toBridge(),
338-
indexField: indexField
341+
field: self.field.toBridge(),
342+
alias: alias.toBridge(),
343+
indexField: indexField.map { Field($0) } ?? nil
339344
)
340345
}
341346
}
@@ -344,14 +349,14 @@ class Unnest: Stage {
344349
class RawStage: Stage {
345350
let name: String
346351
let bridge: StageBridge
347-
private var params: [Sendable]
352+
private var params: [Sendable?]
348353
private var options: [String: Sendable]?
349354

350-
init(name: String, params: [Sendable], options: [String: Sendable]? = nil) {
355+
init(name: String, params: [Sendable?], options: [String: Sendable]? = nil) {
351356
self.name = name
352357
self.params = params
353358
self.options = options
354-
let bridgeParams = params.map { Helper.sendableToExpr($0).toBridge() }
359+
let bridgeParams = params.map { Helper.sendableToAnyObjectForRawStage($0) }
355360
let bridgeOptions = options?.mapValues { Helper.sendableToExpr($0).toBridge() }
356361
bridge = RawStageBridge(name: name, params: bridgeParams, options: bridgeOptions)
357362
}

0 commit comments

Comments
 (0)