|
| 1 | +/* |
| 2 | + * Copyright (c) Facebook, Inc. and its affiliates. |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | +#include "velox/connectors/hive/iceberg/TransformExprBuilder.h" |
| 17 | +#include "velox/core/Expressions.h" |
| 18 | + |
| 19 | +namespace facebook::velox::connector::hive::iceberg { |
| 20 | + |
| 21 | +namespace { |
| 22 | + |
| 23 | +constexpr char const* kBucketFunction{"iceberg_bucket"}; |
| 24 | +constexpr char const* kTruncateFunction{"iceberg_truncate"}; |
| 25 | +constexpr char const* kYearFunction{"iceberg_years"}; |
| 26 | +constexpr char const* kMonthFunction{"iceberg_months"}; |
| 27 | +constexpr char const* kDayFunction{"iceberg_days"}; |
| 28 | +constexpr char const* kHourFunction{"iceberg_hours"}; |
| 29 | + |
| 30 | +/// Converts a single partition field to a typed expression. |
| 31 | +/// |
| 32 | +/// Builds an expression tree for one partition transform. Identity transforms |
| 33 | +/// become FieldAccessTypedExpr, while other transforms (bucket, truncate, |
| 34 | +/// year, month, day, hour) become CallTypedExpr with appropriate function |
| 35 | +/// names and parameters. |
| 36 | +/// |
| 37 | +/// @param field Partition field containing transform type, source column |
| 38 | +/// type, and optional parameter (e.g., bucket count, truncate width). |
| 39 | +/// @param inputFieldName Name of the source column in the input RowVector. |
| 40 | +/// @return Typed expression representing the transform. |
| 41 | +core::TypedExprPtr toExpression( |
| 42 | + const IcebergPartitionSpec::Field& field, |
| 43 | + const std::string& inputFieldName) { |
| 44 | + // For identity transform, just return a field access expression. |
| 45 | + if (field.transformType == TransformType::kIdentity) { |
| 46 | + return std::make_shared<core::FieldAccessTypedExpr>( |
| 47 | + field.type, inputFieldName); |
| 48 | + } |
| 49 | + |
| 50 | + // For other transforms, build a CallTypedExpr with the appropriate function. |
| 51 | + std::string functionName; |
| 52 | + switch (field.transformType) { |
| 53 | + case TransformType::kBucket: |
| 54 | + functionName = kBucketFunction; |
| 55 | + break; |
| 56 | + case TransformType::kTruncate: |
| 57 | + functionName = kTruncateFunction; |
| 58 | + break; |
| 59 | + case TransformType::kYear: |
| 60 | + functionName = kYearFunction; |
| 61 | + break; |
| 62 | + case TransformType::kMonth: |
| 63 | + functionName = kMonthFunction; |
| 64 | + break; |
| 65 | + case TransformType::kDay: |
| 66 | + functionName = kDayFunction; |
| 67 | + break; |
| 68 | + case TransformType::kHour: |
| 69 | + functionName = kHourFunction; |
| 70 | + break; |
| 71 | + case TransformType::kIdentity: |
| 72 | + break; |
| 73 | + } |
| 74 | + |
| 75 | + // Build the expression arguments. |
| 76 | + std::vector<core::TypedExprPtr> exprArgs; |
| 77 | + if (field.parameter.has_value()) { |
| 78 | + exprArgs.emplace_back( |
| 79 | + std::make_shared<core::ConstantTypedExpr>( |
| 80 | + INTEGER(), Variant(field.parameter.value()))); |
| 81 | + } |
| 82 | + exprArgs.emplace_back( |
| 83 | + std::make_shared<core::FieldAccessTypedExpr>(field.type, inputFieldName)); |
| 84 | + |
| 85 | + return std::make_shared<core::CallTypedExpr>( |
| 86 | + field.resultType(), std::move(exprArgs), functionName); |
| 87 | +} |
| 88 | + |
| 89 | +} // namespace |
| 90 | + |
| 91 | +std::vector<core::TypedExprPtr> TransformExprBuilder::toExpressions( |
| 92 | + const IcebergPartitionSpecPtr& partitionSpec, |
| 93 | + const std::vector<column_index_t>& partitionChannels, |
| 94 | + const RowTypePtr& inputType) { |
| 95 | + VELOX_CHECK_EQ( |
| 96 | + partitionSpec->fields.size(), |
| 97 | + partitionChannels.size(), |
| 98 | + "Number of partition fields must match number of partition channels"); |
| 99 | + |
| 100 | + const auto numTransforms = partitionChannels.size(); |
| 101 | + std::vector<core::TypedExprPtr> transformExprs; |
| 102 | + transformExprs.reserve(numTransforms); |
| 103 | + |
| 104 | + for (auto i = 0; i < numTransforms; i++) { |
| 105 | + const auto channel = partitionChannels[i]; |
| 106 | + transformExprs.emplace_back( |
| 107 | + toExpression(partitionSpec->fields.at(i), inputType->nameOf(channel))); |
| 108 | + } |
| 109 | + |
| 110 | + return transformExprs; |
| 111 | +} |
| 112 | + |
| 113 | +} // namespace facebook::velox::connector::hive::iceberg |
0 commit comments