cayenne-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Erlend Birkenes ...@dataloy.com>
Subject Re: Problem with joint prefetch and flattened attributes
Date Wed, 06 Aug 2014 09:35:33 GMT
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 <andrus@objectstyle.org>:

> 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 <andrus@objectstyle.org>
> 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 <eb@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>
> >
> >
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message