Skip to content

Commit cb6e366

Browse files
committed
[realppl 6] offline ppl evaluation and tests
1 parent 9b9e2d9 commit cb6e366

30 files changed

+8682
-65
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 189 additions & 3 deletions
Large diffs are not rendered by default.

Firestore/Source/API/FIRPipelineBridge+Internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
3737

3838
@interface FIROrderingBridge (Internal)
3939

40-
- (std::shared_ptr<api::Ordering>)cppOrderingWithReader:(FSTUserDataReader *)reader;
40+
- (api::Ordering)cppOrderingWithReader:(FSTUserDataReader *)reader;
4141

4242
@end
4343

Firestore/Source/API/FIRPipelineBridge.mm

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ - (nonnull id)initWithName:(NSString *)name Args:(nonnull NSArray<FIRExprBridge
211211
@end
212212

213213
@implementation FIROrderingBridge {
214-
std::shared_ptr<Ordering> cpp_ordering;
214+
std::unique_ptr<Ordering> cpp_ordering;
215215
NSString *_direction;
216216
FIRExprBridge *_expr;
217217
Boolean isUserDataRead;
@@ -224,14 +224,14 @@ - (nonnull id)initWithExpr:(FIRExprBridge *)expr Direction:(NSString *)direction
224224
return self;
225225
}
226226

227-
- (std::shared_ptr<Ordering>)cppOrderingWithReader:(FSTUserDataReader *)reader {
227+
- (Ordering)cppOrderingWithReader:(FSTUserDataReader *)reader {
228228
if (!isUserDataRead) {
229-
cpp_ordering = std::make_shared<Ordering>(
229+
cpp_ordering = std::make_unique<Ordering>(
230230
[_expr cppExprWithReader:reader], Ordering::DirectionFromString(MakeString(_direction)));
231231
}
232232

233233
isUserDataRead = YES;
234-
return cpp_ordering;
234+
return *cpp_ordering;
235235
}
236236

237237
@end
@@ -650,7 +650,7 @@ - (id)initWithOrderings:(NSArray<id> *)orderings {
650650

651651
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
652652
if (!isUserDataRead) {
653-
std::vector<std::shared_ptr<Ordering>> cpp_orderings;
653+
std::vector<Ordering> cpp_orderings;
654654
for (FIROrderingBridge *ordering in _orderings) {
655655
cpp_orderings.push_back([ordering cppOrderingWithReader:reader]);
656656
}

Firestore/core/src/api/expressions.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace api {
2929

3030
Field::Field(std::string name) {
3131
field_path_ = model::FieldPath::FromDotSeparatedString(name);
32+
alias_ = field_path_.CanonicalString();
3233
}
3334

3435
google_firestore_v1_Value Field::to_proto() const {

Firestore/core/src/api/ordering.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ class Ordering {
4545
: expr_(expr), direction_(direction) {
4646
}
4747

48+
const Expr* expr() const {
49+
return expr_.get();
50+
}
51+
52+
Direction direction() const {
53+
return direction_;
54+
}
55+
4856
google_firestore_v1_Value to_proto() const;
4957

5058
private:

Firestore/core/src/api/realtime_pipeline.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ const std::vector<std::shared_ptr<EvaluableStage>>& RealtimePipeline::stages()
4444
return this->stages_;
4545
}
4646

47+
const std::vector<std::shared_ptr<EvaluableStage>>&
48+
RealtimePipeline::rewritten_stages() const {
49+
return this->rewritten_stages_;
50+
}
51+
52+
void RealtimePipeline::SetRewrittentStages(
53+
std::vector<std::shared_ptr<EvaluableStage>> stages) {
54+
this->rewritten_stages_ = std::move(stages);
55+
}
56+
4757
EvaluateContext RealtimePipeline::evaluate_context() {
4858
return EvaluateContext(&serializer_);
4959
}

Firestore/core/src/api/realtime_pipeline.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@ class RealtimePipeline {
3636
RealtimePipeline AddingStage(std::shared_ptr<EvaluableStage> stage);
3737

3838
const std::vector<std::shared_ptr<EvaluableStage>>& stages() const;
39+
const std::vector<std::shared_ptr<EvaluableStage>>& rewritten_stages() const;
40+
41+
void SetRewrittentStages(std::vector<std::shared_ptr<EvaluableStage>>);
3942

4043
EvaluateContext evaluate_context();
4144

4245
private:
4346
std::vector<std::shared_ptr<EvaluableStage>> stages_;
47+
std::vector<std::shared_ptr<EvaluableStage>> rewritten_stages_;
4448
remote::Serializer serializer_;
4549
};
4650

Firestore/core/src/api/stages.cc

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ namespace api {
4343

4444
using model::DeepClone;
4545

46+
CollectionSource::CollectionSource(std::string path)
47+
: path_(model::ResourcePath::FromStringView(path)) {
48+
}
49+
4650
google_firestore_v1_Pipeline_Stage CollectionSource::to_proto() const {
4751
google_firestore_v1_Pipeline_Stage result;
4852

@@ -52,7 +56,9 @@ google_firestore_v1_Pipeline_Stage CollectionSource::to_proto() const {
5256
result.args = nanopb::MakeArray<google_firestore_v1_Value>(1);
5357
result.args[0].which_value_type =
5458
google_firestore_v1_Value_reference_value_tag;
55-
result.args[0].reference_value = nanopb::MakeBytesArray(this->path_);
59+
// TODO(wuandy): use EncodeResourceName instead
60+
result.args[0].reference_value =
61+
nanopb::MakeBytesArray(this->path_.CanonicalString());
5662

5763
result.options_count = 0;
5864
result.options = nullptr;
@@ -275,7 +281,7 @@ google_firestore_v1_Pipeline_Stage SortStage::to_proto() const {
275281
result.args = nanopb::MakeArray<google_firestore_v1_Value>(result.args_count);
276282

277283
for (size_t i = 0; i < orders_.size(); ++i) {
278-
result.args[i] = orders_[i]->to_proto();
284+
result.args[i] = orders_[i].to_proto();
279285
}
280286

281287
result.options_count = 0;
@@ -481,7 +487,20 @@ model::PipelineInputOutputVector CollectionSource::Evaluate(
481487
std::copy_if(inputs.begin(), inputs.end(), std::back_inserter(results),
482488
[this](const model::MutableDocument& doc) {
483489
return doc.is_found_document() &&
484-
doc.key().path().PopLast().CanonicalString() == path_;
490+
doc.key().path().PopLast().CanonicalString() ==
491+
path_.CanonicalString();
492+
});
493+
return results;
494+
}
495+
496+
model::PipelineInputOutputVector CollectionGroupSource::Evaluate(
497+
const EvaluateContext& /*context*/,
498+
const model::PipelineInputOutputVector& inputs) const {
499+
model::PipelineInputOutputVector results;
500+
std::copy_if(inputs.begin(), inputs.end(), std::back_inserter(results),
501+
[this](const model::MutableDocument& doc) {
502+
return doc.is_found_document() &&
503+
doc.key().GetCollectionGroup() == collection_id_;
485504
});
486505
return results;
487506
}
@@ -530,6 +549,39 @@ model::PipelineInputOutputVector LimitStage::Evaluate(
530549
inputs.begin() + count);
531550
}
532551

552+
model::PipelineInputOutputVector SortStage::Evaluate(
553+
const EvaluateContext& context,
554+
const model::PipelineInputOutputVector& inputs) const {
555+
model::PipelineInputOutputVector input_copy = inputs;
556+
std::sort(
557+
input_copy.begin(), input_copy.end(),
558+
[this, &context](const model::PipelineInputOutput& left,
559+
const model::PipelineInputOutput& right) -> bool {
560+
for (const auto& ordering : this->orders_) {
561+
const auto left_result =
562+
ordering.expr()->ToEvaluable()->Evaluate(context, left);
563+
const auto right_result =
564+
ordering.expr()->ToEvaluable()->Evaluate(context, right);
565+
566+
auto left_val = left_result.IsErrorOrUnset() ? model::MinValue()
567+
: *left_result.value();
568+
auto right_val = right_result.IsErrorOrUnset()
569+
? model::MinValue()
570+
: *right_result.value();
571+
const auto compare_result = model::Compare(left_val, right_val);
572+
if (compare_result != util::ComparisonResult::Same) {
573+
return ordering.direction() == Ordering::ASCENDING
574+
? compare_result == util::ComparisonResult::Ascending
575+
: compare_result == util::ComparisonResult::Descending;
576+
}
577+
}
578+
579+
return false;
580+
});
581+
582+
return input_copy;
583+
}
584+
533585
} // namespace api
534586
} // namespace firestore
535587
} // namespace firebase

Firestore/core/src/api/stages.h

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "Firestore/core/src/api/expressions.h"
3030
#include "Firestore/core/src/api/ordering.h"
3131
#include "Firestore/core/src/model/model_fwd.h"
32+
#include "Firestore/core/src/model/resource_path.h"
3233
#include "Firestore/core/src/nanopb/message.h"
3334
#include "absl/types/optional.h"
3435

@@ -71,25 +72,29 @@ class EvaluableStage : public Stage {
7172
EvaluableStage() = default;
7273
virtual ~EvaluableStage() = default;
7374

75+
virtual absl::string_view name() const = 0;
7476
virtual model::PipelineInputOutputVector Evaluate(
7577
const EvaluateContext& context,
7678
const model::PipelineInputOutputVector& inputs) const = 0;
7779
};
7880

7981
class CollectionSource : public EvaluableStage {
8082
public:
81-
explicit CollectionSource(std::string path) : path_(std::move(path)) {
82-
}
83+
explicit CollectionSource(std::string path);
8384
~CollectionSource() override = default;
8485

8586
google_firestore_v1_Pipeline_Stage to_proto() const override;
8687

88+
absl::string_view name() const override {
89+
return "collection";
90+
}
91+
8792
model::PipelineInputOutputVector Evaluate(
8893
const EvaluateContext& context,
8994
const model::PipelineInputOutputVector& inputs) const override;
9095

9196
private:
92-
std::string path_;
97+
model::ResourcePath path_;
9398
};
9499

95100
class DatabaseSource : public EvaluableStage {
@@ -98,12 +103,17 @@ class DatabaseSource : public EvaluableStage {
98103
~DatabaseSource() override = default;
99104

100105
google_firestore_v1_Pipeline_Stage to_proto() const override;
106+
107+
absl::string_view name() const override {
108+
return "database";
109+
}
110+
101111
model::PipelineInputOutputVector Evaluate(
102112
const EvaluateContext& context,
103113
const model::PipelineInputOutputVector& inputs) const override;
104114
};
105115

106-
class CollectionGroupSource : public Stage {
116+
class CollectionGroupSource : public EvaluableStage {
107117
public:
108118
explicit CollectionGroupSource(std::string collection_id)
109119
: collection_id_(std::move(collection_id)) {
@@ -112,6 +122,14 @@ class CollectionGroupSource : public Stage {
112122

113123
google_firestore_v1_Pipeline_Stage to_proto() const override;
114124

125+
absl::string_view name() const override {
126+
return "collection_group";
127+
}
128+
129+
model::PipelineInputOutputVector Evaluate(
130+
const EvaluateContext& context,
131+
const model::PipelineInputOutputVector& inputs) const override;
132+
115133
private:
116134
std::string collection_id_;
117135
};
@@ -125,6 +143,10 @@ class DocumentsSource : public Stage {
125143

126144
google_firestore_v1_Pipeline_Stage to_proto() const override;
127145

146+
absl::string_view name() const {
147+
return "documents";
148+
}
149+
128150
private:
129151
std::vector<std::string> documents_;
130152
};
@@ -167,6 +189,11 @@ class Where : public EvaluableStage {
167189
~Where() override = default;
168190

169191
google_firestore_v1_Pipeline_Stage to_proto() const override;
192+
193+
absl::string_view name() const override {
194+
return "where";
195+
}
196+
170197
model::PipelineInputOutputVector Evaluate(
171198
const EvaluateContext& context,
172199
const model::PipelineInputOutputVector& inputs) const override;
@@ -218,6 +245,11 @@ class LimitStage : public EvaluableStage {
218245
~LimitStage() override = default;
219246

220247
google_firestore_v1_Pipeline_Stage to_proto() const override;
248+
249+
absl::string_view name() const override {
250+
return "limit";
251+
}
252+
221253
model::PipelineInputOutputVector Evaluate(
222254
const EvaluateContext& context,
223255
const model::PipelineInputOutputVector& inputs) const override;
@@ -252,17 +284,29 @@ class SelectStage : public Stage {
252284
std::unordered_map<std::string, std::shared_ptr<Expr>> fields_;
253285
};
254286

255-
class SortStage : public Stage {
287+
class SortStage : public EvaluableStage {
256288
public:
257-
explicit SortStage(std::vector<std::shared_ptr<Ordering>> orders)
289+
explicit SortStage(std::vector<Ordering> orders)
258290
: orders_(std::move(orders)) {
259291
}
260292
~SortStage() override = default;
261293

262294
google_firestore_v1_Pipeline_Stage to_proto() const override;
263295

296+
absl::string_view name() const override {
297+
return "sort";
298+
}
299+
300+
model::PipelineInputOutputVector Evaluate(
301+
const EvaluateContext& context,
302+
const model::PipelineInputOutputVector& inputs) const override;
303+
304+
const std::vector<Ordering>& orders() const {
305+
return orders_;
306+
}
307+
264308
private:
265-
std::vector<std::shared_ptr<Ordering>> orders_;
309+
std::vector<Ordering> orders_;
266310
};
267311

268312
class DistinctStage : public Stage {

Firestore/core/src/core/expressions_eval.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424

2525
#include "Firestore/core/src/api/expressions.h"
2626
#include "Firestore/core/src/api/stages.h"
27-
#include "Firestore/core/src/model/value_util.h"
2827
#include "Firestore/core/src/nanopb/message.h"
29-
#include "Firestore/core/src/util/hard_assert.h"
3028
#include "absl/types/optional.h"
3129

3230
namespace firebase {

0 commit comments

Comments
 (0)