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 `CHAR` type information.
55    pub const fn char(length: Option<std::num::NonZeroUsize>) -> Self {
56        Self::new(DataType::Char { length })
57    }
58
59    /// Creates `FLOAT` type information.
60    pub const fn float(precision: usize) -> Self {
61        Self::new(DataType::Float { precision })
62    }
63
64    /// Creates `TIME` type information.
65    pub const fn time(precision: i16) -> Self {
66        Self::new(DataType::Time { precision })
67    }
68
69    /// Creates `TIMESTAMP` type information.
70    pub const fn timestamp(precision: i16) -> Self {
71        Self::new(DataType::Timestamp { precision })
72    }
73
74    /// Creates `VARCHAR` type information.
75    pub const fn varchar(length: Option<std::num::NonZeroUsize>) -> Self {
76        Self::new(DataType::Varchar { length })
77    }
78
79    /// Creates `VARBINARY` type information.
80    pub const fn varbinary(length: Option<std::num::NonZeroUsize>) -> Self {
81        Self::new(DataType::Varbinary { length })
82    }
83
84    /// Creates `DECIMAL` type information.
85    pub const fn decimal(precision: usize, scale: i16) -> Self {
86        Self::new(DataType::Decimal { precision, scale })
87    }
88
89    /// Creates `NUMERIC` type information.
90    pub const fn numeric(precision: usize, scale: i16) -> Self {
91        Self::new(DataType::Numeric { precision, scale })
92    }
93}
94
95impl sqlx_core::type_info::TypeInfo for OdbcTypeInfo {
96    fn is_null(&self) -> bool {
97        false
98    }
99
100    fn name(&self) -> &str {
101        match self.data_type {
102            DataType::BigInt => "BIGINT",
103            DataType::Binary { .. } => "BINARY",
104            DataType::Bit => "BIT",
105            DataType::Char { .. } => "CHAR",
106            DataType::Date => "DATE",
107            DataType::Decimal { .. } => "DECIMAL",
108            DataType::Double => "DOUBLE",
109            DataType::Float { .. } => "FLOAT",
110            DataType::Integer => "INTEGER",
111            DataType::LongVarbinary { .. } => "LONGVARBINARY",
112            DataType::LongVarchar { .. } => "LONGVARCHAR",
113            DataType::Numeric { .. } => "NUMERIC",
114            DataType::Real => "REAL",
115            DataType::SmallInt => "SMALLINT",
116            DataType::Time { .. } => "TIME",
117            DataType::Timestamp { .. } => "TIMESTAMP",
118            DataType::TinyInt => "TINYINT",
119            DataType::Varbinary { .. } => "VARBINARY",
120            DataType::Varchar { .. } => "VARCHAR",
121            DataType::WChar { .. } => "WCHAR",
122            DataType::WLongVarchar { .. } => "WLONGVARCHAR",
123            DataType::WVarchar { .. } => "WVARCHAR",
124            DataType::Unknown => "UNKNOWN",
125            DataType::Other { .. } => "OTHER",
126        }
127    }
128}
129
130/// Helper predicates for `odbc-api` data type groups.
131pub trait DataTypeExt {
132    /// Returns the canonical display name for this type.
133    fn name(self) -> &'static str;
134
135    /// Returns whether this type carries character data.
136    fn accepts_character_data(self) -> bool;
137
138    /// Returns whether this type carries binary data.
139    fn accepts_binary_data(self) -> bool;
140
141    /// Returns whether this type carries numeric data.
142    fn accepts_numeric_data(self) -> bool;
143
144    /// Returns whether this type carries date or time data.
145    fn accepts_datetime_data(self) -> bool;
146}
147
148impl DataTypeExt for DataType {
149    fn name(self) -> &'static str {
150        match self {
151            DataType::BigInt => "BIGINT",
152            DataType::Binary { .. } => "BINARY",
153            DataType::Bit => "BIT",
154            DataType::Char { .. } => "CHAR",
155            DataType::Date => "DATE",
156            DataType::Decimal { .. } => "DECIMAL",
157            DataType::Double => "DOUBLE",
158            DataType::Float { .. } => "FLOAT",
159            DataType::Integer => "INTEGER",
160            DataType::LongVarbinary { .. } => "LONGVARBINARY",
161            DataType::LongVarchar { .. } => "LONGVARCHAR",
162            DataType::Numeric { .. } => "NUMERIC",
163            DataType::Real => "REAL",
164            DataType::SmallInt => "SMALLINT",
165            DataType::Time { .. } => "TIME",
166            DataType::Timestamp { .. } => "TIMESTAMP",
167            DataType::TinyInt => "TINYINT",
168            DataType::Varbinary { .. } => "VARBINARY",
169            DataType::Varchar { .. } => "VARCHAR",
170            DataType::WChar { .. } => "WCHAR",
171            DataType::WLongVarchar { .. } => "WLONGVARCHAR",
172            DataType::WVarchar { .. } => "WVARCHAR",
173            DataType::Unknown => "UNKNOWN",
174            DataType::Other { .. } => "OTHER",
175        }
176    }
177
178    fn accepts_character_data(self) -> bool {
179        matches!(
180            self,
181            DataType::Char { .. }
182                | DataType::Varchar { .. }
183                | DataType::LongVarchar { .. }
184                | DataType::WChar { .. }
185                | DataType::WVarchar { .. }
186                | DataType::WLongVarchar { .. }
187        )
188    }
189
190    fn accepts_binary_data(self) -> bool {
191        matches!(
192            self,
193            DataType::Binary { .. } | DataType::Varbinary { .. } | DataType::LongVarbinary { .. }
194        )
195    }
196
197    fn accepts_numeric_data(self) -> bool {
198        matches!(
199            self,
200            DataType::TinyInt
201                | DataType::SmallInt
202                | DataType::Integer
203                | DataType::BigInt
204                | DataType::Real
205                | DataType::Float { .. }
206                | DataType::Double
207                | DataType::Decimal { .. }
208                | DataType::Numeric { .. }
209        )
210    }
211
212    fn accepts_datetime_data(self) -> bool {
213        matches!(
214            self,
215            DataType::Date | DataType::Time { .. } | DataType::Timestamp { .. }
216        )
217    }
218}
219
220impl Display for OdbcTypeInfo {
221    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
222        f.write_str(sqlx_core::type_info::TypeInfo::name(self))
223    }
224}