Skip to content

Commit 63d75fb

Browse files
committed
[realppl 6] offline ppl evaluation and tests
1 parent d32e2ba commit 63d75fb

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
@@ -184,7 +184,7 @@ - (nonnull id)initWithName:(NSString *)name Args:(nonnull NSArray<FIRExprBridge
184184
@end
185185

186186
@implementation FIROrderingBridge {
187-
std::shared_ptr<Ordering> cpp_ordering;
187+
std::unique_ptr<Ordering> cpp_ordering;
188188
NSString *_direction;
189189
FIRExprBridge *_expr;
190190
Boolean isUserDataRead;
@@ -197,14 +197,14 @@ - (nonnull id)initWithExpr:(FIRExprBridge *)expr Direction:(NSString *)direction
197197
return self;
198198
}
199199

200-
- (std::shared_ptr<Ordering>)cppOrderingWithReader:(FSTUserDataReader *)reader {
200+
- (Ordering)cppOrderingWithReader:(FSTUserDataReader *)reader {
201201
if (!isUserDataRead) {
202-
cpp_ordering = std::make_shared<Ordering>(
202+
cpp_ordering = std::make_unique<Ordering>(
203203
[_expr cppExprWithReader:reader], Ordering::DirectionFromString(MakeString(_direction)));
204204
}
205205

206206
isUserDataRead = YES;
207-
return cpp_ordering;
207+
return *cpp_ordering;
208208
}
209209

210210
@end
@@ -610,7 +610,7 @@ - (id)initWithOrderings:(NSArray<id> *)orderings {
610610

611611
- (std::shared_ptr<api::Stage>)cppStageWithReader:(FSTUserDataReader *)reader {
612612
if (!isUserDataRead) {
613-
std::vector<std::shared_ptr<Ordering>> cpp_orderings;
613+
std::vector<Ordering> cpp_orderings;
614614
for (FIROrderingBridge *ordering in _orderings) {
615615
cpp_orderings.push_back([ordering cppOrderingWithReader:reader]);
616616
}

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
@@ -41,6 +41,10 @@ namespace firebase {
4141
namespace firestore {
4242
namespace api {
4343

44+
CollectionSource::CollectionSource(std::string path)
45+
: path_(model::ResourcePath::FromStringView(path)) {
46+
}
47+
4448
google_firestore_v1_Pipeline_Stage CollectionSource::to_proto() const {
4549
google_firestore_v1_Pipeline_Stage result;
4650

@@ -50,7 +54,9 @@ google_firestore_v1_Pipeline_Stage CollectionSource::to_proto() const {
5054
result.args = nanopb::MakeArray<google_firestore_v1_Value>(1);
5155
result.args[0].which_value_type =
5256
google_firestore_v1_Value_reference_value_tag;
53-
result.args[0].reference_value = nanopb::MakeBytesArray(this->path_);
57+
// TODO: use EncodeResourceName instead
58+
result.args[0].reference_value =
59+
nanopb::MakeBytesArray(this->path_.CanonicalString());
5460

5561
result.options_count = 0;
5662
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;
@@ -443,7 +449,20 @@ model::PipelineInputOutputVector CollectionSource::Evaluate(
443449
std::copy_if(inputs.begin(), inputs.end(), std::back_inserter(results),
444450
[this](const model::MutableDocument& doc) {
445451
return doc.is_found_document() &&
446-
doc.key().path().PopLast().CanonicalString() == path_;
452+
doc.key().path().PopLast().CanonicalString() ==
453+
path_.CanonicalString();
454+
});
455+
return results;
456+
}
457+
458+
model::PipelineInputOutputVector CollectionGroupSource::Evaluate(
459+
const EvaluateContext& /*context*/,
460+
const model::PipelineInputOutputVector& inputs) const {
461+
model::PipelineInputOutputVector results;
462+
std::copy_if(inputs.begin(), inputs.end(), std::back_inserter(results),
463+
[this](const model::MutableDocument& doc) {
464+
return doc.is_found_document() &&
465+
doc.key().GetCollectionGroup() == collection_id_;
447466
});
448467
return results;
449468
}
@@ -492,6 +511,39 @@ model::PipelineInputOutputVector LimitStage::Evaluate(
492511
inputs.begin() + count);
493512
}
494513

514+
model::PipelineInputOutputVector SortStage::Evaluate(
515+
const EvaluateContext& context,
516+
const model::PipelineInputOutputVector& inputs) const {
517+
model::PipelineInputOutputVector input_copy = inputs;
518+
std::sort(
519+
input_copy.begin(), input_copy.end(),
520+
[this, &context](const model::PipelineInputOutput& left,
521+
const model::PipelineInputOutput& right) -> bool {
522+
for (const auto& ordering : this->orders_) {
523+
const auto left_result =
524+
ordering.expr()->ToEvaluable()->Evaluate(context, left);
525+
const auto right_result =
526+
ordering.expr()->ToEvaluable()->Evaluate(context, right);
527+
528+
auto left_val = left_result.IsErrorOrUnset() ? model::MinValue()
529+
: *left_result.value();
530+
auto right_val = right_result.IsErrorOrUnset()
531+
? model::MinValue()
532+
: *right_result.value();
533+
const auto compare_result = model::Compare(left_val, right_val);
534+
if (compare_result != util::ComparisonResult::Same) {
535+
return ordering.direction() == Ordering::ASCENDING
536+
? compare_result == util::ComparisonResult::Ascending
537+
: compare_result == util::ComparisonResult::Descending;
538+
}
539+
}
540+
541+
return false;
542+
});
543+
544+
return input_copy;
545+
}
546+
495547
} // namespace api
496548
} // namespace firestore
497549
} // 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;
@@ -219,6 +246,11 @@ class LimitStage : public EvaluableStage {
219246
~LimitStage() override = default;
220247

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

256-
class SortStage : public Stage {
288+
class SortStage : public EvaluableStage {
257289
public:
258-
explicit SortStage(std::vector<std::shared_ptr<Ordering>> orders)
290+
explicit SortStage(std::vector<Ordering> orders)
259291
: orders_(std::move(orders)) {
260292
}
261293
~SortStage() override = default;
262294

263295
google_firestore_v1_Pipeline_Stage to_proto() const override;
264296

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

269313
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)