mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 00:39:20 +08:00
Add ToSql/FromSql for time::Timespec.
Uses SQLite's default format string for `datetime()`.
This commit is contained in:
parent
1fa4c2098e
commit
c8af7e4eb5
37
src/types.rs
37
src/types.rs
@ -1,3 +1,5 @@
|
|||||||
|
extern crate time;
|
||||||
|
|
||||||
use libc::{c_int, c_double};
|
use libc::{c_int, c_double};
|
||||||
use std::c_str::{CString};
|
use std::c_str::{CString};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -5,6 +7,8 @@ use std::vec;
|
|||||||
use super::ffi;
|
use super::ffi;
|
||||||
use super::{SqliteResult, SqliteError};
|
use super::{SqliteResult, SqliteError};
|
||||||
|
|
||||||
|
const SQLITE_DATETIME_FMT: &'static str = "%Y-%m-%d %H:%M:%S";
|
||||||
|
|
||||||
pub trait ToSql {
|
pub trait ToSql {
|
||||||
unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int;
|
unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int;
|
||||||
}
|
}
|
||||||
@ -55,6 +59,13 @@ impl ToSql for Vec<u8> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToSql for time::Timespec {
|
||||||
|
unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int {
|
||||||
|
let time_str = time::at_utc(*self).strftime(SQLITE_DATETIME_FMT).unwrap();
|
||||||
|
time_str.bind_parameter(stmt, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ToSql> ToSql for Option<T> {
|
impl<T: ToSql> ToSql for Option<T> {
|
||||||
unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int {
|
unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int {
|
||||||
match *self {
|
match *self {
|
||||||
@ -112,6 +123,20 @@ impl FromSql for Vec<u8> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromSql for time::Timespec {
|
||||||
|
unsafe fn column_result(stmt: *mut ffi::sqlite3_stmt,
|
||||||
|
col: c_int) -> SqliteResult<time::Timespec> {
|
||||||
|
let col_str = FromSql::column_result(stmt, col);
|
||||||
|
col_str.and_then(|txt: String| {
|
||||||
|
time::strptime(txt.as_slice(), SQLITE_DATETIME_FMT).map(|tm| {
|
||||||
|
tm.to_timespec()
|
||||||
|
}).map_err(|parse_error| {
|
||||||
|
SqliteError{ code: ffi::SQLITE_MISMATCH, message: format!("{}", parse_error) }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: FromSql> FromSql for Option<T> {
|
impl<T: FromSql> FromSql for Option<T> {
|
||||||
unsafe fn column_result(stmt: *mut ffi::sqlite3_stmt, col: c_int) -> SqliteResult<Option<T>> {
|
unsafe fn column_result(stmt: *mut ffi::sqlite3_stmt, col: c_int) -> SqliteResult<Option<T>> {
|
||||||
if ffi::sqlite3_column_type(stmt, col) == ffi::SQLITE_NULL {
|
if ffi::sqlite3_column_type(stmt, col) == ffi::SQLITE_NULL {
|
||||||
@ -125,6 +150,7 @@ impl<T: FromSql> FromSql for Option<T> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use SqliteConnection;
|
use SqliteConnection;
|
||||||
|
use super::time;
|
||||||
|
|
||||||
fn checked_memory_handle() -> SqliteConnection {
|
fn checked_memory_handle() -> SqliteConnection {
|
||||||
let db = SqliteConnection::open(":memory:").unwrap();
|
let db = SqliteConnection::open(":memory:").unwrap();
|
||||||
@ -154,6 +180,17 @@ mod test {
|
|||||||
assert_eq!(from.as_slice(), s);
|
assert_eq!(from.as_slice(), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_timespec() {
|
||||||
|
let db = checked_memory_handle();
|
||||||
|
|
||||||
|
let ts = time::Timespec{sec: 10_000, nsec: 0 };
|
||||||
|
db.execute("INSERT INTO foo(t) VALUES (?)", &[&ts]).unwrap();
|
||||||
|
|
||||||
|
let from: time::Timespec = db.query_row("SELECT t FROM foo", [], |r| r.unwrap().get(0));
|
||||||
|
assert_eq!(from, ts);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_option() {
|
fn test_option() {
|
||||||
let db = checked_memory_handle();
|
let db = checked_memory_handle();
|
||||||
|
Loading…
Reference in New Issue
Block a user