mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-08 10:14:35 +00:00
fix: do not enforce type equality if matching against the NULL type
This commit is contained in:
parent
1247daec83
commit
dc5fc1b6c1
@ -33,6 +33,22 @@ pub(crate) enum AnyTypeInfoKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeInfo for AnyTypeInfo {
|
impl TypeInfo for AnyTypeInfo {
|
||||||
|
fn is_null(&self) -> bool {
|
||||||
|
match &self.0 {
|
||||||
|
#[cfg(feature = "postgres")]
|
||||||
|
AnyTypeInfoKind::Postgres(ty) => ty.is_null(),
|
||||||
|
|
||||||
|
#[cfg(feature = "mysql")]
|
||||||
|
AnyTypeInfoKind::MySql(ty) => ty.is_null(),
|
||||||
|
|
||||||
|
#[cfg(feature = "sqlite")]
|
||||||
|
AnyTypeInfoKind::Sqlite(ty) => ty.is_null(),
|
||||||
|
|
||||||
|
#[cfg(feature = "mssql")]
|
||||||
|
AnyTypeInfoKind::Mssql(ty) => ty.is_null(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
#[cfg(feature = "postgres")]
|
#[cfg(feature = "postgres")]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::mssql::protocol::type_info::TypeInfo as ProtocolTypeInfo;
|
use crate::mssql::protocol::type_info::{TypeInfo as ProtocolTypeInfo, DataType};
|
||||||
use crate::type_info::TypeInfo;
|
use crate::type_info::TypeInfo;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@ -8,6 +8,10 @@ use crate::type_info::TypeInfo;
|
|||||||
pub struct MssqlTypeInfo(pub(crate) ProtocolTypeInfo);
|
pub struct MssqlTypeInfo(pub(crate) ProtocolTypeInfo);
|
||||||
|
|
||||||
impl TypeInfo for MssqlTypeInfo {
|
impl TypeInfo for MssqlTypeInfo {
|
||||||
|
fn is_null(&self) -> bool {
|
||||||
|
matches!(self.0.ty, DataType::Null)
|
||||||
|
}
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
self.0.name()
|
self.0.name()
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,10 @@ impl Display for MySqlTypeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeInfo for MySqlTypeInfo {
|
impl TypeInfo for MySqlTypeInfo {
|
||||||
|
fn is_null(&self) -> bool {
|
||||||
|
matches!(self.r#type, ColumnType::Null)
|
||||||
|
}
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
self.r#type.name(self.char_set, self.flags)
|
self.r#type.name(self.char_set, self.flags)
|
||||||
}
|
}
|
||||||
|
@ -741,6 +741,10 @@ impl TypeInfo for PgTypeInfo {
|
|||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
self.0.display_name()
|
self.0.display_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_null(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<PgCustomType> for PgCustomType {
|
impl PartialEq<PgCustomType> for PgCustomType {
|
||||||
|
@ -6,6 +6,7 @@ use crate::error::{mismatched_types, BoxDynError};
|
|||||||
use crate::postgres::type_info::{PgType, PgTypeKind};
|
use crate::postgres::type_info::{PgType, PgTypeKind};
|
||||||
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
use crate::postgres::{PgArgumentBuffer, PgTypeInfo, PgValueFormat, PgValueRef, Postgres};
|
||||||
use crate::types::Type;
|
use crate::types::Type;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct PgRecordEncoder<'a> {
|
pub struct PgRecordEncoder<'a> {
|
||||||
@ -126,7 +127,7 @@ impl<'r> PgRecordDecoder<'r> {
|
|||||||
self.ind += 1;
|
self.ind += 1;
|
||||||
|
|
||||||
if let Some(ty) = &element_type_opt {
|
if let Some(ty) = &element_type_opt {
|
||||||
if !T::compatible(ty) {
|
if !ty.is_null() && !T::compatible(ty) {
|
||||||
return Err(mismatched_types::<Postgres, T>(ty));
|
return Err(mismatched_types::<Postgres, T>(ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use crate::database::{Database, HasValueRef};
|
|||||||
use crate::decode::Decode;
|
use crate::decode::Decode;
|
||||||
use crate::error::{mismatched_types, Error};
|
use crate::error::{mismatched_types, Error};
|
||||||
use crate::types::Type;
|
use crate::types::Type;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
use crate::value::ValueRef;
|
use crate::value::ValueRef;
|
||||||
|
|
||||||
/// A type that can be used to index into a [`Row`].
|
/// A type that can be used to index into a [`Row`].
|
||||||
@ -171,7 +172,7 @@ pub trait Row: private_row::Sealed + Unpin + Send + Sync + 'static {
|
|||||||
if !value.is_null() {
|
if !value.is_null() {
|
||||||
let ty = value.type_info();
|
let ty = value.type_info();
|
||||||
|
|
||||||
if !T::compatible(&ty) {
|
if !ty.is_null() && !T::compatible(&ty) {
|
||||||
return Err(Error::ColumnDecode {
|
return Err(Error::ColumnDecode {
|
||||||
index: format!("{:?}", index),
|
index: format!("{:?}", index),
|
||||||
source: mismatched_types::<Self::Database, T>(&ty),
|
source: mismatched_types::<Self::Database, T>(&ty),
|
||||||
|
@ -40,6 +40,10 @@ impl Display for SqliteTypeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeInfo for SqliteTypeInfo {
|
impl TypeInfo for SqliteTypeInfo {
|
||||||
|
fn is_null(&self) -> bool {
|
||||||
|
matches!(self.0, DataType::Null)
|
||||||
|
}
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
DataType::Null => "NULL",
|
DataType::Null => "NULL",
|
||||||
|
@ -2,6 +2,8 @@ use std::fmt::{Debug, Display};
|
|||||||
|
|
||||||
/// Provides information about a SQL type for the database driver.
|
/// Provides information about a SQL type for the database driver.
|
||||||
pub trait TypeInfo: Debug + Display + Clone + PartialEq<Self> {
|
pub trait TypeInfo: Debug + Display + Clone + PartialEq<Self> {
|
||||||
|
fn is_null(&self) -> bool;
|
||||||
|
|
||||||
/// Returns the database system name of the type. Length specifiers should not be included.
|
/// Returns the database system name of the type. Length specifiers should not be included.
|
||||||
/// Common type names are `VARCHAR`, `TEXT`, or `INT`. Type names should be uppercase. They
|
/// Common type names are `VARCHAR`, `TEXT`, or `INT`. Type names should be uppercase. They
|
||||||
/// should be a rough approximation of how they are written in SQL in the given database.
|
/// should be a rough approximation of how they are written in SQL in the given database.
|
||||||
|
@ -2,6 +2,7 @@ use crate::database::{Database, HasValueRef};
|
|||||||
use crate::decode::Decode;
|
use crate::decode::Decode;
|
||||||
use crate::error::{mismatched_types, Error};
|
use crate::error::{mismatched_types, Error};
|
||||||
use crate::types::Type;
|
use crate::types::Type;
|
||||||
|
use crate::type_info::TypeInfo;
|
||||||
|
|
||||||
/// An owned value from the database.
|
/// An owned value from the database.
|
||||||
pub trait Value {
|
pub trait Value {
|
||||||
@ -65,7 +66,7 @@ pub trait Value {
|
|||||||
if !self.is_null() {
|
if !self.is_null() {
|
||||||
let ty = self.type_info();
|
let ty = self.type_info();
|
||||||
|
|
||||||
if !T::compatible(&ty) {
|
if !ty.is_null() && !T::compatible(&ty) {
|
||||||
return Err(Error::Decode(mismatched_types::<Self::Database, T>(&ty)));
|
return Err(Error::Decode(mismatched_types::<Self::Database, T>(&ty)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user