Skip to content

Commit 08e11f3

Browse files
committed
add test function
1 parent 90db427 commit 08e11f3

File tree

6 files changed

+375
-20
lines changed

6 files changed

+375
-20
lines changed

src/iceberg/expression/predicate.cc

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
#include "iceberg/expression/predicate.h"
2121

2222
#include <algorithm>
23+
#include <cmath>
2324
#include <format>
2425

25-
#include "iceberg/exception.h"
2626
#include "iceberg/expression/expressions.h"
2727
#include "iceberg/expression/literal.h"
2828
#include "iceberg/result.h"
@@ -143,6 +143,26 @@ bool IsFloatingType(TypeId type) {
143143
return type == TypeId::kFloat || type == TypeId::kDouble;
144144
}
145145

146+
bool IsNan(const Literal& literal) {
147+
const auto& value = literal.value();
148+
if (std::holds_alternative<float>(value)) {
149+
return std::isnan(std::get<float>(value));
150+
} else if (std::holds_alternative<double>(value)) {
151+
return std::isnan(std::get<double>(value));
152+
}
153+
return false;
154+
}
155+
156+
bool StartsWith(const Literal& lhs, const Literal& rhs) {
157+
const auto& lhs_value = lhs.value();
158+
const auto& rhs_value = rhs.value();
159+
if (std::holds_alternative<std::string>(lhs_value) &&
160+
std::holds_alternative<std::string>(rhs_value)) {
161+
return std::get<std::string>(lhs_value).starts_with(std::get<std::string>(rhs_value));
162+
}
163+
return false;
164+
}
165+
146166
} // namespace
147167

148168
template <typename B>
@@ -287,10 +307,10 @@ BoundPredicate::BoundPredicate(Expression::Operation op, std::shared_ptr<BoundTe
287307

288308
BoundPredicate::~BoundPredicate() = default;
289309

290-
Result<Literal::Value> BoundPredicate::Evaluate(const StructLike& data) const {
310+
Result<Literal> BoundPredicate::Evaluate(const StructLike& data) const {
291311
ICEBERG_ASSIGN_OR_RAISE(auto eval_result, term_->Evaluate(data));
292312
ICEBERG_ASSIGN_OR_RAISE(auto test_result, Test(eval_result));
293-
return Literal::Value{test_result};
313+
return Literal::Boolean(test_result);
294314
}
295315

296316
// BoundUnaryPredicate implementation
@@ -300,8 +320,19 @@ BoundUnaryPredicate::BoundUnaryPredicate(Expression::Operation op,
300320

301321
BoundUnaryPredicate::~BoundUnaryPredicate() = default;
302322

303-
Result<bool> BoundUnaryPredicate::Test(const Literal::Value& value) const {
304-
return NotImplemented("BoundUnaryPredicate::Test not implemented");
323+
Result<bool> BoundUnaryPredicate::Test(const Literal& literal) const {
324+
switch (op()) {
325+
case Expression::Operation::kIsNull:
326+
return literal.IsNull();
327+
case Expression::Operation::kNotNull:
328+
return !literal.IsNull();
329+
case Expression::Operation::kIsNan:
330+
return IsNan(literal);
331+
case Expression::Operation::kNotNan:
332+
return !IsNan(literal);
333+
default:
334+
return InvalidExpression("Invalid operation for BoundUnaryPredicate: {}", op());
335+
}
305336
}
306337

307338
Result<std::shared_ptr<Expression>> BoundUnaryPredicate::Negate() const {
@@ -345,8 +376,27 @@ BoundLiteralPredicate::BoundLiteralPredicate(Expression::Operation op,
345376

346377
BoundLiteralPredicate::~BoundLiteralPredicate() = default;
347378

348-
Result<bool> BoundLiteralPredicate::Test(const Literal::Value& value) const {
349-
return NotImplemented("BoundLiteralPredicate::Test not implemented");
379+
Result<bool> BoundLiteralPredicate::Test(const Literal& value) const {
380+
switch (op()) {
381+
case Expression::Operation::kLt:
382+
return value < literal_;
383+
case Expression::Operation::kLtEq:
384+
return value <= literal_;
385+
case Expression::Operation::kGt:
386+
return value > literal_;
387+
case Expression::Operation::kGtEq:
388+
return value >= literal_;
389+
case Expression::Operation::kEq:
390+
return value == literal_;
391+
case Expression::Operation::kNotEq:
392+
return value != literal_;
393+
case Expression::Operation::kStartsWith:
394+
return StartsWith(value, literal_);
395+
case Expression::Operation::kNotStartsWith:
396+
return !StartsWith(value, literal_);
397+
default:
398+
return InvalidExpression("Invalid operation for BoundLiteralPredicate: {}", op());
399+
}
350400
}
351401

352402
Result<std::shared_ptr<Expression>> BoundLiteralPredicate::Negate() const {
@@ -453,8 +503,15 @@ BoundSetPredicate::BoundSetPredicate(Expression::Operation op,
453503

454504
BoundSetPredicate::~BoundSetPredicate() = default;
455505

456-
Result<bool> BoundSetPredicate::Test(const Literal::Value& value) const {
457-
return NotImplemented("BoundSetPredicate::Test not implemented");
506+
Result<bool> BoundSetPredicate::Test(const Literal& value) const {
507+
switch (op()) {
508+
case Expression::Operation::kIn:
509+
return value_set_.contains(value);
510+
case Expression::Operation::kNotIn:
511+
return !value_set_.contains(value);
512+
default:
513+
return InvalidExpression("Invalid operation for BoundSetPredicate: {}", op());
514+
}
458515
}
459516

460517
Result<std::shared_ptr<Expression>> BoundSetPredicate::Negate() const {

src/iceberg/expression/predicate.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,13 @@ class ICEBERG_EXPORT BoundPredicate : public Predicate<BoundTerm>, public Bound
113113

114114
std::shared_ptr<BoundReference> reference() override { return term_->reference(); }
115115

116-
Result<Literal::Value> Evaluate(const StructLike& data) const override;
116+
Result<Literal> Evaluate(const StructLike& data) const override;
117117

118118
/// \brief Test a value against this predicate.
119119
///
120-
/// \param value The value to test
120+
/// \param value The literal value to test
121121
/// \return true if the predicate passes, false otherwise
122-
virtual Result<bool> Test(const Literal::Value& value) const = 0;
122+
virtual Result<bool> Test(const Literal& value) const = 0;
123123

124124
enum class Kind : int8_t {
125125
// A unary predicate (tests for null, not-null, etc.).
@@ -145,7 +145,7 @@ class ICEBERG_EXPORT BoundUnaryPredicate : public BoundPredicate {
145145

146146
~BoundUnaryPredicate() override;
147147

148-
Result<bool> Test(const Literal::Value& value) const override;
148+
Result<bool> Test(const Literal& value) const override;
149149

150150
Kind kind() const override { return Kind::kUnary; }
151151

@@ -172,7 +172,7 @@ class ICEBERG_EXPORT BoundLiteralPredicate : public BoundPredicate {
172172
/// \brief Returns the literal being compared against.
173173
const Literal& literal() const { return literal_; }
174174

175-
Result<bool> Test(const Literal::Value& value) const override;
175+
Result<bool> Test(const Literal& value) const override;
176176

177177
Kind kind() const override { return Kind::kLiteral; }
178178

@@ -208,7 +208,7 @@ class ICEBERG_EXPORT BoundSetPredicate : public BoundPredicate {
208208
/// \brief Returns the set of literals to test against.
209209
const LiteralSet& literal_set() const { return value_set_; }
210210

211-
Result<bool> Test(const Literal::Value& value) const override;
211+
Result<bool> Test(const Literal& value) const override;
212212

213213
Kind kind() const override { return Kind::kSet; }
214214

src/iceberg/expression/term.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ std::string BoundReference::ToString() const {
7171
return std::format("ref(id={}, type={})", field_.field_id(), field_.type()->ToString());
7272
}
7373

74-
Result<Literal::Value> BoundReference::Evaluate(const StructLike& data) const {
74+
Result<Literal> BoundReference::Evaluate(const StructLike& data) const {
7575
return NotImplemented("BoundReference::Evaluate(StructLike) not implemented");
7676
}
7777

@@ -119,7 +119,7 @@ std::string BoundTransform::ToString() const {
119119
return std::format("{}({})", transform_->ToString(), ref_->ToString());
120120
}
121121

122-
Result<Literal::Value> BoundTransform::Evaluate(const StructLike& data) const {
122+
Result<Literal> BoundTransform::Evaluate(const StructLike& data) const {
123123
throw IcebergError("BoundTransform::Evaluate(StructLike) not implemented");
124124
}
125125

src/iceberg/expression/term.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class ICEBERG_EXPORT Bound {
7979
virtual ~Bound();
8080

8181
/// \brief Evaluate this expression against a row-based data.
82-
virtual Result<Literal::Value> Evaluate(const StructLike& data) const = 0;
82+
virtual Result<Literal> Evaluate(const StructLike& data) const = 0;
8383

8484
/// \brief Returns the underlying bound reference for this term.
8585
virtual std::shared_ptr<class BoundReference> reference() = 0;
@@ -176,7 +176,7 @@ class ICEBERG_EXPORT BoundReference
176176

177177
std::string ToString() const override;
178178

179-
Result<Literal::Value> Evaluate(const StructLike& data) const override;
179+
Result<Literal> Evaluate(const StructLike& data) const override;
180180

181181
std::shared_ptr<BoundReference> reference() override { return shared_from_this(); }
182182

@@ -236,7 +236,7 @@ class ICEBERG_EXPORT BoundTransform : public BoundTerm {
236236

237237
std::string ToString() const override;
238238

239-
Result<Literal::Value> Evaluate(const StructLike& data) const override;
239+
Result<Literal> Evaluate(const StructLike& data) const override;
240240

241241
std::shared_ptr<BoundReference> reference() override { return ref_; }
242242

0 commit comments

Comments
 (0)