> 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 <e...@dataloy.com> 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>