mapleFU commented on code in PR #117: URL: https://github.com/apache/iceberg-cpp/pull/117#discussion_r2129149222
########## src/iceberg/literal.cc: ########## @@ -0,0 +1,318 @@ +/* + * 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. + */ + +#include "iceberg/literal.h" + +#include <sstream> + +#include "iceberg/exception.h" + +namespace iceberg { + +// Constructor +PrimitiveLiteral::PrimitiveLiteral(PrimitiveLiteralValue value, + std::shared_ptr<PrimitiveType> type) + : value_(std::move(value)), type_(std::move(type)) {} + +// Factory methods +PrimitiveLiteral PrimitiveLiteral::Boolean(bool value) { + return {PrimitiveLiteralValue{value}, std::make_shared<BooleanType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::Int(int32_t value) { + return {PrimitiveLiteralValue{value}, std::make_shared<IntType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::Long(int64_t value) { + return {PrimitiveLiteralValue{value}, std::make_shared<LongType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::Float(float value) { + return {PrimitiveLiteralValue{value}, std::make_shared<FloatType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::Double(double value) { + return {PrimitiveLiteralValue{value}, std::make_shared<DoubleType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::String(std::string value) { + return {PrimitiveLiteralValue{std::move(value)}, std::make_shared<StringType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::Binary(std::vector<uint8_t> value) { + return {PrimitiveLiteralValue{std::move(value)}, std::make_shared<BinaryType>()}; +} + +PrimitiveLiteral PrimitiveLiteral::BelowMinLiteral(std::shared_ptr<PrimitiveType> type) { + return PrimitiveLiteral(PrimitiveLiteralValue{BelowMin{}}, std::move(type)); +} + +PrimitiveLiteral PrimitiveLiteral::AboveMaxLiteral(std::shared_ptr<PrimitiveType> type) { + return PrimitiveLiteral(PrimitiveLiteralValue{AboveMax{}}, std::move(type)); +} + +Result<PrimitiveLiteral> PrimitiveLiteral::Deserialize(std::span<const uint8_t> data) { + return NotImplemented("Deserialization of PrimitiveLiteral is not implemented yet"); +} + +Result<std::vector<uint8_t>> PrimitiveLiteral::Serialize() const { + return NotImplemented("Serialization of PrimitiveLiteral is not implemented yet"); +} + +// Getters + +const std::shared_ptr<PrimitiveType>& PrimitiveLiteral::type() const { return type_; } + +// Cast method +Result<PrimitiveLiteral> PrimitiveLiteral::CastTo( + const std::shared_ptr<PrimitiveType>& target_type) const { + if (*type_ == *target_type) { + // If types are the same, return a copy of the current literal + return PrimitiveLiteral(value_, target_type); + } + + // Handle special values + if (std::holds_alternative<BelowMin>(value_) || + std::holds_alternative<AboveMax>(value_)) { + // Cannot cast type for special values + return NotSupported("Cannot cast type for {}", ToString()); + } + + auto source_type_id = type_->type_id(); + auto target_type_id = target_type->type_id(); + + // Delegate to specific cast functions based on source type + switch (source_type_id) { + case TypeId::kInt: + return CastFromInt(target_type_id); + case TypeId::kLong: + return CastFromLong(target_type_id); + case TypeId::kFloat: + return CastFromFloat(target_type_id); + case TypeId::kDouble: + return CastFromDouble(target_type_id); + case TypeId::kBoolean: + case TypeId::kString: + case TypeId::kBinary: + // These types only support conversion to string (handled above) + break; + default: + break; + } + + return NotSupported("Cast from {} to {} is not implemented", type_->ToString(), + target_type->ToString()); +} + +Result<PrimitiveLiteral> PrimitiveLiteral::CastFromInt(TypeId target_type_id) const { + auto int_val = std::get<int32_t>(value_); + + switch (target_type_id) { + case TypeId::kLong: + return PrimitiveLiteral::Long(static_cast<int64_t>(int_val)); + case TypeId::kFloat: + return PrimitiveLiteral::Float(static_cast<float>(int_val)); + case TypeId::kDouble: + return PrimitiveLiteral::Double(static_cast<double>(int_val)); + // TODO(mwish): Supports casts to date and literal + default: + return NotSupported("Cast from Int to {} is not implemented", + static_cast<int>(target_type_id)); + } +} + +Result<PrimitiveLiteral> PrimitiveLiteral::CastFromLong(TypeId target_type_id) const { + auto long_val = std::get<int64_t>(value_); + + switch (target_type_id) { + case TypeId::kInt: { + // Check for overflow + if (long_val >= std::numeric_limits<int32_t>::max()) { + return PrimitiveLiteral::AboveMaxLiteral(type_); + } + if (long_val <= std::numeric_limits<int32_t>::min()) { + return PrimitiveLiteral::BelowMinLiteral(type_); + } + return PrimitiveLiteral::Int(static_cast<int32_t>(long_val)); + } + case TypeId::kFloat: + return PrimitiveLiteral::Float(static_cast<float>(long_val)); + case TypeId::kDouble: + return PrimitiveLiteral::Double(static_cast<double>(long_val)); + default: + return NotImplemented("Cast from Long to {} is not implemented", + static_cast<int>(target_type_id)); + } +} + +Result<PrimitiveLiteral> PrimitiveLiteral::CastFromFloat(TypeId target_type_id) const { + auto float_val = std::get<float>(value_); + + switch (target_type_id) { + case TypeId::kDouble: + return PrimitiveLiteral::Double(static_cast<double>(float_val)); + default: + return NotImplemented("Cast from Float to {} is not implemented", + static_cast<int>(target_type_id)); + } +} + +Result<PrimitiveLiteral> PrimitiveLiteral::CastFromDouble(TypeId target_type_id) const { + auto double_val = std::get<double>(value_); + + switch (target_type_id) { + case TypeId::kFloat: { + if (double_val > std::numeric_limits<float>::max()) { Review Comment: this might lost precision, don't know the design considerations here -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org For additional commands, e-mail: issues-h...@iceberg.apache.org