@@ -103,7 +103,17 @@ impl<'a> SyncOperation<'a> {
103
103
104
104
self . collect_tables ( ) ?;
105
105
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
+
107
117
while statement. step ( ) . into_db_result ( self . db ) ? == ResultCode :: ROW {
108
118
let type_name = statement. column_text ( 0 ) ?;
109
119
let id = statement. column_text ( 1 ) ?;
@@ -118,40 +128,70 @@ impl<'a> SyncOperation<'a> {
118
128
// NULL data means no PUT operations found, so we delete the row.
119
129
if data. is_err ( ) {
120
130
// 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 ( ) ?;
125
143
delete_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
126
144
delete_statement. exec ( ) ?;
127
145
} else {
128
146
// 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 ( ) ?;
133
161
insert_statement. bind_text ( 1 , id, sqlite:: Destructor :: STATIC ) ?;
134
162
insert_statement. bind_text ( 2 , data?, sqlite:: Destructor :: STATIC ) ?;
135
163
insert_statement. exec ( ) ?;
136
164
}
137
165
} else {
138
166
if data. is_err ( ) {
139
167
// 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 ( ) ?;
145
178
delete_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
146
179
delete_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
147
180
delete_statement. exec ( ) ?;
148
181
} else {
149
182
// 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 ( ) ?;
155
195
insert_statement. bind_text ( 1 , type_name, sqlite:: Destructor :: STATIC ) ?;
156
196
insert_statement. bind_text ( 2 , id, sqlite:: Destructor :: STATIC ) ?;
157
197
insert_statement. bind_text ( 3 , data?, sqlite:: Destructor :: STATIC ) ?;
0 commit comments