Skip to content

Commit c8ff45a

Browse files
committed
replace the OdbcDataType enum with direct usage of the DataType from the odbc_api crate
updates the OdbcTypeInfo structure to accommodate this change, simplifying the type information implementations for various data types. Additionally, it enhances the compatibility checks for ODBC types in the Type trait implementations, ensuring better integration with the ODBC API.
1 parent 0f5d72b commit c8ff45a

File tree

7 files changed

+214
-256
lines changed

7 files changed

+214
-256
lines changed

sqlx-core/src/odbc/connection/worker.rs

Lines changed: 14 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -6,73 +6,12 @@ use futures_intrusive::sync::Mutex;
66

77
use crate::error::Error;
88
use crate::odbc::{
9-
OdbcArgumentValue, OdbcColumn, OdbcConnectOptions, OdbcQueryResult, OdbcRow, OdbcTypeInfo, OdbcDataType,
9+
OdbcArgumentValue, OdbcColumn, OdbcConnectOptions, OdbcQueryResult, OdbcRow, OdbcTypeInfo,
1010
};
1111
#[allow(unused_imports)]
1212
use crate::row::Row as SqlxRow;
1313
use either::Either;
14-
use odbc_api::{Cursor, CursorRow, IntoParameter, ResultSetMetadata, DataType};
15-
16-
/// Map ODBC API DataType to our OdbcDataType
17-
fn map_odbc_data_type(data_type: DataType) -> OdbcTypeInfo {
18-
let odbc_data_type = match data_type {
19-
DataType::BigInt => OdbcDataType::BigInt,
20-
DataType::Binary { .. } => OdbcDataType::Binary,
21-
DataType::Bit => OdbcDataType::Bit,
22-
DataType::Char { .. } => OdbcDataType::Char,
23-
DataType::Date => OdbcDataType::Date,
24-
DataType::Decimal { .. } => OdbcDataType::Decimal,
25-
DataType::Double => OdbcDataType::Double,
26-
DataType::Float { .. } => OdbcDataType::Float,
27-
DataType::Integer => OdbcDataType::Integer,
28-
DataType::LongVarbinary { .. } => OdbcDataType::LongVarbinary,
29-
DataType::LongVarchar { .. } => OdbcDataType::LongVarchar,
30-
DataType::Numeric { .. } => OdbcDataType::Numeric,
31-
DataType::Real => OdbcDataType::Real,
32-
DataType::SmallInt => OdbcDataType::SmallInt,
33-
DataType::Time { .. } => OdbcDataType::Time,
34-
DataType::Timestamp { .. } => OdbcDataType::Timestamp,
35-
DataType::TinyInt => OdbcDataType::TinyInt,
36-
DataType::Varbinary { .. } => OdbcDataType::Varbinary,
37-
DataType::Varchar { .. } => OdbcDataType::Varchar,
38-
DataType::WChar { .. } => OdbcDataType::WChar,
39-
DataType::WLongVarchar { .. } => OdbcDataType::WLongVarchar,
40-
DataType::WVarchar { .. } => OdbcDataType::WVarchar,
41-
DataType::Other { .. } => OdbcDataType::Unknown,
42-
DataType::Unknown => OdbcDataType::Unknown,
43-
};
44-
45-
// Extract precision, scale, and length information where available
46-
match data_type {
47-
DataType::Decimal { precision, scale } => {
48-
OdbcTypeInfo::with_precision_and_scale(odbc_data_type, precision as u32, scale as u16)
49-
},
50-
DataType::Numeric { precision, scale } => {
51-
OdbcTypeInfo::with_precision_and_scale(odbc_data_type, precision as u32, scale as u16)
52-
},
53-
DataType::Char { length } | DataType::Varchar { length } | DataType::WChar { length } | DataType::WVarchar { length } => {
54-
if let Some(len) = length {
55-
OdbcTypeInfo::with_length(odbc_data_type, len.get() as u32)
56-
} else {
57-
OdbcTypeInfo::new(odbc_data_type)
58-
}
59-
},
60-
DataType::Binary { length } | DataType::Varbinary { length } => {
61-
if let Some(len) = length {
62-
OdbcTypeInfo::with_length(odbc_data_type, len.get() as u32)
63-
} else {
64-
OdbcTypeInfo::new(odbc_data_type)
65-
}
66-
},
67-
DataType::Float { precision } => {
68-
OdbcTypeInfo::with_precision(odbc_data_type, precision as u32)
69-
},
70-
DataType::Time { precision } | DataType::Timestamp { precision } => {
71-
OdbcTypeInfo::with_precision(odbc_data_type, precision as u32)
72-
},
73-
_ => OdbcTypeInfo::new(odbc_data_type),
74-
}
75-
}
14+
use odbc_api::{Cursor, CursorRow, IntoParameter, ResultSetMetadata};
7615

7716
#[derive(Debug)]
7817
pub(crate) struct ConnectionWorker {
@@ -384,7 +323,7 @@ where
384323
let name = String::from_utf8(cd.name).unwrap_or_else(|_| format!("col{}", i - 1));
385324
columns.push(OdbcColumn {
386325
name,
387-
type_info: map_odbc_data_type(cd.data_type),
326+
type_info: OdbcTypeInfo::new(cd.data_type),
388327
ordinal: (i - 1) as usize,
389328
});
390329
}
@@ -403,7 +342,7 @@ where
403342
loop {
404343
match cursor.next_row() {
405344
Ok(Some(mut row)) => {
406-
let values = collect_row_values(&mut row, columns.len())?;
345+
let values = collect_row_values(&mut row, columns)?;
407346
let _ = tx.send(Ok(Either::Right(OdbcRow {
408347
columns: columns.to_vec(),
409348
values,
@@ -418,31 +357,20 @@ where
418357

419358
fn collect_row_values(
420359
row: &mut CursorRow<'_>,
421-
num_cols: usize,
360+
columns: &[OdbcColumn],
422361
) -> Result<Vec<(OdbcTypeInfo, Option<Vec<u8>>)>, Error> {
423-
let mut values: Vec<(OdbcTypeInfo, Option<Vec<u8>>)> = Vec::with_capacity(num_cols);
424-
for i in 1..=num_cols {
362+
let mut values: Vec<(OdbcTypeInfo, Option<Vec<u8>>)> = Vec::with_capacity(columns.len());
363+
for (i, column) in columns.iter().enumerate() {
364+
let col_idx = (i + 1) as u16;
425365
let mut buf = Vec::new();
426-
match row.get_text(i as u16, &mut buf) {
427-
Ok(true) => values.push((
428-
OdbcTypeInfo::VARCHAR,
429-
Some(buf),
430-
)),
431-
Ok(false) => values.push((
432-
OdbcTypeInfo::VARCHAR,
433-
None,
434-
)),
366+
match row.get_text(col_idx, &mut buf) {
367+
Ok(true) => values.push((column.type_info.clone(), Some(buf))),
368+
Ok(false) => values.push((column.type_info.clone(), None)),
435369
Err(_) => {
436370
let mut bin = Vec::new();
437-
match row.get_binary(i as u16, &mut bin) {
438-
Ok(true) => values.push((
439-
OdbcTypeInfo::VARBINARY,
440-
Some(bin),
441-
)),
442-
Ok(false) => values.push((
443-
OdbcTypeInfo::VARBINARY,
444-
None,
445-
)),
371+
match row.get_binary(col_idx, &mut bin) {
372+
Ok(true) => values.push((column.type_info.clone(), Some(bin))),
373+
Ok(false) => values.push((column.type_info.clone(), None)),
446374
Err(e) => return Err(Error::from(e)),
447375
}
448376
}

sqlx-core/src/odbc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub use query_result::OdbcQueryResult;
2525
pub use row::OdbcRow;
2626
pub use statement::OdbcStatement;
2727
pub use transaction::OdbcTransactionManager;
28-
pub use type_info::{OdbcTypeInfo, OdbcDataType};
28+
pub use type_info::{DataTypeExt, OdbcTypeInfo};
2929
pub use value::{OdbcValue, OdbcValueRef};
3030

3131
/// An alias for [`Pool`][crate::pool::Pool], specialized for ODBC.

sqlx-core/src/odbc/type.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
use crate::odbc::{Odbc, OdbcTypeInfo, OdbcDataType};
1+
use crate::odbc::{DataTypeExt, Odbc, OdbcTypeInfo};
22
use crate::types::Type;
3+
use odbc_api::DataType;
34

45
impl Type<Odbc> for i32 {
56
fn type_info() -> OdbcTypeInfo {
67
OdbcTypeInfo::INTEGER
78
}
89
fn compatible(ty: &OdbcTypeInfo) -> bool {
9-
matches!(ty.data_type(), OdbcDataType::Integer | OdbcDataType::SmallInt | OdbcDataType::TinyInt)
10+
matches!(
11+
ty.data_type(),
12+
DataType::Integer | DataType::SmallInt | DataType::TinyInt | DataType::BigInt
13+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
1014
}
1115
}
1216

@@ -15,7 +19,15 @@ impl Type<Odbc> for i64 {
1519
OdbcTypeInfo::BIGINT
1620
}
1721
fn compatible(ty: &OdbcTypeInfo) -> bool {
18-
matches!(ty.data_type(), OdbcDataType::BigInt | OdbcDataType::Integer)
22+
matches!(
23+
ty.data_type(),
24+
DataType::BigInt
25+
| DataType::Integer
26+
| DataType::SmallInt
27+
| DataType::TinyInt
28+
| DataType::Numeric { .. }
29+
| DataType::Decimal { .. }
30+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
1931
}
2032
}
2133

@@ -24,43 +36,65 @@ impl Type<Odbc> for f64 {
2436
OdbcTypeInfo::DOUBLE
2537
}
2638
fn compatible(ty: &OdbcTypeInfo) -> bool {
27-
matches!(ty.data_type(), OdbcDataType::Double | OdbcDataType::Float | OdbcDataType::Real)
39+
matches!(
40+
ty.data_type(),
41+
DataType::Double
42+
| DataType::Float { .. }
43+
| DataType::Real
44+
| DataType::Numeric { .. }
45+
| DataType::Decimal { .. }
46+
| DataType::Integer
47+
| DataType::BigInt
48+
| DataType::SmallInt
49+
| DataType::TinyInt
50+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
2851
}
2952
}
3053

3154
impl Type<Odbc> for f32 {
3255
fn type_info() -> OdbcTypeInfo {
33-
OdbcTypeInfo::FLOAT
56+
OdbcTypeInfo::float(24) // Standard float precision
3457
}
3558
fn compatible(ty: &OdbcTypeInfo) -> bool {
36-
matches!(ty.data_type(), OdbcDataType::Float | OdbcDataType::Real)
59+
matches!(
60+
ty.data_type(),
61+
DataType::Float { .. }
62+
| DataType::Real
63+
| DataType::Double
64+
| DataType::Numeric { .. }
65+
| DataType::Decimal { .. }
66+
| DataType::Integer
67+
| DataType::BigInt
68+
| DataType::SmallInt
69+
| DataType::TinyInt
70+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
3771
}
3872
}
3973

4074
impl Type<Odbc> for String {
4175
fn type_info() -> OdbcTypeInfo {
42-
OdbcTypeInfo::VARCHAR
76+
OdbcTypeInfo::varchar(None)
4377
}
4478
fn compatible(ty: &OdbcTypeInfo) -> bool {
45-
ty.data_type().is_character_type()
79+
ty.data_type().accepts_character_data()
4680
}
4781
}
4882

4983
impl Type<Odbc> for &str {
5084
fn type_info() -> OdbcTypeInfo {
51-
OdbcTypeInfo::VARCHAR
85+
OdbcTypeInfo::varchar(None)
5286
}
5387
fn compatible(ty: &OdbcTypeInfo) -> bool {
54-
ty.data_type().is_character_type()
88+
ty.data_type().accepts_character_data()
5589
}
5690
}
5791

5892
impl Type<Odbc> for Vec<u8> {
5993
fn type_info() -> OdbcTypeInfo {
60-
OdbcTypeInfo::VARBINARY
94+
OdbcTypeInfo::varbinary(None)
6195
}
6296
fn compatible(ty: &OdbcTypeInfo) -> bool {
63-
ty.data_type().is_binary_type()
97+
ty.data_type().accepts_binary_data()
6498
}
6599
}
66100

@@ -69,7 +103,10 @@ impl Type<Odbc> for i16 {
69103
OdbcTypeInfo::SMALLINT
70104
}
71105
fn compatible(ty: &OdbcTypeInfo) -> bool {
72-
matches!(ty.data_type(), OdbcDataType::SmallInt | OdbcDataType::TinyInt)
106+
matches!(
107+
ty.data_type(),
108+
DataType::SmallInt | DataType::TinyInt | DataType::Integer | DataType::BigInt
109+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
73110
}
74111
}
75112

@@ -78,7 +115,10 @@ impl Type<Odbc> for i8 {
78115
OdbcTypeInfo::TINYINT
79116
}
80117
fn compatible(ty: &OdbcTypeInfo) -> bool {
81-
matches!(ty.data_type(), OdbcDataType::TinyInt)
118+
matches!(
119+
ty.data_type(),
120+
DataType::TinyInt | DataType::SmallInt | DataType::Integer | DataType::BigInt
121+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
82122
}
83123
}
84124

@@ -87,9 +127,11 @@ impl Type<Odbc> for bool {
87127
OdbcTypeInfo::BIT
88128
}
89129
fn compatible(ty: &OdbcTypeInfo) -> bool {
90-
matches!(ty.data_type(), OdbcDataType::Bit | OdbcDataType::TinyInt)
130+
matches!(
131+
ty.data_type(),
132+
DataType::Bit | DataType::TinyInt | DataType::SmallInt | DataType::Integer
133+
) || ty.data_type().accepts_character_data() // Allow parsing from strings
91134
}
92135
}
93136

94137
// Option<T> blanket impl is provided in core types; do not re-implement here.
95-

0 commit comments

Comments
 (0)