mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
feat(core): add Type, TypeEncode, and TypeDecode
This commit is contained in:
parent
f7516ea22d
commit
831df74b93
@ -6,12 +6,15 @@ use crate::database::HasRawValue;
|
||||
use crate::Database;
|
||||
|
||||
/// A type that can be decoded from a SQL value.
|
||||
pub trait Decode<'r, Db: Database>: Sized + Send + Sync {
|
||||
fn decode(value: <Db as HasRawValue<'r>>::RawValue) -> Result<Self>;
|
||||
pub trait Decode<'r, Db: Database>: Send + Sync {
|
||||
fn decode(value: <Db as HasRawValue<'r>>::RawValue) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// A type that can be decoded from a SQL value, without borrowing any data
|
||||
/// from the row.
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub trait DecodeOwned<Db: Database>: for<'r> Decode<'r, Db> {}
|
||||
|
||||
impl<T, Db: Database> DecodeOwned<Db> for T where T: for<'r> Decode<'r, Db> {}
|
||||
@ -33,6 +36,13 @@ pub enum Error {
|
||||
Custom(Box<dyn StdError + Send + Sync>),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
#[doc(hidden)]
|
||||
pub fn msg<D: Display>(msg: D) -> Self {
|
||||
Self::Custom(msg.to_string().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
||||
@ -6,14 +6,8 @@ use crate::Database;
|
||||
|
||||
/// A type that can be encoded into a SQL value.
|
||||
pub trait Encode<Db: Database>: Send + Sync {
|
||||
/// Encode this value into a SQL value.
|
||||
/// Encode this value into the specified SQL type.
|
||||
fn encode(&self, ty: &Db::TypeInfo, out: &mut <Db as HasOutput<'_>>::Output) -> Result<()>;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
fn __type_name(&self) -> &'static str {
|
||||
std::any::type_name::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Encode<Db>, Db: Database> Encode<Db> for &T {
|
||||
@ -31,6 +25,13 @@ pub enum Error {
|
||||
Custom(Box<dyn StdError + Send + Sync>),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
#[doc(hidden)]
|
||||
pub fn msg<D: Display>(msg: D) -> Self {
|
||||
Self::Custom(msg.to_string().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#![allow(clippy::clippy::missing_errors_doc)]
|
||||
|
||||
mod acquire;
|
||||
mod arguments;
|
||||
mod close;
|
||||
mod column;
|
||||
mod connect;
|
||||
@ -32,6 +33,8 @@ mod options;
|
||||
mod query_result;
|
||||
pub mod row;
|
||||
mod runtime;
|
||||
mod r#type;
|
||||
mod type_info;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub mod io;
|
||||
@ -47,6 +50,7 @@ pub mod mock;
|
||||
pub mod blocking;
|
||||
|
||||
pub use acquire::Acquire;
|
||||
pub use arguments::{Argument, Arguments};
|
||||
#[cfg(feature = "blocking")]
|
||||
pub use blocking::runtime::Blocking;
|
||||
pub use close::Close;
|
||||
@ -60,6 +64,7 @@ pub use error::{DatabaseError, Error, Result};
|
||||
pub use executor::Executor;
|
||||
pub use options::ConnectOptions;
|
||||
pub use query_result::QueryResult;
|
||||
pub use r#type::{Type, TypeEncode, TypeDecode};
|
||||
pub use row::Row;
|
||||
#[cfg(feature = "actix")]
|
||||
pub use runtime::Actix;
|
||||
@ -70,3 +75,4 @@ pub use runtime::AsyncStd;
|
||||
pub use runtime::Runtime;
|
||||
#[cfg(feature = "tokio")]
|
||||
pub use runtime::Tokio;
|
||||
pub use type_info::TypeInfo;
|
||||
|
||||
52
sqlx-core/src/type.rs
Normal file
52
sqlx-core/src/type.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use crate::{Database, Decode, Encode, TypeInfo};
|
||||
|
||||
// NOTE: The interface here is not final. There are some special considerations
|
||||
// for MSSQL and Postgres (Arrays and Ranges) that need careful handling
|
||||
// to ensure we correctly cover them.
|
||||
|
||||
/// Indicates that a SQL type is supported for a database.
|
||||
pub trait Type<Db: Database> {
|
||||
/// Returns the canonical SQL type identifier for this Rust type.
|
||||
///
|
||||
/// When binding arguments, this is used to tell the database what is about to be sent; which,
|
||||
/// the database then uses to guide query plans. This can be overridden by [`type_id_of`].
|
||||
///
|
||||
/// A map of SQL types to Rust types is populated with this and used
|
||||
/// to determine the type that is returned from the anonymous struct type from [`query!`].
|
||||
///
|
||||
fn type_id() -> Db::TypeId
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Determines if this Rust type is compatible with the specified SQL type.
|
||||
///
|
||||
/// To be compatible, the Rust type must support encoding _and_ decoding
|
||||
/// from the specified SQL type.
|
||||
///
|
||||
fn compatible(ty: &Db::TypeInfo) -> bool
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
ty.id() == Self::type_id()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub trait TypeEncode<Db: Database>: Type<Db> + Encode<Db> {
|
||||
/// Returns the SQL type identifier that best hints to the database
|
||||
/// at the incoming value for a bind parameter.
|
||||
#[allow(unused_variables)]
|
||||
fn type_id_of(&self, ty: &Db::TypeInfo) -> Db::TypeId;
|
||||
|
||||
/// Returns the Rust type name of this.
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
fn __rust_type_name_of(&self) -> &'static str {
|
||||
std::any::type_name::<Self>()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub trait TypeDecode<'r, Db: Database>: Type<Db> + Decode<'r, Db> {}
|
||||
|
||||
impl<'r, T: Type<Db> + Decode<'r, Db>, Db: Database> TypeDecode<'r, Db> for T {}
|
||||
Loading…
x
Reference in New Issue
Block a user