Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::expression::function::table::TableFunctionImpl;
use crate::expression::function::FunctionSummary;
use crate::function::char_length::CharLength;
use crate::function::current_date::CurrentDate;
use crate::function::current_timestamp::CurrentTimeStamp;
use crate::function::lower::Lower;
use crate::function::numbers::Numbers;
use crate::function::octet_length::OctetLength;
Expand Down Expand Up @@ -61,6 +62,7 @@ impl DataBaseBuilder {
builder =
builder.register_scala_function(CharLength::new("character_length".to_lowercase()));
builder = builder.register_scala_function(CurrentDate::new());
builder = builder.register_scala_function(CurrentTimeStamp::new());
builder = builder.register_scala_function(Lower::new());
builder = builder.register_scala_function(OctetLength::new());
builder = builder.register_scala_function(Upper::new());
Expand Down
56 changes: 56 additions & 0 deletions src/function/current_timestamp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use crate::catalog::ColumnRef;
use crate::errors::DatabaseError;
use crate::expression::function::scala::FuncMonotonicity;
use crate::expression::function::scala::ScalarFunctionImpl;
use crate::expression::function::FunctionSummary;
use crate::expression::ScalarExpression;
use crate::types::tuple::Tuple;
use crate::types::value::DataValue;
use crate::types::LogicalType;
use chrono::Utc;
use serde::Deserialize;
use serde::Serialize;
use std::sync::Arc;

#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct CurrentTimeStamp {
summary: FunctionSummary,
}

impl CurrentTimeStamp {
#[allow(unused_mut)]
pub(crate) fn new() -> Arc<Self> {
let function_name = "current_timestamp".to_lowercase();

Arc::new(Self {
summary: FunctionSummary {
name: function_name,
arg_types: Vec::new(),
},
})
}
}

#[typetag::serde]
impl ScalarFunctionImpl for CurrentTimeStamp {
#[allow(unused_variables, clippy::redundant_closure_call)]
fn eval(
&self,
_: &[ScalarExpression],
_: Option<(&Tuple, &[ColumnRef])>,
) -> Result<DataValue, DatabaseError> {
Ok(DataValue::Time64(Utc::now().timestamp(), 0, false))
}

fn monotonicity(&self) -> Option<FuncMonotonicity> {
todo!()
}

fn return_type(&self) -> &LogicalType {
&LogicalType::TimeStamp(None, false)
}

fn summary(&self) -> &FunctionSummary {
&self.summary
}
}
1 change: 1 addition & 0 deletions src/function/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub(crate) mod char_length;
pub(crate) mod current_date;
pub(crate) mod current_timestamp;
pub(crate) mod lower;
pub(crate) mod numbers;
pub(crate) mod octet_length;
Expand Down
10 changes: 8 additions & 2 deletions src/optimizer/core/histogram.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,14 +329,20 @@ impl Histogram {
}
_ => unreachable!(),
},
LogicalType::Date | LogicalType::DateTime | LogicalType::Time => match value {
LogicalType::Date
| LogicalType::DateTime
| LogicalType::Time(_, _)
| LogicalType::TimeStamp(_, _) => match value {
DataValue::Date32(value) => DataValue::Int32(*value)
.cast(&LogicalType::Double)?
.double(),
DataValue::Date64(value) => DataValue::Int64(*value)
.cast(&LogicalType::Double)?
.double(),
DataValue::Time(value) => DataValue::UInt32(*value)
DataValue::Time(value, ..) => DataValue::UInt32(*value)
.cast(&LogicalType::Double)?
.double(),
DataValue::Time64(value, ..) => DataValue::Int64(*value)
.cast(&LogicalType::Double)?
.double(),
_ => unreachable!(),
Expand Down
29 changes: 28 additions & 1 deletion src/types/evaluator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod int64;
pub mod int8;
pub mod null;
pub mod time;
pub mod time64;
pub mod tuple;
pub mod uint16;
pub mod uint32;
Expand All @@ -31,6 +32,7 @@ use crate::types::evaluator::int64::*;
use crate::types::evaluator::int8::*;
use crate::types::evaluator::null::NullBinaryEvaluator;
use crate::types::evaluator::time::*;
use crate::types::evaluator::time64::*;
use crate::types::evaluator::tuple::{
TupleEqBinaryEvaluator, TupleGtBinaryEvaluator, TupleGtEqBinaryEvaluator,
TupleLtBinaryEvaluator, TupleLtEqBinaryEvaluator, TupleNotEqBinaryEvaluator,
Expand Down Expand Up @@ -191,7 +193,32 @@ impl EvaluatorFactory {
LogicalType::Double => numeric_binary_evaluator!(Float64, op, LogicalType::Double),
LogicalType::Date => numeric_binary_evaluator!(Date, op, LogicalType::Date),
LogicalType::DateTime => numeric_binary_evaluator!(DateTime, op, LogicalType::DateTime),
LogicalType::Time => numeric_binary_evaluator!(Time, op, LogicalType::Time),
LogicalType::Time(_, _) => match op {
BinaryOperator::Plus => Ok(BinaryEvaluatorBox(Arc::new(TimePlusBinaryEvaluator))),
BinaryOperator::Minus => Ok(BinaryEvaluatorBox(Arc::new(TimeMinusBinaryEvaluator))),
BinaryOperator::Gt => Ok(BinaryEvaluatorBox(Arc::new(TimeGtBinaryEvaluator))),
BinaryOperator::GtEq => Ok(BinaryEvaluatorBox(Arc::new(TimeGtEqBinaryEvaluator))),
BinaryOperator::Lt => Ok(BinaryEvaluatorBox(Arc::new(TimeLtBinaryEvaluator))),
BinaryOperator::LtEq => Ok(BinaryEvaluatorBox(Arc::new(TimeLtEqBinaryEvaluator))),
BinaryOperator::Eq => Ok(BinaryEvaluatorBox(Arc::new(TimeEqBinaryEvaluator))),
BinaryOperator::NotEq => Ok(BinaryEvaluatorBox(Arc::new(TimeNotEqBinaryEvaluator))),
_ => Err(DatabaseError::UnsupportedBinaryOperator(ty, op)),
},
LogicalType::TimeStamp(_, _) => match op {
BinaryOperator::Plus => Ok(BinaryEvaluatorBox(Arc::new(Time64PlusBinaryEvaluator))),
BinaryOperator::Minus => {
Ok(BinaryEvaluatorBox(Arc::new(Time64MinusBinaryEvaluator)))
}
BinaryOperator::Gt => Ok(BinaryEvaluatorBox(Arc::new(Time64GtBinaryEvaluator))),
BinaryOperator::GtEq => Ok(BinaryEvaluatorBox(Arc::new(Time64GtEqBinaryEvaluator))),
BinaryOperator::Lt => Ok(BinaryEvaluatorBox(Arc::new(Time64LtBinaryEvaluator))),
BinaryOperator::LtEq => Ok(BinaryEvaluatorBox(Arc::new(Time64LtEqBinaryEvaluator))),
BinaryOperator::Eq => Ok(BinaryEvaluatorBox(Arc::new(Time64EqBinaryEvaluator))),
BinaryOperator::NotEq => {
Ok(BinaryEvaluatorBox(Arc::new(Time64NotEqBinaryEvaluator)))
}
_ => Err(DatabaseError::UnsupportedBinaryOperator(ty, op)),
},
LogicalType::Decimal(_, _) => numeric_binary_evaluator!(Decimal, op, ty),
LogicalType::Boolean => match op {
BinaryOperator::And => Ok(BinaryEvaluatorBox(Arc::new(BooleanAndBinaryEvaluator))),
Expand Down
208 changes: 205 additions & 3 deletions src/types/evaluator/time.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,210 @@
use crate::numeric_binary_evaluator_definition;
use crate::types::evaluator::BinaryEvaluator;
use crate::types::evaluator::DataValue;
use paste::paste;
use serde::{Deserialize, Serialize};
use std::hint;

numeric_binary_evaluator_definition!(Time, DataValue::Time);
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimePlusBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeMinusBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeGtBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeGtEqBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeLtBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeLtEqBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeEqBinaryEvaluator;
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
pub struct TimeNotEqBinaryEvaluator;

#[typetag::serde]
impl BinaryEvaluator for TimePlusBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (mut v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
let mut n = n1 + n2;
while n > 1_000_000_000 {
v1 += 1;
n -= 1_000_000_000;
}
let p = if p2 > p1 { *p2 } else { *p1 };
if v1 + v2 > 86400 {
return DataValue::Null;
}
DataValue::Time(DataValue::pack(v1 + v2, n, p), p, false)
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
#[typetag::serde]
impl BinaryEvaluator for TimeMinusBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (mut v1, mut n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
while n1 < n2 {
v1 -= 1;
n1 += 1_000_000_000;
}
if v1 < v2 {
return DataValue::Null;
}
let p = if p2 > p1 { *p2 } else { *p1 };
DataValue::Time(DataValue::pack(v1 - v2, n1 - n2, p), p, false)
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}

#[typetag::serde]
impl BinaryEvaluator for TimeGtBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
match v1 > v2 {
true => DataValue::Boolean(true),
false => match v1 < v2 {
true => DataValue::Boolean(false),
false => match n1 > n2 {
true => DataValue::Boolean(true),
false => DataValue::Boolean(false),
},
},
}
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
#[typetag::serde]
impl BinaryEvaluator for TimeGtEqBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
match v1 > v2 {
true => DataValue::Boolean(true),
false => match v1 < v2 {
true => DataValue::Boolean(false),
false => match n1 >= n2 {
true => DataValue::Boolean(true),
false => DataValue::Boolean(false),
},
},
}
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
#[typetag::serde]
impl BinaryEvaluator for TimeLtBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
match v1 < v2 {
true => DataValue::Boolean(true),
false => match v1 > v2 {
true => DataValue::Boolean(false),
false => match n1 < n2 {
true => DataValue::Boolean(true),
false => DataValue::Boolean(false),
},
},
}
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
#[typetag::serde]
impl BinaryEvaluator for TimeLtEqBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
match v1 < v2 {
true => DataValue::Boolean(true),
false => match v1 > v2 {
true => DataValue::Boolean(false),
false => match n1 <= n2 {
true => DataValue::Boolean(true),
false => DataValue::Boolean(false),
},
},
}
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
#[typetag::serde]
impl BinaryEvaluator for TimeEqBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
match (v1 == v2, n1 == n2) {
(true, true) => DataValue::Boolean(true),
_ => DataValue::Boolean(false),
}
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
#[typetag::serde]
impl BinaryEvaluator for TimeNotEqBinaryEvaluator {
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
match (left, right) {
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
let (v1, n1) = DataValue::unpack(*v1, *p1);
let (v2, n2) = DataValue::unpack(*v2, *p2);
match (v1 != v2, n1 != n2) {
(false, false) => DataValue::Boolean(false),
_ => DataValue::Boolean(true),
}
}
(DataValue::Time(..), DataValue::Null)
| (DataValue::Null, DataValue::Time(..))
| (DataValue::Null, DataValue::Null) => DataValue::Null,
_ => unsafe { hint::unreachable_unchecked() },
}
}
}
Loading
Loading