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

   Fixes #16700. Stacked on #16750 (it builds on the shared join table 
uniqueness of #16701 and the Db2 rules of #16750); retarget to `8.0.x` once 
those merge.
   
   ## Problem
   
   Two unidirectional `hasMany` lists (or maps) to the same class that share 
one join table could not be saved:
   
   ```
   NULL not allowed for column "ROLES_IDX"; SQL statement:
   insert into owner_role (owner_deny_roles_id, deny_roles_idx, role_id) values 
(?, ?, ?)
   ```
   
   Hibernate keys the join table of a list or a map with a primary key over its 
key and index columns (`IndexedCollection.createPrimaryKey`). On a shared table 
the next collection replaces it with its own, and it makes those columns `NOT 
NULL`, while a row of one list leaves the other list's columns null.
   
   ## Change
   
   `SharedJoinTableUniqueKeyBinder`, for each list or map of a shared table: 
makes its key and index columns nullable, drops that primary key, and gives it 
a uniqueness of its own over its key and index columns through 
`SharedJoinTableUniqueness`, the same per-database rules sets get:
   
   | Database | Two lists with a key column each | Two lists with one shared 
key column |
   |---|---|---|
   | H2, PostgreSQL, MySQL, MariaDB | a unique key per list | a unique key per 
list |
   | Oracle, Db2 LUW | a unique key per list | one unique key over the key 
column and both index columns |
   | Db2 for IBM i and z/OS | — | a `create unique where not null index` per 
list |
   | SQL Server | — | a filtered unique index per list |
   
   A position or a map key is taken once; an element may repeat, as a list 
allows. On Oracle and Db2 LUW `SharedJoinTableUniqueness` now creates the key 
when there is none to widen, since a list has no implicit unique key (a set 
always has one, so sets are unchanged).
   
   ## Tests
   
   - `SharedJoinTableListHibernate7Spec` (new): both shapes keep their lists in 
order; removing from one list keeps the other and the order of the rest; an 
element may repeat and clearing one list keeps the other; two maps keep their 
entries. A container feature writes and reads both shapes on H2, PostgreSQL, 
MySQL, MariaDB, Oracle and Db2 (CI, amd64), and checks that a second row at a 
taken position is rejected; with the uniqueness removed every database accepts 
it.
   - `SharedJoinTableUniqueKeyBinderSpec`: the DDL of two shared lists on H2, 
Oracle, Db2 LUW, IBM i and SQL Server (55/0).
   - Full `grails-data-hibernate7-core` suite locally: 4293 tests, 0 failures 
(the shared `DatabaseContainers` of #16750 makes the Oracle rows pass locally 
too).
   
   Not covered: a set that shares a join table with a list.
   
   ## Docs
   
   The shared join table note of the 8.0.x upgrade guide, with the migration a 
schema created by an earlier Grails 8 release needs (drop the primary key, make 
the index columns nullable; `dbCreate: update` changes neither), and the 
one-to-many chapter.
   
   https://claude.ai/code/session_01MDHn7fC3hsGJ27vFHD2o1p
   


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