Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/iceberg/expression/predicate.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "iceberg/expression/expression.h"
#include "iceberg/expression/literal.h"
#include "iceberg/expression/term.h"
#include "iceberg/iceberg_export.h"

namespace iceberg {

Expand Down
768 changes: 768 additions & 0 deletions src/iceberg/test/transform_test.cc

Large diffs are not rendered by default.

66 changes: 66 additions & 0 deletions src/iceberg/transform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,14 @@
#include <regex>
#include <utility>

#include "iceberg/expression/predicate.h"
#include "iceberg/expression/term.h"
#include "iceberg/result.h"
#include "iceberg/transform_function.h"
#include "iceberg/type.h"
#include "iceberg/util/checked_cast.h"
#include "iceberg/util/macros.h"
#include "iceberg/util/projection_util_internal.h"

namespace iceberg {
namespace {
Expand Down Expand Up @@ -240,6 +246,66 @@ bool Transform::SatisfiesOrderOf(const Transform& other) const {
std::unreachable();
}

Result<std::unique_ptr<UnboundPredicate>> Transform::Project(
std::string_view name, const std::shared_ptr<BoundPredicate>& predicate) {
switch (transform_type_) {
case TransformType::kIdentity:
return ProjectionUtil::IdentityProject(name, predicate);
case TransformType::kBucket: {
// If the predicate has a transformed child that matches the given transform, return
// a predicate.
if (predicate->term()->kind() == Term::Kind::kTransform) {
const auto boundTransform =
internal::checked_pointer_cast<BoundTransform>(predicate->term());
if (*this == *boundTransform->transform()) {
return ProjectionUtil::RemoveTransform(name, predicate);
} else {
return nullptr;
}
}
ICEBERG_ASSIGN_OR_RAISE(auto func, Bind(predicate->term()->type()));
return ProjectionUtil::BucketProject(name, predicate, func);
}
case TransformType::kTruncate: {
// If the predicate has a transformed child that matches the given transform, return
// a predicate.
if (predicate->term()->kind() == Term::Kind::kTransform) {
const auto boundTransform =
internal::checked_pointer_cast<BoundTransform>(predicate->term());
if (*this == *boundTransform->transform()) {
return ProjectionUtil::RemoveTransform(name, predicate);
} else {
return nullptr;
}
}
ICEBERG_ASSIGN_OR_RAISE(auto func, Bind(predicate->term()->type()));
return ProjectionUtil::TruncateProject(name, predicate, func);
}
case TransformType::kYear:
case TransformType::kMonth:
case TransformType::kDay:
case TransformType::kHour: {
// If the predicate has a transformed child that matches the given transform, return
// a predicate.
if (predicate->term()->kind() == Term::Kind::kTransform) {
const auto boundTransform =
internal::checked_pointer_cast<BoundTransform>(predicate->term());
if (*this == *boundTransform->transform()) {
return ProjectionUtil::RemoveTransform(name, predicate);
} else {
return nullptr;
}
}
ICEBERG_ASSIGN_OR_RAISE(auto func, Bind(predicate->term()->type()));
return ProjectionUtil::TemporalProject(name, predicate, func);
}
case TransformType::kUnknown:
case TransformType::kVoid:
return nullptr;
}
std::unreachable();
}

bool TransformFunction::Equals(const TransformFunction& other) const {
return transform_type_ == other.transform_type_ && *source_type_ == *other.source_type_;
}
Expand Down
15 changes: 14 additions & 1 deletion src/iceberg/transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <cstdint>
#include <memory>
#include <string_view>
#include <utility>
#include <variant>

Expand Down Expand Up @@ -164,11 +165,23 @@ class ICEBERG_EXPORT Transform : public util::Formattable {
/// For example, sorting by day(ts) will produce an ordering that is also by month(ts)
/// or year(ts). However, sorting by day(ts) will not satisfy the order of hour(ts) or
/// identity(ts).
///
/// \param other The other transform to compare with.
/// \return true if ordering by this transform is equivalent to ordering by the other
/// transform.
bool SatisfiesOrderOf(const Transform& other) const;

/// \brief Transforms a BoundPredicate to an inclusive predicate on the partition values
/// produced by the transform.
///
/// This inclusive transform guarantees that if predicate->Test(value) is true, then
/// Projected(transform(value)) is true.
/// \param name The name of the partition column.
/// \param predicate The predicate to project.
/// \return A Result containing either a unique pointer to the projected predicate,
/// nullptr if the projection cannot be performed, or an Error if the projection fails.
Result<std::unique_ptr<UnboundPredicate>> Project(
std::string_view name, const std::shared_ptr<BoundPredicate>& predicate);

/// \brief Returns a string representation of this transform (e.g., "bucket[16]").
std::string ToString() const override;

Expand Down
3 changes: 3 additions & 0 deletions src/iceberg/transform_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ class ICEBERG_EXPORT TruncateTransform : public TransformFunction {
/// \brief Returns the same type as source_type.
std::shared_ptr<Type> ResultType() const override;

/// \brief Returns the width to truncate to.
int32_t width() const { return width_; }

/// \brief Create a TruncateTransform.
/// \param source_type Type of the input data.
/// \param width The width to truncate to.
Expand Down
3 changes: 3 additions & 0 deletions src/iceberg/type_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ class Uuid;
class Expression;
class Literal;

class BoundPredicate;
class UnboundPredicate;

class DataTableScan;
class FileScanTask;
class ScanTask;
Expand Down
Loading
Loading