netreconlab / Parse-Swift

The original (OG) Swift SDK for Parse Platform (iOS, macOS, watchOS, tvOS, visionOS, Linux, Android, Windows). This repo is maintained by Parse-Swift's original developer and all new features and bug fixes will occur here.
https://swiftpackageindex.com/netreconlab/Parse-Swift/documentation
Apache License 2.0
59 stars 6 forks source link

Creating an object with properties that are new objects which consist of the exact same properties as other new objects causes schema error #151

Open jaysonng opened 7 months ago

jaysonng commented 7 months ago

New Issue Checklist

Issue Description

saving an object with pointers and pointers point to objects with the same struct causes schema error when saving.

caught error: "ParseError code=111 error=schema mismatch for TestObject.test1; expected Pointer<Test1> but got Pointer<Test3>"

Parse-Swift in the middle of saving the pointers gets confused as to what the object is.

Steps to reproduce

Given something like so:

    struct Test1: ParseObject {
        //: Those are required for Object
        var originalData: Data?
        var objectId: String?
        var createdAt: Date?
        var updatedAt: Date?
        var ACL: ParseACL?

        var description: String?
    }

    struct Test2: ParseObject {
        //: Those are required for Object
        var originalData: Data?
        var objectId: String?
        var createdAt: Date?
        var updatedAt: Date?
        var ACL: ParseACL?

        var name: String?
    }

    struct Test3: ParseObject {
        //: Those are required for Object
        var originalData: Data?
        var objectId: String?
        var createdAt: Date?
        var updatedAt: Date?
        var ACL: ParseACL?

        var type: String?
    }

    struct TestObject: ParseObject {
        //: Those are required for Object
        var originalData: Data?
        var objectId: String?
        var createdAt: Date?
        var updatedAt: Date?
        var ACL: ParseACL?

        var test1: Test1?
        var test2: Test2?
        var test3: Test3?
    }

    func testSaving() async throws {
        var acl = ParseACL()
        acl.publicRead = true
        acl.publicWrite = false

        var testObject = TestObject()
        testObject.test1 = Test1(ACL: acl)
        testObject.test2 = Test2(ACL: acl)
        testObject.test3 = Test3(ACL: acl)

        do {
            try await testObject.save()
        } catch {
            throw error
        }
    }

running testSaving() will cause the schema error.

Even if there's only 2 that are the same - will cause an error.

        var testObject = TestObject()
        testObject.test1 = Test1(ACL: acl, description: "test1")
        testObject.test2 = Test2(ACL: acl)
        testObject.test3 = Test3(ACL: acl)

However, adding extra arguments to differentiate each object clearly like so:

 func testSaving() async throws {
        var acl = ParseACL()
        acl.publicRead = true
        acl.publicWrite = false

        var testObject = TestObject()
        testObject.test1 = Test1(ACL: acl, description: "test1")
        testObject.test2 = Test2(ACL: acl, name: "test2")
        testObject.test3 = Test3(ACL: acl, type: "test3")

        do {
            try await testObject.save()
        } catch {
            throw error
        }
    }

will save the testObject successfully.

Actual Outcome

schema error

caught error: "ParseError code=111 error=schema mismatch for TestObject.test1; expected Pointer<Test1> but got Pointer<Test3>"

Expected Outcome

object should still save successfully.

Environment

Client

Server

Database

Logs

jaysonng commented 7 months ago

To be honest I'm not sure if it's a Parse-Swift problem or something deeper with Swift itself.

But I figure the way it acts that it's something with how Pointer interacts with saving.

cbaker6 commented 7 months ago

If you run into situations like this, you should save the objects Test1, Test2, and Test3 separately and first before adding them to TestObject. I imagine the problem is the items are currently unsaved and look exactly the same when they are encoded, so the SDK is having trouble differentiating them. As soon as they are saved and obtain an objectId, the SDK can differentiate them. You also shouldn’t run into this problem if you are using custom objectIds

jaysonng commented 7 months ago

Ah i see. Gotcha.

So this isn't a bug or something we can add as. Feature request?

Thanks!

cbaker6 commented 7 months ago

I’m not sure if it will get addressed as saving like this is something that shouldn’t occur and is more of a developer error. If Test1, 2, or 3, are going to have zero properties set initially, just leave them as nil on TestObject, update the respective properties when you really have something to save. Or, if you are going to create multiple ParseObjects that have the same properties/fields, just represent them as 1 ParseObject and take advantage of “querying”.

In your examples it seems you are trying to set ACL’s. You can do that with CLP’s or by using Cloud Code when those objects are created.

jaysonng commented 7 months ago

I’m not sure if it will get addressed as saving like this is something that shouldn’t occur and is more of a developer error. If Test1, 2, or 3, are going to have zero properties set initially, just leave them as nil on TestObject, update the respective properties when you really have something to save. Or, if you are going to create multiple ParseObjects that have the same properties/fields, just represent them as 1 ParseObject and take advantage of “querying”.

In your examples it seems you are trying to set ACL’s. You can do that with CLP’s or by using Cloud Code when those objects are created.

I initially encountered this problem when I ran a check on login to make sure my User object has all the Pointers it needed. if not, it creates those objects and adds it in. They're all blank objects to start with but those objects of course can be edited by the user once they login.

so I needed them "blank".

All good though. Saving before hand worked well.