-
-
Notifications
You must be signed in to change notification settings - Fork 499
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
Default filters break references loading #4975
Comments
Apparently this is expected behavior ("soft deletes"), but its current implementation is very confusing in my opinion.
|
Indeed, both
We should probably have
This is a good point, I agree we should return
I am just not fully sure about this part, while it's technically correct, it feels a bit too strict. Maybe we could (in v7) change the way references work to align it with collections more - the reference instance would be always present, and you would query that, instead of it being null when the underlying FK is null. Few years ago, one user was suggesting that and now I am finally seeing why it would be a good idea.
I am not sure about that, how would you use this information? We could store it quite easily (in
Same as the last point, I don't think this is something to change, it always worked this way. |
I am starting to think we should join the relation automatically and ensure the FK is not present when the filters disallow it. That's the only way to properly ensure things without the need for |
@darkbasic wdyt about the above? unless you are strongly opposed, I'll give that a shot today, it's pretty much the last thing I want to finalize before another RC (and technically before the stable release too, I might just ship things tomorrow if there won't be any roadblocks in this one. We are probably also missing the |
@B4nan that makes sense and would kind of remove (more on that later) the need for the reference instance to be always present instead of it being null when the underlying FK is null. One downside that I see is that you are always going to make an additional join even when you are not interested in the value of such property. Also, while that would solve the issue for default filters, that won't fix it for custom filters that you might want to apply manually to the reference via While I think that this is nice to have, it should probably be configurable if not even opt-in and in v7 we should still aim to change how references work to align them with collections. I'm also a bit skeptical of how this eagerly-join-and-remove-the-FK would interact with a user that later wants to apply a different filter to the reference, unless the FK won't be some kind of wrapper instead of null. |
Well, you have a filter that affects the FK, without the join you don't get the true value respecting the filters. Keep in mind you can always disable the filter locally (and in the end, you've opted into that by having a default filter in the first place). You can also use partial loading if you are not interested in the value at all (which reminds me I should also finally add Another argument for this is that technically, you are always interested in the value if you select it, it will end up in serialized entity even if you don't populate the relation, and speaking of the soft deletes, I doubt you would want that.
That feels like even minor issue imo, I don't want to make 99% cases less ergononic because of that (aka I'd keep the
As I said above, I prefer correctness here, that's why I want to have it enabled by default, but will be happy to make this configurable for others who might not like it.
I am still not sure about that, if we have the join, the problem is technically solved. I still like the way it works now more than having the ref instance there all the time, but open to discussion. We could run a poll in the discussions over time and see what others think, and maybe even consider having both ways (but that would complicate the types I guess, and could be a chore to maintain). |
Good, an
I don't think this issue would be solved by overloading the load() option. Let's say you have a default filter on Book.author which shows only authors that are still alive. If you run
See the previous point. |
Sounds like the internal join here should be
You would disable filters when loading the Book if that's what you are after. Also, I don't think it would be any better if we had the |
Sounds good to me. |
Btw I've started with the exclude option and it's a major chore to support this on the type level once again :D |
Yeah I would have bet on that: the most time consuming part are always the typings :] |
Looking at this again, and I actually think the problem you highlighted with I feel like we could have something like (with that said, I still believe we should have the auto joining in place for enabled filters - note that I say enabled, it is really not just about the default filters) Here is the edit: I guess I will go with |
…ection.load()` `Reference.load()` (and other methods that are using `WrappedEntity.init()` under the hood) now return `null` when the target entity is not found instead of resolving to unloaded entity. This can happen either because it was removed in the meantime, or it is not compatible with the currently enabled filters. A new method called `loadOrFail()` is added to the `Reference` class which always returns a value or throws otherwise, just like `em.findOneOrFail`. This PR also adds more options to both `Reference.load` and `Collection.load`, aligning them with the underlying methods used (`em.findOnd` and `em.populate` respectively). BREAKING CHANGE Closes #4975
…ection.load()` `Reference.load()` (and other methods that are using `WrappedEntity.init()` under the hood) now return `null` when the target entity is not found instead of resolving to unloaded entity. This can happen either because it was removed in the meantime, or it is not compatible with the currently enabled filters. A new method called `loadOrFail()` is added to the `Reference` class which always returns a value or throws otherwise, just like `em.findOneOrFail`. This PR also adds more options to both `Reference.load` and `Collection.load`, aligning them with the underlying methods used (`em.findOnd` and `em.populate` respectively). BREAKING CHANGE Closes #4975
…ection.load()` (#5025) `Reference.load()` (and other methods that are using `WrappedEntity.init()` under the hood) now return `null` when the target entity is not found instead of resolving to unloaded entity. This can happen either because it was removed in the meantime, or it is not compatible with the currently enabled filters. A new method called `loadOrFail()` is added to the `Reference` class which always returns a value or throws otherwise, just like `em.findOneOrFail`. This PR also adds more options to both `Reference.load` and `Collection.load`, aligning them with the underlying methods used (`em.findOne` and `em.populate` respectively). BREAKING CHANGE Closes #4975
Filters are applied to the relations too, as part of `JOIN ON` condition. If a filter exists on a M:1 or 1:1 relation target, such an entity will be automatically joined, and when the foreign key is defined as `NOT NULL`, it will result in an `INNER JOIN` rather than `LEFT JOIN`. This is especially important for implementing soft deletes via filters, as the foreign key might point to a soft-deleted entity. When this happens, the automatic `INNER JOIN` will result in such a record not being returned at all. You can disable this behavior via `autoJoinRefsForFilters` ORM option. Related: #4975
Filters are applied to the relations too, as part of `JOIN ON` condition. If a filter exists on a M:1 or 1:1 relation target, such an entity will be automatically joined, and when the foreign key is defined as `NOT NULL`, it will result in an `INNER JOIN` rather than `LEFT JOIN`. This is especially important for implementing soft deletes via filters, as the foreign key might point to a soft-deleted entity. When this happens, the automatic `INNER JOIN` will result in such a record not being returned at all. You can disable this behavior via `autoJoinRefsForFilters` ORM option. Related: #4975
Filters are applied to the relations too, as part of `JOIN ON` condition. If a filter exists on a M:1 or 1:1 relation target, such an entity will be automatically joined, and when the foreign key is defined as `NOT NULL`, it will result in an `INNER JOIN` rather than `LEFT JOIN`. This is especially important for implementing soft deletes via filters, as the foreign key might point to a soft-deleted entity. When this happens, the automatic `INNER JOIN` will result in such a record not being returned at all. You can disable this behavior via `autoJoinRefsForFilters` ORM option. Related: #4975
Describe the bug
If you have a reference to an
Author
who is not "old".load()
it will return just its id instead of a loaded entity.Default filters should be applied to Collections but it makes no sense to apply them to References IMO.
Reproduction
There won't be any reproduction because I've already created a failing test and the relative fix.
Since this is a prerequisite for my upcoming PR which is going to improve the Reference and Collection dataloaders this fix will be part of that PR.
What driver are you using?
@mikro-orm/sqlite
MikroORM version
git master
Node.js version
20
Operating system
Arch Linux
Validations
The text was updated successfully, but these errors were encountered: