Attribute ident can't be retarget when the attribute is part of composite attribute

For some needs I have some alias ident which is moved from one attribute to another one.

Original schema is:

(def post-schema [
                   {
                       :db/ident :Post/title.version.1
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :db/fulltext true
                       :IModel/type "db"
                   }
                    {
                       :db/ident :Post/title.version.2
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :db/fulltext true
                       :IModel/type "db"
                   }
                   {
                       :db/ident :Post/category
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :IModel/type "db"
                   }
                ])
(d/transact connInternal post-schema)

And alias is set firstly for :Post/title.version.1

 (d/transact
      connInternal 
[[:db/add :Post/title.version.1 :db/ident :Post/title]] )

Now, I need to use :Post/title for :Post/title.version.2, it is done very easily by executing the next statements:

 ; Retracting of alias from first version and setting for second one

 (d/transact
      connInternal 
[[:db/add :Post/title :db/ident :Post/title.version.1] ] )

 (d/transact
      connInternal 
[[:db/add :Post/title.version.2 :db/ident :Post/title]] )

So all works fine until :Post/title.version.1 is part of composite attribute, the above statements do not work if the schema is the next:

(def post-schema [
                   {
                       :db/ident :Post/title.version.1
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :db/fulltext true
                       :IModel/type "db"
                   }
                   {
                       :db/ident :Post/title.version.2
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :IModel/type "db"
                   }
                  {
                       :db/ident :Post/category
                       :db/valueType :db.type/string
                       :db/cardinality :db.cardinality/one
                       :IModel/type "db"
                   }
                 {
                       :db/ident :Post/title.category
                       :db/valueType :db.type/tuple
                       :db/cardinality :db.cardinality/one
                       :db/tupleAttrs [:Post/title.version.1 :Post/category]
                       :IModel/type "db"
                   }
                ])
(d/transact connInternal post-schema)

In such case

 (d/transact
      connInternal 
[[:db/add :Post/title :db/ident :Post/title.version.1] ] )

is executed successfully, even the history shows, that alias ident has been retracted:

But once the next statement is executed:

 (d/transact
      connInternal 
[[:db/add :Post/title.version.2 :db/ident :Post/title]] )

Then the next error happens:

{:cognitect.anomalies/category :cognitect.anomalies/incorrect, :cognitect.anomalies/message "Ident :Post/title cannot be used for entity :Post/title.version.2, already used for :Post/title.version.1", :db/error :db.error/cannot-retarget-ident}

The error states that :Post/title is hold by :Post/title.version.1, but the history confirms that :Post/title is not linked to :Post/title.version.1

Datomic on-prem 0.9.6045

2 Likes

Guys any thoughts on the issue?
@marshall are you aware whether it is expected behaviour?

I would suggest agains changing schema attributes ever.

I think the (schema) idents are cached locally in the local connection, and somehow also resolved locally. So if you do your changes and then reconnects, does it work then?

I would recommend against anyway.

Unfortunately neither transactor restart and/or creating of new connection do not help. The same issue still happens.

Yeah, I’m understanding that such approach is not recommended but on other hand datomic allows such operation. Let me explain why I need alias idents:
There is some kind of master schema, let’s say represented as json, this schema is managed by the customer, and the customer might need to change value type of some field, since datomic does not support such kind of operation because of its history features then a new attribute is created to represent field from the customer’s schema, also there is some functionality which determines attribute ident(e.g. to execute query, transact data) based on name of field. So using of alias idents is ideal way for me since I do not need to think which exact attribute represents field from master schema now since once each time new attribute is created to reprsent field I’m setting alias ident which actually is just name of field. So everything works cool while attribute is not part of tuple attribute.

My suggestion would be to put the master schema key names in some attribute you defined on your own, just like you’ve done with :IModel/type above, and use the fact that the schema entities can have whatever data attached to them just like any other entity. These attributes are not magic and would make it easy to change and put extra data on these.

At some point I guess it would be easier (but maybe not that easy) to have just a meta layer of mappings from the master schema, and just some value-type boxes for various data types referenced by mappings. A lot of things becomes more complicated with queries etc, though.

Even more such approach was firstly developed :slight_smile: But then I got an idea why not to use alias idents, did PoC, all was working good, minus extra meta layer, the code became simpler. But I once I started to test case when some fields might be part of composite field(on datomic I used tuple attributes to reflects such composite fields from the master schema) I noticed such unexpected behaviour. I sill believe it is just some small issue on datomic side which can be easily solved

Ok! :slight_smile: Yes, it’s probably a glitch somewhere.

Can anyone from datomic team give a response on this issue?