mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-02 15:25:32 +00:00
First attempt at roundtripping chrono types through SQLite
This commit is contained in:
parent
7beceba832
commit
7c27065c09
@ -22,6 +22,7 @@ pub(crate) enum DataType {
|
||||
// non-standard extensions
|
||||
Bool,
|
||||
Int64,
|
||||
Timestamp,
|
||||
}
|
||||
|
||||
/// Type information for a SQLite type.
|
||||
@ -47,6 +48,7 @@ impl TypeInfo for SqliteTypeInfo {
|
||||
// non-standard extensions
|
||||
DataType::Bool => "BOOLEAN",
|
||||
DataType::Int64 => "BIGINT",
|
||||
DataType::Timestamp => "TIMESTAMP",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
71
sqlx-core/src/sqlite/types/chrono.rs
Normal file
71
sqlx-core/src/sqlite/types/chrono.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use crate::{
|
||||
decode::Decode,
|
||||
encode::Encode,
|
||||
sqlite::{
|
||||
type_info::{SqliteType, SqliteTypeAffinity},
|
||||
Sqlite, SqliteArgumentValue, SqliteTypeInfo, SqliteValue,
|
||||
},
|
||||
types::Type,
|
||||
Result,
|
||||
};
|
||||
use chrono::NaiveDateTime;
|
||||
|
||||
impl Type<Sqlite> for NaiveDateTime {
|
||||
fn type_info() -> SqliteTypeInfo {
|
||||
SqliteTypeInfo::new(SqliteType::Timestamp, SqliteTypeAffinity::Text)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<Sqlite> for NaiveDateTime {
|
||||
fn encode(&self, buf: &mut Vec<SqliteArgumentValue>) {
|
||||
buf.push(SqliteArgumentValue::Text(
|
||||
self.format("%F %T%.f").to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decode<'a, Sqlite> for NaiveDateTime {
|
||||
fn decode(value: SqliteValue) -> Result<Self> {
|
||||
let the_type = value.r#type();
|
||||
|
||||
match the_type {
|
||||
Some(SqliteType::Text) => return decode_from_text(value.text()),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Err(protocol_err!("Unexpected affinity for data: {:?} in value", the_type).into())
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_from_text(text: Option<&str>) -> Result<NaiveDateTime> {
|
||||
if let Some(raw) = text {
|
||||
// Loop over common date time partterns, inspired by Diesel
|
||||
// https://docs.diesel.rs/src/diesel/sqlite/types/date_and_time/chrono.rs.html#56-97
|
||||
let sqlite_datetime_formats = &[
|
||||
// Most likely format
|
||||
"%F %T%.f",
|
||||
// Other formats in order of appearance in docs
|
||||
"%F %R",
|
||||
"%F %RZ",
|
||||
"%F %R%:z",
|
||||
"%F %T%.fZ",
|
||||
"%F %T%.f%:z",
|
||||
"%FT%R",
|
||||
"%FT%RZ",
|
||||
"%FT%R%:z",
|
||||
"%FT%T%.f",
|
||||
"%FT%T%.fZ",
|
||||
"%FT%T%.f%:z",
|
||||
];
|
||||
|
||||
for format in sqlite_datetime_formats {
|
||||
if let Ok(dt) = NaiveDateTime::parse_from_str(raw, format) {
|
||||
return Ok(dt);
|
||||
}
|
||||
}
|
||||
|
||||
return Err(protocol_err!("Did not find a matching pattern").into());
|
||||
}
|
||||
|
||||
Err(protocol_err!("There was not text value to decode").into())
|
||||
}
|
@ -12,6 +12,19 @@
|
||||
//! | `f64` | REAL |
|
||||
//! | `&str`, `String` | TEXT |
|
||||
//! | `&[u8]`, `Vec<u8>` | BLOB |
|
||||
//!
|
||||
//! ### [`chrono`](https://crates.io/crates/chrono)
|
||||
//!
|
||||
//! Requires the `chrono` Cargo feature flag.
|
||||
//!
|
||||
//! | Rust type | MySQL type(s) |
|
||||
//! |---------------------------------------|------------------------------------------------------|
|
||||
//! | `chrono::DateTime<Utc>` | TIMESTAMP |
|
||||
//! | `chrono::DateTime<Local>` | TIMETAMP |
|
||||
//! | `chrono::NaiveDateTime` | DATETIME |
|
||||
//! | `chrono::NaiveDate` | DATE |
|
||||
//! | `chrono::NaiveTime` | TIME |
|
||||
|
||||
//!
|
||||
//! # Nullable
|
||||
//!
|
||||
@ -21,6 +34,8 @@
|
||||
|
||||
mod bool;
|
||||
mod bytes;
|
||||
#[cfg(feature = "chrono")]
|
||||
mod chrono;
|
||||
mod float;
|
||||
mod int;
|
||||
mod str;
|
||||
|
Loading…
x
Reference in New Issue
Block a user