Skip to content

Commit 18f7d5c

Browse files
committed
[realppl 6] offline ppl evaluation and tests
1 parent 3a7418a commit 18f7d5c

30 files changed

+8714
-64
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
@@ -38,11 +38,15 @@ class RealtimePipeline {
3838
RealtimePipeline AddingStage(std::shared_ptr<EvaluableStage> stage);
3939

4040
const std::vector<std::shared_ptr<EvaluableStage>>& stages() const;
41+
const std::vector<std::shared_ptr<EvaluableStage>>& rewritten_stages() const;
42+
43+
void SetRewrittentStages(std::vector<std::shared_ptr<EvaluableStage>>);
4144

4245
EvaluateContext evaluate_context();
4346

4447
private:
4548
std::vector<std::shared_ptr<EvaluableStage>> stages_;
49+
std::vector<std::shared_ptr<EvaluableStage>> rewritten_stages_;
4650
remote::Serializer serializer_;
4751
};
4852

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: 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

@@ -68,25 +69,29 @@ class EvaluableStage : public Stage {
6869
EvaluableStage() = default;
6970
virtual ~EvaluableStage() = default;
7071

72+
virtual absl::string_view name() const = 0;
7173
virtual model::PipelineInputOutputVector Evaluate(
7274
const EvaluateContext& context,
7375
const model::PipelineInputOutputVector& inputs) const = 0;
7476
};
7577

7678
class CollectionSource : public EvaluableStage {
7779
public:
78-
explicit CollectionSource(std::string path) : path_(std::move(path)) {
79-
}
80+
explicit CollectionSource(std::string path);
8081
~CollectionSource() override = default;
8182

8283
google_firestore_v1_Pipeline_Stage to_proto() const override;
8384

85+
absl::string_view name() const override {
86+
return "collection";
87+
}
88+
8489
model::PipelineInputOutputVector Evaluate(
8590
const EvaluateContext& context,
8691
const model::PipelineInputOutputVector& inputs) const override;
8792

8893
private:
89-
std::string path_;
94+
model::ResourcePath path_;
9095
};
9196

9297
class DatabaseSource : public EvaluableStage {
@@ -95,12 +100,17 @@ class DatabaseSource : public EvaluableStage {
95100
~DatabaseSource() override = default;
96101

97102
google_firestore_v1_Pipeline_Stage to_proto() const override;
103+
104+
absl::string_view name() const override {
105+
return "database";
106+
}
107+
98108
model::PipelineInputOutputVector Evaluate(
99109
const EvaluateContext& context,
100110
const model::PipelineInputOutputVector& inputs) const override;
101111
};
102112

103-
class CollectionGroupSource : public Stage {
113+
class CollectionGroupSource : public EvaluableStage {
104114
public:
105115
explicit CollectionGroupSource(std::string collection_id)
106116
: collection_id_(std::move(collection_id)) {
@@ -109,6 +119,14 @@ class CollectionGroupSource : public Stage {
109119

110120
google_firestore_v1_Pipeline_Stage to_proto() const override;
111121

122+
absl::string_view name() const override {
123+
return "collection_group";
124+
}
125+
126+
model::PipelineInputOutputVector Evaluate(
127+
const EvaluateContext& context,
128+
const model::PipelineInputOutputVector& inputs) const override;
129+
112130
private:
113131
std::string collection_id_;
114132
};
@@ -122,6 +140,10 @@ class DocumentsSource : public Stage {
122140

123141
google_firestore_v1_Pipeline_Stage to_proto() const override;
124142

143+
absl::string_view name() const {
144+
return "documents";
145+
}
146+
125147
private:
126148
std::vector<std::string> documents_;
127149
};
@@ -164,6 +186,11 @@ class Where : public EvaluableStage {
164186
~Where() override = default;
165187

166188
google_firestore_v1_Pipeline_Stage to_proto() const override;
189+
190+
absl::string_view name() const override {
191+
return "where";
192+
}
193+
167194
model::PipelineInputOutputVector Evaluate(
168195
const EvaluateContext& context,
169196
const model::PipelineInputOutputVector& inputs) const override;
@@ -215,6 +242,11 @@ class LimitStage : public EvaluableStage {
215242
~LimitStage() override = default;
216243

217244
google_firestore_v1_Pipeline_Stage to_proto() const override;
245+
246+
absl::string_view name() const override {
247+
return "limit";
248+
}
249+
218250
model::PipelineInputOutputVector Evaluate(
219251
const EvaluateContext& context,
220252
const model::PipelineInputOutputVector& inputs) const override;
@@ -249,17 +281,29 @@ class SelectStage : public Stage {
249281
std::unordered_map<std::string, std::shared_ptr<Expr>> fields_;
250282
};
251283

252-
class SortStage : public Stage {
284+
class SortStage : public EvaluableStage {
253285
public:
254-
explicit SortStage(std::vector<std::shared_ptr<Ordering>> orders)
286+
explicit SortStage(std::vector<Ordering> orders)
255287
: orders_(std::move(orders)) {
256288
}
257289
~SortStage() override = default;
258290

259291
google_firestore_v1_Pipeline_Stage to_proto() const override;
260292

293+
absl::string_view name() const override {
294+
return "sort";
295+
}
296+
297+
model::PipelineInputOutputVector Evaluate(
298+
const EvaluateContext& context,
299+
const model::PipelineInputOutputVector& inputs) const override;
300+
301+
const std::vector<Ordering>& orders() const {
302+
return orders_;
303+
}
304+
261305
private:
262-
std::vector<std::shared_ptr<Ordering>> orders_;
306+
std::vector<Ordering> orders_;
263307
};
264308

265309
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
@@ -25,9 +25,7 @@
2525

2626
#include "Firestore/core/src/api/expressions.h"
2727
#include "Firestore/core/src/api/stages.h"
28-
#include "Firestore/core/src/model/value_util.h"
2928
#include "Firestore/core/src/nanopb/message.h"
30-
#include "Firestore/core/src/util/hard_assert.h"
3129
#include "absl/types/optional.h"
3230

3331
namespace firebase {

0 commit comments

Comments
 (0)