# HG changeset patch # User Florent Cayré # Date 1304497935 -7200 # Node ID c281afe35b8bc19998ca3f5596cf68a065c79c74 # Parent a448e470c1503ccb1db82d44fd13ce20eba6cb6f [entity] fix entity fetch_rql when fetch_attrs contains a rtype with multiple destination etypes which do not have the same fetched attributes themselves (closes #1631282) diff -r a448e470c150 -r c281afe35b8b cwvreg.py --- a/cwvreg.py Tue May 03 11:02:32 2011 +0200 +++ b/cwvreg.py Wed May 04 10:32:15 2011 +0200 @@ -373,6 +373,16 @@ cls.__initialize__(self.schema) return cls + def fetch_attrs(self, targettypes): + """return intersection of fetch_attrs of each entity type in + `targettypes` + """ + fetchattrs_list = [] + for ttype in targettypes: + etypecls = self.etype_class(ttype) + fetchattrs_list.append(set(etypecls.fetch_attrs)) + return reduce(set.intersection, fetchattrs_list) + VRegistry.REGISTRY_FACTORY['etypes'] = ETypeRegistry diff -r a448e470c150 -r c281afe35b8b entity.py --- a/entity.py Tue May 03 11:02:32 2011 +0200 +++ b/entity.py Wed May 04 10:32:15 2011 +0200 @@ -204,8 +204,6 @@ restriction = '%s %s %s' % (mainvar, attr, var) restrictions.append(restriction) if not rschema.final: - # XXX this does not handle several destination types - desttype = rschema.objects(eschema.type)[0] card = rdef.cardinality[0] if card not in '?1': cls.warning('bad relation %s specified in fetch attrs for %s', @@ -218,11 +216,17 @@ # that case the relation may still be missing. As we miss this # later information here, systematically add it. restrictions[-1] += '?' + targettypes = rschema.objects(eschema.type) # XXX user._cw.vreg iiiirk - destcls = user._cw.vreg['etypes'].etype_class(desttype) - destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs, - selection, orderby, restrictions, - user, ordermethod, visited=visited) + etypecls = user._cw.vreg['etypes'].etype_class(targettypes[0]) + if len(targettypes) > 1: + # find fetch_attrs common to all destination types + fetchattrs = user._cw.vreg['etypes'].fetch_attrs(targettypes) + else: + fetchattrs = etypecls.fetch_attrs + etypecls._fetch_restrictions(var, varmaker, fetchattrs, + selection, orderby, restrictions, + user, ordermethod, visited=visited) if ordermethod is not None: orderterm = getattr(cls, ordermethod)(attr, var) if orderterm: @@ -730,17 +734,13 @@ else: restriction += ', X is IN (%s)' % ','.join(targettypes) card = greater_card(rschema, targettypes, (self.e_schema,), 1) + etypecls = self._cw.vreg['etypes'].etype_class(targettypes[0]) if len(targettypes) > 1: - fetchattrs_list = [] - for ttype in targettypes: - etypecls = self._cw.vreg['etypes'].etype_class(ttype) - fetchattrs_list.append(set(etypecls.fetch_attrs)) - fetchattrs = reduce(set.intersection, fetchattrs_list) - rql = etypecls.fetch_rql(self._cw.user, [restriction], fetchattrs, - settype=False) + fetchattrs = self._cw.vreg['etypes'].fetch_attrs(targettypes) else: - etypecls = self._cw.vreg['etypes'].etype_class(targettypes[0]) - rql = etypecls.fetch_rql(self._cw.user, [restriction], settype=False) + fetchattrs = etypecls.fetch_attrs + rql = etypecls.fetch_rql(self._cw.user, [restriction], fetchattrs, + settype=False) # optimisation: remove ORDERBY if cardinality is 1 or ? (though # greater_card return 1 for those both cases) if card == '1': diff -r a448e470c150 -r c281afe35b8b test/unittest_entity.py --- a/test/unittest_entity.py Tue May 03 11:02:32 2011 +0200 +++ b/test/unittest_entity.py Wed May 04 10:32:15 2011 +0200 @@ -171,9 +171,9 @@ # testing two non final relations Personne.fetch_attrs = ('nom', 'prenom', 'travaille', 'evaluee') self.assertEqual(Personne.fetch_rql(user), - 'Any X,AA,AB,AC,AD,AE,AF ORDERBY AA ASC,AF DESC ' - 'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD, ' - 'X evaluee AE?, AE modification_date AF') + 'Any X,AA,AB,AC,AD,AE ORDERBY AA ASC ' + 'WHERE X is Personne, X nom AA, X prenom AB, X travaille AC?, AC nom AD, ' + 'X evaluee AE?') # testing one non final relation with recursion Personne.fetch_attrs = ('nom', 'prenom', 'travaille') Societe.fetch_attrs = ('nom', 'evaluee')