diff --git a/rsfbclient-core/src/row.rs b/rsfbclient-core/src/row.rs index 02fa4a8..61b9fd7 100644 --- a/rsfbclient-core/src/row.rs +++ b/rsfbclient-core/src/row.rs @@ -37,12 +37,17 @@ impl Row { #[derive(Debug, Clone)] pub struct Column { pub value: SqlType, + pub raw_type: u32, pub name: String, } impl Column { - pub fn new(name: String, value: SqlType) -> Self { - Column { name, value } + pub fn new(name: String, raw_type: u32, value: SqlType) -> Self { + Column { + name, + raw_type, + value, + } } } diff --git a/rsfbclient-native/src/row.rs b/rsfbclient-native/src/row.rs index 6e8adf9..98900ad 100644 --- a/rsfbclient-native/src/row.rs +++ b/rsfbclient-native/src/row.rs @@ -55,6 +55,8 @@ pub struct ColumnBuffer { /// Column name col_name: String, + + raw_type: i16, } impl ColumnBuffer { @@ -154,6 +156,7 @@ impl ColumnBuffer { buffer, nullind, col_name, + raw_type: sqltype, }) } @@ -166,7 +169,11 @@ impl ColumnBuffer { charset: &Charset, ) -> Result { if *self.nullind != 0 { - return Ok(Column::new(self.col_name.clone(), SqlType::Null)); + return Ok(Column::new( + self.col_name.clone(), + self.raw_type as u32, + SqlType::Null, + )); } let col_type = match &self.buffer { @@ -185,7 +192,11 @@ impl ColumnBuffer { Boolean(b) => SqlType::Boolean(**b != 0), }; - Ok(Column::new(self.col_name.clone(), col_type)) + Ok(Column::new( + self.col_name.clone(), + self.raw_type as u32, + col_type, + )) } } diff --git a/rsfbclient-rust/src/wire.rs b/rsfbclient-rust/src/wire.rs index 6075d7c..21a1964 100644 --- a/rsfbclient-rust/src/wire.rs +++ b/rsfbclient-rust/src/wire.rs @@ -586,18 +586,19 @@ pub fn parse_sql_response( let mut data = Vec::with_capacity(xsqlda.len()); for (col_index, var) in xsqlda.iter().enumerate() { + // Remove nullable type indicator + let sqltype = var.sqltype as u32 & (!1); + if version >= ProtocolVersion::V13 && read_null(resp, col_index)? { // There is no data in protocol 13 if null, so just continue data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))); continue; } - // Remove nullable type indicator - let sqltype = var.sqltype as u32 & (!1); - match sqltype { ibase::SQL_VARYING => { let d = resp.get_wire_bytes()?; @@ -606,11 +607,13 @@ pub fn parse_sql_response( if null { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))) } else { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Text(charset.decode(&d[..])?), ))) } @@ -623,11 +626,13 @@ pub fn parse_sql_response( if null { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))) } else { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Integer(i), ))) } @@ -640,11 +645,13 @@ pub fn parse_sql_response( if null { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))) } else { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Floating(f), ))) } @@ -660,11 +667,13 @@ pub fn parse_sql_response( if null { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))) } else { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Timestamp(rsfbclient_core::date_time::decode_timestamp(ts)), ))) } @@ -677,6 +686,7 @@ pub fn parse_sql_response( if null { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))) } else { @@ -697,11 +707,13 @@ pub fn parse_sql_response( if null { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Null, ))) } else { data.push(ParsedColumn::Complete(Column::new( var.alias_name.clone(), + sqltype, SqlType::Boolean(b), ))) } @@ -767,6 +779,7 @@ impl ParsedColumn { Column::new( col_name, + ibase::SQL_BLOB, if binary { SqlType::Binary(data) } else { diff --git a/src/tests/row.rs b/src/tests/row.rs index dcde821..3d69537 100644 --- a/src/tests/row.rs +++ b/src/tests/row.rs @@ -411,6 +411,22 @@ mk_tests_default! { assert_eq!(res, col); } + Ok(()) + } + #[test] + fn raw_type () -> Result<(), FbError> { + let mut conn = cbuilder().connect()?; + + let row: Row = conn + .query_first( + "select cast('firebird' as varchar(8)), cast('firebird' as char(8)) from rdb$database", + (), + )? + .unwrap(); + assert_eq!(2, row.cols.len()); + + assert_eq!(448, row.cols.first().unwrap().raw_type); + Ok(()) } }