@@ -136,11 +136,13 @@ impl<'a> SyncOperation<'a> {
136
136
let statement = self . collect_full_operations ( ) ?;
137
137
138
138
// We cache the last insert and delete statements for each row
139
- let mut last_insert_table: Option < String > = None ;
140
- let mut last_insert_statement: Option < ManagedStmt > = None ;
139
+ struct CachedStatement {
140
+ table : String ,
141
+ statement : ManagedStmt ,
142
+ }
141
143
142
- let mut last_delete_table : Option < String > = None ;
143
- let mut last_delete_statement : Option < ManagedStmt > = None ;
144
+ let mut last_insert = None :: < CachedStatement > ;
145
+ let mut last_delete = None :: < CachedStatement > ;
144
146
145
147
let mut untyped_delete_statement: Option < ManagedStmt > = None ;
146
148
let mut untyped_insert_statement: Option < ManagedStmt > = None ;
@@ -173,35 +175,50 @@ impl<'a> SyncOperation<'a> {
173
175
// NULL data means no PUT operations found, so we delete the row.
174
176
if data. is_err ( ) {
175
177
// DELETE
176
- if last_delete_table. as_deref ( ) != Some ( & quoted) {
177
- // Prepare statement when the table changed
178
- last_delete_statement = Some (
179
- self . db
178
+ let delete_statement = match & last_delete {
179
+ Some ( stmt) if & * stmt. table == & * quoted => & stmt. statement ,
180
+ _ => {
181
+ // Prepare statement when the table changed
182
+ let statement = self
183
+ . db
180
184
. prepare_v2 ( & format ! ( "DELETE FROM {} WHERE id = ?" , quoted) )
181
- . into_db_result ( self . db ) ?,
182
- ) ;
183
- last_delete_table = Some ( quoted. clone ( ) ) ;
184
- }
185
- let delete_statement = last_delete_statement. as_mut ( ) . unwrap ( ) ;
185
+ . into_db_result ( self . db ) ?;
186
+
187
+ & last_delete
188
+ . insert ( CachedStatement {
189
+ table : quoted. clone ( ) ,
190
+ statement,
191
+ } )
192
+ . statement
193
+ }
194
+ } ;
186
195
187
196
delete_statement. reset ( ) ?;
188
197
delete_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
189
198
delete_statement. exec ( ) ?;
190
199
} else {
191
200
// INSERT/UPDATE
192
- if last_insert_table. as_deref ( ) != Some ( & quoted) {
193
- // Prepare statement when the table changed
194
- last_insert_statement = Some (
195
- self . db
201
+ let insert_statement = match & last_insert {
202
+ Some ( stmt) if & * stmt. table == & * quoted => & stmt. statement ,
203
+ _ => {
204
+ // Prepare statement when the table changed
205
+ let statement = self
206
+ . db
196
207
. prepare_v2 ( & format ! (
197
208
"REPLACE INTO {}(id, data) VALUES(?, ?)" ,
198
209
quoted
199
210
) )
200
- . into_db_result ( self . db ) ?,
201
- ) ;
202
- last_insert_table = Some ( quoted. clone ( ) ) ;
203
- }
204
- let insert_statement = last_insert_statement. as_mut ( ) . unwrap ( ) ;
211
+ . into_db_result ( self . db ) ?;
212
+
213
+ & last_insert
214
+ . insert ( CachedStatement {
215
+ table : quoted. clone ( ) ,
216
+ statement,
217
+ } )
218
+ . statement
219
+ }
220
+ } ;
221
+
205
222
insert_statement. reset ( ) ?;
206
223
insert_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
207
224
insert_statement. bind_text ( 2 , data?, sqlite:: Destructor :: STATIC ) ?;
@@ -211,32 +228,38 @@ impl<'a> SyncOperation<'a> {
211
228
} else {
212
229
if data. is_err ( ) {
213
230
// DELETE
214
- if untyped_delete_statement. is_none ( ) {
215
- // Prepare statement on first use
216
- untyped_delete_statement = Some (
217
- self . db
218
- . prepare_v2 ( "DELETE FROM ps_untyped WHERE type = ? AND id = ?" )
219
- . into_db_result ( self . db ) ?,
220
- ) ;
221
- }
222
- let delete_statement = untyped_delete_statement. as_mut ( ) . unwrap ( ) ;
231
+ let delete_statement = match & untyped_delete_statement {
232
+ Some ( stmt) => stmt,
233
+ None => {
234
+ // Prepare statement on first use
235
+ untyped_delete_statement. insert (
236
+ self . db
237
+ . prepare_v2 ( "DELETE FROM ps_untyped WHERE type = ? AND id = ?" )
238
+ . into_db_result ( self . db ) ?,
239
+ )
240
+ }
241
+ } ;
242
+
223
243
delete_statement. reset ( ) ?;
224
244
delete_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
225
245
delete_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
226
246
delete_statement. exec ( ) ?;
227
247
} else {
228
248
// INSERT/UPDATE
229
- if untyped_insert_statement. is_none ( ) {
230
- // Prepare statement on first use
231
- untyped_insert_statement = Some (
232
- self . db
233
- . prepare_v2 (
234
- "REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)" ,
235
- )
236
- . into_db_result ( self . db ) ?,
237
- ) ;
238
- }
239
- let insert_statement = untyped_insert_statement. as_mut ( ) . unwrap ( ) ;
249
+ let insert_statement = match & untyped_insert_statement {
250
+ Some ( stmt) => stmt,
251
+ None => {
252
+ // Prepare statement on first use
253
+ untyped_insert_statement. insert (
254
+ self . db
255
+ . prepare_v2 (
256
+ "REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)" ,
257
+ )
258
+ . into_db_result ( self . db ) ?,
259
+ )
260
+ }
261
+ } ;
262
+
240
263
insert_statement. reset ( ) ?;
241
264
insert_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
242
265
insert_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
@@ -449,30 +472,35 @@ struct RawTableWithCachedStatements<'a> {
449
472
}
450
473
451
474
impl < ' a > RawTableWithCachedStatements < ' a > {
475
+ fn prepare_lazily < ' b > (
476
+ db : * mut sqlite:: sqlite3 ,
477
+ slot : & ' b mut Option < PreparedPendingStatement < ' a > > ,
478
+ def : & ' a PendingStatement ,
479
+ ) -> Result < & ' b PreparedPendingStatement < ' a > , PowerSyncError >
480
+ where
481
+ ' a : ' b ,
482
+ {
483
+ Ok ( match slot {
484
+ Some ( stmt) => stmt,
485
+ None => {
486
+ let stmt = PreparedPendingStatement :: prepare ( db, def) ?;
487
+ slot. insert ( stmt)
488
+ }
489
+ } )
490
+ }
491
+
452
492
fn put_statement (
453
493
& mut self ,
454
494
db : * mut sqlite:: sqlite3 ,
455
495
) -> Result < & PreparedPendingStatement , PowerSyncError > {
456
- let cache_slot = & mut self . cached_put ;
457
- if let None = cache_slot {
458
- let stmt = PreparedPendingStatement :: prepare ( db, & self . definition . put ) ?;
459
- * cache_slot = Some ( stmt) ;
460
- }
461
-
462
- return Ok ( cache_slot. as_ref ( ) . unwrap ( ) ) ;
496
+ Self :: prepare_lazily ( db, & mut self . cached_put , & self . definition . put )
463
497
}
464
498
465
499
fn delete_statement (
466
500
& mut self ,
467
501
db : * mut sqlite:: sqlite3 ,
468
502
) -> Result < & PreparedPendingStatement , PowerSyncError > {
469
- let cache_slot = & mut self . cached_delete ;
470
- if let None = cache_slot {
471
- let stmt = PreparedPendingStatement :: prepare ( db, & self . definition . delete ) ?;
472
- * cache_slot = Some ( stmt) ;
473
- }
474
-
475
- return Ok ( cache_slot. as_ref ( ) . unwrap ( ) ) ;
503
+ Self :: prepare_lazily ( db, & mut self . cached_delete , & self . definition . delete )
476
504
}
477
505
}
478
506
0 commit comments