Search code examples
swiftcore-datansbatchdeleterequest

NSBatchDeleteRequest deletes all child entities


My CoreData model got two child entities "CarA" and "CarB" with the same abstract parent entity "Car".

I'm trying to delete all CarA objects using

    func deleteObjects(entityName: String) {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
        do {
            try context.execute(deleteRequest)
        } catch let error as NSError {
            print(error)
        }
    }

Executing deleteObjects("CarA") results in deleting not only all CarA objects, but also all CarB objects as well.


Solution

  • This looks to me like a bug. If you enable SQLDebug, you can see from the console output that the entire parent entity is deleted:

    CoreData: sql: BEGIN EXCLUSIVE
    CoreData: sql: DELETE FROM ZABSTRACT
    CoreData: sql: COMMIT
    

    (my parent entity is named "Abstract"). But I notice that if you add a predicate, CoreData remembers to qualify the underlying fetch to restrict it to the correct child entity. So a workaround is to add a predicate that is always true:

    fetchRequest.predicate = NSPredicate(value:true)
    

    and the resulting console output is:

    CoreData: sql: BEGIN EXCLUSIVE
    CoreData: sql: DELETE FROM ZABSTRACT WHERE Z_PK IN (SELECT t0.Z_PK FROM ZABSTRACT t0 WHERE  t0.Z_ENT = ? )
    CoreData: sql: COMMIT
    

    It seems CoreData even optimises out the true predicate, leaving only the WHERE clause to limit the delete to the correct entity.