:db.unique/identity added later not enforced?

Hi, I noticed that if I add a :db.unique/identity after datoms having the attribute already created, the constraint is never enforced. Below is my reproduction.

  (def in-mem-connection2
    (do (d/create-database "datomic:mem://datamodel-schema4")
        (d/connect "datomic:mem://datamodel-schema4")))
  (d/transact in-mem-connection2
              [#:db{:ident :foo/unique-entity
                    :valueType :db.type/string,
                    :cardinality :db.cardinality/one}
               #:db{:ident :foo/bar
                    :valueType :db.type/string,
                    :cardinality :db.cardinality/one}])
  (d/transact in-mem-connection2
              [{:foo/unique-entity "foo"
                :foo/bar "bee"}
               {:foo/unique-entity "foo"
                :foo/bar "bea"}])
  ;; Succeeds even though violating records exist.
  (d/transact in-mem-connection2
              [#:db{:unique :db.unique/identity
                    :ident :foo/unique-entity}])
  ;; Succeeds
  (d/transact in-mem-connection2
              [{:foo/unique-entity "foo"
                :foo/bar "baa"}])

Tested with com.datomic/datomic-pro 0.9.6045 and in mem db.
If the :db/unique/identity is added before any records are transacted it does throw exceptions as expected.
Also queried the schema entity and indeed there was a :db.unique/unique-identity.

Hi @iku000888,

I see from your schema definition that :db/index is unset, thus Datomic is not keeping an AVET index for this attribute. In order to add :db/unique you must first have an AVET index including that attribute. Also worth noting if you add non-unique data, you will have to find and retract non-unique data before enabling a unique constraint.

https://docs.datomic.com/on-prem/schema.html#altering-attribute-to-unique

In order to add a unique constraint to an attribute, Datomic must already be maintaining an AVET index on the attribute, or the attribute must have never had any values asserted. Furthemore, if there are values present for that attribute, they must be unique in the set of current assertions. If either of these constraints are not met, the alteration will not be accepted and the transaction will fail.

Thanks,
Jaret

1 Like

Thanks! Fully understood.

Keep in mind that enabling of index is async operation and setting of unique constraints should be executed after the datomic has finished indexing