Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
A little bit simplified than the original POC but given MongoDB's
lookupandunwindstages are not identifical to SQL joining, there are still quite some subtle tech challenges.Just realized this PR only covers basic
@ManyToOne(maybe also@OneToOne, but definitively not@OneToMany(mappedBy=...), which requires tons of code refactoring on our MQL translator; I created a broken simple integration testing class so my colleagues who love challenge could try. It is hard, I have to prewarn here). Table joining is the heart and soul of SQL and Hibernate ORM, so we have to build our features little by little.Take the following enitties with natural hiararchical relationshiop as example:
when we load a province, internally MQL translator is supposed to translate the table joining from
provincestocountries; MQL'slookupandunwindwill help as below:lookupstage, we need to create an array field containing the joining result; a natural way is to use the table alias generated by Hibernate (c1_0forcountriesandp1_0forprovinces), so after the joining,provincesdoc will contain a new array field namedc1_0; given this is atoOneassociation, the new array field contains only one entryunwindstage, the array field will be transformed to a non-array field, ending up with SQL's cartisan product analogbut there is big difference between the above transformation and SQL's table joinining. SQL's table joining has no embedding relatinoshiop and each table involved in the join will have its own global namespace (or its table alias created automatically by Hibernate).
Let us consider the
projectstage which requires irrevocable changes to our existing code for sure. In the SQL AST model, the projection list will be as below:So in our MQL doc, c1 is embedded as a new field of
provincescollection, this PR introudces some minor code loigc to translate the above SQL projection list as below:Now new project fields need to be accommodated other than the entity fields per se, so the above projection relies on the projection set feature; the new assigned field names doesn't matter for Hibernate v6 only requires the order is aligned correctly (
ResultSetJDBC methods accepting field names are not used by Hibernate ORM at all!).Another complexity is the
lookupcould be recursive (e.g.cities->provinces->countries), but the final project SQL AST uses flat global table namespaces. We need to map the deeply nested lookup new field (e.g.p1_0.c1_0is the new country nested doc incitiescollection), so some transformation logic is required. That is why a newcolumnQualifierFullPathsmap field was introduced inAbstractMqlTranslator, so it could translatec1_0.nameSQL projection entry top1_0.c1_0.namein thecitiescollection doc.After the table joining emulation is sorted out, the following typical association relationships integration testing cases all passed:
@OneToOne@ManyToOne@OneToMany@ManyToMany