1
- use crate :: stmt_cache:: { PrepareCallback , StmtCache } ;
1
+ use crate :: stmt_cache:: { CallbackHelper , QueryFragmentHelper } ;
2
2
use crate :: { AnsiTransactionManager , AsyncConnection , SimpleAsyncConnection } ;
3
- use diesel:: connection:: statement_cache:: { MaybeCached , StatementCacheKey } ;
4
- use diesel :: connection :: Instrumentation ;
5
- use diesel :: connection :: InstrumentationEvent ;
3
+ use diesel:: connection:: statement_cache:: {
4
+ MaybeCached , QueryFragmentForCachedStatement , StatementCache ,
5
+ } ;
6
6
use diesel:: connection:: StrQueryHelper ;
7
+ use diesel:: connection:: { CacheSize , Instrumentation } ;
8
+ use diesel:: connection:: { DynInstrumentation , InstrumentationEvent } ;
7
9
use diesel:: mysql:: { Mysql , MysqlQueryBuilder , MysqlType } ;
8
10
use diesel:: query_builder:: QueryBuilder ;
9
11
use diesel:: query_builder:: { bind_collector:: RawBytesBindCollector , QueryFragment , QueryId } ;
@@ -27,9 +29,9 @@ use self::serialize::ToSqlHelper;
27
29
/// `mysql://[user[:password]@]host/database_name`
28
30
pub struct AsyncMysqlConnection {
29
31
conn : mysql_async:: Conn ,
30
- stmt_cache : StmtCache < Mysql , Statement > ,
32
+ stmt_cache : StatementCache < Mysql , Statement > ,
31
33
transaction_manager : AnsiTransactionManager ,
32
- instrumentation : std :: sync :: Mutex < Option < Box < dyn Instrumentation > > > ,
34
+ instrumentation : DynInstrumentation ,
33
35
}
34
36
35
37
#[ async_trait:: async_trait]
@@ -72,7 +74,7 @@ impl AsyncConnection for AsyncMysqlConnection {
72
74
type TransactionManager = AnsiTransactionManager ;
73
75
74
76
async fn establish ( database_url : & str ) -> diesel:: ConnectionResult < Self > {
75
- let mut instrumentation = diesel :: connection :: get_default_instrumentation ( ) ;
77
+ let mut instrumentation = DynInstrumentation :: default_instrumentation ( ) ;
76
78
instrumentation. on_connection_event ( InstrumentationEvent :: start_establish_connection (
77
79
database_url,
78
80
) ) ;
@@ -82,7 +84,7 @@ impl AsyncConnection for AsyncMysqlConnection {
82
84
r. as_ref ( ) . err ( ) ,
83
85
) ) ;
84
86
let mut conn = r?;
85
- conn. instrumentation = std :: sync :: Mutex :: new ( instrumentation) ;
87
+ conn. instrumentation = instrumentation;
86
88
Ok ( conn)
87
89
}
88
90
@@ -177,16 +179,15 @@ impl AsyncConnection for AsyncMysqlConnection {
177
179
}
178
180
179
181
fn instrumentation ( & mut self ) -> & mut dyn Instrumentation {
180
- self . instrumentation
181
- . get_mut ( )
182
- . unwrap_or_else ( |p| p. into_inner ( ) )
182
+ & mut * self . instrumentation
183
183
}
184
184
185
185
fn set_instrumentation ( & mut self , instrumentation : impl Instrumentation ) {
186
- * self
187
- . instrumentation
188
- . get_mut ( )
189
- . unwrap_or_else ( |p| p. into_inner ( ) ) = Some ( Box :: new ( instrumentation) ) ;
186
+ self . instrumentation = instrumentation. into ( ) ;
187
+ }
188
+
189
+ fn set_prepared_statement_cache_size ( & mut self , size : CacheSize ) {
190
+ self . stmt_cache . set_cache_size ( size) ;
190
191
}
191
192
}
192
193
@@ -207,17 +208,24 @@ fn update_transaction_manager_status<T>(
207
208
query_result
208
209
}
209
210
210
- #[ async_trait:: async_trait]
211
- impl PrepareCallback < Statement , MysqlType > for & ' _ mut mysql_async:: Conn {
212
- async fn prepare (
213
- self ,
214
- sql : & str ,
215
- _metadata : & [ MysqlType ] ,
216
- _is_for_cache : diesel:: connection:: statement_cache:: PrepareForCache ,
217
- ) -> QueryResult < ( Statement , Self ) > {
218
- let s = self . prep ( sql) . await . map_err ( ErrorHelper ) ?;
219
- Ok ( ( s, self ) )
220
- }
211
+ fn prepare_statement_helper < ' a , ' b > (
212
+ conn : & ' a mut mysql_async:: Conn ,
213
+ sql : & ' b str ,
214
+ _is_for_cache : diesel:: connection:: statement_cache:: PrepareForCache ,
215
+ _metadata : & [ MysqlType ] ,
216
+ ) -> CallbackHelper < impl Future < Output = QueryResult < ( Statement , & ' a mut mysql_async:: Conn ) > > + Send >
217
+ {
218
+ // ideally we wouldn't clone the SQL string here
219
+ // but as we usually cache statements anyway
220
+ // this is a fixed one time const
221
+ //
222
+ // The probleme with not cloning it is that we then cannot express
223
+ // the right result lifetime anymore (at least not easily)
224
+ let sql = sql. to_owned ( ) ;
225
+ CallbackHelper ( async move {
226
+ let s = conn. prep ( sql) . await . map_err ( ErrorHelper ) ?;
227
+ Ok ( ( s, conn) )
228
+ } )
221
229
}
222
230
223
231
impl AsyncMysqlConnection {
@@ -229,11 +237,9 @@ impl AsyncMysqlConnection {
229
237
use crate :: run_query_dsl:: RunQueryDsl ;
230
238
let mut conn = AsyncMysqlConnection {
231
239
conn,
232
- stmt_cache : StmtCache :: new ( ) ,
240
+ stmt_cache : StatementCache :: new ( ) ,
233
241
transaction_manager : AnsiTransactionManager :: default ( ) ,
234
- instrumentation : std:: sync:: Mutex :: new (
235
- diesel:: connection:: get_default_instrumentation ( ) ,
236
- ) ,
242
+ instrumentation : DynInstrumentation :: default_instrumentation ( ) ,
237
243
} ;
238
244
239
245
for stmt in CONNECTION_SETUP_QUERIES {
@@ -286,36 +292,29 @@ impl AsyncMysqlConnection {
286
292
} = bind_collector?;
287
293
let is_safe_to_cache_prepared = is_safe_to_cache_prepared?;
288
294
let sql = sql?;
295
+ let helper = QueryFragmentHelper {
296
+ sql,
297
+ safe_to_cache : is_safe_to_cache_prepared,
298
+ } ;
289
299
let inner = async {
290
- let cache_key = if let Some ( query_id) = query_id {
291
- StatementCacheKey :: Type ( query_id)
292
- } else {
293
- StatementCacheKey :: Sql {
294
- sql : sql. clone ( ) ,
295
- bind_types : metadata. clone ( ) ,
296
- }
297
- } ;
298
-
299
300
let ( stmt, conn) = stmt_cache
300
- . cached_prepared_statement (
301
- cache_key ,
302
- sql . clone ( ) ,
303
- is_safe_to_cache_prepared ,
301
+ . cached_statement_non_generic (
302
+ query_id ,
303
+ & helper ,
304
+ & Mysql ,
304
305
& metadata,
305
306
conn,
306
- instrumentation,
307
+ prepare_statement_helper,
308
+ & mut * * instrumentation,
307
309
)
308
310
. await ?;
309
311
callback ( conn, stmt, ToSqlHelper { metadata, binds } ) . await
310
312
} ;
311
313
let r = update_transaction_manager_status ( inner. await , transaction_manager) ;
312
- instrumentation
313
- . get_mut ( )
314
- . unwrap_or_else ( |p| p. into_inner ( ) )
315
- . on_connection_event ( InstrumentationEvent :: finish_query (
316
- & StrQueryHelper :: new ( & sql) ,
317
- r. as_ref ( ) . err ( ) ,
318
- ) ) ;
314
+ instrumentation. on_connection_event ( InstrumentationEvent :: finish_query (
315
+ & StrQueryHelper :: new ( & helper. sql ) ,
316
+ r. as_ref ( ) . err ( ) ,
317
+ ) ) ;
319
318
r
320
319
}
321
320
. boxed ( )
@@ -370,9 +369,9 @@ impl AsyncMysqlConnection {
370
369
371
370
Ok ( AsyncMysqlConnection {
372
371
conn,
373
- stmt_cache : StmtCache :: new ( ) ,
372
+ stmt_cache : StatementCache :: new ( ) ,
374
373
transaction_manager : AnsiTransactionManager :: default ( ) ,
375
- instrumentation : std :: sync :: Mutex :: new ( None ) ,
374
+ instrumentation : DynInstrumentation :: none ( ) ,
376
375
} )
377
376
}
378
377
}
@@ -427,3 +426,13 @@ mod tests {
427
426
}
428
427
}
429
428
}
429
+
430
+ impl QueryFragmentForCachedStatement < Mysql > for QueryFragmentHelper {
431
+ fn construct_sql ( & self , _backend : & Mysql ) -> QueryResult < String > {
432
+ Ok ( self . sql . clone ( ) )
433
+ }
434
+
435
+ fn is_safe_to_cache_prepared ( & self , _backend : & Mysql ) -> QueryResult < bool > {
436
+ Ok ( self . safe_to_cache )
437
+ }
438
+ }
0 commit comments