borinquenkid opened a new pull request, #16583:
URL: https://github.com/apache/grails-core/pull/16583

   ## Problem
   
   `UniqueConstraint` added a condition for a property of the unique group only 
when its value was not `null`. A `null` group value dropped the property from 
the query, so `language unique: 'country'` checked `new Language(language: 
'en')` as `where language = 'en'` and rejected it because `('en', 'US')` 
exists. The same happened for the `Requestmap` (`url unique: 'httpMethod'`) of 
the issue and for a self-referencing `Folder` (`name unique: 'parent'`), where 
a top level folder conflicted with a folder of the same name under any parent. 
This is stricter than any reading of `null`: in SQL `null` values never 
conflict, and if `null` is a value it conflicts only with another `null`. All 
datastores were affected.
   
   ## Fix
   
   A `null` group value now adds `isNull(property)` to the query, so `null` is 
compared as a value: `('Root', null)` conflicts only with another top level 
`Root`. Non null values, the handling of unsaved to-one group members and the 
`DirtyCheckable` shortcut are unchanged. The shortcut already looks at every 
group property, so changing a group value to `null` triggers validation.
   
   ## Behaviour change (who is affected)
   
   Applications that relied on a `null` group value matching every row of the 
constrained property now get a successful validation when the rows differ in 
the group property. The old behaviour was a defect and has no replacement. The 
upgrade guide gets a new `upgrading90x` page (and a `toc.yml` entry) with this 
note, and the `unique` constraint reference states the null semantics.
   
   ## Tests
   
   - `UniqueConstraintNullGroupValueSpec` (TCK, runs on every datastore that 
registers the constraint, here Hibernate 7): the `Requestmap`, `Language` and 
`Folder` shapes, several nullable group members, and changing a saved row's 
group value. Skipped on the simple in-memory datastore of the TCK, which does 
not register the `unique` constraint.
   - `UniqueConstraintSpec` in `grails-datamapping-core-test` (simple in-memory 
datastore with the constraint registered): a null group value, including a 
subclass.
   - Red before the fix, green after. `:grails-datamapping-core` (2175 tests) 
and `:grails-datamapping-core-test` (664 tests) pass; so do all `*Unique*` 
specs of `:grails-data-hibernate7-core`.
   
   Fixes #14503
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
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]

Reply via email to