Skip to content

Commit 1476f43

Browse files
committed
expr: convert more timestamp functions
Signed-off-by: Petros Angelatos <[email protected]>
1 parent 217efb5 commit 1476f43

File tree

3 files changed

+172
-68
lines changed

3 files changed

+172
-68
lines changed

src/expr/src/scalar/func.rs

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,44 +1722,11 @@ where
17221722
{
17231723
let units = a.unwrap_str();
17241724
match units.parse() {
1725-
Ok(units) => date_part_timestamp_inner::<_, D>(units, ts),
1725+
Ok(units) => Ok(date_part_timestamp_inner::<_, D>(units, ts)?.into()),
17261726
Err(_) => Err(EvalError::UnknownUnits(units.to_owned())),
17271727
}
17281728
}
17291729

1730-
fn date_part_timestamp_inner<'a, T, D>(units: DateTimeUnits, ts: T) -> Result<Datum<'a>, EvalError>
1731-
where
1732-
T: TimestampLike,
1733-
D: DecimalLike + Into<Datum<'a>>,
1734-
{
1735-
match units {
1736-
DateTimeUnits::Epoch => Ok(TimestampLike::extract_epoch::<D>(&ts).into()),
1737-
DateTimeUnits::Millennium => Ok(D::from(ts.millennium()).into()),
1738-
DateTimeUnits::Century => Ok(D::from(ts.century()).into()),
1739-
DateTimeUnits::Decade => Ok(D::from(ts.decade()).into()),
1740-
DateTimeUnits::Year => Ok(D::from(ts.year()).into()),
1741-
DateTimeUnits::Quarter => Ok(D::from(ts.quarter()).into()),
1742-
DateTimeUnits::Week => Ok(D::from(ts.week()).into()),
1743-
DateTimeUnits::Month => Ok(D::from(ts.month()).into()),
1744-
DateTimeUnits::Day => Ok(D::from(ts.day()).into()),
1745-
DateTimeUnits::DayOfWeek => Ok(D::from(ts.day_of_week()).into()),
1746-
DateTimeUnits::DayOfYear => Ok(D::from(ts.ordinal()).into()),
1747-
DateTimeUnits::IsoDayOfWeek => Ok(D::from(ts.iso_day_of_week()).into()),
1748-
DateTimeUnits::Hour => Ok(D::from(ts.hour()).into()),
1749-
DateTimeUnits::Minute => Ok(D::from(ts.minute()).into()),
1750-
DateTimeUnits::Second => Ok(ts.extract_second::<D>().into()),
1751-
DateTimeUnits::Milliseconds => Ok(ts.extract_millisecond::<D>().into()),
1752-
DateTimeUnits::Microseconds => Ok(ts.extract_microsecond::<D>().into()),
1753-
DateTimeUnits::Timezone
1754-
| DateTimeUnits::TimezoneHour
1755-
| DateTimeUnits::TimezoneMinute
1756-
| DateTimeUnits::IsoDayOfYear => Err(EvalError::Unsupported {
1757-
feature: format!("'{}' timestamp units", units),
1758-
issue_no: None,
1759-
}),
1760-
}
1761-
}
1762-
17631730
fn extract_date<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
17641731
let units = a.unwrap_str();
17651732
match units.parse() {
@@ -3182,14 +3149,16 @@ pub enum UnaryFunc {
31823149
RegexpMatch(RegexpMatch),
31833150

31843151
ExtractInterval(ExtractInterval),
3185-
ExtractTime(DateTimeUnits),
3186-
ExtractTimestamp(DateTimeUnits),
3187-
ExtractTimestampTz(DateTimeUnits),
3188-
ExtractDate(DateTimeUnits),
31893152
DatePartInterval(DatePartInterval),
3153+
3154+
ExtractTimestamp(ExtractTimestamp),
3155+
ExtractTimestampTz(ExtractTimestampTz),
3156+
DatePartTimestamp(DatePartTimestamp),
3157+
DatePartTimestampTz(DatePartTimestampTz),
3158+
3159+
ExtractDate(DateTimeUnits),
3160+
ExtractTime(DateTimeUnits),
31903161
DatePartTime(DateTimeUnits),
3191-
DatePartTimestamp(DateTimeUnits),
3192-
DatePartTimestampTz(DateTimeUnits),
31933162
DateTruncTimestamp(DateTimeUnits),
31943163
DateTruncTimestampTz(DateTimeUnits),
31953164
TimezoneTimestamp(Timezone),
@@ -3437,7 +3406,11 @@ derive_unary!(
34373406
IsRegexpMatch,
34383407
RegexpMatch,
34393408
ExtractInterval,
3440-
DatePartInterval
3409+
DatePartInterval,
3410+
ExtractTimestamp,
3411+
ExtractTimestampTz,
3412+
DatePartTimestamp,
3413+
DatePartTimestampTz
34413414
);
34423415

34433416
impl UnaryFunc {
@@ -3644,6 +3617,10 @@ impl UnaryFunc {
36443617
| RegexpMatch(_)
36453618
| ExtractInterval(_)
36463619
| DatePartInterval(_)
3620+
| ExtractTimestamp(_)
3621+
| ExtractTimestampTz(_)
3622+
| DatePartTimestamp(_)
3623+
| DatePartTimestampTz(_)
36473624
| Chr(_) => unreachable!(),
36483625
CastRecordToString { ty }
36493626
| CastArrayToString { ty }
@@ -3657,20 +3634,8 @@ impl UnaryFunc {
36573634
cast_record1_to_record2(a, cast_exprs, temp_storage)
36583635
}
36593636
ExtractTime(units) => date_part_time_inner::<Numeric>(*units, a),
3660-
ExtractTimestamp(units) => {
3661-
date_part_timestamp_inner::<_, Numeric>(*units, a.unwrap_timestamp())
3662-
}
3663-
ExtractTimestampTz(units) => {
3664-
date_part_timestamp_inner::<_, Numeric>(*units, a.unwrap_timestamptz())
3665-
}
36663637
ExtractDate(units) => extract_date_inner(*units, a),
36673638
DatePartTime(units) => date_part_time_inner::<f64>(*units, a),
3668-
DatePartTimestamp(units) => {
3669-
date_part_timestamp_inner::<_, f64>(*units, a.unwrap_timestamp())
3670-
}
3671-
DatePartTimestampTz(units) => {
3672-
date_part_timestamp_inner::<_, f64>(*units, a.unwrap_timestamptz())
3673-
}
36743639
DateTruncTimestamp(units) => date_trunc_inner(*units, a.unwrap_timestamp()),
36753640
DateTruncTimestampTz(units) => date_trunc_inner(*units, a.unwrap_timestamptz()),
36763641
TimezoneTimestamp(tz) => timezone_timestamp(*tz, a.unwrap_timestamp()),
@@ -3883,6 +3848,10 @@ impl UnaryFunc {
38833848
| RegexpMatch(_)
38843849
| ExtractInterval(_)
38853850
| DatePartInterval(_)
3851+
| ExtractTimestamp(_)
3852+
| ExtractTimestampTz(_)
3853+
| DatePartTimestamp(_)
3854+
| DatePartTimestampTz(_)
38863855
| Chr(_) => unreachable!(),
38873856

38883857
CastRecordToString { .. }
@@ -3903,13 +3872,11 @@ impl UnaryFunc {
39033872

39043873
CastList1ToList2 { return_ty, .. } => return_ty.without_modifiers().nullable(false),
39053874

3906-
ExtractTime(_) | ExtractTimestamp(_) | ExtractTimestampTz(_) | ExtractDate(_) => {
3875+
ExtractTime(_) | ExtractDate(_) => {
39073876
ScalarType::Numeric { max_scale: None }.nullable(nullable)
39083877
}
39093878

3910-
DatePartTime(_) | DatePartTimestamp(_) | DatePartTimestampTz(_) => {
3911-
ScalarType::Float64.nullable(nullable)
3912-
}
3879+
DatePartTime(_) => ScalarType::Float64.nullable(nullable),
39133880

39143881
DateTruncTimestamp(_) => ScalarType::Timestamp.nullable(nullable),
39153882
DateTruncTimestampTz(_) => ScalarType::TimestampTz.nullable(nullable),
@@ -4135,6 +4102,10 @@ impl UnaryFunc {
41354102
| RegexpMatch(_)
41364103
| ExtractInterval(_)
41374104
| DatePartInterval(_)
4105+
| ExtractTimestamp(_)
4106+
| ExtractTimestampTz(_)
4107+
| DatePartTimestamp(_)
4108+
| DatePartTimestampTz(_)
41384109
| Chr(_) => unreachable!(),
41394110
// Return null if the inner field is null
41404111
RecordGet(_) => true,
@@ -4149,8 +4120,8 @@ impl UnaryFunc {
41494120
TimezoneTimestamp(_) => false,
41504121
CastList1ToList2 { .. } | CastRecord1ToRecord2 { .. } => false,
41514122
ListLength | MapLength => false,
4152-
ExtractTime(_) | ExtractTimestamp(_) | ExtractTimestampTz(_) | ExtractDate(_) => false,
4153-
DatePartTime(_) | DatePartTimestamp(_) | DatePartTimestampTz(_) => false,
4123+
ExtractTime(_) | ExtractDate(_) => false,
4124+
DatePartTime(_) => false,
41544125
DateTruncTimestamp(_) | DateTruncTimestampTz(_) => false,
41554126
RescaleNumeric(_) => false,
41564127
}
@@ -4255,6 +4226,10 @@ impl UnaryFunc {
42554226
| RegexpMatch(_)
42564227
| ExtractInterval(_)
42574228
| DatePartInterval(_)
4229+
| ExtractTimestamp(_)
4230+
| ExtractTimestampTz(_)
4231+
| DatePartTimestamp(_)
4232+
| DatePartTimestampTz(_)
42584233
| CastVarCharToString(_) => unreachable!(),
42594234
_ => false,
42604235
}
@@ -4453,6 +4428,10 @@ impl UnaryFunc {
44534428
| RegexpMatch(_)
44544429
| ExtractInterval(_)
44554430
| DatePartInterval(_)
4431+
| ExtractTimestamp(_)
4432+
| ExtractTimestampTz(_)
4433+
| DatePartTimestamp(_)
4434+
| DatePartTimestampTz(_)
44564435
| Chr(_) => unreachable!(),
44574436
CastRecordToString { .. } => f.write_str("recordtostr"),
44584437
CastRecord1ToRecord2 { .. } => f.write_str("record1torecord2"),
@@ -4462,12 +4441,8 @@ impl UnaryFunc {
44624441
CastList1ToList2 { .. } => f.write_str("list1tolist2"),
44634442
CastMapToString { .. } => f.write_str("maptostr"),
44644443
ExtractTime(units) => write!(f, "extract_{}_t", units),
4465-
ExtractTimestamp(units) => write!(f, "extract_{}_ts", units),
4466-
ExtractTimestampTz(units) => write!(f, "extract_{}_tstz", units),
44674444
ExtractDate(units) => write!(f, "extract_{}_d", units),
44684445
DatePartTime(units) => write!(f, "date_part_{}_t", units),
4469-
DatePartTimestamp(units) => write!(f, "date_part_{}_ts", units),
4470-
DatePartTimestampTz(units) => write!(f, "date_part_{}_tstz", units),
44714446
DateTruncTimestamp(units) => write!(f, "date_trunc_{}_ts", units),
44724447
DateTruncTimestampTz(units) => write!(f, "date_trunc_{}_tstz", units),
44734448
TimezoneTimestamp(tz) => write!(f, "timezone_{}_ts", tz),

src/expr/src/scalar/func/impls/timestamp.rs

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use mz_repr::adt::interval::Interval;
1818
use mz_repr::adt::numeric::{DecimalLike, Numeric};
1919
use mz_repr::{strconv, ColumnType, ScalarType};
2020

21-
use crate::scalar::func::EagerUnaryFunc;
21+
use crate::scalar::func::{EagerUnaryFunc, TimestampLike};
2222
use crate::EvalError;
2323

2424
sqlfunc!(
@@ -159,3 +159,124 @@ impl fmt::Display for DatePartInterval {
159159
write!(f, "date_part_{}_iv", self.0)
160160
}
161161
}
162+
163+
pub fn date_part_timestamp_inner<T, D>(units: DateTimeUnits, ts: T) -> Result<D, EvalError>
164+
where
165+
T: TimestampLike,
166+
D: DecimalLike,
167+
{
168+
match units {
169+
DateTimeUnits::Epoch => Ok(TimestampLike::extract_epoch(&ts)),
170+
DateTimeUnits::Millennium => Ok(D::from(ts.millennium())),
171+
DateTimeUnits::Century => Ok(D::from(ts.century())),
172+
DateTimeUnits::Decade => Ok(D::from(ts.decade())),
173+
DateTimeUnits::Year => Ok(D::from(ts.year())),
174+
DateTimeUnits::Quarter => Ok(D::from(ts.quarter())),
175+
DateTimeUnits::Week => Ok(D::from(ts.week())),
176+
DateTimeUnits::Month => Ok(D::from(ts.month())),
177+
DateTimeUnits::Day => Ok(D::from(ts.day())),
178+
DateTimeUnits::DayOfWeek => Ok(D::from(ts.day_of_week())),
179+
DateTimeUnits::DayOfYear => Ok(D::from(ts.ordinal())),
180+
DateTimeUnits::IsoDayOfWeek => Ok(D::from(ts.iso_day_of_week())),
181+
DateTimeUnits::Hour => Ok(D::from(ts.hour())),
182+
DateTimeUnits::Minute => Ok(D::from(ts.minute())),
183+
DateTimeUnits::Second => Ok(ts.extract_second()),
184+
DateTimeUnits::Milliseconds => Ok(ts.extract_millisecond()),
185+
DateTimeUnits::Microseconds => Ok(ts.extract_microsecond()),
186+
DateTimeUnits::Timezone
187+
| DateTimeUnits::TimezoneHour
188+
| DateTimeUnits::TimezoneMinute
189+
| DateTimeUnits::IsoDayOfYear => Err(EvalError::Unsupported {
190+
feature: format!("'{}' timestamp units", units),
191+
issue_no: None,
192+
}),
193+
}
194+
}
195+
196+
#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
197+
pub struct ExtractTimestamp(pub DateTimeUnits);
198+
199+
impl<'a> EagerUnaryFunc<'a> for ExtractTimestamp {
200+
type Input = NaiveDateTime;
201+
type Output = Result<Numeric, EvalError>;
202+
203+
fn call(&self, a: NaiveDateTime) -> Result<Numeric, EvalError> {
204+
date_part_timestamp_inner(self.0, a)
205+
}
206+
207+
fn output_type(&self, input: ColumnType) -> ColumnType {
208+
ScalarType::Numeric { max_scale: None }.nullable(input.nullable)
209+
}
210+
}
211+
212+
impl fmt::Display for ExtractTimestamp {
213+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214+
write!(f, "extract_{}_ts", self.0)
215+
}
216+
}
217+
218+
#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
219+
pub struct ExtractTimestampTz(pub DateTimeUnits);
220+
221+
impl<'a> EagerUnaryFunc<'a> for ExtractTimestampTz {
222+
type Input = DateTime<Utc>;
223+
type Output = Result<Numeric, EvalError>;
224+
225+
fn call(&self, a: DateTime<Utc>) -> Result<Numeric, EvalError> {
226+
date_part_timestamp_inner(self.0, a)
227+
}
228+
229+
fn output_type(&self, input: ColumnType) -> ColumnType {
230+
ScalarType::Numeric { max_scale: None }.nullable(input.nullable)
231+
}
232+
}
233+
234+
impl fmt::Display for ExtractTimestampTz {
235+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236+
write!(f, "extract_{}_tstz", self.0)
237+
}
238+
}
239+
240+
#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
241+
pub struct DatePartTimestamp(pub DateTimeUnits);
242+
243+
impl<'a> EagerUnaryFunc<'a> for DatePartTimestamp {
244+
type Input = NaiveDateTime;
245+
type Output = Result<f64, EvalError>;
246+
247+
fn call(&self, a: NaiveDateTime) -> Result<f64, EvalError> {
248+
date_part_timestamp_inner(self.0, a)
249+
}
250+
251+
fn output_type(&self, input: ColumnType) -> ColumnType {
252+
ScalarType::Float64.nullable(input.nullable)
253+
}
254+
}
255+
256+
impl fmt::Display for DatePartTimestamp {
257+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258+
write!(f, "date_part_{}_ts", self.0)
259+
}
260+
}
261+
262+
#[derive(Ord, PartialOrd, Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash, MzReflect)]
263+
pub struct DatePartTimestampTz(pub DateTimeUnits);
264+
265+
impl<'a> EagerUnaryFunc<'a> for DatePartTimestampTz {
266+
type Input = DateTime<Utc>;
267+
type Output = Result<f64, EvalError>;
268+
269+
fn call(&self, a: DateTime<Utc>) -> Result<f64, EvalError> {
270+
date_part_timestamp_inner(self.0, a)
271+
}
272+
273+
fn output_type(&self, input: ColumnType) -> ColumnType {
274+
ScalarType::Float64.nullable(input.nullable)
275+
}
276+
}
277+
278+
impl fmt::Display for DatePartTimestampTz {
279+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
280+
write!(f, "date_part_{}_tstz", self.0)
281+
}
282+
}

src/expr/src/scalar/mod.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,9 @@ impl MirScalarExpr {
402402
let units = expr1.as_literal_str().unwrap();
403403
*e = match units.parse::<DateTimeUnits>() {
404404
Ok(units) => MirScalarExpr::CallUnary {
405-
func: UnaryFunc::ExtractTimestamp(units),
405+
func: UnaryFunc::ExtractTimestamp(func::ExtractTimestamp(
406+
units,
407+
)),
406408
expr: Box::new(expr2.take()),
407409
},
408410
Err(_) => MirScalarExpr::literal(
@@ -414,7 +416,9 @@ impl MirScalarExpr {
414416
let units = expr1.as_literal_str().unwrap();
415417
*e = match units.parse::<DateTimeUnits>() {
416418
Ok(units) => MirScalarExpr::CallUnary {
417-
func: UnaryFunc::ExtractTimestampTz(units),
419+
func: UnaryFunc::ExtractTimestampTz(func::ExtractTimestampTz(
420+
units,
421+
)),
418422
expr: Box::new(expr2.take()),
419423
},
420424
Err(_) => MirScalarExpr::literal(
@@ -464,7 +468,9 @@ impl MirScalarExpr {
464468
let units = expr1.as_literal_str().unwrap();
465469
*e = match units.parse::<DateTimeUnits>() {
466470
Ok(units) => MirScalarExpr::CallUnary {
467-
func: UnaryFunc::DatePartTimestamp(units),
471+
func: UnaryFunc::DatePartTimestamp(func::DatePartTimestamp(
472+
units,
473+
)),
468474
expr: Box::new(expr2.take()),
469475
},
470476
Err(_) => MirScalarExpr::literal(
@@ -476,7 +482,9 @@ impl MirScalarExpr {
476482
let units = expr1.as_literal_str().unwrap();
477483
*e = match units.parse::<DateTimeUnits>() {
478484
Ok(units) => MirScalarExpr::CallUnary {
479-
func: UnaryFunc::DatePartTimestampTz(units),
485+
func: UnaryFunc::DatePartTimestampTz(
486+
func::DatePartTimestampTz(units),
487+
),
480488
expr: Box::new(expr2.take()),
481489
},
482490
Err(_) => MirScalarExpr::literal(

0 commit comments

Comments
 (0)