[BugFix] Fix cast from LARGEINT to DECIMAL128 (#63559)

Signed-off-by: zihe.liu <ziheliu1024@gmail.com>
This commit is contained in:
zihe.liu 2025-09-29 10:36:35 +08:00 committed by GitHub
parent d597f92555
commit 4c248a560b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 292 additions and 3 deletions

View File

@ -140,6 +140,15 @@ struct DecimalNonDecimalCast<overflow_mode, DecimalType, NonDecimalType, Decimal
using NonDecimalColumnType = RunTimeColumnType<NonDecimalType>;
static inline ColumnPtr decimal_from(const ColumnPtr& column, int precision, int scale) {
if (scale == 0) {
return _decimal_from<true>(column, precision, scale);
} else {
return _decimal_from<false>(column, precision, scale);
}
}
template <bool ZeroScale>
static inline ColumnPtr _decimal_from(const ColumnPtr& column, int precision, int scale) {
const auto num_rows = column->size();
typename DecimalColumnType::MutablePtr result = DecimalColumnType::create(precision, scale, num_rows);
const auto data = &ColumnHelper::cast_to_raw<NonDecimalType>(column.get())->immutable_data().front();
@ -163,9 +172,16 @@ struct DecimalNonDecimalCast<overflow_mode, DecimalType, NonDecimalType, Decimal
DecimalV3Cast::from_integer<SignedBooleanType, DecimalCppType, check_overflow<overflow_mode>>(
(SignedBooleanType)(data[i]), scale_factor, &result_data[i]);
} else if constexpr (lt_is_integer<NonDecimalType>) {
overflow =
DecimalV3Cast::from_integer<NonDecimalCppType, DecimalCppType, check_overflow<overflow_mode>>(
data[i], scale_factor, &result_data[i]);
if constexpr (ZeroScale) {
// Fast path for integer-to-decimal conversion with scale 0.
overflow =
DecimalV3Cast::to_decimal_trivial<NonDecimalCppType, DecimalCppType,
check_overflow<overflow_mode>>(data[i], &result_data[i]);
} else {
overflow = DecimalV3Cast::from_integer<NonDecimalCppType, DecimalCppType,
check_overflow<overflow_mode>>(data[i], scale_factor,
&result_data[i]);
}
} else if constexpr (lt_is_float<NonDecimalType>) {
overflow = DecimalV3Cast::from_float<NonDecimalCppType, DecimalCppType>(data[i], scale_factor,
&result_data[i]);
@ -218,6 +234,7 @@ struct DecimalNonDecimalCast<overflow_mode, DecimalType, NonDecimalType, Decimal
}
}
}
if constexpr (check_overflow<overflow_mode>) {
ColumnBuilder<DecimalType> builder(std::move(result), std::move(null_column), has_null);
return builder.build(column->is_constant());

View File

@ -210,6 +210,14 @@ static inline int64_t i32_x_i32_produce_i64(int32_t a, int32_t b) {
}
static inline int multi3(const int128_t& x, const int128_t& y, int128_t& res) {
// This algorithm mistakenly treats `INT128_MIN * 1` as an overflow, because `abs(INT128_MIN)` remains `INT128_MIN`,
// which causes `asm_add` to detect `SF=1`. Therefore, we add a special case here to bypass this issue.
if (UNLIKELY((x == std::numeric_limits<int128_t>::min() && y == 1) ||
(y == std::numeric_limits<int128_t>::min() && x == 1))) {
res = std::numeric_limits<int128_t>::min();
return 0;
}
// sgn(x)
auto sx = x >> 127;
// sgn(y)

View File

@ -0,0 +1,179 @@
-- name: test_decimal_cast
CREATE TABLE t1 (
k1 bigint NULL,
c_tinyint tinyint null,
c_int int null,
c_bigint bigint null,
c_largeint largeint null
) ENGINE=OLAP
DUPLICATE KEY(`k1`)
DISTRIBUTED BY HASH(`k1`) BUCKETS 96
PROPERTIES (
"replication_num" = "1"
);
-- result:
-- !result
insert into t1 values
(1, 127, 2147483647, 9223372036854775807, 170141183460469231731687303715884105727),
(2, -128, -2147483648, -9223372036854775808, -170141183460469231731687303715884105728),
(3, null, null, null, null),
(4, 0, 0, 0, 0),
(5, 1, 1, 1, 1),
(6, -1, -1, -1, -1),
(7, 12, 214748364, 922337203685477580, 17014118346046923173168730371588410572),
(8, -12, -214748364, -922337203685477580, -17014118346046923173168730371588410572);
-- result:
-- !result
select
k1,
cast(c_tinyint as DECIMAL(9,0)),
cast(c_int as DECIMAL(9,0)),
cast(c_bigint as DECIMAL(9,0)),
cast(c_largeint as DECIMAL(9,0))
from t1
order by k1;
-- result:
1 127 2147483647 9223372036854775807 None
2 -128 -2147483648 -9223372036854775808 None
3 None None None None
4 0 0 0 0
5 1 1 1 1
6 -1 -1 -1 -1
7 12 214748364 922337203685477580 None
8 -12 -214748364 -922337203685477580 None
-- !result
select
k1,
cast(c_tinyint as DECIMAL(9,1)),
cast(c_int as DECIMAL(9,1)),
cast(c_bigint as DECIMAL(9,1)),
cast(c_largeint as DECIMAL(9,1))
from t1
order by k1;
-- result:
1 127.0 2147483647.0 None None
2 -128.0 -2147483648.0 None None
3 None None None None
4 0.0 0.0 0.0 0.0
5 1.0 1.0 1.0 1.0
6 -1.0 -1.0 -1.0 -1.0
7 12.0 214748364.0 922337203685477580.0 None
8 -12.0 -214748364.0 -922337203685477580.0 None
-- !result
select
k1,
cast(c_tinyint as DECIMAL(27,0)),
cast(c_int as DECIMAL(27,0)),
cast(c_bigint as DECIMAL(27,0)),
cast(c_largeint as DECIMAL(27,0))
from t1
order by k1;
-- result:
1 127 2147483647 9223372036854775807 170141183460469231731687303715884105727
2 -128 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728
3 None None None None
4 0 0 0 0
5 1 1 1 1
6 -1 -1 -1 -1
7 12 214748364 922337203685477580 17014118346046923173168730371588410572
8 -12 -214748364 -922337203685477580 -17014118346046923173168730371588410572
-- !result
select
k1,
cast(c_tinyint as DECIMAL(27,1)),
cast(c_int as DECIMAL(27,1)),
cast(c_bigint as DECIMAL(27,1)),
cast(c_largeint as DECIMAL(27,1))
from t1
order by k1;
-- result:
1 127.0 2147483647.0 9223372036854775807.0 None
2 -128.0 -2147483648.0 -9223372036854775808.0 None
3 None None None None
4 0.0 0.0 0.0 0.0
5 1.0 1.0 1.0 1.0
6 -1.0 -1.0 -1.0 -1.0
7 12.0 214748364.0 922337203685477580.0 17014118346046923173168730371588410572.0
8 -12.0 -214748364.0 -922337203685477580.0 -17014118346046923173168730371588410572.0
-- !result
select
k1,
cast(c_tinyint as DECIMAL(38,0)),
cast(c_int as DECIMAL(38,0)),
cast(c_bigint as DECIMAL(38,0)),
cast(c_largeint as DECIMAL(38,0))
from t1
order by k1;
-- result:
1 127 2147483647 9223372036854775807 170141183460469231731687303715884105727
2 -128 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728
3 None None None None
4 0 0 0 0
5 1 1 1 1
6 -1 -1 -1 -1
7 12 214748364 922337203685477580 17014118346046923173168730371588410572
8 -12 -214748364 -922337203685477580 -17014118346046923173168730371588410572
-- !result
select
k1,
cast(c_tinyint as DECIMAL(38,1)),
cast(c_int as DECIMAL(38,1)),
cast(c_bigint as DECIMAL(38,1)),
cast(c_largeint as DECIMAL(38,1))
from t1
order by k1;
-- result:
1 127.0 2147483647.0 9223372036854775807.0 None
2 -128.0 -2147483648.0 -9223372036854775808.0 None
3 None None None None
4 0.0 0.0 0.0 0.0
5 1.0 1.0 1.0 1.0
6 -1.0 -1.0 -1.0 -1.0
7 12.0 214748364.0 922337203685477580.0 17014118346046923173168730371588410572.0
8 -12.0 -214748364.0 -922337203685477580.0 -17014118346046923173168730371588410572.0
-- !result
select k1, c_tinyint * 0, c_int * 0, c_bigint * 0, c_largeint * 0 from t1 order by k1;
-- result:
1 0 0 0 0
2 0 0 0 0
3 None None None None
4 0 0 0 0
5 0 0 0 0
6 0 0 0 0
7 0 0 0 0
8 0 0 0 0
-- !result
select k1, c_tinyint * 1, c_int * 1, c_bigint * 1, c_largeint * 1 from t1 order by k1;
-- result:
1 127 2147483647 9223372036854775807 170141183460469231731687303715884105727
2 -128 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728
3 None None None None
4 0 0 0 0
5 1 1 1 1
6 -1 -1 -1 -1
7 12 214748364 922337203685477580 17014118346046923173168730371588410572
8 -12 -214748364 -922337203685477580 -17014118346046923173168730371588410572
-- !result
select k1, cast(c_tinyint * 0 as decimal(38, 0)), cast(c_int * 0 as decimal(38, 0)), cast(c_bigint * 0 as decimal(38, 0)), cast(c_largeint * 0 as decimal(38, 0)) from t1 order by k1;
-- result:
1 0 0 0 0
2 0 0 0 0
3 None None None None
4 0 0 0 0
5 0 0 0 0
6 0 0 0 0
7 0 0 0 0
8 0 0 0 0
-- !result
select k1, cast(c_tinyint * 1 as decimal(38, 0)), cast(c_int * 1 as decimal(38, 0)), cast(c_bigint * 1 as decimal(38, 0)), cast(c_largeint * 1 as decimal(38, 0)) from t1 order by k1;
-- result:
1 127 2147483647 9223372036854775807 170141183460469231731687303715884105727
2 -128 -2147483648 -9223372036854775808 -170141183460469231731687303715884105728
3 None None None None
4 0 0 0 0
5 1 1 1 1
6 -1 -1 -1 -1
7 12 214748364 922337203685477580 17014118346046923173168730371588410572
8 -12 -214748364 -922337203685477580 -17014118346046923173168730371588410572
-- !result

View File

@ -0,0 +1,85 @@
-- name: test_decimal_cast
CREATE TABLE t1 (
k1 bigint NULL,
c_tinyint tinyint null,
c_int int null,
c_bigint bigint null,
c_largeint largeint null
) ENGINE=OLAP
DUPLICATE KEY(`k1`)
DISTRIBUTED BY HASH(`k1`) BUCKETS 96
PROPERTIES (
"replication_num" = "1"
);
insert into t1 values
(1, 127, 2147483647, 9223372036854775807, 170141183460469231731687303715884105727),
(2, -128, -2147483648, -9223372036854775808, -170141183460469231731687303715884105728),
(3, null, null, null, null),
(4, 0, 0, 0, 0),
(5, 1, 1, 1, 1),
(6, -1, -1, -1, -1),
(7, 12, 214748364, 922337203685477580, 17014118346046923173168730371588410572),
(8, -12, -214748364, -922337203685477580, -17014118346046923173168730371588410572);
select
k1,
cast(c_tinyint as DECIMAL(9,0)),
cast(c_int as DECIMAL(9,0)),
cast(c_bigint as DECIMAL(9,0)),
cast(c_largeint as DECIMAL(9,0))
from t1
order by k1;
select
k1,
cast(c_tinyint as DECIMAL(9,1)),
cast(c_int as DECIMAL(9,1)),
cast(c_bigint as DECIMAL(9,1)),
cast(c_largeint as DECIMAL(9,1))
from t1
order by k1;
select
k1,
cast(c_tinyint as DECIMAL(27,0)),
cast(c_int as DECIMAL(27,0)),
cast(c_bigint as DECIMAL(27,0)),
cast(c_largeint as DECIMAL(27,0))
from t1
order by k1;
select
k1,
cast(c_tinyint as DECIMAL(27,1)),
cast(c_int as DECIMAL(27,1)),
cast(c_bigint as DECIMAL(27,1)),
cast(c_largeint as DECIMAL(27,1))
from t1
order by k1;
select
k1,
cast(c_tinyint as DECIMAL(38,0)),
cast(c_int as DECIMAL(38,0)),
cast(c_bigint as DECIMAL(38,0)),
cast(c_largeint as DECIMAL(38,0))
from t1
order by k1;
select
k1,
cast(c_tinyint as DECIMAL(38,1)),
cast(c_int as DECIMAL(38,1)),
cast(c_bigint as DECIMAL(38,1)),
cast(c_largeint as DECIMAL(38,1))
from t1
order by k1;
select k1, c_tinyint * 0, c_int * 0, c_bigint * 0, c_largeint * 0 from t1 order by k1;
select k1, c_tinyint * 1, c_int * 1, c_bigint * 1, c_largeint * 1 from t1 order by k1;
select k1, cast(c_tinyint * 0 as decimal(38, 0)), cast(c_int * 0 as decimal(38, 0)), cast(c_bigint * 0 as decimal(38, 0)), cast(c_largeint * 0 as decimal(38, 0)) from t1 order by k1;
select k1, cast(c_tinyint * 1 as decimal(38, 0)), cast(c_int * 1 as decimal(38, 0)), cast(c_bigint * 1 as decimal(38, 0)), cast(c_largeint * 1 as decimal(38, 0)) from t1 order by k1;