0

I have a lot of data I need to insert in a two tables for my sqlite database. I want to put this work in the background. My flow basically goes like this: (pseudocode)

while (files in database are not parsed) {

if (fileType == type1) {
   parseType1;
   showProgress;
}
else {
   parseType2;
   showProgress;
}
}

I got the most current version of FMDB and I thought I could enqueue my data like this:

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self databasePath]];

BOOL oldshouldcachestatements = _db.shouldCacheStatements;
[_db setShouldCacheStatements:YES];
[_db beginTransaction];
NSString *insertQuery = [[NSString alloc] initWithFormat:@"INSERT INTO %@ values(null, ?, ?, ?, ?);", tableName];
[tableName release];

__block BOOL success;

// Parse each line by tabs
for (NSString *line in lines) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *fields = [line componentsSeparatedByString:@"\t"];

    // Need to check since some of the .txt files have an empty newline at the EOF.
    if ([fields count] == NUM_FIELDS) {
        NSNumber *start = [NSNumber numberWithInteger:[[fields objectAtIndex:1] integerValue]];
        NSNumber *end = [NSNumber numberWithInteger:[[fields objectAtIndex:2] integerValue]];
        NSNumber *length = [NSNumber numberWithInteger:([end integerValue] - [start integerValue])];

        NSArray *argArray = [[NSArray alloc] initWithObjects:ID, start, end, length, nil];

        [queue inDatabase:^(FMDatabase *db) {
            success = [_db executeUpdate:insertQuery withArgumentsInArray:argArray];
        }];

        [argArray release];

    }
    [pool drain];
}

Both my parseType methods look like this. When I run it on its own, I get the error that the FMDatabase is currently in use. Is it because I need to put both in the queue in the same method vs separate methods? I also tried something like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0) ^{
   parseType1;
});
dispatch_async(dispatch_get_main_queue, ^{
   update UI;
});

But I get the same problem that the db is currently in use. Am I using the FMDatabaseQueue correctly? Or do I need to do something differently? If I use NSOperationQueue here instead of GCD is that better? Thanks!

Crystal
  • 28,460
  • 62
  • 219
  • 393
  • Maybe just a typo, but within the block of the [queue inDatabase:] call you are using the variable '_db' (member variable?), not 'db' (the parameter). This could be a reason why you are getting the error, but I believe it is just a typo. – Sebastian Hojas Jul 25 '12 at 18:11
  • If using an operation queue, make sure it is serial in accordance with the README OR SUFFER. Bad things can happen when you try to parallelism SQL access. – CodaFi Jan 04 '13 at 08:56

0 Answers0