Skip to content

Commit

Permalink
fix(common): interval overflow panic / wrap during comparison and jus…
Browse files Browse the repository at this point in the history
  • Loading branch information
xiangjinwu authored Mar 16, 2023
1 parent 04a2885 commit e61af5a
Show file tree
Hide file tree
Showing 3 changed files with 321 additions and 105 deletions.
53 changes: 47 additions & 6 deletions e2e_test/batch/types/interval.slt.part
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,20 @@ SELECT INTERVAL '3 mins' * 1.5;
00:04:30

# https://github.com/risingwavelabs/risingwave/issues/3873
query TTTTT
query T
select distinct * from (values (interval '1' month), (interval '30' day)) as t;
----
30 days
1 mon

query TTTTT
query T
select distinct * from (values (interval '30' day), (interval '1' month)) as t;
----
30 days
1 mon

query TTTTT
query T
select distinct * from (values (interval '720' hour), (interval '1' month)) as t;
----
30 days
1 mon

query TTTTTT
select interval '1 year 1 month 1 day 1';
Expand Down Expand Up @@ -119,3 +119,44 @@ query T
select '1 mons 1 days 00:00:00.0000001'::INTERVAL;
----
1 mon 1 day

# Tests moved from regress tests due to not matching exactly.

# In mixed sign intervals, PostgreSQL displays positive sign after negative
# (e.g. `-1 mons +1 day`) while we display it without sign
# (e.g. `-1 mons 1 day`).
# But the main purpose of this test case is ordering of large values.

statement ok
CREATE TABLE INTERVAL_TBL_OF (f1 interval);

statement ok
INSERT INTO INTERVAL_TBL_OF (f1) VALUES
('2147483647 days 2147483647 months'),
('2147483647 days -2147483648 months'),
('1 year'),
('-2147483648 days 2147483647 months'),
('-2147483648 days -2147483648 months');

statement ok
FLUSH;

query TT
SELECT r1.*, r2.*
FROM INTERVAL_TBL_OF r1, INTERVAL_TBL_OF r2
WHERE r1.f1 > r2.f1
ORDER BY r1.f1, r2.f1;
----
-178956970 years -8 mons 2147483647 days -178956970 years -8 mons -2147483648 days
1 year -178956970 years -8 mons -2147483648 days
1 year -178956970 years -8 mons 2147483647 days
178956970 years 7 mons -2147483648 days -178956970 years -8 mons -2147483648 days
178956970 years 7 mons -2147483648 days -178956970 years -8 mons 2147483647 days
178956970 years 7 mons -2147483648 days 1 year
178956970 years 7 mons 2147483647 days -178956970 years -8 mons -2147483648 days
178956970 years 7 mons 2147483647 days -178956970 years -8 mons 2147483647 days
178956970 years 7 mons 2147483647 days 1 year
178956970 years 7 mons 2147483647 days 178956970 years 7 mons -2147483648 days

statement ok
DROP TABLE INTERVAL_TBL_OF;
27 changes: 2 additions & 25 deletions src/common/src/hash/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ use crate::collection::estimate_size::EstimateSize;
use crate::hash::VirtualNode;
use crate::row::{OwnedRow, RowDeserializer};
use crate::types::{
DataType, Decimal, IntervalUnit, NaiveDateTimeWrapper, NaiveDateWrapper, NaiveTimeWrapper,
OrderedF32, OrderedF64, ScalarRef,
DataType, Decimal, NaiveDateTimeWrapper, NaiveDateWrapper, NaiveTimeWrapper, OrderedF32,
OrderedF64, ScalarRef,
};
use crate::util::hash_util::Crc32FastBuilder;
use crate::util::iter_util::ZipEqFast;
Expand Down Expand Up @@ -357,29 +357,6 @@ impl HashKeySerDe<'_> for Decimal {
}
}

impl HashKeySerDe<'_> for IntervalUnit {
type S = [u8; 16];

fn serialize(mut self) -> Self::S {
self.justify_interval();
let mut ret = [0; 16];
ret[0..4].copy_from_slice(&self.get_months().to_ne_bytes());
ret[4..8].copy_from_slice(&self.get_days().to_ne_bytes());
ret[8..16].copy_from_slice(&self.get_usecs().to_ne_bytes());

ret
}

fn deserialize<R: Read>(source: &mut R) -> Self {
let value = Self::read_fixed_size_bytes::<R, 16>(source);
IntervalUnit::from_month_day_usec(
i32::from_ne_bytes(value[0..4].try_into().unwrap()),
i32::from_ne_bytes(value[4..8].try_into().unwrap()),
i64::from_ne_bytes(value[8..16].try_into().unwrap()),
)
}
}

impl<'a> HashKeySerDe<'a> for &'a str {
type S = Vec<u8>;

Expand Down
Loading

0 comments on commit e61af5a

Please sign in to comment.