matrei commented on PR #16297:
URL: https://github.com/apache/grails-core/pull/16297#issuecomment-5537409198

   Round 2:
   
   ## Review Findings
   
   The latest update adds production fixes for the codec engine and for 
mapping-engine insert/point-read behavior. The focused tests pass, but the 
mapping engine still has inconsistent update/delete and association write 
paths. There is also a regression in codec bulk updates.
   
   ## Merge Blockers
   
   ### High: Mapping-engine updates and deletes still use the wrong `_id` type
   
   References:
   
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/MongoEntityPersister.java:331-340,415-421`
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java:141-160,181-195`
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java:286-295`
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/query/MongoQuery.java:802-808`
   
   The mapping-engine insert and point-read paths now use `MongoIdCoercion`, 
but the flush path still constructs pending update and delete filters from the 
declared identifier without coercion:
   
   ```java
   final Document id = new Document(MongoConstants.MONGO_ID_FIELD, nativeKey);
   ```
   
   and:
   
   ```java
   final Object k = delete.getNativeKey();
   ```
   
   For a bare `String id` using the new ObjectId default, MongoDB stores `_id` 
as an `ObjectId`, while these filters use the String value. As a result, after 
reloading a mapping-engine entity, `save()` can fail to update it and 
`delete()` can leave it in the database.
   
   The iterable delete path also builds a query using literal `_id`, while 
`resolveIdCriterionTarget()` only recognizes the logical identity name `id`, so 
that path does not receive the new ID coercion either.
   
   The new `MappingEngineStringIdStorageSpec` only covers insert and point 
retrieval at `:59-95`; it does not cover update, single delete, iterable 
delete, or batch delete.
   
   ### High: Mapping-engine association references still use declared String IDs
   
   References:
   
   - 
`grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/engine/NativeEntryEntityPersister.java:1001-1057`
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/engine/AbstractMongoObectEntityPersister.java:197-207,328-334,434-449`
   
   The mapping engine still passes association IDs unchanged to 
`formulateDatabaseReference()` and to the association indexer. For a String-id 
target stored as ObjectId:
   
   - Plain association foreign keys are stored as BSON Strings.
   - DBRef `$id` values are stored as BSON Strings.
   - Embedded and unidirectional collection references have the same mismatch.
   
   `MongoQuery` now coerces association criteria to ObjectId, so mapping-engine 
association queries can search for ObjectIds against String foreign keys and 
return no results. This affects direct to-one queries, reverse one-to-many 
lookups, DBRefs, and association `IN`/negated criteria.
   
   The new `StringIdAssociationStorageSpec` exercises the default codec engine 
and does not exercise `MongoSession` or the mapping-engine persister.
   
   ### High: Mapping-engine `updateAll` still does not encode association values
   
   Reference:
   
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoSession.java:346-354`
   
   The mapping-engine bulk update path sends the caller's property map directly 
inside `$set`. It does not:
   
   - Extract a to-one association's identifier.
   - Coerce that identifier to the target entity's `storedAs` type.
   - Create a DBRef when the association uses `reference: true`.
   
   Therefore, with `engine: mapping`, an operation such as:
   
   ```groovy
   Parent.where { ... }.updateAll(child: child)
   ```
   
   can write an incompatible domain object or an association representation 
that cannot be queried or decoded consistently.
   
   Please add mapping-engine coverage for to-one associations, DBRefs, and bulk 
association updates.
   
   ### Medium: Codec `updateAll` mutates the caller's property map and rejects 
immutable maps
   
   Reference:
   
   - 
`grails-data-mongodb/core/src/main/groovy/org/grails/datastore/mapping/mongo/MongoCodecSession.groovy:345-374`
   
   The codec bulk-update implementation normalizes association values by 
calling `properties.put(...)` on the caller-provided map. This changes the 
caller's data:
   
   ```groovy
   def updates = [project: project]
   criteria.updateAll(updates)
   ```
   
   After the call, `updates.project` is an ObjectId or DBRef rather than the 
original domain object.
   
   It also fails for immutable maps:
   
   ```groovy
   Map updates = Collections.singletonMap('project', project)
   criteria.updateAll(updates)
   ```
   
   This throws `UnsupportedOperationException` before the update is sent. Copy 
the map before normalizing association values.
   
   ## Previous Findings Status
   
   | Finding | Status |
   | --- | --- |
   | Default incompatible with mapping engine | **Partially fixed**: insert and 
point read fixed; update, delete, and association paths remain inconsistent |
   | To-one association `IN` criteria | **Fixed for codec-backed documents; 
still inconsistent for mapping-engine data because association writes remain 
uncoerced** |
   | Negated scalar/association criteria | **Fixed for codec-backed documents; 
still inconsistent for mapping-engine data because association writes remain 
uncoerced** |
   | Codec `updateAll` association representation | **Representation fixed for 
mutable maps; map mutation and immutable-map regression introduced** |
   | Empty assigned String ID deletion | **Fixed** at 
`MongoCodecSession.groovy:204-207` |
   | Contradictory identity-generation documentation | **Fixed** at 
`idGeneration.adoc:131-171` |
   
   ## Verification
   
   The following focused command passed:
   
   ```text
   ./gradlew :grails-data-mongodb-core:test \
     --tests 
'org.grails.datastore.gorm.mongo.bugs.MappingEngineStringIdStorageSpec' \
     --tests 
'org.grails.datastore.gorm.mongo.bugs.StringIdAssociationStorageSpec' \
     --tests 
'org.grails.datastore.gorm.mongo.bugs.StringIdWithObjectIdStorageSpec' \
     --no-daemon
   ```
   
   The existing MongoDB association, negation, batch update/delete, and 
`hasOne` tests also passed. The complete `grails-data-mongodb-core` test task 
was run, but the local process exceeded the ten-minute timeout before Gradle 
printed a final completion result; no failures were visible in the captured 
output.
   
   The remaining mapping-engine issues should be fixed and covered with update, 
delete, association, DBRef, and bulk-update tests before merging.
   


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