Skip to content

Commit 1e106ed

Browse files
committed
add decimal support
1 parent 636e323 commit 1e106ed

File tree

4 files changed

+243
-56
lines changed

4 files changed

+243
-56
lines changed

src/iceberg/expression/literal.cc

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "iceberg/exception.h"
2727
#include "iceberg/type_fwd.h"
28+
#include "iceberg/util/macros.h"
2829

2930
namespace iceberg {
3031

@@ -102,7 +103,10 @@ Result<Literal> LiteralCaster::CastFromInt(
102103
return Literal::Double(static_cast<double>(int_val));
103104
case TypeId::kDate:
104105
return Literal::Date(int_val);
105-
// TODO(Li Feiyang): Implement cast from Int to decimal
106+
case TypeId::kDecimal: {
107+
auto decimal_type = std::static_pointer_cast<DecimalType>(target_type);
108+
return Literal::Decimal(int_val, decimal_type->precision(), decimal_type->scale());
109+
}
106110
default:
107111
return NotSupported("Cast from Int to {} is not implemented",
108112
target_type->ToString());
@@ -143,7 +147,10 @@ Result<Literal> LiteralCaster::CastFromLong(
143147
return Literal::Timestamp(long_val);
144148
case TypeId::kTimestampTz:
145149
return Literal::TimestampTz(long_val);
146-
// TODO(Li Feiyang): Implement cast from Long to decimal, TimestampNs and
150+
case TypeId::kDecimal: {
151+
auto decimal_type = std::static_pointer_cast<DecimalType>(target_type);
152+
return Literal::Decimal(long_val, decimal_type->precision(), decimal_type->scale());
153+
}
147154
default:
148155
return NotSupported("Cast from Long to {} is not supported",
149156
target_type->ToString());
@@ -157,7 +164,21 @@ Result<Literal> LiteralCaster::CastFromFloat(
157164
switch (target_type->type_id()) {
158165
case TypeId::kDouble:
159166
return Literal::Double(static_cast<double>(float_val));
160-
// TODO(Li Feiyang): Implement cast from Float to decimal
167+
case TypeId::kDecimal: {
168+
auto decimal_type = std::static_pointer_cast<DecimalType>(target_type);
169+
std::string float_str = std::to_string(float_val);
170+
171+
iceberg::Decimal parsed_val;
172+
int32_t parsed_scale = 0;
173+
ICEBERG_ASSIGN_OR_RAISE(
174+
parsed_val, iceberg::Decimal::FromString(float_str, nullptr, &parsed_scale));
175+
iceberg::Decimal rescaled_val;
176+
ICEBERG_ASSIGN_OR_RAISE(rescaled_val,
177+
parsed_val.Rescale(parsed_scale, decimal_type->scale()));
178+
179+
return Literal::Decimal(rescaled_val.value(), decimal_type->precision(),
180+
decimal_type->scale());
181+
}
161182
default:
162183
return NotSupported("Cast from Float to {} is not supported",
163184
target_type->ToString());
@@ -178,6 +199,21 @@ Result<Literal> LiteralCaster::CastFromDouble(
178199
}
179200
return Literal::Float(static_cast<float>(double_val));
180201
}
202+
case TypeId::kDecimal: {
203+
auto decimal_type = std::static_pointer_cast<DecimalType>(target_type);
204+
std::string double_str = std::to_string(double_val);
205+
206+
iceberg::Decimal parsed_val;
207+
int32_t parsed_scale = 0;
208+
ICEBERG_ASSIGN_OR_RAISE(
209+
parsed_val, iceberg::Decimal::FromString(double_str, nullptr, &parsed_scale));
210+
iceberg::Decimal rescaled_val;
211+
ICEBERG_ASSIGN_OR_RAISE(rescaled_val,
212+
parsed_val.Rescale(parsed_scale, decimal_type->scale()));
213+
214+
return Literal::Decimal(rescaled_val.value(), decimal_type->precision(),
215+
decimal_type->scale());
216+
}
181217
default:
182218
return NotSupported("Cast from Double to {} is not supported",
183219
target_type->ToString());
@@ -193,9 +229,16 @@ Result<Literal> LiteralCaster::CastFromString(
193229
case TypeId::kTime:
194230
case TypeId::kTimestamp:
195231
case TypeId::kTimestampTz:
232+
case TypeId::kUuid:
196233
return NotImplemented("Cast from String to {} is not implemented yet",
197234
target_type->ToString());
198-
// TODO(Li Feiyang): Implement cast from String to uuid and decimal
235+
case TypeId::kDecimal: {
236+
auto decimal_type = std::static_pointer_cast<DecimalType>(target_type);
237+
iceberg::Decimal dec_val;
238+
ICEBERG_ASSIGN_OR_RAISE(dec_val, iceberg::Decimal::FromString(str_val));
239+
return Literal::Decimal(dec_val.value(), decimal_type->precision(),
240+
decimal_type->scale());
241+
}
199242

200243
default:
201244
return NotSupported("Cast from String to {} is not supported",
@@ -407,14 +450,25 @@ std::partial_ordering Literal::operator<=>(const Literal& other) const {
407450
return this_val <=> other_val;
408451
}
409452

453+
case TypeId::kDecimal: {
454+
auto this_val = std::get<int128_t>(value_);
455+
auto other_val = std::get<int128_t>(other.value_);
456+
return this_val <=> other_val;
457+
}
458+
410459
default:
411460
// For unsupported types, return unordered
412461
return std::partial_ordering::unordered;
413462
}
414463
}
415464

416465
std::string Literal::ToString() const {
417-
auto invalid_ = [this]() { return std::format(" = {}", type_->ToString()); };
466+
auto unsupported_error = [this]() {
467+
return std::format("ToString not supported for type: {}", type_->ToString());
468+
};
469+
auto invalid_argument = [this]() {
470+
return std::format("Invalid argument for type: {}", type_->ToString());
471+
};
418472

419473
if (std::holds_alternative<BelowMin>(value_)) {
420474
return "belowMin";
@@ -443,7 +497,7 @@ std::string Literal::ToString() const {
443497
return std::to_string(std::get<double>(value_));
444498
}
445499
case TypeId::kString: {
446-
return std::get<std::string>(value_);
500+
return "\"" + std::get<std::string>(value_) + "\"";
447501
}
448502
case TypeId::kBinary:
449503
case TypeId::kFixed: {
@@ -475,13 +529,10 @@ std::string Literal::ToString() const {
475529
if (str_res.has_value()) {
476530
return str_res.value();
477531
}
478-
return
479-
}
480-
case TypeId::kUuid: {
481-
return {"kDecimal and kUuid are not implemented yet"};
532+
return invalid_argument();
482533
}
483534
default: {
484-
throw IcebergError("Unknown type: " + type_->ToString());
535+
return unsupported_error();
485536
}
486537
}
487538
}
@@ -513,6 +564,9 @@ Result<Literal> LiteralCaster::CastTo(const Literal& literal,
513564

514565
// Delegate to specific cast functions based on source type
515566
switch (source_type_id) {
567+
case TypeId::kBoolean:
568+
// No casts defined for Boolean, other than to itself.
569+
break;
516570
case TypeId::kInt:
517571
return CastFromInt(literal, target_type);
518572
case TypeId::kLong:
@@ -531,12 +585,11 @@ Result<Literal> LiteralCaster::CastTo(const Literal& literal,
531585
return CastFromTimestamp(literal, target_type);
532586
case TypeId::kTimestampTz:
533587
return CastFromTimestampTz(literal, target_type);
534-
case TypeId::kBoolean:
535588
default:
536589
break;
537590
}
538591

539-
return NotSupported("Cast from {} to {} is not implemented", literal.type_->ToString(),
592+
return NotSupported("Cast from {} to {} is not supported", literal.type_->ToString(),
540593
target_type->ToString());
541594
}
542595

src/iceberg/expression/literal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class ICEBERG_EXPORT Literal {
146146
/// \return true if this literal is null, false otherwise
147147
bool IsNull() const;
148148

149-
Result<std::string> ToString() const;
149+
std::string ToString() const;
150150

151151
private:
152152
Literal(Value value, std::shared_ptr<PrimitiveType> type);

src/iceberg/transform_function.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "iceberg/expression/literal.h"
2929
#include "iceberg/type.h"
30+
#include "iceberg/util/int128.h"
3031
#include "iceberg/util/murmurhash3_internal.h"
3132
#include "iceberg/util/truncate_util.h"
3233

@@ -77,6 +78,8 @@ Result<Literal> BucketTransform::Transform(const Literal& literal) {
7778
MurmurHash3_x86_32(value.data(), value.size(), 0, &hash_value);
7879
} else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
7980
MurmurHash3_x86_32(value.data(), value.size(), 0, &hash_value);
81+
} else if constexpr (std::is_same_v<T, int128_t>) {
82+
MurmurHash3_x86_32(&value, sizeof(int128_t), 0, &hash_value);
8083
} else if constexpr (std::is_same_v<T, std::monostate> ||
8184
std::is_same_v<T, bool> || std::is_same_v<T, float> ||
8285
std::is_same_v<T, double> ||

0 commit comments

Comments
 (0)