Skip to content

Commit 53c6a4c

Browse files
authored
fix(expr): do not construct error for extracting time subfield (risingwavelabs#8538)
Signed-off-by: Bugen Zhao <[email protected]>
1 parent 53eaa24 commit 53c6a4c

File tree

1 file changed

+35
-32
lines changed

1 file changed

+35
-32
lines changed

src/expr/src/vector_op/extract.rs

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,61 +15,64 @@
1515
use chrono::{Datelike, Timelike};
1616
use risingwave_common::types::{Decimal, NaiveDateTimeWrapper, NaiveDateWrapper, NaiveTimeWrapper};
1717

18-
use crate::{bail, Result};
18+
use crate::{ExprError, Result};
1919

20-
fn extract_time<T>(time: T, time_unit: &str) -> Result<Decimal>
20+
fn extract_time<T>(time: T, unit: &str) -> Option<Decimal>
2121
where
2222
T: Timelike,
2323
{
24-
match time_unit {
25-
"HOUR" => Ok(time.hour().into()),
26-
"MINUTE" => Ok(time.minute().into()),
27-
"SECOND" => Ok(time.second().into()),
28-
_ => bail!("Unsupported time unit {} in extract function", time_unit),
29-
}
24+
Some(match unit {
25+
"HOUR" => time.hour().into(),
26+
"MINUTE" => time.minute().into(),
27+
"SECOND" => time.second().into(),
28+
_ => return None,
29+
})
3030
}
3131

32-
fn extract_date<T>(date: T, time_unit: &str) -> Result<Decimal>
32+
fn extract_date<T>(date: T, unit: &str) -> Option<Decimal>
3333
where
3434
T: Datelike,
3535
{
36-
match time_unit {
37-
"DAY" => Ok(date.day().into()),
38-
"MONTH" => Ok(date.month().into()),
39-
"YEAR" => Ok(date.year().into()),
36+
Some(match unit {
37+
"DAY" => date.day().into(),
38+
"MONTH" => date.month().into(),
39+
"YEAR" => date.year().into(),
4040
// Sun = 0 and Sat = 6
41-
"DOW" => Ok(date.weekday().num_days_from_sunday().into()),
42-
"DOY" => Ok(date.ordinal().into()),
43-
_ => bail!("Unsupported time unit {} in extract function", time_unit),
41+
"DOW" => date.weekday().num_days_from_sunday().into(),
42+
"DOY" => date.ordinal().into(),
43+
_ => return None,
44+
})
45+
}
46+
47+
fn invalid_unit(name: &'static str, unit: &str) -> ExprError {
48+
ExprError::InvalidParam {
49+
name,
50+
reason: format!("\"{unit}\" not recognized or supported"),
4451
}
4552
}
4653

47-
pub fn extract_from_date(time_unit: &str, date: NaiveDateWrapper) -> Result<Decimal> {
48-
extract_date(date.0, time_unit)
54+
pub fn extract_from_date(unit: &str, date: NaiveDateWrapper) -> Result<Decimal> {
55+
extract_date(date.0, unit).ok_or_else(|| invalid_unit("date unit", unit))
4956
}
5057

51-
pub fn extract_from_timestamp(time_unit: &str, timestamp: NaiveDateTimeWrapper) -> Result<Decimal> {
58+
pub fn extract_from_timestamp(unit: &str, timestamp: NaiveDateTimeWrapper) -> Result<Decimal> {
5259
let time = timestamp.0;
53-
let mut res = extract_date(time, time_unit);
54-
if res.is_err() {
55-
res = extract_time(time, time_unit);
56-
}
57-
res
60+
61+
extract_date(time, unit)
62+
.or_else(|| extract_time(time, unit))
63+
.ok_or_else(|| invalid_unit("timestamp unit", unit))
5864
}
5965

60-
pub fn extract_from_timestamptz(time_unit: &str, usecs: i64) -> Result<Decimal> {
61-
match time_unit {
66+
pub fn extract_from_timestamptz(unit: &str, usecs: i64) -> Result<Decimal> {
67+
match unit {
6268
"EPOCH" => Ok(Decimal::from(usecs) / 1_000_000.into()),
6369
// TODO(#5826): all other units depend on implicit session TimeZone
64-
_ => bail!(
65-
"Unsupported timestamp with time zone unit {} in extract function",
66-
time_unit
67-
),
70+
_ => Err(invalid_unit("timestamp with time zone units", unit)),
6871
}
6972
}
7073

71-
pub fn extract_from_time(time_unit: &str, time: NaiveTimeWrapper) -> Result<Decimal> {
72-
extract_time(time.0, time_unit)
74+
pub fn extract_from_time(unit: &str, time: NaiveTimeWrapper) -> Result<Decimal> {
75+
extract_time(time.0, unit).ok_or_else(|| invalid_unit("time unit", unit))
7376
}
7477

7578
#[cfg(test)]

0 commit comments

Comments
 (0)