Skip to content

Commit 5a49c08

Browse files
committed
feat: scaffolding work for expression
1 parent 55b0436 commit 5a49c08

16 files changed

+2257
-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: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
#include "iceberg/expression/expression.h"
2121

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

2428
namespace iceberg {
2529

@@ -29,15 +33,15 @@ const std::shared_ptr<True>& True::Instance() {
2933
return instance;
3034
}
3135

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

3438
// False implementation
3539
const std::shared_ptr<False>& False::Instance() {
3640
static const std::shared_ptr<False> instance = std::shared_ptr<False>(new False());
3741
return instance;
3842
}
3943

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

4246
// And implementation
4347
And::And(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)
@@ -47,11 +51,11 @@ std::string And::ToString() const {
4751
return std::format("({} and {})", left_->ToString(), right_->ToString());
4852
}
4953

50-
std::shared_ptr<Expression> And::Negate() const {
54+
Result<std::shared_ptr<Expression>> And::Negate() const {
5155
// 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);
56+
ICEBERG_ASSIGN_OR_RAISE(auto left_negated, left_->Negate());
57+
ICEBERG_ASSIGN_OR_RAISE(auto right_negated, right_->Negate());
58+
return std::make_shared<Or>(std::move(left_negated), std::move(right_negated));
5559
}
5660

5761
bool And::Equals(const Expression& expr) const {
@@ -71,11 +75,11 @@ std::string Or::ToString() const {
7175
return std::format("({} or {})", left_->ToString(), right_->ToString());
7276
}
7377

74-
std::shared_ptr<Expression> Or::Negate() const {
78+
Result<std::shared_ptr<Expression>> Or::Negate() const {
7579
// 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);
80+
ICEBERG_ASSIGN_OR_RAISE(auto left_negated, left_->Negate());
81+
ICEBERG_ASSIGN_OR_RAISE(auto right_negated, right_->Negate());
82+
return std::make_shared<And>(std::move(left_negated), std::move(right_negated));
7983
}
8084

8185
bool Or::Equals(const Expression& expr) const {
@@ -87,4 +91,91 @@ bool Or::Equals(const Expression& expr) const {
8791
return false;
8892
}
8993

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

src/iceberg/expression/expression.h

Lines changed: 16 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,10 @@ class ICEBERG_EXPORT Or : public Expression {
193194
std::shared_ptr<Expression> right_;
194195
};
195196

197+
/// \brief Returns a string representation of an expression operation.
198+
ICEBERG_EXPORT std::string_view ToString(Expression::Operation op);
199+
200+
/// \brief Returns the negated operation.
201+
Result<Expression::Operation> Negate(Expression::Operation op);
202+
196203
} // namespace iceberg

0 commit comments

Comments
 (0)