Skip to content

Commit 4e062ea

Browse files
committed
feat: add more tests
1 parent a325c03 commit 4e062ea

File tree

4 files changed

+404
-62
lines changed

4 files changed

+404
-62
lines changed

src/iceberg/expression/decimal.cc

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <iomanip>
3434
#include <iostream>
3535
#include <limits>
36+
#include <ostream>
3637
#include <sstream>
3738
#include <string>
3839
#include <string_view>
@@ -183,7 +184,7 @@ static Status BuildFromArray(Decimal* result, const uint32_t* array, int64_t len
183184
std::array<uint64_t, 2> result_array = {0, 0};
184185
for (int64_t i = length - 2 * 2 - 1; i >= 0; i--) {
185186
if (array[i] != 0) {
186-
return Overflow("Decimal division overflow");
187+
return Invalid("Decimal division overflow");
187188
}
188189
}
189190

@@ -250,7 +251,7 @@ static inline Status DecimalDivide(const Decimal& dividend, const Decimal& divis
250251
}
251252

252253
if (divisor_length == 0) {
253-
return DivideByZero("Cannot divide by zero in DecimalDivide");
254+
return Invalid("Cannot divide by zero in DecimalDivide");
254255
}
255256

256257
if (divisor_length == 1) {
@@ -1013,9 +1014,8 @@ struct DecimalRealConversion {
10131014
const auto x = std::nearbyint(real * PowerOfTen<double>(scale));
10141015
const auto max_abs = PowerOfTen<double>(precision);
10151016
if (x <= -max_abs || x >= max_abs) {
1016-
return Overflow(
1017-
"Cannot convert {} to Decimal(precision = {}, scale = {}): overflow", real,
1018-
precision, scale);
1017+
return Invalid("Cannot convert {} to Decimal(precision = {}, scale = {}): overflow",
1018+
real, precision, scale);
10191019
}
10201020

10211021
// Extract high and low bits
@@ -1048,9 +1048,8 @@ struct DecimalRealConversion {
10481048
// overflow.
10491049
// NOTE: `limit` is allowed here as rounding can make it smaller than
10501050
// the theoretical limit (for example, 1.0e23 < 10^23).
1051-
return Overflow(
1052-
"Cannot convert {} to Decimal(precision = {}, scale = {}): overflow", real,
1053-
precision, scale);
1051+
return Invalid("Cannot convert {} to Decimal(precision = {}, scale = {}): overflow",
1052+
real, precision, scale);
10541053
}
10551054

10561055
// 2. Losslessly convert `real` to `mant * 2**k`
@@ -1140,9 +1139,8 @@ struct DecimalRealConversion {
11401139

11411140
// Rounding might have pushed `x` just above the max precision, check again
11421141
if (!x.FitsInPrecision(precision)) {
1143-
return Overflow(
1144-
"Cannot convert {} to Decimal(precision = {}, scale = {}): overflow", real,
1145-
precision, scale);
1142+
return Invalid("Cannot convert {} to Decimal(precision = {}, scale = {}): overflow",
1143+
real, precision, scale);
11461144
}
11471145
return x;
11481146
}
@@ -1346,6 +1344,11 @@ std::array<uint8_t, Decimal::kByteWidth> Decimal::ToBytes() const {
13461344
return out;
13471345
}
13481346

1347+
ICEBERG_EXPORT std::ostream& operator<<(std::ostream& os, const Decimal& decimal) {
1348+
os << decimal.ToIntegerString();
1349+
return os;
1350+
}
1351+
13491352
// Unary operators
13501353
ICEBERG_EXPORT Decimal operator-(const Decimal& operand) {
13511354
Decimal result(operand.high(), operand.low());

src/iceberg/expression/decimal.h

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

2828
#include "iceberg/iceberg_export.h"
2929
#include "iceberg/result.h"
30+
#include "iceberg/util/macros.h"
3031
#include "iceberg/util/port.h"
3132

3233
namespace iceberg {
@@ -171,6 +172,28 @@ class ICEBERG_EXPORT Decimal {
171172
/// Returns true if the number of significant digits is less or equal to `precision`.
172173
bool FitsInPrecision(int32_t precision) const;
173174

175+
/// \brief Convert to a signed integer
176+
template <typename T>
177+
requires std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t>
178+
Result<T> ToInteger() const {
179+
constexpr auto min_value = std::numeric_limits<T>::min();
180+
constexpr auto max_value = std::numeric_limits<T>::max();
181+
const auto& self = *this;
182+
if (self < min_value || self > max_value) {
183+
return Invalid("Invalid cast from Decimal to {} byte integer", sizeof(T));
184+
}
185+
return static_cast<T>(low());
186+
}
187+
188+
/// \brief Convert to a signed integer
189+
template <typename T>
190+
requires std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t>
191+
Status ToInteger(T* out) const {
192+
ICEBERG_ASSIGN_OR_RAISE(auto result, ToInteger<T>());
193+
*out = result;
194+
return {};
195+
}
196+
174197
/// \brief Convert to a floating-point number (scaled)
175198
float ToFloat(int32_t scale) const;
176199
/// \brief Convert to a floating-point number (scaled)
@@ -212,6 +235,8 @@ class ICEBERG_EXPORT Decimal {
212235
return lhs.data_ != rhs.data_;
213236
}
214237

238+
friend std::ostream& operator<<(std::ostream& os, const Decimal& decimal);
239+
215240
private:
216241
#if ICEBERG_LITTLE_ENDIAN
217242
static constexpr int32_t kHighIndex = 1;

src/iceberg/result.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ enum class ErrorKind {
3232
kAlreadyExists,
3333
kCommitStateUnknown,
3434
kDecompressError,
35-
kDivideByZero,
35+
kInvalid, // For general invalid errors
3636
kInvalidArgument,
3737
kInvalidArrowData,
3838
kInvalidExpression,
@@ -47,8 +47,6 @@ enum class ErrorKind {
4747
kNotFound,
4848
kNotImplemented,
4949
kNotSupported,
50-
kOverflow,
51-
kRescaleDataLoss,
5250
kUnknownError,
5351
};
5452

@@ -82,7 +80,7 @@ using Status = Result<void>;
8280
DEFINE_ERROR_FUNCTION(AlreadyExists)
8381
DEFINE_ERROR_FUNCTION(CommitStateUnknown)
8482
DEFINE_ERROR_FUNCTION(DecompressError)
85-
DEFINE_ERROR_FUNCTION(DivideByZero)
83+
DEFINE_ERROR_FUNCTION(Invalid)
8684
DEFINE_ERROR_FUNCTION(InvalidArgument)
8785
DEFINE_ERROR_FUNCTION(InvalidArrowData)
8886
DEFINE_ERROR_FUNCTION(InvalidExpression)
@@ -97,8 +95,6 @@ DEFINE_ERROR_FUNCTION(NotAllowed)
9795
DEFINE_ERROR_FUNCTION(NotFound)
9896
DEFINE_ERROR_FUNCTION(NotImplemented)
9997
DEFINE_ERROR_FUNCTION(NotSupported)
100-
DEFINE_ERROR_FUNCTION(Overflow)
101-
DEFINE_ERROR_FUNCTION(RescaleDataLoss)
10298
DEFINE_ERROR_FUNCTION(UnknownError)
10399

104100
#undef DEFINE_ERROR_FUNCTION

0 commit comments

Comments
 (0)