Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement more datetime functions #202

Merged
merged 8 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Changed
- some cleaning in the translation of Expr -> ast::Expr [#204](https://github.com/Qrlew/qrlew/issues/204)
## Added
- implemented `DAYNAME`, `FROM_UNIXTIME`, `UNIX_TIMESTAMP`, `DATETIME_DIFF`, `QUARTER` and `DATE_FORMAT` [#202](https://github.com/Qrlew/qrlew/issues/202)
- implemented `CURRENT_DATE`, `CURRENT_TIME`, `CURRENT_TIMESTAMP` and `EXTRACT(datepart FROM col)` [#200](https://github.com/Qrlew/qrlew/issues/200)
- implemented `DISTINCT` in aggregations [#197](https://github.com/Qrlew/qrlew/issues/197)
- Implemented math functions: `PI`, `DEGREES`, `TAN`, `RANDOM`, `LOG10`, `LOG2`, `SQUARE` [#196](https://github.com/Qrlew/qrlew/issues/196)
Expand Down
258 changes: 225 additions & 33 deletions src/data_type/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1157,10 +1157,10 @@ pub fn cast(into: DataType) -> impl Function {
match into {
DataType::Text(t) if t == data_type::Text::full() => {
Pointwise::univariate(
//DataType::Any,
DataType::Any,
DataType::text(),
|v| v.to_string().into())
|v| v.to_string().into()
)
}
DataType::Float(f) if f == data_type::Float::full() => {
Pointwise::univariate(
Expand Down Expand Up @@ -1203,27 +1203,6 @@ pub fn cast(into: DataType) -> impl Function {
}
)
}
DataType::Date(d) if d == data_type::Date::full() => {
Pointwise::univariate(
DataType::text(),
DataType::date(),
|v| unimplemented!()
)
}
DataType::DateTime(d) if d == data_type::DateTime::full() => {
Pointwise::univariate(
DataType::text(),
DataType::date_time(),
|v| unimplemented!()
)
}
DataType::Time(t) if t == data_type::Time::full() => {
Pointwise::univariate(
DataType::text(),
DataType::time(),
|v| unimplemented!()
)
}
_ => todo!(),
}
}
Expand Down Expand Up @@ -1789,7 +1768,7 @@ pub fn regexp_contains() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([DataType::text(), DataType::text()]),
DataType::boolean(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1798,7 +1777,7 @@ pub fn regexp_extract() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([DataType::text(), DataType::text(), DataType::integer(), DataType::integer()]),
DataType::optional(DataType::text()),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1807,7 +1786,7 @@ pub fn regexp_replace() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([DataType::text(), DataType::text(), DataType::text()]),
DataType::text(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1816,7 +1795,7 @@ pub fn newid() -> impl Function {
Unimplemented::new(
DataType::unit(),
DataType::text(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1825,7 +1804,7 @@ pub fn encode() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([DataType::text(), DataType::text()]),
DataType::text(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1834,7 +1813,7 @@ pub fn decode() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([DataType::text(), DataType::text()]),
DataType::text(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1843,7 +1822,7 @@ pub fn unhex() -> impl Function {
Unimplemented::new(
DataType::text(),
DataType::text(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand All @@ -1852,23 +1831,23 @@ pub fn current_date() -> impl Function {
Unimplemented::new(
DataType::unit(),
DataType::date(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

pub fn current_time() -> impl Function {
Unimplemented::new(
DataType::unit(),
DataType::time(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

pub fn current_timestamp() -> impl Function {
Unimplemented::new(
DataType::unit(),
DataType::date_time(),
Arc::new(Mutex::new(RefCell::new(|v| unimplemented!())))
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

Expand Down Expand Up @@ -2022,6 +2001,147 @@ pub fn extract_millisecond() -> impl Function {
))
}

pub fn dayname() -> impl Function {
Polymorphic::from((
Pointwise::univariate(
data_type::Date::default(),
DataType::text_values(["Monday".to_string(), "Tuesday".to_string(), "Wednesday".to_string(), "Thursday".to_string(), "Friday".to_string(), "Saturday".to_string(), "Sunday".to_string()]),
|a| (match a.weekday(){
chrono::Weekday::Mon => "Monday",
chrono::Weekday::Tue => "Tuesday",
chrono::Weekday::Wed => "Wednesday",
chrono::Weekday::Thu => "Thursday",
chrono::Weekday::Fri => "Friday",
chrono::Weekday::Sat => "Saturday",
chrono::Weekday::Sun => "Sunday",
}).to_string().into(),
),
Pointwise::univariate(
data_type::DateTime::default(),
DataType::text_values(["Monday".to_string(), "Tuesday".to_string(), "Wednesday".to_string(), "Thursday".to_string(), "Friday".to_string(), "Saturday".to_string(), "Sunday".to_string()]),
|a| (match a.weekday(){
chrono::Weekday::Mon => "Monday",
chrono::Weekday::Tue => "Tuesday",
chrono::Weekday::Wed => "Wednesday",
chrono::Weekday::Thu => "Thursday",
chrono::Weekday::Fri => "Friday",
chrono::Weekday::Sat => "Saturday",
chrono::Weekday::Sun => "Sunday",
}).to_string().into(),
),
))
}

// MySQL FROM_UNIXTIME
pub fn from_unixtime() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([DataType::integer(), DataType::text()]),
DataType::sum([DataType::date(), DataType::date_time()]),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

// MySQL UNIX_TIMESTAMP
pub fn unix_timestamp() -> impl Function {
Unimplemented::new(
DataType::sum([DataType::date(), DataType::date_time()]),
DataType::integer(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

// MySQL DATE_FORMAT
pub fn date_format() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([
DataType::sum([DataType::date(), DataType::date_time(), DataType::text()]),
DataType::text()
]),
DataType::text(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

// MySQL Quarter
pub fn quarter() -> impl Function {
Polymorphic::from((
Pointwise::univariate(
data_type::Date::default(),
DataType::integer_interval(1, 4),
|a| match a.month() {
1..=3 => 1,
4..=6 => 2,
7..=9 => 3,
_ => 4,
}.into()
),
Pointwise::univariate(
data_type::DateTime::default(),
DataType::integer_interval(1, 4),
|a| match a.month() {
1..=3 => 1,
4..=6 => 2,
7..=9 => 3,
_ => 4,
}.into()
),
))
}

// BigQuery DATETIME_DIFF
// MySQL Quarter
pub fn datetime_diff() -> impl Function {
Unimplemented::new(
DataType::structured_from_data_types([
DataType::sum([DataType::date(), DataType::date_time(), DataType::text()]),
DataType::sum([DataType::date(), DataType::date_time(), DataType::text()]),
DataType::text()
]),
DataType::integer(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

// MySQL DATE
pub fn date() -> impl Function {
Polymorphic::from((
Pointwise::univariate(
data_type::Date::default(),
data_type::Date::default(),
|a| a.into(),
),
Pointwise::univariate(
data_type::DateTime::default(),
data_type::Date::default(),
|a| a.date().into(),
),
))
}

pub fn cast_as_date() -> impl Function {
Unimplemented::new(
DataType::sum([DataType::text(), DataType::date_time()]),
DataType::date(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

pub fn cast_as_datetime() -> impl Function {
Unimplemented::new(
DataType::sum([DataType::text(), DataType::date()]),
DataType::date(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

pub fn cast_as_time() -> impl Function {
Unimplemented::new(
DataType::sum([DataType::text(), DataType::date_time()]),
DataType::date_time(),
Arc::new(Mutex::new(RefCell::new(|_| unimplemented!())))
)
}

// Case function
pub fn case() -> impl Function {
Case
Expand Down Expand Up @@ -4256,4 +4376,76 @@ mod tests {
println!("im({}) = {}", set, im);
assert!(im == DataType::float_values([1000.000, 11000.000]));
}

#[test]
fn test_dayname() {
println!("\nTest dayname");
let fun = dayname();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

let set = DataType::date_value(
NaiveDate::from_ymd_opt(2023, 01, 01).unwrap(),
);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::text_value("Sunday".to_string()));

let set = DataType::date_time_value(
NaiveDate::from_ymd_opt(2026, 7, 8).unwrap().and_hms_opt(9, 15, 11).unwrap(),
);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::text_value("Wednesday".to_string()));
}

#[test]
fn test_quarter() {
println!("\nTest quarter");
let fun = quarter();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

let set = DataType::date_value(
NaiveDate::from_ymd_opt(2023, 01, 01).unwrap(),
);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::integer_value(1));

let set = DataType::date_time_value(
NaiveDate::from_ymd_opt(2026, 7, 8).unwrap().and_hms_opt(9, 15, 11).unwrap(),
);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::integer_value(3));
}

#[test]
fn test_date() {
println!("\nTest date");
let fun = date();
println!("type = {}", fun);
println!("domain = {}", fun.domain());
println!("co_domain = {}", fun.co_domain());
println!("data_type = {}", fun.data_type());

let set = DataType::date_value(
NaiveDate::from_ymd_opt(2023, 01, 01).unwrap(),
);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::date_value(NaiveDate::from_ymd_opt(2023, 01, 01).unwrap()));

let set = DataType::date_time_value(
NaiveDate::from_ymd_opt(2026, 7, 8).unwrap().and_hms_opt(9, 15, 11).unwrap(),
);
let im = fun.super_image(&set).unwrap();
println!("im({}) = {}", set, im);
assert!(im == DataType::date_value(NaiveDate::from_ymd_opt(2026, 7, 8).unwrap()));
}
}
2 changes: 1 addition & 1 deletion src/data_type/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl From<DataType> for ast::DataType {
DataType::Bytes(_) => ast::DataType::Blob(None),
DataType::Date(_) => ast::DataType::Date,
DataType::Time(_) => ast::DataType::Time(None, ast::TimezoneInfo::None),
DataType::DateTime(_) => ast::DataType::Datetime(None),
DataType::DateTime(_) => ast::DataType::Timestamp(None, ast::TimezoneInfo::None),
DataType::Optional(o) => ast::DataType::from(o.data_type().clone()),
_ => todo!(),
}
Expand Down
Loading