diff --git a/sqlx-core/src/any/arguments.rs b/sqlx-core/src/any/arguments.rs index 59d6f4d6e0..40090f7c0e 100644 --- a/sqlx-core/src/any/arguments.rs +++ b/sqlx-core/src/any/arguments.rs @@ -41,17 +41,27 @@ impl AnyArguments { where Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, + Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, + Option: Type + Encode<'a, A::Database>, + Option: Type + Encode<'a, A::Database>, + Option: Type + Encode<'a, A::Database>, + Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, Option: Type + Encode<'a, A::Database>, Option>: Type + Encode<'a, A::Database>, bool: Type + Encode<'a, A::Database>, + i8: Type + Encode<'a, A::Database>, i16: Type + Encode<'a, A::Database>, i32: Type + Encode<'a, A::Database>, i64: Type + Encode<'a, A::Database>, + u8: Type + Encode<'a, A::Database>, + u16: Type + Encode<'a, A::Database>, + u32: Type + Encode<'a, A::Database>, + u64: Type + Encode<'a, A::Database>, f32: Type + Encode<'a, A::Database>, f64: Type + Encode<'a, A::Database>, Arc: Type + Encode<'a, A::Database>, @@ -64,17 +74,31 @@ impl AnyArguments { match arg { AnyValueKind::Null(AnyTypeInfoKind::Null) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Bool) => out.add(Option::::None), + AnyValueKind::Null(AnyTypeInfoKind::TinyInt) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::SmallInt) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Integer) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::BigInt) => out.add(Option::::None), + AnyValueKind::Null(AnyTypeInfoKind::UnsignedTinyInt) => out.add(Option::::None), + AnyValueKind::Null(AnyTypeInfoKind::UnsignedSmallInt) => { + out.add(Option::::None) + } + AnyValueKind::Null(AnyTypeInfoKind::UnsignedInteger) => { + out.add(Option::::None) + } + AnyValueKind::Null(AnyTypeInfoKind::UnsignedBigInt) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Real) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Double) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Text) => out.add(Option::::None), AnyValueKind::Null(AnyTypeInfoKind::Blob) => out.add(Option::>::None), AnyValueKind::Bool(b) => out.add(b), + AnyValueKind::TinyInt(i) => out.add(i), AnyValueKind::SmallInt(i) => out.add(i), AnyValueKind::Integer(i) => out.add(i), AnyValueKind::BigInt(i) => out.add(i), + AnyValueKind::UnsignedTinyInt(i) => out.add(i), + AnyValueKind::UnsignedSmallInt(i) => out.add(i), + AnyValueKind::UnsignedInteger(i) => out.add(i), + AnyValueKind::UnsignedBigInt(i) => out.add(i), AnyValueKind::Real(r) => out.add(r), AnyValueKind::Double(d) => out.add(d), AnyValueKind::Text(t) => out.add(t), diff --git a/sqlx-core/src/any/row.rs b/sqlx-core/src/any/row.rs index 57b8590b5f..12711308da 100644 --- a/sqlx-core/src/any/row.rs +++ b/sqlx-core/src/any/row.rs @@ -88,9 +88,14 @@ impl AnyRow { AnyTypeInfo: for<'b> TryFrom<&'b ::TypeInfo, Error = Error>, AnyColumn: for<'b> TryFrom<&'b ::Column, Error = Error>, bool: Type + Decode<'a, R::Database>, + i8: Type + Decode<'a, R::Database>, i16: Type + Decode<'a, R::Database>, i32: Type + Decode<'a, R::Database>, i64: Type + Decode<'a, R::Database>, + u8: Type + Decode<'a, R::Database>, + u16: Type + Decode<'a, R::Database>, + u32: Type + Decode<'a, R::Database>, + u64: Type + Decode<'a, R::Database>, f32: Type + Decode<'a, R::Database>, f64: Type + Decode<'a, R::Database>, String: Type + Decode<'a, R::Database>, @@ -120,9 +125,14 @@ impl AnyRow { k if value.is_null() => AnyValueKind::Null(k), AnyTypeInfoKind::Null => AnyValueKind::Null(AnyTypeInfoKind::Null), AnyTypeInfoKind::Bool => AnyValueKind::Bool(decode(value)?), + AnyTypeInfoKind::TinyInt => AnyValueKind::TinyInt(decode(value)?), AnyTypeInfoKind::SmallInt => AnyValueKind::SmallInt(decode(value)?), AnyTypeInfoKind::Integer => AnyValueKind::Integer(decode(value)?), AnyTypeInfoKind::BigInt => AnyValueKind::BigInt(decode(value)?), + AnyTypeInfoKind::UnsignedTinyInt => AnyValueKind::UnsignedTinyInt(decode(value)?), + AnyTypeInfoKind::UnsignedSmallInt => AnyValueKind::UnsignedSmallInt(decode(value)?), + AnyTypeInfoKind::UnsignedInteger => AnyValueKind::UnsignedInteger(decode(value)?), + AnyTypeInfoKind::UnsignedBigInt => AnyValueKind::UnsignedBigInt(decode(value)?), AnyTypeInfoKind::Real => AnyValueKind::Real(decode(value)?), AnyTypeInfoKind::Double => AnyValueKind::Double(decode(value)?), AnyTypeInfoKind::Blob => AnyValueKind::Blob(decode::<_, Vec>(value)?.into()), diff --git a/sqlx-core/src/any/type_info.rs b/sqlx-core/src/any/type_info.rs index 0879b333ca..f5ca3b20b6 100644 --- a/sqlx-core/src/any/type_info.rs +++ b/sqlx-core/src/any/type_info.rs @@ -20,9 +20,14 @@ impl AnyTypeInfo { pub enum AnyTypeInfoKind { Null, Bool, + TinyInt, SmallInt, Integer, BigInt, + UnsignedTinyInt, + UnsignedSmallInt, + UnsignedInteger, + UnsignedBigInt, Real, Double, Text, @@ -39,9 +44,14 @@ impl TypeInfo for AnyTypeInfo { match self.kind { Bool => "BOOLEAN", + TinyInt => "TINYINT", SmallInt => "SMALLINT", Integer => "INTEGER", BigInt => "BIGINT", + UnsignedTinyInt => "UNSIGNED TINYINT", + UnsignedSmallInt => "UNSIGNED SMALLINT", + UnsignedInteger => "UNSIGNED INTEGER", + UnsignedBigInt => "UNSIGNED BIGINT", Real => "REAL", Double => "DOUBLE", Text => "TEXT", @@ -59,6 +69,16 @@ impl Display for AnyTypeInfo { impl AnyTypeInfoKind { pub fn is_integer(&self) -> bool { - matches!(self, SmallInt | Integer | BigInt) + matches!( + self, + TinyInt + | SmallInt + | Integer + | BigInt + | UnsignedTinyInt + | UnsignedSmallInt + | UnsignedInteger + | UnsignedBigInt + ) } } diff --git a/sqlx-core/src/any/types/int.rs b/sqlx-core/src/any/types/int.rs index e2bb43212f..2672e234e3 100644 --- a/sqlx-core/src/any/types/int.rs +++ b/sqlx-core/src/any/types/int.rs @@ -5,6 +5,34 @@ use crate::encode::{Encode, IsNull}; use crate::error::BoxDynError; use crate::types::Type; +impl Type for i8 { + fn type_info() -> AnyTypeInfo { + AnyTypeInfo { + kind: AnyTypeInfoKind::TinyInt, + } + } + + fn compatible(ty: &AnyTypeInfo) -> bool { + ty.kind().is_integer() + } +} + +impl Encode<'_, Any> for i8 { + fn encode_by_ref( + &self, + buf: &mut ::ArgumentBuffer, + ) -> Result { + buf.0.push(AnyValueKind::TinyInt(*self)); + Ok(IsNull::No) + } +} + +impl<'r> Decode<'r, Any> for i8 { + fn decode(value: ::ValueRef<'r>) -> Result { + value.kind.try_integer() + } +} + impl Type for i16 { fn type_info() -> AnyTypeInfo { AnyTypeInfo { diff --git a/sqlx-core/src/any/types/mod.rs b/sqlx-core/src/any/types/mod.rs index a0ae55156d..4956e2eb94 100644 --- a/sqlx-core/src/any/types/mod.rs +++ b/sqlx-core/src/any/types/mod.rs @@ -5,9 +5,14 @@ //! | Rust type | SQL type(s) | //! |---------------------------------------|------------------------------------------------------| //! | `bool` | BOOLEAN | +//! | `i8` | TINYINT | //! | `i16` | SMALLINT | //! | `i32` | INT | //! | `i64` | BIGINT | +//! | `u8` | UNSIGNED TINYINT | +//! | `u16` | UNSIGNED SMALLINT | +//! | `u32` | UNSIGNED INT | +//! | `u64` | UNSIGNED BIGINT | //! | `f32` | FLOAT | //! | `f64` | DOUBLE | //! | `&str`, [`String`] | VARCHAR, CHAR, TEXT | @@ -22,6 +27,7 @@ mod bool; mod float; mod int; mod str; +mod uint; #[test] fn test_type_impls() { @@ -40,10 +46,16 @@ fn test_type_impls() { has_type::(); + has_type::(); has_type::(); has_type::(); has_type::(); + has_type::(); + has_type::(); + has_type::(); + has_type::(); + has_type::(); has_type::(); diff --git a/sqlx-core/src/any/types/uint.rs b/sqlx-core/src/any/types/uint.rs new file mode 100644 index 0000000000..ed88ed4531 --- /dev/null +++ b/sqlx-core/src/any/types/uint.rs @@ -0,0 +1,118 @@ +use crate::any::{Any, AnyTypeInfo, AnyTypeInfoKind, AnyValueKind}; +use crate::database::Database; +use crate::decode::Decode; +use crate::encode::{Encode, IsNull}; +use crate::error::BoxDynError; +use crate::types::Type; + +impl Type for u8 { + fn type_info() -> AnyTypeInfo { + AnyTypeInfo { + kind: AnyTypeInfoKind::UnsignedTinyInt, + } + } + + fn compatible(ty: &AnyTypeInfo) -> bool { + ty.kind().is_integer() + } +} + +impl Encode<'_, Any> for u8 { + fn encode_by_ref( + &self, + buf: &mut ::ArgumentBuffer, + ) -> Result { + buf.0.push(AnyValueKind::UnsignedTinyInt(*self)); + Ok(IsNull::No) + } +} + +impl<'r> Decode<'r, Any> for u8 { + fn decode(value: ::ValueRef<'r>) -> Result { + value.kind.try_integer() + } +} + +impl Type for u16 { + fn type_info() -> AnyTypeInfo { + AnyTypeInfo { + kind: AnyTypeInfoKind::UnsignedTinyInt, + } + } + + fn compatible(ty: &AnyTypeInfo) -> bool { + ty.kind().is_integer() + } +} + +impl Encode<'_, Any> for u16 { + fn encode_by_ref( + &self, + buf: &mut ::ArgumentBuffer, + ) -> Result { + buf.0.push(AnyValueKind::UnsignedSmallInt(*self)); + Ok(IsNull::No) + } +} + +impl<'r> Decode<'r, Any> for u16 { + fn decode(value: ::ValueRef<'r>) -> Result { + value.kind.try_integer() + } +} + +impl Type for u32 { + fn type_info() -> AnyTypeInfo { + AnyTypeInfo { + kind: AnyTypeInfoKind::UnsignedInteger, + } + } + + fn compatible(ty: &AnyTypeInfo) -> bool { + ty.kind().is_integer() + } +} + +impl Encode<'_, Any> for u32 { + fn encode_by_ref( + &self, + buf: &mut ::ArgumentBuffer, + ) -> Result { + buf.0.push(AnyValueKind::UnsignedInteger(*self)); + Ok(IsNull::No) + } +} + +impl<'r> Decode<'r, Any> for u32 { + fn decode(value: ::ValueRef<'r>) -> Result { + value.kind.try_integer() + } +} + +impl Type for u64 { + fn type_info() -> AnyTypeInfo { + AnyTypeInfo { + kind: AnyTypeInfoKind::UnsignedBigInt, + } + } + + fn compatible(ty: &AnyTypeInfo) -> bool { + ty.kind().is_integer() + } +} + +impl Encode<'_, Any> for u64 { + fn encode_by_ref( + &self, + buf: &mut ::ArgumentBuffer, + ) -> Result { + buf.0.push(AnyValueKind::UnsignedBigInt(*self)); + Ok(IsNull::No) + } +} + +impl<'r> Decode<'r, Any> for u64 { + fn decode(value: ::ValueRef<'r>) -> Result { + value.kind.try_integer() + } +} diff --git a/sqlx-core/src/any/value.rs b/sqlx-core/src/any/value.rs index a85c1dc69c..ec1b7b7355 100644 --- a/sqlx-core/src/any/value.rs +++ b/sqlx-core/src/any/value.rs @@ -11,9 +11,14 @@ use std::sync::Arc; pub enum AnyValueKind { Null(AnyTypeInfoKind), Bool(bool), + TinyInt(i8), SmallInt(i16), Integer(i32), BigInt(i64), + UnsignedTinyInt(u8), + UnsignedSmallInt(u16), + UnsignedInteger(u32), + UnsignedBigInt(u64), Real(f32), Double(f64), Text(Arc), @@ -27,9 +32,14 @@ impl AnyValueKind { kind: match self { AnyValueKind::Null(_) => AnyTypeInfoKind::Null, AnyValueKind::Bool(_) => AnyTypeInfoKind::Bool, + AnyValueKind::TinyInt(_) => AnyTypeInfoKind::TinyInt, AnyValueKind::SmallInt(_) => AnyTypeInfoKind::SmallInt, AnyValueKind::Integer(_) => AnyTypeInfoKind::Integer, AnyValueKind::BigInt(_) => AnyTypeInfoKind::BigInt, + AnyValueKind::UnsignedTinyInt(_) => AnyTypeInfoKind::UnsignedTinyInt, + AnyValueKind::UnsignedSmallInt(_) => AnyTypeInfoKind::UnsignedSmallInt, + AnyValueKind::UnsignedInteger(_) => AnyTypeInfoKind::UnsignedInteger, + AnyValueKind::UnsignedBigInt(_) => AnyTypeInfoKind::UnsignedBigInt, AnyValueKind::Real(_) => AnyTypeInfoKind::Real, AnyValueKind::Double(_) => AnyTypeInfoKind::Double, AnyValueKind::Text(_) => AnyTypeInfoKind::Text, @@ -45,15 +55,33 @@ impl AnyValueKind { pub(in crate::any) fn try_integer(&self) -> Result where - T: Type + TryFrom + TryFrom + TryFrom, + T: Type + + TryFrom + + TryFrom + + TryFrom + + TryFrom + + TryFrom + + TryFrom + + TryFrom + + TryFrom, + BoxDynError: From<>::Error>, BoxDynError: From<>::Error>, BoxDynError: From<>::Error>, BoxDynError: From<>::Error>, + BoxDynError: From<>::Error>, + BoxDynError: From<>::Error>, + BoxDynError: From<>::Error>, + BoxDynError: From<>::Error>, { Ok(match self { + AnyValueKind::TinyInt(i) => (*i).try_into()?, AnyValueKind::SmallInt(i) => (*i).try_into()?, AnyValueKind::Integer(i) => (*i).try_into()?, AnyValueKind::BigInt(i) => (*i).try_into()?, + AnyValueKind::UnsignedTinyInt(i) => (*i).try_into()?, + AnyValueKind::UnsignedSmallInt(i) => (*i).try_into()?, + AnyValueKind::UnsignedInteger(i) => (*i).try_into()?, + AnyValueKind::UnsignedBigInt(i) => (*i).try_into()?, _ => return self.unexpected(), }) } diff --git a/sqlx-sqlite/src/any.rs b/sqlx-sqlite/src/any.rs index 83b141decd..85f6a0e15c 100644 --- a/sqlx-sqlite/src/any.rs +++ b/sqlx-sqlite/src/any.rs @@ -214,9 +214,13 @@ fn map_arguments(args: AnyArguments) -> SqliteArguments { .map(|val| match val { AnyValueKind::Null(_) => SqliteArgumentValue::Null, AnyValueKind::Bool(b) => SqliteArgumentValue::Int(b as i32), + AnyValueKind::TinyInt(i) => SqliteArgumentValue::Int(i as i32), AnyValueKind::SmallInt(i) => SqliteArgumentValue::Int(i as i32), AnyValueKind::Integer(i) => SqliteArgumentValue::Int(i), AnyValueKind::BigInt(i) => SqliteArgumentValue::Int64(i), + AnyValueKind::UnsignedTinyInt(i) => SqliteArgumentValue::Int(i as i32), + AnyValueKind::UnsignedSmallInt(i) => SqliteArgumentValue::Int(i as i32), + AnyValueKind::UnsignedInteger(i) => SqliteArgumentValue::Int64(i as i64), AnyValueKind::Real(r) => SqliteArgumentValue::Double(r as f64), AnyValueKind::Double(d) => SqliteArgumentValue::Double(d), AnyValueKind::Text(t) => SqliteArgumentValue::Text(Arc::new(t.to_string())),