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]