Skip to content

Commit

Permalink
fix(query): Correct sign extension handling in months_days_micros str…
Browse files Browse the repository at this point in the history
…uct (#17086)

Casting days to u32 before casting to i128 to prevent sign extension.
Casting microseconds to u64 before casting to i128 to prevent sign extension.
  • Loading branch information
TCeason authored Dec 20, 2024
1 parent f7a4a5d commit bed61d2
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/common/column/src/types/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,10 @@ pub struct months_days_micros(pub i128);
impl months_days_micros {
pub fn new(months: i32, days: i32, microseconds: i64) -> Self {
let months_bits = (months as i128) << 96;
let days_bits = (days as i128) << 64;
let micros_bits = microseconds as i128;
// converting to u32 before i128 ensures we’re working with the raw, unsigned bit pattern of the i32 value,
// preventing unwanted sign extension when that value is later used within the i128.
let days_bits = ((days as u32) as i128) << 64;
let micros_bits = (microseconds as u64) as i128;

Self(months_bits | days_bits | micros_bits)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ query TT
select * from t order by c1;
----
-1 year -1 month 0:00:00.000001
-1 month -1 day -1:00:00 0:00:00.001
-1 month -1:00:00 0:00:00.001

onlyif http
statement error 1006
Expand All @@ -22,3 +22,9 @@ query T
select to_interval('1 month 1 hour 1 microsecond');
----
1 month 1:00:00.000001

onlyif http
query T
select to_interval('1 month 1 hour 1 microsecond ago');
----
-1 month -1:00:00.000001

0 comments on commit bed61d2

Please sign in to comment.