Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter not always finding data but the data appears to exist? #6171

Closed
bmt2018 opened this issue Jun 7, 2019 · 10 comments
Closed

Filter not always finding data but the data appears to exist? #6171

bmt2018 opened this issue Jun 7, 2019 · 10 comments

Comments

@bmt2018
Copy link

bmt2018 commented Jun 7, 2019

Goals

I'm trying to delete a child object that Is part of a list property on a parent object.

Expected Results

The child object gets deleted.

Actual Results

The child object often does get deleted as expected. However, about 25% of the time, my filter fails to return the child object yet when I iterate through the .list property on the parent object, the child object appears to be there.

I have a Swift app with a couple of models defined like this:

class Child: Object {
    @objc dynamic var id: Int = generateChildId()
    //other properties removed
}

class Parent: Object {
    @objc dynamic var id: Int = generateParentId()
    let children = List<Child>()
    //other properties removed
}

Elsewhere in my app, I have a method that deletes a Child object like this:

static func deleteChild(parentId: Int, childId: Int) {
    do {
        let realm = try Realm()
        realm.refresh()
        guard let parent = realm.objects(Parent.self).filter("id == %@", parentId).first else {
            print("Parent with ID: \(parentId) was not found!")
            return
        }

        guard let child = parent.children.filter("id == %@", childId).first else {
            print("Child with ID: \(childId) was not found!")
            print("This parent object has \(parent.children.count) children:")
            for child in parent.children {
               print("child ID: \(child.id)")
            }
            return
        }
        realm.beginWrite()
        // extraneous code removed
        realm.delete(child)            
        try realm.commitWrite()
    } catch {
        print(error)
    }
}

The Child objects are displayed in a UITableView. When I attempt to delete a Child object, I print out the child object's ID to the console and then I call the deleteChild(parentId:childId) method above. Most of the time, this works as expected. But sometimes, the code that filters the Child objects by ID fails to find the matching object and prints "Child with ID: X was not found!" to the console. When this happens, I iterate through the .children property on the Parent object and print out all of the Child objects. The thing that's confusing me is that when I do this, the Child object that I tried to find and delete appears to be there. For example:

Child with ID: 1559835636225 was not found!

This parent object has 5 children:
child ID: 1559835626285
child ID: 1559835628608
child ID: 1559835636225 <-- here is the child object that I tried to find
child ID: 1559835643522
child ID: 1559835653041

On a side note, the reason I don't just delete the child object using its "id" is because the child's id is not globally unique but rather unique among the child objects for that specific parent.

----- Update -----

I've added some more debug code into my app so that in addition to printing out the id of all the child objects in the parent object's children list, I am now also dumping the actual contents of that list to the console, as well. Furthermore, while my child ids are technically not globally unique, they effectively are in my test scenario because my Realm only has a single parent object in it. So as one last test, when my parent.children.filter("id == %@", childId).first query fails to find the child object, I added some additional code to query/retrieve the child object directly based on its id property and that works as expected. When I dump out the returned object, it is fully and correctly populated so I'm completely confused as to why my filter isn't always finding and returning the object.

Version of Realm and Tooling

Realm framework version: 3.16.1
Xcode version: 10.2
iOS/OSX version: 12.3.1
Dependency manager + version: CocoaPods 1.7.1

@tgoyne
Copy link
Member

tgoyne commented Jun 7, 2019

This does look like a bug in the query engine of some sort. The code you've shared looks fine (assuming the calling code is wrapping it in a write transaction, as otherwise realm.delete(child) would throw an exception).

If you can share the project or code which hits the problem that'd be very helpful, as otherwise I'm not sure how to go about tracking down the cause. I did try testing the simple case of just some objects with those specific IDs just in case that was somehow an issue and it wasn't.

@bmt2018
Copy link
Author

bmt2018 commented Jun 7, 2019

Thanks for the update! Your assumption about the write transaction is correct. I inadvertently removed that when I was "sanitizing" the code before posting it. I've updated my post above to reflect that. Unfortunately, my employer will not allow me to share the project but I might be able to create a small sample app that reproduces the issue.

@bmt2018
Copy link
Author

bmt2018 commented Jun 11, 2019

Since I can't share the actual project, I'm working on trying to create a sample app that reproduces the problem. On a side note, I exported the Realm from my device so I can open it in Realm Studio and that appears to confirm what I am seeing in the Xcode debug console (the child object I queried for is indeed present in the Realm and is part of the parent.children collection).

@LuckinDog
Copy link

I also meet this issue using Realm Swift, I write realm objects in a background thread, and once completed, switch to main thread to filter the objects, most of the time ,it get the correct amount of objects I had added, but sometimes, it was wrong. when I move the objects write actions in main thread, it always work. I checked the objects in Realm Studio, whether write in background thread or main thread, the objects did write to disk. So it might be bug for the filter

@LuckinDog
Copy link

add: once I write objects in background thread(I indeed commit writes), back to main thread, add realm.refresh(), then the filter result work well!

@bmt2018
Copy link
Author

bmt2018 commented Jul 2, 2019

After seeing #6192, I was finally able to get my sample app to reproduce this issue. The sample app was sent to support@realm.io.

@ironage
Copy link

ironage commented Jul 11, 2019

Thank you for your help in identifying this issue, please try out the fix in version v3.17.1.

@ironage ironage closed this as completed Jul 11, 2019
@gshahbazian
Copy link

@bmt2018 can you confirm the issue is resolved on version 3.17.1 (https://github.com/realm/realm-cocoa/blob/master/CHANGELOG.md#3171-release-notes-2019-07-10).

We upgraded to 3.17.3 and still see the bug with our filters.

@bmt2018
Copy link
Author

bmt2018 commented Sep 12, 2019

@gshahbazian yes, 3.17.1 seemed to fix this issue for us

@gshahbazian
Copy link

@bmt2018 thanks! I've opened a new issue #6249 with my specific case

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants