@@ -16,7 +16,7 @@ use either::Either;
1616#[ allow( unused_imports) ]
1717use odbc_api:: handles:: Statement as OdbcStatementTrait ;
1818use odbc_api:: handles:: StatementImpl ;
19- use odbc_api:: { Cursor , CursorRow , IntoParameter , Preallocated , ResultSetMetadata } ;
19+ use odbc_api:: { Cursor , CursorRow , IntoParameter , Nullable , Preallocated , ResultSetMetadata } ;
2020
2121// Type aliases for commonly used types
2222type OdbcConnection = odbc_api:: Connection < ' static > ;
@@ -562,7 +562,7 @@ where
562562 OdbcColumn {
563563 name : decode_column_name ( cd. name , index) ,
564564 type_info : OdbcTypeInfo :: new ( cd. data_type ) ,
565- ordinal : ( index - 1 ) as usize ,
565+ ordinal : usize :: from ( index. checked_sub ( 1 ) . unwrap ( ) ) ,
566566 }
567567}
568568
@@ -581,7 +581,7 @@ where
581581 let values = collect_row_values ( & mut row, columns) ?;
582582 let row_data = OdbcRow {
583583 columns : columns. to_vec ( ) ,
584- values,
584+ values : values . into_iter ( ) . map ( | ( _ , value ) | value ) . collect ( ) ,
585585 } ;
586586
587587 if send_row ( tx, row_data) . is_err ( ) {
@@ -601,7 +601,7 @@ where
601601fn collect_row_values (
602602 row : & mut CursorRow < ' _ > ,
603603 columns : & [ OdbcColumn ] ,
604- ) -> Result < Vec < ( OdbcTypeInfo , Option < Vec < u8 > > ) > , Error > {
604+ ) -> Result < Vec < ( OdbcTypeInfo , crate :: odbc :: OdbcValue ) > , Error > {
605605 columns
606606 . iter ( )
607607 . enumerate ( )
@@ -613,37 +613,155 @@ fn collect_column_value(
613613 row : & mut CursorRow < ' _ > ,
614614 index : usize ,
615615 column : & OdbcColumn ,
616- ) -> Result < ( OdbcTypeInfo , Option < Vec < u8 > > ) , Error > {
616+ ) -> Result < ( OdbcTypeInfo , crate :: odbc:: OdbcValue ) , Error > {
617+ use odbc_api:: DataType ;
618+
617619 let col_idx = ( index + 1 ) as u16 ;
620+ let type_info = column. type_info . clone ( ) ;
621+ let data_type = type_info. data_type ( ) ;
622+
623+ // Extract value based on data type
624+ let value = match data_type {
625+ // Integer types
626+ DataType :: TinyInt
627+ | DataType :: SmallInt
628+ | DataType :: Integer
629+ | DataType :: BigInt
630+ | DataType :: Bit => extract_int ( row, col_idx, & type_info) ?,
631+
632+ // Floating point types
633+ DataType :: Real => extract_float :: < f32 > ( row, col_idx, & type_info) ?,
634+ DataType :: Float { .. } | DataType :: Double => {
635+ extract_float :: < f64 > ( row, col_idx, & type_info) ?
636+ }
637+
638+ // String types
639+ DataType :: Char { .. }
640+ | DataType :: Varchar { .. }
641+ | DataType :: LongVarchar { .. }
642+ | DataType :: WChar { .. }
643+ | DataType :: WVarchar { .. }
644+ | DataType :: WLongVarchar { .. }
645+ | DataType :: Date
646+ | DataType :: Time { .. }
647+ | DataType :: Timestamp { .. }
648+ | DataType :: Decimal { .. }
649+ | DataType :: Numeric { .. } => extract_text ( row, col_idx, & type_info) ?,
650+
651+ // Binary types
652+ DataType :: Binary { .. } | DataType :: Varbinary { .. } | DataType :: LongVarbinary { .. } => {
653+ extract_binary ( row, col_idx, & type_info) ?
654+ }
618655
619- // Try text first
620- match try_get_text ( row, col_idx) {
621- Ok ( value) => Ok ( ( column. type_info . clone ( ) , value) ) ,
622- Err ( _) => {
623- // Fall back to binary
624- match try_get_binary ( row, col_idx) {
625- Ok ( value) => Ok ( ( column. type_info . clone ( ) , value) ) ,
626- Err ( e) => Err ( Error :: from ( e) ) ,
656+ // Unknown types - try text first, fall back to binary
657+ DataType :: Unknown | DataType :: Other { .. } => {
658+ match extract_text ( row, col_idx, & type_info) {
659+ Ok ( v) => v,
660+ Err ( _) => extract_binary ( row, col_idx, & type_info) ?,
627661 }
628662 }
629- }
663+ } ;
664+
665+ Ok ( ( type_info, value) )
666+ }
667+
668+ fn extract_int (
669+ row : & mut CursorRow < ' _ > ,
670+ col_idx : u16 ,
671+ type_info : & OdbcTypeInfo ,
672+ ) -> Result < crate :: odbc:: OdbcValue , Error > {
673+ let mut nullable = Nullable :: < i64 > :: null ( ) ;
674+ row. get_data ( col_idx, & mut nullable) ?;
675+
676+ let ( is_null, int) = match nullable. into_opt ( ) {
677+ None => ( true , None ) ,
678+ Some ( v) => ( false , Some ( v. into ( ) ) ) ,
679+ } ;
680+
681+ Ok ( crate :: odbc:: OdbcValue {
682+ type_info : type_info. clone ( ) ,
683+ is_null,
684+ text : None ,
685+ blob : None ,
686+ int,
687+ float : None ,
688+ } )
689+ }
690+
691+ fn extract_float < T > (
692+ row : & mut CursorRow < ' _ > ,
693+ col_idx : u16 ,
694+ type_info : & OdbcTypeInfo ,
695+ ) -> Result < crate :: odbc:: OdbcValue , Error >
696+ where
697+ T : Into < f64 > + Default ,
698+ odbc_api:: Nullable < T > : odbc_api:: parameter:: CElement + odbc_api:: handles:: CDataMut ,
699+ {
700+ let mut nullable = Nullable :: < T > :: null ( ) ;
701+ row. get_data ( col_idx, & mut nullable) ?;
702+
703+ let ( is_null, float) = match nullable. into_opt ( ) {
704+ None => ( true , None ) ,
705+ Some ( v) => ( false , Some ( v. into ( ) ) ) ,
706+ } ;
707+
708+ Ok ( crate :: odbc:: OdbcValue {
709+ type_info : type_info. clone ( ) ,
710+ is_null,
711+ text : None ,
712+ blob : None ,
713+ int : None ,
714+ float,
715+ } )
630716}
631717
632- fn try_get_text ( row : & mut CursorRow < ' _ > , col_idx : u16 ) -> Result < Option < Vec < u8 > > , odbc_api:: Error > {
718+ fn extract_text (
719+ row : & mut CursorRow < ' _ > ,
720+ col_idx : u16 ,
721+ type_info : & OdbcTypeInfo ,
722+ ) -> Result < crate :: odbc:: OdbcValue , Error > {
633723 let mut buf = Vec :: new ( ) ;
634- match row. get_text ( col_idx, & mut buf) ? {
635- true => Ok ( Some ( buf) ) ,
636- false => Ok ( None ) ,
637- }
724+ let is_some = row. get_text ( col_idx, & mut buf) ?;
725+
726+ let ( is_null, text) = if !is_some {
727+ ( true , None )
728+ } else {
729+ match String :: from_utf8 ( buf) {
730+ Ok ( s) => ( false , Some ( s) ) ,
731+ Err ( e) => return Err ( Error :: Decode ( e. into ( ) ) ) ,
732+ }
733+ } ;
734+
735+ Ok ( crate :: odbc:: OdbcValue {
736+ type_info : type_info. clone ( ) ,
737+ is_null,
738+ text,
739+ blob : None ,
740+ int : None ,
741+ float : None ,
742+ } )
638743}
639744
640- fn try_get_binary (
745+ fn extract_binary (
641746 row : & mut CursorRow < ' _ > ,
642747 col_idx : u16 ,
643- ) -> Result < Option < Vec < u8 > > , odbc_api:: Error > {
748+ type_info : & OdbcTypeInfo ,
749+ ) -> Result < crate :: odbc:: OdbcValue , Error > {
644750 let mut buf = Vec :: new ( ) ;
645- match row. get_binary ( col_idx, & mut buf) ? {
646- true => Ok ( Some ( buf) ) ,
647- false => Ok ( None ) ,
648- }
751+ let is_some = row. get_binary ( col_idx, & mut buf) ?;
752+
753+ let ( is_null, blob) = if !is_some {
754+ ( true , None )
755+ } else {
756+ ( false , Some ( buf) )
757+ } ;
758+
759+ Ok ( crate :: odbc:: OdbcValue {
760+ type_info : type_info. clone ( ) ,
761+ is_null,
762+ text : None ,
763+ blob,
764+ int : None ,
765+ float : None ,
766+ } )
649767}
0 commit comments