Skip to content

Commit f6ae9c2

Browse files
committed
[realppl 2] Minimalistic ppl offline evaluation
1 parent 838a5dc commit f6ae9c2

File tree

18 files changed

+1184
-241
lines changed

18 files changed

+1184
-241
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 289 additions & 226 deletions
Large diffs are not rendered by default.

Firestore/core/src/api/expressions.cc

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,58 @@
1919
#include <memory>
2020

2121
#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
22+
#include "Firestore/core/src/core/expressions_eval.h"
2223
#include "Firestore/core/src/model/value_util.h"
2324
#include "Firestore/core/src/nanopb/nanopb_util.h"
2425

2526
namespace firebase {
2627
namespace firestore {
2728
namespace api {
2829

30+
Field::Field(std::string name) {
31+
field_path_ = model::FieldPath::FromDotSeparatedString(name);
32+
}
33+
2934
google_firestore_v1_Value Field::to_proto() const {
3035
google_firestore_v1_Value result;
3136

3237
result.which_value_type = google_firestore_v1_Value_field_reference_value_tag;
33-
result.field_reference_value = nanopb::MakeBytesArray(this->name_);
38+
result.field_reference_value = nanopb::MakeBytesArray(this->alias());
3439

3540
return result;
3641
}
3742

43+
std::unique_ptr<core::EvaluableExpr> Field::ToEvaluable() const {
44+
return std::make_unique<core::CoreField>(std::make_unique<Field>(*this));
45+
}
46+
3847
google_firestore_v1_Value Constant::to_proto() const {
3948
// Return a copy of the value proto to avoid double delete.
4049
return *model::DeepClone(*value_).release();
4150
}
4251

52+
std::unique_ptr<core::EvaluableExpr> Constant::ToEvaluable() const {
53+
return std::make_unique<core::CoreConstant>(
54+
std::make_unique<Constant>(*this));
55+
}
56+
4357
google_firestore_v1_Value FunctionExpr::to_proto() const {
4458
google_firestore_v1_Value result;
4559

4660
result.which_value_type = google_firestore_v1_Value_function_value_tag;
4761
result.function_value = google_firestore_v1_Function{};
4862
result.function_value.name = nanopb::MakeBytesArray(name_);
4963
nanopb::SetRepeatedField(
50-
&result.function_value.args, &result.function_value.args_count, args_,
64+
&result.function_value.args, &result.function_value.args_count, params_,
5165
[](const std::shared_ptr<Expr>& arg) { return arg->to_proto(); });
5266

5367
return result;
5468
}
5569

70+
std::unique_ptr<core::EvaluableExpr> FunctionExpr::ToEvaluable() const {
71+
return core::FunctionToEvaluable(*this);
72+
}
73+
5674
} // namespace api
5775
} // namespace firestore
5876
} // namespace firebase

Firestore/core/src/api/expressions.h

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,54 @@
2323
#include <vector>
2424

2525
#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
26+
#include "Firestore/core/src/model/field_path.h"
2627
#include "Firestore/core/src/nanopb/message.h"
2728

2829
namespace firebase {
2930
namespace firestore {
31+
namespace core {
32+
class EvaluableExpr;
33+
} // namespace core
3034
namespace api {
3135

3236
class Expr {
3337
public:
3438
Expr() = default;
3539
virtual ~Expr() = default;
3640
virtual google_firestore_v1_Value to_proto() const = 0;
41+
virtual std::unique_ptr<core::EvaluableExpr> ToEvaluable() const = 0;
3742
};
3843

39-
class Field : public Expr {
44+
class Selectable : public Expr {
4045
public:
41-
explicit Field(std::string name) : name_(std::move(name)) {
46+
~Selectable() override = default;
47+
virtual const std::string& alias() const = 0;
48+
};
49+
50+
class Field : public Selectable {
51+
public:
52+
explicit Field(model::FieldPath field_path)
53+
: field_path_(std::move(field_path)),
54+
alias_(field_path_.CanonicalString()) {
4255
}
56+
~Field() override = default;
57+
58+
explicit Field(std::string name);
59+
4360
google_firestore_v1_Value to_proto() const override;
44-
const std::string& alias() const {
45-
return name_;
61+
62+
const std::string& alias() const override {
63+
return alias_;
4664
}
65+
const model::FieldPath& field_path() const {
66+
return field_path_;
67+
}
68+
69+
std::unique_ptr<core::EvaluableExpr> ToEvaluable() const override;
4770

4871
private:
49-
std::string name_;
72+
model::FieldPath field_path_;
73+
std::string alias_;
5074
};
5175

5276
class Constant : public Expr {
@@ -56,21 +80,33 @@ class Constant : public Expr {
5680
}
5781
google_firestore_v1_Value to_proto() const override;
5882

83+
std::unique_ptr<core::EvaluableExpr> ToEvaluable() const override;
84+
5985
private:
6086
nanopb::SharedMessage<google_firestore_v1_Value> value_;
6187
};
6288

6389
class FunctionExpr : public Expr {
6490
public:
65-
FunctionExpr(std::string name, std::vector<std::shared_ptr<Expr>> args)
66-
: name_(std::move(name)), args_(std::move(args)) {
91+
FunctionExpr(std::string name, std::vector<std::shared_ptr<Expr>> params)
92+
: name_(std::move(name)), params_(std::move(params)) {
6793
}
6894

6995
google_firestore_v1_Value to_proto() const override;
7096

97+
std::unique_ptr<core::EvaluableExpr> ToEvaluable() const override;
98+
99+
const std::string& name() const {
100+
return name_;
101+
}
102+
103+
const std::vector<std::shared_ptr<Expr>>& params() const {
104+
return params_;
105+
}
106+
71107
private:
72108
std::string name_;
73-
std::vector<std::shared_ptr<Expr>> args_;
109+
std::vector<std::shared_ptr<Expr>> params_;
74110
};
75111

76112
} // namespace api
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "Firestore/core/src/api/realtime_pipeline.h"
18+
19+
#include <memory>
20+
#include <utility>
21+
22+
#include "Firestore/core/src/remote/serializer.h"
23+
24+
namespace firebase {
25+
namespace firestore {
26+
namespace api {
27+
28+
RealtimePipeline::RealtimePipeline(
29+
std::vector<std::shared_ptr<EvaluableStage>> stages,
30+
remote::Serializer serializer)
31+
: stages_(std::move(stages)), serializer_(serializer) {
32+
}
33+
34+
RealtimePipeline RealtimePipeline::AddingStage(
35+
std::shared_ptr<EvaluableStage> stage) {
36+
auto copy = std::vector<std::shared_ptr<EvaluableStage>>(this->stages_);
37+
copy.push_back(stage);
38+
39+
return {copy, serializer_};
40+
}
41+
42+
const std::vector<std::shared_ptr<EvaluableStage>>& RealtimePipeline::stages()
43+
const {
44+
return this->stages_;
45+
}
46+
47+
EvaluateContext RealtimePipeline::evaluate_context() {
48+
return EvaluateContext(&serializer_);
49+
}
50+
51+
} // namespace api
52+
} // namespace firestore
53+
} // namespace firebase
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef FIRESTORE_CORE_SRC_API_REALTIME_PIPELINE_H_
18+
#define FIRESTORE_CORE_SRC_API_REALTIME_PIPELINE_H_
19+
20+
#include <memory>
21+
#include <utility>
22+
#include <vector>
23+
24+
#include "Firestore/core/src/api/firestore.h"
25+
#include "Firestore/core/src/api/pipeline_snapshot.h"
26+
#include "Firestore/core/src/api/stages.h"
27+
#include "Firestore/core/src/remote/serializer.h"
28+
29+
namespace firebase {
30+
namespace firestore {
31+
namespace api {
32+
33+
class RealtimePipeline {
34+
public:
35+
RealtimePipeline(std::vector<std::shared_ptr<EvaluableStage>> stages,
36+
remote::Serializer serializer);
37+
38+
RealtimePipeline AddingStage(std::shared_ptr<EvaluableStage> stage);
39+
40+
const std::vector<std::shared_ptr<EvaluableStage>>& stages() const;
41+
42+
EvaluateContext evaluate_context();
43+
44+
private:
45+
std::vector<std::shared_ptr<EvaluableStage>> stages_;
46+
remote::Serializer serializer_;
47+
};
48+
49+
} // namespace api
50+
} // namespace firestore
51+
} // namespace firebase
52+
53+
#endif // FIRESTORE_CORE_SRC_API_REALTIME_PIPELINE_H_

Firestore/core/src/api/stages.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,26 @@
1616

1717
#include "Firestore/core/src/api/stages.h"
1818

19+
#include <algorithm>
20+
#include <memory>
21+
#include <stdexcept>
1922
#include <unordered_map>
23+
#include <unordered_set>
2024
#include <utility>
25+
#include <vector>
2126

2227
#include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
2328
#include "Firestore/core/src/api/pipeline.h"
29+
#include "Firestore/core/src/core/expressions_eval.h"
30+
#include "Firestore/core/src/model/document.h"
31+
#include "Firestore/core/src/model/document_key.h"
32+
#include "Firestore/core/src/model/mutable_document.h"
33+
#include "Firestore/core/src/model/resource_path.h"
34+
#include "Firestore/core/src/model/value_util.h"
2435
#include "Firestore/core/src/nanopb/message.h"
2536
#include "Firestore/core/src/nanopb/nanopb_util.h"
37+
#include "Firestore/core/src/util/comparison.h"
38+
#include "Firestore/core/src/util/hard_assert.h"
2639

2740
namespace firebase {
2841
namespace firestore {
@@ -423,6 +436,62 @@ google_firestore_v1_Pipeline_Stage GenericStage::to_proto() const {
423436
return result;
424437
}
425438

439+
model::PipelineInputOutputVector CollectionSource::Evaluate(
440+
const EvaluateContext& /*context*/,
441+
const model::PipelineInputOutputVector& inputs) const {
442+
model::PipelineInputOutputVector results;
443+
std::copy_if(inputs.begin(), inputs.end(), std::back_inserter(results),
444+
[this](const model::MutableDocument& doc) {
445+
return doc.is_found_document() &&
446+
doc.key().path().PopLast().CanonicalString() == path_;
447+
});
448+
return results;
449+
}
450+
451+
model::PipelineInputOutputVector DatabaseSource::Evaluate(
452+
const EvaluateContext& /*context*/,
453+
const model::PipelineInputOutputVector& inputs) const {
454+
model::PipelineInputOutputVector results;
455+
std::copy_if(inputs.begin(), inputs.end(), std::back_inserter(results),
456+
[](const model::MutableDocument& doc) {
457+
return doc.is_found_document();
458+
});
459+
return results;
460+
}
461+
462+
model::PipelineInputOutputVector Where::Evaluate(
463+
const EvaluateContext& context,
464+
const model::PipelineInputOutputVector& inputs) const {
465+
model::PipelineInputOutputVector results;
466+
const auto evaluable_expr = expr_->ToEvaluable();
467+
const auto true_value = model::TrueValue();
468+
469+
for (const auto& doc : inputs) {
470+
auto result = evaluable_expr->Evaluate(context, doc);
471+
if (!result.IsErrorOrUnset() &&
472+
model::Equals(*result.value(), true_value)) {
473+
results.push_back(doc);
474+
}
475+
}
476+
477+
return results;
478+
}
479+
480+
model::PipelineInputOutputVector LimitStage::Evaluate(
481+
const EvaluateContext& /*context*/,
482+
const model::PipelineInputOutputVector& inputs) const {
483+
if (limit_ < 0) {
484+
// Or handle as error? Assuming non-negative limit.
485+
return {};
486+
}
487+
size_t count = static_cast<size_t>(limit_);
488+
if (count > inputs.size()) {
489+
count = inputs.size();
490+
}
491+
return model::PipelineInputOutputVector(inputs.begin(),
492+
inputs.begin() + count);
493+
}
494+
426495
} // namespace api
427496
} // namespace firestore
428497
} // namespace firebase

0 commit comments

Comments
 (0)