|
23 | 23 | #include <regex> |
24 | 24 | #include <utility> |
25 | 25 |
|
| 26 | +#include "iceberg/expression/predicate.h" |
| 27 | +#include "iceberg/expression/term.h" |
| 28 | +#include "iceberg/result.h" |
26 | 29 | #include "iceberg/transform_function.h" |
27 | 30 | #include "iceberg/type.h" |
| 31 | +#include "iceberg/util/checked_cast.h" |
| 32 | +#include "iceberg/util/macros.h" |
| 33 | +#include "iceberg/util/projection_util_internal.h" |
28 | 34 |
|
29 | 35 | namespace iceberg { |
30 | 36 | namespace { |
@@ -240,6 +246,66 @@ bool Transform::SatisfiesOrderOf(const Transform& other) const { |
240 | 246 | std::unreachable(); |
241 | 247 | } |
242 | 248 |
|
| 249 | +Result<std::unique_ptr<UnboundPredicate>> Transform::Project( |
| 250 | + std::string_view name, const std::shared_ptr<BoundPredicate>& predicate) { |
| 251 | + switch (transform_type_) { |
| 252 | + case TransformType::kIdentity: |
| 253 | + return ProjectionUtil::IdentityProject(name, predicate); |
| 254 | + case TransformType::kBucket: { |
| 255 | + // If the predicate has a transformed child that matches the given transform, return |
| 256 | + // a predicate. |
| 257 | + if (predicate->term()->kind() == Term::Kind::kTransform) { |
| 258 | + const auto boundTransform = |
| 259 | + internal::checked_pointer_cast<BoundTransform>(predicate->term()); |
| 260 | + if (*this == *boundTransform->transform()) { |
| 261 | + return ProjectionUtil::RemoveTransform(name, predicate); |
| 262 | + } else { |
| 263 | + return nullptr; |
| 264 | + } |
| 265 | + } |
| 266 | + ICEBERG_ASSIGN_OR_RAISE(auto func, Bind(predicate->term()->type())); |
| 267 | + return ProjectionUtil::BucketProject(name, predicate, func); |
| 268 | + } |
| 269 | + case TransformType::kTruncate: { |
| 270 | + // If the predicate has a transformed child that matches the given transform, return |
| 271 | + // a predicate. |
| 272 | + if (predicate->term()->kind() == Term::Kind::kTransform) { |
| 273 | + const auto boundTransform = |
| 274 | + internal::checked_pointer_cast<BoundTransform>(predicate->term()); |
| 275 | + if (*this == *boundTransform->transform()) { |
| 276 | + return ProjectionUtil::RemoveTransform(name, predicate); |
| 277 | + } else { |
| 278 | + return nullptr; |
| 279 | + } |
| 280 | + } |
| 281 | + ICEBERG_ASSIGN_OR_RAISE(auto func, Bind(predicate->term()->type())); |
| 282 | + return ProjectionUtil::TruncateProject(name, predicate, func); |
| 283 | + } |
| 284 | + case TransformType::kYear: |
| 285 | + case TransformType::kMonth: |
| 286 | + case TransformType::kDay: |
| 287 | + case TransformType::kHour: { |
| 288 | + // If the predicate has a transformed child that matches the given transform, return |
| 289 | + // a predicate. |
| 290 | + if (predicate->term()->kind() == Term::Kind::kTransform) { |
| 291 | + const auto boundTransform = |
| 292 | + internal::checked_pointer_cast<BoundTransform>(predicate->term()); |
| 293 | + if (*this == *boundTransform->transform()) { |
| 294 | + return ProjectionUtil::RemoveTransform(name, predicate); |
| 295 | + } else { |
| 296 | + return nullptr; |
| 297 | + } |
| 298 | + } |
| 299 | + ICEBERG_ASSIGN_OR_RAISE(auto func, Bind(predicate->term()->type())); |
| 300 | + return ProjectionUtil::TemporalProject(name, predicate, func); |
| 301 | + } |
| 302 | + case TransformType::kUnknown: |
| 303 | + case TransformType::kVoid: |
| 304 | + return nullptr; |
| 305 | + } |
| 306 | + std::unreachable(); |
| 307 | +} |
| 308 | + |
243 | 309 | bool TransformFunction::Equals(const TransformFunction& other) const { |
244 | 310 | return transform_type_ == other.transform_type_ && *source_type_ == *other.source_type_; |
245 | 311 | } |
|
0 commit comments