Skip to content

Commit 1571e8f

Browse files
committed
fix comm
1 parent d975bf0 commit 1571e8f

File tree

4 files changed

+124
-16
lines changed

4 files changed

+124
-16
lines changed

e2e_test/batch/types/timestamp_ns.slt.part

+98-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ statement ok
55
create table t1(v1 int, v2 timestamp);
66

77
statement ok
8-
insert into t1 values(1,'2013-01-01 01:01:01.123456789'),(2,'2012-01-01 01:01:01.123456'),(3,'0000-01-01 01:01:01.123456789'),(4,'2213-01-01 01:01:01.123456789'),(5,null);
8+
insert into t1 values(1,'2013-01-01 01:01:01.123456789'),(2,'2012-01-01 01:01:01.123456'),(3,'0000-01-01 01:01:01.123456789'),(4,'2213-01-01 01:01:01.123456789'),(5,null),(6,'2013-01-01 01:01:01.123456789');
99

1010
query T rowsort
1111
select * from t1;
@@ -15,6 +15,7 @@ select * from t1;
1515
3 0001-01-01 01:01:01.123456789 BC
1616
4 2213-01-01 01:01:01.123456789
1717
5 NULL
18+
6 2013-01-01 01:01:01.123456789
1819

1920
query T
2021
select * from t1 where v2 is null;
@@ -35,6 +36,7 @@ from t1;
3536
3 0001-01-01 01:01:01.123456789 BC Before 2000
3637
4 2213-01-01 01:01:01.123456789 Future
3738
5 NULL Future
39+
6 2013-01-01 01:01:01.123456789 21st Century
3840

3941
query T rowsort
4042
select v1, v2, coalesce(v2, '1900-01-01 00:00:00') as coalesce_v2 from t1;
@@ -44,6 +46,7 @@ select v1, v2, coalesce(v2, '1900-01-01 00:00:00') as coalesce_v2 from t1;
4446
3 0001-01-01 01:01:01.123456789 BC 0001-01-01 01:01:01.123456789 BC
4547
4 2213-01-01 01:01:01.123456789 2213-01-01 01:01:01.123456789
4648
5 NULL 1900-01-01 00:00:00
49+
6 2013-01-01 01:01:01.123456789 2013-01-01 01:01:01.123456789
4750

4851
query T
4952
select count(v2) as total_rows from t1;
@@ -58,13 +61,15 @@ select * from t1 order by v2;
5861
3 0001-01-01 01:01:01.123456789 BC
5962
4 2213-01-01 01:01:01.123456789
6063
5 NULL
64+
6 2013-01-01 01:01:01.123456789
6165

6266
query T rowsort
6367
select * from t1 where v2 >= '2012-01-01 01:01:01.123456';
6468
----
6569
1 2013-01-01 01:01:01.123456789
6670
2 2012-01-01 01:01:01.123456
6771
4 2213-01-01 01:01:01.123456789
72+
6 2013-01-01 01:01:01.123456789
6873

6974
query T rowsort
7075
select v1, cast(v2 as date) as date_v2, cast(v2 as timestamp with time zone) as timestamptz_v2 from t1;
@@ -74,6 +79,7 @@ select v1, cast(v2 as date) as date_v2, cast(v2 as timestamp with time zone) as
7479
3 0001-01-01 BC 0001-01-01 01:01:01.123456+00:00 BC
7580
4 2213-01-01 2213-01-01 01:01:01.123456+00:00
7681
5 NULL NULL
82+
6 2013-01-01 2013-01-01 01:01:01.123456+00:00
7783

7884
query T rowsort
7985
select v1, date_trunc('day', v2) AS truncated_v2 from t1;
@@ -83,6 +89,7 @@ select v1, date_trunc('day', v2) AS truncated_v2 from t1;
8389
3 0001-01-01 00:00:00 BC
8490
4 2213-01-01 00:00:00
8591
5 NULL
92+
6 2013-01-01 00:00:00
8693

8794
query T rowsort
8895
select v1, v2 at time zone 'UTC' as v2_utc from t1;
@@ -92,6 +99,7 @@ select v1, v2 at time zone 'UTC' as v2_utc from t1;
9299
3 0001-01-01 01:01:01.123456+00:00 BC
93100
4 2213-01-01 01:01:01.123456+00:00
94101
5 NULL
102+
6 2013-01-01 01:01:01.123456+00:00
95103

96104
query T rowsort
97105
select v1, to_char(v2, 'YYYY-MM-DD HH24:MI:SS.NS') as formatted_v2 from t1;
@@ -101,6 +109,7 @@ select v1, to_char(v2, 'YYYY-MM-DD HH24:MI:SS.NS') as formatted_v2 from t1;
101109
3 0000-01-01 01:01:01.123456789
102110
4 2213-01-01 01:01:01.123456789
103111
5 NULL
112+
6 2013-01-01 01:01:01.123456789
104113

105114
query T rowsort
106115
select generate_series('2013-01-01 01:01:01.123456789'::timestamp,'2013-01-01 01:01:05.123456790'::timestamp, '1 s');
@@ -111,5 +120,93 @@ select generate_series('2013-01-01 01:01:01.123456789'::timestamp,'2013-01-01 01
111120
2013-01-01 01:01:04.123456789
112121
2013-01-01 01:01:05.123456789
113122

123+
query T rowsort
124+
select DISTINCT v2 FROM t1;
125+
----
126+
0001-01-01 01:01:01.123456789 BC
127+
2012-01-01 01:01:01.123456
128+
2013-01-01 01:01:01.123456789
129+
2213-01-01 01:01:01.123456789
130+
NULL
131+
132+
query T rowsort
133+
select v2, count(*) from t1 group by v2;
134+
----
135+
0001-01-01 01:01:01.123456789 BC 1
136+
2012-01-01 01:01:01.123456 1
137+
2013-01-01 01:01:01.123456789 2
138+
2213-01-01 01:01:01.123456789 1
139+
null 1
140+
141+
query T rowsort
142+
select * from t1 order by v2 desc;
143+
----
144+
5 NULL
145+
4 2213-01-01 01:01:01.123456789
146+
6 2013-01-01 01:01:01.123456789
147+
1 2013-01-01 01:01:01.123456789
148+
2 2012-01-01 01:01:01.123456
149+
3 0001-01-01 01:01:01.123456789 BC
150+
151+
query T rowsort
152+
select max(v2) from t1;
153+
----
154+
2213-01-01 01:01:01.123456789
155+
156+
query T rowsort
157+
select v1, extract(epoch from v2) from t1;
158+
----
159+
1 1357002061.123456789
160+
2 1325379661.123456000
161+
3 -62167215538.876544
162+
4 7668349261.123456789
163+
5 NULL
164+
6 1357002061.123456789
165+
166+
query T rowsort
167+
select v1, extract(second from v2) from t1;
168+
----
169+
1 1.123456789
170+
2 1.123456000
171+
3 1.123456789
172+
4 1.123456789
173+
5 NULL
174+
6 1.123456789
175+
176+
query T rowsort
177+
select v1, extract(millisecond from v2) from t1;
178+
----
179+
1 1123.456789
180+
2 1123.456000
181+
3 1123.456789
182+
4 1123.456789
183+
5 NULL
184+
6 1123.456789
185+
186+
query T rowsort
187+
select v1, extract(microsecond from v2) from t1;
188+
----
189+
1 1123456.789
190+
2 1123456.000
191+
3 1123456.789
192+
4 1123456.789
193+
5 NULL
194+
6 1123456.789
195+
196+
query T rowsort
197+
select v1, extract(nanosecond from v2) from t1;
198+
----
199+
1 1123456789
200+
2 1123456000
201+
3 1123456789
202+
4 1123456789
203+
5 NULL
204+
6 1123456789
205+
206+
query T rowsort
207+
select make_timestamp(2013, 01, 01, 01, 01, 1.123456789);
208+
----
209+
2013-01-01 01:01:01.123456789
210+
114211
statement ok
115212
drop table t1;

src/common/src/types/datetime.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ enum ErrorKind {
256256
ParseDate,
257257
#[error("Can't cast string to time (expected format is HH:MM:SS[.D+{{up to 6 digits}}][Z] or HH:MM)")]
258258
ParseTime,
259-
#[error("Can't cast string to timestamp (expected format is YYYY-MM-DD HH:MM:SS[.D+{{up to 6 digits}}] or YYYY-MM-DD HH:MM or YYYY-MM-DD or ISO 8601 format)")]
259+
#[error("Can't cast string to timestamp (expected format is YYYY-MM-DD HH:MM:SS[.D+{{up to 9 digits}}] or YYYY-MM-DD HH:MM or YYYY-MM-DD or ISO 8601 format)")]
260260
ParseTimestamp,
261261
}
262262

@@ -486,6 +486,7 @@ impl Time {
486486
// it is *microseconds* since 1970-01-01 midnight. 2^62 microseconds covers 146235 years.
487487
// * When the highest 2 bits are `10` or `01`, we flip the second bit to get values from `0b1100...00` to `0b0011..11` again.
488488
// It is *seconds* since 1970-01-01 midnight. It is then followed by another 32 bits as nanoseconds within a second.
489+
// Since timestamp is negative when it is less than 1970-1-1, you need to take both cases into account(`11+00`` or `01+10``).
489490
enum FirstI64 {
490491
V0 { usecs: i64 },
491492
V1 { secs: i64 },

src/expr/impl/src/scalar/extract.rs

+22-12
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,18 @@ fn extract_from_datelike(date: impl Datelike, unit: Unit) -> Decimal {
4242

4343
/// Extract field from `Timelike`.
4444
fn extract_from_timelike(time: impl Timelike, unit: Unit) -> Decimal {
45-
let usecs = || time.second() as u64 * 1_000_000 + (time.nanosecond() / 1000) as u64;
45+
let usecs = || time.second() as u64 * 1_000_000_000 + time.nanosecond() as u64;
4646
match unit {
4747
Hour => time.hour().into(),
4848
Minute => time.minute().into(),
49-
Second => Decimal::from_i128_with_scale(usecs() as i128, 6),
50-
Millisecond => Decimal::from_i128_with_scale(usecs() as i128, 3),
51-
Microsecond => usecs().into(),
49+
Second => Decimal::from_i128_with_scale(usecs() as i128, 9),
50+
Millisecond => Decimal::from_i128_with_scale(usecs() as i128, 6),
51+
Microsecond => Decimal::from_i128_with_scale(usecs() as i128, 3),
52+
Nanosecond => usecs().into(),
5253
Epoch => {
53-
let usecs = time.num_seconds_from_midnight() as u64 * 1_000_000
54-
+ (time.nanosecond() / 1000) as u64;
55-
Decimal::from_i128_with_scale(usecs as i128, 6)
54+
let usecs =
55+
time.num_seconds_from_midnight() as u64 * 1_000_000_000 + time.nanosecond() as u64;
56+
Decimal::from_i128_with_scale(usecs as i128, 9)
5657
}
5758
u => unreachable!("invalid unit {:?} for time", u),
5859
}
@@ -92,12 +93,20 @@ fn extract_from_time(time: Time, unit: &Unit) -> Decimal {
9293
fn extract_from_timestamp(timestamp: Timestamp, unit: &Unit) -> Decimal {
9394
match unit {
9495
Epoch => {
95-
let epoch = timestamp.0.and_utc().timestamp_micros();
96-
Decimal::from_i128_with_scale(epoch as i128, 6)
96+
if let Some(nanos) = timestamp.0.and_utc().timestamp_nanos_opt() {
97+
Decimal::from_i128_with_scale(nanos as i128, 9)
98+
} else {
99+
let micros = timestamp.0.and_utc().timestamp_micros();
100+
Decimal::from_i128_with_scale(micros as i128, 6)
101+
}
97102
}
98103
Julian => {
99-
let epoch =
100-
Decimal::from_i128_with_scale(timestamp.0.and_utc().timestamp_micros() as i128, 6);
104+
let epoch = if let Some(nanos) = timestamp.0.and_utc().timestamp_nanos_opt() {
105+
Decimal::from_i128_with_scale(nanos as i128, 9)
106+
} else {
107+
let epoch = timestamp.0.and_utc().timestamp_micros();
108+
Decimal::from_i128_with_scale(epoch as i128, 6)
109+
};
101110
epoch / (24 * 60 * 60).into() + 2_440_588.into()
102111
}
103112
_ if unit.is_date_unit() => extract_from_datelike(timestamp.0.date(), *unit),
@@ -284,6 +293,7 @@ define_unit! {
284293
Second,
285294
Millisecond,
286295
Microsecond,
296+
Nanosecond,
287297
Epoch,
288298
Julian,
289299
Timezone,
@@ -307,7 +317,7 @@ impl Unit {
307317
const fn is_time_unit(self) -> bool {
308318
matches!(
309319
self,
310-
Hour | Minute | Second | Millisecond | Microsecond | Epoch
320+
Hour | Minute | Second | Millisecond | Microsecond | Nanosecond | Epoch
311321
)
312322
}
313323

src/expr/impl/src/scalar/make_time.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ fn make_naive_time(hour: i32, min: i32, sec: F64) -> Result<NaiveTime> {
4343
});
4444
}
4545
let sec_u32 = sec.0.trunc() as u32;
46-
let microsecond_u32 = ((sec.0 - sec.0.trunc()) * 1_000_000.0).round_ties_even() as u32;
47-
NaiveTime::from_hms_micro_opt(hour as u32, min as u32, sec_u32, microsecond_u32).ok_or_else(
46+
let nanosecond_u32 = ((sec.0 - sec.0.trunc()) * 1_000_000_000.0).round_ties_even() as u32;
47+
NaiveTime::from_hms_nano_opt(hour as u32, min as u32, sec_u32, nanosecond_u32).ok_or_else(
4848
|| ExprError::InvalidParam {
4949
name: "hour, min, sec",
5050
reason: format!("invalid time: {}:{}:{}", hour, min, sec).into(),

0 commit comments

Comments
 (0)