Skip to content

Commit 17bd1f8

Browse files
committed
feat: scaffolding work for expression
1 parent 55b0436 commit 17bd1f8

File tree

16 files changed

+2256
-39
lines changed

16 files changed

+2256
-39
lines changed

src/iceberg/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ set(ICEBERG_SOURCES
2121
arrow_c_data_internal.cc
2222
catalog/in_memory_catalog.cc
2323
expression/expression.cc
24+
expression/expressions.cc
2425
expression/literal.cc
26+
expression/predicate.cc
27+
expression/term.cc
2528
file_reader.cc
2629
file_writer.cc
2730
json_internal.cc

src/iceberg/expression/expression.cc

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#include "iceberg/expression/expression.h"
2121

2222
#include <format>
23+
#include <utility>
24+
25+
#include "iceberg/result.h"
26+
#include "iceberg/util/formatter_internal.h"
27+
#include "iceberg/util/macros.h"
2328

2429
namespace iceberg {
2530

@@ -29,15 +34,15 @@ const std::shared_ptr<True>& True::Instance() {
2934
return instance;
3035
}
3136

32-
std::shared_ptr<Expression> True::Negate() const { return False::Instance(); }
37+
Result<std::shared_ptr<Expression>> True::Negate() const { return False::Instance(); }
3338

3439
// False implementation
3540
const std::shared_ptr<False>& False::Instance() {
3641
static const std::shared_ptr<False> instance = std::shared_ptr<False>(new False());
3742
return instance;
3843
}
3944

40-
std::shared_ptr<Expression> False::Negate() const { return True::Instance(); }
45+
Result<std::shared_ptr<Expression>> False::Negate() const { return True::Instance(); }
4146

4247
// And implementation
4348
And::And(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
@@ -47,11 +52,11 @@ std::string And::ToString() const {
4752
return std::format("({} and {})", left_->ToString(), right_->ToString());
4853
}
4954

50-
std::shared_ptr<Expression> And::Negate() const {
55+
Result<std::shared_ptr<Expression>> And::Negate() const {
5156
// De Morgan's law: not(A and B) = (not A) or (not B)
52-
auto left_negated = left_->Negate();
53-
auto right_negated = right_->Negate();
54-
return std::make_shared<Or>(left_negated, right_negated);
57+
ICEBERG_ASSIGN_OR_RAISE(auto left_negated, left_->Negate());
58+
ICEBERG_ASSIGN_OR_RAISE(auto right_negated, right_->Negate());
59+
return std::make_shared<Or>(std::move(left_negated), std::move(right_negated));
5560
}
5661

5762
bool And::Equals(const Expression& expr) const {
@@ -71,11 +76,11 @@ std::string Or::ToString() const {
7176
return std::format("({} or {})", left_->ToString(), right_->ToString());
7277
}
7378

74-
std::shared_ptr<Expression> Or::Negate() const {
79+
Result<std::shared_ptr<Expression>> Or::Negate() const {
7580
// De Morgan's law: not(A or B) = (not A) and (not B)
76-
auto left_negated = left_->Negate();
77-
auto right_negated = right_->Negate();
78-
return std::make_shared<And>(left_negated, right_negated);
81+
ICEBERG_ASSIGN_OR_RAISE(auto left_negated, left_->Negate());
82+
ICEBERG_ASSIGN_OR_RAISE(auto right_negated, right_->Negate());
83+
return std::make_shared<And>(std::move(left_negated), std::move(right_negated));
7984
}
8085

8186
bool Or::Equals(const Expression& expr) const {
@@ -87,4 +92,91 @@ bool Or::Equals(const Expression& expr) const {
8792
return false;
8893
}
8994

95+
std::string_view ToString(Expression::Operation op) {
96+
switch (op) {
97+
case Expression::Operation::kAnd:
98+
return "AND";
99+
case Expression::Operation::kOr:
100+
return "OR";
101+
case Expression::Operation::kTrue:
102+
return "TRUE";
103+
case Expression::Operation::kFalse:
104+
return "FALSE";
105+
case Expression::Operation::kIsNull:
106+
return "IS_NULL";
107+
case Expression::Operation::kNotNull:
108+
return "NOT_NULL";
109+
case Expression::Operation::kIsNan:
110+
return "IS_NAN";
111+
case Expression::Operation::kNotNan:
112+
return "NOT_NAN";
113+
case Expression::Operation::kLt:
114+
return "LT";
115+
case Expression::Operation::kLtEq:
116+
return "LT_EQ";
117+
case Expression::Operation::kGt:
118+
return "GT";
119+
case Expression::Operation::kGtEq:
120+
return "GT_EQ";
121+
case Expression::Operation::kEq:
122+
return "EQ";
123+
case Expression::Operation::kNotEq:
124+
return "NOT_EQ";
125+
case Expression::Operation::kIn:
126+
return "IN";
127+
case Expression::Operation::kNotIn:
128+
return "NOT_IN";
129+
case Expression::Operation::kStartsWith:
130+
return "STARTS_WITH";
131+
case Expression::Operation::kNotStartsWith:
132+
return "NOT_STARTS_WITH";
133+
case Expression::Operation::kCount:
134+
return "COUNT";
135+
case Expression::Operation::kNot:
136+
return "NOT";
137+
case Expression::Operation::kCountStar:
138+
return "COUNT_STAR";
139+
case Expression::Operation::kMax:
140+
return "MAX";
141+
case Expression::Operation::kMin:
142+
return "MIN";
143+
}
144+
std::unreachable();
145+
}
146+
147+
Result<Expression::Operation> Negate(Expression::Operation op) {
148+
switch (op) {
149+
case Expression::Operation::kIsNull:
150+
return Expression::Operation::kNotNull;
151+
case Expression::Operation::kNotNull:
152+
return Expression::Operation::kIsNull;
153+
case Expression::Operation::kIsNan:
154+
return Expression::Operation::kNotNan;
155+
case Expression::Operation::kNotNan:
156+
return Expression::Operation::kIsNan;
157+
case Expression::Operation::kLt:
158+
return Expression::Operation::kGtEq;
159+
case Expression::Operation::kLtEq:
160+
return Expression::Operation::kGt;
161+
case Expression::Operation::kGt:
162+
return Expression::Operation::kLtEq;
163+
case Expression::Operation::kGtEq:
164+
return Expression::Operation::kLt;
165+
case Expression::Operation::kEq:
166+
return Expression::Operation::kNotEq;
167+
case Expression::Operation::kNotEq:
168+
return Expression::Operation::kEq;
169+
case Expression::Operation::kIn:
170+
return Expression::Operation::kNotIn;
171+
case Expression::Operation::kNotIn:
172+
return Expression::Operation::kIn;
173+
case Expression::Operation::kStartsWith:
174+
return Expression::Operation::kNotStartsWith;
175+
case Expression::Operation::kNotStartsWith:
176+
return Expression::Operation::kStartsWith;
177+
default:
178+
return InvalidArgument("No negation for operation: {}", op);
179+
}
180+
}
181+
90182
} // namespace iceberg

src/iceberg/expression/expression.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
#include <memory>
2626
#include <string>
2727

28-
#include "iceberg/exception.h"
2928
#include "iceberg/iceberg_export.h"
29+
#include "iceberg/result.h"
30+
#include "iceberg/util/formattable.h"
3031

3132
namespace iceberg {
3233

3334
/// \brief Represents a boolean expression tree.
34-
class ICEBERG_EXPORT Expression {
35+
class ICEBERG_EXPORT Expression : public util::Formattable {
3536
public:
3637
/// Operation types for expressions
3738
enum class Operation {
@@ -66,8 +67,8 @@ class ICEBERG_EXPORT Expression {
6667
virtual Operation op() const = 0;
6768

6869
/// \brief Returns the negation of this expression, equivalent to not(this).
69-
virtual std::shared_ptr<Expression> Negate() const {
70-
throw IcebergError("Expression cannot be negated");
70+
virtual Result<std::shared_ptr<Expression>> Negate() const {
71+
return NotSupported("Expression cannot be negated");
7172
}
7273

7374
/// \brief Returns whether this expression will accept the same values as another.
@@ -78,7 +79,7 @@ class ICEBERG_EXPORT Expression {
7879
return false;
7980
}
8081

81-
virtual std::string ToString() const { return "Expression"; }
82+
std::string ToString() const override { return "Expression"; }
8283
};
8384

8485
/// \brief An Expression that is always true.
@@ -93,7 +94,7 @@ class ICEBERG_EXPORT True : public Expression {
9394

9495
std::string ToString() const override { return "true"; }
9596

96-
std::shared_ptr<Expression> Negate() const override;
97+
Result<std::shared_ptr<Expression>> Negate() const override;
9798

9899
bool Equals(const Expression& other) const override {
99100
return other.op() == Operation::kTrue;
@@ -113,7 +114,7 @@ class ICEBERG_EXPORT False : public Expression {
113114

114115
std::string ToString() const override { return "false"; }
115116

116-
std::shared_ptr<Expression> Negate() const override;
117+
Result<std::shared_ptr<Expression>> Negate() const override;
117118

118119
bool Equals(const Expression& other) const override {
119120
return other.op() == Operation::kFalse;
@@ -149,7 +150,7 @@ class ICEBERG_EXPORT And : public Expression {
149150

150151
std::string ToString() const override;
151152

152-
std::shared_ptr<Expression> Negate() const override;
153+
Result<std::shared_ptr<Expression>> Negate() const override;
153154

154155
bool Equals(const Expression& other) const override;
155156

@@ -184,7 +185,7 @@ class ICEBERG_EXPORT Or : public Expression {
184185

185186
std::string ToString() const override;
186187

187-
std::shared_ptr<Expression> Negate() const override;
188+
Result<std::shared_ptr<Expression>> Negate() const override;
188189

189190
bool Equals(const Expression& other) const override;
190191

@@ -193,4 +194,8 @@ class ICEBERG_EXPORT Or : public Expression {
193194
std::shared_ptr<Expression> right_;
194195
};
195196

197+
ICEBERG_EXPORT std::string_view ToString(Expression::Operation op);
198+
199+
Result<Expression::Operation> Negate(Expression::Operation op);
200+
196201
} // namespace iceberg

0 commit comments

Comments
 (0)