@@ -328,6 +328,7 @@ impl Decode for chrono::Duration {
328
328
}
329
329
}
330
330
331
+ #[ cfg( feature = "postgres4-types" ) ]
331
332
impl Decode for uuid:: Uuid {
332
333
fn decode ( value : & DbValue ) -> Result < Self , Error > {
333
334
match value {
@@ -337,20 +338,23 @@ impl Decode for uuid::Uuid {
337
338
}
338
339
}
339
340
341
+ #[ cfg( feature = "json" ) ]
340
342
impl Decode for serde_json:: Value {
341
343
fn decode ( value : & DbValue ) -> Result < Self , Error > {
342
344
from_jsonb ( value)
343
345
}
344
346
}
345
347
346
348
/// Convert a Postgres JSONB value to a `Deserialize`-able type.
349
+ #[ cfg( feature = "json" ) ]
347
350
pub fn from_jsonb < ' a , T : serde:: Deserialize < ' a > > ( value : & ' a DbValue ) -> Result < T , Error > {
348
351
match value {
349
352
DbValue :: Jsonb ( j) => serde_json:: from_slice ( j) . map_err ( |e| Error :: Decode ( e. to_string ( ) ) ) ,
350
353
_ => Err ( Error :: Decode ( format_decode_err ( "JSONB" , value) ) ) ,
351
354
}
352
355
}
353
356
357
+ #[ cfg( feature = "postgres4-types" ) ]
354
358
impl Decode for rust_decimal:: Decimal {
355
359
fn decode ( value : & DbValue ) -> Result < Self , Error > {
356
360
match value {
@@ -362,13 +366,15 @@ impl Decode for rust_decimal::Decimal {
362
366
}
363
367
}
364
368
369
+ #[ cfg( feature = "postgres4-types" ) ]
365
370
fn bound_type_from_wit ( kind : RangeBoundKind ) -> postgres_range:: BoundType {
366
371
match kind {
367
372
RangeBoundKind :: Inclusive => postgres_range:: BoundType :: Inclusive ,
368
373
RangeBoundKind :: Exclusive => postgres_range:: BoundType :: Exclusive ,
369
374
}
370
375
}
371
376
377
+ #[ cfg( feature = "postgres4-types" ) ]
372
378
impl Decode for postgres_range:: Range < i32 > {
373
379
fn decode ( value : & DbValue ) -> Result < Self , Error > {
374
380
match value {
@@ -386,6 +392,7 @@ impl Decode for postgres_range::Range<i32> {
386
392
}
387
393
}
388
394
395
+ #[ cfg( feature = "postgres4-types" ) ]
389
396
impl Decode for postgres_range:: Range < i64 > {
390
397
fn decode ( value : & DbValue ) -> Result < Self , Error > {
391
398
match value {
@@ -403,7 +410,41 @@ impl Decode for postgres_range::Range<i64> {
403
410
}
404
411
}
405
412
406
- // TODO: NUMERICRANGE
413
+ // We can't use postgres_range::Range because rust_decimal::Decimal
414
+ // is not Normalizable
415
+ #[ cfg( feature = "postgres4-types" ) ]
416
+ impl Decode
417
+ for (
418
+ Option < ( rust_decimal:: Decimal , RangeBoundKind ) > ,
419
+ Option < ( rust_decimal:: Decimal , RangeBoundKind ) > ,
420
+ )
421
+ {
422
+ fn decode ( value : & DbValue ) -> Result < Self , Error > {
423
+ fn parse (
424
+ value : & str ,
425
+ kind : RangeBoundKind ,
426
+ ) -> Result < ( rust_decimal:: Decimal , RangeBoundKind ) , Error > {
427
+ let dec = rust_decimal:: Decimal :: from_str_exact ( value)
428
+ . map_err ( |e| Error :: Decode ( e. to_string ( ) ) ) ?;
429
+ Ok ( ( dec, kind) )
430
+ }
431
+
432
+ match value {
433
+ DbValue :: RangeDecimal ( ( lbound, ubound) ) => {
434
+ let lower = lbound
435
+ . as_ref ( )
436
+ . map ( |( value, kind) | parse ( value, * kind) )
437
+ . transpose ( ) ?;
438
+ let upper = ubound
439
+ . as_ref ( )
440
+ . map ( |( value, kind) | parse ( value, * kind) )
441
+ . transpose ( ) ?;
442
+ Ok ( ( lower, upper) )
443
+ }
444
+ _ => Err ( Error :: Decode ( format_decode_err ( "NUMERICRANGE" , value) ) ) ,
445
+ }
446
+ }
447
+ }
407
448
408
449
// TODO: can we return a slice here? It seems like it should be possible but
409
450
// I wasn't able to get the lifetimes to work with the trait
@@ -434,13 +475,15 @@ impl Decode for Vec<Option<String>> {
434
475
}
435
476
}
436
477
478
+ #[ cfg( feature = "postgres4-types" ) ]
437
479
fn map_decimal ( s : & Option < String > ) -> Result < Option < rust_decimal:: Decimal > , Error > {
438
480
s. as_ref ( )
439
481
. map ( |s| rust_decimal:: Decimal :: from_str_exact ( s) )
440
482
. transpose ( )
441
483
. map_err ( |e| Error :: Decode ( e. to_string ( ) ) )
442
484
}
443
485
486
+ #[ cfg( feature = "postgres4-types" ) ]
444
487
impl Decode for Vec < Option < rust_decimal:: Decimal > > {
445
488
fn decode ( value : & DbValue ) -> Result < Self , Error > {
446
489
match value {
@@ -526,12 +569,14 @@ impl From<chrono::TimeDelta> for ParameterValue {
526
569
}
527
570
}
528
571
572
+ #[ cfg( feature = "postgres4-types" ) ]
529
573
impl From < uuid:: Uuid > for ParameterValue {
530
574
fn from ( v : uuid:: Uuid ) -> ParameterValue {
531
575
ParameterValue :: Uuid ( v. to_string ( ) )
532
576
}
533
577
}
534
578
579
+ #[ cfg( feature = "json" ) ]
535
580
impl TryFrom < serde_json:: Value > for ParameterValue {
536
581
type Error = serde_json:: Error ;
537
582
@@ -541,11 +586,13 @@ impl TryFrom<serde_json::Value> for ParameterValue {
541
586
}
542
587
543
588
/// Converts a `Serialize` value to a Postgres JSONB SQL parameter.
589
+ #[ cfg( feature = "json" ) ]
544
590
pub fn jsonb < T : serde:: Serialize > ( value : & T ) -> Result < ParameterValue , serde_json:: Error > {
545
591
let json = serde_json:: to_vec ( value) ?;
546
592
Ok ( ParameterValue :: Jsonb ( json) )
547
593
}
548
594
595
+ #[ cfg( feature = "postgres4-types" ) ]
549
596
impl From < rust_decimal:: Decimal > for ParameterValue {
550
597
fn from ( v : rust_decimal:: Decimal ) -> ParameterValue {
551
598
ParameterValue :: Decimal ( v. to_string ( ) )
@@ -580,6 +627,7 @@ fn range_bound_to_wit<T, U>(
580
627
}
581
628
}
582
629
630
+ #[ cfg( feature = "postgres4-types" ) ]
583
631
fn pg_range_bound_to_wit < S : postgres_range:: BoundSided , T : Copy > (
584
632
bound : & postgres_range:: RangeBound < S , T > ,
585
633
) -> ( T , RangeBoundKind ) {
@@ -620,6 +668,7 @@ impl From<std::ops::RangeToInclusive<i32>> for ParameterValue {
620
668
}
621
669
}
622
670
671
+ #[ cfg( feature = "postgres4-types" ) ]
623
672
impl From < postgres_range:: Range < i32 > > for ParameterValue {
624
673
fn from ( v : postgres_range:: Range < i32 > ) -> ParameterValue {
625
674
let lbound = v. lower ( ) . map ( pg_range_bound_to_wit) ;
@@ -658,6 +707,7 @@ impl From<std::ops::RangeToInclusive<i64>> for ParameterValue {
658
707
}
659
708
}
660
709
710
+ #[ cfg( feature = "postgres4-types" ) ]
661
711
impl From < postgres_range:: Range < i64 > > for ParameterValue {
662
712
fn from ( v : postgres_range:: Range < i64 > ) -> ParameterValue {
663
713
let lbound = v. lower ( ) . map ( pg_range_bound_to_wit) ;
@@ -666,6 +716,7 @@ impl From<postgres_range::Range<i64>> for ParameterValue {
666
716
}
667
717
}
668
718
719
+ #[ cfg( feature = "postgres4-types" ) ]
669
720
impl From < std:: ops:: Range < rust_decimal:: Decimal > > for ParameterValue {
670
721
fn from ( v : std:: ops:: Range < rust_decimal:: Decimal > ) -> ParameterValue {
671
722
ParameterValue :: RangeDecimal ( range_bounds_to_wit ( v, |d| d. to_string ( ) ) )
@@ -690,6 +741,7 @@ impl From<Vec<String>> for ParameterValue {
690
741
}
691
742
}
692
743
744
+ #[ cfg( feature = "postgres4-types" ) ]
693
745
impl From < Vec < Option < rust_decimal:: Decimal > > > for ParameterValue {
694
746
fn from ( v : Vec < Option < rust_decimal:: Decimal > > ) -> ParameterValue {
695
747
let strs = v
@@ -700,6 +752,7 @@ impl From<Vec<Option<rust_decimal::Decimal>>> for ParameterValue {
700
752
}
701
753
}
702
754
755
+ #[ cfg( feature = "postgres4-types" ) ]
703
756
impl From < Vec < rust_decimal:: Decimal > > for ParameterValue {
704
757
fn from ( v : Vec < rust_decimal:: Decimal > ) -> ParameterValue {
705
758
let strs = v. into_iter ( ) . map ( |d| Some ( d. to_string ( ) ) ) . collect ( ) ;
@@ -859,4 +912,117 @@ mod tests {
859
912
. unwrap( )
860
913
. is_none( ) ) ;
861
914
}
915
+
916
+ #[ test]
917
+ #[ cfg( feature = "postgres4-types" ) ]
918
+ fn uuid ( ) {
919
+ let uuid_str = "12341234-1234-1234-1234-123412341234" ;
920
+ assert_eq ! (
921
+ uuid:: Uuid :: try_parse( uuid_str) . unwrap( ) ,
922
+ uuid:: Uuid :: decode( & DbValue :: Uuid ( uuid_str. to_owned( ) ) ) . unwrap( ) ,
923
+ ) ;
924
+ assert ! ( Option :: <uuid:: Uuid >:: decode( & DbValue :: DbNull )
925
+ . unwrap( )
926
+ . is_none( ) ) ;
927
+ }
928
+
929
+ #[ derive( Debug , serde:: Deserialize , PartialEq ) ]
930
+ struct JsonTest {
931
+ hello : String ,
932
+ }
933
+
934
+ #[ test]
935
+ #[ cfg( feature = "json" ) ]
936
+ fn jsonb ( ) {
937
+ let json_val = serde_json:: json!( {
938
+ "hello" : "world"
939
+ } ) ;
940
+ let dbval = DbValue :: Jsonb ( r#"{"hello":"world"}"# . into ( ) ) ;
941
+
942
+ assert_eq ! ( json_val, serde_json:: Value :: decode( & dbval) . unwrap( ) , ) ;
943
+
944
+ let json_struct = JsonTest {
945
+ hello : "world" . to_owned ( ) ,
946
+ } ;
947
+ assert_eq ! ( json_struct, from_jsonb( & dbval) . unwrap( ) ) ;
948
+ }
949
+
950
+ #[ test]
951
+ #[ cfg( feature = "postgres4-types" ) ]
952
+ fn ranges ( ) {
953
+ let i32_range = postgres_range:: Range :: < i32 > :: decode ( & DbValue :: RangeInt32 ( (
954
+ Some ( ( 45 , RangeBoundKind :: Inclusive ) ) ,
955
+ Some ( ( 89 , RangeBoundKind :: Exclusive ) ) ,
956
+ ) ) )
957
+ . unwrap ( ) ;
958
+ assert_eq ! ( 45 , i32_range. lower( ) . unwrap( ) . value) ;
959
+ assert_eq ! (
960
+ postgres_range:: BoundType :: Inclusive ,
961
+ i32_range. lower( ) . unwrap( ) . type_
962
+ ) ;
963
+ assert_eq ! ( 89 , i32_range. upper( ) . unwrap( ) . value) ;
964
+ assert_eq ! (
965
+ postgres_range:: BoundType :: Exclusive ,
966
+ i32_range. upper( ) . unwrap( ) . type_
967
+ ) ;
968
+
969
+ let i32_range_from = postgres_range:: Range :: < i32 > :: decode ( & DbValue :: RangeInt32 ( (
970
+ Some ( ( 45 , RangeBoundKind :: Inclusive ) ) ,
971
+ None ,
972
+ ) ) )
973
+ . unwrap ( ) ;
974
+ assert ! ( i32_range_from. upper( ) . is_none( ) ) ;
975
+
976
+ let i64_range = postgres_range:: Range :: < i64 > :: decode ( & DbValue :: RangeInt64 ( (
977
+ Some ( ( 4567456745674567 , RangeBoundKind :: Inclusive ) ) ,
978
+ Some ( ( 890189018901890189 , RangeBoundKind :: Exclusive ) ) ,
979
+ ) ) )
980
+ . unwrap ( ) ;
981
+ assert_eq ! ( 4567456745674567 , i64_range. lower( ) . unwrap( ) . value) ;
982
+ assert_eq ! ( 890189018901890189 , i64_range. upper( ) . unwrap( ) . value) ;
983
+
984
+ let ( dec_lbound, dec_ubound) : (
985
+ Option < ( rust_decimal:: Decimal , RangeBoundKind ) > ,
986
+ Option < ( rust_decimal:: Decimal , RangeBoundKind ) > ,
987
+ ) = Decode :: decode ( & DbValue :: RangeDecimal ( (
988
+ Some ( ( "4567.8901" . to_owned ( ) , RangeBoundKind :: Inclusive ) ) ,
989
+ Some ( ( "8901.2345678901" . to_owned ( ) , RangeBoundKind :: Exclusive ) ) ,
990
+ ) ) )
991
+ . unwrap ( ) ;
992
+ assert_eq ! (
993
+ rust_decimal:: Decimal :: from_i128_with_scale( 45678901 , 4 ) ,
994
+ dec_lbound. unwrap( ) . 0
995
+ ) ;
996
+ assert_eq ! (
997
+ rust_decimal:: Decimal :: from_i128_with_scale( 89012345678901 , 10 ) ,
998
+ dec_ubound. unwrap( ) . 0
999
+ ) ;
1000
+ }
1001
+
1002
+ #[ test]
1003
+ #[ cfg( feature = "postgres4-types" ) ]
1004
+ fn arrays ( ) {
1005
+ let v32 = vec ! [ Some ( 123 ) , None , Some ( 456 ) ] ;
1006
+ let i32_arr = Vec :: < Option < i32 > > :: decode ( & DbValue :: ArrayInt32 ( v32. clone ( ) ) ) . unwrap ( ) ;
1007
+ assert_eq ! ( v32, i32_arr) ;
1008
+
1009
+ let v64 = vec ! [ Some ( 123 ) , None , Some ( 456 ) ] ;
1010
+ let i64_arr = Vec :: < Option < i64 > > :: decode ( & DbValue :: ArrayInt64 ( v64. clone ( ) ) ) . unwrap ( ) ;
1011
+ assert_eq ! ( v64, i64_arr) ;
1012
+
1013
+ let vdec = vec ! [ Some ( "1.23" . to_owned( ) ) , None ] ;
1014
+ let dec_arr =
1015
+ Vec :: < Option < rust_decimal:: Decimal > > :: decode ( & DbValue :: ArrayDecimal ( vdec) ) . unwrap ( ) ;
1016
+ assert_eq ! (
1017
+ vec![
1018
+ Some ( rust_decimal:: Decimal :: from_i128_with_scale( 123 , 2 ) ) ,
1019
+ None
1020
+ ] ,
1021
+ dec_arr
1022
+ ) ;
1023
+
1024
+ let vstr = vec ! [ Some ( "alice" . to_owned( ) ) , None , Some ( "bob" . to_owned( ) ) ] ;
1025
+ let str_arr = Vec :: < Option < String > > :: decode ( & DbValue :: ArrayStr ( vstr. clone ( ) ) ) . unwrap ( ) ;
1026
+ assert_eq ! ( vstr, str_arr) ;
1027
+ }
862
1028
}
0 commit comments