jdaugherty commented on code in PR #16539:
URL: https://github.com/apache/grails-core/pull/16539#discussion_r4218417671
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/CompositeIdentifierToManyToOneBinder.java:
##########
@@ -126,7 +127,10 @@ private Optional<Stream<ColumnConfig>>
tryExpandNestedComposite(
if (nestedComposite == null) {
return Optional.empty();
}
+ // Hibernate sorts the properties of a composite identifier by name,
and the columns this key
+ // references follow that order, so the foreign key columns are named
in the same order
return Optional.of(Arrays.stream(nestedComposite)
+
.sorted(Comparator.comparing(HibernatePersistentProperty::getName))
Review Comment:
This orders the columns inside the nested part, but the parts themselves are
still misordered when the nested to-one is declared after a part that sorts
before it. `sortOrIndexForeignKeyColumns` passes the property permutation from
`Component.sortProperties()` to `SimpleValue.sortColumns`, which applies it to
the column list. That only lines up when every part has one column.
`getReferencedIdentifierColumns` does the same through `sortedByPermutation`.
To reproduce, declare the middle entity's nested part second:
```groovy
@Entity
class PrbGrand implements Serializable {
String zeta
String alpha
static hasMany = [middles: PrbMiddle]
static mapping = MappingBuilder.define { composite('zeta', 'alpha') }
}
@Entity
class PrbMiddle implements Serializable {
String name
static belongsTo = [grandParent: PrbGrand]
static hasMany = [leaves: PrbLeaf]
static mapping = MappingBuilder.define { composite('name',
'grandParent') }
}
@Entity
class PrbLeaf implements Serializable {
String name
static belongsTo = [middle: PrbMiddle]
static mapping = MappingBuilder.define { composite('middle', 'name') }
}
```
The leaf's foreign key, in `KEY_SEQ` order, is
`prb_middle_grand_parent_alpha, prb_middle_name, prb_middle_grand_parent_zeta`.
Saving a leaf fails:
```
Referential integrity constraint violation: "FKDEN36EQGOPJY1BD3T41V9BTYS:
PUBLIC.PRB_LEAF FOREIGN KEY(PRB_MIDDLE_GRAND_PARENT_ALPHA, PRB_MIDDLE_NAME,
PRB_MIDDLE_GRAND_PARENT_ZETA) REFERENCES PUBLIC.PRB_MIDDLE(PRB_GRAND_ALPHA,
NAME, PRB_GRAND_ZETA) ('Z', 'A', 'M')"
```
`aa54db7056` fails the same way, so this is not a regression. It is the same
nested composite chain this PR fixes, though, and the new spec misses it
because both middle entities declare `composite('grandParent', 'name')`, which
is already in name order.
I tried turning the property permutation into a column permutation, moving
each part to its sorted position across its whole column span, in both
`sortOrIndexForeignKeyColumns` and `getReferencedIdentifierColumns`. With that
change the foreign key becomes `alpha, zeta, name`, the leaf saves and reloads,
and the `*Composite*` specs still pass.
Would you be willing to fix this in this PR? If so, a middle entity that
declares `composite('name', 'grandParent')` in
`CompositeForeignKeyColumnTypesSpec` would cover it, with the `KEY_SEQ`
assertion and a save and reload.
--
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]