Ok, I'll Jira it when I have a moment. But I also just discovered that all the flattened attributes are null in the resolved objects (and in the DataRow), even though the data is present in the query result.
I was hoping there would be a quick fix to let me use joint prefetch, but this, together with the problem with combining joint and disjoint_by_id, makes me think that joint prefetch has more problems than I thought. I'll go back to using only disjoint_by_id and not dig any deeper into this, at least for now. But it would really help us a lot if we could get this to work, so maybe I can find the time later. – Erlend <http://www.dataloy-systems.com> 2014-08-06 8:40 GMT+02:00 Andrus Adamchik <[email protected]>: > Actually, checking the release notes [1], we have a bunch of > prefetch-related fixes in (yet unreleased) 3.2M2 - CAY-1928, CAY-1695, > CAY-1905. 1905 and 1928 are also fixed on 3.1 branch > > Could you maybe try your case with a source code build of Cayenne (either > 3.1 or master) ? > > Thanks, > Andrus > > [1] > https://github.com/apache/cayenne/blob/master/docs/doc/src/main/resources/RELEASE-NOTES.txt > [2] > https://github.com/apache/cayenne/blob/STABLE-3.1/docs/doc/src/main/resources/RELEASE-NOTES.txt > > On Aug 6, 2014, at 9:34 AM, Andrus Adamchik <[email protected]> > wrote: > > >> This is clearly a bug. Should I create a JIRA issue? > > > > Hi Erlend, > > > > Yes, please Jira it. Sounds like a bug. > > > > Thanks, > > Andrus > > > > > > On Aug 5, 2014, at 2:07 PM, Erlend Birkenes <[email protected]> wrote: > > > >> Hi > >> > >> I discovered a problem with joint prefetch and flattened attributes. > This > >> is in 3.1B2 which is the version we use at the moment. Not sure if this > is > >> the lates or not.. > >> > >> If I have a entity A with a normal relationship to an entity B, and B > has > >> flattened attributes from C via toCdbrel.SOME_PROPERTY. > >> This works fine normally. But when using joint prefetch the table > aliases > >> in the query will be wrong. (Querying A and prefetching B). > >> If there are multiple flattened attributes, C will also be joined in > >> multiple times. > >> > >> The problem is in SelectTranslator#appendQueryColumns. > >> This section adds columns from the target entity of a joint prefetch, > >> including relationships for flattened attributes: > >> > >> while (targetObjAttrs.hasNext()) { > >> ObjAttribute oa = targetObjAttrs.next(); > >> Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator(); > >> while (dbPathIterator.hasNext()) { > >> Object pathPart = dbPathIterator.next(); > >> > >> if (pathPart == null) { > >> throw new CayenneRuntimeException( > >> "ObjAttribute has no component: " > + > >> oa.getName()); > >> } > >> else if (pathPart instanceof DbRelationship) { > >> DbRelationship rel = (DbRelationship) pathPart; > >> dbRelationshipAdded(rel, JoinType.INNER, null); > >> //PROBLEM > >> } > >> else if (pathPart instanceof DbAttribute) { > >> DbAttribute attribute = (DbAttribute) pathPart; > >> > >> appendColumn(columns, oa, attribute, attributes, > >> labelPrefix > >> + '.' > >> + attribute.getName()); > >> } > >> } > >> } > >> > >> The problem is that dbRelationshipAdded sets the topNode of the > JoinStack > >> to the new node when a relationship is added and this is never reset in > >> this case. So every time a relationship is added in this loop it will > add a > >> node to the previously added node. This will increase the tableAlias by > 1 > >> for every relationship, and also cause any attributes directly on B to > >> belong to the wrong node and therefore get the wrong tableAlias. It will > >> also cause an additional join, but joined to the wrong table. > >> > >> The topNode of the JoinStack needs to be reset to the correct value > after > >> handing each attribute, or more presisely: after the "while > >> (dbPathIterator.hasNext())" loop the topNode needs to be the same as it > was > >> before the loop, because we are still processing attributes on the same > >> entity (B in this case). > >> > >> Storing the current topNode, and resetting it after processing each > >> attribute fixed the problem for me. Like this: > >> > >> while (targetObjAttrs.hasNext()) { > >> JoinTreeNode topNode = getJoinStack().topNode; // FIX > >> ObjAttribute oa = targetObjAttrs.next(); > >> Iterator<CayenneMapEntry> dbPathIterator = > >> oa.getDbPathIterator(); > >> while (dbPathIterator.hasNext()) { > >> Object pathPart = dbPathIterator.next(); > >> > >> if (pathPart == null) { > >> throw new CayenneRuntimeException( > >> "ObjAttribute has no component: " + > >> oa.getName()); > >> } > >> else if (pathPart instanceof DbRelationship) { > >> DbRelationship rel = (DbRelationship) > pathPart; > >> dbRelationshipAdded(rel, JoinType.INNER, > null); > >> } > >> else if (pathPart instanceof DbAttribute) { > >> DbAttribute attribute = (DbAttribute) > pathPart; > >> > >> appendColumn(columns, oa, attribute, > >> attributes, labelPrefix > >> + '.' > >> + attribute.getName()); > >> } > >> } > >> getJoinStack().topNode = topNode; // FIX > >> } > >> > >> resetJoinStack() can't be used in this case, since we don't want the > >> rootNode. > >> > >> I've run the Cayenne tests after this change with no errors, but I've > only > >> done limited testing in our own app so far. > >> > >> This is clearly a bug. Should I create a JIRA issue? > >> > >> > >> – > >> Erlend <http://www.dataloy-systems.com> > > > > > >
