New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(fix) Warn for duplicated inverseBy relationships #15217
Conversation
Codecov ReportBase: 61.25% // Head: 65.96% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #15217 +/- ##
==========================================
+ Coverage 61.25% 65.96% +4.71%
==========================================
Files 1353 1056 -297
Lines 33435 22981 -10454
Branches 6438 4120 -2318
==========================================
- Hits 20481 15160 -5321
+ Misses 11129 6889 -4240
+ Partials 1825 932 -893
Flags with carried forward coverage won't be shown. Click here to find out more. Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
` instead of inversedBy in the relation "${invRelation.inversedBy}".` | ||
); | ||
} else { | ||
// Both sides have data in the join table |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to discuss what should we do if this happens. It should be extremely rare and would only happen if useres are tweaking with the tables manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we have both directions of the relationship in the relationship table? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad wording sorry, that comment should be:
Both sides of the relation have a different join table, and both have data
Only one join table should exist, which would contain all necessary info of the relation.
In the other two cases, only one of the join tables holds data, so it's safe to remove the other. But in this case both have data, which leaves the question of what do we communicate to the user.
errorList.push( | ||
`Error on attribute "${relation.inversedBy}" in model "${contentType.tableName}"(${contentType.uid}):` + | ||
` One of the sides of the relationship must be the owning side. You should use mappedBy` + | ||
` instead of inversedBy in the relation "${relation.inversedBy}".` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending for a discussion.
Should this be an error?
It could be a little bit intrusive for the users updating to the new version , when everything was working for them before, and now getting this error.
What do you think to make this a warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the relations work if they didn't do this correctly?
If so, I guess it should be a warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer warning too. At the same time we can add some sense of urgency in the message:
"Please modify your schema by renaming the key inversedBy
by mappedBy
. Ex: { inverseBy: 'api::dog.dog' } -> { mappedBy: 'api::dog.dog' }
"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed error to a warning and also the message inside, let me know what you think. @petersg83
Also, do we have a better way to log a warning than process.emitWarning
? I don't feel it's quite visible when starting the application.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do this way as apparently it's the official way and allows some features (choosing what to log depending on server config etc.). I would say it's enough, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright :) asking just in case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job, I find the code structure clean!
I have put some comments.
packages/core/database/lib/validations/relations/bidirectional.js
Outdated
Show resolved
Hide resolved
packages/core/database/lib/validations/relations/bidirectional.js
Outdated
Show resolved
Hide resolved
packages/core/database/lib/validations/relations/bidirectional.js
Outdated
Show resolved
Hide resolved
const linkTableEmpty = await isLinkTableEmpty(db, joinTableName); | ||
const inverseLinkTableEmpty = await isLinkTableEmpty(db, inverseJoinTableName); | ||
|
||
if (linkTableEmpty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if it's not the opposite? Based on what the error message says I would put if (inverseLinkTableEmpty)
here and else if (linkTableEmpty) {
.
(or exchange the error message)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tried and I think it's just the message that as to be rewritten. I did a relation between country
and categories
and the error message is :
Error on attribute "categories" in model "categories"(api::category.category): One of the sides of the relationship must be the owning side. You should use mappedBy instead of inversedBy in the relation "categories".
It doesn't mention country
at all and it feels it should :p
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, rephrased it , let me know if it sounds better now.
packages/core/database/lib/validations/relations/bidirectional.js
Outdated
Show resolved
Hide resolved
errorList.push( | ||
`Error on attribute "${relation.inversedBy}" in model "${contentType.tableName}"(${contentType.uid}):` + | ||
` One of the sides of the relationship must be the owning side. You should use mappedBy` + | ||
` instead of inversedBy in the relation "${relation.inversedBy}".` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer warning too. At the same time we can add some sense of urgency in the message:
"Please modify your schema by renaming the key inversedBy
by mappedBy
. Ex: { inverseBy: 'api::dog.dog' } -> { mappedBy: 'api::dog.dog' }
"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works very well! It's awesome 😊 I've put a suggestion for the message. What do you think?
// Its safe to delete the inverse join table | ||
process.emitWarning( | ||
`Error on attribute "${relation.inversedBy}" in model "${invContentType.singularName}" (${invContentType.uid}).` + | ||
` Please modify your schema by renaming the key inversedBy by mappedBy.` + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
` Please modify your schema by renaming the key inversedBy by mappedBy.` + | |
` Please modify your ${invContentType.singularName} schema by renaming the key "inversedBy" by "mappedBy".` + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Same for the other message)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Well done :)
What does it do?
Warn users to fix bidirectional relations where both sides use
inversedBy
.Why is it needed?
There was this bug resolved, which was placing inversedBy in both sides of relations. Which resulted in creating two db tables for each relation.
This brought this problem for some users #14912.
Switching one of the sides to mapped by fixes the issue, but if you switch the wrong side the join table with data would be removed.
How to test it?
Create Cat content type:
Create Dog content type:
This should bring an error saying you should change one of the sides inversedBy.
To test it properly, you could try to add data in that relation and switching to this branch, to see if makes you switch the inversedBy wich removes the empty join table.
Related issue(s)/PR(s)
#14912