@@ -228,3 +228,199 @@ async fn it_binds_null_string_parameter() -> anyhow::Result<()> {
228228 assert ! ( b. is_null( ) ) ;
229229 Ok ( ( ) )
230230}
231+
232+ #[ tokio:: test]
233+ async fn it_handles_different_integer_types ( ) -> anyhow:: Result < ( ) > {
234+ let mut conn = new :: < Odbc > ( ) . await ?;
235+
236+ // Test various integer sizes
237+ let mut s = conn. fetch (
238+ "SELECT 127 AS tiny, 32767 AS small, 2147483647 AS regular, 9223372036854775807 AS big" ,
239+ ) ;
240+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
241+
242+ let tiny = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < i8 > ( ) ;
243+ let small = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < i16 > ( ) ;
244+ let regular = row. try_get_raw ( 2 ) ?. to_owned ( ) . decode :: < i32 > ( ) ;
245+ let big = row. try_get_raw ( 3 ) ?. to_owned ( ) . decode :: < i64 > ( ) ;
246+
247+ assert_eq ! ( tiny, 127 ) ;
248+ assert_eq ! ( small, 32767 ) ;
249+ assert_eq ! ( regular, 2147483647 ) ;
250+ assert_eq ! ( big, 9223372036854775807 ) ;
251+ Ok ( ( ) )
252+ }
253+
254+ #[ tokio:: test]
255+ async fn it_handles_negative_integers ( ) -> anyhow:: Result < ( ) > {
256+ let mut conn = new :: < Odbc > ( ) . await ?;
257+
258+ let mut s = conn. fetch (
259+ "SELECT -128 AS tiny, -32768 AS small, -2147483648 AS regular, -9223372036854775808 AS big" ,
260+ ) ;
261+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
262+
263+ let tiny = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < i8 > ( ) ;
264+ let small = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < i16 > ( ) ;
265+ let regular = row. try_get_raw ( 2 ) ?. to_owned ( ) . decode :: < i32 > ( ) ;
266+ let big = row. try_get_raw ( 3 ) ?. to_owned ( ) . decode :: < i64 > ( ) ;
267+
268+ assert_eq ! ( tiny, -128 ) ;
269+ assert_eq ! ( small, -32768 ) ;
270+ assert_eq ! ( regular, -2147483648 ) ;
271+ assert_eq ! ( big, -9223372036854775808 ) ;
272+ Ok ( ( ) )
273+ }
274+
275+ #[ tokio:: test]
276+ async fn it_handles_different_float_types ( ) -> anyhow:: Result < ( ) > {
277+ let mut conn = new :: < Odbc > ( ) . await ?;
278+
279+ let sql = format ! (
280+ "SELECT {} AS f32_val, {} AS f64_val, 1.23456789 AS precise_val" ,
281+ std:: f32 :: consts:: PI ,
282+ std:: f64 :: consts:: E
283+ ) ;
284+ let mut s = conn. fetch ( sql. as_str ( ) ) ;
285+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
286+
287+ let f32_val = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < f32 > ( ) ;
288+ let f64_val = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < f64 > ( ) ;
289+ let precise_val = row. try_get_raw ( 2 ) ?. to_owned ( ) . decode :: < f64 > ( ) ;
290+
291+ assert ! ( ( f32_val - std:: f32 :: consts:: PI ) . abs( ) < 1e-5 ) ;
292+ assert ! ( ( f64_val - std:: f64 :: consts:: E ) . abs( ) < 1e-10 ) ;
293+ assert ! ( ( precise_val - 1.23456789 ) . abs( ) < 1e-8 ) ;
294+ Ok ( ( ) )
295+ }
296+
297+ #[ tokio:: test]
298+ async fn it_handles_boolean_values ( ) -> anyhow:: Result < ( ) > {
299+ let mut conn = new :: < Odbc > ( ) . await ?;
300+
301+ // Test boolean-like values - some databases represent booleans as 1/0
302+ let mut s = conn. fetch ( "SELECT 1 AS true_val, 0 AS false_val" ) ;
303+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
304+
305+ let true_val = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < bool > ( ) ;
306+ let false_val = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < bool > ( ) ;
307+
308+ assert ! ( true_val) ;
309+ assert ! ( !false_val) ;
310+ Ok ( ( ) )
311+ }
312+
313+ #[ tokio:: test]
314+ async fn it_handles_zero_and_special_numbers ( ) -> anyhow:: Result < ( ) > {
315+ let mut conn = new :: < Odbc > ( ) . await ?;
316+
317+ let mut s = conn. fetch ( "SELECT 0 AS zero, 0.0 AS zero_float" ) ;
318+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
319+
320+ let zero = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < i32 > ( ) ;
321+ let zero_float = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < f64 > ( ) ;
322+
323+ assert_eq ! ( zero, 0 ) ;
324+ assert_eq ! ( zero_float, 0.0 ) ;
325+ Ok ( ( ) )
326+ }
327+
328+ #[ tokio:: test]
329+ async fn it_handles_string_variations ( ) -> anyhow:: Result < ( ) > {
330+ let mut conn = new :: < Odbc > ( ) . await ?;
331+
332+ let mut s = conn. fetch ( "SELECT '' AS empty, ' ' AS space, 'Hello, World!' AS greeting, 'Unicode: 🦀 Rust' AS unicode" ) ;
333+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
334+
335+ let empty = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < String > ( ) ;
336+ let space = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < String > ( ) ;
337+ let greeting = row. try_get_raw ( 2 ) ?. to_owned ( ) . decode :: < String > ( ) ;
338+ let unicode = row. try_get_raw ( 3 ) ?. to_owned ( ) . decode :: < String > ( ) ;
339+
340+ assert_eq ! ( empty, "" ) ;
341+ assert_eq ! ( space, " " ) ;
342+ assert_eq ! ( greeting, "Hello, World!" ) ;
343+ assert_eq ! ( unicode, "Unicode: 🦀 Rust" ) ;
344+ Ok ( ( ) )
345+ }
346+
347+ #[ tokio:: test]
348+ async fn it_handles_type_coercion_from_strings ( ) -> anyhow:: Result < ( ) > {
349+ let mut conn = new :: < Odbc > ( ) . await ?;
350+
351+ // Test that numeric values returned as strings can be parsed
352+ let sql = format ! (
353+ "SELECT '42' AS str_int, '{}' AS str_float, '1' AS str_bool" ,
354+ std:: f64 :: consts:: PI
355+ ) ;
356+ let mut s = conn. fetch ( sql. as_str ( ) ) ;
357+ let row = s. try_next ( ) . await ?. expect ( "row expected" ) ;
358+
359+ let str_int = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < i32 > ( ) ;
360+ let str_float = row. try_get_raw ( 1 ) ?. to_owned ( ) . decode :: < f64 > ( ) ;
361+ let str_bool = row. try_get_raw ( 2 ) ?. to_owned ( ) . decode :: < bool > ( ) ;
362+
363+ assert_eq ! ( str_int, 42 ) ;
364+ assert ! ( ( str_float - std:: f64 :: consts:: PI ) . abs( ) < 1e-10 ) ;
365+ assert ! ( str_bool) ;
366+ Ok ( ( ) )
367+ }
368+
369+ #[ tokio:: test]
370+ async fn it_handles_large_strings ( ) -> anyhow:: Result < ( ) > {
371+ let mut conn = new :: < Odbc > ( ) . await ?;
372+
373+ // Test a moderately large string
374+ let large_string = "a" . repeat ( 1000 ) ;
375+ let stmt = ( & mut conn) . prepare ( "SELECT ? AS large_str" ) . await ?;
376+ let row = stmt
377+ . query ( )
378+ . bind ( & large_string)
379+ . fetch_one ( & mut conn)
380+ . await ?;
381+
382+ let result = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < String > ( ) ;
383+ assert_eq ! ( result, large_string) ;
384+ assert_eq ! ( result. len( ) , 1000 ) ;
385+ Ok ( ( ) )
386+ }
387+
388+ #[ tokio:: test]
389+ async fn it_handles_binary_data ( ) -> anyhow:: Result < ( ) > {
390+ let mut conn = new :: < Odbc > ( ) . await ?;
391+
392+ // Test binary data - use UTF-8 safe bytes for PostgreSQL compatibility
393+ let binary_data = vec ! [ 65u8 , 66 , 67 , 68 , 69 ] ; // "ABCDE" in ASCII
394+ let stmt = ( & mut conn) . prepare ( "SELECT ? AS binary_data" ) . await ?;
395+ let row = stmt. query ( ) . bind ( & binary_data) . fetch_one ( & mut conn) . await ?;
396+
397+ let result = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < Vec < u8 > > ( ) ;
398+ assert_eq ! ( result, binary_data) ;
399+ Ok ( ( ) )
400+ }
401+
402+ #[ tokio:: test]
403+ async fn it_handles_mixed_null_and_values ( ) -> anyhow:: Result < ( ) > {
404+ let mut conn = new :: < Odbc > ( ) . await ?;
405+
406+ let stmt = ( & mut conn) . prepare ( "SELECT ?, ?, ?, ?" ) . await ?;
407+ let row = stmt
408+ . query ( )
409+ . bind ( 42_i32 )
410+ . bind ( Option :: < i32 > :: None )
411+ . bind ( "hello" )
412+ . bind ( Option :: < String > :: None )
413+ . fetch_one ( & mut conn)
414+ . await ?;
415+
416+ let int_val = row. try_get_raw ( 0 ) ?. to_owned ( ) . decode :: < i32 > ( ) ;
417+ let null_int = row. try_get_raw ( 1 ) ?. to_owned ( ) ;
418+ let str_val = row. try_get_raw ( 2 ) ?. to_owned ( ) . decode :: < String > ( ) ;
419+ let null_str = row. try_get_raw ( 3 ) ?. to_owned ( ) ;
420+
421+ assert_eq ! ( int_val, 42 ) ;
422+ assert ! ( null_int. is_null( ) ) ;
423+ assert_eq ! ( str_val, "hello" ) ;
424+ assert ! ( null_str. is_null( ) ) ;
425+ Ok ( ( ) )
426+ }
0 commit comments