jagiro commented on issue #14503:
URL: https://github.com/apache/grails-core/issues/14503#issuecomment-4371569185
Confirming on Grails 7.x (Hibernate 6) — unique with nullable discriminator
emits SQL without the discriminator filter
This bug is still present in Grails 7.x with Hibernate 6. The validator's
underlying SQL omits the discriminator clause entirely when the new entity's
discriminator value is null, making the validator behave as a plain unique:true
on the main field.
Minimal reproducer
```
class Foo implements Serializable {
Bar bar
Date discriminator
static constraints = {
bar unique: ['discriminator']
discriminator nullable: true
}
}
```
```
class Bar implements Serializable {
String name
}
```
```
@Integration
@Rollback
class FooSpec extends Specification {
void "save with null discriminator must succeed when only rows with
non-null discriminator exist for the same bar"() {
given:
Bar bar = new Bar(name: 'b').save(flush: true, failOnError: true)
new Foo(bar: bar, discriminator: new Date()).save(flush: true,
failOnError: true)
when:
Foo created = new Foo(bar: bar, discriminator: null).save(flush:
true, insert: true)
then:
created != null
created.id != null
}
}
```
Expected: save passes — the combination (bar, null) is distinct from (bar,
<some date>).
Actual: ValidationException with code unique.error.
SQL evidence (MySQL 8, Hibernate 6)
The validator emits:
`select this_.id from foo this_ where this_.bar_id=? limit ?`
The discriminator column does not appear in the WHERE clause at all. The
query should include either and this_.discriminator is null or a null-safe
equivalent (and (this_.discriminator = ? or (this_.discriminator is null and ?
is null))).
Reproduced under
Grails 7.x
Hibernate 6
MySQL 8.0 server, also reproducible against H2 in tests
@GrailsCompileStatic on the domain — confirmed not the cause: removing it
does not change the behavior
cascadeValidate: 'none' on associations — confirmed not the cause
Both where{} and createCriteria{} queries against the same data show that IS
NULL translates correctly when used explicitly; the issue is purely the
validator's auto-generated query
Workaround
We removed the unique constraint from the domain and delegated the
uniqueness check to the service layer (an explicit query plus thrown
precondition exception). The original constraint was redundant in our case
anyway: the service-layer guard was already in place.
For domains where the service-layer guard is not viable, an alternative is a
custom validator: { ... } closure that performs the explicit isNull check.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]