@@ -264,20 +264,7 @@ impl<'stmt, 'query> BoundStatement<'stmt, 'query> {
264
264
let mut ret = BoundStatement {
265
265
statement,
266
266
query : None ,
267
- binds_to_free : Vec :: with_capacity (
268
- binds
269
- . iter ( )
270
- . filter ( |& ( b, _) | {
271
- matches ! (
272
- b,
273
- SqliteBindValue :: BorrowedBinary ( _)
274
- | SqliteBindValue :: BorrowedString ( _)
275
- | SqliteBindValue :: String ( _)
276
- | SqliteBindValue :: Binary ( _)
277
- )
278
- } )
279
- . count ( ) ,
280
- ) ,
267
+ binds_to_free : Vec :: new ( ) ,
281
268
} ;
282
269
283
270
ret. bind_buffers ( binds) ?;
@@ -292,6 +279,24 @@ impl<'stmt, 'query> BoundStatement<'stmt, 'query> {
292
279
// not the whole construtor is generic over the query type T.
293
280
// This hopefully prevents binary bloat.
294
281
fn bind_buffers ( & mut self , binds : Vec < ( SqliteBindValue < ' _ > , SqliteType ) > ) -> QueryResult < ( ) > {
282
+ // It is useful to preallocate `binds_to_free` because it
283
+ // - Guarantees that pushing inside it cannot panic, which guarantees the `Drop`
284
+ // impl of `BoundStatement` will always re-`bind` as needed
285
+ // - Avoids reallocations
286
+ self . binds_to_free . reserve (
287
+ binds
288
+ . iter ( )
289
+ . filter ( |& ( b, _) | {
290
+ matches ! (
291
+ b,
292
+ SqliteBindValue :: BorrowedBinary ( _)
293
+ | SqliteBindValue :: BorrowedString ( _)
294
+ | SqliteBindValue :: String ( _)
295
+ | SqliteBindValue :: Binary ( _)
296
+ )
297
+ } )
298
+ . count ( ) ,
299
+ ) ;
295
300
for ( bind_idx, ( bind, tpe) ) in ( 1 ..) . zip ( binds) {
296
301
if matches ! (
297
302
bind,
0 commit comments