mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-12-29 21:00:54 +00:00
feat(mysql): add support for &str and &[u8]
This commit is contained in:
parent
d2da565d0b
commit
22960f1610
@ -31,6 +31,16 @@ pub trait Type<Db: Database> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Db: Database, T: Type<Db>> Type<Db> for &'_ T {
|
||||
fn type_id() -> Db::TypeId {
|
||||
T::type_id()
|
||||
}
|
||||
|
||||
fn compatible(ty: &Db::TypeInfo) -> bool {
|
||||
T::compatible(ty)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub trait TypeEncode<Db: Database>: Type<Db> + Encode<Db> {
|
||||
/// Returns the canonical SQL type identifier for this Rust type.
|
||||
|
||||
@ -57,30 +57,6 @@ impl MySqlTypeId {
|
||||
pub(crate) const fn is_unsigned(&self) -> bool {
|
||||
self.1 == UNSIGNED
|
||||
}
|
||||
|
||||
/// Returns the name for this MySQL data type.
|
||||
pub(crate) const fn name(&self) -> &'static str {
|
||||
match *self {
|
||||
Self::NULL => "NULL",
|
||||
|
||||
Self::TINYINT => "TINYINT",
|
||||
Self::SMALLINT => "SMALLINT",
|
||||
Self::MEDIUMINT => "MEDIUMINT",
|
||||
Self::INT => "INT",
|
||||
Self::BIGINT => "BIGINT",
|
||||
|
||||
Self::TINYINT_UNSIGNED => "TINYINT UNSIGNED",
|
||||
Self::SMALLINT_UNSIGNED => "SMALLINT UNSIGNED",
|
||||
Self::MEDIUMINT_UNSIGNED => "MEDIUMINT UNSIGNED",
|
||||
Self::INT_UNSIGNED => "INT UNSIGNED",
|
||||
Self::BIGINT_UNSIGNED => "BIGINT UNSIGNED",
|
||||
|
||||
Self::FLOAT => "FLOAT",
|
||||
Self::DOUBLE => "DOUBLE",
|
||||
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/data-types.html
|
||||
@ -199,4 +175,40 @@ impl MySqlTypeId {
|
||||
/// used to send a SQL `NULL` without knowing the SQL type.
|
||||
///
|
||||
pub const NULL: Self = Self(6, 0);
|
||||
|
||||
/// A fixed-length string that is always right-padded with spaces
|
||||
/// to the specified length when stored.
|
||||
///
|
||||
pub const CHAR: Self = Self(254, 0);
|
||||
|
||||
/// A fixed-length binary string that is always right-padded with zeroes
|
||||
/// to the specified length when stored.
|
||||
///
|
||||
/// The type identifier for `BINARY` is the same as `CHAR`. At the type
|
||||
/// level, they are identical. At the column, the presence of a binary (`_bin`)
|
||||
/// collation determines if the type stores binary data.
|
||||
///
|
||||
pub const BINARY: Self = Self(254, 0);
|
||||
|
||||
/// A variable-length string.
|
||||
pub const VARCHAR: Self = Self(253, 0);
|
||||
|
||||
/// A variable-length binary string.
|
||||
///
|
||||
/// The type identifier for `VARBINARY` is the same as `VARCHAR`. At the type
|
||||
/// level, they are identical. At the column, the presence of a binary (`_bin`)
|
||||
/// collation determines if the type stores binary data.
|
||||
///
|
||||
pub const VARBINARY: Self = Self(253, 0);
|
||||
|
||||
/// A variable-length string that is assumed to be stored by reference.
|
||||
pub const TEXT: Self = Self(252, 0);
|
||||
|
||||
/// A variable-length string that is assumed to be stored by reference.
|
||||
///
|
||||
/// The type identifier for `BLOB` is the same as `TEXT`. At the type
|
||||
/// level, they are identical. At the column, the presence of a binary (`_bin`)
|
||||
/// collation determines if the type stores binary data.
|
||||
///
|
||||
pub const BLOB: Self = Self(252, 0);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use sqlx_core::TypeInfo;
|
||||
|
||||
use crate::protocol::ColumnDefinition;
|
||||
use crate::protocol::{ColumnDefinition, ColumnFlags};
|
||||
use crate::{MySql, MySqlTypeId};
|
||||
|
||||
/// Provides information about a MySQL type.
|
||||
@ -13,6 +13,7 @@ use crate::{MySql, MySqlTypeId};
|
||||
pub struct MySqlTypeInfo {
|
||||
id: MySqlTypeId,
|
||||
charset: u16,
|
||||
has_binary_collation: bool,
|
||||
|
||||
// [max_size] for integer types, this is (M) in BIT(M) or TINYINT(M)
|
||||
max_size: u32,
|
||||
@ -20,15 +21,63 @@ pub struct MySqlTypeInfo {
|
||||
|
||||
impl MySqlTypeInfo {
|
||||
pub(crate) const fn new(def: &ColumnDefinition) -> Self {
|
||||
Self { id: MySqlTypeId::new(def), charset: def.charset, max_size: def.max_size }
|
||||
Self {
|
||||
id: MySqlTypeId::new(def),
|
||||
charset: def.charset,
|
||||
max_size: def.max_size,
|
||||
has_binary_collation: def.flags.contains(ColumnFlags::BINARY_COLLATION),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MySqlTypeInfo {
|
||||
/// Returns the unique identifier for this MySQL type.
|
||||
#[must_use]
|
||||
pub const fn id(&self) -> MySqlTypeId {
|
||||
self.id
|
||||
}
|
||||
|
||||
/// Returns `true` if this type has a binary collation.
|
||||
#[must_use]
|
||||
pub const fn has_binary_collation(&self) -> bool {
|
||||
self.has_binary_collation
|
||||
}
|
||||
|
||||
/// Returns the name for this MySQL type.
|
||||
#[must_use]
|
||||
pub const fn name(&self) -> &'static str {
|
||||
match self.id {
|
||||
MySqlTypeId::NULL => "NULL",
|
||||
|
||||
MySqlTypeId::TINYINT => "TINYINT",
|
||||
MySqlTypeId::SMALLINT => "SMALLINT",
|
||||
MySqlTypeId::MEDIUMINT => "MEDIUMINT",
|
||||
MySqlTypeId::INT => "INT",
|
||||
MySqlTypeId::BIGINT => "BIGINT",
|
||||
|
||||
MySqlTypeId::TINYINT_UNSIGNED => "TINYINT UNSIGNED",
|
||||
MySqlTypeId::SMALLINT_UNSIGNED => "SMALLINT UNSIGNED",
|
||||
MySqlTypeId::MEDIUMINT_UNSIGNED => "MEDIUMINT UNSIGNED",
|
||||
MySqlTypeId::INT_UNSIGNED => "INT UNSIGNED",
|
||||
MySqlTypeId::BIGINT_UNSIGNED => "BIGINT UNSIGNED",
|
||||
|
||||
MySqlTypeId::FLOAT => "FLOAT",
|
||||
MySqlTypeId::DOUBLE => "DOUBLE",
|
||||
|
||||
// note: VARBINARY, BINARY, and BLOB have the same type IDs as
|
||||
// VARCHAR, CHAR, and TEXT; the only difference is the
|
||||
// presence of a binary collation
|
||||
MySqlTypeId::VARBINARY if self.has_binary_collation() => "VARBINARY",
|
||||
MySqlTypeId::BINARY if self.has_binary_collation() => "BINARY",
|
||||
MySqlTypeId::BLOB if self.has_binary_collation() => "BLOB",
|
||||
|
||||
MySqlTypeId::VARCHAR => "VARCHAR",
|
||||
MySqlTypeId::CHAR => "CHAR",
|
||||
MySqlTypeId::TEXT => "TEXT",
|
||||
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeInfo for MySqlTypeInfo {
|
||||
@ -43,6 +92,6 @@ impl TypeInfo for MySqlTypeInfo {
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
self.id.name()
|
||||
self.name()
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
mod bool;
|
||||
mod str;
|
||||
mod uint;
|
||||
mod bytes;
|
||||
|
||||
// TODO: mod decimal;
|
||||
// TODO: mod int;
|
||||
|
||||
52
sqlx-mysql/src/types/bytes.rs
Normal file
52
sqlx-mysql/src/types/bytes.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use sqlx_core::{decode, encode, Type};
|
||||
use sqlx_core::{Decode, Encode};
|
||||
|
||||
use crate::io::MySqlWriteExt;
|
||||
use crate::type_info::MySqlTypeInfo;
|
||||
use crate::{MySql, MySqlOutput, MySqlRawValue, MySqlTypeId};
|
||||
|
||||
impl Type<MySql> for &'_ [u8] {
|
||||
fn type_id() -> MySqlTypeId {
|
||||
MySqlTypeId::BLOB
|
||||
}
|
||||
|
||||
fn compatible(ty: &MySqlTypeInfo) -> bool {
|
||||
matches!(ty.id(), MySqlTypeId::BLOB | MySqlTypeId::BINARY | MySqlTypeId::VARBINARY)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<MySql> for &'_ [u8] {
|
||||
fn encode(&self, _: &MySqlTypeInfo, out: &mut MySqlOutput<'_>) -> encode::Result<()> {
|
||||
out.buffer().write_bytes_lenenc(self);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, MySql> for &'r [u8] {
|
||||
fn decode(value: MySqlRawValue<'r>) -> decode::Result<Self> {
|
||||
value.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<MySql> for Vec<u8> {
|
||||
fn type_id() -> MySqlTypeId {
|
||||
<&[u8] as Type<MySql>>::type_id()
|
||||
}
|
||||
|
||||
fn compatible(ty: &MySqlTypeInfo) -> bool {
|
||||
<&[u8] as Type<MySql>>::compatible(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<MySql> for Vec<u8> {
|
||||
fn encode(&self, ty: &MySqlTypeInfo, out: &mut MySqlOutput<'_>) -> encode::Result<()> {
|
||||
<&[u8] as Encode<MySql>>::encode(&self.as_slice(), ty, out)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, MySql> for Vec<u8> {
|
||||
fn decode(value: MySqlRawValue<'r>) -> decode::Result<Self> {
|
||||
value.as_bytes().map(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
@ -1,25 +1,23 @@
|
||||
use sqlx_core::{decode, encode};
|
||||
use sqlx_core::{decode, encode, Type};
|
||||
use sqlx_core::{Decode, Encode};
|
||||
|
||||
use crate::io::MySqlWriteExt;
|
||||
use crate::type_info::MySqlTypeInfo;
|
||||
use crate::{MySql, MySqlOutput, MySqlRawValue};
|
||||
use crate::{MySql, MySqlOutput, MySqlRawValue, MySqlTypeId};
|
||||
|
||||
// https://dev.mysql.com/doc/internals/en/binary-protocol-value.html#packet-ProtocolBinary
|
||||
impl Type<MySql> for &'_ str {
|
||||
fn type_id() -> MySqlTypeId {
|
||||
MySqlTypeId::TEXT
|
||||
}
|
||||
|
||||
// TODO: accepts(ty)
|
||||
// TODO: compatible(ty)
|
||||
|
||||
impl Encode<MySql> for str {
|
||||
fn encode(&self, _: &MySqlTypeInfo, out: &mut MySqlOutput<'_>) -> encode::Result<()> {
|
||||
todo!("encode: &str");
|
||||
|
||||
Ok(())
|
||||
fn compatible(ty: &MySqlTypeInfo) -> bool {
|
||||
matches!(ty.id(), MySqlTypeId::TEXT | MySqlTypeId::CHAR | MySqlTypeId::VARCHAR)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<MySql> for String {
|
||||
impl Encode<MySql> for &'_ str {
|
||||
fn encode(&self, _: &MySqlTypeInfo, out: &mut MySqlOutput<'_>) -> encode::Result<()> {
|
||||
todo!("encode: String");
|
||||
out.buffer().write_bytes_lenenc(self.as_bytes());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -31,6 +29,22 @@ impl<'r> Decode<'r, MySql> for &'r str {
|
||||
}
|
||||
}
|
||||
|
||||
impl Type<MySql> for String {
|
||||
fn type_id() -> MySqlTypeId {
|
||||
<&str as Type<MySql>>::type_id()
|
||||
}
|
||||
|
||||
fn compatible(ty: &MySqlTypeInfo) -> bool {
|
||||
<&str as Type<MySql>>::compatible(ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encode<MySql> for String {
|
||||
fn encode(&self, ty: &MySqlTypeInfo, out: &mut MySqlOutput<'_>) -> encode::Result<()> {
|
||||
<&str as Encode<MySql>>::encode(&self.as_str(), ty, out)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'r> Decode<'r, MySql> for String {
|
||||
fn decode(value: MySqlRawValue<'r>) -> decode::Result<Self> {
|
||||
value.as_str().map(str::to_owned)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user