@@ -484,11 +484,22 @@ impl InnerConnection {
484
484
mem:: replace ( & mut self . notice_handler , handler)
485
485
}
486
486
487
- fn raw_prepare ( & mut self , stmt_name : & str , query : & str ) -> Result < ( Vec < Type > , Vec < Column > ) > {
487
+ fn raw_prepare (
488
+ & mut self ,
489
+ stmt_name : & str ,
490
+ query : & str ,
491
+ types : & [ Option < Type > ] ,
492
+ ) -> Result < ( Vec < Type > , Vec < Column > ) > {
488
493
debug ! ( "preparing query with name `{}`: {}" , stmt_name, query) ;
489
494
490
- self . stream
491
- . write_message ( |buf| frontend:: parse ( stmt_name, query, None , buf) ) ?;
495
+ self . stream . write_message ( |buf| {
496
+ frontend:: parse (
497
+ stmt_name,
498
+ query,
499
+ types. iter ( ) . map ( |t| t. as_ref ( ) . map_or ( 0 , |t| t. oid ( ) ) ) ,
500
+ buf,
501
+ )
502
+ } ) ?;
492
503
self . stream
493
504
. write_message ( |buf| frontend:: describe ( b'S' , stmt_name, buf) ) ?;
494
505
self . stream
@@ -657,9 +668,14 @@ impl InnerConnection {
657
668
stmt_name
658
669
}
659
670
660
- fn prepare < ' a > ( & mut self , query : & str , conn : & ' a Connection ) -> Result < Statement < ' a > > {
671
+ fn prepare_typed < ' a > (
672
+ & mut self ,
673
+ query : & str ,
674
+ types : & [ Option < Type > ] ,
675
+ conn : & ' a Connection ,
676
+ ) -> Result < Statement < ' a > > {
661
677
let stmt_name = self . make_stmt_name ( ) ;
662
- let ( param_types, columns) = self . raw_prepare ( & stmt_name, query) ?;
678
+ let ( param_types, columns) = self . raw_prepare ( & stmt_name, query, types ) ?;
663
679
let info = Arc :: new ( StatementInfo {
664
680
name : stmt_name,
665
681
param_types : param_types,
@@ -675,7 +691,7 @@ impl InnerConnection {
675
691
Some ( info) => info,
676
692
None => {
677
693
let stmt_name = self . make_stmt_name ( ) ;
678
- let ( param_types, columns) = self . raw_prepare ( & stmt_name, query) ?;
694
+ let ( param_types, columns) = self . raw_prepare ( & stmt_name, query, & [ ] ) ?;
679
695
let info = Arc :: new ( StatementInfo {
680
696
name : stmt_name,
681
697
param_types : param_types,
@@ -734,6 +750,7 @@ impl InnerConnection {
734
750
INNER JOIN pg_catalog.pg_namespace n ON \
735
751
t.typnamespace = n.oid \
736
752
WHERE t.oid = $1",
753
+ & [ ] ,
737
754
) {
738
755
Ok ( ..) => { }
739
756
// Range types weren't added until Postgres 9.2, so pg_range may not exist
@@ -746,6 +763,7 @@ impl InnerConnection {
746
763
INNER JOIN pg_catalog.pg_namespace n \
747
764
ON t.typnamespace = n.oid \
748
765
WHERE t.oid = $1",
766
+ & [ ] ,
749
767
) ?;
750
768
}
751
769
Err ( e) => return Err ( e) ,
@@ -811,6 +829,7 @@ impl InnerConnection {
811
829
FROM pg_catalog.pg_enum \
812
830
WHERE enumtypid = $1 \
813
831
ORDER BY enumsortorder",
832
+ & [ ] ,
814
833
) {
815
834
Ok ( ..) => { }
816
835
// Postgres 9.0 doesn't have enumsortorder
@@ -821,6 +840,7 @@ impl InnerConnection {
821
840
FROM pg_catalog.pg_enum \
822
841
WHERE enumtypid = $1 \
823
842
ORDER BY oid",
843
+ & [ ] ,
824
844
) ?;
825
845
}
826
846
Err ( e) => return Err ( e) ,
@@ -858,6 +878,7 @@ impl InnerConnection {
858
878
AND NOT attisdropped \
859
879
AND attnum > 0 \
860
880
ORDER BY attnum",
881
+ & [ ] ,
861
882
) ?;
862
883
863
884
self . has_typeinfo_composite_query = true ;
@@ -1055,7 +1076,7 @@ impl Connection {
1055
1076
/// println!("{} rows updated", rows_updated);
1056
1077
/// ```
1057
1078
pub fn execute ( & self , query : & str , params : & [ & ToSql ] ) -> Result < u64 > {
1058
- let ( param_types, columns) = self . 0 . borrow_mut ( ) . raw_prepare ( "" , query) ?;
1079
+ let ( param_types, columns) = self . 0 . borrow_mut ( ) . raw_prepare ( "" , query, & [ ] ) ?;
1059
1080
let info = Arc :: new ( StatementInfo {
1060
1081
name : String :: new ( ) ,
1061
1082
param_types : param_types,
@@ -1091,7 +1112,7 @@ impl Connection {
1091
1112
/// }
1092
1113
/// ```
1093
1114
pub fn query ( & self , query : & str , params : & [ & ToSql ] ) -> Result < Rows > {
1094
- let ( param_types, columns) = self . 0 . borrow_mut ( ) . raw_prepare ( "" , query) ?;
1115
+ let ( param_types, columns) = self . 0 . borrow_mut ( ) . raw_prepare ( "" , query, & [ ] ) ?;
1095
1116
let info = Arc :: new ( StatementInfo {
1096
1117
name : String :: new ( ) ,
1097
1118
param_types : param_types,
@@ -1167,7 +1188,32 @@ impl Connection {
1167
1188
/// }
1168
1189
/// ```
1169
1190
pub fn prepare < ' a > ( & ' a self , query : & str ) -> Result < Statement < ' a > > {
1170
- self . 0 . borrow_mut ( ) . prepare ( query, self )
1191
+ self . prepare_typed ( query, & [ ] )
1192
+ }
1193
+
1194
+ /// Like `prepare`, but allows for the types of query parameters to be explicitly specified.
1195
+ ///
1196
+ /// Postgres will normally infer the types of paramters, but this function offers more control
1197
+ /// of that behavior. `None` will cause Postgres to infer the type. The list of types can be
1198
+ /// shorter than the number of parameters in the query; it will act as if padded out with `None`
1199
+ /// values.
1200
+ ///
1201
+ /// # Example
1202
+ ///
1203
+ /// ```rust,no_run
1204
+ /// # use postgres::{Connection, TlsMode};
1205
+ /// # use postgres::types::Type;
1206
+ /// # let conn = Connection::connect("", TlsMode::None).unwrap();
1207
+ /// // $1 would normally be assigned the type INT4, but we can override that to INT8
1208
+ /// let stmt = conn.prepare_typed("SELECT $1::INT4", &[Some(Type::INT8)]).unwrap();
1209
+ /// assert_eq!(stmt.param_types()[0], Type::INT8);
1210
+ /// ```
1211
+ pub fn prepare_typed < ' a > (
1212
+ & ' a self ,
1213
+ query : & str ,
1214
+ types : & [ Option < Type > ] ,
1215
+ ) -> Result < Statement < ' a > > {
1216
+ self . 0 . borrow_mut ( ) . prepare_typed ( query, types, self )
1171
1217
}
1172
1218
1173
1219
/// Creates a cached prepared statement.
0 commit comments