Skip to main content

sqlx_odbc/
type_info.rs

1use odbc_api::DataType;
2use std::fmt::{Display, Formatter, Result as FmtResult};
3
4/// Type information for an ODBC value.
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct OdbcTypeInfo {
7    data_type: DataType,
8}
9
10impl OdbcTypeInfo {
11    /// Creates type information from an `odbc-api` data type.
12    pub const fn new(data_type: DataType) -> Self {
13        Self { data_type }
14    }
15
16    /// Returns the underlying `odbc-api` data type.
17    pub const fn data_type(&self) -> DataType {
18        self.data_type
19    }
20
21    /// `BIGINT` type information.
22    pub const BIGINT: Self = Self::new(DataType::BigInt);
23
24    /// `BIT` type information.
25    pub const BIT: Self = Self::new(DataType::Bit);
26
27    /// `DATE` type information.
28    pub const DATE: Self = Self::new(DataType::Date);
29
30    /// `DOUBLE` type information.
31    pub const DOUBLE: Self = Self::new(DataType::Double);
32
33    /// `INTEGER` type information.
34    pub const INTEGER: Self = Self::new(DataType::Integer);
35
36    /// `REAL` type information.
37    pub const REAL: Self = Self::new(DataType::Real);
38
39    /// `SMALLINT` type information.
40    pub const SMALLINT: Self = Self::new(DataType::SmallInt);
41
42    /// `TINYINT` type information.
43    pub const TINYINT: Self = Self::new(DataType::TinyInt);
44
45    /// `UNKNOWN` type information.
46    pub const UNKNOWN: Self = Self::new(DataType::Unknown);
47
48    /// `TIME` type information with zero fractional precision.
49    pub const TIME: Self = Self::new(DataType::Time { precision: 0 });
50
51    /// `TIMESTAMP` type information with zero fractional precision.
52    pub const TIMESTAMP: Self = Self::new(DataType::Timestamp { precision: 0 });
53
54    /// Creates `VARCHAR` type information.
55    pub const fn varchar(length: Option<std::num::NonZeroUsize>) -> Self {
56        Self::new(DataType::Varchar { length })
57    }
58
59    /// Creates `VARBINARY` type information.
60    pub const fn varbinary(length: Option<std::num::NonZeroUsize>) -> Self {
61        Self::new(DataType::Varbinary { length })
62    }
63
64    /// Creates `DECIMAL` type information.
65    pub const fn decimal(precision: usize, scale: i16) -> Self {
66        Self::new(DataType::Decimal { precision, scale })
67    }
68
69    /// Creates `NUMERIC` type information.
70    pub const fn numeric(precision: usize, scale: i16) -> Self {
71        Self::new(DataType::Numeric { precision, scale })
72    }
73}
74
75impl sqlx_core::type_info::TypeInfo for OdbcTypeInfo {
76    fn is_null(&self) -> bool {
77        false
78    }
79
80    fn name(&self) -> &str {
81        match self.data_type {
82            DataType::BigInt => "BIGINT",
83            DataType::Binary { .. } => "BINARY",
84            DataType::Bit => "BIT",
85            DataType::Char { .. } => "CHAR",
86            DataType::Date => "DATE",
87            DataType::Decimal { .. } => "DECIMAL",
88            DataType::Double => "DOUBLE",
89            DataType::Float { .. } => "FLOAT",
90            DataType::Integer => "INTEGER",
91            DataType::LongVarbinary { .. } => "LONGVARBINARY",
92            DataType::LongVarchar { .. } => "LONGVARCHAR",
93            DataType::Numeric { .. } => "NUMERIC",
94            DataType::Real => "REAL",
95            DataType::SmallInt => "SMALLINT",
96            DataType::Time { .. } => "TIME",
97            DataType::Timestamp { .. } => "TIMESTAMP",
98            DataType::TinyInt => "TINYINT",
99            DataType::Varbinary { .. } => "VARBINARY",
100            DataType::Varchar { .. } => "VARCHAR",
101            DataType::WChar { .. } => "WCHAR",
102            DataType::WLongVarchar { .. } => "WLONGVARCHAR",
103            DataType::WVarchar { .. } => "WVARCHAR",
104            DataType::Unknown => "UNKNOWN",
105            DataType::Other { .. } => "OTHER",
106        }
107    }
108}
109
110/// Helper predicates for `odbc-api` data type groups.
111pub trait DataTypeExt {
112    /// Returns the canonical display name for this type.
113    fn name(self) -> &'static str;
114
115    /// Returns whether this type carries character data.
116    fn accepts_character_data(self) -> bool;
117
118    /// Returns whether this type carries binary data.
119    fn accepts_binary_data(self) -> bool;
120
121    /// Returns whether this type carries numeric data.
122    fn accepts_numeric_data(self) -> bool;
123}
124
125impl DataTypeExt for DataType {
126    fn name(self) -> &'static str {
127        match self {
128            DataType::BigInt => "BIGINT",
129            DataType::Binary { .. } => "BINARY",
130            DataType::Bit => "BIT",
131            DataType::Char { .. } => "CHAR",
132            DataType::Date => "DATE",
133            DataType::Decimal { .. } => "DECIMAL",
134            DataType::Double => "DOUBLE",
135            DataType::Float { .. } => "FLOAT",
136            DataType::Integer => "INTEGER",
137            DataType::LongVarbinary { .. } => "LONGVARBINARY",
138            DataType::LongVarchar { .. } => "LONGVARCHAR",
139            DataType::Numeric { .. } => "NUMERIC",
140            DataType::Real => "REAL",
141            DataType::SmallInt => "SMALLINT",
142            DataType::Time { .. } => "TIME",
143            DataType::Timestamp { .. } => "TIMESTAMP",
144            DataType::TinyInt => "TINYINT",
145            DataType::Varbinary { .. } => "VARBINARY",
146            DataType::Varchar { .. } => "VARCHAR",
147            DataType::WChar { .. } => "WCHAR",
148            DataType::WLongVarchar { .. } => "WLONGVARCHAR",
149            DataType::WVarchar { .. } => "WVARCHAR",
150            DataType::Unknown => "UNKNOWN",
151            DataType::Other { .. } => "OTHER",
152        }
153    }
154
155    fn accepts_character_data(self) -> bool {
156        matches!(
157            self,
158            DataType::Char { .. }
159                | DataType::Varchar { .. }
160                | DataType::LongVarchar { .. }
161                | DataType::WChar { .. }
162                | DataType::WVarchar { .. }
163                | DataType::WLongVarchar { .. }
164        )
165    }
166
167    fn accepts_binary_data(self) -> bool {
168        matches!(
169            self,
170            DataType::Binary { .. } | DataType::Varbinary { .. } | DataType::LongVarbinary { .. }
171        )
172    }
173
174    fn accepts_numeric_data(self) -> bool {
175        matches!(
176            self,
177            DataType::TinyInt
178                | DataType::SmallInt
179                | DataType::Integer
180                | DataType::BigInt
181                | DataType::Real
182                | DataType::Float { .. }
183                | DataType::Double
184                | DataType::Decimal { .. }
185                | DataType::Numeric { .. }
186        )
187    }
188}
189
190impl Display for OdbcTypeInfo {
191    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
192        f.write_str(sqlx_core::type_info::TypeInfo::name(self))
193    }
194}