Skip to content

Commit ca7d59f

Browse files
committed
simplify a little bit
1 parent c621085 commit ca7d59f

3 files changed

Lines changed: 35 additions & 54 deletions

File tree

src/iceberg/expression/residual_evaluator.cc

Lines changed: 29 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
#include "iceberg/expression/residual_evaluator.h"
2121

22-
#include "iceberg/expression/binder.h"
2322
#include "iceberg/expression/expression.h"
2423
#include "iceberg/expression/expression_visitor.h"
2524
#include "iceberg/expression/predicate.h"
@@ -187,19 +186,19 @@ class ResidualVisitor : public BoundVisitor<std::shared_ptr<Expression>> {
187186

188187
Result<std::shared_ptr<Expression>> Predicate(
189188
const std::shared_ptr<UnboundPredicate>& pred) override {
190-
ICEBERG_ASSIGN_OR_RAISE(auto bound_predicate, pred->Bind(schema_, case_sensitive_));
191-
if (bound_predicate->is_bound_predicate()) {
189+
ICEBERG_ASSIGN_OR_RAISE(auto bound, pred->Bind(schema_, case_sensitive_));
190+
if (bound->is_bound_predicate()) {
192191
ICEBERG_ASSIGN_OR_RAISE(
193192
auto residual,
194-
Predicate(std::dynamic_pointer_cast<BoundPredicate>(bound_predicate)));
193+
Predicate(internal::checked_pointer_cast<BoundPredicate>(bound)));
195194
if (residual->is_bound_predicate()) {
196195
// replace inclusive original unbound predicate
197196
return pred;
198197
}
199198
return residual;
200199
}
201200
// if binding didn't result in a Predicate, return the expression
202-
return bound_predicate;
201+
return bound;
203202
}
204203

205204
private:
@@ -218,7 +217,6 @@ class ResidualVisitor : public BoundVisitor<std::shared_ptr<Expression>> {
218217
const StructLike& partition_data_;
219218
bool case_sensitive_;
220219
};
221-
} // namespace
222220

223221
Result<std::shared_ptr<Expression>> ResidualVisitor::Predicate(
224222
const std::shared_ptr<BoundPredicate>& pred) {
@@ -230,37 +228,30 @@ Result<std::shared_ptr<Expression>> ResidualVisitor::Predicate(
230228
// have returned false, so the predicate can also be eliminated if the inclusive
231229
// projection evaluates to false.
232230

233-
// Get the field ID from the predicate's reference
234-
const auto& ref = pred->reference();
235-
int32_t field_id = ref->field().field_id();
236-
237-
// Find partition fields that match this source field ID
238-
auto matching_fields = spec_.GetFieldsBySourceId(field_id);
239-
240-
if (!matching_fields.has_value()) {
231+
// If there is no strict projection or if it evaluates to false, then return the
232+
// predicate.
233+
ICEBERG_ASSIGN_OR_RAISE(
234+
auto parts, spec_.GetFieldsBySourceId(pred->reference()->field().field_id()));
235+
if (parts.empty()) {
241236
// Not associated with a partition field, can't be evaluated
242237
return pred;
243238
}
244239

245-
for (const auto& part : matching_fields.value()) {
240+
for (const auto& part : parts) {
246241
// Check the strict projection
247242
ICEBERG_ASSIGN_OR_RAISE(auto strict_projection, part.get().transform()->ProjectStrict(
248243
part.get().name(), pred));
249244
std::shared_ptr<Expression> strict_result = nullptr;
250245

251246
if (strict_projection != nullptr) {
252-
// Bind the projected predicate to partition type
253247
ICEBERG_ASSIGN_OR_RAISE(
254248
auto bound_strict,
255-
Binder::Bind(*partition_schema_,
256-
std::shared_ptr<Expression>(std::move(strict_projection)),
257-
case_sensitive_));
258-
249+
strict_projection->Bind(*partition_schema_, case_sensitive_));
259250
if (bound_strict->is_bound_predicate()) {
260-
// Evaluate the bound predicate against partition data
261251
ICEBERG_ASSIGN_OR_RAISE(
262-
strict_result, BoundVisitor::Predicate(
263-
std::dynamic_pointer_cast<BoundPredicate>(bound_strict)));
252+
strict_result,
253+
BoundVisitor::Predicate(
254+
internal::checked_pointer_cast<BoundPredicate>(bound_strict)));
264255
} else {
265256
// If the result is not a predicate, then it must be a constant like alwaysTrue
266257
// or alwaysFalse
@@ -279,19 +270,15 @@ Result<std::shared_ptr<Expression>> ResidualVisitor::Predicate(
279270
std::shared_ptr<Expression> inclusive_result = nullptr;
280271

281272
if (inclusive_projection != nullptr) {
282-
// Bind the projected predicate to partition type
283273
ICEBERG_ASSIGN_OR_RAISE(
284274
auto bound_inclusive,
285-
Binder::Bind(*partition_schema_,
286-
std::shared_ptr<Expression>(std::move(inclusive_projection)),
287-
case_sensitive_));
275+
inclusive_projection->Bind(*partition_schema_, case_sensitive_));
288276

289277
if (bound_inclusive->is_bound_predicate()) {
290-
// Evaluate the bound predicate against partition data
291278
ICEBERG_ASSIGN_OR_RAISE(
292279
inclusive_result,
293280
BoundVisitor::Predicate(
294-
std::dynamic_pointer_cast<BoundPredicate>(bound_inclusive)));
281+
internal::checked_pointer_cast<BoundPredicate>(bound_inclusive)));
295282
} else {
296283
// If the result is not a predicate, then it must be a constant like alwaysTrue
297284
// or alwaysFalse
@@ -310,24 +297,12 @@ Result<std::shared_ptr<Expression>> ResidualVisitor::Predicate(
310297
return pred;
311298
}
312299

313-
ResidualEvaluator::ResidualEvaluator(std::shared_ptr<Expression> expr,
314-
const PartitionSpec& spec, const Schema& schema,
315-
bool case_sensitive)
316-
: expr_(std::move(expr)),
317-
spec_(spec),
318-
schema_(schema),
319-
case_sensitive_(case_sensitive) {}
320-
321-
ResidualEvaluator::~ResidualEvaluator() = default;
322-
323-
namespace {
324-
325300
// Unpartitioned residual evaluator that always returns the original expression
326301
class UnpartitionedResidualEvaluator : public ResidualEvaluator {
327302
public:
328303
explicit UnpartitionedResidualEvaluator(std::shared_ptr<Expression> expr)
329304
: ResidualEvaluator(std::move(expr), *PartitionSpec::Unpartitioned(),
330-
*empty_schema_, true) {}
305+
*kEmptySchema_, true) {}
331306

332307
Result<std::shared_ptr<Expression>> ResidualFor(
333308
const StructLike& /*partition_data*/) const override {
@@ -336,15 +311,22 @@ class UnpartitionedResidualEvaluator : public ResidualEvaluator {
336311

337312
private:
338313
// Store an empty schema to avoid dangling reference when passing to base class
339-
static const std::shared_ptr<Schema> empty_schema_;
314+
inline static const std::shared_ptr<Schema> kEmptySchema_ =
315+
std::make_shared<Schema>(std::vector<SchemaField>{}, std::nullopt);
340316
};
341317

342-
// Static member definition
343-
const std::shared_ptr<Schema> UnpartitionedResidualEvaluator::empty_schema_ =
344-
std::make_shared<Schema>(std::vector<SchemaField>{}, std::nullopt);
345-
346318
} // namespace
347319

320+
ResidualEvaluator::ResidualEvaluator(std::shared_ptr<Expression> expr,
321+
const PartitionSpec& spec, const Schema& schema,
322+
bool case_sensitive)
323+
: expr_(std::move(expr)),
324+
spec_(spec),
325+
schema_(schema),
326+
case_sensitive_(case_sensitive) {}
327+
328+
ResidualEvaluator::~ResidualEvaluator() = default;
329+
348330
Result<std::unique_ptr<ResidualEvaluator>> ResidualEvaluator::Unpartitioned(
349331
std::shared_ptr<Expression> expr) {
350332
return std::unique_ptr<ResidualEvaluator>(

src/iceberg/partition_spec.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ PartitionSpec::GetFieldsBySourceId(int32_t source_id) const {
162162
it != source_id_to_fields.get().cend()) {
163163
return it->second;
164164
}
165-
return NotFound("Cannot find partition fields for source id: {}", source_id);
165+
// Note that it is not an error to not find any partition fields for a source id.
166+
return std::vector<PartitionFieldRef>{};
166167
}
167168

168169
Result<PartitionSpec::SourceIdToFieldsMap> PartitionSpec::InitSourceIdToFieldsMap(

src/iceberg/partition_spec.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class ICEBERG_EXPORT PartitionSpec : public util::Formattable {
6262
std::span<const PartitionField> fields() const;
6363

6464
/// \brief Get the partition type binding to the input schema.
65-
Result<std::unique_ptr<StructType>> PartitionType(const Schema&) const;
65+
Result<std::unique_ptr<StructType>> PartitionType(const Schema& schema) const;
6666

6767
std::string ToString() const override;
6868

@@ -83,8 +83,8 @@ class ICEBERG_EXPORT PartitionSpec : public util::Formattable {
8383
/// \param source_id The id of the source field.
8484
/// \return The partition fields by source ID, or NotFound if the source field is not
8585
/// found.
86-
Result<std::vector<std::reference_wrapper<const PartitionField>>> GetFieldsBySourceId(
87-
int32_t source_id) const;
86+
using PartitionFieldRef = std::reference_wrapper<const PartitionField>;
87+
Result<std::vector<PartitionFieldRef>> GetFieldsBySourceId(int32_t source_id) const;
8888

8989
/// \brief Create a PartitionSpec binding to a schema.
9090
/// \param schema The schema to bind the partition spec to.
@@ -125,9 +125,7 @@ class ICEBERG_EXPORT PartitionSpec : public util::Formattable {
125125
/// \brief Compare two partition specs for equality.
126126
bool Equals(const PartitionSpec& other) const;
127127

128-
using SourceIdToFieldsMap =
129-
std::unordered_map<int32_t,
130-
std::vector<std::reference_wrapper<const PartitionField>>>;
128+
using SourceIdToFieldsMap = std::unordered_map<int32_t, std::vector<PartitionFieldRef>>;
131129
static Result<SourceIdToFieldsMap> InitSourceIdToFieldsMap(const PartitionSpec&);
132130

133131
const int32_t spec_id_;

0 commit comments

Comments
 (0)