Compare commits

...

1 Commits

Author SHA1 Message Date
stephen 4cf2aba9f8
Decimal256 (#60265)
Signed-off-by: stephen <stephen5217@163.com>
2025-06-25 10:56:32 +08:00
69 changed files with 9159 additions and 172 deletions

View File

@ -20,6 +20,7 @@
#include "column/vectorized_fwd.h"
#include "storage/uint24.h"
#include "types/int256.h"
#ifdef __SSE4_2__
#include <nmmintrin.h>
@ -124,12 +125,34 @@ inline uint64_t hash_128(uint64_t seed, int128_t val) {
return seed;
}
inline uint64_t hash_256(uint64_t seed, const int256_t& val) {
uint64_t parts[4];
parts[0] = static_cast<uint64_t>(val.low);
parts[1] = static_cast<uint64_t>(val.low >> 64);
parts[2] = static_cast<uint64_t>(static_cast<uint128_t>(val.high));
parts[3] = static_cast<uint64_t>(static_cast<uint128_t>(val.high) >> 64);
uint64_t hash = seed;
for (int i = 0; i < 4; ++i) {
hash_combine(hash, parts[i]);
}
return hash;
}
template <PhmapSeed seed>
struct Hash128WithSeed {
std::size_t operator()(int128_t value) const {
return phmap_mix_with_seed<sizeof(size_t), seed>()(hash_128(seed, value));
}
};
template <PhmapSeed seed>
struct Hash256WithSeed {
std::size_t operator()(const int256_t& value) const {
return phmap_mix_with_seed<sizeof(size_t), seed>()(hash_256(seed, value));
}
};
template <typename T>
struct HashTypeTraits {
using HashFunc = StdHashWithSeed<T, PhmapSeed2>;
@ -139,6 +162,11 @@ struct HashTypeTraits<int128_t> {
using HashFunc = Hash128WithSeed<PhmapSeed2>;
};
template <>
struct HashTypeTraits<int256_t> {
using HashFunc = Hash256WithSeed<PhmapSeed2>;
};
template <LogicalType LT, PhmapSeed seed>
struct PhmapDefaultHashFunc {
std::size_t operator()(const RunTimeCppType<LT>& value) const {
@ -146,6 +174,8 @@ struct PhmapDefaultHashFunc {
if constexpr (lt_is_largeint<LT> || lt_is_decimal128<LT>) {
return Hash128WithSeed<seed>()(value);
} else if constexpr (lt_is_decimal256<LT>) {
return Hash256WithSeed<seed>()(value);
} else if constexpr (lt_is_fixedlength<LT>) {
return StdHashWithSeed<RunTimeCppType<LT>, seed>()(value);
} else if constexpr (lt_is_string<LT> || lt_is_binary<LT>) {

View File

@ -61,12 +61,13 @@ public:
: Field(id, name, get_type_info(type, precision, scale), STORAGE_AGGREGATE_NONE, nullptr, 0, false,
nullable) {}
// Non-key field of any type except for DECIMAL32, DECIMAL64, DECIMAL128, and ARRAY
// Non-key field of any type except for DECIMAL32, DECIMAL64, DECIMAL128, DECIMAL256, and ARRAY
Field(ColumnId id, std::string_view name, LogicalType type, bool nullable)
: Field(id, name, type, -1, -1, nullable) {
DCHECK(type != TYPE_DECIMAL32);
DCHECK(type != TYPE_DECIMAL64);
DCHECK(type != TYPE_DECIMAL128);
DCHECK(type != TYPE_DECIMAL256);
DCHECK(type != TYPE_ARRAY);
}

View File

@ -399,6 +399,8 @@ std::string FixedLengthColumnBase<T>::get_name() const {
return "timestamp";
} else if constexpr (IsInt128<T>) {
return "int128";
} else if constexpr (IsInt256<T>) {
return "int256";
} else if constexpr (std::is_floating_point_v<T>) {
return "float-" + std::to_string(sizeof(T));
} else {

View File

@ -41,6 +41,11 @@ constexpr bool IsInt128 = false;
template <>
inline constexpr bool IsInt128<int128_t> = true;
template <typename T>
constexpr bool IsInt256 = false;
template <>
inline constexpr bool IsInt256<int256_t> = true;
template <typename T>
constexpr bool IsSlice = false;
template <>
@ -54,7 +59,8 @@ template <>
inline constexpr bool IsDateTime<DateValue> = true;
template <typename T>
using is_starrocks_arithmetic = std::integral_constant<bool, std::is_arithmetic_v<T> || IsDecimal<T>>;
using is_starrocks_arithmetic =
std::integral_constant<bool, std::is_arithmetic_v<T> || IsDecimal<T> || std::is_same_v<T, int256_t>>;
// If isArithmeticLT is true, means this type support +,-,*,/
template <LogicalType logical_type>

View File

@ -66,6 +66,8 @@ using Int64AggHashMap = phmap::flat_hash_map<int64_t, AggDataPtr, StdHashWithSee
template <PhmapSeed seed>
using Int128AggHashMap = phmap::flat_hash_map<int128_t, AggDataPtr, Hash128WithSeed<seed>>;
template <PhmapSeed seed>
using Int256AggHashMap = phmap::flat_hash_map<int256_t, AggDataPtr, Hash256WithSeed<seed>>;
template <PhmapSeed seed>
using DateAggHashMap = phmap::flat_hash_map<DateValue, AggDataPtr, StdHashWithSeed<DateValue, seed>>;
template <PhmapSeed seed>
using TimeStampAggHashMap = phmap::flat_hash_map<TimestampValue, AggDataPtr, StdHashWithSeed<TimestampValue, seed>>;

View File

@ -63,6 +63,8 @@ using Int64AggHashSet = phmap::flat_hash_set<int64_t, StdHashWithSeed<int64_t, s
template <PhmapSeed seed>
using Int128AggHashSet = phmap::flat_hash_set<int128_t, Hash128WithSeed<seed>>;
template <PhmapSeed seed>
using Int256AggHashSet = phmap::flat_hash_set<int256_t, Hash256WithSeed<seed>>;
template <PhmapSeed seed>
using DateAggHashSet = phmap::flat_hash_set<DateValue, StdHashWithSeed<DateValue, seed>>;
template <PhmapSeed seed>
using TimeStampAggHashSet = phmap::flat_hash_set<TimestampValue, StdHashWithSeed<TimestampValue, seed>>;

View File

@ -40,6 +40,7 @@ DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_int128, Int128AggHashMapWithOneN
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_decimal32, Decimal32AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_decimal64, Decimal64AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_decimal128, Decimal128AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_decimal256, Decimal256AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_date, DateAggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_timestamp, TimeStampAggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_string, OneStringAggHashMap<PhmapSeed1>);
@ -52,6 +53,7 @@ DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_int128, NullInt128AggHashMa
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_decimal32, NullDecimal32AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_decimal64, NullDecimal64AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_decimal128, NullDecimal128AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_decimal256, NullDecimal256AggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_date, NullDateAggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_timestamp, NullTimeStampAggHashMapWithOneNumberKey<PhmapSeed1>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase1_null_string, NullOneStringAggHashMap<PhmapSeed1>);
@ -72,6 +74,7 @@ DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_int128, Int128AggHashMapWithOneN
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_decimal32, Decimal32AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_decimal64, Decimal64AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_decimal128, Decimal128AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_decimal256, Decimal256AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_date, DateAggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_timestamp, TimeStampAggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_string, OneStringAggHashMap<PhmapSeed2>);
@ -84,6 +87,7 @@ DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_int128, NullInt128AggHashMa
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_decimal32, NullDecimal32AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_decimal64, NullDecimal64AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_decimal128, NullDecimal128AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_decimal256, NullDecimal256AggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_date, NullDateAggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_timestamp, NullTimeStampAggHashMapWithOneNumberKey<PhmapSeed2>);
DEFINE_MAP_TYPE(AggHashMapVariant::Type::phase2_null_string, NullOneStringAggHashMap<PhmapSeed2>);
@ -114,6 +118,7 @@ DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_int128, Int128AggHashSetOfOneNum
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_decimal32, Decimal32AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_decimal64, Decimal64AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_decimal128, Decimal128AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_decimal256, Decimal256AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_date, DateAggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_timestamp, TimeStampAggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_string, OneStringAggHashSet<PhmapSeed1>);
@ -126,6 +131,7 @@ DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_int128, NullInt128AggHashSe
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_decimal32, NullDecimal32AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_decimal64, NullDecimal64AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_decimal128, NullDecimal128AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_decimal256, NullDecimal256AggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_date, NullDateAggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_timestamp, NullTimeStampAggHashSetOfOneNumberKey<PhmapSeed1>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase1_null_string, NullOneStringAggHashSet<PhmapSeed1>);
@ -144,6 +150,7 @@ DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_int128, Int128AggHashSetOfOneNum
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_decimal32, Decimal32AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_decimal64, Decimal64AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_decimal128, Decimal128AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_decimal256, Decimal256AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_date, DateAggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_timestamp, TimeStampAggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_string, OneStringAggHashSet<PhmapSeed2>);
@ -156,6 +163,7 @@ DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_int128, NullInt128AggHashSe
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_decimal32, NullDecimal32AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_decimal64, NullDecimal64AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_decimal128, NullDecimal128AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_decimal256, NullDecimal256AggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_date, NullDateAggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_timestamp, NullTimeStampAggHashSetOfOneNumberKey<PhmapSeed2>);
DEFINE_SET_TYPE(AggHashSetVariant::Type::phase2_null_string, NullOneStringAggHashSet<PhmapSeed2>);
@ -370,6 +378,7 @@ HashVariantResolver<HashVariantType>::HashVariantResolver() {
ADD_VARIANT_PHASE1_TYPE(TYPE_DATE, date);
ADD_VARIANT_PHASE1_TYPE(TYPE_DATETIME, timestamp);
ADD_VARIANT_PHASE1_TYPE(TYPE_DECIMAL128, decimal128);
ADD_VARIANT_PHASE1_TYPE(TYPE_DECIMAL256, decimal256);
ADD_VARIANT_PHASE1_TYPE(TYPE_LARGEINT, int128);
ADD_VARIANT_PHASE1_TYPE(TYPE_CHAR, string);
ADD_VARIANT_PHASE1_TYPE(TYPE_VARCHAR, string);

View File

@ -42,6 +42,7 @@ enum AggrPhase { AggrPhase1, AggrPhase2 };
M(phase1_decimal32) \
M(phase1_decimal64) \
M(phase1_decimal128) \
M(phase1_decimal256) \
M(phase1_date) \
M(phase1_timestamp) \
M(phase1_string) \
@ -55,6 +56,7 @@ enum AggrPhase { AggrPhase1, AggrPhase2 };
M(phase1_null_decimal32) \
M(phase1_null_decimal64) \
M(phase1_null_decimal128) \
M(phase1_null_decimal256) \
M(phase1_null_date) \
M(phase1_null_timestamp) \
M(phase1_null_string) \
@ -72,6 +74,7 @@ enum AggrPhase { AggrPhase1, AggrPhase2 };
M(phase2_decimal32) \
M(phase2_decimal64) \
M(phase2_decimal128) \
M(phase2_decimal256) \
M(phase2_date) \
M(phase2_timestamp) \
M(phase2_string) \
@ -85,6 +88,7 @@ enum AggrPhase { AggrPhase1, AggrPhase2 };
M(phase2_null_decimal32) \
M(phase2_null_decimal64) \
M(phase2_null_decimal128) \
M(phase2_null_decimal256) \
M(phase2_null_date) \
M(phase2_null_timestamp) \
M(phase2_null_string) \
@ -122,6 +126,8 @@ using Decimal64AggHashMapWithOneNumberKey = AggHashMapWithOneNumberKey<TYPE_DECI
template <PhmapSeed seed>
using Decimal128AggHashMapWithOneNumberKey = AggHashMapWithOneNumberKey<TYPE_DECIMAL128, Int128AggHashMap<seed>>;
template <PhmapSeed seed>
using Decimal256AggHashMapWithOneNumberKey = AggHashMapWithOneNumberKey<TYPE_DECIMAL256, Int256AggHashMap<seed>>;
template <PhmapSeed seed>
using DateAggHashMapWithOneNumberKey = AggHashMapWithOneNumberKey<TYPE_DATE, DateAggHashMap<seed>>;
template <PhmapSeed seed>
using TimeStampAggHashMapWithOneNumberKey = AggHashMapWithOneNumberKey<TYPE_DATETIME, TimeStampAggHashMap<seed>>;
@ -147,6 +153,9 @@ using NullDecimal64AggHashMapWithOneNumberKey =
template <PhmapSeed seed>
using NullDecimal128AggHashMapWithOneNumberKey =
AggHashMapWithOneNullableNumberKey<TYPE_DECIMAL128, Int128AggHashMap<seed>>;
template <PhmapSeed seed>
using NullDecimal256AggHashMapWithOneNumberKey =
AggHashMapWithOneNullableNumberKey<TYPE_DECIMAL256, Int256AggHashMap<seed>>;
template <PhmapSeed seed>
using NullDateAggHashMapWithOneNumberKey = AggHashMapWithOneNullableNumberKey<TYPE_DATE, DateAggHashMap<seed>>;
@ -198,6 +207,8 @@ template <PhmapSeed seed>
using Decimal64AggHashSetOfOneNumberKey = AggHashSetOfOneNumberKey<TYPE_DECIMAL64, Int64AggHashSet<seed>>;
template <PhmapSeed seed>
using Decimal128AggHashSetOfOneNumberKey = AggHashSetOfOneNumberKey<TYPE_DECIMAL128, Int128AggHashSet<seed>>;
template <PhmapSeed seed>
using Decimal256AggHashSetOfOneNumberKey = AggHashSetOfOneNumberKey<TYPE_DECIMAL256, Int256AggHashSet<seed>>;
template <PhmapSeed seed>
using DateAggHashSetOfOneNumberKey = AggHashSetOfOneNumberKey<TYPE_DATE, DateAggHashSet<seed>>;
@ -225,6 +236,9 @@ template <PhmapSeed seed>
using NullDecimal128AggHashSetOfOneNumberKey =
AggHashSetOfOneNullableNumberKey<TYPE_DECIMAL128, Int128AggHashSet<seed>>;
template <PhmapSeed seed>
using NullDecimal256AggHashSetOfOneNumberKey =
AggHashSetOfOneNullableNumberKey<TYPE_DECIMAL256, Int256AggHashSet<seed>>;
template <PhmapSeed seed>
using NullDateAggHashSetOfOneNumberKey = AggHashSetOfOneNullableNumberKey<TYPE_DATE, DateAggHashSet<seed>>;
template <PhmapSeed seed>
using NullTimeStampAggHashSetOfOneNumberKey =
@ -303,6 +317,7 @@ using AggHashMapWithKeyPtr = std::variant<
std::unique_ptr<Decimal32AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<Decimal64AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<Decimal128AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<Decimal256AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<DateAggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<TimeStampAggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<OneStringAggHashMap<PhmapSeed1>>,
@ -315,6 +330,7 @@ using AggHashMapWithKeyPtr = std::variant<
std::unique_ptr<NullDecimal32AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDecimal64AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDecimal128AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDecimal256AggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDateAggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullTimeStampAggHashMapWithOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullOneStringAggHashMap<PhmapSeed1>>, std::unique_ptr<SerializedKeyAggHashMap<PhmapSeed1>>,
@ -334,6 +350,7 @@ using AggHashMapWithKeyPtr = std::variant<
std::unique_ptr<Decimal32AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<Decimal64AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<Decimal128AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<Decimal256AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<DateAggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<TimeStampAggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<OneStringAggHashMap<PhmapSeed2>>,
@ -346,6 +363,7 @@ using AggHashMapWithKeyPtr = std::variant<
std::unique_ptr<NullDecimal32AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDecimal64AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDecimal128AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDecimal256AggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDateAggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullTimeStampAggHashMapWithOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullOneStringAggHashMap<PhmapSeed2>>, std::unique_ptr<SerializedKeyAggHashMap<PhmapSeed2>>,
@ -367,6 +385,7 @@ using AggHashSetWithKeyPtr = std::variant<
std::unique_ptr<Decimal32AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<Decimal64AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<Decimal128AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<Decimal256AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<DateAggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<TimeStampAggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<OneStringAggHashSet<PhmapSeed1>>,
@ -379,6 +398,7 @@ using AggHashSetWithKeyPtr = std::variant<
std::unique_ptr<NullDecimal32AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDecimal64AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDecimal128AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDecimal256AggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullDateAggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullTimeStampAggHashSetOfOneNumberKey<PhmapSeed1>>,
std::unique_ptr<NullOneStringAggHashSet<PhmapSeed1>>, std::unique_ptr<SerializedKeyAggHashSet<PhmapSeed1>>,
@ -395,6 +415,7 @@ using AggHashSetWithKeyPtr = std::variant<
std::unique_ptr<Decimal32AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<Decimal64AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<Decimal128AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<Decimal256AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<DateAggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<TimeStampAggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<OneStringAggHashSet<PhmapSeed2>>,
@ -407,6 +428,7 @@ using AggHashSetWithKeyPtr = std::variant<
std::unique_ptr<NullDecimal32AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDecimal64AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDecimal128AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDecimal256AggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullDateAggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullTimeStampAggHashSetOfOneNumberKey<PhmapSeed2>>,
std::unique_ptr<NullOneStringAggHashSet<PhmapSeed2>>, std::unique_ptr<SerializedKeyAggHashSet<PhmapSeed2>>,
@ -432,6 +454,7 @@ struct AggHashMapVariant {
phase1_decimal32,
phase1_decimal64,
phase1_decimal128,
phase1_decimal256,
phase1_date,
phase1_timestamp,
phase1_string,
@ -444,6 +467,7 @@ struct AggHashMapVariant {
phase1_null_decimal32,
phase1_null_decimal64,
phase1_null_decimal128,
phase1_null_decimal256,
phase1_null_date,
phase1_null_timestamp,
phase1_null_string,
@ -466,6 +490,7 @@ struct AggHashMapVariant {
phase2_decimal32,
phase2_decimal64,
phase2_decimal128,
phase2_decimal256,
phase2_date,
phase2_timestamp,
phase2_string,
@ -478,6 +503,7 @@ struct AggHashMapVariant {
phase2_null_decimal32,
phase2_null_decimal64,
phase2_null_decimal128,
phase2_null_decimal256,
phase2_null_date,
phase2_null_timestamp,
phase2_null_string,
@ -542,6 +568,7 @@ struct AggHashSetVariant {
phase1_decimal32,
phase1_decimal64,
phase1_decimal128,
phase1_decimal256,
phase1_date,
phase1_timestamp,
phase1_string,
@ -554,6 +581,7 @@ struct AggHashSetVariant {
phase1_null_decimal32,
phase1_null_decimal64,
phase1_null_decimal128,
phase1_null_decimal256,
phase1_null_date,
phase1_null_timestamp,
phase1_null_string,
@ -572,6 +600,7 @@ struct AggHashSetVariant {
phase2_decimal32,
phase2_decimal64,
phase2_decimal128,
phase2_decimal256,
phase2_date,
phase2_timestamp,
phase2_string,
@ -584,6 +613,7 @@ struct AggHashSetVariant {
phase2_null_decimal32,
phase2_null_decimal64,
phase2_null_decimal128,
phase2_null_decimal256,
phase2_null_date,
phase2_null_timestamp,
phase2_null_string,

View File

@ -62,6 +62,15 @@ inline size_t difference<Slice>(const Slice& low, const Slice& high) {
return 0;
}
template <>
inline size_t difference<int256_t>(const int256_t& low, const int256_t& high) {
DCHECK_LE(low, high);
if (high - low > static_cast<int256_t>(SIZE_MAX)) {
return SIZE_MAX;
}
return static_cast<size_t>(high - low);
}
template <>
inline size_t difference<DateValue>(const DateValue& low, const DateValue& high) {
DCHECK_LE(low, high);
@ -140,6 +149,14 @@ inline std::string cast_to_string(T value, [[maybe_unused]] LogicalType lt, [[ma
return DecimalV3Cast::to_string<CppType>(*reinterpret_cast<CppType*>(&value), precision, scale);
}
}
case TYPE_DECIMAL256: {
using CppType = RunTimeCppType<TYPE_DECIMAL256>;
if constexpr (use_static_cast) {
return DecimalV3Cast::to_string<CppType>(static_cast<CppType>(value), precision, scale);
} else {
return DecimalV3Cast::to_string<CppType>(*reinterpret_cast<CppType*>(&value), precision, scale);
}
}
default:
return cast_to_string<T>(value);
}

View File

@ -38,6 +38,11 @@ struct AvgResultTrait<LT, DecimalLTGuard<LT>> {
static const LogicalType value = TYPE_DECIMAL128;
};
template <>
struct AvgResultTrait<TYPE_DECIMAL256, DecimalLTGuard<TYPE_DECIMAL256>> {
static const LogicalType value = TYPE_DECIMAL256;
};
template <LogicalType LT>
inline constexpr LogicalType AvgResultLT = AvgResultTrait<LT>::value;
@ -230,7 +235,8 @@ public:
} else if constexpr (lt_is_arithmetic<LT>) {
result = this->data(state).sum / this->data(state).count;
} else if constexpr (lt_is_decimal<LT>) {
static_assert(lt_is_decimal128<ResultLT>, "Result type of avg on decimal32/64/128 is decimal 128");
static_assert(lt_is_decimal128<ResultLT> || lt_is_decimal256<ResultLT>,
"Result type of avg on decimal32/64/128/256 is decimal 128 or 256");
auto sum = ResultType(this->data(state).sum);
auto count = ResultType(this->data(state).count);
result = decimal_div_integer<ResultType>(sum, count, ctx->get_arg_type(0)->scale);
@ -256,7 +262,8 @@ public:
} else if constexpr (lt_is_arithmetic<LT>) {
result = this->data(state).sum / this->data(state).count;
} else if constexpr (lt_is_decimal<LT>) {
static_assert(lt_is_decimal128<ResultLT>, "Result type of avg on decimal32/64/128 is decimal 128");
static_assert(lt_is_decimal128<ResultLT> || lt_is_decimal256<ResultLT>,
"Result type of avg on decimal32/64/128/256 is decimal 128 or 256");
auto sum = ResultType(this->data(state).sum);
auto count = ResultType(this->data(state).count);
result = decimal_div_integer<ResultType>(sum, count, ctx->get_arg_type(0)->scale);
@ -270,8 +277,9 @@ public:
std::string get_name() const override { return "avg"; }
};
template <LogicalType LT, typename = DecimalLTGuard<LT>>
using DecimalAvgAggregateFunction =
AvgAggregateFunction<LT, RunTimeCppType<LT>, TYPE_DECIMAL128, RunTimeCppType<TYPE_DECIMAL128>>;
AvgAggregateFunction<LT, RunTimeCppType<LT>, (LT == TYPE_DECIMAL256) ? TYPE_DECIMAL256 : TYPE_DECIMAL128>;
} // namespace starrocks

View File

@ -179,8 +179,8 @@ public:
int64_t count = 1;
for (size_t i = 0; i < chunk_size; ++i) {
meanX = src_column0->get_data()[i];
meanY = src_column1->get_data()[i];
meanX = static_cast<double>(src_column0->get_data()[i]);
meanY = static_cast<double>(src_column1->get_data()[i]);
memcpy(bytes.data() + old_size, &meanX, sizeof(double));
memcpy(bytes.data() + old_size + sizeof(double), &meanY, sizeof(double));
memcpy(bytes.data() + old_size + sizeof(double) * 2, &c2, sizeof(double));

View File

@ -534,7 +534,8 @@ using DistinctAggregateFunctionV2 =
template <LogicalType LT, AggDistinctType DistinctType, typename T = RunTimeCppType<LT>>
using DecimalDistinctAggregateFunction =
TDistinctAggregateFunction<LT, TYPE_DECIMAL128, DistinctAggregateStateV2, DistinctType, T>;
TDistinctAggregateFunction<LT, lt_is_decimal256<LT> ? TYPE_DECIMAL256 : TYPE_DECIMAL128,
DistinctAggregateStateV2, DistinctType, T>;
// now we only support String
struct DictMergeState : DistinctAggregateStateV2<TYPE_VARCHAR, SumResultLT<TYPE_VARCHAR>> {

View File

@ -120,7 +120,7 @@ static const AggregateFunction* get_function(const std::string& name, LogicalTyp
}
auto is_decimal_type = [](LogicalType lt) {
return lt == TYPE_DECIMAL32 || lt == TYPE_DECIMAL64 || lt == TYPE_DECIMAL128;
return lt == TYPE_DECIMAL32 || lt == TYPE_DECIMAL64 || lt == TYPE_DECIMAL128 || lt == TYPE_DECIMAL256;
};
if (func_version > 2 && is_decimal_type(arg_type)) {
if (name == "sum") {

View File

@ -70,10 +70,11 @@ public:
void register_hypothesis_testing();
const std::vector<LogicalType>& aggregate_types() const {
const static std::vector<LogicalType> kTypes{
TYPE_BOOLEAN, TYPE_TINYINT, TYPE_SMALLINT, TYPE_INT, TYPE_BIGINT, TYPE_LARGEINT,
TYPE_FLOAT, TYPE_DOUBLE, TYPE_VARCHAR, TYPE_CHAR, TYPE_DATE, TYPE_DATETIME,
TYPE_DECIMALV2, TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128, TYPE_HLL, TYPE_OBJECT};
const static std::vector<LogicalType> kTypes{TYPE_BOOLEAN, TYPE_TINYINT, TYPE_SMALLINT, TYPE_INT,
TYPE_BIGINT, TYPE_LARGEINT, TYPE_FLOAT, TYPE_DOUBLE,
TYPE_VARCHAR, TYPE_CHAR, TYPE_DATE, TYPE_DATETIME,
TYPE_DECIMALV2, TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128,
TYPE_DECIMAL256, TYPE_HLL, TYPE_OBJECT};
return kTypes;
}
@ -221,7 +222,7 @@ public:
template <LogicalType ArgLT, LogicalType ResultLT, bool IsWindowFunc, bool IsNull>
std::enable_if_t<isArithmeticLT<ArgLT>, AggregateFunctionPtr> create_decimal_function(std::string& name) {
static_assert(lt_is_decimal128<ResultLT>);
static_assert(lt_is_decimal128<ResultLT> || lt_is_decimal256<ResultLT>);
if constexpr (IsNull) {
using ResultType = RunTimeCppType<ResultLT>;
if (name == "decimal_avg") {

View File

@ -133,15 +133,18 @@ struct MapAggDispatcher {
void AggregateFuncResolver::register_avg() {
for (auto type : aggregate_types()) {
type_dispatch_all(type, AvgDispatcher(), this);
type_dispatch_all(type, ArrayAggDispatcher(), this);
type_dispatch_all(type, ArrayAggDistinctDispatcher(), this);
type_dispatch_all(type, ArrayUniqueAggDispatcher(), this);
type_dispatch_all(type, MapAggDispatcher(), this);
if (type != TYPE_DECIMAL256) {
type_dispatch_all(type, ArrayAggDispatcher(), this);
type_dispatch_all(type, ArrayAggDistinctDispatcher(), this);
type_dispatch_all(type, ArrayUniqueAggDispatcher(), this);
type_dispatch_all(type, MapAggDispatcher(), this);
}
}
type_dispatch_all(TYPE_JSON, ArrayAggDispatcher(), this);
add_decimal_mapping<TYPE_DECIMAL32, TYPE_DECIMAL128, true>("decimal_avg");
add_decimal_mapping<TYPE_DECIMAL64, TYPE_DECIMAL128, true>("decimal_avg");
add_decimal_mapping<TYPE_DECIMAL128, TYPE_DECIMAL128, true>("decimal_avg");
add_decimal_mapping<TYPE_DECIMAL256, TYPE_DECIMAL256, true>("decimal_avg");
}
} // namespace starrocks

View File

@ -87,6 +87,7 @@ void AggregateFuncResolver::register_others() {
add_decimal_mapping<TYPE_DECIMAL32, TYPE_DECIMAL128>("decimal_multi_distinct_sum");
add_decimal_mapping<TYPE_DECIMAL64, TYPE_DECIMAL128>("decimal_multi_distinct_sum");
add_decimal_mapping<TYPE_DECIMAL128, TYPE_DECIMAL128>("decimal_multi_distinct_sum");
add_decimal_mapping<TYPE_DECIMAL256, TYPE_DECIMAL256>("decimal_multi_distinct_sum");
// This first type is the 4th type input of windowfunnel.
// And the 1st type is BigInt, 2nd is datetime, 3rd is mode(default 0).

View File

@ -24,8 +24,10 @@ namespace starrocks {
struct SumDispatcher {
template <LogicalType lt>
void operator()(AggregateFuncResolver* resolver) {
if constexpr (lt_is_decimal<lt>) {
if constexpr (lt_is_decimal<lt> && !lt_is_decimal256<lt>) {
resolver->add_decimal_mapping<lt, TYPE_DECIMAL128, true>("decimal_sum");
} else if constexpr (lt_is_decimal256<lt>) {
resolver->add_decimal_mapping<lt, TYPE_DECIMAL256, true>("decimal_sum");
} else if constexpr (lt_is_numeric<lt> || lt_is_decimalv2<lt>) {
using SumState = SumAggregateState<RunTimeCppType<SumResultLT<lt>>>;
resolver->add_aggregate_mapping<lt, SumResultLT<lt>, SumState>(

View File

@ -24,7 +24,7 @@ namespace starrocks {
struct StdDispatcher {
template <LogicalType lt>
void operator()(AggregateFuncResolver* resolver) {
if constexpr (lt_is_numeric<lt>) {
if constexpr (lt_is_numeric<lt> && lt != TYPE_DECIMAL256) {
using VarState = DevFromAveAggregateState<RunTimeCppType<DevFromAveResultLT<lt>>>;
resolver->add_aggregate_mapping<lt, DevFromAveResultLT<lt>, VarState>(
"variance", true, AggregateFactory::MakeVarianceAggregateFunction<lt, false>());
@ -56,7 +56,7 @@ struct StdDispatcher {
struct CorVarDispatcher {
template <LogicalType lt>
void operator()(AggregateFuncResolver* resolver) {
if constexpr (lt_is_numeric<lt>) {
if constexpr (lt_is_numeric<lt> && lt != TYPE_DECIMAL256) {
using VarState = CovarianceCorelationAggregateState<false>;
resolver->add_aggregate_mapping_variadic<lt, TYPE_DOUBLE, VarState>(
"covar_pop", true, AggregateFactory::MakeCovarianceAggregateFunction<lt, false>());

View File

@ -177,6 +177,5 @@ public:
template <LogicalType LT, typename = DecimalLTGuard<LT>>
using DecimalSumAggregateFunction =
SumAggregateFunction<LT, RunTimeCppType<LT>, TYPE_DECIMAL128, RunTimeCppType<TYPE_DECIMAL128>>;
SumAggregateFunction<LT, RunTimeCppType<LT>, lt_is_decimal256<LT> ? TYPE_DECIMAL256 : TYPE_DECIMAL128>;
} // namespace starrocks

View File

@ -486,10 +486,11 @@ public:
#define CASE_DECIMAL_TYPE(OP) CASE_TYPE(TYPE_DECIMALV2, OP);
#define CASE_DECIMAL_V3_TYPE(OP) \
CASE_TYPE(TYPE_DECIMAL32, OP) \
CASE_TYPE(TYPE_DECIMAL64, OP) \
CASE_TYPE(TYPE_DECIMAL128, OP)
#define CASE_DECIMAL_V3_TYPE(OP) \
CASE_TYPE(TYPE_DECIMAL32, OP) \
CASE_TYPE(TYPE_DECIMAL64, OP) \
CASE_TYPE(TYPE_DECIMAL128, OP) \
CASE_TYPE(TYPE_DECIMAL256, OP)
#define SWITCH_INT_TYPE(OP) \
switch (resultType) { \

View File

@ -408,6 +408,10 @@ static inline std::tuple<int, int, int> compute_decimal_result_type(int lhs_scal
DCHECK(scale <= max_precision);
} else if constexpr (is_div_op<Op>) {
precision = decimal_precision_limit<int128_t>;
if (std::is_same_v<int256_t, T>) {
precision = decimal_precision_limit<int256_t>;
}
if (lhs_scale <= 6) {
scale = lhs_scale + 6;
} else if (lhs_scale <= 12) {

View File

@ -676,6 +676,7 @@ private:
CASE_WHEN_RESULT_TYPE(TYPE_DECIMAL32, RESULT_TYPE); \
CASE_WHEN_RESULT_TYPE(TYPE_DECIMAL64, RESULT_TYPE); \
CASE_WHEN_RESULT_TYPE(TYPE_DECIMAL128, RESULT_TYPE); \
CASE_WHEN_RESULT_TYPE(TYPE_DECIMAL256, RESULT_TYPE); \
CASE_WHEN_RESULT_TYPE(TYPE_JSON, RESULT_TYPE); \
CASE_WHEN_RESULT_TYPE(TYPE_ARRAY, RESULT_TYPE); \
CASE_WHEN_RESULT_TYPE(TYPE_MAP, RESULT_TYPE); \

View File

@ -1477,6 +1477,7 @@ private:
CASE_FROM_TYPE(TYPE_DECIMAL32, TO_TYPE, ALLOWTHROWEXCEPTION); \
CASE_FROM_TYPE(TYPE_DECIMAL64, TO_TYPE, ALLOWTHROWEXCEPTION); \
CASE_FROM_TYPE(TYPE_DECIMAL128, TO_TYPE, ALLOWTHROWEXCEPTION); \
CASE_FROM_TYPE(TYPE_DECIMAL256, TO_TYPE, ALLOWTHROWEXCEPTION); \
default: \
LOG(WARNING) << "Not support cast from type: " << type_to_string(from_type) \
<< " to type: " << type_to_string(to_type); \
@ -1683,6 +1684,7 @@ Expr* VectorizedCastExprFactory::create_primitive_cast(ObjectPool* pool, const T
CASE_TO_STRING_FROM(TYPE_DECIMAL32, allow_throw_exception);
CASE_TO_STRING_FROM(TYPE_DECIMAL64, allow_throw_exception);
CASE_TO_STRING_FROM(TYPE_DECIMAL128, allow_throw_exception);
CASE_TO_STRING_FROM(TYPE_DECIMAL256, allow_throw_exception);
CASE_TO_STRING_FROM(TYPE_JSON, allow_throw_exception);
CASE_TO_STRING_FROM(TYPE_VARBINARY, allow_throw_exception);
default:
@ -1758,6 +1760,7 @@ Expr* VectorizedCastExprFactory::create_primitive_cast(ObjectPool* pool, const T
CASE_TO_TYPE(TYPE_DECIMAL32, allow_throw_exception);
CASE_TO_TYPE(TYPE_DECIMAL64, allow_throw_exception);
CASE_TO_TYPE(TYPE_DECIMAL128, allow_throw_exception);
CASE_TO_TYPE(TYPE_DECIMAL256, allow_throw_exception);
default:
LOG(WARNING) << "Not support cast " << type_to_string(from_type) << " to " << type_to_string(to_type);
return nullptr;

View File

@ -291,6 +291,9 @@ struct CastToString {
} else if constexpr (IsInt128<Type>) {
// int128_t
return LargeIntValue::to_string(v);
} else if constexpr (IsInt256<Type>) {
// int256_t
return v.to_string();
} else {
// int8_t ~ int64_t, boolean
return SimpleItoa(v);

View File

@ -513,7 +513,8 @@ private:
CASE_TYPE(TYPE_JSON, CLASS); \
CASE_TYPE(TYPE_DECIMAL32, CLASS); \
CASE_TYPE(TYPE_DECIMAL64, CLASS); \
CASE_TYPE(TYPE_DECIMAL128, CLASS);
CASE_TYPE(TYPE_DECIMAL128, CLASS); \
CASE_TYPE(TYPE_DECIMAL256, CLASS);
Expr* VectorizedConditionExprFactory::create_if_null_expr(const starrocks::TExprNode& node) {
LogicalType resultType = TypeDescriptor::from_thrift(node.type).type;

View File

@ -265,6 +265,7 @@ DEFINE_MATH_UNARY_FN_CAST_WITH_IMPL(abs_tinyint, TYPE_TINYINT, TYPE_SMALLINT, st
DEFINE_MATH_UNARY_FN_WITH_IMPL(abs_decimal32, TYPE_DECIMAL32, TYPE_DECIMAL32, std::abs);
DEFINE_MATH_UNARY_FN_WITH_IMPL(abs_decimal64, TYPE_DECIMAL64, TYPE_DECIMAL64, std::abs);
DEFINE_MATH_UNARY_FN_WITH_IMPL(abs_decimal128, TYPE_DECIMAL128, TYPE_DECIMAL128, std::abs);
DEFINE_MATH_UNARY_FN_WITH_IMPL(abs_decimal256, TYPE_DECIMAL256, TYPE_DECIMAL256, std::abs);
// degrees
DEFINE_UNARY_FN_WITH_IMPL(abs_decimalv2valImpl, v) {

View File

@ -110,6 +110,8 @@ public:
DEFINE_VECTORIZED_FN(abs_decimal32);
DEFINE_VECTORIZED_FN(abs_decimal64);
DEFINE_VECTORIZED_FN(abs_decimal128);
DEFINE_VECTORIZED_FN(abs_decimal256);
/**
* @param columns: [DoubleColumn]
* @return DoubleColumn

View File

@ -56,5 +56,6 @@ bool DecimalV3Converter<T>::read_quoted_string(Column* column, const Slice& s, c
template class DecimalV3Converter<int32_t>;
template class DecimalV3Converter<int64_t>;
template class DecimalV3Converter<int128_t>;
template class DecimalV3Converter<int256_t>;
} // namespace starrocks::csv

View File

@ -33,7 +33,8 @@ namespace starrocks {
TYPE_GUARD(Decimal32Guard, is_decimal32, int32_t)
TYPE_GUARD(Decimal64Guard, is_decimal64, int64_t)
TYPE_GUARD(Decimal128Guard, is_decimal128, int128_t)
TYPE_GUARD(DecimalGuard, is_decimal, int32_t, int64_t, int128_t)
TYPE_GUARD(Decimal256Guard, is_decimal256, int256_t)
TYPE_GUARD(DecimalGuard, is_decimal, int32_t, int64_t, int128_t, int256_t)
template <typename ST>
struct unsigned_type {
@ -226,7 +227,7 @@ public:
// (https://www.felixcloutier.com/x86/cvttsd2si)
return (*dec_value == float_lower_overflow_indicator<To>) ||
(*dec_value == float_upper_overflow_indicator<To>);
} else if constexpr (is_decimal128<To>) {
} else if constexpr (is_decimal128<To> || is_decimal256<To>) {
// std::abs(value)<1.0 -> 0: Acceptable
// std::abs(value)>=1.0 -> 0 or different sign: Overflow!!
return std::abs(value) >= From(1) && (*dec_value == To(0) || ((value < From(0)) ^ (*dec_value < To(0))));

View File

@ -42,6 +42,12 @@ inline bool int128_add_overflow(int128_t a, int128_t b, int128_t* c) {
return ((a < 0) == (b < 0)) && ((*c < 0) != (a < 0));
}
template <>
inline bool add_overflow(int256_t a, int256_t b, int256_t* c) {
*c = a + b;
return ((a < 0) == (b < 0)) && ((*c < 0) != (a < 0));
}
template <>
inline bool add_overflow(int128_t a, int128_t b, int128_t* c) {
#if defined(__x86_64__) && defined(__GNUC__)
@ -74,6 +80,12 @@ inline bool int128_sub_overflow(int128_t a, int128_t b, int128_t* c) {
return ((a < 0) == (0 < b)) && ((*c < 0) != (a < 0));
}
template <>
inline bool sub_overflow(int256_t a, int256_t b, int256_t* c) {
*c = a - b;
return ((a < 0) == (0 < b)) && ((*c < 0) != (a < 0));
}
template <>
inline bool sub_overflow(int128_t a, int128_t b, int128_t* c) {
#if defined(__x86_64__) && defined(__GNUC__)
@ -125,4 +137,92 @@ inline bool mul_overflow(int128_t a, int128_t b, int128_t* c) {
#endif
}
inline int count_bits(const int256_t& x) noexcept {
if (x == 0) return 0;
for (int shift = 192; shift >= 0; shift -= 64) {
uint64_t segment = static_cast<uint64_t>(x >> shift);
if (segment != 0) {
return shift + 64 - __builtin_clzll(segment);
}
}
return 0;
}
template <>
inline bool mul_overflow(const int256_t a, const int256_t b, int256_t* c) {
if (a == 0 || b == 0) {
*c = int256_t(0);
return false;
}
if (a == int256_t(1)) {
*c = b;
return false;
}
if (b == int256_t(1)) {
*c = a;
return false;
}
if (a == int256_t(-1)) {
if (b == INT256_MIN) return true;
*c = -b;
return false;
}
if (b == int256_t(-1)) {
if (a == INT256_MIN) return true;
*c = -a;
return false;
}
if (a == INT256_MIN || b == INT256_MIN) {
return true;
}
if (a == INT256_MAX || b == INT256_MAX) {
return true;
}
const bool negative = (a < 0) ^ (b < 0);
const int256_t abs_a = (a.high < 0) ? -a : a;
const int256_t abs_b = (b.high < 0) ? -b : b;
const int abs_a_bits = count_bits(abs_a);
const int abs_b_bits = count_bits(abs_b);
if (abs_a_bits + abs_b_bits <= 255) {
*c = a * b;
return false;
}
if (abs_a_bits + abs_b_bits > 256) {
if (negative) {
if (abs_a_bits + abs_b_bits == 257) {
const int256_t product_abs = abs_a * abs_b;
if (product_abs == INT256_MIN) {
*c = INT256_MIN;
return false;
}
}
return true;
} else {
return true;
}
}
const int256_t& larger = (abs_a >= abs_b) ? abs_a : abs_b;
const int256_t& smaller = (abs_a >= abs_b) ? abs_b : abs_a;
const int256_t quotient = INT256_MAX / smaller;
if (larger > quotient) {
return true;
}
const int256_t result = abs_a * abs_b;
*c = negative ? -result : result;
return false;
}
} // namespace starrocks

View File

@ -645,11 +645,11 @@ ColumnPredicate* new_column_in_predicate_generic(const TypeInfoPtr& type_info, C
SetType values = predicate_internal::strings_to_decimal_set<TYPE_DECIMAL128>(scale, strs);
return new ColumnInPredicate<TYPE_DECIMAL128, SetType>(type_info, id, std::move(values));
}
// TODO(stephen): implement decimal256 and int256
case TYPE_DECIMAL256:
return nullptr;
case TYPE_INT256:
return nullptr;
case TYPE_DECIMAL256: {
using SetType = Set<CppTypeTraits<TYPE_DECIMAL256>::CppType, (Args)...>;
SetType values = predicate_internal::strings_to_decimal_set<TYPE_DECIMAL256>(scale, strs);
return new ColumnInPredicate<TYPE_DECIMAL256, SetType>(type_info, id, std::move(values));
}
case TYPE_CHAR:
return new BinaryColumnInPredicate<TYPE_CHAR>(type_info, id, strs);
case TYPE_VARCHAR:
@ -704,6 +704,7 @@ ColumnPredicate* new_column_in_predicate_generic(const TypeInfoPtr& type_info, C
case TYPE_BINARY:
case TYPE_VARBINARY:
case TYPE_MAX_VALUE:
case TYPE_INT256:
return nullptr;
// No default to ensure newly added enumerator will be handled.
}

View File

@ -359,10 +359,12 @@ ColumnPredicate* new_column_not_in_predicate(const TypeInfoPtr& type_info, Colum
SetType values = predicate_internal::strings_to_decimal_set<TYPE_DECIMAL128>(scale, strs);
return new ColumnNotInPredicate<TYPE_DECIMAL128>(type_info, id, std::move(values));
}
// TODO(stephen): implement it later
case TYPE_DECIMAL256:
case TYPE_INT256:
return nullptr;
case TYPE_DECIMAL256: {
const auto scale = type_info->scale();
using SetType = ItemHashSet<CppTypeTraits<TYPE_DECIMAL256>::CppType>;
SetType values = predicate_internal::strings_to_decimal_set<TYPE_DECIMAL256>(scale, strs);
return new ColumnNotInPredicate<TYPE_DECIMAL256>(type_info, id, std::move(values));
}
case TYPE_CHAR:
return new BinaryColumnNotInPredicate<TYPE_CHAR>(type_info, id, strs);
case TYPE_VARCHAR:
@ -399,6 +401,7 @@ ColumnPredicate* new_column_not_in_predicate(const TypeInfoPtr& type_info, Colum
case TYPE_BINARY:
case TYPE_MAX_VALUE:
case TYPE_VARBINARY:
case TYPE_INT256:
return nullptr;
// No default to ensure newly added enumerator will be handled.
}

View File

@ -138,10 +138,13 @@ static ColumnPredicate* new_column_predicate(const TypeInfoPtr& type_info, Colum
DCHECK(st.ok());
return new Predicate<TYPE_DECIMAL128>(type_info, id, value);
}
// TODO(stephen): implement it later
case TYPE_DECIMAL256:
case TYPE_INT256:
return nullptr;
case TYPE_DECIMAL256: {
int256_t value;
auto st = type_info->from_string(&value, operand.to_string());
DCHECK(st.ok());
return new Predicate<TYPE_DECIMAL256>(type_info, id, value);
}
case TYPE_DATE_V1: {
uint24_t value = 0;
auto st = type_info->from_string(&value, operand.to_string());

View File

@ -175,7 +175,7 @@ public:
void set_to_min(void* buf) const override {
auto* data = reinterpret_cast<CppType*>(buf);
*data = 1 - get_scale_factor<CppType>(_precision);
*data = CppType(1) - get_scale_factor<CppType>(_precision);
}
size_t size() const override { return _delegate->size(); }

View File

@ -548,6 +548,55 @@ struct ScalarTypeInfoImpl<TYPE_LARGEINT> : public ScalarTypeInfoImplBase<TYPE_LA
}
};
template <>
struct ScalarTypeInfoImpl<TYPE_INT256> : public ScalarTypeInfoImplBase<TYPE_INT256> {
static Status from_string(void* buf, const std::string& scan_key) {
try {
int256_t value = parse_int256(scan_key);
unaligned_store<int256_t>(buf, value);
return Status::OK();
} catch (const std::exception& e) {
// Fallback to zero on parse error
unaligned_store<int256_t>(buf, int256_t(0));
return Status::InternalError(fmt::format("Fail to parse int256 from string: {}", scan_key));
}
}
static std::string to_string(const void* src) {
auto value = unaligned_load<int256_t>(src);
return value.to_string();
}
static void shallow_copy(void* dest, const void* src) {
unaligned_store<int256_t>(dest, unaligned_load<int256_t>(src));
}
static void deep_copy(void* dest, const void* src, MemPool* mem_pool __attribute__((unused))) {
unaligned_store<int256_t>(dest, unaligned_load<int256_t>(src));
}
static void direct_copy(void* dest, const void* src) {
unaligned_store<int256_t>(dest, unaligned_load<int256_t>(src));
}
static void set_to_max(void* buf) { unaligned_store<int256_t>(buf, INT256_MAX); }
static void set_to_min(void* buf) { unaligned_store<int256_t>(buf, INT256_MIN); }
static Status convert_from(void* dest, const void* src, const TypeInfoPtr& src_type,
MemPool* mem_pool __attribute__((unused))) {
if (src_type->type() == TYPE_VARCHAR) {
return convert_int_from_varchar<CppType>(dest, src);
}
return Status::InternalError("Fail to cast to bigint.");
}
static int datum_cmp(const Datum& left, const Datum& right) {
const int256_t& v1 = left.get<int256_t>();
const int256_t& v2 = right.get<int256_t>();
return (v1 < v2) ? -1 : (v2 < v1) ? 1 : 0;
}
};
template <>
struct ScalarTypeInfoImpl<TYPE_FLOAT> : public ScalarTypeInfoImplBase<TYPE_FLOAT> {
static Status from_string(void* buf, const std::string& scan_key) {
@ -1055,10 +1104,4 @@ int TypeComparator<ftype>::cmp(const void* lhs, const void* rhs) {
#define M(ftype) template struct TypeComparator<ftype>;
APPLY_FOR_SUPPORTED_FIELD_TYPE(M)
#undef M
// TODO(stephen): support this trait in next patch
// template <>
// struct ScalarTypeInfoImplBase<TYPE_INT256> {
// };
} // namespace starrocks

View File

@ -21,10 +21,6 @@
namespace starrocks {
// =============================================================================
// Anonymous namespace for internal utilities
// =============================================================================
namespace {
// -----------------------------------------------------------------------------
@ -244,46 +240,221 @@ int256_t divide_positive(const int256_t& dividend, const int256_t& divisor) {
} // anonymous namespace
// Constructor from floating point types
int256_t::int256_t(float value) {
if (std::isnan(value) || std::isinf(value)) {
low = 0;
high = 0;
return;
}
if (value == 0.0f) {
low = 0;
high = 0;
return;
}
bool negative = std::signbit(value);
float abs_value = std::abs(value);
if (abs_value < 1.0f) {
low = 0;
high = 0;
return;
}
constexpr float max_safe_float = 16777216.0f; // 2^24
constexpr float max_float = 3.4028235e38f;
high = 0;
if (abs_value >= max_safe_float) {
int exponent;
float mantissa = std::frexp(abs_value, &exponent);
mantissa *= 2.0f;
exponent -= 1;
uint32_t mantissa_bits = static_cast<uint32_t>((mantissa - 1.0f) * (1U << 23));
uint32_t significand = (1U << 23) | mantissa_bits;
if (exponent <= 64) {
if (exponent >= 23) {
low = static_cast<uint128_t>(significand) << (exponent - 23);
} else {
low = static_cast<uint128_t>(significand) >> (23 - exponent);
}
} else if (exponent <= 128) {
if (exponent >= 87) {
int high_shift = exponent - 87;
if (high_shift >= 64) {
low = static_cast<uint128_t>(max_float);
high = 0;
} else {
low = static_cast<uint128_t>(significand) << 64;
high = static_cast<int128_t>(static_cast<uint64_t>(significand) >> (64 - high_shift));
}
} else if (exponent >= 23) {
low = static_cast<uint128_t>(significand) << (exponent - 23);
high = 0;
} else {
low = static_cast<uint128_t>(significand) >> (23 - exponent);
high = 0;
}
} else {
low = static_cast<uint128_t>(max_float);
high = 0;
}
} else {
if (abs_value <= static_cast<float>(UINT64_MAX)) {
low = static_cast<uint128_t>(static_cast<uint64_t>(abs_value));
} else {
low = static_cast<uint128_t>(abs_value);
}
}
if (negative) {
*this = -*this;
}
}
// Constructor from floating double types with proper overflow detection
int256_t::int256_t(double value) {
if (std::isnan(value) || std::isinf(value) || value == 0.0) {
low = 0;
high = 0;
return;
}
double abs_value = std::abs(value);
if (abs_value < 1.0) {
low = 0;
high = 0;
return;
}
constexpr double max_safe_double = 9007199254740992.0; // 2^53
constexpr double max_int256_double =
5.7896044618658097711785492504343953926634992332820282019728792003956564819968e+76;
if (abs_value >= max_int256_double) {
low = 0;
high = 0;
return;
}
if (abs_value >= max_safe_double) {
constexpr double pow_128 = 340282366920938463463374607431768211456.0; // 2^128
bool negative = value < 0.0;
double abs_val = std::abs(value);
double high_part = std::floor(abs_val / pow_128);
double low_part = abs_val - (high_part * pow_128);
if (high_part > 0) {
high = static_cast<int128_t>(high_part);
} else {
high = 0;
}
low = static_cast<uint128_t>(low_part);
if (negative) {
*this = -*this;
}
} else {
int64_t int_value = static_cast<int64_t>(value);
if (int_value >= 0) {
low = static_cast<uint128_t>(int_value);
high = 0;
} else {
uint64_t abs_int = static_cast<uint64_t>(-int_value);
low = static_cast<uint128_t>(abs_int);
high = 0;
*this = -*this;
}
}
}
// =============================================================================
// Type Conversion Operators Implementation
// =============================================================================
int256_t::operator double() const {
if (*this == 0) return 0.0;
// int256_t::operator double() const {
// if (*this == 0) return 0.0;
//
// const bool negative = (high < 0);
// const int256_t abs_val = negative ? -*this : *this;
//
// // Find the position of the most significant bit
// int bit_count = 0;
// int256_t temp = abs_val;
// while (temp > 0) {
// temp >>= 1;
// bit_count++;
// }
//
// if (bit_count <= 53) {
// // Can represent exactly in double
// double result = static_cast<double>(static_cast<uint64_t>(abs_val.low));
// if (abs_val.high != 0) {
// result += static_cast<double>(static_cast<uint64_t>(abs_val.high)) * (1ULL << 32) * (1ULL << 32) *
// (1ULL << 32) * (1ULL << 32);
// }
// return negative ? -result : result;
// } else {
// // Need to round to fit in double precision
// const int shift = bit_count - 53;
// const int256_t rounded = (abs_val + (int256_t(1) << (shift - 1))) >> shift;
// const double mantissa = static_cast<double>(static_cast<uint64_t>(rounded.low));
// const double result = mantissa * pow(2.0, shift);
// return negative ? -result : result;
// }
// }
const bool negative = (high < 0);
const int256_t abs_val = negative ? -*this : *this;
const int leading_zeros = count_leading_zeros(abs_val);
if (leading_zeros == 256) return 0.0;
const int msb_pos = 255 - leading_zeros;
const int double_precision = 53;
if (msb_pos < double_precision) {
double result = static_cast<double>(static_cast<uint64_t>(abs_val.low));
return negative ? -result : result;
} else if (msb_pos < 128) {
const int excess_bits = msb_pos + 1 - double_precision;
uint128_t shifted = static_cast<uint128_t>(abs_val.low) >> excess_bits;
if (excess_bits > 0) {
uint128_t remainder = static_cast<uint128_t>(abs_val.low) - (shifted << excess_bits);
uint128_t half = uint128_t(1) << (excess_bits - 1);
if (remainder > half || (remainder == half && (shifted & 1) == 1)) {
shifted += 1;
}
}
double mantissa = static_cast<double>(static_cast<uint64_t>(shifted));
double result = mantissa * pow(2.0, excess_bits);
return negative ? -result : result;
} else {
const int excess_bits = msb_pos + 1 - double_precision;
int256_t shifted = abs_val >> excess_bits;
if (excess_bits > 0) {
int256_t remainder = abs_val - (shifted << excess_bits);
int256_t half = int256_t(1) << (excess_bits - 1);
if (remainder > half || (remainder == half && (shifted.low & 1) == 1)) {
shifted = shifted + 1;
}
}
double mantissa;
if (shifted.high == 0) {
mantissa = static_cast<double>(static_cast<uint64_t>(shifted.low));
} else {
mantissa = static_cast<double>(static_cast<uint64_t>(shifted.low));
constexpr double pow_128 = 340282366920938463463374607431768211456.0; // 2^128
mantissa += static_cast<double>(static_cast<uint64_t>(shifted.high)) * pow_128;
}
double result = mantissa * pow(2.0, excess_bits);
if (std::isinf(result)) {
result = negative ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity();
}
return negative ? -result : result;
}
}
// =============================================================================
// Multiplication Runtime Implementation - Helper Functions
// =============================================================================
/**
* @brief Multiply two 64-bit unsigned integers to produce a 256-bit result
*
@ -502,7 +673,6 @@ int256_t int256_t::operator/(const int256_t& other) const {
if (other.high == 0 && other.low == 0) {
throw std::domain_error("Division by zero");
}
if (high == 0 && low == 0) return int256_t(0);
if (*this == other) return int256_t(1);

View File

@ -153,38 +153,33 @@ public:
/// Constructor from floating point types
/// @param value Floating point value to convert (truncated to integer)
constexpr int256_t(float value)
: low(static_cast<uint128_t>(static_cast<long long>(value))), high(value < 0 ? -1 : 0) {}
constexpr int256_t(double value)
: low(static_cast<uint128_t>(static_cast<long long>(value))), high(value < 0 ? -1 : 0) {}
explicit int256_t(float value);
explicit int256_t(double value);
// =============================================================================
// Type Conversion Operators
// =============================================================================
/// Convert to boolean (true if non-zero)
operator bool() const { return high != 0 || low != 0; }
//
// /// High precision conversion using bit manipulation
// operator double() const;
//
// /// Convert to size_t (safe conversion with overflow checking)
// operator size_t() const {
// if (high < 0) {
// throw std::out_of_range("Cannot convert negative int256_t to size_t");
// }
//
// if (high > 0) {
// throw std::out_of_range("int256_t value too large for size_t");
// }
//
// constexpr uint128_t max_size_t = std::numeric_limits<size_t>::max();
// if (low > max_size_t) {
// throw std::out_of_range("int256_t value too large for size_t");
// }
//
// return static_cast<size_t>(low);
// }
explicit operator bool() const { return high != 0 || low != 0; }
/// High precision conversion using bit manipulation
explicit operator double() const;
explicit operator int() const { return static_cast<int>(static_cast<uint32_t>(low)); }
explicit operator long() const { return static_cast<long>(static_cast<uint64_t>(low)); }
explicit operator int128_t() const { return static_cast<__int128>(low); }
/// Convert to signed char
explicit operator signed char() const { return static_cast<signed char>(static_cast<int64_t>(low)); }
/// Convert to short int
explicit operator short int() const { return static_cast<short>(static_cast<int64_t>(low)); }
/// Convert to size_t
explicit operator size_t() const { return static_cast<size_t>(low); }
// =============================================================================
// Unary Operators
@ -197,6 +192,7 @@ public:
return int256_t(-high, 0);
} else {
uint128_t new_low = ~low + 1;
int128_t new_high = ~high;
if (new_low == 0) {
new_high++;
@ -276,6 +272,93 @@ public:
/// @return true if this value is greater than or equal to other
constexpr bool operator>=(int other) const { return *this >= int256_t(other); }
/// Equality comparison with double
/// @param other Double value to compare with
/// @return true if values are equal (within floating point precision)
bool operator==(double other) const {
if (std::floor(other) != other) {
return false;
}
int256_t INT256_MAX{static_cast<int128_t>((static_cast<uint128_t>(1) << 127) - 1), static_cast<uint128_t>(-1)};
int256_t INT256_MIN{static_cast<int128_t>(static_cast<uint128_t>(1) << 127), static_cast<uint128_t>(0)};
if (other > static_cast<double>(INT256_MAX) || other < static_cast<double>(INT256_MIN)) {
return false;
}
return *this == int256_t(other);
}
/// Inequality comparison with double
/// @param other Double value to compare with
/// @return true if values are not equal
bool operator!=(double other) const { return !(*this == other); }
/// Less than comparison with double
/// @param other Double value to compare with
/// @return true if this value is less than other
bool operator<(double other) const { return static_cast<double>(*this) < other; }
/// Less than or equal comparison with double
/// @param other Double value to compare with
/// @return true if this value is less than or equal to other
bool operator<=(double other) const { return static_cast<double>(*this) <= other; }
/// Greater than comparison with double
/// @param other Double value to compare with
/// @return true if this value is greater than other
bool operator>(double other) const { return static_cast<double>(*this) > other; }
/// Greater than or equal comparison with double
/// @param other Double value to compare with
/// @return true if this value is greater than or equal to other
bool operator>=(double other) const { return static_cast<double>(*this) >= other; }
// =============================================================================
// Friend Comparison Operators (for reverse operand order)
// =============================================================================
/// Equality comparison: int == int256_t
friend constexpr bool operator==(int lhs, const int256_t& rhs) { return int256_t(lhs) == rhs; }
/// Inequality comparison: int != int256_t
friend constexpr bool operator!=(int lhs, const int256_t& rhs) { return int256_t(lhs) != rhs; }
/// Less than comparison: int < int256_t
friend constexpr bool operator<(int lhs, const int256_t& rhs) { return int256_t(lhs) < rhs; }
/// Less than or equal comparison: int <= int256_t
friend constexpr bool operator<=(int lhs, const int256_t& rhs) { return int256_t(lhs) <= rhs; }
/// Greater than comparison: int > int256_t
friend constexpr bool operator>(int lhs, const int256_t& rhs) { return int256_t(lhs) > rhs; }
/// Greater than or equal comparison: int >= int256_t
friend constexpr bool operator>=(int lhs, const int256_t& rhs) { return int256_t(lhs) >= rhs; }
// =============================================================================
// Friend Comparison Operators (for reverse operand order with double)
// =============================================================================
/// Equality comparison: double == int256_t
friend bool operator==(double lhs, const int256_t& rhs) { return rhs == lhs; }
/// Inequality comparison: double != int256_t
friend bool operator!=(double lhs, const int256_t& rhs) { return rhs != lhs; }
/// Less than comparison: double < int256_t
friend bool operator<(double lhs, const int256_t& rhs) { return lhs < static_cast<double>(rhs); }
/// Less than or equal comparison: double <= int256_t
friend bool operator<=(double lhs, const int256_t& rhs) { return lhs <= static_cast<double>(rhs); }
/// Greater than comparison: double > int256_t
friend bool operator>(double lhs, const int256_t& rhs) { return lhs > static_cast<double>(rhs); }
/// Greater than or equal comparison: double >= int256_t
friend bool operator>=(double lhs, const int256_t& rhs) { return lhs >= static_cast<double>(rhs); }
// =============================================================================
// Arithmetic Operators - Addition
// =============================================================================
@ -298,6 +381,21 @@ public:
/// @return Sum of this value and other
constexpr int256_t operator+(int other) const { return *this + int256_t(other); }
/// Addition with double (returns double)
/// @param other Double value to add
/// @return Sum as double
double operator+(double other) const { return static_cast<double>(*this) + other; }
// =============================================================================
// Friend Arithmetic Operators - Addition
// =============================================================================
/// Addition: double + int256_t (returns double)
/// @param lhs Double value
/// @param rhs int256_t value
/// @return Sum as double
friend double operator+(double lhs, const int256_t& rhs) { return lhs + static_cast<double>(rhs); }
// =============================================================================
// Arithmetic Operators - Subtraction
// =============================================================================
@ -322,6 +420,16 @@ public:
/// @return Difference as double
double operator-(double other) const { return static_cast<double>(*this) - other; }
// =============================================================================
// Friend Arithmetic Operators - Subtraction
// =============================================================================
/// Subtraction: double - int256_t (returns double)
/// @param lhs Double value
/// @param rhs int256_t value
/// @return Difference as double
friend double operator-(double lhs, const int256_t& rhs) { return lhs - static_cast<double>(rhs); }
// =============================================================================
// Arithmetic Operators - Multiplication
// =============================================================================
@ -341,8 +449,23 @@ public:
/// @return Product of this value and other
int256_t operator*(int other) const { return *this * int256_t(other); }
/// Multiplication with double (returns double)
/// @param other Double value to multiply by
/// @return Product as double
double operator*(double other) const { return static_cast<double>(*this) * other; }
// =============================================================================
// Arithmetic Operators - Division (Declaration only)
// Friend Arithmetic Operators - Multiplication
// =============================================================================
/// Multiplication: double * int256_t (returns double)
/// @param lhs Double value
/// @param rhs int256_t value
/// @return Product as double
friend double operator*(double lhs, const int256_t& rhs) { return lhs * static_cast<double>(rhs); }
// =============================================================================
// Arithmetic Operators - Division
// =============================================================================
/// Division with another int256_t
@ -351,8 +474,57 @@ public:
/// @throws std::domain_error if other is zero
int256_t operator/(const int256_t& other) const;
/// @brief Division with int
/// @param other Integer value to divide by
/// @return Quotient of this value divided by other
/// @throws std::domain_error if other is zero
int256_t operator/(int other) const {
if (other == 0) {
throw std::domain_error("Division by zero");
}
return *this / int256_t(other);
}
/// Division with double (returns double)
/// @param other Double value to divide by
/// @return Quotient as double
/// @throws std::domain_error if other is zero
double operator/(double other) const {
if (other == 0.0) {
throw std::domain_error("Division by zero");
}
return static_cast<double>(*this) / other;
}
// =============================================================================
// Arithmetic Operators - Modulo (Declaration only)
// Friend Arithmetic Operators - Division
// =============================================================================
/// @brief Division: int / int256_t
/// @param lhs Integer value
/// @param rhs int256_t value to divide by
/// @return Quotient as int256_t
/// @throws std::domain_error if rhs is zero
friend int256_t operator/(int lhs, const int256_t& rhs) {
if (rhs == int256_t(0)) {
throw std::domain_error("Division by zero");
}
return int256_t(lhs) / rhs;
}
/// Division: double / int256_t (returns double)
/// @param lhs Double value
/// @param rhs int256_t value
/// @return Quotient as double
/// @throws std::domain_error if rhs is zero
friend double operator/(double lhs, const int256_t& rhs) {
if (rhs == int256_t(0)) {
throw std::domain_error("Division by zero");
}
return lhs / static_cast<double>(rhs);
}
// =============================================================================
// Arithmetic Operators - Modulo
// =============================================================================
/// Modulo operation with another int256_t
@ -361,6 +533,55 @@ public:
/// @throws std::domain_error if other is zero
int256_t operator%(const int256_t& other) const;
/// Modulo operation with int
/// @param other Integer value to take modulo by
/// @return Remainder of this value divided by other
/// @throws std::domain_error if other is zero
int256_t operator%(int other) const {
if (other == 0) {
throw std::domain_error("Modulo by zero");
}
return *this % int256_t(other);
}
/// Modulo operation with double (using fmod semantics)
/// @param other Double value to take modulo by
/// @return Remainder as double (using fmod semantics)
/// @throws std::domain_error if other is zero
double operator%(double other) const {
if (other == 0.0) {
throw std::domain_error("Modulo by zero");
}
return std::fmod(static_cast<double>(*this), other);
}
// =============================================================================
// Friend Arithmetic Operators - Modulo
// =============================================================================
/// Modulo operation: int % int256_t
/// @param lhs Integer value
/// @param rhs int256_t value to take modulo by
/// @return Remainder as int256_t
/// @throws std::domain_error if rhs is zero
friend int256_t operator%(int lhs, const int256_t& rhs) {
if (rhs == int256_t(0)) {
throw std::domain_error("Modulo by zero");
}
return int256_t(lhs) % rhs;
}
/// Modulo operation: double % int256_t (using fmod semantics)
/// @param lhs Double value
/// @param rhs int256_t value to take modulo by
/// @return Remainder as double (using fmod semantics)
/// @throws std::domain_error if rhs is zero
friend double operator%(double lhs, const int256_t& rhs) {
if (rhs == int256_t(0)) {
throw std::domain_error("Modulo by zero");
}
return std::fmod(lhs, static_cast<double>(rhs));
}
// =============================================================================
// Assignment Operators
// =============================================================================
@ -480,7 +701,57 @@ public:
/// Left shift assignment operator
/// @param shift Number of bits to shift left
/// @return Reference to this after shifting
constexpr int256_t& operator<<=(int shift) { return *this = *this << shift; }
int256_t& operator<<=(int shift) { return *this = *this << shift; }
// =============================================================================
// Bitwise Operators
// =============================================================================
/// Bitwise AND operator
/// @param other Value to perform AND with
/// @return Bitwise AND result
int256_t operator&(const int256_t& other) const { return int256_t(high & other.high, low & other.low); }
/// Bitwise OR operator
/// @param other Value to perform OR with
/// @return Bitwise OR result
int256_t operator|(const int256_t& other) const { return int256_t(high | other.high, low | other.low); }
/// Bitwise XOR operator
/// @param other Value to perform XOR with
/// @return Bitwise XOR result
int256_t operator^(const int256_t& other) const { return int256_t(high ^ other.high, low ^ other.low); }
/// Bitwise NOT operator
/// @return Bitwise complement of this value
int256_t operator~() const { return int256_t(~high, ~low); }
/// Bitwise AND assignment operator
/// @param other Value to perform AND with
/// @return Reference to this after AND operation
int256_t& operator&=(const int256_t& other) {
high &= other.high;
low &= other.low;
return *this;
}
/// Bitwise OR assignment operator
/// @param other Value to perform OR with
/// @return Reference to this after OR operation
int256_t& operator|=(const int256_t& other) {
high |= other.high;
low |= other.low;
return *this;
}
/// Bitwise XOR assignment operator
/// @param other Value to perform XOR with
/// @return Reference to this after XOR operation
int256_t& operator^=(const int256_t& other) {
high ^= other.high;
low ^= other.low;
return *this;
}
// =============================================================================
// Utility Methods
@ -636,6 +907,12 @@ int256_t parse_int256(const std::string& str);
namespace std {
/// Specialization of make_signed for int256_t
template <>
struct make_signed<starrocks::int256_t> {
using type = starrocks::int256_t;
};
/// Specialization of make_unsigned for int256_t
template <>
struct make_unsigned<starrocks::int256_t> {

View File

@ -277,6 +277,7 @@ constexpr bool support_column_expr_predicate(LogicalType ltype) {
case TYPE_DECIMAL32: /* 24 */
case TYPE_DECIMAL64: /* 25 */
case TYPE_DECIMAL128: /* 26 */
case TYPE_DECIMAL256: /* 27 */
case TYPE_STRUCT:
return true;
default:
@ -318,6 +319,7 @@ VALUE_GUARD(LogicalType, FloatLTGuard, lt_is_float, TYPE_FLOAT, TYPE_DOUBLE)
VALUE_GUARD(LogicalType, Decimal32LTGuard, lt_is_decimal32, TYPE_DECIMAL32)
VALUE_GUARD(LogicalType, Decimal64LTGuard, lt_is_decimal64, TYPE_DECIMAL64)
VALUE_GUARD(LogicalType, Decimal128LTGuard, lt_is_decimal128, TYPE_DECIMAL128)
VALUE_GUARD(LogicalType, Decimal256LTGuard, lt_is_decimal256, TYPE_DECIMAL256)
VALUE_GUARD(LogicalType, DecimalLTGuard, lt_is_decimal, TYPE_DECIMAL32, TYPE_DECIMAL64, TYPE_DECIMAL128,
TYPE_DECIMAL256)
VALUE_GUARD(LogicalType, SumDecimal64LTGuard, lt_is_sum_decimal64, TYPE_DECIMAL32, TYPE_DECIMAL64)

View File

@ -43,6 +43,7 @@
#include "common/logging.h"
#include "gutil/strings/fastmem.h"
#include "types/int256.h"
#include "types/large_int_value.h"
#include "util/mysql_global.h"
@ -126,6 +127,9 @@ void MysqlRowBuffer::push_number_binary_format(T data) {
} else if constexpr (std::is_same_v<std::make_signed_t<T>, __int128>) {
std::string value = LargeIntValue::to_string(data);
_push_string_normal(value.data(), value.size());
} else if constexpr (std::is_same_v<T, int256_t>) {
std::string value = data.to_string();
_push_string_normal(value.data(), value.size());
} else {
CHECK(false) << "unhandled data type";
}
@ -133,7 +137,7 @@ void MysqlRowBuffer::push_number_binary_format(T data) {
template <typename T>
void MysqlRowBuffer::push_number(T data, bool is_binary_protocol) {
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, __int128>);
static_assert(std::is_arithmetic_v<T> || std::is_same_v<T, __int128> || std::is_same_v<T, int256_t>);
if (is_binary_protocol) {
return push_number_binary_format(data);
@ -171,6 +175,10 @@ void MysqlRowBuffer::push_number(T data, bool is_binary_protocol) {
pos = _resize_extra(2 + 40);
end = fmt::format_to(pos + length_prefix_bytes, FMT_COMPILE("{}"), data);
length = end - pos - length_prefix_bytes;
} else if constexpr (std::is_same_v<T, int256_t>) {
pos = _resize_extra(2 + 80);
end = fmt::format_to(pos + length_prefix_bytes, FMT_COMPILE("{}"), data);
length = end - pos - length_prefix_bytes;
} else {
CHECK(false) << "unhandled data type";
}
@ -346,6 +354,7 @@ template void MysqlRowBuffer::push_number<uint16_t>(uint16_t, bool);
template void MysqlRowBuffer::push_number<uint32_t>(uint32_t, bool);
template void MysqlRowBuffer::push_number<uint64_t>(uint64_t, bool);
template void MysqlRowBuffer::push_number<__int128>(__int128, bool);
template void MysqlRowBuffer::push_number<int256_t>(int256_t, bool);
template void MysqlRowBuffer::push_number<float>(float, bool);
template void MysqlRowBuffer::push_number<double>(double, bool);

View File

@ -608,6 +608,11 @@ inline int StringParser::StringParseTraits<__int128>::max_ascii_len() {
return 39;
}
template <>
inline int StringParser::StringParseTraits<int256_t>::max_ascii_len() {
return 77;
}
template <typename T>
inline T StringParser::string_to_decimal(const char* s, int len, int type_precision, int type_scale,
ParseResult* result) {

View File

@ -947,4 +947,289 @@ TEST_F(Int256ArithmeticTest, division_truncation_behavior) {
}
}
// NOLINTNEXTLINE
TEST_F(Int256ArithmeticTest, multiplication_both_over_128bit) {
// Test cases where both operands are over 128 bits
// These tests focus on multiply_core_256bit logic coverage
// Test case 1: Both operands have significant high parts
{
int256_t a(0x123456789ABCDEF0ULL, 0xFEDCBA9876543210ULL); // > 128 bit
int256_t b(0x0FEDCBA987654321ULL, 0x123456789ABCDEF0ULL); // > 128 bit
int256_t result = a * b;
// Since this will overflow, we mainly check that:
// 1. The operation doesn't crash
// 2. The result is deterministic
int256_t result2 = a * b;
ASSERT_EQ(result, result2); // Should be deterministic
// Check commutativity (even with overflow)
int256_t result_comm = b * a;
ASSERT_EQ(result, result_comm);
}
// Test case 2: Large positive numbers
{
int256_t large1(0x7FFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL);
int256_t large2(0x3FFFFFFFFFFFFFFFULL, 0x8000000000000000ULL);
int256_t result = large1 * large2;
// Verify the multiplication is consistent
ASSERT_EQ(result, large1 * large2);
ASSERT_EQ(result, large2 * large1);
// The result should not be zero (unless there's a specific overflow pattern)
// This is a sanity check for the core multiplication logic
ASSERT_NE(result, int256_t(0));
}
// Test case 3: Mixed sign large numbers
{
int256_t pos_large(0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL);
int256_t neg_large = -pos_large;
int256_t result_pos_neg = pos_large * neg_large;
int256_t result_neg_pos = neg_large * pos_large;
// Should be commutative
ASSERT_EQ(result_pos_neg, result_neg_pos);
}
// Test case 4: Numbers close to 2^128
{
int256_t just_over_128(1, 0x1000000000000000ULL); // Slightly over 2^128
int256_t another_large(0x8000000000000000ULL, 0); // 2^127 * 2^64
int256_t result = just_over_128 * another_large;
// Check deterministic behavior
ASSERT_EQ(result, just_over_128 * another_large);
ASSERT_EQ(result, another_large * just_over_128);
}
// Test case 5: Maximum high parts
{
int256_t max_high1(0xFFFFFFFFFFFFFFFFULL, 0x123456789ABCDEF0ULL);
int256_t max_high2(0xFFFFFFFFFFFFFFFFULL, 0xFEDCBA0987654321ULL);
int256_t result = max_high1 * max_high2;
// This will definitely overflow, but should be consistent
ASSERT_EQ(result, max_high1 * max_high2);
ASSERT_EQ(result, max_high2 * max_high1);
}
// Test case 6: Patterns that test different code paths in multiply_core_256bit
{
// Test with alternating bit patterns
int256_t pattern1(0xAAAAAAAAAAAAAAAAULL, 0x5555555555555555ULL);
int256_t pattern2(0x5555555555555555ULL, 0xAAAAAAAAAAAAAAAAULL);
int256_t result = pattern1 * pattern2;
// Verify consistency
ASSERT_EQ(result, pattern1 * pattern2);
ASSERT_EQ(result, pattern2 * pattern1);
}
// Test case 7: Powers of 2 over 128 bits
{
int256_t power_129(2, 0); // 2^129
int256_t power_130(4, 0); // 2^130
int256_t result = power_129 * power_130;
// This should be 2^259, which will overflow significantly
// Check that it's consistent
ASSERT_EQ(result, power_129 * power_130);
ASSERT_EQ(result, power_130 * power_129);
}
// Test case 8: Large numbers with specific bit positions set
{
int256_t sparse1(0x8000000000000001ULL, 0x0000000000000001ULL);
int256_t sparse2(0x0000000000000001ULL, 0x8000000000000001ULL);
int256_t result = sparse1 * sparse2;
// Verify deterministic behavior
ASSERT_EQ(result, sparse1 * sparse2);
ASSERT_EQ(result, sparse2 * sparse1);
}
}
// NOLINTNEXTLINE
TEST_F(Int256ArithmeticTest, multiplication_overflow_patterns) {
// Test specific overflow patterns to ensure multiply_core_256bit handles them correctly
// Test case 1: Multiplication that causes carry propagation
{
int256_t carry_test1(0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL);
int256_t carry_test2(0x0000000000000002ULL, 0x0000000000000001ULL);
int256_t result = carry_test1 * carry_test2;
// This tests carry propagation through all 64-bit chunks
ASSERT_EQ(result, carry_test1 * carry_test2);
ASSERT_EQ(result, carry_test2 * carry_test1);
}
// Test case 2: Multiplication with maximum values
{
int256_t near_max(INT256_MAX.high, INT256_MAX.low - 1000);
int256_t multiplier(0x0000000000000001ULL, 0x0000000000000002ULL);
int256_t result = near_max * multiplier;
// Should handle near-maximum values without crashing
ASSERT_EQ(result, near_max * multiplier);
ASSERT_EQ(result, multiplier * near_max);
}
// Test case 3: Test all four 64-bit chunk combinations
{
int256_t chunk_test(0x123456789ABCDEF0ULL, 0xFEDCBA9876543210ULL);
int256_t chunk_mult(0x0FEDCBA987654321ULL, 0x0123456789ABCDEFULL);
int256_t result = chunk_test * chunk_mult;
// This exercises all combinations of 64-bit chunk multiplications
// in multiply_core_256bit
ASSERT_EQ(result, chunk_test * chunk_mult);
ASSERT_EQ(result, chunk_mult * chunk_test);
}
}
// NOLINTNEXTLINE
TEST_F(Int256ArithmeticTest, multiplication_edge_bit_boundaries) {
// Test multiplications at various bit boundaries to ensure proper handling
// Test at 129-bit boundary
{
int256_t just_129_bit(1, 1); // 2^128 + 1
int256_t multiplier(0, 0x8000000000000000ULL); // 2^63
int256_t result = just_129_bit * multiplier;
ASSERT_EQ(result, just_129_bit * multiplier);
ASSERT_EQ(result, multiplier * just_129_bit);
}
// Test at 192-bit boundary
{
int256_t val_192(0x1000000000000000ULL, 0); // 2^192
int256_t val_128(1, 0); // 2^128
int256_t result = val_192 * val_128;
ASSERT_EQ(result, val_192 * val_128);
ASSERT_EQ(result, val_128 * val_192);
}
// Test with values that span multiple 64-bit boundaries
{
int256_t span_test(0x00000000FFFFFFFFULL, 0xFFFFFFFF00000000ULL);
int256_t span_mult(0xFFFFFFFF00000000ULL, 0x00000000FFFFFFFFULL);
int256_t result = span_test * span_mult;
ASSERT_EQ(result, span_test * span_mult);
ASSERT_EQ(result, span_mult * span_test);
}
}
// NOLINTNEXTLINE
TEST_F(Int256ArithmeticTest, multiplication_stress_large_numbers) {
// Stress test with various large number combinations
std::vector<int256_t> large_test_values = {
int256_t(0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL), // Near max positive
int256_t(0x8000000000000000ULL, 0x0000000000000000ULL), // 2^191
int256_t(0x7FFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL), // Large positive
int256_t(0x1234567890ABCDEFULL, 0xFEDCBA9876543210ULL), // Random large
int256_t(0xFEDCBA9876543210ULL, 0x1234567890ABCDEFULL), // Random large 2
int256_t(0xAAAAAAAAAAAAAAAAULL, 0x5555555555555555ULL), // Alternating bits
int256_t(0x5555555555555555ULL, 0xAAAAAAAAAAAAAAAAULL), // Alternating bits 2
};
// Test all combinations
for (size_t i = 0; i < large_test_values.size(); ++i) {
for (size_t j = i; j < large_test_values.size(); ++j) {
const auto& a = large_test_values[i];
const auto& b = large_test_values[j];
int256_t result = a * b;
// Basic consistency checks
ASSERT_EQ(result, a * b) << "Multiplication not deterministic for values at indices " << i << ", " << j;
ASSERT_EQ(result, b * a) << "Multiplication not commutative for values at indices " << i << ", " << j;
// Test with negatives
int256_t neg_a = -a;
int256_t neg_b = -b;
int256_t result_neg_pos = neg_a * b;
int256_t result_pos_neg = a * neg_b;
// These should be equal (both negative * positive)
ASSERT_EQ(result_neg_pos, result_pos_neg) << "Sign handling inconsistent for indices " << i << ", " << j;
}
}
}
// NOLINTNEXTLINE
TEST_F(Int256ArithmeticTest, multiplication_256bit_core_coverage) {
// Specific tests to ensure multiply_core_256bit gets proper coverage
// Test case 1: Force all partial products to be non-zero
{
int256_t full_bits(0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL);
int256_t partial_bits(0x0F0F0F0F0F0F0F0FULL, 0xF0F0F0F0F0F0F0F0ULL);
int256_t result = full_bits * partial_bits;
// This should exercise all partial product calculations
ASSERT_EQ(result, full_bits * partial_bits);
ASSERT_EQ(result, partial_bits * full_bits);
}
// Test case 2: Test carry chain propagation
{
int256_t carry_gen(0x8000000000000000ULL, 0x8000000000000000ULL);
int256_t carry_prop(0x0000000000000002ULL, 0x0000000000000002ULL);
int256_t result = carry_gen * carry_prop;
// This should test carry propagation between 64-bit chunks
ASSERT_EQ(result, carry_gen * carry_prop);
ASSERT_EQ(result, carry_prop * carry_gen);
}
// Test case 3: Mixed zero and non-zero chunks
{
int256_t mixed1(0xFFFFFFFFFFFFFFFFULL, 0x0000000000000000ULL);
int256_t mixed2(0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFFULL);
int256_t result = mixed1 * mixed2;
// This tests the case where some 64-bit chunks are zero
ASSERT_EQ(result, mixed1 * mixed2);
ASSERT_EQ(result, mixed2 * mixed1);
}
// Test case 4: Boundary values for each 64-bit chunk
{
int256_t boundary1(0x7FFFFFFFFFFFFFFFULL, 0x8000000000000000ULL);
int256_t boundary2(0x8000000000000000ULL, 0x7FFFFFFFFFFFFFFFULL);
int256_t result = boundary1 * boundary2;
// This tests sign bit boundaries in each chunk
ASSERT_EQ(result, boundary1 * boundary2);
ASSERT_EQ(result, boundary2 * boundary1);
}
}
} // end namespace starrocks

File diff suppressed because it is too large Load Diff

View File

@ -141,6 +141,11 @@ public class ArithmeticExpr extends Expr {
Operator.DIVIDE.getName(),
Lists.<Type>newArrayList(Type.DECIMAL128, Type.DECIMAL128),
Type.DECIMAL128));
functionSet.addBuiltin(ScalarFunction.createBuiltinOperator(
Operator.DIVIDE.getName(),
Lists.<Type>newArrayList(Type.DECIMAL256, Type.DECIMAL256),
Type.DECIMAL256));
// MOD(), FACTORIAL(), BITAND(), BITOR(), BITXOR(), and BITNOT() are registered as
// builtins, see starrocks_functions.py
@ -208,13 +213,18 @@ public class ArithmeticExpr extends Expr {
final int lhsScale = lhsType.getScalarScale();
final int rhsScale = rhsType.getScalarScale();
int maxRetPrecision = 38;
// TODO(stephen): support auto scale up decimal precision
if (triple.lhsTargetType.isDecimal256() || triple.rhsTargetType.isDecimal256()) {
maxRetPrecision = 76;
}
// decimal(p1, s1) + decimal(p2, s2)
// result type = decimal(max(p1 - s1, p2 - s2) + max(s1, s2) + 1, max(s1, s2))
int maxIntLength = Math.max(lhsPrecision - lhsScale, rhsPrecision - rhsScale);
int retPrecision = maxIntLength + Math.max(lhsScale, rhsScale) + 1;
int retScale = Math.max(lhsScale, rhsScale);
// precision
retPrecision = Math.min(retPrecision, 38);
retPrecision = Math.min(retPrecision, maxRetPrecision);
PrimitiveType decimalType = PrimitiveType.getDecimalPrimitiveType(retPrecision);
decimalType = PrimitiveType.getWiderDecimalV3Type(decimalType, lhsType.getPrimitiveType());
decimalType = PrimitiveType.getWiderDecimalV3Type(decimalType, rhsType.getPrimitiveType());
@ -257,7 +267,12 @@ public class ArithmeticExpr extends Expr {
case MULTIPLY:
returnScale = lhsScale + rhsScale;
returnPrecision = lhsPrecision + rhsPrecision;
final int maxDecimalPrecision = PrimitiveType.getMaxPrecisionOfDecimal(PrimitiveType.DECIMAL128);
PrimitiveType defaultMaxDecimalType = PrimitiveType.DECIMAL128;
// TODO(stephen): support auto scale up decimal precision
if (result.lhsTargetType.isDecimal256() || result.rhsTargetType.isDecimal256()) {
defaultMaxDecimalType = PrimitiveType.DECIMAL256;
}
final int maxDecimalPrecision = PrimitiveType.getMaxPrecisionOfDecimal(defaultMaxDecimalType);
if (returnPrecision <= maxDecimalPrecision) {
// returnPrecision <= 38, result never overflows, use the narrowest decimal type that can holds the result.
// for examples:
@ -265,6 +280,11 @@ public class ArithmeticExpr extends Expr {
// decimal64(15,3) * decimal32(9,4) => decimal128(24,7).
PrimitiveType commonPtype =
ScalarType.createDecimalV3NarrowestType(returnPrecision, returnScale).getPrimitiveType();
// TODO(stephen): support auto scale up decimal precision
if (defaultMaxDecimalType == PrimitiveType.DECIMAL128 && commonPtype == PrimitiveType.DECIMAL256) {
commonPtype = PrimitiveType.DECIMAL128;
}
// a common type shall never be narrower than type of lhs and rhs
commonPtype = PrimitiveType.getWiderDecimalV3Type(commonPtype, lhsPtype);
commonPtype = PrimitiveType.getWiderDecimalV3Type(commonPtype, rhsPtype);
@ -279,11 +299,11 @@ public class ArithmeticExpr extends Expr {
// for examples:
// decimal128(23,5) * decimal64(18,4) => decimal128(38, 9).
result.returnType =
ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, maxDecimalPrecision, returnScale);
ScalarType.createDecimalV3Type(defaultMaxDecimalType, maxDecimalPrecision, returnScale);
result.lhsTargetType =
ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, lhsPrecision, lhsScale);
ScalarType.createDecimalV3Type(defaultMaxDecimalType, lhsPrecision, lhsScale);
result.rhsTargetType =
ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, rhsPrecision, rhsScale);
ScalarType.createDecimalV3Type(defaultMaxDecimalType, rhsPrecision, rhsScale);
return result;
} else {
// returnScale > 38, so it is cannot be represented as decimal.
@ -292,6 +312,7 @@ public class ArithmeticExpr extends Expr {
"Return scale(%d) exceeds maximum value(%d), please cast decimal type to low-precision one",
returnScale, maxDecimalPrecision));
}
case INT_DIVIDE:
case DIVIDE:
if (lhsScale <= 6) {
@ -302,6 +323,11 @@ public class ArithmeticExpr extends Expr {
returnScale = lhsScale;
}
widerType = PrimitiveType.DECIMAL128;
// TODO(stephen): support auto scale up decimal precision
if (result.lhsTargetType.isDecimal256() || result.rhsTargetType.isDecimal256()) {
widerType = PrimitiveType.DECIMAL256;
}
maxPrecision = PrimitiveType.getMaxPrecisionOfDecimal(widerType);
result.lhsTargetType = ScalarType.createDecimalV3Type(widerType, maxPrecision, lhsScale);
result.rhsTargetType = ScalarType.createDecimalV3Type(widerType, maxPrecision, rhsScale);

View File

@ -93,6 +93,7 @@ public abstract class LiteralExpr extends Expr implements Comparable<LiteralExpr
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
literalExpr = new DecimalLiteral(value);
break;
case CHAR:

View File

@ -225,6 +225,7 @@ public class StringLiteral extends LiteralExpr {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return new DecimalLiteral(value).uncheckedCastTo(targetType);
default:
break;

View File

@ -159,7 +159,8 @@ public class TypeDef implements ParseNode {
case DECIMALV2:
case DECIMAL32:
case DECIMAL64:
case DECIMAL128: {
case DECIMAL128:
case DECIMAL256: {
final String name = scalarType.getPrimitiveType().name();
final int precision = scalarType.decimalPrecision();
final int scale = scalarType.decimalScale();

View File

@ -1381,8 +1381,13 @@ public class FunctionSet {
}
}
for (ScalarType type : Type.DECIMAL_TYPES) {
Type retType = Type.DECIMAL128;
// TODO(stephen): support auto scale up decimal precision
if (type.isDecimal256()) {
retType = Type.DECIMAL256;
}
addBuiltin(AggregateFunction.createBuiltin(name,
Lists.newArrayList(type), Type.DECIMAL128, Type.DECIMAL128,
Lists.newArrayList(type), retType, retType,
false, true, false));
}
addBuiltin(AggregateFunction.createBuiltin(name,
@ -1407,8 +1412,13 @@ public class FunctionSet {
}
}
for (ScalarType type : Type.DECIMAL_TYPES) {
Type retType = Type.DECIMAL128;
// TODO(stephen): support auto scale up decimal precision
if (type.isDecimal256()) {
retType = Type.DECIMAL256;
}
addBuiltin(AggregateFunction.createBuiltin(MULTI_DISTINCT_SUM,
Lists.newArrayList(type), Type.DECIMAL128, Type.VARBINARY,
Lists.newArrayList(type), retType, Type.VARBINARY,
false, true, false));
}
addBuiltin(AggregateFunction.createBuiltin(MULTI_DISTINCT_SUM,
@ -1501,8 +1511,13 @@ public class FunctionSet {
false, true, false));
}
for (ScalarType type : Type.DECIMAL_TYPES) {
Type retType = Type.DECIMAL128;
// TODO(stephen): support auto scale up decimal precision
if (type.isDecimal256()) {
retType = Type.DECIMAL256;
}
addBuiltin(AggregateFunction.createBuiltin(AVG,
Lists.newArrayList(type), Type.DECIMAL128, Type.VARBINARY,
Lists.newArrayList(type), retType, Type.VARBINARY,
false, true, false));
}
addBuiltin(AggregateFunction.createBuiltin(AVG,

View File

@ -37,7 +37,6 @@ package com.starrocks.catalog;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.starrocks.mysql.MysqlColType;
import com.starrocks.thrift.TPrimitiveType;
@ -144,25 +143,6 @@ public enum PrimitiveType {
.addAll(STRING_TYPE_LIST)
.build();
private static final ImmutableSortedSet<String> VARIABLE_TYPE_SET =
ImmutableSortedSet.orderedBy(String.CASE_INSENSITIVE_ORDER)
.add(PrimitiveType.CHAR.toString())
.add(PrimitiveType.VARCHAR.toString())
.add(PrimitiveType.DECIMALV2.toString())
.add(PrimitiveType.DECIMAL32.toString())
.add(PrimitiveType.DECIMAL64.toString())
.add(PrimitiveType.DECIMAL128.toString())
.add("DECIMAL") // generic name for all decimal types
.build();
public static boolean isVariableType(String typeName) {
return VARIABLE_TYPE_SET.contains(typeName);
}
public static boolean isStaticType(String typeName) {
return !VARIABLE_TYPE_SET.contains(typeName);
}
static {
ImmutableSetMultimap.Builder<PrimitiveType, PrimitiveType> builder = ImmutableSetMultimap.builder();
builder.putAll(NULL_TYPE, BASIC_TYPE_LIST);
@ -312,6 +292,10 @@ public enum PrimitiveType {
*/
public static PrimitiveType getWiderDecimalV3Type(PrimitiveType t1, PrimitiveType t2) {
Preconditions.checkState(t1.isDecimalV3Type() && t2.isDecimalV3Type());
// TODO(stephen): support auto scale up decimal precision
if (t1.equals(DECIMAL256) || t2.equals(DECIMAL256)) {
return DECIMAL256;
}
if (t1.equals(DECIMAL32)) {
return t2;
} else if (t2.equals(DECIMAL32)) {
@ -382,6 +366,8 @@ public enum PrimitiveType {
return DECIMAL64;
} else if (precision <= getMaxPrecisionOfDecimal(DECIMAL128)) {
return DECIMAL128;
} else if (precision <= getMaxPrecisionOfDecimal(DECIMAL256)) {
return DECIMAL256;
}
Preconditions.checkState(type.isDecimalOfAnyVersion());
return type;

View File

@ -385,7 +385,9 @@ public class ScalarType extends Type implements Cloneable {
int integerPartWidth = Math.max(lhsIntegerPartWidth, rhsIntegerPartWidth);
int scale = Math.max(lhsScale, rhsScale);
int precision = integerPartWidth + scale;
if (precision > 38) {
boolean hasDecimal256 = lhs.isDecimal256() || rhs.isDecimal256();
// TODO(stephen): support auto scale up decimal precision
if ((precision > 38 && !hasDecimal256) || (precision > 76)) {
return ScalarType.DOUBLE;
} else {
// the common type's PrimitiveType of two decimal types should wide enough, i.e
@ -422,6 +424,7 @@ public class ScalarType extends Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return getCommonTypeForDecimalV3(decimalType, otherType);
case BOOLEAN:

View File

@ -318,6 +318,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[TINYINT.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[TINYINT.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[TINYINT.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[TINYINT.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[TINYINT.ordinal()][JSON.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[TINYINT.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -340,6 +341,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[SMALLINT.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[SMALLINT.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[SMALLINT.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[SMALLINT.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[SMALLINT.ordinal()][JSON.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[SMALLINT.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -360,6 +362,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[INT.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[INT.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[INT.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[INT.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[INT.ordinal()][JSON.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[INT.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -380,6 +383,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[BIGINT.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[BIGINT.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[BIGINT.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[BIGINT.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[BIGINT.ordinal()][JSON.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[BIGINT.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -398,6 +402,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[LARGEINT.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.DECIMAL32;
compatibilityMatrix[LARGEINT.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.DECIMAL64;
compatibilityMatrix[LARGEINT.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.DECIMAL128;
compatibilityMatrix[LARGEINT.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.DECIMAL256;
compatibilityMatrix[LARGEINT.ordinal()][JSON.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[LARGEINT.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -415,6 +420,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[FLOAT.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[FLOAT.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[FLOAT.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[FLOAT.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[FLOAT.ordinal()][JSON.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[FLOAT.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -431,6 +437,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[DOUBLE.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DOUBLE.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DOUBLE.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DOUBLE.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DOUBLE.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// DATE
@ -471,6 +478,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[CHAR.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[CHAR.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[CHAR.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[CHAR.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[CHAR.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// VARCHAR
@ -482,6 +490,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[VARCHAR.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[VARCHAR.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[VARCHAR.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[VARCHAR.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[VARCHAR.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// DECIMALV2
@ -502,6 +511,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[DECIMAL32.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.DECIMAL32;
compatibilityMatrix[DECIMAL32.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.DECIMAL64;
compatibilityMatrix[DECIMAL32.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.DECIMAL128;
compatibilityMatrix[DECIMAL32.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.DECIMAL256;
compatibilityMatrix[DECIMAL32.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// DECIMAL64
@ -512,6 +522,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[DECIMAL64.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.DECIMAL32;
compatibilityMatrix[DECIMAL64.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.DECIMAL64;
compatibilityMatrix[DECIMAL64.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.DECIMAL128;
compatibilityMatrix[DECIMAL64.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.DECIMAL256;
compatibilityMatrix[DECIMAL64.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// DECIMAL128
@ -524,6 +535,16 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[DECIMAL128.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.DECIMAL128;
compatibilityMatrix[DECIMAL128.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// DECIMAL256
compatibilityMatrix[DECIMAL256.ordinal()][HLL.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DECIMAL256.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DECIMAL256.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DECIMAL256.ordinal()][PERCENTILE.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[DECIMAL256.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.DECIMAL32;
compatibilityMatrix[DECIMAL256.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.DECIMAL64;
compatibilityMatrix[DECIMAL256.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.DECIMAL128;
compatibilityMatrix[DECIMAL256.ordinal()][UNKNOWN_TYPE.ordinal()] = PrimitiveType.INVALID_TYPE;
// HLL
compatibilityMatrix[HLL.ordinal()][TIME.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[HLL.ordinal()][BITMAP.ordinal()] = PrimitiveType.INVALID_TYPE;
@ -556,6 +577,7 @@ public abstract class Type implements Cloneable {
compatibilityMatrix[JSON.ordinal()][DECIMAL32.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[JSON.ordinal()][DECIMAL64.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[JSON.ordinal()][DECIMAL128.ordinal()] = PrimitiveType.INVALID_TYPE;
compatibilityMatrix[JSON.ordinal()][DECIMAL256.ordinal()] = PrimitiveType.INVALID_TYPE;
// binary type
for (PrimitiveType type : PrimitiveType.BINARY_INCOMPATIBLE_TYPE_LIST) {
@ -695,6 +717,10 @@ public abstract class Type implements Cloneable {
return isDecimalV2() || isDecimalV3();
}
public boolean isDecimal256() {
return this.getPrimitiveType() == PrimitiveType.DECIMAL256;
}
public boolean isStringType() {
return PrimitiveType.STRING_TYPE_LIST.contains(this.getPrimitiveType());
}
@ -760,6 +786,8 @@ public abstract class Type implements Cloneable {
return Type.DECIMAL64;
case DECIMAL128:
return Type.DECIMAL128;
case DECIMAL256:
return Type.DECIMAL256;
case JSON:
return Type.JSON;
case FUNCTION:
@ -1283,7 +1311,8 @@ public abstract class Type implements Cloneable {
scalarType.getScale());
} else if (scalarType.getType() == TPrimitiveType.DECIMAL32 ||
scalarType.getType() == TPrimitiveType.DECIMAL64 ||
scalarType.getType() == TPrimitiveType.DECIMAL128) {
scalarType.getType() == TPrimitiveType.DECIMAL128 ||
scalarType.getType() == TPrimitiveType.DECIMAL256) {
Preconditions.checkState(scalarType.isSetPrecision() && scalarType.isSetScale());
type = ScalarType.createDecimalV3Type(
PrimitiveType.fromThrift(scalarType.getType()),
@ -1446,6 +1475,7 @@ public abstract class Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return t.decimalPrecision();
default:
return null;
@ -1478,6 +1508,7 @@ public abstract class Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return t.decimalScale();
default:
return null;
@ -1512,6 +1543,7 @@ public abstract class Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return this;
case FUNCTION:
return FUNCTION;
@ -1586,6 +1618,7 @@ public abstract class Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return this;
default:
return Type.INVALID;
@ -1640,6 +1673,7 @@ public abstract class Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
// precision + (scale > 0 ? 1 : 0) + (unsigned_flag || !precision ? 0 : 1));
ScalarType decimalType = (ScalarType) this;
int length = decimalType.getScalarPrecision();
@ -1690,6 +1724,7 @@ public abstract class Type implements Cloneable {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return ((ScalarType) this).getScalarScale();
case FLOAT:
case DOUBLE:

View File

@ -416,6 +416,7 @@ public class FeExecuteCoordinator extends Coordinator {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
int scale = ((ScalarType) constantOperator.getType()).getScalarScale();
BigDecimal val1 = constantOperator.getDecimal();
DecimalFormat df = new DecimalFormat((scale == 0 ? "0" : "0.") + StringUtils.repeat("0", scale));

View File

@ -1257,7 +1257,8 @@ public class AnalyzerUtils {
if (convertDouble) {
newType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, 38, 9);
}
} else if (PrimitiveType.DECIMAL128 == srcType.getPrimitiveType() ||
} else if (PrimitiveType.DECIMAL256 == srcType.getPrimitiveType() ||
PrimitiveType.DECIMAL128 == srcType.getPrimitiveType() ||
PrimitiveType.DECIMAL64 == srcType.getPrimitiveType() ||
PrimitiveType.DECIMAL32 == srcType.getPrimitiveType()) {
newType = ScalarType.createDecimalV3Type(srcType.getPrimitiveType(),

View File

@ -94,8 +94,9 @@ public class DecimalV3FunctionAnalyzer {
.add(FunctionSet.MULTI_DISTINCT_SUM).build();
private static final ScalarType DECIMAL128P38S0 = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, 38, 0);
private static final ScalarType DECIMAL256P76S0 = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL256, 76, 0);
// For decimal32/64/128 types, normalize argType's scale and precision
// For decimal32/64/128/256 types, normalize argType's scale and precision
private static Type[] normalizeDecimalArgTypes(final Type[] argTypes, String fnName) {
if (argTypes == null || argTypes.length == 0) {
return argTypes;
@ -230,12 +231,17 @@ public class DecimalV3FunctionAnalyzer {
// avg on decimal complies with Snowflake-style
// avg actual processed like sum()/count(), it also has a risk of overflow if the scale is too large,
// so we limit the maximum scale for this case
if (((ScalarType) argType).getScalarScale() > 18) {
int scale = ((ScalarType) argType).getScalarScale();
ScalarType rhsType = argType.isDecimal256() ? DECIMAL256P76S0 : DECIMAL128P38S0;
if (argType.isDecimal256() && scale > 36) {
argType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL256, 76, 36);
} else if (!argType.isDecimal256() && scale > 18) {
argType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, 38, 18);
}
final ArithmeticExpr.TypeTriple triple =
ArithmeticExpr.getReturnTypeOfDecimal(ArithmeticExpr.Operator.DIVIDE, (ScalarType) argType,
DECIMAL128P38S0);
ArithmeticExpr.getReturnTypeOfDecimal(ArithmeticExpr.Operator.DIVIDE, (ScalarType) argType, rhsType);
returnType = triple.returnType;
} else if (fn.functionName().equals(FunctionSet.APPROX_TOP_K)) {
returnType = FunctionSet.APPROX_TOP_N_RET_TYPE_BUILDER.apply(argType);
@ -244,7 +250,11 @@ public class DecimalV3FunctionAnalyzer {
} else if (argType.isDecimalV3() && DECIMAL_SUM_FUNCTION_TYPE.contains(fn.functionName())) {
// For decimal aggregation sum, there is a risk of overflow if the scale is too large,
// so we limit the maximum scale for this case
if (((ScalarType) argType).getScalarScale() > 18) {
int scale = ((ScalarType) argType).getScalarScale();
if (argType.isDecimal256() && scale > 36) {
argType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL256, 76, 36);
returnType = argType;
} else if (!argType.isDecimal256() && scale > 18) {
argType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, 38, 18);
returnType = argType;
}
@ -278,10 +288,13 @@ public class DecimalV3FunctionAnalyzer {
if (!argType.isDecimalV3()) {
return fn;
}
ScalarType decimal128Type =
ScalarType decimalType =
ScalarType.createDecimalV3NarrowestType(38, ((ScalarType) argType).getScalarScale());
if (argType.isDecimal256()) {
decimalType = ScalarType.createDecimalV3NarrowestType(76, ((ScalarType) argType).getScalarScale());
}
AggregateFunction newFn = new AggregateFunction(
fn.getFunctionName(), Arrays.asList(sumFn.getArgs()), decimal128Type,
fn.getFunctionName(), Arrays.asList(sumFn.getArgs()), decimalType,
fn.getIntermediateType(), fn.hasVarArgs());
newFn.setFunctionId(fn.getFunctionId());
@ -302,10 +315,14 @@ public class DecimalV3FunctionAnalyzer {
}
ScalarType decimalType = (ScalarType) argType;
AggregateFunction fn = (AggregateFunction) sumFn;
ScalarType decimal128Type = ScalarType.createDecimalV3Type(
ScalarType retType = ScalarType.createDecimalV3Type(
PrimitiveType.DECIMAL128, 38, decimalType.getScalarScale());
// TODO(stephen): support auto scale up decimal precision
if (argType.isDecimal256()) {
retType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL256, 76, decimalType.getScalarScale());
}
AggregateFunction newFn = new AggregateFunction(
fn.getFunctionName(), Collections.singletonList(decimalType), decimal128Type,
fn.getFunctionName(), Collections.singletonList(decimalType), retType,
fn.getIntermediateType(), fn.hasVarArgs());
newFn.setFunctionId(fn.getFunctionId());
newFn.setChecksum(fn.getChecksum());
@ -421,10 +438,16 @@ public class DecimalV3FunctionAnalyzer {
} else if (DECIMAL_AGG_FUNCTION_WIDER_TYPE.contains(fnName) && argumentTypes[0].isDecimalV3()) {
ScalarType argScalarType = (ScalarType) argumentTypes[0];
int precision = PrimitiveType.getMaxPrecisionOfDecimal(PrimitiveType.DECIMAL128);
if (argScalarType.isDecimal256()) {
precision = PrimitiveType.getMaxPrecisionOfDecimal(PrimitiveType.DECIMAL256);
}
int scale = argScalarType.getScalarScale();
// TODO(by satanson): Maybe accumulating narrower decimal types to wider decimal types directly w/o
// casting the narrower type to the wider type is sound and efficient.
commonType = ScalarType.createDecimalV3Type(PrimitiveType.DECIMAL128, precision, scale);
PrimitiveType commonPrimitiveType = argScalarType.isDecimal256() ? PrimitiveType.DECIMAL256 :
PrimitiveType.DECIMAL128;
commonType = ScalarType.createDecimalV3Type(commonPrimitiveType, precision, scale);
}
Type argType = argumentTypes[0];

View File

@ -459,6 +459,7 @@ public class ColumnDef implements ParseNode {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
DecimalLiteral decimalLiteral = new DecimalLiteral(defaultValue);
decimalLiteral.checkPrecisionAndScale(scalarType,
scalarType.getScalarPrecision(), scalarType.getScalarScale());

View File

@ -285,6 +285,10 @@ public class TypeManager {
if (ConnectContext.get() != null && SessionVariableConstants.DECIMAL.equalsIgnoreCase(ConnectContext.get()
.getSessionVariable().getCboEqBaseType())) {
baseType = Type.DEFAULT_DECIMAL128;
// TODO(stephen): support auto scale up decimal precision
if (type1.isDecimal256() || type2.isDecimal256()) {
baseType = Type.DEFAULT_DECIMAL256;
}
if (type1.isDecimalOfAnyVersion() || type2.isDecimalOfAnyVersion()) {
baseType = type1.isDecimalOfAnyVersion() ? type1 : type2;
}

View File

@ -500,6 +500,7 @@ public class ColumnFilterConverter {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
literalExpr = new DecimalLiteral(operator.getDecimal());
break;
case CHAR:

View File

@ -92,6 +92,7 @@ import static com.starrocks.catalog.PrimitiveType.BOOLEAN;
import static com.starrocks.catalog.PrimitiveType.DATE;
import static com.starrocks.catalog.PrimitiveType.DATETIME;
import static com.starrocks.catalog.PrimitiveType.DECIMAL128;
import static com.starrocks.catalog.PrimitiveType.DECIMAL256;
import static com.starrocks.catalog.PrimitiveType.DECIMAL32;
import static com.starrocks.catalog.PrimitiveType.DECIMAL64;
import static com.starrocks.catalog.PrimitiveType.DECIMALV2;
@ -1037,7 +1038,8 @@ public class ScalarOperatorFunctions {
@ConstantFunction(name = "add", argTypes = {DECIMALV2, DECIMALV2}, returnType = DECIMALV2),
@ConstantFunction(name = "add", argTypes = {DECIMAL32, DECIMAL32}, returnType = DECIMAL32),
@ConstantFunction(name = "add", argTypes = {DECIMAL64, DECIMAL64}, returnType = DECIMAL64),
@ConstantFunction(name = "add", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128)
@ConstantFunction(name = "add", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128),
@ConstantFunction(name = "add", argTypes = {DECIMAL256, DECIMAL256}, returnType = DECIMAL256)
})
public static ConstantOperator addDecimal(ConstantOperator first, ConstantOperator second) {
return createDecimalConstant(first.getDecimal().add(second.getDecimal()));
@ -1072,7 +1074,8 @@ public class ScalarOperatorFunctions {
@ConstantFunction(name = "subtract", argTypes = {DECIMALV2, DECIMALV2}, returnType = DECIMALV2),
@ConstantFunction(name = "subtract", argTypes = {DECIMAL32, DECIMAL32}, returnType = DECIMAL32),
@ConstantFunction(name = "subtract", argTypes = {DECIMAL64, DECIMAL64}, returnType = DECIMAL64),
@ConstantFunction(name = "subtract", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128)
@ConstantFunction(name = "subtract", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128),
@ConstantFunction(name = "subtract", argTypes = {DECIMAL256, DECIMAL256}, returnType = DECIMAL256)
})
public static ConstantOperator subtractDecimal(ConstantOperator first, ConstantOperator second) {
return createDecimalConstant(first.getDecimal().subtract(second.getDecimal()));
@ -1103,11 +1106,13 @@ public class ScalarOperatorFunctions {
return ConstantOperator.createDouble(first.getDouble() * second.getDouble());
}
// TODO(stephen): support auto scale up decimal precision
@ConstantFunction.List(list = {
@ConstantFunction(name = "multiply", argTypes = {DECIMALV2, DECIMALV2}, returnType = DECIMALV2),
@ConstantFunction(name = "multiply", argTypes = {DECIMAL32, DECIMAL32}, returnType = DECIMAL32),
@ConstantFunction(name = "multiply", argTypes = {DECIMAL64, DECIMAL64}, returnType = DECIMAL64),
@ConstantFunction(name = "multiply", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128)
@ConstantFunction(name = "multiply", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128),
@ConstantFunction(name = "multiply", argTypes = {DECIMAL256, DECIMAL256}, returnType = DECIMAL256)
})
public static ConstantOperator multiplyDecimal(ConstantOperator first, ConstantOperator second) {
return createDecimalConstant(first.getDecimal().multiply(second.getDecimal()));
@ -1130,7 +1135,8 @@ public class ScalarOperatorFunctions {
@ConstantFunction(name = "divide", argTypes = {DECIMALV2, DECIMALV2}, returnType = DECIMALV2),
@ConstantFunction(name = "divide", argTypes = {DECIMAL32, DECIMAL32}, returnType = DECIMAL32),
@ConstantFunction(name = "divide", argTypes = {DECIMAL64, DECIMAL64}, returnType = DECIMAL64),
@ConstantFunction(name = "divide", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128)
@ConstantFunction(name = "divide", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128),
@ConstantFunction(name = "divide", argTypes = {DECIMAL256, DECIMAL256}, returnType = DECIMAL256)
})
public static ConstantOperator divideDecimal(ConstantOperator first, ConstantOperator second) {
if (BigDecimal.ZERO.compareTo(second.getDecimal()) == 0) {
@ -1208,7 +1214,8 @@ public class ScalarOperatorFunctions {
@ConstantFunction(name = "mod", argTypes = {DECIMALV2, DECIMALV2}, returnType = DECIMALV2),
@ConstantFunction(name = "mod", argTypes = {DECIMAL32, DECIMAL32}, returnType = DECIMAL32),
@ConstantFunction(name = "mod", argTypes = {DECIMAL64, DECIMAL64}, returnType = DECIMAL64),
@ConstantFunction(name = "mod", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128)
@ConstantFunction(name = "mod", argTypes = {DECIMAL128, DECIMAL128}, returnType = DECIMAL128),
@ConstantFunction(name = "mod", argTypes = {DECIMAL256, DECIMAL256}, returnType = DECIMAL256)
})
public static ConstantOperator modDecimal(ConstantOperator first, ConstantOperator second) {
if (BigDecimal.ZERO.compareTo(second.getDecimal()) == 0) {

View File

@ -242,6 +242,7 @@ public class FilterSelectivityEvaluator {
case DECIMAL32:
case DECIMAL64:
case DECIMAL128:
case DECIMAL256:
return true;
default:
return false;

View File

@ -282,9 +282,12 @@ public class MultiDistinctByCTERewriter {
if (avgCallOperator.getType().isDecimalV3()) {
// There is not need to apply ImplicitCastRule to divide operator of decimal types.
// but we should cast BIGINT-typed countColRef into DECIMAL(38,0).
ScalarType decimal128p38s0 = ScalarType.createDecimalV3NarrowestType(38, 0);
ScalarType decimalType = ScalarType.createDecimalV3NarrowestType(38, 0);
if (avgCallOperator.getType().isDecimal256()) {
decimalType = ScalarType.createDecimalV3NarrowestType(76, 0);
}
distinctAvgCallOperator.getChildren().set(
1, new CastOperator(decimal128p38s0, distinctAvgCallOperator.getChild(1), true));
1, new CastOperator(decimalType, distinctAvgCallOperator.getChild(1), true));
} else {
distinctAvgCallOperator = (CallOperator) scalarRewriter.rewrite(distinctAvgCallOperator,
Lists.newArrayList(new ImplicitCastRule()));

View File

@ -119,9 +119,12 @@ public class MultiDistinctByMultiFuncRewriter {
if (multiAvg.getType().isDecimalV3()) {
// There is not need to apply ImplicitCastRule to divide operator of decimal types.
// but we should cast BIGINT-typed countColRef into DECIMAL(38,0).
ScalarType decimal128p38s0 = ScalarType.createDecimalV3NarrowestType(38, 0);
ScalarType decimalType = ScalarType.createDecimalV3NarrowestType(38, 0);
if (multiAvg.getType().isDecimal256()) {
decimalType = ScalarType.createDecimalV3NarrowestType(76, 0);
}
multiAvg.getChildren().set(
1, new CastOperator(decimal128p38s0, multiAvg.getChild(1), true));
1, new CastOperator(decimalType, multiAvg.getChild(1), true));
} else {
multiAvg = (CallOperator) scalarRewriter.rewrite(multiAvg,
Lists.newArrayList(new ImplicitCastRule()));

View File

@ -46,6 +46,7 @@ vectorized_functions = [
[100470, "abs", True, False, "DECIMAL32", ["DECIMAL32"], "MathFunctions::abs_decimal32"],
[100471, "abs", True, False, "DECIMAL64", ["DECIMAL64"], "MathFunctions::abs_decimal64"],
[100472, "abs", True, False, "DECIMAL128", ["DECIMAL128"], "MathFunctions::abs_decimal128"],
[100473, "abs", True, False, "DECIMAL256", ["DECIMAL256"], "MathFunctions::abs_decimal256"],
[10050, "sin", True, False, "DOUBLE", ["DOUBLE"], "MathFunctions::sin"],
[10060, "asin", True, False, "DOUBLE", ["DOUBLE"], "MathFunctions::asin"],

View File

@ -0,0 +1,667 @@
-- name: test_decimal256_aggregate_function
DROP DATABASE IF EXISTS test_decimal256_agg_func;
-- result:
-- !result
CREATE DATABASE test_decimal256_agg_func;
-- result:
-- !result
USE test_decimal256_agg_func;
-- result:
-- !result
DROP TABLE IF EXISTS decimal256_agg_test;
-- result:
-- !result
CREATE TABLE decimal256_agg_test (
id INT,
category VARCHAR(10),
p40s10 DECIMAL(40,10), -- 30 integer digits + 10 decimal digits
p50s15 DECIMAL(50,15), -- 35 integer digits + 15 decimal digits
p76s20 DECIMAL(76,20), -- 56 integer digits + 20 decimal digits
p76s0 DECIMAL(76,0) -- 76 integer digits + 0 decimal digits
) properties("replication_num"="1");
-- result:
-- !result
INSERT INTO decimal256_agg_test VALUES
(1, 'A', 100.1234567890, 100.123456789012345, 100.12345678901234567890, 100),
(2, 'A', 100.1234567890, 100.123456789012345, 100.12345678901234567890, 100),
(3, 'A', 100.1234567890, 100.123456789012345, 100.12345678901234567890, 100),
(4, 'B', 200.5555555555, 200.555555555555555, 200.55555555555555555555, 200),
(5, 'B', 200.5555555555, 200.555555555555555, 200.55555555555555555555, 200),
(6, 'C', 0.0000000000, 0.000000000000000, 0.00000000000000000000, 0),
(7, 'C', 0.0000000000, 0.000000000000000, 0.00000000000000000000, 0),
(8, 'C', 0.0000000000, 0.000000000000000, 0.00000000000000000000, 0),
(9, 'D', -50.9876543210, -50.987654321098765, -50.98765432109876543210, -50),
(10, 'D', -50.9876543210, -50.987654321098765, -50.98765432109876543210, -50),
(11, 'E', 300.1111111111, 300.111111111111111, 300.11111111111111111111, 300),
(12, 'F', 400.2222222222, 400.222222222222222, 400.22222222222222222222, 400),
(13, 'G', 500.3333333333, 500.333333333333333, 500.33333333333333333333, 500),
(14, 'H', 999999999999999999999999999999.9999999999,
99999999999999999999999999999999999.999999999999999,
99999999999999999999999999999999999999999999999999999999.99999999999999999999,
9999999999999999999999999999999999999999999999999999999999999999999999999999),
(15, 'H', 999999999999999999999999999999.9999999999,
99999999999999999999999999999999999.999999999999999,
99999999999999999999999999999999999999999999999999999999.99999999999999999999,
9999999999999999999999999999999999999999999999999999999999999999999999999999),
(16, 'I', 0.0000000001, 0.000000000000001, 0.00000000000000000001, 1),
(17, 'I', 0.0000000001, 0.000000000000001, 0.00000000000000000001, 1),
(18, 'J', NULL, NULL, NULL, NULL),
(19, 'J', 600.4444444444, 600.444444444444444, 600.44444444444444444444, 600),
(20, 'K', 777.7777777777, 777.777777777777777, 777.77777777777777777777, 777),
(21, 'K', 777.7777777777, 888.888888888888888, 999.99999999999999999999, 777),
(22, 'K', 777.7777777777, 777.777777777777777, 777.77777777777777777777, 888);
-- result:
-- !result
SELECT 'Test1_COUNT_BASIC' as test_name, COUNT(*) as total_rows FROM decimal256_agg_test;
-- result:
Test1_COUNT_BASIC 22
-- !result
SELECT
'Test1_COUNT_NON_NULL' as test_name,
COUNT(p40s10) as count_p40s10,
COUNT(p50s15) as count_p50s15,
COUNT(p76s20) as count_p76s20,
COUNT(p76s0) as count_p76s0
FROM decimal256_agg_test;
-- result:
Test1_COUNT_NON_NULL 21 21 21 21
-- !result
SELECT
'Test2_SUM' as test_name,
SUM(p40s10) as sum_p40s10,
SUM(p50s15) as sum_p50s15,
SUM(p76s20) as sum_p76s20,
SUM(p76s0) as sum_p76s0
FROM decimal256_agg_test;
-- result:
Test2_SUM 2000000000000000000000000004733.9506172801 200000000000000000000000000000004845.061728391506167 200000000000000000000000000000000000000000000000000004956.17283950261728395023 20000000000000000000000000000000000000000000000000000000000000000000000004842
-- !result
SELECT
'Test3_AVG' as test_name,
AVG(p40s10) as avg_p40s10,
AVG(p50s15) as avg_p50s15,
AVG(p76s20) as avg_p76s20,
AVG(p76s0) as avg_p76s0
FROM decimal256_agg_test;
-- result:
Test3_AVG 95238095238095238095238095463.521457965719 9523809523809523809523809523809754.526748971024103 9523809523809523809523809523809523809523809523809524045.53203997631510875953 2046222049275135930893159257071040935639933169755114893700828629548287.777822
-- !result
SELECT
'Test4_MIN_MAX' as test_name,
MIN(p40s10) as min_p40s10,
MAX(p40s10) as max_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p50s15) as max_p50s15,
MIN(p76s20) as min_p76s20,
MAX(p76s20) as max_p76s20,
MIN(p76s0) as min_p76s0,
MAX(p76s0) as max_p76s0
FROM decimal256_agg_test;
-- result:
Test4_MIN_MAX -50.9876543210 999999999999999999999999999999.9999999999 -50.987654321098765 99999999999999999999999999999999999.999999999999999 -50.98765432109876543210 99999999999999999999999999999999999999999999999999999999.99999999999999999999 -50 9999999999999999999999999999999999999999999999999999999999999999999999999999
-- !result
SELECT
'Test5_GROUP_BY_CATEGORY' as test_name,
category,
COUNT(*) as row_count,
SUM(p40s10) as sum_p40s10,
AVG(p40s10) as avg_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p76s20) as max_p76s20
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test5_GROUP_BY_CATEGORY A 3 300.3703703670 100.123456789000 100.123456789012345 100.12345678901234567890
Test5_GROUP_BY_CATEGORY B 2 401.1111111110 200.555555555500 200.555555555555555 200.55555555555555555555
Test5_GROUP_BY_CATEGORY C 3 0E-10 0E-12 0E-15 0E-20
Test5_GROUP_BY_CATEGORY D 2 -101.9753086420 -50.987654321000 -50.987654321098765 -50.98765432109876543210
Test5_GROUP_BY_CATEGORY E 1 300.1111111111 300.111111111100 300.111111111111111 300.11111111111111111111
Test5_GROUP_BY_CATEGORY F 1 400.2222222222 400.222222222200 400.222222222222222 400.22222222222222222222
Test5_GROUP_BY_CATEGORY G 1 500.3333333333 500.333333333300 500.333333333333333 500.33333333333333333333
Test5_GROUP_BY_CATEGORY H 2 1999999999999999999999999999999.9999999998 999999999999999999999999999999.999999999900 99999999999999999999999999999999999.999999999999999 99999999999999999999999999999999999999999999999999999999.99999999999999999999
Test5_GROUP_BY_CATEGORY I 2 2E-10 1.00E-10 1E-15 1E-20
Test5_GROUP_BY_CATEGORY J 2 600.4444444444 600.444444444400 600.444444444444444 600.44444444444444444444
Test5_GROUP_BY_CATEGORY K 3 2333.3333333331 777.777777777700 777.777777777777777 999.99999999999999999999
-- !result
SELECT
'Test6_GROUP_BY_P40S10' as test_name,
p40s10,
COUNT(*) as row_count,
SUM(p50s15) as sum_p50s15,
AVG(p50s15) as avg_p50s15,
MIN(p76s0) as min_p76s0,
MAX(p76s0) as max_p76s0
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
GROUP BY p40s10
ORDER BY p40s10;
-- result:
Test6_GROUP_BY_P40S10 -50.9876543210 2 -101.975308642197530 -50.987654321098765 -50 -50
Test6_GROUP_BY_P40S10 0E-10 3 0E-15 0E-15 0 0
Test6_GROUP_BY_P40S10 1E-10 2 2E-15 1E-15 1 1
Test6_GROUP_BY_P40S10 100.1234567890 3 300.370370367037035 100.123456789012345 100 100
Test6_GROUP_BY_P40S10 200.5555555555 2 401.111111111111110 200.555555555555555 200 200
Test6_GROUP_BY_P40S10 300.1111111111 1 300.111111111111111 300.111111111111111 300 300
Test6_GROUP_BY_P40S10 400.2222222222 1 400.222222222222222 400.222222222222222 400 400
Test6_GROUP_BY_P40S10 500.3333333333 1 500.333333333333333 500.333333333333333 500 500
Test6_GROUP_BY_P40S10 600.4444444444 1 600.444444444444444 600.444444444444444 600 600
Test6_GROUP_BY_P40S10 777.7777777777 3 2444.444444444444442 814.814814814814814 777 888
Test6_GROUP_BY_P40S10 999999999999999999999999999999.9999999999 2 199999999999999999999999999999999999.999999999999998 99999999999999999999999999999999999.999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test7_COUNT_DISTINCT_planner0' as test_name,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p50s15) as distinct_p50s15,
COUNT(DISTINCT p76s20) as distinct_p76s20,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test7_COUNT_DISTINCT_planner0 11 12 12 12
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test7_COUNT_DISTINCT_planner2' as test_name,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p50s15) as distinct_p50s15,
COUNT(DISTINCT p76s20) as distinct_p76s20,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test7_COUNT_DISTINCT_planner2 11 12 12 12
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test8_SUM_DISTINCT_planner0' as test_name,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15,
SUM(DISTINCT p76s20) as sum_distinct_p76s20,
SUM(DISTINCT p76s0) as sum_distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test8_SUM_DISTINCT_planner0 1000000000000000000000000002828.5802469122 100000000000000000000000000000003717.469135801246910 100000000000000000000000000000000000000000000000000003828.58024691235802469121 10000000000000000000000000000000000000000000000000000000000000000000000003715
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test8_SUM_DISTINCT_planner2' as test_name,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15,
SUM(DISTINCT p76s20) as sum_distinct_p76s20,
SUM(DISTINCT p76s0) as sum_distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test8_SUM_DISTINCT_planner2 1000000000000000000000000002828.5802469122 100000000000000000000000000000003717.469135801246910 100000000000000000000000000000000000000000000000000003828.58024691235802469121 10000000000000000000000000000000000000000000000000000000000000000000000003715
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test9_AVG_DISTINCT_planner0' as test_name,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p50s15) as avg_distinct_p50s15,
AVG(DISTINCT p76s20) as avg_distinct_p76s20,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test9_AVG_DISTINCT_planner0 90909090909090909090909091166.234567901109 8333333333333333333333333333333643.122427983437243 8333333333333333333333333333333333333333333333333333652.38168724269650205760 None
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test9_AVG_DISTINCT_planner2' as test_name,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p50s15) as avg_distinct_p50s15,
AVG(DISTINCT p76s20) as avg_distinct_p76s20,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test9_AVG_DISTINCT_planner2 90909090909090909090909091166.234567901109 8333333333333333333333333333333643.122427983437243 8333333333333333333333333333333333333333333333333333652.38168724269650205760 None
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test10_GROUP_COUNT_DISTINCT_planner0' as test_name,
category,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test10_GROUP_COUNT_DISTINCT_planner0 A 3 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 B 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 C 3 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 D 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 E 1 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 F 1 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 G 1 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 H 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 I 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 J 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner0 K 3 1 2
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test10_GROUP_COUNT_DISTINCT_planner2' as test_name,
category,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test10_GROUP_COUNT_DISTINCT_planner2 A 3 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 B 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 C 3 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 D 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 E 1 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 F 1 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 G 1 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 H 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 I 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 J 2 1 1
Test10_GROUP_COUNT_DISTINCT_planner2 K 3 1 2
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test11_GROUP_SUM_DISTINCT_planner0' as test_name,
category,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test11_GROUP_SUM_DISTINCT_planner0 A 100.1234567890 100.123456789012345
Test11_GROUP_SUM_DISTINCT_planner0 B 200.5555555555 200.555555555555555
Test11_GROUP_SUM_DISTINCT_planner0 C 0E-10 0E-15
Test11_GROUP_SUM_DISTINCT_planner0 D -50.9876543210 -50.987654321098765
Test11_GROUP_SUM_DISTINCT_planner0 E 300.1111111111 300.111111111111111
Test11_GROUP_SUM_DISTINCT_planner0 F 400.2222222222 400.222222222222222
Test11_GROUP_SUM_DISTINCT_planner0 G 500.3333333333 500.333333333333333
Test11_GROUP_SUM_DISTINCT_planner0 H 999999999999999999999999999999.9999999999 99999999999999999999999999999999999.999999999999999
Test11_GROUP_SUM_DISTINCT_planner0 I 1E-10 1E-15
Test11_GROUP_SUM_DISTINCT_planner0 J 600.4444444444 600.444444444444444
Test11_GROUP_SUM_DISTINCT_planner0 K 777.7777777777 1666.666666666666665
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test11_GROUP_SUM_DISTINCT_planner2' as test_name,
category,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test11_GROUP_SUM_DISTINCT_planner2 A 100.1234567890 100.123456789012345
Test11_GROUP_SUM_DISTINCT_planner2 B 200.5555555555 200.555555555555555
Test11_GROUP_SUM_DISTINCT_planner2 C 0E-10 0E-15
Test11_GROUP_SUM_DISTINCT_planner2 D -50.9876543210 -50.987654321098765
Test11_GROUP_SUM_DISTINCT_planner2 E 300.1111111111 300.111111111111111
Test11_GROUP_SUM_DISTINCT_planner2 F 400.2222222222 400.222222222222222
Test11_GROUP_SUM_DISTINCT_planner2 G 500.3333333333 500.333333333333333
Test11_GROUP_SUM_DISTINCT_planner2 H 999999999999999999999999999999.9999999999 99999999999999999999999999999999999.999999999999999
Test11_GROUP_SUM_DISTINCT_planner2 I 1E-10 1E-15
Test11_GROUP_SUM_DISTINCT_planner2 J 600.4444444444 600.444444444444444
Test11_GROUP_SUM_DISTINCT_planner2 K 777.7777777777 1666.666666666666665
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test12_GROUP_AVG_DISTINCT_planner0' as test_name,
category,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test12_GROUP_AVG_DISTINCT_planner0 A 100.123456789000 100.000000
Test12_GROUP_AVG_DISTINCT_planner0 B 200.555555555500 200.000000
Test12_GROUP_AVG_DISTINCT_planner0 C 0E-12 0.000000
Test12_GROUP_AVG_DISTINCT_planner0 D -50.987654321000 -50.000000
Test12_GROUP_AVG_DISTINCT_planner0 E 300.111111111100 300.000000
Test12_GROUP_AVG_DISTINCT_planner0 F 400.222222222200 400.000000
Test12_GROUP_AVG_DISTINCT_planner0 G 500.333333333300 500.000000
Test12_GROUP_AVG_DISTINCT_planner0 H 999999999999999999999999999999.999999999900 None
Test12_GROUP_AVG_DISTINCT_planner0 I 1.00E-10 1.000000
Test12_GROUP_AVG_DISTINCT_planner0 J 600.444444444400 600.000000
Test12_GROUP_AVG_DISTINCT_planner0 K 777.777777777700 832.500000
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test12_GROUP_AVG_DISTINCT_planner2' as test_name,
category,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- result:
Test12_GROUP_AVG_DISTINCT_planner2 A 100.123456789000 100.000000
Test12_GROUP_AVG_DISTINCT_planner2 B 200.555555555500 200.000000
Test12_GROUP_AVG_DISTINCT_planner2 C 0E-12 0.000000
Test12_GROUP_AVG_DISTINCT_planner2 D -50.987654321000 -50.000000
Test12_GROUP_AVG_DISTINCT_planner2 E 300.111111111100 300.000000
Test12_GROUP_AVG_DISTINCT_planner2 F 400.222222222200 400.000000
Test12_GROUP_AVG_DISTINCT_planner2 G 500.333333333300 500.000000
Test12_GROUP_AVG_DISTINCT_planner2 H 999999999999999999999999999999.999999999900 None
Test12_GROUP_AVG_DISTINCT_planner2 I 1.00E-10 1.000000
Test12_GROUP_AVG_DISTINCT_planner2 J 600.444444444400 600.000000
Test12_GROUP_AVG_DISTINCT_planner2 K 777.777777777700 832.500000
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test13_GROUP_BY_DECIMAL_DISTINCT_planner0' as test_name,
p76s0,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10
FROM decimal256_agg_test
WHERE p76s0 IS NOT NULL
GROUP BY p76s0
ORDER BY p76s0;
-- result:
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 -50 2 1 -50.9876543210 -50.987654321000
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 0 3 1 0E-10 0E-12
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 1 2 1 1E-10 1.00E-10
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 100 3 1 100.1234567890 100.123456789000
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 200 2 1 200.5555555555 200.555555555500
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 300 1 1 300.1111111111 300.111111111100
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 400 1 1 400.2222222222 400.222222222200
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 500 1 1 500.3333333333 500.333333333300
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 600 1 1 600.4444444444 600.444444444400
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 777 2 1 777.7777777777 777.777777777700
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 888 1 1 777.7777777777 777.777777777700
Test13_GROUP_BY_DECIMAL_DISTINCT_planner0 9999999999999999999999999999999999999999999999999999999999999999999999999999 2 1 999999999999999999999999999999.9999999999 999999999999999999999999999999.999999999900
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test13_GROUP_BY_DECIMAL_DISTINCT_planner2' as test_name,
p76s0,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10
FROM decimal256_agg_test
WHERE p76s0 IS NOT NULL
GROUP BY p76s0
ORDER BY p76s0;
-- result:
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 -50 2 1 -50.9876543210 -50.987654321000
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 0 3 1 0E-10 0E-12
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 1 2 1 1E-10 1.00E-10
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 100 3 1 100.1234567890 100.123456789000
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 200 2 1 200.5555555555 200.555555555500
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 300 1 1 300.1111111111 300.111111111100
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 400 1 1 400.2222222222 400.222222222200
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 500 1 1 500.3333333333 500.333333333300
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 600 1 1 600.4444444444 600.444444444400
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 777 2 1 777.7777777777 777.777777777700
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 888 1 1 777.7777777777 777.777777777700
Test13_GROUP_BY_DECIMAL_DISTINCT_planner2 9999999999999999999999999999999999999999999999999999999999999999999999999999 2 1 999999999999999999999999999999.9999999999 999999999999999999999999999999.999999999900
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT DISTINCT 'Test14_SELECT_DISTINCT_SINGLE_planner0' as test_name, p40s10
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10;
-- result:
Test14_SELECT_DISTINCT_SINGLE_planner0 -50.9876543210
Test14_SELECT_DISTINCT_SINGLE_planner0 0E-10
Test14_SELECT_DISTINCT_SINGLE_planner0 1E-10
Test14_SELECT_DISTINCT_SINGLE_planner0 100.1234567890
Test14_SELECT_DISTINCT_SINGLE_planner0 200.5555555555
Test14_SELECT_DISTINCT_SINGLE_planner0 300.1111111111
Test14_SELECT_DISTINCT_SINGLE_planner0 400.2222222222
Test14_SELECT_DISTINCT_SINGLE_planner0 500.3333333333
Test14_SELECT_DISTINCT_SINGLE_planner0 600.4444444444
Test14_SELECT_DISTINCT_SINGLE_planner0 777.7777777777
Test14_SELECT_DISTINCT_SINGLE_planner0 999999999999999999999999999999.9999999999
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT DISTINCT 'Test14_SELECT_DISTINCT_SINGLE_planner2' as test_name, p40s10
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10;
-- result:
Test14_SELECT_DISTINCT_SINGLE_planner2 -50.9876543210
Test14_SELECT_DISTINCT_SINGLE_planner2 0E-10
Test14_SELECT_DISTINCT_SINGLE_planner2 1E-10
Test14_SELECT_DISTINCT_SINGLE_planner2 100.1234567890
Test14_SELECT_DISTINCT_SINGLE_planner2 200.5555555555
Test14_SELECT_DISTINCT_SINGLE_planner2 300.1111111111
Test14_SELECT_DISTINCT_SINGLE_planner2 400.2222222222
Test14_SELECT_DISTINCT_SINGLE_planner2 500.3333333333
Test14_SELECT_DISTINCT_SINGLE_planner2 600.4444444444
Test14_SELECT_DISTINCT_SINGLE_planner2 777.7777777777
Test14_SELECT_DISTINCT_SINGLE_planner2 999999999999999999999999999999.9999999999
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT DISTINCT 'Test15_SELECT_DISTINCT_MULTI_planner0' as test_name, p40s10, p50s15, p76s0
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10, p50s15;
-- result:
Test15_SELECT_DISTINCT_MULTI_planner0 -50.9876543210 -50.987654321098765 -50
Test15_SELECT_DISTINCT_MULTI_planner0 0E-10 0E-15 0
Test15_SELECT_DISTINCT_MULTI_planner0 1E-10 1E-15 1
Test15_SELECT_DISTINCT_MULTI_planner0 100.1234567890 100.123456789012345 100
Test15_SELECT_DISTINCT_MULTI_planner0 200.5555555555 200.555555555555555 200
Test15_SELECT_DISTINCT_MULTI_planner0 300.1111111111 300.111111111111111 300
Test15_SELECT_DISTINCT_MULTI_planner0 400.2222222222 400.222222222222222 400
Test15_SELECT_DISTINCT_MULTI_planner0 500.3333333333 500.333333333333333 500
Test15_SELECT_DISTINCT_MULTI_planner0 600.4444444444 600.444444444444444 600
Test15_SELECT_DISTINCT_MULTI_planner0 777.7777777777 777.777777777777777 777
Test15_SELECT_DISTINCT_MULTI_planner0 777.7777777777 777.777777777777777 888
Test15_SELECT_DISTINCT_MULTI_planner0 777.7777777777 888.888888888888888 777
Test15_SELECT_DISTINCT_MULTI_planner0 999999999999999999999999999999.9999999999 99999999999999999999999999999999999.999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT DISTINCT 'Test15_SELECT_DISTINCT_MULTI_planner2' as test_name, p40s10, p50s15, p76s0
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10, p50s15;
-- result:
Test15_SELECT_DISTINCT_MULTI_planner2 -50.9876543210 -50.987654321098765 -50
Test15_SELECT_DISTINCT_MULTI_planner2 0E-10 0E-15 0
Test15_SELECT_DISTINCT_MULTI_planner2 1E-10 1E-15 1
Test15_SELECT_DISTINCT_MULTI_planner2 100.1234567890 100.123456789012345 100
Test15_SELECT_DISTINCT_MULTI_planner2 200.5555555555 200.555555555555555 200
Test15_SELECT_DISTINCT_MULTI_planner2 300.1111111111 300.111111111111111 300
Test15_SELECT_DISTINCT_MULTI_planner2 400.2222222222 400.222222222222222 400
Test15_SELECT_DISTINCT_MULTI_planner2 500.3333333333 500.333333333333333 500
Test15_SELECT_DISTINCT_MULTI_planner2 600.4444444444 600.444444444444444 600
Test15_SELECT_DISTINCT_MULTI_planner2 777.7777777777 777.777777777777777 777
Test15_SELECT_DISTINCT_MULTI_planner2 777.7777777777 777.777777777777777 888
Test15_SELECT_DISTINCT_MULTI_planner2 777.7777777777 888.888888888888888 777
Test15_SELECT_DISTINCT_MULTI_planner2 999999999999999999999999999999.9999999999 99999999999999999999999999999999999.999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test16_COMPLEX_DISTINCT_planner0' as test_name,
COUNT(DISTINCT p40s10) as count_distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
COUNT(DISTINCT p76s0) as count_distinct_p76s0,
SUM(DISTINCT p76s0) as sum_distinct_p76s0,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test16_COMPLEX_DISTINCT_planner0 11 1000000000000000000000000002828.5802469122 90909090909090909090909091166.234567901109 12 10000000000000000000000000000000000000000000000000000000000000000000000003715 None
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test16_COMPLEX_DISTINCT_planner2' as test_name,
COUNT(DISTINCT p40s10) as count_distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
COUNT(DISTINCT p76s0) as count_distinct_p76s0,
SUM(DISTINCT p76s0) as sum_distinct_p76s0,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
-- result:
Test16_COMPLEX_DISTINCT_planner2 11 1000000000000000000000000002828.5802469122 90909090909090909090909091166.234567901109 12 10000000000000000000000000000000000000000000000000000000000000000000000003715 None
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test17_HAVING_DISTINCT_planner0' as test_name,
p40s10,
COUNT(*) as row_count,
COUNT(DISTINCT p50s15) as distinct_p50s15,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
GROUP BY p40s10
HAVING COUNT(*) > 1
ORDER BY p40s10;
-- result:
Test17_HAVING_DISTINCT_planner0 -50.9876543210 2 1 -50.987654321098765
Test17_HAVING_DISTINCT_planner0 0E-10 3 1 0E-15
Test17_HAVING_DISTINCT_planner0 1E-10 2 1 1E-15
Test17_HAVING_DISTINCT_planner0 100.1234567890 3 1 100.123456789012345
Test17_HAVING_DISTINCT_planner0 200.5555555555 2 1 200.555555555555555
Test17_HAVING_DISTINCT_planner0 777.7777777777 3 2 1666.666666666666665
Test17_HAVING_DISTINCT_planner0 999999999999999999999999999999.9999999999 2 1 99999999999999999999999999999999999.999999999999999
-- !result
set new_planner_agg_stage=2;
-- result:
-- !result
SELECT
'Test17_HAVING_DISTINCT_planner2' as test_name,
p40s10,
COUNT(*) as row_count,
COUNT(DISTINCT p50s15) as distinct_p50s15,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
GROUP BY p40s10
HAVING COUNT(*) > 1
ORDER BY p40s10;
-- result:
Test17_HAVING_DISTINCT_planner2 -50.9876543210 2 1 -50.987654321098765
Test17_HAVING_DISTINCT_planner2 0E-10 3 1 0E-15
Test17_HAVING_DISTINCT_planner2 1E-10 2 1 1E-15
Test17_HAVING_DISTINCT_planner2 100.1234567890 3 1 100.123456789012345
Test17_HAVING_DISTINCT_planner2 200.5555555555 2 1 200.555555555555555
Test17_HAVING_DISTINCT_planner2 777.7777777777 3 2 1666.666666666666665
Test17_HAVING_DISTINCT_planner2 999999999999999999999999999999.9999999999 2 1 99999999999999999999999999999999999.999999999999999
-- !result
set new_planner_agg_stage=0;
-- result:
-- !result
SELECT
'Test18_EMPTY_RESULT' as test_name,
COUNT(*) as count_all,
SUM(p40s10) as sum_p40s10,
AVG(p40s10) as avg_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p76s20) as max_p76s20
FROM decimal256_agg_test
WHERE id > 1000;
-- result:
Test18_EMPTY_RESULT 0 None None None None
-- !result
SELECT
'Test19_NULL_ONLY' as test_name,
COUNT(*) as count_all,
COUNT(p40s10) as count_p40s10,
SUM(p50s15) as sum_p50s15,
AVG(p50s15) as avg_p50s15
FROM decimal256_agg_test
WHERE id = 18;
-- result:
Test19_NULL_ONLY 1 0 None None
-- !result
SELECT
'Test20_SINGLE_ROW' as test_name,
COUNT(*) as count_all,
SUM(p40s10) as sum_p40s10,
AVG(p40s10) as avg_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p76s20) as max_p76s20
FROM decimal256_agg_test
WHERE id = 11;
-- result:
Test20_SINGLE_ROW 1 300.1111111111 300.111111111100 300.111111111111111 300.11111111111111111111
-- !result

View File

@ -0,0 +1,439 @@
-- name: test_decimal256_arithmetic_overflow
DROP DATABASE IF EXISTS test_decimal256_overflow;
-- result:
-- !result
CREATE DATABASE test_decimal256_overflow;
-- result:
-- !result
USE test_decimal256_overflow;
-- result:
-- !result
CREATE TABLE powers_of_2 (
power_250 DECIMAL(76, 0)
) PROPERTIES("replication_num"="1");
-- result:
-- !result
insert into powers_of_2 select 1809251394333065553493296640760748560207343510400633813116524750123642650624;
-- result:
-- !result
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 as string) from powers_of_2;
-- result:
57896044618658097711785492504343953926634992332820282019728792003956564819967
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- result:
--57896044618658097711785492504343953926634992332820282019728792003956564819968
-- !result
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 + 1 as string) from powers_of_2;
-- result:
None
-- !result
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 - 1 as string) from powers_of_2;
-- result:
57896044618658097711785492504343953926634992332820282019728792003956564819966
-- !result
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * 0 as string) from powers_of_2;
-- result:
0
-- !result
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * -1 as string) from powers_of_2;
-- result:
-57896044618658097711785492504343953926634992332820282019728792003956564819967
-- !result
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * 2 as string) from powers_of_2;
-- result:
None
-- !result
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * -2 as string) from powers_of_2;
-- result:
None
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) - 1 as string) from powers_of_2;
-- result:
None
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) + 1 as string) from powers_of_2;
-- result:
-57896044618658097711785492504343953926634992332820282019728792003956564819967
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * 1 as string) from powers_of_2;
-- result:
--57896044618658097711785492504343953926634992332820282019728792003956564819968
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * -1 as string) from powers_of_2;
-- result:
None
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * -2 as string) from powers_of_2;
-- result:
None
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * 2 as string) from powers_of_2;
-- result:
None
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * 0 as string) from powers_of_2;
-- result:
0
-- !result
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 + (-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- result:
-1
-- !result
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * (-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- result:
None
-- !result
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * (power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) as string) from powers_of_2;
-- result:
None
-- !result
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * (-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- result:
None
-- !result
create table test_256max_result(d1 decimal(76, 0)) PROPERTIES("replication_num"="1");
-- result:
-- !result
insert into test_256max_result select 1496577676626844588240573307387100039795808514605057;
-- result:
-- !result
select cast(d1 * 38685626227668133590597631 as string) from test_256max_result;
-- result:
57896044618658097711785492504343953926634992332820282019728792003956564819967
-- !result
create table test_256min_result(d1 decimal(76, 0), d2 decimal(76, 0)) PROPERTIES("replication_num"="1");
-- result:
-- !result
insert into test_256min_result select 340282366920938463463374607431768211456, -170141183460469231731687303715884105728;
-- result:
-- !result
select cast(d1 * d2 as string) from test_256min_result; -- 2^128 * -2^127
CREATE TABLE test_decimal_multiply_overflow (
id INT,
case_desc VARCHAR(200),
d60_30 DECIMAL(60, 30),
d70_20 DECIMAL(70, 20),
d76_10 DECIMAL(76, 10),
d76_38 DECIMAL(76, 38),
d50_0 DECIMAL(50, 0),
d38_0 DECIMAL(38, 0) -- Maximum 38-digit decimal number
) PROPERTIES("replication_num"="1");
-- result:
--57896044618658097711785492504343953926634992332820282019728792003956564819968
-- !result
INSERT INTO test_decimal_multiply_overflow VALUES
(1, 'Small values',
1.123456789012345678901234567890,
12.12345678901234567890,
123.1234567890,
0.12345678901234567890123456789012345678,
1000,
12345),
(2, 'Medium values',
123456789012345678901234567890.123456789012345678901234567890, -- 60 digits
12345678901234567890123456789012345678901234567890.12345678901234567890, -- 70 digits
1234567890123456789012345678901234567890123456789012345678901234.1234567890, -- 76 digits
12345678901234567890123456789012345678.12345678901234567890123456789012345678, -- 76 digits
12345678901234567890123456789012345678901234567890, -- 50 digits
12345678901234567890123456789012345678), -- 38 digits
(3, 'Near max positive values',
999999999999999999999999999999.999999999999999999999999999999, -- d60_30 maximum
99999999999999999999999999999999999999999999999999.99999999999999999999, -- d70_20 maximum
9999999999999999999999999999999999999999999999999999999999999999.9999999999, -- d76_10 maximum
99999999999999999999999999999999999999.99999999999999999999999999999999999999, -- d76_38 maximum
99999999999999999999999999999999999999999999999999, -- d50_0 maximum
99999999999999999999999999999999999999), -- d38_0 maximum (38 nines)
(4, 'Near max negative values',
-999999999999999999999999999999.999999999999999999999999999999,
-99999999999999999999999999999999999999999999999999.99999999999999999999,
-9999999999999999999999999999999999999999999999999999999999999999.9999999999,
-99999999999999999999999999999999999999.99999999999999999999999999999999999999,
-99999999999999999999999999999999999999999999999999,
-99999999999999999999999999999999999999);
-- result:
-- !result
CREATE TABLE test_boundary_values (
id INT,
case_desc VARCHAR(200),
-- Designed based on actual DECIMAL precision limits
val_76_0 DECIMAL(76, 0),
val_38_0 DECIMAL(38, 0),
val_19_0 DECIMAL(19, 0),
val_25_0 DECIMAL(25, 0),
val_high_scale DECIMAL(76, 50)
) PROPERTIES("replication_num"="1");
-- result:
-- !result
INSERT INTO test_boundary_values VALUES
(1, 'Near 76-digit decimal max',
9999999999999999999999999999999999999999999999999999999999999999999999999999, -- 76 nines
99999999999999999999999999999999999999, -- 38 nines
9999999999999999999, -- 19 nines
9999999999999999999999999, -- 25 nines
0.00000000000000000000000000000000000000000000000001),
(2, 'Near 76-digit decimal min',
-9999999999999999999999999999999999999999999999999999999999999999999999999999,
-99999999999999999999999999999999999999,
-9999999999999999999,
-9999999999999999999999999,
-0.00000000000000000000000000000000000000000000000001),
(3, 'Multiplication overflow test values',
1000000000000000000000000000000000000000000000000000000000000000000000000000, -- 76-digit 10^75
10000000000000000000000000000000000000, -- 38-digit 10^37
1000000000000000000, -- 19-digit 10^18
1000000000000000000000000, -- 25-digit 10^24
0.00000000000000000000000000000000000000000000000001),
(4, 'Medium size values',
5000000000000000000000000000000000000000000000000000000000000000000000000000, -- 76-digit 5*10^75
50000000000000000000000000000000000000, -- 38-digit 5*10^37
5000000000000000000, -- 19-digit 5*10^18
5000000000000000000000000, -- 25-digit 5*10^24
0.50000000000000000000000000000000000000000000000000);
-- result:
-- !result
SELECT
'Test 1.1: 76-digit max * 76-digit max (definite overflow)' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * val_76_0 as string) as result,
'Should overflow: 10^75 * 10^75 = 10^150, way beyond int256' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.1: 76-digit max * 76-digit max (definite overflow) 9999999999999999999999999999999999999999999999999999999999999999999999999999 None Should overflow: 10^75 * 10^75 = 10^150, way beyond int256
-- !result
SELECT
'Test 1.2: 38-digit max * 38-digit max (may overflow)' as test_case,
cast(val_38_0 as string),
cast(cast(val_38_0 as decimal(76, 0)) * val_38_0 as string) as result,
'not overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.2: 38-digit max * 38-digit max (may overflow) 99999999999999999999999999999999999999 9999999999999999999999999999999999999800000000000000000000000000000000000001 not overflow
-- !result
SELECT
'Test 1.3: 19-digit * 19-digit (should not overflow)' as test_case,
cast(val_19_0 as string),
cast(val_19_0 * val_19_0 as string) as result,
'Should not overflow: 10^18 * 10^18 = 10^36, within int256' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.3: 19-digit * 19-digit (should not overflow) 9999999999999999999 99999999999999999980000000000000000001 Should not overflow: 10^18 * 10^18 = 10^36, within int256
-- !result
SELECT
'Test 1.4: Large value * 2' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 2 as string) as result,
'Should overflow: near-max * 2' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.4: Large value * 2 9999999999999999999999999999999999999999999999999999999999999999999999999999 19999999999999999999999999999999999999999999999999999999999999999999999999998 Should overflow: near-max * 2
-- !result
SELECT
'Test 1.5: Large value * 5' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 5 as string) as result,
'Should overflow: near-max * 5' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.5: Large value * 5 9999999999999999999999999999999999999999999999999999999999999999999999999999 49999999999999999999999999999999999999999999999999999999999999999999999999995 Should overflow: near-max * 5
-- !result
SELECT
'Test 1.6: Large value * 5.1' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 5.1 as string) as result,
'Should overflow: near-max * 5.1' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.6: Large value * 5.1 9999999999999999999999999999999999999999999999999999999999999999999999999999 None Should overflow: near-max * 5.1
-- !result
SELECT
'Test 1.7: Large value * 6' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 6 as string) as result,
'Should overflow: near-max * 6' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 1.7: Large value * 6 9999999999999999999999999999999999999999999999999999999999999999999999999999 None Should overflow: near-max * 6
-- !result
SELECT
'Test 2.1: Large negative * Large negative (positive overflow)' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * val_76_0 as string) as result,
'Should overflow: (-10^75) * (-10^75) = +10^150' as expected
FROM test_boundary_values WHERE id = 2;
-- result:
Test 2.1: Large negative * Large negative (positive overflow) -9999999999999999999999999999999999999999999999999999999999999999999999999999 None Should overflow: (-10^75) * (-10^75) = +10^150
-- !result
SELECT
'Test 2.2: Large negative * Large positive (negative overflow)' as test_case,
cast(a.val_76_0 as string) as neg_val,
cast(b.val_76_0 as string) as pos_val,
cast(a.val_76_0 * b.val_76_0 as string) as result,
'Should overflow: (-10^75) * (+10^75) = -10^150' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 2 AND b.id = 1;
-- result:
Test 2.2: Large negative * Large positive (negative overflow) -9999999999999999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999 None Should overflow: (-10^75) * (+10^75) = -10^150
-- !result
SELECT
'Test 2.3: Negative boundary * 5' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 5 as string) as result,
'Should not overflow' as expected
FROM test_boundary_values WHERE id = 2;
-- result:
Test 2.3: Negative boundary * 5 -9999999999999999999999999999999999999999999999999999999999999999999999999999 -49999999999999999999999999999999999999999999999999999999999999999999999999995 Should not overflow
-- !result
SELECT
'Test 2.4: Negative boundary * 6' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 6 as string) as result,
'Should overflow' as expected
FROM test_boundary_values WHERE id = 2;
-- result:
Test 2.4: Negative boundary * 6 -9999999999999999999999999999999999999999999999999999999999999999999999999999 None Should overflow
-- !result
SELECT
'Test 3.1: 76-digit * 38-digit' as test_case,
cast(a.val_76_0 as string),
cast(b.val_38_0 as string),
cast(a.val_76_0 * b.val_38_0 as string) as result,
'Should overflow: 10^75 * 10^37 = 10^112' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 1 AND b.id = 1;
-- result:
Test 3.1: 76-digit * 38-digit 9999999999999999999999999999999999999999999999999999999999999999999999999999 99999999999999999999999999999999999999 None Should overflow: 10^75 * 10^37 = 10^112
-- !result
SELECT
'Test 3.2: 38-digit * 25-digit' as test_case,
cast(a.val_38_0 as string),
cast(b.val_25_0 as string),
cast(a.val_38_0 * b.val_25_0 as string) as result,
'overflow' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 1 AND b.id = 1;
-- result:
Test 3.2: 38-digit * 25-digit 99999999999999999999999999999999999999 9999999999999999999999999 None overflow
-- !result
SELECT
'Test 3.2: 38-digit * 25-digit' as test_case,
cast(a.val_38_0 as string),
cast(b.val_25_0 as string),
cast(cast(a.val_38_0 as decimal(50, 10)) * b.val_25_0 as string) as result,
'should not overflow' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 1 AND b.id = 1;
-- result:
Test 3.2: 38-digit * 25-digit 99999999999999999999999999999999999999 9999999999999999999999999 999999999999999999999999899999999999990000000000000000000000001.0000000000 should not overflow
-- !result
SELECT
'Test 3.3: 25-digit * 25-digit' as test_case,
cast(val_25_0 as string),
cast(val_25_0 * val_25_0 as string) as result,
'overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 3.3: 25-digit * 25-digit 9999999999999999999999999 None overflow
-- !result
SELECT
'Test 3.3: 25-digit * 25-digit' as test_case,
cast(val_25_0 as string),
cast(val_25_0 * cast(val_25_0 as decimal(39, 0)) as string) as result,
'should not overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 3.3: 25-digit * 25-digit 9999999999999999999999999 99999999999999999999999980000000000000000000000001 should not overflow
-- !result
CREATE TABLE test_progressive_boundary (
id INT,
digits INT,
test_val DECIMAL(76, 0)
) PROPERTIES("replication_num"="1");
-- result:
-- !result
INSERT INTO test_progressive_boundary VALUES
(1, 10, 9999999999), -- 10 digits
(2, 15, 999999999999999), -- 15 digits
(3, 20, 99999999999999999999), -- 20 digits
(4, 25, 9999999999999999999999999), -- 25 digits
(5, 30, 999999999999999999999999999999), -- 30 digits
(6, 35, 99999999999999999999999999999999999), -- 35 digits
(7, 38, 99999999999999999999999999999999999999); -- 38 digits
SELECT
id,
digits,
cast(test_val as string),
cast(test_val * test_val as string) as result,
CASE
WHEN digits <= 19 THEN 'Should succeed'
WHEN digits <= 25 THEN 'May succeed'
WHEN digits > 30 THEN 'Should succeed'
ELSE 'Boundary case'
END as expected
FROM test_progressive_boundary ORDER BY id;
-- result:
-- !result
SELECT
'Test 5.1: Scale overflow, tiny value' as test_case,
cast(val_high_scale * val_high_scale as string) as result,
'Should fail due to scale=100 > 76' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
E: (1064, 'Getting analyzing error. Detail message: Return scale(100) exceeds maximum value(76), please cast decimal type to low-precision one.')
-- !result
SELECT
'Test 5.2: Value overflow, scale OK' as test_case,
cast(val_38_0 * val_38_0 as string) as result,
'Should fail due to value overflow, scale=0 is fine' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 5.2: Value overflow, scale OK None Should fail due to value overflow, scale=0 is fine
-- !result
SELECT
'Test 6.1: Large * 0' as test_case,
cast(val_76_0 * 0 as string) as result,
'Should return 0, no overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 6.1: Large * 0 0 Should return 0, no overflow
-- !result
SELECT
'Test 6.2: Large * 1' as test_case,
cast(val_76_0 * 1 as string) as result,
'Should return original value' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 6.2: Large * 1 9999999999999999999999999999999999999999999999999999999999999999999999999999 Should return original value
-- !result
SELECT
'Test 6.3: Large * 0.1' as test_case,
cast(val_76_0 * 0.1 as string) as result,
'Should succeed, reduces magnitude' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 6.3: Large * 0.1 999999999999999999999999999999999999999999999999999999999999999999999999999.9 Should succeed, reduces magnitude
-- !result
SELECT
'Test 6.4: Large * -1' as test_case,
cast(val_76_0 * (-1) as string) as result,
'Should return negative of original' as expected
FROM test_boundary_values WHERE id = 1;
-- result:
Test 6.4: Large * -1 -9999999999999999999999999999999999999999999999999999999999999999999999999999 Should return negative of original
-- !result
SELECT
'Test 7.2: Scientific calculation' as test_case,
cast(d76_10 * d76_10 as string) as result,
'Simulates scientific computation overflow' as expected
FROM test_decimal_multiply_overflow WHERE id = 3;
-- result:
Test 7.2: Scientific calculation None Simulates scientific computation overflow
-- !result

View File

@ -0,0 +1,656 @@
-- name: test_decimal256_cast_operations
DROP DATABASE IF EXISTS test_decimal256_cast;
-- result:
-- !result
CREATE DATABASE test_decimal256_cast;
-- result:
-- !result
USE test_decimal256_cast;
-- result:
-- !result
CREATE TABLE cast_test_source (
id int,
bool_val boolean,
tinyint_val tinyint,
smallint_val smallint,
int_val int,
bigint_val bigint,
largeint_val largeint,
float_val float,
double_val double,
varchar_val varchar(100),
-- decimal256 columns for testing (precision > 38, <= 76)
decimal256_50_15 decimal(50,15), -- 50 digits total, 15 after decimal
decimal256_76_20 decimal(76,20), -- 76 digits total, 20 after decimal
decimal256_76_0 decimal(76,0), -- 76 digits total, 0 after decimal
-- regular decimal columns for comparison (precision <= 38)
decimal_38_10 decimal(38,10), -- 38 digits total, 10 after decimal
decimal_20_5 decimal(20,5) -- 20 digits total, 5 after decimal
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
-- result:
-- !result
INSERT INTO cast_test_source VALUES
(1, true, 127, 32767, 2147483647, 9223372036854775807, 170141183460469231731687303715884105727,
3.14159, 2.718281828459045, '12345678901234567890123456789012345.123456789012345',
12345678901234567890123456789012345.123456789012345, -- 35+15=50 digits
12345678901234567890123456789012345678901234567890123456.12345678901234567890, -- 56+20=76 digits
1234567890123456789012345678901234567890123456789012345678901234567890123456, -- 76 digits
1234567890123456789012345678.1234567890, -- 28+10=38 digits
123456789012345.12345), -- 15+5=20 digits
(2, false, 0, 0, 0, 0, 0, 0.0, 0.0, '0',
0.000000000000000,
0.00000000000000000000,
0,
0.0000000000,
0.00000),
(3, false, -128, -32768, -2147483648, -9223372036854775808, -170141183460469231731687303715884105728,
-3.14159, -2.718281828459045, '-87654321098765432109876543210987654.987654321098765',
-87654321098765432109876543210987654.987654321098765, -- 35+15=50 digits
-87654321098765432109876543210987654321098765432109876543.98765432109876543210, -- 56+20=76 digits
-8765432109876543210987654321098765432109876543210987654321098765432109876543, -- 76 digits
-8765432109876543210987654321.9876543210, -- 28+10=38 digits
-876543210987654.98765), -- 15+5=20 digits
(4, true, 127, 32767, 2147483647, 9223372036854775807, 170141183460469231731687303715884105727,
1.7976931348623157e+308, 1.7976931348623157e+308, '99999999999999999999999999999999999.999999999999999',
99999999999999999999999999999999999.999999999999999, -- 35+15=50 digits
99999999999999999999999999999999999999999999999999999999.99999999999999999999, -- 56+20=76 digits
9999999999999999999999999999999999999999999999999999999999999999999999999999, -- 76 digits
9999999999999999999999999999.9999999999, -- 28+10=38 digits
999999999999999.99999), -- 15+5=20 digits
(5, false, -128, -32768, -2147483648, -9223372036854775808, -170141183460469231731687303715884105728,
-1.7976931348623157e+308, -1.7976931348623157e+308, '-99999999999999999999999999999999999.999999999999999',
-99999999999999999999999999999999999.999999999999999, -- 35+15=50 digits
-99999999999999999999999999999999999999999999999999999999.99999999999999999999, -- 56+20=76 digits
-9999999999999999999999999999999999999999999999999999999999999999999999999999, -- 76 digits
-9999999999999999999999999999.9999999999, -- 28+10=38 digits
-999999999999999.99999), -- 15+5=20 digits
(6, true, 1, 1, 1, 1, 1, 0.000001, 0.000000000000001, '0.000000000000001',
0.000000000000001,
0.00000000000000000001,
1,
0.0000000001,
0.00001),
(7, false, 42, 1234, 567890, 123456789012345, 987654321098765432109876543210,
123.456789, 987.654321123456789, '555555555555555555555555555555555.555555555555555',
55555555555555555555555555555555555.555555555555555, -- 35+15=50 digits
55555555555555555555555555555555555555555555555555555555.55555555555555555555, -- 56+20=76 digits
5555555555555555555555555555555555555555555555555555555555555555555555555555, -- 76 digits
5555555555555555555555555555.5555555555, -- 28+10=38 digits
555555555555555.55555), -- 15+5=20 digits
(8, true, 1, 10, 100, 1000, 10000,
1e-10, 1e-15, '0.000000000000001',
0.000000000000001,
0.00000000000000000001,
1,
0.0000000001,
0.00001),
(9, false, 99, 9999, 999999999, 999999999999999999, 99999999999999999999999999999999999999,
999999.999999, 999999999.999999999999, '77777777777777777777777777777777777.777777777777777',
77777777777777777777777777777777777.777777777777777, -- 35+15=50 digits
77777777777777777777777777777777777777777777777777777777.77777777777777777777, -- 56+20=76 digits
7777777777777777777777777777777777777777777777777777777777777777777777777777, -- 76 digits
7777777777777777777777777777.7777777777, -- 28+10=38 digits
777777777777777.77777), -- 15+5=20 digits
(10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-- result:
-- !result
SELECT
id,
bool_val,
CAST(bool_val AS decimal(50,15)) as bool_to_decimal256_50_15,
CAST(bool_val AS decimal(76,20)) as bool_to_decimal256_76_20,
CAST(bool_val AS decimal(76,0)) as bool_to_decimal256_76_0,
CAST(bool_val AS decimal(38,10)) as bool_to_decimal_38_10
FROM cast_test_source
ORDER BY id;
-- result:
1 1 1.000000000000000 1.00000000000000000000 1 1.0000000000
2 0 0E-15 0E-20 0 0E-10
3 0 0E-15 0E-20 0 0E-10
4 1 1.000000000000000 1.00000000000000000000 1 1.0000000000
5 0 0E-15 0E-20 0 0E-10
6 1 1.000000000000000 1.00000000000000000000 1 1.0000000000
7 0 0E-15 0E-20 0 0E-10
8 1 1.000000000000000 1.00000000000000000000 1 1.0000000000
9 0 0E-15 0E-20 0 0E-10
10 None None None None None
-- !result
SELECT
id,
tinyint_val,
CAST(tinyint_val AS decimal(50,15)) as tinyint_to_decimal256,
smallint_val,
CAST(smallint_val AS decimal(50,15)) as smallint_to_decimal256,
int_val,
CAST(int_val AS decimal(50,15)) as int_to_decimal256
FROM cast_test_source
ORDER BY id;
-- result:
1 127 127.000000000000000 32767 32767.000000000000000 2147483647 2147483647.000000000000000
2 0 0E-15 0 0E-15 0 0E-15
3 -128 -128.000000000000000 -32768 -32768.000000000000000 -2147483648 -2147483648.000000000000000
4 127 127.000000000000000 32767 32767.000000000000000 2147483647 2147483647.000000000000000
5 -128 -128.000000000000000 -32768 -32768.000000000000000 -2147483648 -2147483648.000000000000000
6 1 1.000000000000000 1 1.000000000000000 1 1.000000000000000
7 42 42.000000000000000 1234 1234.000000000000000 567890 567890.000000000000000
8 1 1.000000000000000 10 10.000000000000000 100 100.000000000000000
9 99 99.000000000000000 9999 9999.000000000000000 999999999 999999999.000000000000000
10 None None None None None None
-- !result
SELECT
id,
bigint_val,
CAST(bigint_val AS decimal(76,20)) as bigint_to_decimal256,
largeint_val,
CAST(largeint_val AS decimal(76,0)) as largeint_to_decimal256
FROM cast_test_source
ORDER BY id;
-- result:
1 9223372036854775807 9223372036854775807.00000000000000000000 170141183460469231731687303715884105727 170141183460469231731687303715884105727
2 0 0E-20 0 0
3 -9223372036854775808 -9223372036854775808.00000000000000000000 -170141183460469231731687303715884105728 -170141183460469231731687303715884105728
4 9223372036854775807 9223372036854775807.00000000000000000000 170141183460469231731687303715884105727 170141183460469231731687303715884105727
5 -9223372036854775808 -9223372036854775808.00000000000000000000 -170141183460469231731687303715884105728 -170141183460469231731687303715884105728
6 1 1.00000000000000000000 1 1
7 123456789012345 123456789012345.00000000000000000000 987654321098765432109876543210 987654321098765432109876543210
8 1000 1000.00000000000000000000 10000 10000
9 999999999999999999 999999999999999999.00000000000000000000 99999999999999999999999999999999999999 99999999999999999999999999999999999999
10 None None None None
-- !result
SELECT
id,
float_val,
CAST(float_val AS decimal(50,15)) as float_to_decimal256_50_15,
CAST(float_val AS decimal(76,20)) as float_to_decimal256_76_20,
double_val,
CAST(double_val AS decimal(50,15)) as double_to_decimal256_50_15,
CAST(double_val AS decimal(76,20)) as double_to_decimal256_76_20
FROM cast_test_source
ORDER BY id;
-- result:
1 3.14159 3.141590118408203 3.14159011840820314112 2.718281828459045 2.718281828459045 2.71828182845904519168
2 0.0 0E-15 0E-20 0.0 0E-15 0E-20
3 -3.14159 -3.141590118408203 -3.14159011840820314112 -2.718281828459045 -2.718281828459045 -2.71828182845904519168
4 inf None None 1.7976931348623157e+308 None None
5 -inf None None -1.7976931348623157e+308 None None
6 1e-06 9.99999997E-7 9.9999999747524E-7 1e-15 1E-15 1.00000E-15
7 123.45679 123.456787109375008 123.45678710937499992064 987.6543211234568 987.654321123456896 987.65432112345690144768
8 1e-10 1.00000E-10 1.0000000134E-10 1e-15 1E-15 1.00000E-15
9 1000000.0 1000000.000000000000000 1000000.00000000004764729344 1000000000.0 999999999.999999983222784 999999999.99999991433150857216
10 None None None None None None
-- !result
SELECT
id,
varchar_val,
CAST(varchar_val AS decimal(50,15)) as varchar_to_decimal256_50_15,
CAST(varchar_val AS decimal(76,20)) as varchar_to_decimal256_76_20,
CAST(varchar_val AS decimal(76,0)) as varchar_to_decimal256_76_0
FROM cast_test_source
WHERE varchar_val IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012345.123456789012345 12345678901234567890123456789012345.123456789012345 12345678901234567890123456789012345.12345678901234500000 12345678901234567890123456789012345
2 0 0E-15 0E-20 0
3 -87654321098765432109876543210987654.987654321098765 -87654321098765432109876543210987654.987654321098765 -87654321098765432109876543210987654.98765432109876500000 -87654321098765432109876543210987655
4 99999999999999999999999999999999999.999999999999999 99999999999999999999999999999999999.999999999999999 99999999999999999999999999999999999.99999999999999900000 100000000000000000000000000000000000
5 -99999999999999999999999999999999999.999999999999999 -99999999999999999999999999999999999.999999999999999 -99999999999999999999999999999999999.99999999999999900000 -100000000000000000000000000000000000
6 0.000000000000001 1E-15 1.00000E-15 0
7 555555555555555555555555555555555.555555555555555 555555555555555555555555555555555.555555555555555 555555555555555555555555555555555.55555555555555500000 555555555555555555555555555555556
8 0.000000000000001 1E-15 1.00000E-15 0
9 77777777777777777777777777777777777.777777777777777 77777777777777777777777777777777777.777777777777777 77777777777777777777777777777777777.77777777777777700000 77777777777777777777777777777777778
-- !result
SELECT
id,
decimal256_50_15,
CAST(decimal256_50_15 AS boolean) as decimal256_to_bool,
CAST(decimal256_50_15 AS tinyint) as decimal256_to_tinyint,
CAST(decimal256_50_15 AS smallint) as decimal256_to_smallint,
CAST(decimal256_50_15 AS int) as decimal256_to_int,
CAST(decimal256_50_15 AS bigint) as decimal256_to_bigint,
CAST(decimal256_50_15 AS largeint) as decimal256_to_largeint
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012345.123456789012345 1 None None None None 12345678901234567890123456789012345
2 0E-15 0 0 0 0 0 0
3 -87654321098765432109876543210987654.987654321098765 1 None None None None -87654321098765432109876543210987654
4 99999999999999999999999999999999999.999999999999999 1 None None None None 99999999999999999999999999999999999
5 -99999999999999999999999999999999999.999999999999999 1 None None None None -99999999999999999999999999999999999
6 1E-15 1 0 0 0 0 0
7 55555555555555555555555555555555555.555555555555555 1 None None None None 55555555555555555555555555555555555
8 1E-15 1 0 0 0 0 0
9 77777777777777777777777777777777777.777777777777777 1 None None None None 77777777777777777777777777777777777
-- !result
SELECT
id,
decimal256_76_20,
CAST(decimal256_76_20 AS float) as decimal256_to_float,
CAST(decimal256_76_20 AS double) as decimal256_to_double,
CAST(decimal256_76_20 AS varchar(100)) as decimal256_to_varchar
FROM cast_test_source
WHERE decimal256_76_20 IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012345678901234567890123456.12345678901234567890 inf 1.234567890123457e+55 12345678901234567890123456789012345678901234567890123456.12345678901234567890
2 0E-20 0.0 0.0 0.00000000000000000000
3 -87654321098765432109876543210987654321098765432109876543.98765432109876543210 -inf -8.765432109876543e+55 -87654321098765432109876543210987654321098765432109876543.98765432109876543210
4 99999999999999999999999999999999999999999999999999999999.99999999999999999999 inf 1e+56 99999999999999999999999999999999999999999999999999999999.99999999999999999999
5 -99999999999999999999999999999999999999999999999999999999.99999999999999999999 -inf -1e+56 -99999999999999999999999999999999999999999999999999999999.99999999999999999999
6 1E-20 1e-20 1e-20 0.00000000000000000001
7 55555555555555555555555555555555555555555555555555555555.55555555555555555555 inf 5.555555555555556e+55 55555555555555555555555555555555555555555555555555555555.55555555555555555555
8 1E-20 1e-20 1e-20 0.00000000000000000001
9 77777777777777777777777777777777777777777777777777777777.77777777777777777777 inf 7.777777777777777e+55 77777777777777777777777777777777777777777777777777777777.77777777777777777777
-- !result
SELECT
id,
decimal256_50_15,
CAST(decimal256_50_15 AS decimal(76,20)) as decimal256_50_15_to_76_20,
CAST(decimal256_50_15 AS decimal(76,0)) as decimal256_50_15_to_76_0,
CAST(decimal256_50_15 AS decimal(38,10)) as decimal256_50_15_to_38_10,
decimal256_76_20,
CAST(decimal256_76_20 AS decimal(50,15)) as decimal256_76_20_to_50_15,
CAST(decimal256_76_20 AS decimal(76,0)) as decimal256_76_20_to_76_0
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012345.123456789012345 12345678901234567890123456789012345.12345678901234500000 12345678901234567890123456789012345 None 12345678901234567890123456789012345678901234567890123456.12345678901234567890 12345678901234567890123456789012345678901234567890123456.123456789012346 12345678901234567890123456789012345678901234567890123456
2 0E-15 0E-20 0 0E-10 0E-20 0E-15 0
3 -87654321098765432109876543210987654.987654321098765 -87654321098765432109876543210987654.98765432109876500000 -87654321098765432109876543210987655 None -87654321098765432109876543210987654321098765432109876543.98765432109876543210 -87654321098765432109876543210987654321098765432109876543.987654321098765 -87654321098765432109876543210987654321098765432109876544
4 99999999999999999999999999999999999.999999999999999 99999999999999999999999999999999999.99999999999999900000 100000000000000000000000000000000000 None 99999999999999999999999999999999999999999999999999999999.99999999999999999999 100000000000000000000000000000000000000000000000000000000.000000000000000 100000000000000000000000000000000000000000000000000000000
5 -99999999999999999999999999999999999.999999999999999 -99999999999999999999999999999999999.99999999999999900000 -100000000000000000000000000000000000 None -99999999999999999999999999999999999999999999999999999999.99999999999999999999 -100000000000000000000000000000000000000000000000000000000.000000000000000 -100000000000000000000000000000000000000000000000000000000
6 1E-15 1.00000E-15 0 0E-10 1E-20 0E-15 0
7 55555555555555555555555555555555555.555555555555555 55555555555555555555555555555555555.55555555555555500000 55555555555555555555555555555555556 None 55555555555555555555555555555555555555555555555555555555.55555555555555555555 55555555555555555555555555555555555555555555555555555555.555555555555556 55555555555555555555555555555555555555555555555555555556
8 1E-15 1.00000E-15 0 0E-10 1E-20 0E-15 0
9 77777777777777777777777777777777777.777777777777777 77777777777777777777777777777777777.77777777777777700000 77777777777777777777777777777777778 None 77777777777777777777777777777777777777777777777777777777.77777777777777777777 77777777777777777777777777777777777777777777777777777777.777777777777778 77777777777777777777777777777777777777777777777777777778
-- !result
SELECT
id,
decimal_38_10,
CAST(decimal_38_10 AS decimal(50,15)) as decimal_38_10_to_decimal256_50_15,
CAST(decimal_38_10 AS decimal(76,20)) as decimal_38_10_to_decimal256_76_20,
decimal256_50_15,
CAST(decimal256_50_15 AS decimal(38,10)) as decimal256_50_15_to_decimal_38_10,
CAST(decimal256_50_15 AS decimal(20,5)) as decimal256_50_15_to_decimal_20_5
FROM cast_test_source
WHERE decimal_38_10 IS NOT NULL AND decimal256_50_15 IS NOT NULL
ORDER BY id;
-- result:
1 1234567890123456789012345678.1234567890 1234567890123456789012345678.123456789000000 1234567890123456789012345678.12345678900000000000 12345678901234567890123456789012345.123456789012345 None None
2 0E-10 0E-15 0E-20 0E-15 0E-10 0.00000
3 -8765432109876543210987654321.9876543210 -8765432109876543210987654321.987654321000000 -8765432109876543210987654321.98765432100000000000 -87654321098765432109876543210987654.987654321098765 None None
4 9999999999999999999999999999.9999999999 9999999999999999999999999999.999999999900000 9999999999999999999999999999.99999999990000000000 99999999999999999999999999999999999.999999999999999 None None
5 -9999999999999999999999999999.9999999999 -9999999999999999999999999999.999999999900000 -9999999999999999999999999999.99999999990000000000 -99999999999999999999999999999999999.999999999999999 None None
6 1E-10 1.00000E-10 1.0000000000E-10 1E-15 0E-10 0.00000
7 5555555555555555555555555555.5555555555 5555555555555555555555555555.555555555500000 5555555555555555555555555555.55555555550000000000 55555555555555555555555555555555555.555555555555555 None None
8 1E-10 1.00000E-10 1.0000000000E-10 1E-15 0E-10 0.00000
9 7777777777777777777777777777.7777777777 7777777777777777777777777777.777777777700000 7777777777777777777777777777.77777777770000000000 77777777777777777777777777777777777.777777777777777 None None
-- !result
SELECT
id,
decimal256_50_15 + tinyint_val as decimal256_plus_tinyint,
decimal256_50_15 + smallint_val as decimal256_plus_smallint,
decimal256_50_15 + int_val as decimal256_plus_int,
decimal256_50_15 + bigint_val as decimal256_plus_bigint,
decimal256_50_15 + largeint_val as decimal256_plus_largeint
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND tinyint_val IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012472.123456789012345 12345678901234567890123456789045112.123456789012345 12345678901234567890123458936495992.123456789012345 12345678901234577113495493643788152.123456789012345 170153529139370466299577427172673118072.123456789012345
2 0E-15 0E-15 0E-15 0E-15 0E-15
3 -87654321098765432109876543210987782.987654321098765 -87654321098765432109876543211020422.987654321098765 -87654321098765432109876545358471302.987654321098765 -87654321098765441333248580065763462.987654321098765 -170228837781567997163797180259095093382.987654321098765
4 100000000000000000000000000000000126.999999999999999 100000000000000000000000000000032766.999999999999999 100000000000000000000000002147483646.999999999999999 100000000000000009223372036854775806.999999999999999 170241183460469231731687303715884105726.999999999999999
5 -100000000000000000000000000000000127.999999999999999 -100000000000000000000000000000032767.999999999999999 -100000000000000000000000002147483647.999999999999999 -100000000000000009223372036854775807.999999999999999 -170241183460469231731687303715884105727.999999999999999
6 1.000000000000001 1.000000000000001 1.000000000000001 1.000000000000001 1.000000000000001
7 55555555555555555555555555555555597.555555555555555 55555555555555555555555555555556789.555555555555555 55555555555555555555555555556123445.555555555555555 55555555555555555555679012344567900.555555555555555 55556543209876654320987665432098765.555555555555555
8 1.000000000000001 10.000000000000001 100.000000000000001 1000.000000000000001 10000.000000000000001
9 77777777777777777777777777777777876.777777777777777 77777777777777777777777777777787776.777777777777777 77777777777777777777777778777777776.777777777777777 77777777777777778777777777777777776.777777777777777 100077777777777777777777777777777777776.777777777777777
-- !result
SELECT
id,
decimal256_76_20 + float_val as decimal256_plus_float,
decimal256_76_20 + double_val as decimal256_plus_double,
decimal256_50_15 + decimal_38_10 as decimal256_plus_decimal38
FROM cast_test_source
WHERE decimal256_76_20 IS NOT NULL AND float_val IS NOT NULL AND decimal256_50_15 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- result:
1 1.234567890123457e+55 1.234567890123457e+55 12345680135802458013580245801358023.246913578012345
2 0.0 0.0 0E-15
3 -8.765432109876543e+55 -8.765432109876543e+55 -87654329864197541986419754198641976.975308642098765
4 inf 1.7976931348623157e+308 100000009999999999999999999999999999.999999999899999
5 -inf -1.7976931348623157e+308 -100000009999999999999999999999999999.999999999899999
6 9.999999974752527e-07 1.00001e-15 1.00001E-10
7 5.555555555555556e+55 5.555555555555556e+55 55555561111111111111111111111111111.111111111055555
8 1.000000013451432e-10 1.00001e-15 1.00001E-10
9 7.777777777777777e+55 7.777777777777777e+55 77777785555555555555555555555555555.555555555477777
-- !result
SELECT
id,
decimal256_50_15 - tinyint_val as decimal256_minus_tinyint,
decimal256_50_15 - smallint_val as decimal256_minus_smallint,
decimal256_50_15 - int_val as decimal256_minus_int,
decimal256_50_15 - bigint_val as decimal256_minus_bigint,
decimal256_76_20 - decimal_38_10 as decimal256_minus_decimal38
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND tinyint_val IS NOT NULL AND decimal256_76_20 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012218.123456789012345 12345678901234567890123456788979578.123456789012345 12345678901234567890123454641528698.123456789012345 12345678901234558666751419934236538.123456789012345 12345678901234567890123456787777777788777777778877777778.00000000001234567890
2 0E-15 0E-15 0E-15 0E-15 0E-20
3 -87654321098765432109876543210987526.987654321098765 -87654321098765432109876543210954886.987654321098765 -87654321098765432109876541063504006.987654321098765 -87654321098765422886504506356211846.987654321098765 -87654321098765432109876543202222222211222222221122222222.00000000009876543210
4 99999999999999999999999999999999872.999999999999999 99999999999999999999999999999967232.999999999999999 99999999999999999999999997852516352.999999999999999 99999999999999990776627963145224192.999999999999999 99999999999999999999999999990000000000000000000000000000.00000000009999999999
5 -99999999999999999999999999999999871.999999999999999 -99999999999999999999999999999967231.999999999999999 -99999999999999999999999997852516351.999999999999999 -99999999999999990776627963145224191.999999999999999 -99999999999999999999999999990000000000000000000000000000.00000000009999999999
6 -0.999999999999999 -0.999999999999999 -0.999999999999999 -0.999999999999999 -9.999999999E-11
7 55555555555555555555555555555555513.555555555555555 55555555555555555555555555555554321.555555555555555 55555555555555555555555555554987665.555555555555555 55555555555555555555432098766543210.555555555555555 55555555555555555555555555550000000000000000000000000000.00000000005555555555
8 -0.999999999999999 -9.999999999999999 -99.999999999999999 -999.999999999999999 -9.999999999E-11
9 77777777777777777777777777777777678.777777777777777 77777777777777777777777777777767778.777777777777777 77777777777777777777777776777777778.777777777777777 77777777777777776777777777777777778.777777777777777 77777777777777777777777777770000000000000000000000000000.00000000007777777777
-- !result
SELECT
id,
decimal256_50_15 * tinyint_val as decimal256_multiply_tinyint,
decimal256_50_15 * smallint_val as decimal256_multiply_smallint,
decimal256_76_20 * float_val as decimal256_multiply_float,
decimal256_76_20 * double_val as decimal256_multiply_double,
decimal256_50_15 * decimal_20_5 as decimal256_multiply_decimal20
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL AND tinyint_val IS NOT NULL
AND float_val IS NOT NULL AND decimal_20_5 IS NOT NULL
ORDER BY id;
-- result:
1 1567901220456790122045679012204567830.679012204567815 404530860556753086055675308605567512660.308605567508615 3.878506284115917e+55 3.3559034617216163e+55 1524157875323876817626947886762694720102881755837.67461130300259899025
2 0E-15 0E-15 0.0 0.0 0E-20
3 11219753100641975310064197531006419838.419753100641920 2872256793764345679376434567937643478635.456793764331520 2.753739489996612e+56 2.3826914822868836e+56 76832800072854806320898565170589857101323732717416.38954291988050525225
4 12699999999999999999999999999999999999.999999999999873 3276699999999999999999999999999999999999.999999999967233 inf inf 99999999999999999998999999999999999999999999999999.00000000000000000001
5 12799999999999999999999999999999999999.999999999999872 3276799999999999999999999999999999999999.999999999967232 inf inf 99999999999999999998999999999999999999999999999999.00000000000000000001
6 1E-15 1E-15 9.999999974752427e-27 1e-35 1E-20
7 2333333333333333333333333333333333333.333333333333310 68555555555555555555555555555555555555.555555555554870 6.858710394965278e+57 5.486968450685872e+58 30864197530864197530555555555555555555555555555555.24691358024691358025
8 1E-15 1.0E-14 1.0000000133514319e-30 1e-35 1E-20
9 7699999999999999999999999999999999999.999999999999923 777699999999999999999999999999999999999.999999999992223 7.777777777777778e+61 7.777777777777778e+64 60493827160493827159888888888888888888888888888888.28395061728395061729
-- !result
SELECT
id,
decimal256_50_15 / tinyint_val as decimal256_divide_tinyint,
decimal256_50_15 / smallint_val as decimal256_divide_smallint,
decimal256_76_20 / float_val as decimal256_divide_float,
decimal256_76_20 / double_val as decimal256_divide_double,
decimal256_50_15 / decimal_20_5 as decimal256_divide_decimal20
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL
AND tinyint_val IS NOT NULL AND tinyint_val != 0 AND smallint_val != 0
AND float_val IS NOT NULL AND float_val != 0 AND double_val IS NOT NULL AND double_val != 0
AND decimal_20_5 IS NOT NULL AND decimal_20_5 != 0
ORDER BY id;
-- result:
1 97210070088461164489161077078837.363176825110333 376771718534945765255392827814.946291191039430 3.929754817121064e+54 4.54172145506824e+54 100000000000000449915.504049232561083
3 684799383584104938358410493835841.054591049383584 2674997592125409915462540991546.254119496286655 2.790125948803868e+55 3.2246222662075993e+55 99999999999999923956.831082309567732
4 787401574803149606299212598425196.850393700787402 3051850947599719229712820825830.866420484023560 0.0 5.562684646268005e-253 100000000000000000001.000000000000000
5 781250000000000000000000000000000.000000000000000 3051757812500000000000000000000.000000000000000 0.0 5.562684646268005e-253 100000000000000000001.000000000000000
6 1E-15 1E-15 1.0000000025247572e-14 9.999999999999999e-06 1.00000E-10
7 1322751322751322751322751322751322.751322751322751 45020709526382135782459931568521.519899153610661 4.5000001098632844e+53 5.624999999226563e+52 100000000000000000001.000000000000000
8 1E-15 0E-15 9.999999866485681e-11 9.999999999999999e-06 1.00000E-10
9 785634118967452300785634118967452.300785634118967 7778555633341111888966674445222.300007778555633 7.777777777777778e+49 7.777777777777778e+46 100000000000000000001.000000000000000
-- !result
SELECT
id,
decimal256_50_15 + decimal256_76_20 as decimal256_addition,
decimal256_50_15 - decimal256_76_20 as decimal256_subtraction,
decimal256_50_15 * decimal256_76_0 as decimal256_multiplication,
decimal256_76_20 / decimal256_76_0 as decimal256_division
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL
AND decimal256_76_0 IS NOT NULL AND decimal256_76_0 != 0
ORDER BY id;
-- result:
1 12345678901234567890135802467913580246791358024679135801.24691357802469067890 -12345678901234567890111111110111111111011111111101111111.00000000000000067890 None 1E-20
3 -87654321098765432109964197532086419753208641975320864198.97530864219753043210 87654321098765432109788888889888888888988888888898888889.00000000000000043210 None 1E-20
4 100000000000000000000099999999999999999999999999999999999.99999999999999899999 -99999999999999999999900000000000000000000000000000000000.00000000000000099999 None 1E-20
5 -100000000000000000000099999999999999999999999999999999999.99999999999999899999 99999999999999999999900000000000000000000000000000000000.00000000000000099999 None 1E-20
6 1.00001E-15 9.9999E-16 1E-15 1E-20
7 55555555555555555555611111111111111111111111111111111111.11111111111111055555 -55555555555555555555500000000000000000000000000000000000.00000000000000055555 None 1E-20
8 1.00001E-15 9.9999E-16 1E-15 1E-20
9 77777777777777777777855555555555555555555555555555555555.55555555555555477777 -77777777777777777777700000000000000000000000000000000000.00000000000000077777 None 1E-20
-- !result
SELECT
id,
(decimal256_50_15 + CAST(int_val AS decimal(50,15))) * CAST(float_val AS decimal(50,15)) as complex_expr1,
(decimal256_76_20 - CAST(bigint_val AS decimal(76,20))) / CAST(double_val AS decimal(76,20)) as complex_expr2,
CAST(tinyint_val AS decimal(76,0)) + decimal256_76_0 - CAST(smallint_val AS decimal(76,0)) as complex_expr3,
(decimal256_50_15 + decimal_38_10) * CAST(decimal_20_5 AS decimal(50,15)) as complex_expr4
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL AND decimal256_76_0 IS NOT NULL
AND int_val IS NOT NULL AND float_val IS NOT NULL AND float_val != 0
AND bigint_val IS NOT NULL AND double_val IS NOT NULL AND double_val != 0
AND tinyint_val IS NOT NULL AND smallint_val IS NOT NULL
AND decimal_38_10 IS NOT NULL AND decimal_20_5 IS NOT NULL
ORDER BY id;
-- result:
1 38785062841159159648132622711326664.709912157833965463651916266035 None 1234567890123456789012345678901234567890123456789012345678901234567890090816 None
3 275373948999661140351867390781700148.497562752457348482839749169295 None -8765432109876543210987654321098765432109876543210987654321098765432109843903 None
4 None None 9999999999999999999999999999999999999999999999999999999999999999999999967359 None
5 None None -9999999999999999999999999999999999999999999999999999999999999999999999967359 None
6 9.99999997000000999999997E-7 -999999999999999.99999000000000000000 1 1.000010000000000E-15
7 6858710394965278222222222222292332097.053765195515273635118272569440 None 5555555555555555555555555555555555555555555555555555555555555555555555554363 None
8 1.0000000000000000100000E-8 -999999999999999999.99999000000000000000 -8 1.000010000000000E-15
9 77777777777777777777777778777777776777777.777777777000000000000000000000 None 7777777777777777777777777777777777777777777777777777777777777777777777767877 None
-- !result
SELECT
SUM(CAST(tinyint_val AS decimal(76,20))) as sum_tinyint_as_decimal256,
AVG(CAST(int_val AS decimal(76,20))) as avg_int_as_decimal256,
MIN(CAST(bigint_val AS decimal(76,20))) as min_bigint_as_decimal256,
MAX(CAST(largeint_val AS decimal(76,0))) as max_largeint_as_decimal256
FROM cast_test_source
WHERE tinyint_val IS NOT NULL;
-- result:
141.00000000000000000000 111174220.88888888888888888889 -9223372036854775808.00000000000000000000 170141183460469231731687303715884105727
-- !result
SELECT
SUM(decimal256_50_15) as sum_decimal256_50_15,
AVG(decimal256_76_20) as avg_decimal256_76_20,
MIN(decimal256_76_0) as min_decimal256_76_0,
MAX(decimal256_76_0) as max_decimal256_76_0,
SUM(decimal_38_10) as sum_decimal_38_10,
AVG(decimal_20_5) as avg_decimal_20_5
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL;
-- result:
58024691135802469113580246911358023.469135801246914 6447187903978052123731138545706447187903978052123731138.38545953347187928668 -9999999999999999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999999999999999 5802469113580246911358024689.4691358014 64471879039780.38546000000
-- !result
SELECT
id,
CASE
WHEN tinyint_val > 0 THEN CAST(tinyint_val AS decimal(50,15))
WHEN tinyint_val < 0 THEN CAST(ABS(tinyint_val) AS decimal(50,15))
ELSE 0.000000000000000
END as case_tinyint_to_decimal256,
CASE
WHEN decimal256_50_15 > 0 THEN CAST(decimal256_50_15 AS varchar(100))
WHEN decimal256_50_15 < 0 THEN CONCAT('negative: ', CAST(ABS(decimal256_50_15) AS varchar(100)))
ELSE 'zero'
END as case_decimal256_to_varchar,
CASE
WHEN decimal_38_10 > decimal256_50_15 THEN 'decimal38_larger'
WHEN decimal_38_10 < decimal256_50_15 THEN 'decimal256_larger'
ELSE 'equal'
END as case_decimal_comparison
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- result:
1 127.000000000000000 12345678901234567890123456789012345.123456789012345 decimal256_larger
2 0E-15 zero equal
3 128.000000000000000 negative: 87654321098765432109876543210987654.987654321098765 decimal38_larger
4 127.000000000000000 99999999999999999999999999999999999.999999999999999 decimal256_larger
5 128.000000000000000 negative: 99999999999999999999999999999999999.999999999999999 decimal38_larger
6 1.000000000000000 0.000000000000001 decimal38_larger
7 42.000000000000000 55555555555555555555555555555555555.555555555555555 decimal256_larger
8 1.000000000000000 0.000000000000001 decimal38_larger
9 99.000000000000000 77777777777777777777777777777777777.777777777777777 decimal256_larger
-- !result
SELECT
id,
decimal256_50_15 > CAST(int_val AS decimal(50,15)) as decimal256_gt_int,
decimal256_76_20 = CAST(float_val AS decimal(76,20)) as decimal256_eq_float,
decimal256_76_0 < CAST(largeint_val AS decimal(76,0)) as decimal256_lt_largeint,
CAST(bigint_val AS decimal(76,20)) BETWEEN decimal256_76_20 - 1000 AND decimal256_76_20 + 1000 as bigint_between_decimal256,
decimal256_50_15 > decimal_38_10 as decimal256_gt_decimal38,
decimal_20_5 = CAST(decimal256_50_15 AS decimal(20,5)) as decimal20_eq_decimal256_cast
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL AND decimal256_76_0 IS NOT NULL
AND int_val IS NOT NULL AND float_val IS NOT NULL AND largeint_val IS NOT NULL AND bigint_val IS NOT NULL
AND decimal_38_10 IS NOT NULL AND decimal_20_5 IS NOT NULL
ORDER BY id;
-- result:
1 1 0 0 0 1 None
2 0 1 0 1 0 1
3 0 0 1 0 0 None
4 1 None 0 0 1 None
5 0 None 1 0 0 None
6 0 0 0 1 0 0
7 1 0 0 0 1 None
8 0 0 1 1 0 0
9 1 0 0 0 1 None
-- !result
SELECT id, CAST(tinyint_val AS decimal(76,20)) as unified_decimal256, 'tinyint' as source_type FROM cast_test_source WHERE tinyint_val IS NOT NULL
UNION ALL
SELECT id, CAST(int_val AS decimal(76,20)) as unified_decimal256, 'int' as source_type FROM cast_test_source WHERE int_val IS NOT NULL
UNION ALL
SELECT id, decimal256_76_20 as unified_decimal256, 'decimal256_76_20' as source_type FROM cast_test_source WHERE decimal256_76_20 IS NOT NULL
UNION ALL
SELECT id, CAST(decimal_38_10 AS decimal(76,20)) as unified_decimal256, 'decimal_38_10' as source_type FROM cast_test_source WHERE decimal_38_10 IS NOT NULL
ORDER BY id, unified_decimal256;
-- result:
1 127.00000000000000000000 tinyint
1 2147483647.00000000000000000000 int
1 1234567890123456789012345678.12345678900000000000 decimal_38_10
1 12345678901234567890123456789012345678901234567890123456.12345678901234567890 decimal256_76_20
2 0E-20 int
2 0E-20 decimal_38_10
2 0E-20 tinyint
2 0E-20 decimal256_76_20
3 -87654321098765432109876543210987654321098765432109876543.98765432109876543210 decimal256_76_20
3 -8765432109876543210987654321.98765432100000000000 decimal_38_10
3 -2147483648.00000000000000000000 int
3 -128.00000000000000000000 tinyint
4 127.00000000000000000000 tinyint
4 2147483647.00000000000000000000 int
4 9999999999999999999999999999.99999999990000000000 decimal_38_10
4 99999999999999999999999999999999999999999999999999999999.99999999999999999999 decimal256_76_20
5 -99999999999999999999999999999999999999999999999999999999.99999999999999999999 decimal256_76_20
5 -9999999999999999999999999999.99999999990000000000 decimal_38_10
5 -2147483648.00000000000000000000 int
5 -128.00000000000000000000 tinyint
6 1E-20 decimal256_76_20
6 1.0000000000E-10 decimal_38_10
6 1.00000000000000000000 int
6 1.00000000000000000000 tinyint
7 42.00000000000000000000 tinyint
7 567890.00000000000000000000 int
7 5555555555555555555555555555.55555555550000000000 decimal_38_10
7 55555555555555555555555555555555555555555555555555555555.55555555555555555555 decimal256_76_20
8 1E-20 decimal256_76_20
8 1.0000000000E-10 decimal_38_10
8 1.00000000000000000000 tinyint
8 100.00000000000000000000 int
9 99.00000000000000000000 tinyint
9 999999999.00000000000000000000 int
9 7777777777777777777777777777.77777777770000000000 decimal_38_10
9 77777777777777777777777777777777777777777777777777777777.77777777777777777777 decimal256_76_20
-- !result
CREATE TABLE cast_test_target (
id int,
target_decimal256 decimal(76,20),
target_decimal38 decimal(38,10),
target_int bigint
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
-- result:
-- !result
INSERT INTO cast_test_target VALUES
(1, 12345678901234567890123456789012345678901234567890123456.12345678901234567890, 1234567890123456789012345678.1234567890, 9223372036854775807),
(2, 0.00000000000000000000, 0.0000000000, 0),
(3, -87654321098765432109876543210987654321098765432109876543.98765432109876543210, -8765432109876543210987654321.9876543210, -9223372036854775808),
(4, 99999999999999999999999999999999999999999999999999999999.99999999999999999999, 9999999999999999999999999999.9999999999, 9223372036854775807),
(5, -99999999999999999999999999999999999999999999999999999999.99999999999999999999, -9999999999999999999999999999.9999999999, -9223372036854775808);
-- result:
-- !result
SELECT
id,
CAST('9999999999999999999999999999999999999999999999999999999999999999999999999999' AS decimal(76,0)) as max_decimal256_76_0,
CAST('99999999999999999999999999999999999999999999999999999999.99999999999999999999' AS decimal(76,20)) as max_decimal256_76_20,
CAST('99999999999999999999999999999999999.999999999999999' AS decimal(50,15)) as max_decimal256_50_15
FROM cast_test_source
WHERE id = 1;
-- result:
1 9999999999999999999999999999999999999999999999999999999999999999999999999999 99999999999999999999999999999999999999999999999999999999.99999999999999999999 99999999999999999999999999999999999.999999999999999
-- !result
SELECT
id,
CAST('0.00000000000000000001' AS decimal(76,20)) as min_decimal256_76_20,
CAST('0.000000000000001' AS decimal(50,15)) as min_decimal256_50_15,
CAST('0.0000000001' AS decimal(38,10)) as min_decimal_38_10
FROM cast_test_source
WHERE id = 1;
-- result:
1 1E-20 1E-15 1E-10
-- !result
SELECT
id,
decimal256_76_20,
CAST(decimal256_76_20 AS decimal(50,10)) as decimal256_with_precision_loss,
CAST(decimal256_50_15 AS decimal(38,5)) as decimal256_with_scale_loss,
CAST(decimal_38_10 AS decimal(20,5)) as decimal38_with_precision_loss
FROM cast_test_source
WHERE decimal256_76_20 IS NOT NULL AND decimal256_50_15 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- result:
1 12345678901234567890123456789012345678901234567890123456.12345678901234567890 12345678901234567890123456789012345678901234567890123456.1234567890 None 1234567890123456789012345678.12346
2 0E-20 0E-10 0.00000 0.00000
3 -87654321098765432109876543210987654321098765432109876543.98765432109876543210 -87654321098765432109876543210987654321098765432109876543.9876543211 None -8765432109876543210987654321.98765
4 99999999999999999999999999999999999999999999999999999999.99999999999999999999 100000000000000000000000000000000000000000000000000000000.0000000000 None 10000000000000000000000000000.00000
5 -99999999999999999999999999999999999999999999999999999999.99999999999999999999 -100000000000000000000000000000000000000000000000000000000.0000000000 None -10000000000000000000000000000.00000
6 1E-20 0E-10 0.00000 0.00000
7 55555555555555555555555555555555555555555555555555555555.55555555555555555555 55555555555555555555555555555555555555555555555555555555.5555555556 None 5555555555555555555555555555.55556
8 1E-20 0E-10 0.00000 0.00000
9 77777777777777777777777777777777777777777777777777777777.77777777777777777777 77777777777777777777777777777777777777777777777777777777.7777777778 None 7777777777777777777777777777.77778
-- !result
SELECT
id,
CAST(NULL AS decimal(76,20)) as null_to_decimal256,
CAST(decimal256_50_15 AS varchar(100)) as decimal256_to_varchar_with_null,
COALESCE(CAST(tinyint_val AS decimal(50,15)), 0.000000000000000) as coalesce_cast_tinyint,
COALESCE(CAST(decimal_38_10 AS decimal(76,20)), 0.00000000000000000000) as coalesce_cast_decimal38
FROM cast_test_source
ORDER BY id;
-- result:
1 None 12345678901234567890123456789012345.123456789012345 127.0 1.2345678901234569e+27
2 None 0.000000000000000 0.0 0.0
3 None -87654321098765432109876543210987654.987654321098765 -128.0 -8.765432109876543e+27
4 None 99999999999999999999999999999999999.999999999999999 127.0 1e+28
5 None -99999999999999999999999999999999999.999999999999999 -128.0 -1e+28
6 None 0.000000000000001 1.0 1e-10
7 None 55555555555555555555555555555555555.555555555555555 42.0 5.555555555555556e+27
8 None 0.000000000000001 1.0 1e-10
9 None 77777777777777777777777777777777777.777777777777777 99.0 7.777777777777777e+27
10 None None 0.0 0.0
-- !result

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,413 @@
-- name: test_decimal256_aggregate_function
DROP DATABASE IF EXISTS test_decimal256_agg_func;
CREATE DATABASE test_decimal256_agg_func;
USE test_decimal256_agg_func;
DROP TABLE IF EXISTS decimal256_agg_test;
CREATE TABLE decimal256_agg_test (
id INT,
category VARCHAR(10),
p40s10 DECIMAL(40,10), -- 30 integer digits + 10 decimal digits
p50s15 DECIMAL(50,15), -- 35 integer digits + 15 decimal digits
p76s20 DECIMAL(76,20), -- 56 integer digits + 20 decimal digits
p76s0 DECIMAL(76,0) -- 76 integer digits + 0 decimal digits
) properties("replication_num"="1");
-- Insert test data (simple values with duplicates for testing)
INSERT INTO decimal256_agg_test VALUES
-- Duplicate group 1 - for testing distinct
(1, 'A', 100.1234567890, 100.123456789012345, 100.12345678901234567890, 100),
(2, 'A', 100.1234567890, 100.123456789012345, 100.12345678901234567890, 100),
(3, 'A', 100.1234567890, 100.123456789012345, 100.12345678901234567890, 100),
-- Duplicate group 2
(4, 'B', 200.5555555555, 200.555555555555555, 200.55555555555555555555, 200),
(5, 'B', 200.5555555555, 200.555555555555555, 200.55555555555555555555, 200),
-- Duplicate group 3 - zero values
(6, 'C', 0.0000000000, 0.000000000000000, 0.00000000000000000000, 0),
(7, 'C', 0.0000000000, 0.000000000000000, 0.00000000000000000000, 0),
(8, 'C', 0.0000000000, 0.000000000000000, 0.00000000000000000000, 0),
-- Duplicate group 4 - negative values
(9, 'D', -50.9876543210, -50.987654321098765, -50.98765432109876543210, -50),
(10, 'D', -50.9876543210, -50.987654321098765, -50.98765432109876543210, -50),
-- Unique data
(11, 'E', 300.1111111111, 300.111111111111111, 300.11111111111111111111, 300),
(12, 'F', 400.2222222222, 400.222222222222222, 400.22222222222222222222, 400),
(13, 'G', 500.3333333333, 500.333333333333333, 500.33333333333333333333, 500),
-- Large number duplicates
(14, 'H', 999999999999999999999999999999.9999999999,
99999999999999999999999999999999999.999999999999999,
99999999999999999999999999999999999999999999999999999999.99999999999999999999,
9999999999999999999999999999999999999999999999999999999999999999999999999999),
(15, 'H', 999999999999999999999999999999.9999999999,
99999999999999999999999999999999999.999999999999999,
99999999999999999999999999999999999999999999999999999999.99999999999999999999,
9999999999999999999999999999999999999999999999999999999999999999999999999999),
-- Small decimal duplicates
(16, 'I', 0.0000000001, 0.000000000000001, 0.00000000000000000001, 1),
(17, 'I', 0.0000000001, 0.000000000000001, 0.00000000000000000001, 1),
-- NULL values
(18, 'J', NULL, NULL, NULL, NULL),
(19, 'J', 600.4444444444, 600.444444444444444, 600.44444444444444444444, 600),
-- Mixed duplicates (partial column duplicates)
(20, 'K', 777.7777777777, 777.777777777777777, 777.77777777777777777777, 777),
(21, 'K', 777.7777777777, 888.888888888888888, 999.99999999999999999999, 777),
(22, 'K', 777.7777777777, 777.777777777777777, 777.77777777777777777777, 888);
-- =====================================================
-- Non-DISTINCT aggregate function test cases
-- =====================================================
-- Test 1: Basic COUNT test
SELECT 'Test1_COUNT_BASIC' as test_name, COUNT(*) as total_rows FROM decimal256_agg_test;
SELECT
'Test1_COUNT_NON_NULL' as test_name,
COUNT(p40s10) as count_p40s10,
COUNT(p50s15) as count_p50s15,
COUNT(p76s20) as count_p76s20,
COUNT(p76s0) as count_p76s0
FROM decimal256_agg_test;
-- Test 2: SUM test
SELECT
'Test2_SUM' as test_name,
SUM(p40s10) as sum_p40s10,
SUM(p50s15) as sum_p50s15,
SUM(p76s20) as sum_p76s20,
SUM(p76s0) as sum_p76s0
FROM decimal256_agg_test;
-- Test 3: AVG test
SELECT
'Test3_AVG' as test_name,
AVG(p40s10) as avg_p40s10,
AVG(p50s15) as avg_p50s15,
AVG(p76s20) as avg_p76s20,
AVG(p76s0) as avg_p76s0
FROM decimal256_agg_test;
-- Test 4: MIN/MAX test
SELECT
'Test4_MIN_MAX' as test_name,
MIN(p40s10) as min_p40s10,
MAX(p40s10) as max_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p50s15) as max_p50s15,
MIN(p76s20) as min_p76s20,
MAX(p76s20) as max_p76s20,
MIN(p76s0) as min_p76s0,
MAX(p76s0) as max_p76s0
FROM decimal256_agg_test;
-- Test 5: Group by aggregation (non-DISTINCT)
SELECT
'Test5_GROUP_BY_CATEGORY' as test_name,
category,
COUNT(*) as row_count,
SUM(p40s10) as sum_p40s10,
AVG(p40s10) as avg_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p76s20) as max_p76s20
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
-- Test 6: Group by decimal column (non-DISTINCT)
SELECT
'Test6_GROUP_BY_P40S10' as test_name,
p40s10,
COUNT(*) as row_count,
SUM(p50s15) as sum_p50s15,
AVG(p50s15) as avg_p50s15,
MIN(p76s0) as min_p76s0,
MAX(p76s0) as max_p76s0
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
GROUP BY p40s10
ORDER BY p40s10;
-- =====================================================
-- DISTINCT test cases - each case tests both planners
-- =====================================================
-- Test 7: COUNT DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test7_COUNT_DISTINCT_planner0' as test_name,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p50s15) as distinct_p50s15,
COUNT(DISTINCT p76s20) as distinct_p76s20,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=2;
SELECT
'Test7_COUNT_DISTINCT_planner2' as test_name,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p50s15) as distinct_p50s15,
COUNT(DISTINCT p76s20) as distinct_p76s20,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=0;
-- Test 8: SUM DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test8_SUM_DISTINCT_planner0' as test_name,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15,
SUM(DISTINCT p76s20) as sum_distinct_p76s20,
SUM(DISTINCT p76s0) as sum_distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=2;
SELECT
'Test8_SUM_DISTINCT_planner2' as test_name,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15,
SUM(DISTINCT p76s20) as sum_distinct_p76s20,
SUM(DISTINCT p76s0) as sum_distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=0;
-- Test 9: AVG DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test9_AVG_DISTINCT_planner0' as test_name,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p50s15) as avg_distinct_p50s15,
AVG(DISTINCT p76s20) as avg_distinct_p76s20,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=2;
SELECT
'Test9_AVG_DISTINCT_planner2' as test_name,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p50s15) as avg_distinct_p50s15,
AVG(DISTINCT p76s20) as avg_distinct_p76s20,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=0;
-- Test 10: Group by COUNT DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test10_GROUP_COUNT_DISTINCT_planner0' as test_name,
category,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
set new_planner_agg_stage=2;
SELECT
'Test10_GROUP_COUNT_DISTINCT_planner2' as test_name,
category,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
COUNT(DISTINCT p76s0) as distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
set new_planner_agg_stage=0;
-- Test 11: Group by SUM DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test11_GROUP_SUM_DISTINCT_planner0' as test_name,
category,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
set new_planner_agg_stage=2;
SELECT
'Test11_GROUP_SUM_DISTINCT_planner2' as test_name,
category,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
set new_planner_agg_stage=0;
-- Test 12: Group by AVG DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test12_GROUP_AVG_DISTINCT_planner0' as test_name,
category,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
set new_planner_agg_stage=2;
SELECT
'Test12_GROUP_AVG_DISTINCT_planner2' as test_name,
category,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test
GROUP BY category
ORDER BY category;
set new_planner_agg_stage=0;
-- Test 13: Group by decimal column DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test13_GROUP_BY_DECIMAL_DISTINCT_planner0' as test_name,
p76s0,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10
FROM decimal256_agg_test
WHERE p76s0 IS NOT NULL
GROUP BY p76s0
ORDER BY p76s0;
set new_planner_agg_stage=2;
SELECT
'Test13_GROUP_BY_DECIMAL_DISTINCT_planner2' as test_name,
p76s0,
COUNT(*) as row_count,
COUNT(DISTINCT p40s10) as distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10
FROM decimal256_agg_test
WHERE p76s0 IS NOT NULL
GROUP BY p76s0
ORDER BY p76s0;
set new_planner_agg_stage=0;
-- Test 14: SELECT DISTINCT single column test
set new_planner_agg_stage=0;
SELECT DISTINCT 'Test14_SELECT_DISTINCT_SINGLE_planner0' as test_name, p40s10
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10;
set new_planner_agg_stage=2;
SELECT DISTINCT 'Test14_SELECT_DISTINCT_SINGLE_planner2' as test_name, p40s10
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10;
set new_planner_agg_stage=0;
-- Test 15: SELECT DISTINCT multiple columns test
set new_planner_agg_stage=0;
SELECT DISTINCT 'Test15_SELECT_DISTINCT_MULTI_planner0' as test_name, p40s10, p50s15, p76s0
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10, p50s15;
set new_planner_agg_stage=2;
SELECT DISTINCT 'Test15_SELECT_DISTINCT_MULTI_planner2' as test_name, p40s10, p50s15, p76s0
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
ORDER BY p40s10, p50s15;
set new_planner_agg_stage=0;
-- Test 16: Complex DISTINCT query test
set new_planner_agg_stage=0;
SELECT
'Test16_COMPLEX_DISTINCT_planner0' as test_name,
COUNT(DISTINCT p40s10) as count_distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
COUNT(DISTINCT p76s0) as count_distinct_p76s0,
SUM(DISTINCT p76s0) as sum_distinct_p76s0,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=2;
SELECT
'Test16_COMPLEX_DISTINCT_planner2' as test_name,
COUNT(DISTINCT p40s10) as count_distinct_p40s10,
SUM(DISTINCT p40s10) as sum_distinct_p40s10,
AVG(DISTINCT p40s10) as avg_distinct_p40s10,
COUNT(DISTINCT p76s0) as count_distinct_p76s0,
SUM(DISTINCT p76s0) as sum_distinct_p76s0,
AVG(DISTINCT p76s0) as avg_distinct_p76s0
FROM decimal256_agg_test;
set new_planner_agg_stage=0;
-- Test 17: HAVING with DISTINCT test
set new_planner_agg_stage=0;
SELECT
'Test17_HAVING_DISTINCT_planner0' as test_name,
p40s10,
COUNT(*) as row_count,
COUNT(DISTINCT p50s15) as distinct_p50s15,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
GROUP BY p40s10
HAVING COUNT(*) > 1
ORDER BY p40s10;
set new_planner_agg_stage=2;
SELECT
'Test17_HAVING_DISTINCT_planner2' as test_name,
p40s10,
COUNT(*) as row_count,
COUNT(DISTINCT p50s15) as distinct_p50s15,
SUM(DISTINCT p50s15) as sum_distinct_p50s15
FROM decimal256_agg_test
WHERE p40s10 IS NOT NULL
GROUP BY p40s10
HAVING COUNT(*) > 1
ORDER BY p40s10;
set new_planner_agg_stage=0;
-- =====================================================
-- Edge case tests
-- =====================================================
-- Test 18: Empty result set
SELECT
'Test18_EMPTY_RESULT' as test_name,
COUNT(*) as count_all,
SUM(p40s10) as sum_p40s10,
AVG(p40s10) as avg_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p76s20) as max_p76s20
FROM decimal256_agg_test
WHERE id > 1000;
-- Test 19: NULL values only
SELECT
'Test19_NULL_ONLY' as test_name,
COUNT(*) as count_all,
COUNT(p40s10) as count_p40s10,
SUM(p50s15) as sum_p50s15,
AVG(p50s15) as avg_p50s15
FROM decimal256_agg_test
WHERE id = 18;
-- Test 20: Single row result
SELECT
'Test20_SINGLE_ROW' as test_name,
COUNT(*) as count_all,
SUM(p40s10) as sum_p40s10,
AVG(p40s10) as avg_p40s10,
MIN(p50s15) as min_p50s15,
MAX(p76s20) as max_p76s20
FROM decimal256_agg_test
WHERE id = 11;

View File

@ -0,0 +1,424 @@
-- name: test_decimal256_arithmetic_overflow
DROP DATABASE IF EXISTS test_decimal256_overflow;
CREATE DATABASE test_decimal256_overflow;
USE test_decimal256_overflow;
-- =============================================================================
-- TEST-0: int256 boundary values extreme cases
-- =============================================================================
CREATE TABLE powers_of_2 (
power_250 DECIMAL(76, 0)
) PROPERTIES("replication_num"="1");
-- pow(2, 250)
insert into powers_of_2 select 1809251394333065553493296640760748560207343510400633813116524750123642650624;
-- INT_256MAX
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 as string) from powers_of_2;
-- INT_256MIN
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- INT_256MAX + 1 (overflow)
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 + 1 as string) from powers_of_2;
-- INT_256MAX - 1 (INT_256MAX - 1)
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 - 1 as string) from powers_of_2;
-- INT_256MAX * 0 (0)
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * 0 as string) from powers_of_2;
-- INT_256MAX * -1 (-INT_256MAX)
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * -1 as string) from powers_of_2;
-- INT_256MAX * 2 (overflow)
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * 2 as string) from powers_of_2;
-- INT_256MAX * -2 (overflow)
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * -2 as string) from powers_of_2;
-- INT_256MIN - 1 (overflow)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) - 1 as string) from powers_of_2;
-- INT_256MIN + 1 (not overflow)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) + 1 as string) from powers_of_2;
-- INT_256MIN * 1 (INT_256MIN)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * 1 as string) from powers_of_2;
-- INT_256MIN * -1 (overflow. special case)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * -1 as string) from powers_of_2;
-- INT_256MIN * -2 (overflow)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * -2 as string) from powers_of_2;
-- INT_256MIN * 2 (overflow)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * 2 as string) from powers_of_2;
-- INT_256MIN * 0 (0)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * 0 as string) from powers_of_2;
-- INT_256MIN + INT256_MAX(-1)
select cast(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495 + (-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- INT_256MAX * INT_256MIN (overflow)
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * (-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- INT_256MAX * INT_256MAX (overflow)
select cast((power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) * (power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) as string) from powers_of_2;
-- INT_256MIN * INT_256MIN (overflow)
select cast((-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) * (-(power_250 * 16 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602496 + 7237005577332262213973186563042994240829374041602535252466099000494570602495) - 1) as string) from powers_of_2;
-- TEST INT_256MAX result (bit count is 256)
create table test_256max_result(d1 decimal(76, 0)) PROPERTIES("replication_num"="1");
insert into test_256max_result select 1496577676626844588240573307387100039795808514605057;
select cast(d1 * 38685626227668133590597631 as string) from test_256max_result;
-- TEST INT_256MIN result (bit count is 257)
create table test_256min_result(d1 decimal(76, 0), d2 decimal(76, 0)) PROPERTIES("replication_num"="1");
insert into test_256min_result select 340282366920938463463374607431768211456, -170141183460469231731687303715884105728;
select cast(d1 * d2 as string) from test_256min_result; -- 2^128 * -2^127
CREATE TABLE test_decimal_multiply_overflow (
id INT,
case_desc VARCHAR(200),
d60_30 DECIMAL(60, 30),
d70_20 DECIMAL(70, 20),
d76_10 DECIMAL(76, 10),
d76_38 DECIMAL(76, 38),
d50_0 DECIMAL(50, 0),
d38_0 DECIMAL(38, 0) -- Maximum 38-digit decimal number
) PROPERTIES("replication_num"="1");
-- Insert test data
INSERT INTO test_decimal_multiply_overflow VALUES
-- 1. Small values
(1, 'Small values',
1.123456789012345678901234567890,
12.12345678901234567890,
123.1234567890,
0.12345678901234567890123456789012345678,
1000,
12345),
-- 2. Medium values
(2, 'Medium values',
123456789012345678901234567890.123456789012345678901234567890, -- 60 digits
12345678901234567890123456789012345678901234567890.12345678901234567890, -- 70 digits
1234567890123456789012345678901234567890123456789012345678901234.1234567890, -- 76 digits
12345678901234567890123456789012345678.12345678901234567890123456789012345678, -- 76 digits
12345678901234567890123456789012345678901234567890, -- 50 digits
12345678901234567890123456789012345678), -- 38 digits
-- 3. Near maximum values for each type
(3, 'Near max positive values',
999999999999999999999999999999.999999999999999999999999999999, -- d60_30 maximum
99999999999999999999999999999999999999999999999999.99999999999999999999, -- d70_20 maximum
9999999999999999999999999999999999999999999999999999999999999999.9999999999, -- d76_10 maximum
99999999999999999999999999999999999999.99999999999999999999999999999999999999, -- d76_38 maximum
99999999999999999999999999999999999999999999999999, -- d50_0 maximum
99999999999999999999999999999999999999), -- d38_0 maximum (38 nines)
-- 4. Corresponding negative values
(4, 'Near max negative values',
-999999999999999999999999999999.999999999999999999999999999999,
-99999999999999999999999999999999999999999999999999.99999999999999999999,
-9999999999999999999999999999999999999999999999999999999999999999.9999999999,
-99999999999999999999999999999999999999.99999999999999999999999999999999999999,
-99999999999999999999999999999999999999999999999999,
-99999999999999999999999999999999999999);
-- =============================================================================
-- Create dedicated boundary value test table
-- =============================================================================
CREATE TABLE test_boundary_values (
id INT,
case_desc VARCHAR(200),
-- Designed based on actual DECIMAL precision limits
val_76_0 DECIMAL(76, 0),
val_38_0 DECIMAL(38, 0),
val_19_0 DECIMAL(19, 0),
val_25_0 DECIMAL(25, 0),
val_high_scale DECIMAL(76, 50)
) PROPERTIES("replication_num"="1");
INSERT INTO test_boundary_values VALUES
-- 1. Near 76-digit decimal maximum
(1, 'Near 76-digit decimal max',
9999999999999999999999999999999999999999999999999999999999999999999999999999, -- 76 nines
99999999999999999999999999999999999999, -- 38 nines
9999999999999999999, -- 19 nines
9999999999999999999999999, -- 25 nines
0.00000000000000000000000000000000000000000000000001),
-- 2. Corresponding negative values
(2, 'Near 76-digit decimal min',
-9999999999999999999999999999999999999999999999999999999999999999999999999999,
-99999999999999999999999999999999999999,
-9999999999999999999,
-9999999999999999999999999,
-0.00000000000000000000000000000000000000000000000001),
-- 3. Values for testing multiplication overflow
(3, 'Multiplication overflow test values',
1000000000000000000000000000000000000000000000000000000000000000000000000000, -- 76-digit 10^75
10000000000000000000000000000000000000, -- 38-digit 10^37
1000000000000000000, -- 19-digit 10^18
1000000000000000000000000, -- 25-digit 10^24
0.00000000000000000000000000000000000000000000000001),
-- 4. Medium size values
(4, 'Medium size values',
5000000000000000000000000000000000000000000000000000000000000000000000000000, -- 76-digit 5*10^75
50000000000000000000000000000000000000, -- 38-digit 5*10^37
5000000000000000000, -- 19-digit 5*10^18
5000000000000000000000000, -- 25-digit 5*10^24
0.50000000000000000000000000000000000000000000000000);
-- =============================================================================
-- Test 1: Positive number multiplication overflow
-- =============================================================================
-- Test 76-digit max multiplication (definite overflow)
SELECT
'Test 1.1: 76-digit max * 76-digit max (definite overflow)' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * val_76_0 as string) as result,
'Should overflow: 10^75 * 10^75 = 10^150, way beyond int256' as expected
FROM test_boundary_values WHERE id = 1;
-- Test 38-digit max multiplication (may overflow)
SELECT
'Test 1.2: 38-digit max * 38-digit max (may overflow)' as test_case,
cast(val_38_0 as string),
cast(cast(val_38_0 as decimal(76, 0)) * val_38_0 as string) as result,
'not overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- Test 19-digit multiplication (should not overflow)
SELECT
'Test 1.3: 19-digit * 19-digit (should not overflow)' as test_case,
cast(val_19_0 as string),
cast(val_19_0 * val_19_0 as string) as result,
'Should not overflow: 10^18 * 10^18 = 10^36, within int256' as expected
FROM test_boundary_values WHERE id = 1;
-- Test large number multiplied by 2
SELECT
'Test 1.4: Large value * 2' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 2 as string) as result,
'Should overflow: near-max * 2' as expected
FROM test_boundary_values WHERE id = 1;
-- Test large number multiplied by 5 (not overflow)
SELECT
'Test 1.5: Large value * 5' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 5 as string) as result,
'Should overflow: near-max * 5' as expected
FROM test_boundary_values WHERE id = 1;
-- Test large number multiplied by 5.1 (overflow)
SELECT
'Test 1.6: Large value * 5.1' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 5.1 as string) as result,
'Should overflow: near-max * 5.1' as expected
FROM test_boundary_values WHERE id = 1;
-- Test large number multiplied by 6 (overflow)
SELECT
'Test 1.7: Large value * 6' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 6 as string) as result,
'Should overflow: near-max * 6' as expected
FROM test_boundary_values WHERE id = 1;
-- =============================================================================
-- Test 2: Negative number multiplication overflow
-- =============================================================================
-- Test large negative * large negative = positive overflow
SELECT
'Test 2.1: Large negative * Large negative (positive overflow)' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * val_76_0 as string) as result,
'Should overflow: (-10^75) * (-10^75) = +10^150' as expected
FROM test_boundary_values WHERE id = 2;
-- Test large negative * positive = negative overflow
SELECT
'Test 2.2: Large negative * Large positive (negative overflow)' as test_case,
cast(a.val_76_0 as string) as neg_val,
cast(b.val_76_0 as string) as pos_val,
cast(a.val_76_0 * b.val_76_0 as string) as result,
'Should overflow: (-10^75) * (+10^75) = -10^150' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 2 AND b.id = 1;
-- Test negative boundary case
SELECT
'Test 2.3: Negative boundary * 5' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 5 as string) as result,
'Should not overflow' as expected
FROM test_boundary_values WHERE id = 2;
-- Test negative boundary case
SELECT
'Test 2.4: Negative boundary * 6' as test_case,
cast(val_76_0 as string),
cast(val_76_0 * 6 as string) as result,
'Should overflow' as expected
FROM test_boundary_values WHERE id = 2;
-- =============================================================================
-- Test 3: Different precision combination overflow tests
-- =============================================================================
-- 76-digit * 38-digit
SELECT
'Test 3.1: 76-digit * 38-digit' as test_case,
cast(a.val_76_0 as string),
cast(b.val_38_0 as string),
cast(a.val_76_0 * b.val_38_0 as string) as result,
'Should overflow: 10^75 * 10^37 = 10^112' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 1 AND b.id = 1;
-- 38-digit * 25-digit
-- can't auto scale up now
SELECT
'Test 3.2: 38-digit * 25-digit' as test_case,
cast(a.val_38_0 as string),
cast(b.val_25_0 as string),
cast(a.val_38_0 * b.val_25_0 as string) as result,
'overflow' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 1 AND b.id = 1;
-- 38-digit * 25-digit
SELECT
'Test 3.2: 38-digit * 25-digit' as test_case,
cast(a.val_38_0 as string),
cast(b.val_25_0 as string),
cast(cast(a.val_38_0 as decimal(50, 10)) * b.val_25_0 as string) as result,
'should not overflow' as expected
FROM test_boundary_values a, test_boundary_values b
WHERE a.id = 1 AND b.id = 1;
-- 25-digit * 25-digit
-- can't auto scale up now
SELECT
'Test 3.3: 25-digit * 25-digit' as test_case,
cast(val_25_0 as string),
cast(val_25_0 * val_25_0 as string) as result,
'overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- 25-digit * 25-digit
SELECT
'Test 3.3: 25-digit * 25-digit' as test_case,
cast(val_25_0 as string),
cast(val_25_0 * cast(val_25_0 as decimal(39, 0)) as string) as result,
'should not overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- =============================================================================
-- Test 4: Progressive boundary testing
-- =============================================================================
CREATE TABLE test_progressive_boundary (
id INT,
digits INT,
test_val DECIMAL(76, 0)
) PROPERTIES("replication_num"="1");
-- Insert different digit count test values
INSERT INTO test_progressive_boundary VALUES
(1, 10, 9999999999), -- 10 digits
(2, 15, 999999999999999), -- 15 digits
(3, 20, 99999999999999999999), -- 20 digits
(4, 25, 9999999999999999999999999), -- 25 digits
(5, 30, 999999999999999999999999999999), -- 30 digits
(6, 35, 99999999999999999999999999999999999), -- 35 digits
(7, 38, 99999999999999999999999999999999999999); -- 38 digits
-- Test self-multiplication, observe overflow boundary
SELECT
id,
digits,
cast(test_val as string),
cast(test_val * test_val as string) as result,
CASE
WHEN digits <= 19 THEN 'Should succeed'
WHEN digits <= 25 THEN 'May succeed'
WHEN digits > 30 THEN 'Should succeed'
ELSE 'Boundary case'
END as expected
FROM test_progressive_boundary ORDER BY id;
-- =============================================================================
-- Test 5: Scale overflow vs value overflow distinction
-- =============================================================================
-- throw exception
SELECT
'Test 5.1: Scale overflow, tiny value' as test_case,
cast(val_high_scale * val_high_scale as string) as result,
'Should fail due to scale=100 > 76' as expected
FROM test_boundary_values WHERE id = 1;
-- Value overflow but reasonable scale
SELECT
'Test 5.2: Value overflow, scale OK' as test_case,
cast(val_38_0 * val_38_0 as string) as result,
'Should fail due to value overflow, scale=0 is fine' as expected
FROM test_boundary_values WHERE id = 1;
-- =============================================================================
-- Test 6: Special values and boundary cases
-- =============================================================================
-- Multiply by 0
SELECT
'Test 6.1: Large * 0' as test_case,
cast(val_76_0 * 0 as string) as result,
'Should return 0, no overflow' as expected
FROM test_boundary_values WHERE id = 1;
-- Multiply by 1
SELECT
'Test 6.2: Large * 1' as test_case,
cast(val_76_0 * 1 as string) as result,
'Should return original value' as expected
FROM test_boundary_values WHERE id = 1;
-- Multiply by decimal
SELECT
'Test 6.3: Large * 0.1' as test_case,
cast(val_76_0 * 0.1 as string) as result,
'Should succeed, reduces magnitude' as expected
FROM test_boundary_values WHERE id = 1;
-- Multiply by -1
SELECT
'Test 6.4: Large * -1' as test_case,
cast(val_76_0 * (-1) as string) as result,
'Should return negative of original' as expected
FROM test_boundary_values WHERE id = 1;
-- =============================================================================
-- Test 7: Real-world scenario boundary tests
-- =============================================================================
-- Test scientific computation scenario
SELECT
'Test 7.2: Scientific calculation' as test_case,
cast(d76_10 * d76_10 as string) as result,
'Simulates scientific computation overflow' as expected
FROM test_decimal_multiply_overflow WHERE id = 3;

View File

@ -0,0 +1,437 @@
-- name: test_decimal256_cast_operations
DROP DATABASE IF EXISTS test_decimal256_cast;
CREATE DATABASE test_decimal256_cast;
USE test_decimal256_cast;
-- Create test table with various data types
CREATE TABLE cast_test_source (
id int,
bool_val boolean,
tinyint_val tinyint,
smallint_val smallint,
int_val int,
bigint_val bigint,
largeint_val largeint,
float_val float,
double_val double,
varchar_val varchar(100),
-- decimal256 columns for testing (precision > 38, <= 76)
decimal256_50_15 decimal(50,15), -- 50 digits total, 15 after decimal
decimal256_76_20 decimal(76,20), -- 76 digits total, 20 after decimal
decimal256_76_0 decimal(76,0), -- 76 digits total, 0 after decimal
-- regular decimal columns for comparison (precision <= 38)
decimal_38_10 decimal(38,10), -- 38 digits total, 10 after decimal
decimal_20_5 decimal(20,5) -- 20 digits total, 5 after decimal
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
-- Insert comprehensive test data with correct digit limits
INSERT INTO cast_test_source VALUES
-- Basic values - decimal256 (50,15): max 35 digits before decimal, 15 after
-- decimal256 (76,20): max 56 digits before decimal, 20 after
-- decimal256 (76,0): max 76 digits before decimal, 0 after
(1, true, 127, 32767, 2147483647, 9223372036854775807, 170141183460469231731687303715884105727,
3.14159, 2.718281828459045, '12345678901234567890123456789012345.123456789012345',
12345678901234567890123456789012345.123456789012345, -- 35+15=50 digits
12345678901234567890123456789012345678901234567890123456.12345678901234567890, -- 56+20=76 digits
1234567890123456789012345678901234567890123456789012345678901234567890123456, -- 76 digits
1234567890123456789012345678.1234567890, -- 28+10=38 digits
123456789012345.12345), -- 15+5=20 digits
-- Zero values
(2, false, 0, 0, 0, 0, 0, 0.0, 0.0, '0',
0.000000000000000,
0.00000000000000000000,
0,
0.0000000000,
0.00000),
-- Negative values
(3, false, -128, -32768, -2147483648, -9223372036854775808, -170141183460469231731687303715884105728,
-3.14159, -2.718281828459045, '-87654321098765432109876543210987654.987654321098765',
-87654321098765432109876543210987654.987654321098765, -- 35+15=50 digits
-87654321098765432109876543210987654321098765432109876543.98765432109876543210, -- 56+20=76 digits
-8765432109876543210987654321098765432109876543210987654321098765432109876543, -- 76 digits
-8765432109876543210987654321.9876543210, -- 28+10=38 digits
-876543210987654.98765), -- 15+5=20 digits
-- Maximum positive values within limits
(4, true, 127, 32767, 2147483647, 9223372036854775807, 170141183460469231731687303715884105727,
1.7976931348623157e+308, 1.7976931348623157e+308, '99999999999999999999999999999999999.999999999999999',
99999999999999999999999999999999999.999999999999999, -- 35+15=50 digits
99999999999999999999999999999999999999999999999999999999.99999999999999999999, -- 56+20=76 digits
9999999999999999999999999999999999999999999999999999999999999999999999999999, -- 76 digits
9999999999999999999999999999.9999999999, -- 28+10=38 digits
999999999999999.99999), -- 15+5=20 digits
-- Minimum values (most negative) within limits
(5, false, -128, -32768, -2147483648, -9223372036854775808, -170141183460469231731687303715884105728,
-1.7976931348623157e+308, -1.7976931348623157e+308, '-99999999999999999999999999999999999.999999999999999',
-99999999999999999999999999999999999.999999999999999, -- 35+15=50 digits
-99999999999999999999999999999999999999999999999999999999.99999999999999999999, -- 56+20=76 digits
-9999999999999999999999999999999999999999999999999999999999999999999999999999, -- 76 digits
-9999999999999999999999999999.9999999999, -- 28+10=38 digits
-999999999999999.99999), -- 15+5=20 digits
-- Small fractional values
(6, true, 1, 1, 1, 1, 1, 0.000001, 0.000000000000001, '0.000000000000001',
0.000000000000001,
0.00000000000000000001,
1,
0.0000000001,
0.00001),
-- Mid-range values
(7, false, 42, 1234, 567890, 123456789012345, 987654321098765432109876543210,
123.456789, 987.654321123456789, '555555555555555555555555555555555.555555555555555',
55555555555555555555555555555555555.555555555555555, -- 35+15=50 digits
55555555555555555555555555555555555555555555555555555555.55555555555555555555, -- 56+20=76 digits
5555555555555555555555555555555555555555555555555555555555555555555555555555, -- 76 digits
5555555555555555555555555555.5555555555, -- 28+10=38 digits
555555555555555.55555), -- 15+5=20 digits
-- Edge case: very small positive numbers
(8, true, 1, 10, 100, 1000, 10000,
1e-10, 1e-15, '0.000000000000001',
0.000000000000001,
0.00000000000000000001,
1,
0.0000000001,
0.00001),
-- Edge case: numbers with many digits but within limits
(9, false, 99, 9999, 999999999, 999999999999999999, 99999999999999999999999999999999999999,
999999.999999, 999999999.999999999999, '77777777777777777777777777777777777.777777777777777',
77777777777777777777777777777777777.777777777777777, -- 35+15=50 digits
77777777777777777777777777777777777777777777777777777777.77777777777777777777, -- 56+20=76 digits
7777777777777777777777777777777777777777777777777777777777777777777777777777, -- 76 digits
7777777777777777777777777777.7777777777, -- 28+10=38 digits
777777777777777.77777), -- 15+5=20 digits
-- NULL values for testing
(10, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-- Test 1: CAST from boolean to decimal256
SELECT
id,
bool_val,
CAST(bool_val AS decimal(50,15)) as bool_to_decimal256_50_15,
CAST(bool_val AS decimal(76,20)) as bool_to_decimal256_76_20,
CAST(bool_val AS decimal(76,0)) as bool_to_decimal256_76_0,
CAST(bool_val AS decimal(38,10)) as bool_to_decimal_38_10
FROM cast_test_source
ORDER BY id;
-- Test 2: CAST from integer types to decimal256
SELECT
id,
tinyint_val,
CAST(tinyint_val AS decimal(50,15)) as tinyint_to_decimal256,
smallint_val,
CAST(smallint_val AS decimal(50,15)) as smallint_to_decimal256,
int_val,
CAST(int_val AS decimal(50,15)) as int_to_decimal256
FROM cast_test_source
ORDER BY id;
SELECT
id,
bigint_val,
CAST(bigint_val AS decimal(76,20)) as bigint_to_decimal256,
largeint_val,
CAST(largeint_val AS decimal(76,0)) as largeint_to_decimal256
FROM cast_test_source
ORDER BY id;
-- Test 3: CAST from floating point types to decimal256
SELECT
id,
float_val,
CAST(float_val AS decimal(50,15)) as float_to_decimal256_50_15,
CAST(float_val AS decimal(76,20)) as float_to_decimal256_76_20,
double_val,
CAST(double_val AS decimal(50,15)) as double_to_decimal256_50_15,
CAST(double_val AS decimal(76,20)) as double_to_decimal256_76_20
FROM cast_test_source
ORDER BY id;
-- Test 4: CAST from varchar to decimal256
SELECT
id,
varchar_val,
CAST(varchar_val AS decimal(50,15)) as varchar_to_decimal256_50_15,
CAST(varchar_val AS decimal(76,20)) as varchar_to_decimal256_76_20,
CAST(varchar_val AS decimal(76,0)) as varchar_to_decimal256_76_0
FROM cast_test_source
WHERE varchar_val IS NOT NULL
ORDER BY id;
-- Test 5: CAST from decimal256 to other types
SELECT
id,
decimal256_50_15,
CAST(decimal256_50_15 AS boolean) as decimal256_to_bool,
CAST(decimal256_50_15 AS tinyint) as decimal256_to_tinyint,
CAST(decimal256_50_15 AS smallint) as decimal256_to_smallint,
CAST(decimal256_50_15 AS int) as decimal256_to_int,
CAST(decimal256_50_15 AS bigint) as decimal256_to_bigint,
CAST(decimal256_50_15 AS largeint) as decimal256_to_largeint
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL
ORDER BY id;
SELECT
id,
decimal256_76_20,
CAST(decimal256_76_20 AS float) as decimal256_to_float,
CAST(decimal256_76_20 AS double) as decimal256_to_double,
CAST(decimal256_76_20 AS varchar(100)) as decimal256_to_varchar
FROM cast_test_source
WHERE decimal256_76_20 IS NOT NULL
ORDER BY id;
-- Test 6: CAST between different decimal precisions
SELECT
id,
decimal256_50_15,
CAST(decimal256_50_15 AS decimal(76,20)) as decimal256_50_15_to_76_20,
CAST(decimal256_50_15 AS decimal(76,0)) as decimal256_50_15_to_76_0,
CAST(decimal256_50_15 AS decimal(38,10)) as decimal256_50_15_to_38_10,
decimal256_76_20,
CAST(decimal256_76_20 AS decimal(50,15)) as decimal256_76_20_to_50_15,
CAST(decimal256_76_20 AS decimal(76,0)) as decimal256_76_20_to_76_0
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL
ORDER BY id;
-- Test 7: CAST between decimal256 and regular decimal
SELECT
id,
decimal_38_10,
CAST(decimal_38_10 AS decimal(50,15)) as decimal_38_10_to_decimal256_50_15,
CAST(decimal_38_10 AS decimal(76,20)) as decimal_38_10_to_decimal256_76_20,
decimal256_50_15,
CAST(decimal256_50_15 AS decimal(38,10)) as decimal256_50_15_to_decimal_38_10,
CAST(decimal256_50_15 AS decimal(20,5)) as decimal256_50_15_to_decimal_20_5
FROM cast_test_source
WHERE decimal_38_10 IS NOT NULL AND decimal256_50_15 IS NOT NULL
ORDER BY id;
-- Test 8: Arithmetic operations with automatic casting
-- Addition with different types
SELECT
id,
decimal256_50_15 + tinyint_val as decimal256_plus_tinyint,
decimal256_50_15 + smallint_val as decimal256_plus_smallint,
decimal256_50_15 + int_val as decimal256_plus_int,
decimal256_50_15 + bigint_val as decimal256_plus_bigint,
decimal256_50_15 + largeint_val as decimal256_plus_largeint
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND tinyint_val IS NOT NULL
ORDER BY id;
SELECT
id,
decimal256_76_20 + float_val as decimal256_plus_float,
decimal256_76_20 + double_val as decimal256_plus_double,
decimal256_50_15 + decimal_38_10 as decimal256_plus_decimal38
FROM cast_test_source
WHERE decimal256_76_20 IS NOT NULL AND float_val IS NOT NULL AND decimal256_50_15 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- Subtraction with different types
SELECT
id,
decimal256_50_15 - tinyint_val as decimal256_minus_tinyint,
decimal256_50_15 - smallint_val as decimal256_minus_smallint,
decimal256_50_15 - int_val as decimal256_minus_int,
decimal256_50_15 - bigint_val as decimal256_minus_bigint,
decimal256_76_20 - decimal_38_10 as decimal256_minus_decimal38
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND tinyint_val IS NOT NULL AND decimal256_76_20 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- Multiplication with different types
SELECT
id,
decimal256_50_15 * tinyint_val as decimal256_multiply_tinyint,
decimal256_50_15 * smallint_val as decimal256_multiply_smallint,
decimal256_76_20 * float_val as decimal256_multiply_float,
decimal256_76_20 * double_val as decimal256_multiply_double,
decimal256_50_15 * decimal_20_5 as decimal256_multiply_decimal20
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL AND tinyint_val IS NOT NULL
AND float_val IS NOT NULL AND decimal_20_5 IS NOT NULL
ORDER BY id;
-- Division with different types
SELECT
id,
decimal256_50_15 / tinyint_val as decimal256_divide_tinyint,
decimal256_50_15 / smallint_val as decimal256_divide_smallint,
decimal256_76_20 / float_val as decimal256_divide_float,
decimal256_76_20 / double_val as decimal256_divide_double,
decimal256_50_15 / decimal_20_5 as decimal256_divide_decimal20
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL
AND tinyint_val IS NOT NULL AND tinyint_val != 0 AND smallint_val != 0
AND float_val IS NOT NULL AND float_val != 0 AND double_val IS NOT NULL AND double_val != 0
AND decimal_20_5 IS NOT NULL AND decimal_20_5 != 0
ORDER BY id;
-- Test 9: Mixed arithmetic operations between decimal256 columns
SELECT
id,
decimal256_50_15 + decimal256_76_20 as decimal256_addition,
decimal256_50_15 - decimal256_76_20 as decimal256_subtraction,
decimal256_50_15 * decimal256_76_0 as decimal256_multiplication,
decimal256_76_20 / decimal256_76_0 as decimal256_division
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL
AND decimal256_76_0 IS NOT NULL AND decimal256_76_0 != 0
ORDER BY id;
-- Test 10: Complex arithmetic expressions with casting
SELECT
id,
(decimal256_50_15 + CAST(int_val AS decimal(50,15))) * CAST(float_val AS decimal(50,15)) as complex_expr1,
(decimal256_76_20 - CAST(bigint_val AS decimal(76,20))) / CAST(double_val AS decimal(76,20)) as complex_expr2,
CAST(tinyint_val AS decimal(76,0)) + decimal256_76_0 - CAST(smallint_val AS decimal(76,0)) as complex_expr3,
(decimal256_50_15 + decimal_38_10) * CAST(decimal_20_5 AS decimal(50,15)) as complex_expr4
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL AND decimal256_76_0 IS NOT NULL
AND int_val IS NOT NULL AND float_val IS NOT NULL AND float_val != 0
AND bigint_val IS NOT NULL AND double_val IS NOT NULL AND double_val != 0
AND tinyint_val IS NOT NULL AND smallint_val IS NOT NULL
AND decimal_38_10 IS NOT NULL AND decimal_20_5 IS NOT NULL
ORDER BY id;
-- Test 11: Aggregation functions with casting
SELECT
SUM(CAST(tinyint_val AS decimal(76,20))) as sum_tinyint_as_decimal256,
AVG(CAST(int_val AS decimal(76,20))) as avg_int_as_decimal256,
MIN(CAST(bigint_val AS decimal(76,20))) as min_bigint_as_decimal256,
MAX(CAST(largeint_val AS decimal(76,0))) as max_largeint_as_decimal256
FROM cast_test_source
WHERE tinyint_val IS NOT NULL;
SELECT
SUM(decimal256_50_15) as sum_decimal256_50_15,
AVG(decimal256_76_20) as avg_decimal256_76_20,
MIN(decimal256_76_0) as min_decimal256_76_0,
MAX(decimal256_76_0) as max_decimal256_76_0,
SUM(decimal_38_10) as sum_decimal_38_10,
AVG(decimal_20_5) as avg_decimal_20_5
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL;
-- Test 12: CASE expressions with casting
SELECT
id,
CASE
WHEN tinyint_val > 0 THEN CAST(tinyint_val AS decimal(50,15))
WHEN tinyint_val < 0 THEN CAST(ABS(tinyint_val) AS decimal(50,15))
ELSE 0.000000000000000
END as case_tinyint_to_decimal256,
CASE
WHEN decimal256_50_15 > 0 THEN CAST(decimal256_50_15 AS varchar(100))
WHEN decimal256_50_15 < 0 THEN CONCAT('negative: ', CAST(ABS(decimal256_50_15) AS varchar(100)))
ELSE 'zero'
END as case_decimal256_to_varchar,
CASE
WHEN decimal_38_10 > decimal256_50_15 THEN 'decimal38_larger'
WHEN decimal_38_10 < decimal256_50_15 THEN 'decimal256_larger'
ELSE 'equal'
END as case_decimal_comparison
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- Test 13: Comparison operations with automatic casting
SELECT
id,
decimal256_50_15 > CAST(int_val AS decimal(50,15)) as decimal256_gt_int,
decimal256_76_20 = CAST(float_val AS decimal(76,20)) as decimal256_eq_float,
decimal256_76_0 < CAST(largeint_val AS decimal(76,0)) as decimal256_lt_largeint,
CAST(bigint_val AS decimal(76,20)) BETWEEN decimal256_76_20 - 1000 AND decimal256_76_20 + 1000 as bigint_between_decimal256,
decimal256_50_15 > decimal_38_10 as decimal256_gt_decimal38,
decimal_20_5 = CAST(decimal256_50_15 AS decimal(20,5)) as decimal20_eq_decimal256_cast
FROM cast_test_source
WHERE decimal256_50_15 IS NOT NULL AND decimal256_76_20 IS NOT NULL AND decimal256_76_0 IS NOT NULL
AND int_val IS NOT NULL AND float_val IS NOT NULL AND largeint_val IS NOT NULL AND bigint_val IS NOT NULL
AND decimal_38_10 IS NOT NULL AND decimal_20_5 IS NOT NULL
ORDER BY id;
-- Test 14: UNION operations with casting
SELECT id, CAST(tinyint_val AS decimal(76,20)) as unified_decimal256, 'tinyint' as source_type FROM cast_test_source WHERE tinyint_val IS NOT NULL
UNION ALL
SELECT id, CAST(int_val AS decimal(76,20)) as unified_decimal256, 'int' as source_type FROM cast_test_source WHERE int_val IS NOT NULL
UNION ALL
SELECT id, decimal256_76_20 as unified_decimal256, 'decimal256_76_20' as source_type FROM cast_test_source WHERE decimal256_76_20 IS NOT NULL
UNION ALL
SELECT id, CAST(decimal_38_10 AS decimal(76,20)) as unified_decimal256, 'decimal_38_10' as source_type FROM cast_test_source WHERE decimal_38_10 IS NOT NULL
ORDER BY id, unified_decimal256;
-- Test 15
CREATE TABLE cast_test_target (
id int,
target_decimal256 decimal(76,20),
target_decimal38 decimal(38,10),
target_int bigint
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
INSERT INTO cast_test_target VALUES
(1, 12345678901234567890123456789012345678901234567890123456.12345678901234567890, 1234567890123456789012345678.1234567890, 9223372036854775807),
(2, 0.00000000000000000000, 0.0000000000, 0),
(3, -87654321098765432109876543210987654321098765432109876543.98765432109876543210, -8765432109876543210987654321.9876543210, -9223372036854775808),
(4, 99999999999999999999999999999999999999999999999999999999.99999999999999999999, 9999999999999999999999999999.9999999999, 9223372036854775807),
(5, -99999999999999999999999999999999999999999999999999999999.99999999999999999999, -9999999999999999999999999999.9999999999, -9223372036854775808);
-- Test 16: Error handling and boundary tests
SELECT
id,
CAST('9999999999999999999999999999999999999999999999999999999999999999999999999999' AS decimal(76,0)) as max_decimal256_76_0,
CAST('99999999999999999999999999999999999999999999999999999999.99999999999999999999' AS decimal(76,20)) as max_decimal256_76_20,
CAST('99999999999999999999999999999999999.999999999999999' AS decimal(50,15)) as max_decimal256_50_15
FROM cast_test_source
WHERE id = 1;
-- Test casting very small numbers
SELECT
id,
CAST('0.00000000000000000001' AS decimal(76,20)) as min_decimal256_76_20,
CAST('0.000000000000001' AS decimal(50,15)) as min_decimal256_50_15,
CAST('0.0000000001' AS decimal(38,10)) as min_decimal_38_10
FROM cast_test_source
WHERE id = 1;
-- Test casting with precision loss
SELECT
id,
decimal256_76_20,
CAST(decimal256_76_20 AS decimal(50,10)) as decimal256_with_precision_loss,
CAST(decimal256_50_15 AS decimal(38,5)) as decimal256_with_scale_loss,
CAST(decimal_38_10 AS decimal(20,5)) as decimal38_with_precision_loss
FROM cast_test_source
WHERE decimal256_76_20 IS NOT NULL AND decimal256_50_15 IS NOT NULL AND decimal_38_10 IS NOT NULL
ORDER BY id;
-- Test 17: NULL handling in casting
SELECT
id,
CAST(NULL AS decimal(76,20)) as null_to_decimal256,
CAST(decimal256_50_15 AS varchar(100)) as decimal256_to_varchar_with_null,
COALESCE(CAST(tinyint_val AS decimal(50,15)), 0.000000000000000) as coalesce_cast_tinyint,
COALESCE(CAST(decimal_38_10 AS decimal(76,20)), 0.00000000000000000000) as coalesce_cast_decimal38
FROM cast_test_source
ORDER BY id;

View File

@ -0,0 +1,657 @@
-- name: test_decimal256_predicate
DROP DATABASE IF EXISTS test_decimal256_predicate;
CREATE DATABASE test_decimal256_predicate;
USE test_decimal256_predicate;
-- Create decimal256 test table with only precision > 38 columns
CREATE TABLE decimal_test (
id int,
big_decimal decimal(50,15), -- decimal256: max 35 integer digits + 15 decimal digits
huge_decimal decimal(76,20), -- decimal256: max 56 integer digits + 20 decimal digits
max_decimal decimal(76,0) -- decimal256: max 76 integer digits + 0 decimal digits
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES (
"replication_num" = "1"
);
-- Insert test data with strict precision limits
INSERT INTO decimal_test VALUES
-- id=1: normal values
(1, 12345678901234567890123456789012345.123456789012345,
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
1234567890123456789012345678901234567890123456789012345678901234567890123456),
-- id=2: another set of values
(2, 87654321098765432109876543210987654.987654321098765,
87654321098765432109876543210987654321098765432109876543.98765432109876543210,
8765432109876543210987654321098765432109876543210987654321098765432109876543),
-- id=3: repeating digits
(3, 55555555555555555555555555555555555.555555555555555,
55555555555555555555555555555555555555555555555555555555.55555555555555555555,
5555555555555555555555555555555555555555555555555555555555555555555555555555),
-- id=4: all ones
(4, 11111111111111111111111111111111111.111111111111111,
11111111111111111111111111111111111111111111111111111111.11111111111111111111,
1111111111111111111111111111111111111111111111111111111111111111111111111111),
-- id=5: near maximum values
(5, 99999999999999999999999999999999999.999999999999999,
99999999999999999999999999999999999999999999999999999999.99999999999999999999,
9999999999999999999999999999999999999999999999999999999999999999999999999999),
-- id=6: minimum positive numbers
(6, 0.000000000000001,
0.00000000000000000001,
1),
-- id=7: negative numbers
(7, -12345678901234567890123456789012345.123456789012345,
-12345678901234567890123456789012345678901234567890123456.12345678901234567890,
-1234567890123456789012345678901234567890123456789012345678901234567890123456),
-- id=8: large negative numbers
(8, -99999999999999999999999999999999999.999999999999999,
-99999999999999999999999999999999999999999999999999999999.99999999999999999999,
-9999999999999999999999999999999999999999999999999999999999999999999999999999),
-- id=9: NULL values
(9, NULL, NULL, NULL),
-- id=10: sevens pattern
(10, 77777777777777777777777777777777777.777777777777777,
77777777777777777777777777777777777777777777777777777777.77777777777777777777,
7777777777777777777777777777777777777777777777777777777777777777777777777777);
-- Insert boundary test values for each column
INSERT INTO decimal_test VALUES
-- id=11: maximum positive values for each column
(11, 99999999999999999999999999999999999.999999999999999,
99999999999999999999999999999999999999999999999999999999.99999999999999999999,
9999999999999999999999999999999999999999999999999999999999999999999999999999),
-- id=12: maximum negative values for each column
(12, -99999999999999999999999999999999999.999999999999999,
-99999999999999999999999999999999999999999999999999999999.99999999999999999999,
-9999999999999999999999999999999999999999999999999999999999999999999999999999),
-- id=13: zero values
(13, 0.000000000000000,
0.00000000000000000000,
0),
-- id=14: minimum precision positive values
(14, 0.000000000000001,
0.00000000000000000001,
1),
-- id=15: minimum precision negative values
(15, -0.000000000000001,
-0.00000000000000000001,
-1);
-- Use CAST to ensure correct precision
INSERT INTO decimal_test VALUES
(16, CAST('12345678901234567890123456789012345.123456789012345' AS decimal(50,15)), -- 35+15=50 digits
CAST('12345678901234567890123456789012345678901234567890123456.12345678901234567890' AS decimal(76,20)), -- 56+20=76 digits
CAST('1234567890123456789012345678901234567890123456789012345678901234567890123456' AS decimal(76,0))); -- 76+0=76 digits
-- Verify data insertion
SELECT
id,
big_decimal,
huge_decimal,
max_decimal
FROM decimal_test
ORDER BY id;
-- Check data types and precision
SELECT
id,
TYPEOF(big_decimal) as big_decimal_type,
TYPEOF(huge_decimal) as huge_decimal_type,
TYPEOF(max_decimal) as max_decimal_type
FROM decimal_test
WHERE id = 1
ORDER BY id;
-- Equality tests
SELECT * FROM decimal_test WHERE big_decimal = 12345678901234567890123456789012345.123456789012345 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal = 12345678901234567890123456789012345678901234567890123456.12345678901234567890 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal = 1234567890123456789012345678901234567890123456789012345678901234567890123456 ORDER BY id;
-- Greater than tests
SELECT * FROM decimal_test WHERE big_decimal > 50000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal > 50000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal > 5000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Less than tests
SELECT * FROM decimal_test WHERE big_decimal < 50000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal < 50000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal < 5000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- IN tests
SELECT * FROM decimal_test WHERE big_decimal IN (
12345678901234567890123456789012345.123456789012345,
87654321098765432109876543210987654.987654321098765
) ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IN (
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
87654321098765432109876543210987654321098765432109876543.98765432109876543210
) ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal IN (
1234567890123456789012345678901234567890123456789012345678901234567890123456,
8765432109876543210987654321098765432109876543210987654321098765432109876543
) ORDER BY id;
-- NOT IN tests
SELECT * FROM decimal_test WHERE big_decimal NOT IN (
12345678901234567890123456789012345.123456789012345,
87654321098765432109876543210987654.987654321098765
) ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal NOT IN (
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
87654321098765432109876543210987654321098765432109876543.98765432109876543210
) ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal NOT IN (
1234567890123456789012345678901234567890123456789012345678901234567890123456,
8765432109876543210987654321098765432109876543210987654321098765432109876543
) ORDER BY id;
-- BETWEEN tests
SELECT * FROM decimal_test WHERE big_decimal BETWEEN
10000000000000000000000000000000000.000000000000000 AND
90000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal BETWEEN
10000000000000000000000000000000000000000000000000000000.00000000000000000000 AND
90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal BETWEEN
1000000000000000000000000000000000000000000000000000000000000000000000000000 AND
9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- NOT BETWEEN tests
SELECT * FROM decimal_test WHERE big_decimal NOT BETWEEN
10000000000000000000000000000000000.000000000000000 AND
90000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal NOT BETWEEN
10000000000000000000000000000000000000000000000000000000.00000000000000000000 AND
90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal NOT BETWEEN
1000000000000000000000000000000000000000000000000000000000000000000000000000 AND
9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Greater than or equal (>=) tests
SELECT * FROM decimal_test WHERE big_decimal >= 12345678901234567890123456789012345.123456789012345 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 12345678901234567890123456789012345678901234567890123456.12345678901234567890 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal >= 1234567890123456789012345678901234567890123456789012345678901234567890123456 ORDER BY id;
-- Boundary value >= tests
SELECT * FROM decimal_test WHERE big_decimal >= 99999999999999999999999999999999999.999999999999999 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 99999999999999999999999999999999999999999999999999999999.99999999999999999999 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal >= 9999999999999999999999999999999999999999999999999999999999999999999999999999 ORDER BY id;
-- Zero value >= tests
SELECT * FROM decimal_test WHERE big_decimal >= 0.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 0.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal >= 0 ORDER BY id;
-- Negative number >= tests
SELECT * FROM decimal_test WHERE big_decimal >= -50000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= -50000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal >= -5000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Small value >= tests
SELECT * FROM decimal_test WHERE big_decimal >= 0.000000000000001 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 0.00000000000000000001 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal >= 1 ORDER BY id;
-- Less than or equal (<=) tests
SELECT * FROM decimal_test WHERE big_decimal <= 87654321098765432109876543210987654.987654321098765 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= 87654321098765432109876543210987654321098765432109876543.98765432109876543210 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal <= 8765432109876543210987654321098765432109876543210987654321098765432109876543 ORDER BY id;
-- Maximum value <= tests
SELECT * FROM decimal_test WHERE big_decimal <= 99999999999999999999999999999999999.999999999999999 ORDER BY id;
-- Zero value <= tests
SELECT * FROM decimal_test WHERE big_decimal <= 0.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= 0.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal <= 0 ORDER BY id;
-- Negative number <= tests
SELECT * FROM decimal_test WHERE big_decimal <= -10000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= -10000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal <= -1000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Middle value <= tests
SELECT * FROM decimal_test WHERE big_decimal <= 50000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= 50000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal <= 5000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Two-condition AND tests
SELECT * FROM decimal_test WHERE big_decimal >= 10000000000000000000000000000000000.000000000000000
AND big_decimal <= 90000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 10000000000000000000000000000000000000000000000000000000.00000000000000000000
AND huge_decimal <= 90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal >= 1000000000000000000000000000000000000000000000000000000000000000000000000000
AND max_decimal <= 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Cross-column AND tests
SELECT * FROM decimal_test WHERE big_decimal >= 10000000000000000000000000000000000.000000000000000 AND huge_decimal <= 90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 AND max_decimal <= 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal >= 0.000000000000000 AND max_decimal >= 0 ORDER BY id;
-- Three-condition AND tests
SELECT * FROM decimal_test WHERE
big_decimal >= 10000000000000000000000000000000000.000000000000000 AND
huge_decimal >= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 AND
max_decimal >= 1000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Mixed comparison AND tests
SELECT * FROM decimal_test WHERE big_decimal > 10000000000000000000000000000000000.000000000000000 AND huge_decimal <= 90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal >= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 AND max_decimal < 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal < 90000000000000000000000000000000000.000000000000000 AND max_decimal >= 1000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- NULL handling AND tests
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL AND huge_decimal IS NOT NULL AND max_decimal IS NOT NULL ORDER BY id;
-- Two-condition OR tests
SELECT * FROM decimal_test WHERE big_decimal <= 10000000000000000000000000000000000.000000000000000
OR big_decimal >= 90000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000
OR huge_decimal >= 90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal <= 1000000000000000000000000000000000000000000000000000000000000000000000000000
OR max_decimal >= 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Cross-column OR tests
SELECT * FROM decimal_test WHERE big_decimal >= 90000000000000000000000000000000000.000000000000000 OR huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 OR max_decimal >= 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal <= 0.000000000000000 OR max_decimal >= 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Three-condition OR tests
SELECT * FROM decimal_test WHERE
big_decimal <= 10000000000000000000000000000000000.000000000000000 OR
huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 OR
max_decimal <= 1000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Mixed comparison OR tests
SELECT * FROM decimal_test WHERE big_decimal < 10000000000000000000000000000000000.000000000000000 OR huge_decimal >= 90000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 OR max_decimal > 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal > 90000000000000000000000000000000000.000000000000000 OR max_decimal < 1000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Extreme value OR tests
SELECT * FROM decimal_test WHERE
big_decimal = 99999999999999999999999999999999999.999999999999999 OR
big_decimal = -99999999999999999999999999999999999.999999999999999 OR
big_decimal = 0.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE
huge_decimal = 99999999999999999999999999999999999999999999999999999999.99999999999999999999 OR
huge_decimal = -99999999999999999999999999999999999999999999999999999999.99999999999999999999 OR
huge_decimal = 0.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE
max_decimal = 9999999999999999999999999999999999999999999999999999999999999999999999999999 OR
max_decimal = -9999999999999999999999999999999999999999999999999999999999999999999999999999 OR
max_decimal = 0 ORDER BY id;
-- NULL handling OR tests
SELECT * FROM decimal_test WHERE big_decimal IS NULL OR huge_decimal IS NULL OR max_decimal IS NULL ORDER BY id;
-- AND and OR mixed tests
SELECT * FROM decimal_test WHERE
(big_decimal >= 10000000000000000000000000000000000.000000000000000 OR huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000) AND
max_decimal >= 1000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Complex nested conditions
SELECT * FROM decimal_test WHERE
((big_decimal >= 50000000000000000000000000000000000.000000000000000 OR big_decimal <= 10000000000000000000000000000000000.000000000000000) AND
(huge_decimal >= 50000000000000000000000000000000000000000000000000000000.00000000000000000000)) OR
max_decimal = 0 ORDER BY id;
-- Multi-level nested AND OR tests
SELECT * FROM decimal_test WHERE
(big_decimal BETWEEN 10000000000000000000000000000000000.000000000000000 AND 90000000000000000000000000000000000.000000000000000 AND
(huge_decimal >= 50000000000000000000000000000000000000000000000000000000.00000000000000000000 OR huge_decimal <= 10000000000000000000000000000000000000000000000000000000.00000000000000000000)) OR
(max_decimal >= 8000000000000000000000000000000000000000000000000000000000000000000000000000 AND
big_decimal BETWEEN 10000000000000000000000000000000000.000000000000000 AND 90000000000000000000000000000000000.000000000000000) ORDER BY id;
-- Positive and negative mixed conditions
SELECT * FROM decimal_test WHERE
(big_decimal >= 0.000000000000000 AND huge_decimal >= 0.00000000000000000000 AND max_decimal >= 0) OR
(big_decimal <= 0.000000000000000 AND huge_decimal <= 0.00000000000000000000 AND max_decimal <= 0) ORDER BY id;
SELECT * FROM decimal_test WHERE
(big_decimal >= 0.000000000000000 OR huge_decimal >= 0.00000000000000000000) AND
(max_decimal >= 0 OR max_decimal <= -1000000000000000000000000000000000000000000000000000000000000000000000000000) ORDER BY id;
-- Range query performance tests
SELECT COUNT(*) FROM decimal_test WHERE
big_decimal >= 10000000000000000000000000000000000.000000000000000 OR
huge_decimal >= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 OR
max_decimal >= 1000000000000000000000000000000000000000000000000000000000000000000000000000;
-- Single column IS NULL tests
SELECT * FROM decimal_test WHERE big_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal IS NULL ORDER BY id;
-- Count NULL values for each column
SELECT COUNT(*) as null_big_decimal_count FROM decimal_test WHERE big_decimal IS NULL;
SELECT COUNT(*) as null_huge_decimal_count FROM decimal_test WHERE huge_decimal IS NULL;
SELECT COUNT(*) as null_max_decimal_count FROM decimal_test WHERE max_decimal IS NULL;
-- Use aggregate functions to count NULL values for all columns
SELECT
SUM(CASE WHEN big_decimal IS NULL THEN 1 ELSE 0 END) as big_decimal_nulls,
SUM(CASE WHEN huge_decimal IS NULL THEN 1 ELSE 0 END) as huge_decimal_nulls,
SUM(CASE WHEN max_decimal IS NULL THEN 1 ELSE 0 END) as max_decimal_nulls
FROM decimal_test;
-- Single column IS NOT NULL tests
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NOT NULL ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal IS NOT NULL ORDER BY id;
-- Count non-NULL values for each column
SELECT COUNT(*) as not_null_big_decimal_count FROM decimal_test WHERE big_decimal IS NOT NULL;
SELECT COUNT(*) as not_null_huge_decimal_count FROM decimal_test WHERE huge_decimal IS NOT NULL;
SELECT COUNT(*) as not_null_max_decimal_count FROM decimal_test WHERE max_decimal IS NOT NULL;
-- Use aggregate functions to count non-NULL values for all columns
SELECT
SUM(CASE WHEN big_decimal IS NOT NULL THEN 1 ELSE 0 END) as big_decimal_not_nulls,
SUM(CASE WHEN huge_decimal IS NOT NULL THEN 1 ELSE 0 END) as huge_decimal_not_nulls,
SUM(CASE WHEN max_decimal IS NOT NULL THEN 1 ELSE 0 END) as max_decimal_not_nulls
FROM decimal_test;
-- Insert various NULL combination test data
INSERT INTO decimal_test VALUES
-- id=17: only big_decimal is NULL
(17, NULL,
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
1234567890123456789012345678901234567890123456789012345678901234567890123456),
-- id=18: only huge_decimal is NULL
(18, 12345678901234567890123456789012345.123456789012345,
NULL,
1234567890123456789012345678901234567890123456789012345678901234567890123456),
-- id=19: only max_decimal is NULL
(19, 12345678901234567890123456789012345.123456789012345,
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
NULL),
-- id=20: big_decimal and huge_decimal are NULL
(20, NULL, NULL,
1234567890123456789012345678901234567890123456789012345678901234567890123456),
-- id=21: big_decimal and max_decimal are NULL
(21, NULL,
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
NULL),
-- id=22: huge_decimal and max_decimal are NULL
(22, 12345678901234567890123456789012345.123456789012345,
NULL, NULL),
-- id=23: alternating NULL (columns 1 and 3)
(23, NULL,
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
NULL),
-- id=24: alternating NULL (column 2)
(24, 12345678901234567890123456789012345.123456789012345,
NULL,
1234567890123456789012345678901234567890123456789012345678901234567890123456),
-- id=25: all columns NULL except id
(25, NULL, NULL, NULL);
-- Two columns both NULL AND tests
SELECT * FROM decimal_test WHERE big_decimal IS NULL AND huge_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal IS NULL AND max_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NULL AND max_decimal IS NULL ORDER BY id;
-- Two columns both NULL OR tests
SELECT * FROM decimal_test WHERE big_decimal IS NULL OR huge_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal IS NULL OR max_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NULL OR max_decimal IS NULL ORDER BY id;
-- All three columns NULL test
SELECT * FROM decimal_test WHERE big_decimal IS NULL AND huge_decimal IS NULL AND max_decimal IS NULL ORDER BY id;
-- Any of three columns NULL test
SELECT * FROM decimal_test WHERE big_decimal IS NULL OR huge_decimal IS NULL OR max_decimal IS NULL ORDER BY id;
-- All columns NULL test
SELECT * FROM decimal_test WHERE
big_decimal IS NULL AND
huge_decimal IS NULL AND
max_decimal IS NULL ORDER BY id;
-- Any column NULL test
SELECT * FROM decimal_test WHERE
big_decimal IS NULL OR
huge_decimal IS NULL OR
max_decimal IS NULL ORDER BY id;
-- Two columns both NOT NULL AND tests
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL AND huge_decimal IS NOT NULL ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL AND max_decimal IS NOT NULL ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NOT NULL AND max_decimal IS NOT NULL ORDER BY id;
-- Two columns both NOT NULL OR tests
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL OR huge_decimal IS NOT NULL ORDER BY id;
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL OR max_decimal IS NOT NULL ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NOT NULL OR max_decimal IS NOT NULL ORDER BY id;
-- All three columns NOT NULL test
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL AND huge_decimal IS NOT NULL AND max_decimal IS NOT NULL ORDER BY id;
-- Any of three columns NOT NULL test
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL OR huge_decimal IS NOT NULL OR max_decimal IS NOT NULL ORDER BY id;
-- Complex mixed conditions
SELECT * FROM decimal_test WHERE
(big_decimal IS NULL AND huge_decimal IS NOT NULL) OR
(max_decimal IS NOT NULL AND big_decimal IS NULL) ORDER BY id;
SELECT * FROM decimal_test WHERE
(huge_decimal IS NULL OR max_decimal IS NULL) AND
(big_decimal IS NOT NULL) ORDER BY id;
-- Alternating NULL and NOT NULL patterns
SELECT * FROM decimal_test WHERE
big_decimal IS NULL AND
huge_decimal IS NOT NULL AND
max_decimal IS NULL ORDER BY id;
SELECT * FROM decimal_test WHERE
big_decimal IS NOT NULL AND
huge_decimal IS NULL AND
max_decimal IS NOT NULL ORDER BY id;
-- NULL with equality condition combinations
SELECT * FROM decimal_test WHERE big_decimal IS NULL OR big_decimal = 12345678901234567890123456789012345.123456789012345 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NULL OR huge_decimal = 12345678901234567890123456789012345678901234567890123456.12345678901234567890 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal IS NULL OR max_decimal = 1234567890123456789012345678901234567890123456789012345678901234567890123456 ORDER BY id;
-- NULL with range condition combinations
SELECT * FROM decimal_test WHERE big_decimal IS NULL OR (big_decimal >= 10000000000000000000000000000000000.000000000000000 AND big_decimal <= 90000000000000000000000000000000000.000000000000000) ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NULL OR (huge_decimal >= 10000000000000000000000000000000000000000000000000000000.00000000000000000000 AND huge_decimal <= 90000000000000000000000000000000000000000000000000000000.00000000000000000000) ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal IS NULL OR max_decimal >= 5000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- NOT NULL with numeric condition combinations
SELECT * FROM decimal_test WHERE big_decimal IS NOT NULL AND big_decimal >= 50000000000000000000000000000000000.000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE huge_decimal IS NOT NULL AND huge_decimal <= 50000000000000000000000000000000000000000000000000000000.00000000000000000000 ORDER BY id;
SELECT * FROM decimal_test WHERE max_decimal IS NOT NULL AND max_decimal BETWEEN 1000000000000000000000000000000000000000000000000000000000000000000000000000 AND 9000000000000000000000000000000000000000000000000000000000000000000000000000 ORDER BY id;
-- Complex NULL with numeric condition combinations
SELECT * FROM decimal_test WHERE
(big_decimal IS NULL OR big_decimal >= 50000000000000000000000000000000000.000000000000000) AND
(huge_decimal IS NOT NULL AND huge_decimal <= 50000000000000000000000000000000000000000000000000000000.00000000000000000000) ORDER BY id;
SELECT * FROM decimal_test WHERE
(max_decimal IS NULL OR max_decimal >= 5000000000000000000000000000000000000000000000000000000000000000000000000000) AND
(big_decimal IS NOT NULL OR huge_decimal IS NULL) ORDER BY id;
-- NULL with IN condition combinations
SELECT * FROM decimal_test WHERE
big_decimal IS NULL OR
big_decimal IN (
12345678901234567890123456789012345.123456789012345,
87654321098765432109876543210987654.987654321098765
) ORDER BY id;
SELECT * FROM decimal_test WHERE
huge_decimal IS NULL OR
huge_decimal IN (
12345678901234567890123456789012345678901234567890123456.12345678901234567890,
87654321098765432109876543210987654321098765432109876543.98765432109876543210
) ORDER BY id;
SELECT * FROM decimal_test WHERE
max_decimal IS NULL OR
max_decimal IN (
1234567890123456789012345678901234567890123456789012345678901234567890123456,
8765432109876543210987654321098765432109876543210987654321098765432109876543
) ORDER BY id;
-- COUNT with NULL
SELECT COUNT(*) as total_rows FROM decimal_test;
SELECT COUNT(big_decimal) as non_null_big_decimal FROM decimal_test;
SELECT COUNT(huge_decimal) as non_null_huge_decimal FROM decimal_test;
SELECT COUNT(max_decimal) as non_null_max_decimal FROM decimal_test;
-- SUM with NULL (NULL values are ignored)
SELECT SUM(big_decimal) as sum_big_decimal FROM decimal_test;
SELECT SUM(huge_decimal) as sum_huge_decimal FROM decimal_test;
SELECT SUM(max_decimal) as sum_max_decimal FROM decimal_test;
-- AVG with NULL (NULL values are ignored)
SELECT AVG(big_decimal) as avg_big_decimal FROM decimal_test;
SELECT AVG(huge_decimal) as avg_huge_decimal FROM decimal_test;
SELECT AVG(max_decimal) as avg_max_decimal FROM decimal_test;
-- MIN/MAX with NULL (NULL values are ignored)
SELECT
MIN(big_decimal) as min_big_decimal, MAX(big_decimal) as max_big_decimal,
MIN(huge_decimal) as min_huge_decimal, MAX(huge_decimal) as max_huge_decimal,
MIN(max_decimal) as min_max_decimal, MAX(max_decimal) as max_max_decimal
FROM decimal_test;
-- Group by NULL status
SELECT
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as big_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
ORDER BY big_decimal_status;
SELECT
CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as huge_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
ORDER BY huge_decimal_status;
SELECT
CASE WHEN max_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as max_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY CASE WHEN max_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
ORDER BY max_decimal_status;
-- Multi-column NULL status combination grouping
SELECT
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as big_decimal_status,
CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as huge_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END,
CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
ORDER BY big_decimal_status, huge_decimal_status;
SELECT
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as big_decimal_status,
CASE WHEN max_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as max_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END,
CASE WHEN max_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
ORDER BY big_decimal_status, max_decimal_status;
-- Three-column NULL status combination grouping
SELECT
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as big_decimal_status,
CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as huge_decimal_status,
CASE WHEN max_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as max_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END,
CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END,
CASE WHEN max_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
ORDER BY big_decimal_status, huge_decimal_status, max_decimal_status;
-- HAVING with NULL conditions
SELECT
CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as big_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY CASE WHEN big_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
HAVING COUNT(*) > 1
ORDER BY big_decimal_status;
SELECT
CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END as huge_decimal_status,
COUNT(*) as count
FROM decimal_test
GROUP BY CASE WHEN huge_decimal IS NULL THEN 'NULL' ELSE 'NOT NULL' END
HAVING COUNT(*) > 2
ORDER BY huge_decimal_status;
-- NULL behavior in sorting (NULL values usually sort first or last)
SELECT * FROM decimal_test ORDER BY big_decimal;
SELECT * FROM decimal_test ORDER BY big_decimal DESC;
SELECT * FROM decimal_test ORDER BY huge_decimal;
SELECT * FROM decimal_test ORDER BY huge_decimal DESC;
SELECT * FROM decimal_test ORDER BY max_decimal;
SELECT * FROM decimal_test ORDER BY max_decimal DESC;
-- Multi-column sorting with NULL handling
SELECT * FROM decimal_test ORDER BY big_decimal, huge_decimal;
SELECT * FROM decimal_test ORDER BY big_decimal DESC, huge_decimal DESC;
SELECT * FROM decimal_test ORDER BY huge_decimal, max_decimal;
SELECT * FROM decimal_test ORDER BY huge_decimal DESC, max_decimal DESC;
SELECT * FROM decimal_test ORDER BY big_decimal, huge_decimal, max_decimal;
SELECT * FROM decimal_test ORDER BY big_decimal DESC, huge_decimal DESC, max_decimal DESC;
-- Using NULLS FIRST/LAST
SELECT * FROM decimal_test ORDER BY big_decimal NULLS FIRST;
SELECT * FROM decimal_test ORDER BY big_decimal NULLS LAST;
SELECT * FROM decimal_test ORDER BY huge_decimal NULLS FIRST;
SELECT * FROM decimal_test ORDER BY huge_decimal NULLS LAST;
SELECT * FROM decimal_test ORDER BY max_decimal NULLS FIRST;
SELECT * FROM decimal_test ORDER BY max_decimal NULLS LAST;
-- Multi-column sorting with NULLS FIRST/LAST combinations
SELECT * FROM decimal_test ORDER BY big_decimal NULLS FIRST, huge_decimal NULLS LAST;
SELECT * FROM decimal_test ORDER BY big_decimal NULLS LAST, huge_decimal NULLS FIRST;
SELECT * FROM decimal_test ORDER BY big_decimal DESC NULLS FIRST, huge_decimal ASC NULLS LAST;