EOF Bug: Prefetching self-referential relationships corrupts the object graph
EOF Bug: Prefetching self-referential relationships corrupts the object graph
- Subject: EOF Bug: Prefetching self-referential relationships corrupts the object graph
- From: Ramsey Gurley <email@hidden>
- Date: Mon, 27 Apr 2015 11:51:31 -0700
Ran into this and thought I should share :)
If you have a table that relates to itself, prefetching across that relationship can wreck your object graph. As an example, let’s say you have an Employee entity. Employee has a relationship to Employee named manager, the reverse of which is subordinates. Further assume manager is top level so a manager’s manager is himself. If you are given a single Employee, and want to know something about all subordinates, you may do something like
EOQualifier q = Employee.SALARY.greaterThan(5000);
EOFetchSpec fs = …
fs.setPrefetchingKeyPaths(“manager.subordinates.restOfPath”);
The problem is in how EOF handles prefetches, it builds qualifier’s backwards for the original fetch. So first it fetches Employee with salary > 5000. Next it fetches managers, which are also employees, so the qualifier on that prefetch is subordinates.salary > 5000, then on the next step, rather than producing manager.subordinates.salary, it notices the relationship is circular and just lops off subordinates leaving salary.
In my case, this left me with a qualifier that only matched the manager for the prefetch. What’s worse, the subordinates relationship was then only populated with the manager by EOF. So in a case where manager.subordinates().count() should equal 5, it was only 1.
This appears to be happening in EOKeyValueQualifier’s sql generation support class. It looks like it might be something that could be patched in ERXExtensions as there is already some patching in there for stuff like the ERX regex qualifiers and such.
ERXBatchFetchingUtils works properly in this case, but that is significantly slower than prefetching due to the sql generated.
My workaround for this problem seems to work. I created a second copy of the relationship. So in the above example, I have manager, boss, subordinates, and underlings. boss == manager, and underlings == subordinate. I make these duplicate relationships non-class properties. Then with a ERXKey that I place in Employee, I can make my prefetch path look like “boss.subordinates.restOfPath”. Both ends of the relationship must exist or EOF finds the subordinates relationship anyway and the bug still happens. I also had to implement handleUnbound for the Employee on the boss relationship path. Since these are basically read-only relationships for my case, it works. It may not work as smoothly in others.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden