[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) stable
authorFlorent Cayré <florent.cayre@gmail.com>
Wed, 04 May 2011 10:32:15 +0200
branchstable
changeset 7302 c281afe35b8b
parent 7298 a448e470c150
child 7303 7e7b44406cb1
[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)
cwvreg.py
entity.py
test/unittest_entity.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
 
 
--- 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':
--- 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')