b00tsy
b00tsy

Reputation: 635

coredata sqlite malformed DB

I have problems with my coredata sqlite DB, which hosts a book DB. After a crash a user experiences has the problem, that the data isn't shown properly any more in his/her tableview.

This is due to the fact, that the performFetch method returns an error:

[NSFetchedResultsController deleteCacheWithName:nil];
if (![[self fetchedResultsController] performFetch:&error]) { 
        //NSArray *array = [[self fetchedResultsController] fetchedObjects];
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
#ifdef DEBUG
        abort();
#endif
    }

which results in this error message:

Unresolved error Error Domain=NSCocoaErrorDomain Code=134060 "The operation couldn’t be completed. (Cocoa error 134060.)" UserInfo=0x1dff80 {reason=The fetched object at index 312 has an out of order section name 'Z. Objects must be sorted by section name'}, { reason = "The fetched object at index 312 has an out of order section name 'Z. Objects must be sorted by section name'";

When I have a look into the sqlite file with 'SQLite Database Browser 2.0 b1' the attributes of each entity seem to be ok.

When I delete some of the entities being mentioned everything works fine again.

I would like to know how I can find out what exactly is wrong with the mentioned entities and fix that, so the user can use his/her data again. Of course I want to fix the bug which causes the malformed DB as well but that is out of focus in this post.

Does anybody have any hints where I could have a look at or what might be malformed within my DB or what "an out of order section name" is?

This is the code for my fetchedResultsController:

- (NSFetchedResultsController *)fetchedResultsController {

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }


    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity;
    entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:[[GlobalData sharedInstance] managedObjectContext]];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:10];

    //set searchPredicate
    NSPredicate *predicate = nil;
    if (self.bibList != nil) {
        predicate = [NSPredicate predicateWithFormat:@"ANY BibLists.name LIKE %@", self.bibList.name];      
    }

    if (predicate) {
        [fetchRequest setPredicate:predicate];
    }


    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor;   
    NSString *sortDescriptorString = nil;       
    sortDescriptorString = @"title";
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortDescriptorString ascending:YES]; 
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];   
    [fetchRequest setSortDescriptors:sortDescriptors];

    NSString *sectionNameKeyPath = nil;
    sectionNameKeyPath = @"uppercaseFirstLetterOfTitle";

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController;
    aFetchedResultsController = [[NSFetchedResultsController alloc] 
                             initWithFetchRequest:fetchRequest 
                             managedObjectContext:[[GlobalData sharedInstance] managedObjectContext] 
                             sectionNameKeyPath:sectionNameKeyPath 
                             cacheName:@"Bibliography"];

    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    return fetchedResultsController;
}    

Thanks b00tsy

Upvotes: 2

Views: 3702

Answers (2)

TechZen
TechZen

Reputation: 64428

I think what is going on here is that your SQL store is corrupted and/or you have an unusual sectionNameKeyPath.

The Core Data schema prefixes all the SQL column names with Z so an error of a name of 'Z suggest a corrupted SQL table. To test for that, execute the fetch request directly instead of using the fetched results controller and see if you can fetch all the objects.

If you can't, then the SQL store is corrupted. Most likely, some table component is simply name 'Z instead of something like ZAttributeName. You will have to edit the SQL directly but that is tricky because of the custom private schema. See this post to get an idea what to look for. There are not any tools for doing this because corruption of the store is so rare.

If the fetch works then the problem is with the sectionNameKeyPath being handed to the fetched results controller. Right now, it looks like you have an entity attribute with the first letter of the title attribute. (This is redundant because by default, the FRC will automatically return alphabetic sections based on any string attribute.) Try changing the sectionNameKeyPath to just the title attribute name (most likely "title"). In any case, just dispense with the uppercaseFirstLetterOfTitle attribute altogether.

Upvotes: 1

falconcreek
falconcreek

Reputation: 4170

The following statement in the documentation hints at the error.

If this key path is not the same as that specified by the first sort descriptor in fetchRequest, they must generate the same relative orderings.

It seems that the item at index 312 is not in the correct section when sorting on title alone. This could be a result of the title property beginning with a non-letter or lowercase letter, which using lexical sorting would put it after the Z section but the value of the item's uppercaseFirstLetterOfTitle is not 'Z'. As a suggestion, try adding a sort descriptor on the uppercaseFirstLetterOfTitle as the first sort descriptor, then add the sort descriptor on title.

Upvotes: 1

Related Questions