Unique constraints on blank field is not checked
- Dominant language
- Groovy
- Stars
- 2.9k
- Forks
- 975
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 92
Description
Consider the domain object:
``` groovy
class Cookie {
String name
static constraints = {
name nullable: false, blank: true, unique: true
}
}
```
Then the following test passes although it shouldn't.
``` groovy
class CookieSpec extends IntegrationSpec {
def 'validation fails'() {
setup:
def cookie = new Cookie()
def sameCookie = new Cookie()
cookie.name = ''
sameCookie.name = ''
Cookie.withTransaction{
cookie.save()
}
expect:
sameCookie.validate()
}
}
```
One cannot set the name to the empty string in the Cookie constructor as it would then yield null due to the data binding mechanism.
## Note
Not checking the unique constraint is the correct behavior for the null value, see https://jira.grails.org/browse/GRAILS-10403. At least for MySQL databases forcing the empty string to be a unique value would be consistent with the database behavior.
## Workaround
One can use a custom validator, which in our example would be
``` groovy
class Cookie {
String name
static constraints = {
name nullable: false, blank: true, validator: { val, obj -> ! Cookie.findByName(obj.name) }
}
}
```
Contributor guide
Research direction
Start by reproducing the behavior in the CookieSpec IntegrationSpec example with two Cookie objects whose name is blank, then trace the validation path for the unique constraint. Compare the handling of blank and null values, including the noted MySQL behavior and the GRAILS-10403 reference. Done means the expected blank-value uniqueness behavior is established and covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- groovy
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100