Skip to content

Commit e666e08

Browse files
0b01wangfenjin
andauthored
Add timestamp wrapper type (#105)
* Add timestamp wrapper type * fix build * Fix tests * Address comments * cargo fmt * add query by duration Change-Id: Ia1df252ab09ec93680d9f1e6a3dba196c6dfe478 Co-authored-by: wangfenjin <[email protected]>
1 parent d2f611f commit e666e08

File tree

3 files changed

+50
-6
lines changed

3 files changed

+50
-6
lines changed

src/appender.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::iter::IntoIterator;
66
use std::os::raw::c_char;
77

88
use crate::error::result_from_duckdb_appender;
9-
use crate::types::{ToSql, ToSqlOutput};
9+
use crate::types::{TimeUnit, ToSql, ToSqlOutput};
1010
use crate::Error;
1111

1212
/// Appender for fast import data
@@ -108,6 +108,15 @@ impl Appender<'_> {
108108
ValueRef::Text(s) => unsafe {
109109
ffi::duckdb_append_varchar_length(ptr, s.as_ptr() as *const c_char, s.len() as u64)
110110
},
111+
ValueRef::Timestamp(u, i) => unsafe {
112+
let micros = match u {
113+
TimeUnit::Second => i * 1_000_000,
114+
TimeUnit::Millisecond => i * 1_000,
115+
TimeUnit::Microsecond => i,
116+
TimeUnit::Nanosecond => i / 1_000,
117+
};
118+
ffi::duckdb_append_timestamp(ptr, ffi::duckdb_timestamp { micros })
119+
},
111120
ValueRef::Blob(b) => unsafe { ffi::duckdb_append_blob(ptr, b.as_ptr() as *const c_void, b.len() as u64) },
112121
_ => unreachable!("not supported"),
113122
};
@@ -215,8 +224,25 @@ mod test {
215224
app.append_row(["2022-04-09 15:56:37.544"])?;
216225
}
217226

218-
let val = db.query_row("SELECT x FROM foo", [], |row| <(String,)>::try_from(row))?;
219-
assert_eq!(val, ("2022-04-09 15:56:37.544".to_string(),));
227+
let val = db.query_row("SELECT x FROM foo", [], |row| <(i64,)>::try_from(row))?;
228+
assert_eq!(val, (1649519797544000,));
229+
Ok(())
230+
}
231+
232+
#[test]
233+
fn test_append_timestamp() -> Result<()> {
234+
use std::time::Duration;
235+
let db = Connection::open_in_memory()?;
236+
db.execute_batch("CREATE TABLE foo(x TIMESTAMP)")?;
237+
238+
let d = Duration::from_secs(1);
239+
{
240+
let mut app = db.appender("foo")?;
241+
app.append_row([d])?;
242+
}
243+
244+
let val = db.query_row("SELECT x FROM foo where x=?", [d], |row| <(i32,)>::try_from(row))?;
245+
assert_eq!(val, (d.as_micros() as i32,));
220246
Ok(())
221247
}
222248
}

src/statement.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::ffi;
77
use super::{AndThenRows, Connection, Error, MappedRows, Params, RawStatement, Result, Row, Rows, ValueRef};
88
use crate::arrow_batch::Arrow;
99
use crate::error::result_from_duckdb_prepare;
10-
use crate::types::{ToSql, ToSqlOutput};
10+
use crate::types::{TimeUnit, ToSql, ToSqlOutput};
1111

1212
use arrow::array::StructArray;
1313
use arrow::datatypes::DataType;
@@ -434,7 +434,16 @@ impl Statement<'_> {
434434
ValueRef::Blob(b) => unsafe {
435435
ffi::duckdb_bind_blob(ptr, col as u64, b.as_ptr() as *const c_void, b.len() as u64)
436436
},
437-
_ => unreachable!("not supported"),
437+
ValueRef::Timestamp(u, i) => unsafe {
438+
let micros = match u {
439+
TimeUnit::Second => i * 1_000_000,
440+
TimeUnit::Millisecond => i * 1_000,
441+
TimeUnit::Microsecond => i,
442+
TimeUnit::Nanosecond => i / 1_000,
443+
};
444+
ffi::duckdb_bind_timestamp(ptr, col as u64, ffi::duckdb_timestamp { micros })
445+
},
446+
_ => unreachable!("not supported: {}", value.data_type()),
438447
};
439448
result_from_duckdb_prepare(rc, ptr)
440449
}

src/types/to_sql.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Null, Value, ValueRef};
1+
use super::{Null, TimeUnit, Value, ValueRef};
22
use crate::Result;
33
use std::borrow::Cow;
44

@@ -202,6 +202,15 @@ impl<T: ToSql> ToSql for Option<T> {
202202
}
203203
}
204204

205+
impl ToSql for std::time::Duration {
206+
fn to_sql(&self) -> crate::Result<ToSqlOutput<'_>> {
207+
Ok(ToSqlOutput::Owned(Value::Timestamp(
208+
TimeUnit::Microsecond,
209+
self.as_micros() as i64,
210+
)))
211+
}
212+
}
213+
205214
#[cfg(test)]
206215
mod test {
207216
use super::ToSql;

0 commit comments

Comments
 (0)