Skip to content

Commit 600d8f0

Browse files
committed
feat: TimeStamp types that support precision and time zones, as well as conversion of related types, are implemented. Added precision support for the Time type. current_timestamp function added
1 parent e32ef34 commit 600d8f0

File tree

12 files changed

+975
-59
lines changed

12 files changed

+975
-59
lines changed

src/db.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::expression::function::table::TableFunctionImpl;
66
use crate::expression::function::FunctionSummary;
77
use crate::function::char_length::CharLength;
88
use crate::function::current_date::CurrentDate;
9+
use crate::function::current_timestamp::CurrentTimeStamp;
910
use crate::function::lower::Lower;
1011
use crate::function::numbers::Numbers;
1112
use crate::function::octet_length::OctetLength;
@@ -61,6 +62,7 @@ impl DataBaseBuilder {
6162
builder =
6263
builder.register_scala_function(CharLength::new("character_length".to_lowercase()));
6364
builder = builder.register_scala_function(CurrentDate::new());
65+
builder = builder.register_scala_function(CurrentTimeStamp::new());
6466
builder = builder.register_scala_function(Lower::new());
6567
builder = builder.register_scala_function(OctetLength::new());
6668
builder = builder.register_scala_function(Upper::new());

src/function/current_timestamp.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use crate::catalog::ColumnRef;
2+
use crate::errors::DatabaseError;
3+
use crate::expression::function::scala::FuncMonotonicity;
4+
use crate::expression::function::scala::ScalarFunctionImpl;
5+
use crate::expression::function::FunctionSummary;
6+
use crate::expression::ScalarExpression;
7+
use crate::types::tuple::Tuple;
8+
use crate::types::value::DataValue;
9+
use crate::types::LogicalType;
10+
use chrono::Utc;
11+
use serde::Deserialize;
12+
use serde::Serialize;
13+
use std::sync::Arc;
14+
15+
#[derive(Debug, Serialize, Deserialize)]
16+
pub(crate) struct CurrentTimeStamp {
17+
summary: FunctionSummary,
18+
}
19+
20+
impl CurrentTimeStamp {
21+
#[allow(unused_mut)]
22+
pub(crate) fn new() -> Arc<Self> {
23+
let function_name = "current_timestamp".to_lowercase();
24+
25+
Arc::new(Self {
26+
summary: FunctionSummary {
27+
name: function_name,
28+
arg_types: Vec::new(),
29+
},
30+
})
31+
}
32+
}
33+
34+
#[typetag::serde]
35+
impl ScalarFunctionImpl for CurrentTimeStamp {
36+
#[allow(unused_variables, clippy::redundant_closure_call)]
37+
fn eval(
38+
&self,
39+
_: &[ScalarExpression],
40+
_: Option<(&Tuple, &[ColumnRef])>,
41+
) -> Result<DataValue, DatabaseError> {
42+
Ok(DataValue::Time64(Utc::now().timestamp(), 0, false))
43+
}
44+
45+
fn monotonicity(&self) -> Option<FuncMonotonicity> {
46+
todo!()
47+
}
48+
49+
fn return_type(&self) -> &LogicalType {
50+
&LogicalType::TimeStamp(None, false)
51+
}
52+
53+
fn summary(&self) -> &FunctionSummary {
54+
&self.summary
55+
}
56+
}

src/function/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub(crate) mod char_length;
22
pub(crate) mod current_date;
3+
pub(crate) mod current_timestamp;
34
pub(crate) mod lower;
45
pub(crate) mod numbers;
56
pub(crate) mod octet_length;

src/optimizer/core/histogram.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,14 +329,20 @@ impl Histogram {
329329
}
330330
_ => unreachable!(),
331331
},
332-
LogicalType::Date | LogicalType::DateTime | LogicalType::Time => match value {
332+
LogicalType::Date
333+
| LogicalType::DateTime
334+
| LogicalType::Time(_, _)
335+
| LogicalType::TimeStamp(_, _) => match value {
333336
DataValue::Date32(value) => DataValue::Int32(*value)
334337
.cast(&LogicalType::Double)?
335338
.double(),
336339
DataValue::Date64(value) => DataValue::Int64(*value)
337340
.cast(&LogicalType::Double)?
338341
.double(),
339-
DataValue::Time(value) => DataValue::UInt32(*value)
342+
DataValue::Time(value, ..) => DataValue::UInt32(*value)
343+
.cast(&LogicalType::Double)?
344+
.double(),
345+
DataValue::Time64(value, ..) => DataValue::Int64(*value)
340346
.cast(&LogicalType::Double)?
341347
.double(),
342348
_ => unreachable!(),

src/types/evaluator/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod int64;
1010
pub mod int8;
1111
pub mod null;
1212
pub mod time;
13+
pub mod time64;
1314
pub mod tuple;
1415
pub mod uint16;
1516
pub mod uint32;
@@ -31,6 +32,7 @@ use crate::types::evaluator::int64::*;
3132
use crate::types::evaluator::int8::*;
3233
use crate::types::evaluator::null::NullBinaryEvaluator;
3334
use crate::types::evaluator::time::*;
35+
use crate::types::evaluator::time64::*;
3436
use crate::types::evaluator::tuple::{
3537
TupleEqBinaryEvaluator, TupleGtBinaryEvaluator, TupleGtEqBinaryEvaluator,
3638
TupleLtBinaryEvaluator, TupleLtEqBinaryEvaluator, TupleNotEqBinaryEvaluator,
@@ -191,7 +193,32 @@ impl EvaluatorFactory {
191193
LogicalType::Double => numeric_binary_evaluator!(Float64, op, LogicalType::Double),
192194
LogicalType::Date => numeric_binary_evaluator!(Date, op, LogicalType::Date),
193195
LogicalType::DateTime => numeric_binary_evaluator!(DateTime, op, LogicalType::DateTime),
194-
LogicalType::Time => numeric_binary_evaluator!(Time, op, LogicalType::Time),
196+
LogicalType::Time(_, _) => match op {
197+
BinaryOperator::Plus => Ok(BinaryEvaluatorBox(Arc::new(TimePlusBinaryEvaluator))),
198+
BinaryOperator::Minus => Ok(BinaryEvaluatorBox(Arc::new(TimeMinusBinaryEvaluator))),
199+
BinaryOperator::Gt => Ok(BinaryEvaluatorBox(Arc::new(TimeGtBinaryEvaluator))),
200+
BinaryOperator::GtEq => Ok(BinaryEvaluatorBox(Arc::new(TimeGtEqBinaryEvaluator))),
201+
BinaryOperator::Lt => Ok(BinaryEvaluatorBox(Arc::new(TimeLtBinaryEvaluator))),
202+
BinaryOperator::LtEq => Ok(BinaryEvaluatorBox(Arc::new(TimeLtEqBinaryEvaluator))),
203+
BinaryOperator::Eq => Ok(BinaryEvaluatorBox(Arc::new(TimeEqBinaryEvaluator))),
204+
BinaryOperator::NotEq => Ok(BinaryEvaluatorBox(Arc::new(TimeNotEqBinaryEvaluator))),
205+
_ => Err(DatabaseError::UnsupportedBinaryOperator(ty, op)),
206+
},
207+
LogicalType::TimeStamp(_, _) => match op {
208+
BinaryOperator::Plus => Ok(BinaryEvaluatorBox(Arc::new(Time64PlusBinaryEvaluator))),
209+
BinaryOperator::Minus => {
210+
Ok(BinaryEvaluatorBox(Arc::new(Time64MinusBinaryEvaluator)))
211+
}
212+
BinaryOperator::Gt => Ok(BinaryEvaluatorBox(Arc::new(Time64GtBinaryEvaluator))),
213+
BinaryOperator::GtEq => Ok(BinaryEvaluatorBox(Arc::new(Time64GtEqBinaryEvaluator))),
214+
BinaryOperator::Lt => Ok(BinaryEvaluatorBox(Arc::new(Time64LtBinaryEvaluator))),
215+
BinaryOperator::LtEq => Ok(BinaryEvaluatorBox(Arc::new(Time64LtEqBinaryEvaluator))),
216+
BinaryOperator::Eq => Ok(BinaryEvaluatorBox(Arc::new(Time64EqBinaryEvaluator))),
217+
BinaryOperator::NotEq => {
218+
Ok(BinaryEvaluatorBox(Arc::new(Time64NotEqBinaryEvaluator)))
219+
}
220+
_ => Err(DatabaseError::UnsupportedBinaryOperator(ty, op)),
221+
},
195222
LogicalType::Decimal(_, _) => numeric_binary_evaluator!(Decimal, op, ty),
196223
LogicalType::Boolean => match op {
197224
BinaryOperator::And => Ok(BinaryEvaluatorBox(Arc::new(BooleanAndBinaryEvaluator))),

src/types/evaluator/time.rs

Lines changed: 205 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,210 @@
1-
use crate::numeric_binary_evaluator_definition;
21
use crate::types::evaluator::BinaryEvaluator;
32
use crate::types::evaluator::DataValue;
4-
use paste::paste;
53
use serde::{Deserialize, Serialize};
64
use std::hint;
75

8-
numeric_binary_evaluator_definition!(Time, DataValue::Time);
6+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
7+
pub struct TimePlusBinaryEvaluator;
8+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
9+
pub struct TimeMinusBinaryEvaluator;
10+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
11+
pub struct TimeGtBinaryEvaluator;
12+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
13+
pub struct TimeGtEqBinaryEvaluator;
14+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
15+
pub struct TimeLtBinaryEvaluator;
16+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
17+
pub struct TimeLtEqBinaryEvaluator;
18+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
19+
pub struct TimeEqBinaryEvaluator;
20+
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
21+
pub struct TimeNotEqBinaryEvaluator;
22+
23+
#[typetag::serde]
24+
impl BinaryEvaluator for TimePlusBinaryEvaluator {
25+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
26+
match (left, right) {
27+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
28+
let (mut v1, n1) = DataValue::unpack(*v1, *p1);
29+
let (v2, n2) = DataValue::unpack(*v2, *p2);
30+
let mut n = n1 + n2;
31+
while n > 1_000_000_000 {
32+
v1 += 1;
33+
n -= 1_000_000_000;
34+
}
35+
let p = if p2 > p1 { *p2 } else { *p1 };
36+
if v1 + v2 > 86400 {
37+
return DataValue::Null;
38+
}
39+
DataValue::Time(DataValue::pack(v1 + v2, n, p), p, false)
40+
}
41+
(DataValue::Time(..), DataValue::Null)
42+
| (DataValue::Null, DataValue::Time(..))
43+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
44+
_ => unsafe { hint::unreachable_unchecked() },
45+
}
46+
}
47+
}
48+
#[typetag::serde]
49+
impl BinaryEvaluator for TimeMinusBinaryEvaluator {
50+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
51+
match (left, right) {
52+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
53+
let (mut v1, mut n1) = DataValue::unpack(*v1, *p1);
54+
let (v2, n2) = DataValue::unpack(*v2, *p2);
55+
while n1 < n2 {
56+
v1 -= 1;
57+
n1 += 1_000_000_000;
58+
}
59+
if v1 < v2 {
60+
return DataValue::Null;
61+
}
62+
let p = if p2 > p1 { *p2 } else { *p1 };
63+
DataValue::Time(DataValue::pack(v1 - v2, n1 - n2, p), p, false)
64+
}
65+
(DataValue::Time(..), DataValue::Null)
66+
| (DataValue::Null, DataValue::Time(..))
67+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
68+
_ => unsafe { hint::unreachable_unchecked() },
69+
}
70+
}
71+
}
72+
73+
#[typetag::serde]
74+
impl BinaryEvaluator for TimeGtBinaryEvaluator {
75+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
76+
match (left, right) {
77+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
78+
let (v1, n1) = DataValue::unpack(*v1, *p1);
79+
let (v2, n2) = DataValue::unpack(*v2, *p2);
80+
match v1 > v2 {
81+
true => DataValue::Boolean(true),
82+
false => match v1 < v2 {
83+
true => DataValue::Boolean(false),
84+
false => match n1 > n2 {
85+
true => DataValue::Boolean(true),
86+
false => DataValue::Boolean(false),
87+
},
88+
},
89+
}
90+
}
91+
(DataValue::Time(..), DataValue::Null)
92+
| (DataValue::Null, DataValue::Time(..))
93+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
94+
_ => unsafe { hint::unreachable_unchecked() },
95+
}
96+
}
97+
}
98+
#[typetag::serde]
99+
impl BinaryEvaluator for TimeGtEqBinaryEvaluator {
100+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
101+
match (left, right) {
102+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
103+
let (v1, n1) = DataValue::unpack(*v1, *p1);
104+
let (v2, n2) = DataValue::unpack(*v2, *p2);
105+
match v1 > v2 {
106+
true => DataValue::Boolean(true),
107+
false => match v1 < v2 {
108+
true => DataValue::Boolean(false),
109+
false => match n1 >= n2 {
110+
true => DataValue::Boolean(true),
111+
false => DataValue::Boolean(false),
112+
},
113+
},
114+
}
115+
}
116+
(DataValue::Time(..), DataValue::Null)
117+
| (DataValue::Null, DataValue::Time(..))
118+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
119+
_ => unsafe { hint::unreachable_unchecked() },
120+
}
121+
}
122+
}
123+
#[typetag::serde]
124+
impl BinaryEvaluator for TimeLtBinaryEvaluator {
125+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
126+
match (left, right) {
127+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
128+
let (v1, n1) = DataValue::unpack(*v1, *p1);
129+
let (v2, n2) = DataValue::unpack(*v2, *p2);
130+
match v1 < v2 {
131+
true => DataValue::Boolean(true),
132+
false => match v1 > v2 {
133+
true => DataValue::Boolean(false),
134+
false => match n1 < n2 {
135+
true => DataValue::Boolean(true),
136+
false => DataValue::Boolean(false),
137+
},
138+
},
139+
}
140+
}
141+
(DataValue::Time(..), DataValue::Null)
142+
| (DataValue::Null, DataValue::Time(..))
143+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
144+
_ => unsafe { hint::unreachable_unchecked() },
145+
}
146+
}
147+
}
148+
#[typetag::serde]
149+
impl BinaryEvaluator for TimeLtEqBinaryEvaluator {
150+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
151+
match (left, right) {
152+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
153+
let (v1, n1) = DataValue::unpack(*v1, *p1);
154+
let (v2, n2) = DataValue::unpack(*v2, *p2);
155+
match v1 < v2 {
156+
true => DataValue::Boolean(true),
157+
false => match v1 > v2 {
158+
true => DataValue::Boolean(false),
159+
false => match n1 <= n2 {
160+
true => DataValue::Boolean(true),
161+
false => DataValue::Boolean(false),
162+
},
163+
},
164+
}
165+
}
166+
(DataValue::Time(..), DataValue::Null)
167+
| (DataValue::Null, DataValue::Time(..))
168+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
169+
_ => unsafe { hint::unreachable_unchecked() },
170+
}
171+
}
172+
}
173+
#[typetag::serde]
174+
impl BinaryEvaluator for TimeEqBinaryEvaluator {
175+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
176+
match (left, right) {
177+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
178+
let (v1, n1) = DataValue::unpack(*v1, *p1);
179+
let (v2, n2) = DataValue::unpack(*v2, *p2);
180+
match (v1 == v2, n1 == n2) {
181+
(true, true) => DataValue::Boolean(true),
182+
_ => DataValue::Boolean(false),
183+
}
184+
}
185+
(DataValue::Time(..), DataValue::Null)
186+
| (DataValue::Null, DataValue::Time(..))
187+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
188+
_ => unsafe { hint::unreachable_unchecked() },
189+
}
190+
}
191+
}
192+
#[typetag::serde]
193+
impl BinaryEvaluator for TimeNotEqBinaryEvaluator {
194+
fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue {
195+
match (left, right) {
196+
(DataValue::Time(v1, p1, _), DataValue::Time(v2, p2, ..)) => {
197+
let (v1, n1) = DataValue::unpack(*v1, *p1);
198+
let (v2, n2) = DataValue::unpack(*v2, *p2);
199+
match (v1 != v2, n1 != n2) {
200+
(false, false) => DataValue::Boolean(false),
201+
_ => DataValue::Boolean(true),
202+
}
203+
}
204+
(DataValue::Time(..), DataValue::Null)
205+
| (DataValue::Null, DataValue::Time(..))
206+
| (DataValue::Null, DataValue::Null) => DataValue::Null,
207+
_ => unsafe { hint::unreachable_unchecked() },
208+
}
209+
}
210+
}

0 commit comments

Comments
 (0)