@@ -103,7 +103,17 @@ impl<'a> SyncOperation<'a> {
103103
104104 self . collect_tables ( ) ?;
105105 let statement = self . collect_full_operations ( ) ?;
106- // TODO: cache statements
106+
107+ // We cache the last insert and delete statements for each row
108+ let mut last_insert_table: Option < String > = None ;
109+ let mut last_insert_statement: Option < ManagedStmt > = None ;
110+
111+ let mut last_delete_table: Option < String > = None ;
112+ let mut last_delete_statement: Option < ManagedStmt > = None ;
113+
114+ let mut untyped_delete_statement: Option < ManagedStmt > = None ;
115+ let mut untyped_insert_statement: Option < ManagedStmt > = None ;
116+
107117 while statement. step ( ) . into_db_result ( self . db ) ? == ResultCode :: ROW {
108118 let type_name = statement. column_text ( 0 ) ?;
109119 let id = statement. column_text ( 1 ) ?;
@@ -118,40 +128,70 @@ impl<'a> SyncOperation<'a> {
118128 // NULL data means no PUT operations found, so we delete the row.
119129 if data. is_err ( ) {
120130 // DELETE
121- let delete_statement = self
122- . db
123- . prepare_v2 ( & format ! ( "DELETE FROM {} WHERE id = ?" , quoted) )
124- . into_db_result ( self . db ) ?;
131+ if last_delete_table. as_deref ( ) != Some ( & quoted) {
132+ // Prepare statement when the table changed
133+ last_delete_statement = Some (
134+ self . db
135+ . prepare_v2 ( & format ! ( "DELETE FROM {} WHERE id = ?" , quoted) )
136+ . into_db_result ( self . db ) ?,
137+ ) ;
138+ last_delete_table = Some ( quoted. clone ( ) ) ;
139+ }
140+ let delete_statement = last_delete_statement. as_mut ( ) . unwrap ( ) ;
141+
142+ delete_statement. reset ( ) ?;
125143 delete_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
126144 delete_statement. exec ( ) ?;
127145 } else {
128146 // INSERT/UPDATE
129- let insert_statement = self
130- . db
131- . prepare_v2 ( & format ! ( "REPLACE INTO {}(id, data) VALUES(?, ?)" , quoted) )
132- . into_db_result ( self . db ) ?;
147+ if last_insert_table. as_deref ( ) != Some ( & quoted) {
148+ // Prepare statement when the table changed
149+ last_insert_statement = Some (
150+ self . db
151+ . prepare_v2 ( & format ! (
152+ "REPLACE INTO {}(id, data) VALUES(?, ?)" ,
153+ quoted
154+ ) )
155+ . into_db_result ( self . db ) ?,
156+ ) ;
157+ last_insert_table = Some ( quoted. clone ( ) ) ;
158+ }
159+ let insert_statement = last_insert_statement. as_mut ( ) . unwrap ( ) ;
160+ insert_statement. reset ( ) ?;
133161 insert_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
134162 insert_statement. bind_text ( 2 , data?, sqlite:: Destructor :: STATIC ) ?;
135163 insert_statement. exec ( ) ?;
136164 }
137165 } else {
138166 if data. is_err ( ) {
139167 // DELETE
140- // language=SQLite
141- let delete_statement = self
142- . db
143- . prepare_v2 ( "DELETE FROM ps_untyped WHERE type = ? AND id = ?" )
144- . into_db_result ( self . db ) ?;
168+ if untyped_delete_statement. is_none ( ) {
169+ // Prepare statement on first use
170+ untyped_delete_statement = Some (
171+ self . db
172+ . prepare_v2 ( "DELETE FROM ps_untyped WHERE type = ? AND id = ?" )
173+ . into_db_result ( self . db ) ?,
174+ ) ;
175+ }
176+ let delete_statement = untyped_delete_statement. as_mut ( ) . unwrap ( ) ;
177+ delete_statement. reset ( ) ?;
145178 delete_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
146179 delete_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
147180 delete_statement. exec ( ) ?;
148181 } else {
149182 // INSERT/UPDATE
150- // language=SQLite
151- let insert_statement = self
152- . db
153- . prepare_v2 ( "REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)" )
154- . into_db_result ( self . db ) ?;
183+ if untyped_insert_statement. is_none ( ) {
184+ // Prepare statement on first use
185+ untyped_insert_statement = Some (
186+ self . db
187+ . prepare_v2 (
188+ "REPLACE INTO ps_untyped(type, id, data) VALUES(?, ?, ?)" ,
189+ )
190+ . into_db_result ( self . db ) ?,
191+ ) ;
192+ }
193+ let insert_statement = untyped_insert_statement. as_mut ( ) . unwrap ( ) ;
194+ insert_statement. reset ( ) ?;
155195 insert_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
156196 insert_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
157197 insert_statement. bind_text ( 3 , data?, sqlite:: Destructor :: STATIC ) ?;
0 commit comments