@@ -39,9 +39,15 @@ impl Row for OdbcRow {
3939
4040impl ColumnIndex < OdbcRow > for & str {
4141 fn index ( & self , row : & OdbcRow ) -> Result < usize , Error > {
42+ // Try exact match first (for performance)
43+ if let Some ( pos) = row. columns . iter ( ) . position ( |col| col. name == * self ) {
44+ return Ok ( pos) ;
45+ }
46+
47+ // Fall back to case-insensitive match (for databases like Snowflake)
4248 row. columns
4349 . iter ( )
44- . position ( |col| col. name == * self )
50+ . position ( |col| col. name . eq_ignore_ascii_case ( self ) )
4551 . ok_or_else ( || Error :: ColumnNotFound ( ( * self ) . into ( ) ) )
4652 }
4753}
@@ -52,6 +58,115 @@ mod private {
5258 impl Sealed for OdbcRow { }
5359}
5460
61+ #[ cfg( test) ]
62+ mod tests {
63+ use super :: * ;
64+ use crate :: odbc:: { OdbcColumn , OdbcTypeInfo } ;
65+ use crate :: type_info:: TypeInfo ;
66+ use odbc_api:: DataType ;
67+
68+ fn create_test_row ( ) -> OdbcRow {
69+ OdbcRow {
70+ columns : vec ! [
71+ OdbcColumn {
72+ name: "lowercase_col" . to_string( ) ,
73+ type_info: OdbcTypeInfo :: new( DataType :: Integer ) ,
74+ ordinal: 0 ,
75+ } ,
76+ OdbcColumn {
77+ name: "UPPERCASE_COL" . to_string( ) ,
78+ type_info: OdbcTypeInfo :: new( DataType :: Varchar { length: None } ) ,
79+ ordinal: 1 ,
80+ } ,
81+ OdbcColumn {
82+ name: "MixedCase_Col" . to_string( ) ,
83+ type_info: OdbcTypeInfo :: new( DataType :: Double ) ,
84+ ordinal: 2 ,
85+ } ,
86+ ] ,
87+ values : vec ! [
88+ ( OdbcTypeInfo :: new( DataType :: Integer ) , Some ( vec![ 1 , 2 , 3 , 4 ] ) ) ,
89+ (
90+ OdbcTypeInfo :: new( DataType :: Varchar { length: None } ) ,
91+ Some ( b"test" . to_vec( ) ) ,
92+ ) ,
93+ (
94+ OdbcTypeInfo :: new( DataType :: Double ) ,
95+ Some ( vec![ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ) ,
96+ ) ,
97+ ] ,
98+ }
99+ }
100+
101+ #[ test]
102+ fn test_exact_column_match ( ) {
103+ let row = create_test_row ( ) ;
104+
105+ // Exact matches should work
106+ assert_eq ! ( "lowercase_col" . index( & row) . unwrap( ) , 0 ) ;
107+ assert_eq ! ( "UPPERCASE_COL" . index( & row) . unwrap( ) , 1 ) ;
108+ assert_eq ! ( "MixedCase_Col" . index( & row) . unwrap( ) , 2 ) ;
109+ }
110+
111+ #[ test]
112+ fn test_case_insensitive_column_match ( ) {
113+ let row = create_test_row ( ) ;
114+
115+ // Case-insensitive matches should work
116+ assert_eq ! ( "LOWERCASE_COL" . index( & row) . unwrap( ) , 0 ) ;
117+ assert_eq ! ( "lowercase_col" . index( & row) . unwrap( ) , 0 ) ;
118+ assert_eq ! ( "uppercase_col" . index( & row) . unwrap( ) , 1 ) ;
119+ assert_eq ! ( "UPPERCASE_COL" . index( & row) . unwrap( ) , 1 ) ;
120+ assert_eq ! ( "mixedcase_col" . index( & row) . unwrap( ) , 2 ) ;
121+ assert_eq ! ( "MIXEDCASE_COL" . index( & row) . unwrap( ) , 2 ) ;
122+ assert_eq ! ( "MixedCase_Col" . index( & row) . unwrap( ) , 2 ) ;
123+ }
124+
125+ #[ test]
126+ fn test_column_not_found ( ) {
127+ let row = create_test_row ( ) ;
128+
129+ let result = "nonexistent_column" . index ( & row) ;
130+ assert ! ( result. is_err( ) ) ;
131+ if let Err ( Error :: ColumnNotFound ( name) ) = result {
132+ assert_eq ! ( name, "nonexistent_column" ) ;
133+ } else {
134+ panic ! ( "Expected ColumnNotFound error" ) ;
135+ }
136+ }
137+
138+ #[ test]
139+ fn test_try_get_raw ( ) {
140+ let row = create_test_row ( ) ;
141+
142+ // Test accessing by exact name
143+ let value = row. try_get_raw ( "lowercase_col" ) . unwrap ( ) ;
144+ assert ! ( !value. is_null) ;
145+ assert_eq ! ( value. type_info. name( ) , "INTEGER" ) ;
146+
147+ // Test accessing by case-insensitive name
148+ let value = row. try_get_raw ( "LOWERCASE_COL" ) . unwrap ( ) ;
149+ assert ! ( !value. is_null) ;
150+ assert_eq ! ( value. type_info. name( ) , "INTEGER" ) ;
151+
152+ // Test accessing uppercase column with lowercase name
153+ let value = row. try_get_raw ( "uppercase_col" ) . unwrap ( ) ;
154+ assert ! ( !value. is_null) ;
155+ assert_eq ! ( value. type_info. name( ) , "VARCHAR" ) ;
156+ }
157+
158+ #[ test]
159+ fn test_columns_method ( ) {
160+ let row = create_test_row ( ) ;
161+ let columns = row. columns ( ) ;
162+
163+ assert_eq ! ( columns. len( ) , 3 ) ;
164+ assert_eq ! ( columns[ 0 ] . name, "lowercase_col" ) ;
165+ assert_eq ! ( columns[ 1 ] . name, "UPPERCASE_COL" ) ;
166+ assert_eq ! ( columns[ 2 ] . name, "MixedCase_Col" ) ;
167+ }
168+ }
169+
55170#[ cfg( feature = "any" ) ]
56171impl From < OdbcRow > for crate :: any:: AnyRow {
57172 fn from ( row : OdbcRow ) -> Self {
0 commit comments