realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.32k stars 2.15k forks source link

Rename "Primary Key" concept to "Object ID" #2849

Closed timanglade closed 7 years ago

timanglade commented 9 years ago

We should transition from using the concept of Primary Key, to introducing the following two concepts: ObjectId, and Unique, resulting in the following attribute hierarchy: ObjectId > Unique > Indexed. The fourth attribute, Required, will remain as it is currently.

The reasons to move away from Primary Key as as follows:

  1. The concept of a Primary Key will be unclear to anyone starting on Realm that does not have preliminary database experience. In general, we prefer to use traditional Object concepts rather than DB concepts
  2. Our current (and preferred) implementation of the Primary Key / ObjectId behavior, is not consistent with that of typical Primary Keys, as having 1 object with a null PK is allowed.

(“ObjectId” is the preferred term over “Identity” because identity can mean other things like use identity / authentication. “ObjectId is the preferred term over “Unique Identifier” because of the overlap with the attribute “Unique”)

Expected subtasks:

AndyDentFree commented 9 years ago

Providing a way to specify composite identifiers and further to specify that they be unique is very databasey and is quite a constrained feature. It also has the implication of pushing that combining logic down into core or ObjectStore.

A more general approach is to allow the user to specify that calculated property results are indexed and thus optionally unique. This allows the user to write the logic to generate the field value, as a getter. If indexed, the getter would be run just prior to saving. If not indexed, the getter is only used when the property is read.

This also becomes really useful if we implement sorting via indexes.

This feature was added to OOFILE by user demand and once people can rapidly search and sort by computed properties, they get extremely creative. It's a great enabler for a more reactive, functional way of coding because it's effectively caching a large part of a filter calculation.

cmelchior commented 9 years ago

I am not sure I see the connection between identifiers and computed properties. I agree that being able to specify indexed computed properties could be extremely useful, but isn't that orthogonal to the discussion of identifiers?

AndyDentFree commented 9 years ago

If you slightly generalise the idea of compound identifier to calculated identifier then you both empower the user's ability to manage identity and give them a very powerful feature.

One quick example - I've written multiple record management systems where the unique identifier derived from a file number was more complex than could be done by simply combining fields. In that case, I had an entirely separate field I generated on saving records, as it was in a 4GL which lacked computed fields.

That reminds me that, of course, if you give people a hook to be able to update the object on save they can always implement their own version of this just by adding a different field to be the identifier.

timanglade commented 9 years ago

I’m not sure what you propose is much better than letting people pass an array of property names to primaryKey (or identifier, unique). On one hand we cover exotic scenarios like people wanting the sum of two things being different but on the other, I think this really opens up the system for abuse. I’m not sure these attributes should be used to cover all sorts of business logic validation. But if so, I think we could come up with a drastically different API, more akin to Rails’ validators for example.

AndyDentFree commented 9 years ago

Passing an array of names assumes no other transforms and that the entirety of the value is used to compose a key. Allowing the user to write the combining function means they can do things like combine an uppercased field with a case-preserving one, or combine string and integer with a given format mask.

The Rails validators look interesting.

That is a bit orthogonal to the discussion of indexing.

Imagine you have a ValidIfannotation on a computed field (not a stored/indexed one).

That can be used for us to bar saving the object and can also be used bound to a GUI to provide user feedback that the object is not yet valid.

cmelchior commented 8 years ago

@alazier also suggested PrimaryId instead of Identifier as it still keeps some resemblance to PrimaryKey while being different. PrimaryIdentifier was also suggested but seems kinda long.

astigsen commented 8 years ago

I like ObjectId, as suggested by Andy, better. It is descriptive without incurring associations with terminology from SQL.

timanglade commented 8 years ago

Minor objections/thoughts.

timanglade commented 8 years ago

Updated the proposal from Identifier to ObjectId based on opinions voiced in internal conversations.

puttin commented 8 years ago

1192 related?

jpsim commented 8 years ago

Not at all.

AndyDentFree commented 8 years ago

I just noticed @timanglade specified the subtask

Call out in the docs that “ObjectId” is similar to the concept of a “Primary Key” but highlight the fact one ObjectId per model can be null

I think that's not quite true - to be nitpicking I think it's really allowing one ObjectId per model (aka RealmObject sublass) per Realm which can be null?

Say you have more than one Realm open with some of the same model classes in them, as you might in a complex manual migration scenario. Different, unrelated objects in different realms can have identical ObjectId values. These include one null per-Realm.

jpsim commented 8 years ago

Rename “Primary Key” to “ObjectId”. Keep both syntaxes for a certain amount of time if possible. This is a breaking API change, so will need to be done before 1.0.

I've renamed this ticket to track doing only this. See below for other pre-existing or newly created tickets to track other enhancements.

To reflect cocoa naming conventions, and to stay consistent with other schema customization APIs, this class method should be capitalized as +[RLMObject objectID].

Introduce a “Unique” attribute for properties that should be unique but not the Primary Key / ObjectId — or split to separate issue)

Already tracking as #1769.

Add ability to have composite ObjectIds (objects have one ObjectId that is the composite of several properties) —or split to separate issue.

We're tracking improved support for composite properties in #3453.

Add the ability to have composite unicity constraints (one unicity constraint as a combination of several properties — or split to seperate issue

This is the combination of two existing tickets: #1769 and #3453.

Call out in the docs that “ObjectId” is similar to the concept of a “Primary Key” but highlight the fact one ObjectId per model can be null

Docs PR: realm/realm.io#2065

Call out in the docs the hierarchy: ObjectId > Unique > Indexed

The objectID > indexed hierarchy is now documented in realm/realm.io#2065.

Documentation for a unique constraint should be added along with that functionality (tracked in #1769).

TimOliver commented 8 years ago

Just to offer my two cents in here.

As a user, I think this is a good idea. 'Object ID' is already terminology that Core Data uses, so it's definitely not a foreign concept that any Cocoa developers would be unfamiliar with. We've also strived very hard to ensure that Realm isn't viewed like a tabular database in its binding implementation, and frankly, marking these properties as 'primary keys' undermines this.

austinzheng commented 7 years ago

Cocoa has decided, regretfully, that we won't be making this change; it's too disruptive at this stage of the product's lifecycle, even for a major version increment.

AndyDentFree commented 7 years ago

FYI the Dotnet team went back to using [PrimaryKey] sometime before our 1.0 launch ;-)