Closed timanglade closed 7 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.
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?
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.
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.
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 ValidIf
annotation 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.
@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.
I like ObjectId
, as suggested by Andy, better. It is descriptive without incurring associations with terminology from SQL.
Minor objections/thoughts.
Id
is always weird depending on your casing rulesUnique
, Ignored
, Indexed
are adjectives but Identifier
/ ObjectId
are nouns, which I guess is fine because there can only be one of the latter whereas any property can be the former.PrimaryId
is still weird. Like, is there a SecondaryId
?Identifier
or even Id
as opposed to ObjectId
.Updated the proposal from Identifier
to ObjectId
based on opinions voiced in internal conversations.
Not at all.
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.
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).
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.
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.
FYI the Dotnet team went back to using [PrimaryKey]
sometime before our 1.0 launch ;-)
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:
(“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: