@@ -136,11 +136,13 @@ impl<'a> SyncOperation<'a> {
136136 let statement = self . collect_full_operations ( ) ?;
137137
138138 // 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+ }
141143
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 > ;
144146
145147 let mut untyped_delete_statement: Option < ManagedStmt > = None ;
146148 let mut untyped_insert_statement: Option < ManagedStmt > = None ;
@@ -173,35 +175,50 @@ impl<'a> SyncOperation<'a> {
173175 // NULL data means no PUT operations found, so we delete the row.
174176 if data. is_err ( ) {
175177 // 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
180184 . 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+ } ;
186195
187196 delete_statement. reset ( ) ?;
188197 delete_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
189198 delete_statement. exec ( ) ?;
190199 } else {
191200 // 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
196207 . prepare_v2 ( & format ! (
197208 "REPLACE INTO {}(id, data) VALUES(?, ?)" ,
198209 quoted
199210 ) )
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+
205222 insert_statement. reset ( ) ?;
206223 insert_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
207224 insert_statement. bind_text ( 2 , data?, sqlite:: Destructor :: STATIC ) ?;
@@ -211,32 +228,38 @@ impl<'a> SyncOperation<'a> {
211228 } else {
212229 if data. is_err ( ) {
213230 // 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+
223243 delete_statement. reset ( ) ?;
224244 delete_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
225245 delete_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
226246 delete_statement. exec ( ) ?;
227247 } else {
228248 // 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+
240263 insert_statement. reset ( ) ?;
241264 insert_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
242265 insert_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
@@ -449,30 +472,35 @@ struct RawTableWithCachedStatements<'a> {
449472}
450473
451474impl < ' 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+
452492 fn put_statement (
453493 & mut self ,
454494 db : * mut sqlite:: sqlite3 ,
455495 ) -> 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 )
463497 }
464498
465499 fn delete_statement (
466500 & mut self ,
467501 db : * mut sqlite:: sqlite3 ,
468502 ) -> 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 )
476504 }
477505}
478506
0 commit comments