jamesfredley commented on code in PR #16756:
URL: https://github.com/apache/grails-core/pull/16756#discussion_r4369042298


##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/SharedJoinTableUniqueKeyBinder.java:
##########
@@ -146,6 +157,41 @@ private void restrictRowsToOwnCollection(Collection 
collection, Table table) {
         }
     }
 
+    /**
+     * Hibernate keys the join table of a list or a map by the key and the 
index columns of the collection, with a
+     * primary key over them ({@code IndexedCollection.createPrimaryKey}), 
which the next collection of a shared table
+     * replaces with its own, and which makes them not null. A row of one 
collection leaves the columns of the others
+     * null, so on a shared table that key fails the first insert of every 
collection but the last
+     * (apache/grails-core#16700). Each list or map of the table loses that 
primary key, gets nullable key and index
+     * columns, and a uniqueness of its own over them in the shape the 
database needs ({@link SharedJoinTableUniqueness}):
+     * a position, or a map key, is taken once in the collection, while its 
elements may repeat.
+     */
+    private void makeIndexedCollectionsShareable(List<Collection> sharing, 
Table table) {
+        for (Collection member : sharing) {
+            if (!(member instanceof IndexedCollection indexed) || 
indexed.getIndex() == null) {
+                continue;
+            }
+            List<Column> keyColumns = member.getKey().getColumns();
+            List<Column> indexColumns = new ArrayList<>();
+            for (Selectable selectable : indexed.getIndex().getSelectables()) {
+                if (selectable instanceof Column column) {
+                    indexColumns.add(column);
+                }
+            }
+            if (keyColumns.isEmpty() || indexColumns.isEmpty()) {
+                continue;
+            }
+            Set<Column> own = new HashSet<>(keyColumns);
+            own.addAll(indexColumns);
+            if (table.hasPrimaryKey() && 
own.containsAll(table.getPrimaryKey().getColumns())) {
+                table.setPrimaryKey(null);
+            }
+            keyColumns.forEach(column -> column.setNullable(true));

Review Comment:
   Two lists that share `owner_id` and `role_id`, with separate index columns 
`roles_idx` and `deny_roles_idx`, both get `role_id is not null`. Clearing one 
after both are flushed deletes both. Loading either list also selects the other 
list's rows, whose index is null, and throws.
   
   Include that collection's own index column in the restriction. Please flush 
both, clear one, and assert the other remains.



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