blob: 453abf8a6da43dbaf260bcbc6600587f3bf819f9 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#pragma once
#include <memory>
#include <string>
#include "arrow/compute/api.h"
#include "fmt/format.h"
#include "paimon/common/utils/arrow/status_utils.h"
#include "paimon/common/utils/field_type_utils.h"
#include "paimon/data/decimal.h"
#include "paimon/predicate/literal.h"
namespace paimon {
class CastingUtils {
public:
CastingUtils() = delete;
~CastingUtils() = delete;
// make sure src and casted literals are both integer (i.e., TINYINT, SMALLINT, INT, BIGINT)
static bool IsIntegerLiteralCastedOverflow(const Literal& src_literal,
const Literal& casted_literal) {
return GetLongValueFromLiteral(src_literal) != GetLongValueFromLiteral(casted_literal);
}
static Result<std::shared_ptr<arrow::Array>> Cast(
const std::shared_ptr<arrow::Array>& src_array,
const std::shared_ptr<arrow::DataType>& target_type,
const arrow::compute::CastOptions& options, arrow::MemoryPool* pool);
template <typename SrcScalar, typename SrcDataType, typename TargetScalar,
typename TargetDataType>
static Result<Literal> Cast(const Literal& literal,
const std::shared_ptr<arrow::DataType>& src_type,
const std::shared_ptr<arrow::DataType>& target_type,
const arrow::compute::CastOptions& options) {
PAIMON_ASSIGN_OR_RAISE(FieldType target_field_type,
FieldTypeUtils::ConvertToFieldType(target_type->id()));
if (literal.IsNull()) {
return Literal(target_field_type);
}
auto src_value = literal.GetValue<SrcDataType>();
if (!arrow::compute::CanCast(*src_type, *target_type)) {
return Status::Invalid(fmt::format("cast literal failed: cannot cast from {} to {}",
src_type->ToString(), target_type->ToString()));
}
std::shared_ptr<arrow::Scalar> src_scalar;
if constexpr (std::is_same_v<SrcDataType, Decimal>) {
src_scalar = std::make_shared<SrcScalar>(
arrow::Decimal128(src_value.HighBits(), src_value.LowBits()), src_type);
} else {
src_scalar = std::make_shared<SrcScalar>(src_value);
}
arrow::TypeHolder type_holder(target_type.get());
PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(
arrow::Datum casted_result,
arrow::compute::Cast(arrow::Datum(src_scalar), type_holder, options));
auto* casted_scalar =
arrow::internal::checked_cast<TargetScalar*>(casted_result.scalar().get());
if (!casted_scalar) {
return Status::Invalid(fmt::format("cast literal failed: cannot cast to {} scalar",
target_type->ToString()));
}
if constexpr (std::is_same_v<TargetDataType, std::string>) {
std::string_view casted_data = casted_scalar->view();
return Literal(FieldType::STRING, casted_data.data(), casted_data.size());
} else {
const auto* casted_data = static_cast<const TargetDataType*>(casted_scalar->data());
assert(casted_data);
return Literal(*casted_data);
}
}
// src_array is local time (no tz), target type is utc (with tz)
static Result<std::shared_ptr<arrow::Array>> TimestampToTimestampWithTimezone(
const std::shared_ptr<arrow::Array>& src_array,
const std::shared_ptr<arrow::TimestampType>& target_type, arrow::MemoryPool* pool);
// src_array is utc (with tz) , target type is local time (no tz),
static Result<std::shared_ptr<arrow::Array>> TimestampWithTimezoneToTimestamp(
const std::shared_ptr<arrow::Array>& src_array,
const std::shared_ptr<arrow::TimestampType>& target_type, arrow::MemoryPool* pool);
private:
static int64_t GetLongValueFromLiteral(const Literal& literal);
};
} // namespace paimon