Skip to content

Commit

Permalink
Implement to number functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
RinChanNOWWW committed Oct 17, 2022
1 parent 5fe5344 commit 34beb4f
Show file tree
Hide file tree
Showing 4 changed files with 984 additions and 11 deletions.
102 changes: 102 additions & 0 deletions src/query/expression/src/date_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use chrono::Duration;
use chrono::NaiveDate;
use chrono::NaiveDateTime;
use chrono::TimeZone;
use chrono::Timelike;
use chrono::Utc;
use chrono_tz::Tz;
use num_traits::AsPrimitive;
Expand Down Expand Up @@ -170,3 +171,104 @@ pub fn today_date() -> i32 {
.signed_duration_since(NaiveDate::from_ymd(1970, 1, 1))
.num_days() as i32
}

pub trait ToNumber<N> {
fn to_number(dt: &DateTime<Tz>) -> N;
}

pub struct ToNumberImpl;

impl ToNumberImpl {
pub fn eval_timestamp<T: ToNumber<R>, R>(ts: i64, tz: &Tz) -> R {
let dt = ts.to_timestamp(tz);
T::to_number(&dt)
}

pub fn eval_date<T: ToNumber<R>, R>(date: i32, tz: &Tz) -> R {
let dt = date.to_date(tz).and_hms(0, 0, 0);
T::to_number(&dt)
}
}

pub struct ToYYYYMM;
pub struct ToYYYYMMDD;
pub struct ToYYYYMMDDHHMMSS;
pub struct ToYear;
pub struct ToMonth;
pub struct ToDayOfYear;
pub struct ToDayOfMonth;
pub struct ToDayOfWeek;
pub struct ToHour;
pub struct ToMinute;
pub struct ToSecond;

impl ToNumber<u32> for ToYYYYMM {
fn to_number(dt: &DateTime<Tz>) -> u32 {
dt.year() as u32 * 100 + dt.month()
}
}

impl ToNumber<u32> for ToYYYYMMDD {
fn to_number(dt: &DateTime<Tz>) -> u32 {
dt.year() as u32 * 10_000 + dt.month() * 100 + dt.day()
}
}

impl ToNumber<u64> for ToYYYYMMDDHHMMSS {
fn to_number(dt: &DateTime<Tz>) -> u64 {
dt.year() as u64 * 10_000_000_000
+ dt.month() as u64 * 100_000_000
+ dt.day() as u64 * 1_000_000
+ dt.hour() as u64 * 10_000
+ dt.minute() as u64 * 100
+ dt.second() as u64
}
}

impl ToNumber<u16> for ToYear {
fn to_number(dt: &DateTime<Tz>) -> u16 {
dt.year() as u16
}
}

impl ToNumber<u8> for ToMonth {
fn to_number(dt: &DateTime<Tz>) -> u8 {
dt.month() as u8
}
}

impl ToNumber<u16> for ToDayOfYear {
fn to_number(dt: &DateTime<Tz>) -> u16 {
dt.ordinal() as u16
}
}

impl ToNumber<u8> for ToDayOfMonth {
fn to_number(dt: &DateTime<Tz>) -> u8 {
dt.day() as u8
}
}

impl ToNumber<u8> for ToDayOfWeek {
fn to_number(dt: &DateTime<Tz>) -> u8 {
dt.weekday().number_from_monday() as u8
}
}

impl ToNumber<u8> for ToHour {
fn to_number(dt: &DateTime<Tz>) -> u8 {
dt.hour() as u8
}
}

impl ToNumber<u8> for ToMinute {
fn to_number(dt: &DateTime<Tz>) -> u8 {
dt.minute() as u8
}
}

impl ToNumber<u8> for ToSecond {
fn to_number(dt: &DateTime<Tz>) -> u8 {
dt.second() as u8
}
}
180 changes: 172 additions & 8 deletions src/query/functions-v2/src/scalars/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,18 @@
use chrono::Datelike;
use chrono::Utc;
use common_arrow::arrow::temporal_conversions::EPOCH_DAYS_FROM_CE;
use common_expression::date_helper::today_date;
use common_expression::date_helper::AddDaysImpl;
use common_expression::date_helper::AddMonthsImpl;
use common_expression::date_helper::AddTimesImpl;
use common_expression::date_helper::AddYearsImpl;
use common_expression::date_helper::FACTOR_HOUR;
use common_expression::date_helper::FACTOR_MINUTE;
use common_expression::date_helper::FACTOR_SECOND;
use common_expression::date_helper::*;
use common_expression::types::date::check_date;
use common_expression::types::date::string_to_date;
use common_expression::types::date::DATE_MAX;
use common_expression::types::date::DATE_MIN;
use common_expression::types::nullable::NullableDomain;
use common_expression::types::number::Int64Type;
use common_expression::types::number::SimpleDomain;
use common_expression::types::number::UInt16Type;
use common_expression::types::number::UInt32Type;
use common_expression::types::number::UInt64Type;
use common_expression::types::number::UInt8Type;
use common_expression::types::timestamp::check_number_to_timestamp;
use common_expression::types::timestamp::microseconds_to_days;
use common_expression::types::timestamp::string_to_timestamp;
Expand All @@ -47,11 +44,21 @@ use common_expression::Value;
use num_traits::AsPrimitive;

pub fn register(registry: &mut FunctionRegistry) {
// [cast | try_cast](xx AS [date | timestamp])
// to_[date | timestamp](xx)
register_cast_functions(registry);
register_try_cast_functions(registry);

// [add | subtract]_[years | months | days | hours | minutes | seconds]([date | timestamp], number)
// date_[add | sub]([year | quarter | month | week | day | hour | minute | second], [date | timstamp], number)
// [date | timestamp] [+ | -] interval number [year | quarter | month | week | day | hour | minute | second]
register_add_functions(registry);
register_sub_functions(registry);

register_real_time_functions(registry);

// to_*([date | timestamp]) -> number
register_to_number_functions(registry);
}

fn number_domain_to_timestamp_domain<T: AsPrimitive<i64>>(
Expand Down Expand Up @@ -435,3 +442,160 @@ fn register_real_time_functions(registry: &mut FunctionRegistry) {
|_| Ok(Value::Scalar(today_date() + 1)),
);
}

fn register_to_number_functions(registry: &mut FunctionRegistry) {
// date
registry.register_passthrough_nullable_1_arg::<DateType, UInt32Type, _, _>(
"to_yyyymm",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt32Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToYYYYMM, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt32Type, _, _>(
"to_yyyymmdd",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt32Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToYYYYMMDD, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt64Type, _, _>(
"to_yyyymmddhhmmss",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt64Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToYYYYMMDDHHMMSS, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt16Type, _, _>(
"to_year",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt16Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToYear, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt8Type, _, _>(
"to_month",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToMonth, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt16Type, _, _>(
"to_day_of_year",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt16Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToDayOfYear, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt8Type, _, _>(
"to_day_of_month",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToDayOfMonth, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<DateType, UInt8Type, _, _>(
"to_day_of_week",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<DateType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_date::<ToDayOfWeek, _>(val, &ctx.tz)
}),
);
// timestamp
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt32Type, _, _>(
"to_yyyymm",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt32Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToYYYYMM, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt32Type, _, _>(
"to_yyyymmdd",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt32Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToYYYYMMDD, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt64Type, _, _>(
"to_yyyymmddhhmmss",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt64Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToYYYYMMDDHHMMSS, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt16Type, _, _>(
"to_year",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt16Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToYear, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt8Type, _, _>(
"to_month",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToMonth, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt16Type, _, _>(
"to_day_of_year",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt16Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToDayOfYear, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt8Type, _, _>(
"to_day_of_month",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToDayOfMonth, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt8Type, _, _>(
"to_day_of_week",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToDayOfWeek, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt8Type, _, _>(
"to_hour",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToHour, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt8Type, _, _>(
"to_minute",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToMinute, _>(val, &ctx.tz)
}),
);
registry.register_passthrough_nullable_1_arg::<TimestampType, UInt8Type, _, _>(
"to_second",
FunctionProperty::default(),
|_| None,
vectorize_1_arg::<TimestampType, UInt8Type>(|val, ctx| {
ToNumberImpl::eval_timestamp::<ToSecond, _>(val, &ctx.tz)
}),
);
}
Loading

0 comments on commit 34beb4f

Please sign in to comment.