Skip to content

Commit 11b7c70

Browse files
committed
feat: Support Date type
1 parent 6199b76 commit 11b7c70

File tree

5 files changed

+111
-15
lines changed

5 files changed

+111
-15
lines changed

src/db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ mod test {
268268
println!("{}", create_table(&tuples_time_max));
269269

270270
println!("time where:");
271-
let tuples_time_where_t2 = kipsql.run("select (c + 1) from t2 where e > '2021-05-20 21:00:00'").await?;
271+
let tuples_time_where_t2 = kipsql.run("select (c + 1) from t2 where e > '2021-05-20'").await?;
272272
println!("{}", create_table(&tuples_time_where_t2));
273273

274274
assert!(kipsql.run("select max(d) from t2 group by c").await.is_err());

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub(crate) const BANNER: &str = "
1212
██║ ██╗██║██║ ███████║╚██████╔╝███████╗
1313
╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝ ╚══▀▀═╝ ╚══════╝";
1414

15-
pub const BLOOM: &str ="
15+
pub const BLOOM: &str = "
1616
_ ._ _ , _ ._
1717
(_ ' ( ` )_ .__)
1818
( ( ( ) `) ) _)

src/types/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ pub enum LogicalType {
5555
Float,
5656
Double,
5757
Varchar,
58+
Date,
5859
DateTime,
5960
}
6061

@@ -75,6 +76,7 @@ impl LogicalType {
7576
LogicalType::Float => Some(4),
7677
LogicalType::Double => Some(8),
7778
LogicalType::Varchar => None,
79+
LogicalType::Date => Some(4),
7880
LogicalType::DateTime => Some(8),
7981
}
8082
}
@@ -146,6 +148,12 @@ impl LogicalType {
146148
if left.is_numeric() && right.is_numeric() {
147149
return LogicalType::combine_numeric_types(left, right);
148150
}
151+
if matches!((left, right), (LogicalType::Date, LogicalType::Varchar) | (LogicalType::Varchar, LogicalType::Date)) {
152+
return Ok(LogicalType::Date);
153+
}
154+
if matches!((left, right), (LogicalType::Date, LogicalType::DateTime) | (LogicalType::DateTime, LogicalType::Date)) {
155+
return Ok(LogicalType::DateTime);
156+
}
149157
if matches!((left, right), (LogicalType::DateTime, LogicalType::Varchar) | (LogicalType::Varchar, LogicalType::DateTime)) {
150158
return Ok(LogicalType::DateTime);
151159
}
@@ -250,7 +258,8 @@ impl LogicalType {
250258
LogicalType::Float => matches!(to, LogicalType::Double),
251259
LogicalType::Double => false,
252260
LogicalType::Varchar => false,
253-
LogicalType::DateTime => false,
261+
LogicalType::Date => matches!(to, LogicalType::DateTime | LogicalType::Varchar),
262+
LogicalType::DateTime => matches!(to, LogicalType::Date | LogicalType::Varchar),
254263
}
255264
}
256265
}

src/types/tuple.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ mod tests {
170170
false,
171171
ColumnDesc::new(LogicalType::DateTime, false)
172172
)),
173+
Arc::new(ColumnCatalog::new(
174+
"c12".to_string(),
175+
false,
176+
ColumnDesc::new(LogicalType::Date, false)
177+
)),
173178
];
174179

175180
let tuples = vec![
@@ -187,7 +192,8 @@ mod tests {
187192
Arc::new(DataValue::Int8(Some(1))),
188193
Arc::new(DataValue::UInt8(Some(1))),
189194
Arc::new(DataValue::Boolean(Some(true))),
190-
Arc::new(DataValue::Date64(Some(0)))
195+
Arc::new(DataValue::Date64(Some(0))),
196+
Arc::new(DataValue::Date32(Some(0))),
191197
]
192198
},
193199
Tuple {
@@ -204,7 +210,8 @@ mod tests {
204210
Arc::new(DataValue::Int8(None)),
205211
Arc::new(DataValue::UInt8(None)),
206212
Arc::new(DataValue::Boolean(None)),
207-
Arc::new(DataValue::Date64(None))
213+
Arc::new(DataValue::Date64(None)),
214+
Arc::new(DataValue::Date32(None))
208215
],
209216
}
210217
];

src/types/value.rs

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ use std::fmt::Formatter;
44
use std::hash::Hash;
55
use std::str::FromStr;
66
use std::sync::Arc;
7-
use chrono::{Duration, NaiveDateTime, Utc, TimeZone};
7+
use chrono::{NaiveDateTime, Datelike, NaiveDate};
8+
use chrono::format::{DelayedFormat, StrftimeItems};
89
use integer_encoding::FixedInt;
910
use lazy_static::lazy_static;
1011

1112
use ordered_float::OrderedFloat;
13+
use crate::types::errors::TypeError;
1214

1315
use super::LogicalType;
1416

@@ -18,6 +20,9 @@ lazy_static! {
1820
};
1921
}
2022

23+
pub const DATE_FMT: &str = "%Y-%m-%d";
24+
pub const DATE_TIME_FMT: &str = "%Y-%m-%d %H:%M:%S";
25+
2126
pub type ValueRef = Arc<DataValue>;
2227

2328
#[derive(Clone)]
@@ -35,7 +40,9 @@ pub enum DataValue {
3540
UInt32(Option<u32>),
3641
UInt64(Option<u64>),
3742
Utf8(Option<String>),
38-
/// Date stored as a unsigned 64bit int days since UNIX epoch 1970-01-01
43+
/// Date stored as a signed 32bit int days since UNIX epoch 1970-01-01
44+
Date32(Option<i32>),
45+
/// Date stored as a signed 64bit int timestamp since UNIX epoch 1970-01-01
3946
Date64(Option<i64>),
4047
}
4148

@@ -77,6 +84,8 @@ impl PartialEq for DataValue {
7784
(Utf8(_), _) => false,
7885
(Null, Null) => true,
7986
(Null, _) => false,
87+
(Date32(v1), Date32(v2)) => v1.eq(v2),
88+
(Date32(_), _) => false,
8089
(Date64(v1), Date64(v2)) => v1.eq(v2),
8190
(Date64(_), _) => false,
8291
}
@@ -121,6 +130,8 @@ impl PartialOrd for DataValue {
121130
(Utf8(_), _) => None,
122131
(Null, Null) => Some(Ordering::Equal),
123132
(Null, _) => None,
133+
(Date32(v1), Date32(v2)) => v1.partial_cmp(v2),
134+
(Date32(_), _) => None,
124135
(Date64(v1), Date64(v2)) => v1.partial_cmp(v2),
125136
(Date64(_), _) => None,
126137
}
@@ -152,6 +163,7 @@ impl Hash for DataValue {
152163
UInt64(v) => v.hash(state),
153164
Utf8(v) => v.hash(state),
154165
Null => 1.hash(state),
166+
Date32(v) => v.hash(state),
155167
Date64(v) => v.hash(state),
156168
}
157169
}
@@ -180,6 +192,7 @@ impl DataValue {
180192
DataValue::UInt32(value) => value.is_none(),
181193
DataValue::UInt64(value) => value.is_none(),
182194
DataValue::Utf8(value) => value.is_none(),
195+
DataValue::Date32(value) => value.is_none(),
183196
DataValue::Date64(value) => value.is_none(),
184197
}
185198
}
@@ -200,6 +213,7 @@ impl DataValue {
200213
LogicalType::Float => DataValue::Float32(None),
201214
LogicalType::Double => DataValue::Float64(None),
202215
LogicalType::Varchar => DataValue::Utf8(None),
216+
LogicalType::Date => DataValue::Date32(None),
203217
LogicalType::DateTime => DataValue::Date64(None)
204218
}
205219
}
@@ -220,6 +234,7 @@ impl DataValue {
220234
LogicalType::Float => DataValue::Float32(Some(0.0)),
221235
LogicalType::Double => DataValue::Float64(Some(0.0)),
222236
LogicalType::Varchar => DataValue::Utf8(Some("".to_string())),
237+
LogicalType::Date => DataValue::Date32(Some(UNIX_DATETIME.num_days_from_ce())),
223238
LogicalType::DateTime => DataValue::Date64(Some(UNIX_DATETIME.timestamp()))
224239
}
225240
}
@@ -239,6 +254,7 @@ impl DataValue {
239254
DataValue::UInt32(v) => v.map(|v| v.encode_fixed_vec()),
240255
DataValue::UInt64(v) => v.map(|v| v.encode_fixed_vec()),
241256
DataValue::Utf8(v) => v.clone().map(|v| v.into_bytes()),
257+
DataValue::Date32(v) => v.map(|v| v.encode_fixed_vec()),
242258
DataValue::Date64(v) => v.map(|v| v.encode_fixed_vec()),
243259
}.unwrap_or(vec![])
244260
}
@@ -267,6 +283,7 @@ impl DataValue {
267283
f64::from_ne_bytes(buf)
268284
})),
269285
LogicalType::Varchar => DataValue::Utf8((!bytes.is_empty()).then(|| String::from_utf8(bytes.to_owned()).unwrap())),
286+
LogicalType::Date => DataValue::Date32((!bytes.is_empty()).then(|| i32::decode_fixed(bytes))),
270287
LogicalType::DateTime => DataValue::Date64((!bytes.is_empty()).then(|| i64::decode_fixed(bytes))),
271288
}
272289
}
@@ -286,6 +303,7 @@ impl DataValue {
286303
DataValue::UInt32(_) => LogicalType::UInteger,
287304
DataValue::UInt64(_) => LogicalType::UBigint,
288305
DataValue::Utf8(_) => LogicalType::Varchar,
306+
DataValue::Date32(_) => LogicalType::Date,
289307
DataValue::Date64(_) => LogicalType::DateTime,
290308
}
291309
}
@@ -308,6 +326,7 @@ impl DataValue {
308326
LogicalType::Float => DataValue::Float32(None),
309327
LogicalType::Double => DataValue::Float64(None),
310328
LogicalType::Varchar => DataValue::Utf8(None),
329+
LogicalType::Date => DataValue::Date32(None),
311330
LogicalType::DateTime => DataValue::Date64(None),
312331
}
313332
}
@@ -327,7 +346,7 @@ impl DataValue {
327346
LogicalType::Float => DataValue::Float32(value.map(|v| v.into())),
328347
LogicalType::Double => DataValue::Float64(value.map(|v| v.into())),
329348
LogicalType::Varchar => DataValue::Utf8(value.map(|v| format!("{}", v))),
330-
LogicalType::DateTime => panic!("not support"),
349+
_ => panic!("not support"),
331350
}
332351
}
333352
DataValue::Float32(value) => {
@@ -481,9 +500,24 @@ impl DataValue {
481500
LogicalType::Float => DataValue::Float32(value.map(|v| f32::from_str(&v).unwrap())),
482501
LogicalType::Double => DataValue::Float64(value.map(|v| f64::from_str(&v).unwrap())),
483502
LogicalType::Varchar => DataValue::Utf8(value),
503+
LogicalType::Date => {
504+
let option = value.map(|v| {
505+
NaiveDate::parse_from_str(&v, DATE_FMT)
506+
.unwrap()
507+
.num_days_from_ce()
508+
});
509+
510+
DataValue::Date32(option)
511+
}
484512
LogicalType::DateTime => {
485513
let option = value.map(|v| {
486-
NaiveDateTime::parse_from_str(&v, "%Y-%m-%d %H:%M:%S")
514+
NaiveDateTime::parse_from_str(&v, DATE_TIME_FMT)
515+
.or_else(|_| {
516+
NaiveDate::parse_from_str(&v, DATE_FMT)
517+
.unwrap()
518+
.and_hms_opt(0, 0 ,0)
519+
.ok_or_else(|| TypeError::InternalError("wrong format".to_string()))
520+
})
487521
.unwrap()
488522
.timestamp()
489523
});
@@ -492,17 +526,63 @@ impl DataValue {
492526
}
493527
}
494528
}
529+
DataValue::Date32(value) => {
530+
match to {
531+
LogicalType::Invalid => panic!("invalid logical type"),
532+
LogicalType::SqlNull => DataValue::Null,
533+
LogicalType::Varchar => DataValue::Utf8(value.map(|v| {
534+
format!("{}", Self::date_format(v))
535+
})),
536+
LogicalType::Date => DataValue::Date32(value),
537+
LogicalType::DateTime => {
538+
let option = value.map(|v| {
539+
NaiveDate::from_num_days_from_ce_opt(v)
540+
.unwrap()
541+
.and_hms_opt(0, 0, 0)
542+
.unwrap()
543+
.timestamp()
544+
});
545+
546+
DataValue::Date64(option)
547+
},
548+
_ => panic!("not support"),
549+
}
550+
}
495551
DataValue::Date64(value) => {
496552
match to {
497553
LogicalType::Invalid => panic!("invalid logical type"),
498554
LogicalType::SqlNull => DataValue::Null,
499-
LogicalType::Varchar => DataValue::Utf8(value.map(|v| format!("{}", v))),
555+
LogicalType::Varchar => DataValue::Utf8(value.map(|v| {
556+
format!("{}", Self::date_time_format(v))
557+
})),
558+
LogicalType::Date => {
559+
let option = value.map(|v| {
560+
NaiveDateTime::from_timestamp_opt(v, 0)
561+
.unwrap()
562+
.date()
563+
.num_days_from_ce()
564+
});
565+
566+
DataValue::Date32(option)
567+
}
500568
LogicalType::DateTime => DataValue::Date64(value),
501569
_ => panic!("not support"),
502570
}
503571
}
504572
}
505573
}
574+
575+
fn date_format<'a>(v: i32) -> DelayedFormat<StrftimeItems<'a>> {
576+
NaiveDate::from_num_days_from_ce_opt(v)
577+
.unwrap()
578+
.format(DATE_FMT)
579+
}
580+
581+
fn date_time_format<'a>(v: i64) -> DelayedFormat<StrftimeItems<'a>> {
582+
NaiveDateTime::from_timestamp_opt(v, 0)
583+
.unwrap()
584+
.format(DATE_TIME_FMT)
585+
}
506586
}
507587

508588
macro_rules! impl_scalar {
@@ -585,12 +665,11 @@ impl fmt::Display for DataValue {
585665
DataValue::UInt64(e) => format_option!(f, e)?,
586666
DataValue::Utf8(e) => format_option!(f, e)?,
587667
DataValue::Null => write!(f, "null")?,
668+
DataValue::Date32(e) => {
669+
format_option!(f, e.map(|s| DataValue::date_format(s)))?
670+
}
588671
DataValue::Date64(e) => {
589-
format_option!(f, e.map(|s| {
590-
let datetime_utc = Utc.from_utc_datetime(&UNIX_DATETIME);
591-
592-
datetime_utc + Duration::seconds(s)
593-
}))?
672+
format_option!(f, e.map(|s| DataValue::date_time_format(s)))?
594673
},
595674
};
596675
Ok(())
@@ -614,6 +693,7 @@ impl fmt::Debug for DataValue {
614693
DataValue::Utf8(None) => write!(f, "Utf8({})", self),
615694
DataValue::Utf8(Some(_)) => write!(f, "Utf8(\"{}\")", self),
616695
DataValue::Null => write!(f, "null"),
696+
DataValue::Date32(_) => write!(f, "Date32({})", self),
617697
DataValue::Date64(_) => write!(f, "Date64({})", self),
618698
}
619699
}

0 commit comments

Comments
 (0)