mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
refactor: split up postgres chrono/time modules
This commit is contained in:
parent
e413cd6b0b
commit
e285f0858f
51
sqlx-core/src/postgres/types/chrono/date.rs
Normal file
51
sqlx-core/src/postgres/types/chrono/date.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||
use crate::types::Type;
|
||||
use chrono::{Duration, NaiveDate};
|
||||
use std::mem;
|
||||
|
||||
impl Type<Postgres> for NaiveDate {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [NaiveDate] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<NaiveDate> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[NaiveDate] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for NaiveDate {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days = (*self - NaiveDate::from_ymd(2000, 1, 1)).num_days() as i32;
|
||||
Encode::<Postgres>::encode(&days, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<i32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for NaiveDate {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days: i32 = Decode::<Postgres>::decode(value)?;
|
||||
NaiveDate::from_ymd(2000, 1, 1) + Duration::days(days.into())
|
||||
}
|
||||
|
||||
PgValueFormat::Text => NaiveDate::parse_from_str(value.as_str()?, "%Y-%m-%d")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,10 @@
|
||||
use std::mem;
|
||||
|
||||
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
|
||||
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||
use crate::types::Type;
|
||||
|
||||
impl Type<Postgres> for NaiveTime {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for NaiveDate {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE
|
||||
}
|
||||
}
|
||||
use chrono::{DateTime, Duration, Local, NaiveDate, NaiveDateTime, TimeZone, Utc};
|
||||
use std::mem;
|
||||
|
||||
impl Type<Postgres> for NaiveDateTime {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
@ -32,18 +18,6 @@ impl<Tz: TimeZone> Type<Postgres> for DateTime<Tz> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [NaiveTime] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [NaiveDate] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [NaiveDateTime] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIMESTAMP_ARRAY
|
||||
@ -56,18 +30,6 @@ impl<Tz: TimeZone> Type<Postgres> for [DateTime<Tz>] {
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<NaiveTime> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[NaiveTime] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<NaiveDate> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[NaiveDate] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<NaiveDateTime> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[NaiveDateTime] as Type<Postgres>>::type_info()
|
||||
@ -80,61 +42,6 @@ impl<Tz: TimeZone> Type<Postgres> for Vec<DateTime<Tz>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for NaiveTime {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
// NOTE: panic! is on overflow and 1 day does not have enough micros to overflow
|
||||
let us = (*self - NaiveTime::from_hms(0, 0, 0))
|
||||
.num_microseconds()
|
||||
.unwrap();
|
||||
Encode::<Postgres>::encode(&us, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<u64>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for NaiveTime {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
let us: i64 = Decode::<Postgres>::decode(value)?;
|
||||
NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(us)
|
||||
}
|
||||
|
||||
PgValueFormat::Text => NaiveTime::parse_from_str(value.as_str()?, "%H:%M:%S%.f")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for NaiveDate {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days = (*self - NaiveDate::from_ymd(2000, 1, 1)).num_days() as i32;
|
||||
Encode::<Postgres>::encode(&days, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<i32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for NaiveDate {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days: i32 = Decode::<Postgres>::decode(value)?;
|
||||
NaiveDate::from_ymd(2000, 1, 1) + Duration::days(days.into())
|
||||
}
|
||||
|
||||
PgValueFormat::Text => NaiveDate::parse_from_str(value.as_str()?, "%Y-%m-%d")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for NaiveDateTime {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// FIXME: We should *really* be returning an error, Encode needs to be fallible
|
||||
@ -143,6 +50,7 @@ impl Encode<'_, Postgres> for NaiveDateTime {
|
||||
let us = (*self - epoch)
|
||||
.num_microseconds()
|
||||
.unwrap_or_else(|| panic!("NaiveDateTime out of range for Postgres: {:?}", self));
|
||||
|
||||
Encode::<Postgres>::encode(&us, buf)
|
||||
}
|
||||
|
||||
3
sqlx-core/src/postgres/types/chrono/mod.rs
Normal file
3
sqlx-core/src/postgres/types/chrono/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
mod date;
|
||||
mod datetime;
|
||||
mod time;
|
||||
55
sqlx-core/src/postgres/types/chrono/time.rs
Normal file
55
sqlx-core/src/postgres/types/chrono/time.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||
use crate::types::Type;
|
||||
use chrono::{Duration, NaiveTime};
|
||||
use std::mem;
|
||||
|
||||
impl Type<Postgres> for NaiveTime {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [NaiveTime] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<NaiveTime> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[NaiveTime] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for NaiveTime {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
// NOTE: panic! is on overflow and 1 day does not have enough micros to overflow
|
||||
let us = (*self - NaiveTime::from_hms(0, 0, 0))
|
||||
.num_microseconds()
|
||||
.unwrap();
|
||||
|
||||
Encode::<Postgres>::encode(&us, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<u64>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for NaiveTime {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
let us: i64 = Decode::<Postgres>::decode(value)?;
|
||||
NaiveTime::from_hms(0, 0, 0) + Duration::microseconds(us)
|
||||
}
|
||||
|
||||
PgValueFormat::Text => NaiveTime::parse_from_str(value.as_str()?, "%H:%M:%S%.f")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@
|
||||
//! | Rust type | Postgres type(s) |
|
||||
//! |---------------------------------------|------------------------------------------------------|
|
||||
//! | `bool` | BOOL |
|
||||
//! | `i8` | "CHAR" |
|
||||
//! | `i16` | SMALLINT, SMALLSERIAL, INT2 |
|
||||
//! | `i32` | INT, SERIAL, INT4 |
|
||||
//! | `i64` | BIGINT, BIGSERIAL, INT8 |
|
||||
@ -143,11 +144,6 @@
|
||||
//! enum Mood { Sad = 0, Ok = 1, Happy = 2 }
|
||||
//! ```
|
||||
//!
|
||||
//! # Nullable
|
||||
//!
|
||||
//! In addition, `Option<T>` is supported where `T` implements `Type`. An `Option<T>` represents
|
||||
//! a potentially `NULL` value from Postgres.
|
||||
//!
|
||||
|
||||
use crate::postgres::type_info::PgTypeKind;
|
||||
use crate::postgres::{PgTypeInfo, Postgres};
|
||||
|
||||
52
sqlx-core/src/postgres/types/time/date.rs
Normal file
52
sqlx-core/src/postgres/types/time/date.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
use crate::postgres::types::time::PG_EPOCH;
|
||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||
use crate::types::Type;
|
||||
use std::mem;
|
||||
use time::{Date, Duration};
|
||||
|
||||
impl Type<Postgres> for Date {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [Date] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<Date> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[Date] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for Date {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days = (*self - PG_EPOCH).whole_days() as i32;
|
||||
Encode::<Postgres>::encode(&days, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<i32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for Date {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days: i32 = Decode::<Postgres>::decode(value)?;
|
||||
PG_EPOCH + Duration::days(days.into())
|
||||
}
|
||||
|
||||
PgValueFormat::Text => Date::parse(value.as_str()?, "%Y-%m-%d")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,27 +1,12 @@
|
||||
use time::{date, offset, Date, Duration, OffsetDateTime, PrimitiveDateTime, Time};
|
||||
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
use crate::postgres::types::time::PG_EPOCH;
|
||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||
use crate::types::Type;
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const PG_EPOCH: Date = date!(2000-1-1);
|
||||
|
||||
impl Type<Postgres> for Time {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Date {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE
|
||||
}
|
||||
}
|
||||
use time::{offset, Duration, OffsetDateTime, PrimitiveDateTime};
|
||||
|
||||
impl Type<Postgres> for PrimitiveDateTime {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
@ -35,18 +20,6 @@ impl Type<Postgres> for OffsetDateTime {
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [Time] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [Date] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::DATE_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [PrimitiveDateTime] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIMESTAMP_ARRAY
|
||||
@ -59,18 +32,6 @@ impl Type<Postgres> for [OffsetDateTime] {
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<Time> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[Time] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<Date> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[Date] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<PrimitiveDateTime> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[PrimitiveDateTime] as Type<Postgres>>::type_info()
|
||||
@ -83,73 +44,6 @@ impl Type<Postgres> for Vec<OffsetDateTime> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for Time {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
let us = (*self - Time::midnight()).whole_microseconds() as i64;
|
||||
Encode::<Postgres>::encode(&us, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<u64>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for Time {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
let us = Decode::<Postgres>::decode(value)?;
|
||||
Time::midnight() + Duration::microseconds(us)
|
||||
}
|
||||
|
||||
PgValueFormat::Text => {
|
||||
// If there are less than 9 digits after the decimal point
|
||||
// We need to zero-pad
|
||||
|
||||
// FIXME: Ask [time] to add a parse % for less-than-fixed-9 nanos
|
||||
|
||||
let s = value.as_str()?;
|
||||
|
||||
let s = if s.len() < 20 {
|
||||
Cow::Owned(format!("{:0<19}", s))
|
||||
} else {
|
||||
Cow::Borrowed(s)
|
||||
};
|
||||
|
||||
Time::parse(&*s, "%H:%M:%S.%N")?
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for Date {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days = (*self - PG_EPOCH).whole_days() as i32;
|
||||
Encode::<Postgres>::encode(&days, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<i32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for Date {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// DATE is encoded as the days since epoch
|
||||
let days: i32 = Decode::<Postgres>::decode(value)?;
|
||||
PG_EPOCH + Duration::days(days.into())
|
||||
}
|
||||
|
||||
PgValueFormat::Text => Date::parse(value.as_str()?, "%Y-%m-%d")?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for PrimitiveDateTime {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// TIMESTAMP is encoded as the microseconds since the epoch
|
||||
6
sqlx-core/src/postgres/types/time/mod.rs
Normal file
6
sqlx-core/src/postgres/types/time/mod.rs
Normal file
@ -0,0 +1,6 @@
|
||||
mod date;
|
||||
mod datetime;
|
||||
mod time;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const PG_EPOCH: ::time::Date = ::time::date!(2000-1-1);
|
||||
67
sqlx-core/src/postgres/types/time/time.rs
Normal file
67
sqlx-core/src/postgres/types/time/time.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use crate::decode::Decode;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::error::BoxDynError;
|
||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||
use crate::types::Type;
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
use time::{Duration, Time};
|
||||
|
||||
impl Type<Postgres> for Time {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for [Time] {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::TIME_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<Postgres> for Vec<Time> {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
<[Time] as Type<Postgres>>::type_info()
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<'_, Postgres> for Time {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
let us = (*self - Time::midnight()).whole_microseconds() as i64;
|
||||
Encode::<Postgres>::encode(&us, buf)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> usize {
|
||||
mem::size_of::<u64>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, Postgres> for Time {
|
||||
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
|
||||
Ok(match value.format() {
|
||||
PgValueFormat::Binary => {
|
||||
// TIME is encoded as the microseconds since midnight
|
||||
let us = Decode::<Postgres>::decode(value)?;
|
||||
Time::midnight() + Duration::microseconds(us)
|
||||
}
|
||||
|
||||
PgValueFormat::Text => {
|
||||
// If there are less than 9 digits after the decimal point
|
||||
// We need to zero-pad
|
||||
|
||||
// FIXME: Ask [time] to add a parse % for less-than-fixed-9 nanos
|
||||
|
||||
let s = value.as_str()?;
|
||||
|
||||
let s = if s.len() < 20 {
|
||||
Cow::Owned(format!("{:0<19}", s))
|
||||
} else {
|
||||
Cow::Borrowed(s)
|
||||
};
|
||||
|
||||
Time::parse(&*s, "%H:%M:%S.%N")?
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -6,10 +6,17 @@
|
||||
//! * [PostgreSQL](../postgres/types/index.html)
|
||||
//! * [MySQL](../mysql/types/index.html)
|
||||
//! * [SQLite](../sqlite/types/index.html)
|
||||
//! * [MSSQL](../mssql/types/index.html)
|
||||
//!
|
||||
//! Any external types that have had [`Type`] implemented for, are re-exported in this module
|
||||
//! for convenience as downstream users need to use a compatible version of the external crate
|
||||
//! to take advantage of the implementation.
|
||||
//!
|
||||
//! # Nullable
|
||||
//!
|
||||
//! To represents nullable SQL types, `Option<T>` is supported where `T` implements `Type`.
|
||||
//! An `Option<T>` represents a potentially `NULL` value from SQL.
|
||||
//!
|
||||
|
||||
use crate::database::Database;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user