question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow updating of primary keys

See original GitHub issue

Goal

There should be a method for updating the primary key of an object after it has been created. Previously one could update it using e.g. object.setId(newId), but starting with Realm 2.0.0 this throws an exception to keep it in line with the Realm API in other languages. See the dicussion in Pull Request #3418. The workflow of my app is similiar to the following:

  1. User creates a new object in the database while offline
  2. This object gets a temporary (negative) id, as the app does not yet know what final id the server will assign to the object
  3. User/app syncs the database when online again
  4. The server receives the new object and assigns a final id to it
  5. The app receives the final id from the server and updates the objects id to the final one (this is currently not directly supported by Realm)

Expected Results

I personally see 2 options going forward with this:

  • Reallow changing primary key fields: this would basically put it in the same state as previously with the following code to update an objects primary key:

    TestObject object = realm.where(TestObject.class).equalTo("mId", oldId).findFirst();
    object.setId(newId);
    
  • Add dedicated method for changing primary keys: this probably makes more sense if you want to align it more with the Realm API in other languages:

    realm.updatePrimaryKey(TestObject.class, oldId, newId);
    

Actual Results

Currently only a rather ugly and not very performant workaround does the job, basically bypassing the check by making an in-memory copy of the object:

private static <E extends RealmObject> void updatePrimaryKey(Realm realm, Class<E> type, long oldId, long newId) {
    E object = realm.where(type).equalTo("mId", oldId).findFirst();
    E copy = realm.copyFromRealm(object);
    copy.setId(newId);
    realm.insertOrUpdate(copy);
    object.deleteFromRealm();
}

I’m really looking forward to seeing this fixed in a future update (though I absolutely acknowledge that you have lots of other issues to attend to 😉)

Version of Realm and tooling

Realm version(s): >2.0.0 Android Studio version: all Which Android version and device: all

References

realm-cocoa: https://github.com/realm/realm-cocoa/issues/4194

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:15
  • Comments:34 (13 by maintainers)

github_iconTop GitHub Comments

5reactions
taltstidlcommented, Nov 18, 2017

Any update on this issue? This is still a huge pain point for me. I love Realm and it is making lots of progress, yet this limitation has continued to annoy me. Currently I just copy the fields and then delete the old object, but unfortunately this triggers the change listener with a deletion and not with the new updated fields. 😢

I would be glad if you could tell me what would I need to do to remove this limitation? What parts of the code would need to be changed. Would you be interested in a pull request (that e.g. ties this limitation to the syncEnabled variable)? Thanks in advance!

2reactions
taltstidlcommented, Oct 9, 2016

@stk1m1 I understand the purpose and value of primary keys, but still I have to update my primary key once (and only once). Call it bad design, but it’s _required_ in my case. In the current library I have to do workarounds, which is ugly to say the least.

Let me reiterate this: I totally agree that primary keys normally shouldn’t be updated, there’s no doubt about that. But in my case there’s no other way. Being offline, a client can’t tell the next id that’s usable in the server database. As such, it has to assign a temporary id to the object, of which it is sure that it won’t clash with any server objects already synced with the client database (i.e. negative ids in my case). One could theoretically try to generate unique ids on the device, but there’s currently no reliable way to do this. Generating temporary ids is such the best a client can do. In order to keep everything consistent though, the client has to update the primary key after the server has assigned the final id though. That is unavoidable and currently unsupported by Realm, which is why I created this issue. I hope I could shed some more light on the use case.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to update primary key - sql server - Stack Overflow
Write a proc. · Begin a Transaction · First INSERT-SELECT a new row in the parent table, from the old row, with the...
Read more >
ALTER PRIMARY KEY | CockroachDB Docs
Use the ALTER PRIMARY KEY statement to change the primary key of a table.
Read more >
Add or change a table's primary key in Access
To set a table's primary key, open the table in Design view. Select the field (or fields) that you want to use, and...
Read more >
SQL PRIMARY KEY Constraint - W3Schools
SQL PRIMARY KEY on ALTER TABLE. ADD CONSTRAINT PK_Person PRIMARY KEY (ID,LastName); Note: If you use ALTER TABLE to add a primary key,...
Read more >
sql server - Best practice - Update Primary Keys
Once a record is created with a primary key, you really shouldn't be updating the primary key. The point of a PK is...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found