@@ -139,56 +139,56 @@ pub struct SQLiteWriter {
139
139
impl SQLiteWriter {
140
140
/// Open an in-memory database.
141
141
pub fn open_in_memory ( ) -> Result < Self > {
142
- let conn = Connection :: open_in_memory ( ) ?;
143
- Self :: init ( & conn) ?;
142
+ let mut conn = Connection :: open_in_memory ( ) ?;
143
+ Self :: init ( & mut conn) ?;
144
144
Ok ( Self { conn } )
145
145
}
146
146
147
147
/// Open a file database. If the file does not exist, it is automatically created.
148
148
/// An error is returned if the database version is not supported.
149
149
pub fn open < P : AsRef < Path > > ( path : P ) -> Result < Self > {
150
150
let is_new = !path. as_ref ( ) . exists ( ) ;
151
- let conn = Connection :: open ( path) ?;
151
+ let mut conn = Connection :: open ( path) ?;
152
152
set_pragmas_and_functions ( & conn) ?;
153
153
if is_new {
154
- Self :: init ( & conn) ?;
154
+ Self :: init ( & mut conn) ?;
155
155
} else {
156
156
check_version ( & conn) ?;
157
157
}
158
158
Ok ( Self { conn } )
159
159
}
160
160
161
161
/// Create database tables and write metadata.
162
- fn init ( conn : & Connection ) -> Result < ( ) > {
163
- conn. execute ( "BEGIN" , [ ] ) ?;
164
- conn . execute_batch ( SCHEMA ) ?;
165
- conn . execute ( "INSERT INTO metadata (version) VALUES (?)" , [ VERSION ] ) ?;
166
- conn . execute ( "COMMIT" , [ ] ) ?;
162
+ fn init ( conn : & mut Connection ) -> Result < ( ) > {
163
+ let tx = conn. transaction ( ) ?;
164
+ tx . execute_batch ( SCHEMA ) ?;
165
+ tx . execute ( "INSERT INTO metadata (version) VALUES (?)" , [ VERSION ] ) ?;
166
+ tx . commit ( ) ?;
167
167
Ok ( ( ) )
168
168
}
169
169
170
170
/// Clean all data from the database.
171
171
pub fn clean_all ( & mut self ) -> Result < usize > {
172
- self . conn . execute ( "BEGIN" , [ ] ) ?;
173
- let count = self . clean_all_inner ( ) ?;
174
- self . conn . execute ( "COMMIT" , [ ] ) ?;
172
+ let tx = self . conn . transaction ( ) ?;
173
+ let count = Self :: clean_all_inner ( & tx ) ?;
174
+ tx . commit ( ) ?;
175
175
Ok ( count)
176
176
}
177
177
178
178
/// Clean all data from the database.
179
179
///
180
180
/// This is an inner method, which does not wrap individual SQL statements in a transaction.
181
- fn clean_all_inner ( & mut self ) -> Result < usize > {
181
+ fn clean_all_inner ( conn : & Connection ) -> Result < usize > {
182
182
{
183
- let mut stmt = self . conn . prepare_cached ( "DELETE FROM file_paths" ) ?;
183
+ let mut stmt = conn. prepare_cached ( "DELETE FROM file_paths" ) ?;
184
184
stmt. execute ( [ ] ) ?;
185
185
}
186
186
{
187
- let mut stmt = self . conn . prepare_cached ( "DELETE FROM root_paths" ) ?;
187
+ let mut stmt = conn. prepare_cached ( "DELETE FROM root_paths" ) ?;
188
188
stmt. execute ( [ ] ) ?;
189
189
}
190
190
let count = {
191
- let mut stmt = self . conn . prepare_cached ( "DELETE FROM graphs" ) ?;
191
+ let mut stmt = conn. prepare_cached ( "DELETE FROM graphs" ) ?;
192
192
stmt. execute ( [ ] ) ?
193
193
} ;
194
194
Ok ( count)
@@ -197,33 +197,27 @@ impl SQLiteWriter {
197
197
/// Clean file data from the database. If recursive is true, data for all descendants of
198
198
/// that file is cleaned.
199
199
pub fn clean_file ( & mut self , file : & Path ) -> Result < usize > {
200
- self . conn . execute ( "BEGIN" , [ ] ) ?;
201
- let count = self . clean_file_inner ( file) ?;
202
- self . conn . execute ( "COMMIT" , [ ] ) ?;
200
+ let tx = self . conn . transaction ( ) ?;
201
+ let count = Self :: clean_file_inner ( & tx , file) ?;
202
+ tx . commit ( ) ?;
203
203
Ok ( count)
204
204
}
205
205
206
206
/// Clean file data from the database.
207
207
///
208
208
/// This is an inner method, which does not wrap individual SQL statements in a transaction.
209
- fn clean_file_inner ( & mut self , file : & Path ) -> Result < usize > {
209
+ fn clean_file_inner ( conn : & Connection , file : & Path ) -> Result < usize > {
210
210
let file = file. to_string_lossy ( ) ;
211
211
{
212
- let mut stmt = self
213
- . conn
214
- . prepare_cached ( "DELETE FROM file_paths WHERE file=?" ) ?;
212
+ let mut stmt = conn. prepare_cached ( "DELETE FROM file_paths WHERE file=?" ) ?;
215
213
stmt. execute ( [ & file] ) ?;
216
214
}
217
215
{
218
- let mut stmt = self
219
- . conn
220
- . prepare_cached ( "DELETE FROM root_paths WHERE file=?" ) ?;
216
+ let mut stmt = conn. prepare_cached ( "DELETE FROM root_paths WHERE file=?" ) ?;
221
217
stmt. execute ( [ & file] ) ?;
222
218
}
223
219
let count = {
224
- let mut stmt = self
225
- . conn
226
- . prepare_cached ( "DELETE FROM graphs WHERE file=?" ) ?;
220
+ let mut stmt = conn. prepare_cached ( "DELETE FROM graphs WHERE file=?" ) ?;
227
221
stmt. execute ( [ & file] ) ?
228
222
} ;
229
223
Ok ( count)
@@ -232,55 +226,56 @@ impl SQLiteWriter {
232
226
/// Clean file or directory data from the database. Data for all decendants of the given path
233
227
/// is cleaned.
234
228
pub fn clean_file_or_directory ( & mut self , file_or_directory : & Path ) -> Result < usize > {
235
- self . conn . execute ( "BEGIN" , [ ] ) ?;
236
- let count = self . clean_file_or_directory_inner ( file_or_directory) ?;
237
- self . conn . execute ( "COMMIT" , [ ] ) ?;
229
+ let tx = self . conn . transaction ( ) ?;
230
+ let count = Self :: clean_file_or_directory_inner ( & tx , file_or_directory) ?;
231
+ tx . commit ( ) ?;
238
232
Ok ( count)
239
233
}
240
234
241
235
/// Clean file or directory data from the database. Data for all decendants of the given path
242
236
/// is cleaned.
243
237
///
244
238
/// This is an inner method, which does not wrap individual SQL statements in a transaction.
245
- fn clean_file_or_directory_inner ( & mut self , file_or_directory : & Path ) -> Result < usize > {
239
+ fn clean_file_or_directory_inner ( conn : & Connection , file_or_directory : & Path ) -> Result < usize > {
246
240
let file_or_directory = file_or_directory. to_string_lossy ( ) ;
247
241
{
248
- let mut stmt = self
249
- . conn
250
- . prepare_cached ( "DELETE FROM file_paths WHERE path_descendant_of(file, ?)" ) ?;
242
+ let mut stmt =
243
+ conn. prepare_cached ( "DELETE FROM file_paths WHERE path_descendant_of(file, ?)" ) ?;
251
244
stmt. execute ( [ & file_or_directory] ) ?;
252
245
}
253
246
{
254
- let mut stmt = self
255
- . conn
256
- . prepare_cached ( "DELETE FROM root_paths WHERE path_descendant_of(file, ?)" ) ?;
247
+ let mut stmt =
248
+ conn. prepare_cached ( "DELETE FROM root_paths WHERE path_descendant_of(file, ?)" ) ?;
257
249
stmt. execute ( [ & file_or_directory] ) ?;
258
250
}
259
251
let count = {
260
- let mut stmt = self
261
- . conn
262
- . prepare_cached ( "DELETE FROM graphs WHERE path_descendant_of(file, ?)" ) ?;
252
+ let mut stmt =
253
+ conn. prepare_cached ( "DELETE FROM graphs WHERE path_descendant_of(file, ?)" ) ?;
263
254
stmt. execute ( [ & file_or_directory] ) ?
264
255
} ;
265
256
Ok ( count)
266
257
}
267
258
268
259
/// Store an error, indicating that indexing this file failed.
269
260
pub fn store_error_for_file ( & mut self , file : & Path , tag : & str , error : & str ) -> Result < ( ) > {
270
- self . conn . execute ( "BEGIN" , [ ] ) ?;
271
- self . store_error_for_file_inner ( file, tag, error) ?;
272
- self . conn . execute ( "COMMIT" , [ ] ) ?;
261
+ let tx = self . conn . transaction ( ) ?;
262
+ Self :: store_error_for_file_inner ( & tx , file, tag, error) ?;
263
+ tx . commit ( ) ?;
273
264
Ok ( ( ) )
274
265
}
275
266
276
267
/// Store an error, indicating that indexing this file failed.
277
268
///
278
269
/// This is an inner method, which does not wrap individual SQL statements in a transaction.
279
- fn store_error_for_file_inner ( & mut self , file : & Path , tag : & str , error : & str ) -> Result < ( ) > {
270
+ fn store_error_for_file_inner (
271
+ conn : & Connection ,
272
+ file : & Path ,
273
+ tag : & str ,
274
+ error : & str ,
275
+ ) -> Result < ( ) > {
280
276
copious_debugging ! ( "--> Store error for {}" , file. display( ) ) ;
281
- let mut stmt = self
282
- . conn
283
- . prepare_cached ( "INSERT INTO graphs (file, tag, error, json) VALUES (?, ?, ?, ?)" ) ?;
277
+ let mut stmt =
278
+ conn. prepare_cached ( "INSERT INTO graphs (file, tag, error, json) VALUES (?, ?, ?, ?)" ) ?;
284
279
let graph = crate :: serde:: StackGraph :: default ( ) ;
285
280
stmt. execute ( (
286
281
& file. to_string_lossy ( ) ,
@@ -304,28 +299,27 @@ impl SQLiteWriter {
304
299
IP : IntoIterator < Item = & ' a PartialPath > ,
305
300
{
306
301
let path = Path :: new ( graph[ file] . name ( ) ) ;
307
- self . conn . execute ( "BEGIN" , [ ] ) ?;
308
- self . clean_file_inner ( path) ?;
309
- self . store_graph_for_file_inner ( graph, file, tag) ?;
310
- self . store_partial_paths_for_file_inner ( graph, file, partials, paths) ?;
311
- self . conn . execute ( "COMMIT" , [ ] ) ?;
302
+ let tx = self . conn . transaction ( ) ?;
303
+ Self :: clean_file_inner ( & tx , path) ?;
304
+ Self :: store_graph_for_file_inner ( & tx , graph, file, tag) ?;
305
+ Self :: store_partial_paths_for_file_inner ( & tx , graph, file, partials, paths) ?;
306
+ tx . commit ( ) ?;
312
307
Ok ( ( ) )
313
308
}
314
309
315
310
/// Store the file graph.
316
311
///
317
312
/// This is an inner method, which does not wrap individual SQL statements in a transaction.
318
313
fn store_graph_for_file_inner (
319
- & mut self ,
314
+ conn : & Connection ,
320
315
graph : & StackGraph ,
321
316
file : Handle < File > ,
322
317
tag : & str ,
323
318
) -> Result < ( ) > {
324
319
let file_str = graph[ file] . name ( ) ;
325
320
copious_debugging ! ( "--> Store graph for {}" , file_str) ;
326
- let mut stmt = self
327
- . conn
328
- . prepare_cached ( "INSERT INTO graphs (file, tag, json) VALUES (?, ?, ?)" ) ?;
321
+ let mut stmt =
322
+ conn. prepare_cached ( "INSERT INTO graphs (file, tag, json) VALUES (?, ?, ?)" ) ?;
329
323
let graph = serde:: StackGraph :: from_graph_filter ( graph, & FileFilter ( file) ) ;
330
324
stmt. execute ( ( file_str, tag, & serde_json:: to_vec ( & graph) ?) ) ?;
331
325
Ok ( ( ) )
@@ -335,7 +329,7 @@ impl SQLiteWriter {
335
329
///
336
330
/// This is an inner method, which does not wrap individual SQL statements in a transaction.
337
331
fn store_partial_paths_for_file_inner < ' a , IP > (
338
- & mut self ,
332
+ conn : & Connection ,
339
333
graph : & StackGraph ,
340
334
file : Handle < File > ,
341
335
partials : & mut PartialPaths ,
@@ -345,11 +339,9 @@ impl SQLiteWriter {
345
339
IP : IntoIterator < Item = & ' a PartialPath > ,
346
340
{
347
341
let file_str = graph[ file] . name ( ) ;
348
- let mut node_stmt = self
349
- . conn
350
- . prepare_cached ( "INSERT INTO file_paths (file, local_id, json) VALUES (?, ?, ?)" ) ?;
351
- let mut root_stmt = self
352
- . conn
342
+ let mut node_stmt =
343
+ conn. prepare_cached ( "INSERT INTO file_paths (file, local_id, json) VALUES (?, ?, ?)" ) ?;
344
+ let mut root_stmt = conn
353
345
. prepare_cached ( "INSERT INTO root_paths (file, symbol_stack, json) VALUES (?, ?, ?)" ) ?;
354
346
#[ cfg_attr( not( feature = "copious-debugging" ) , allow( unused) ) ]
355
347
let mut node_path_count = 0usize ;
0 commit comments