cubicweb/rset.py
changeset 11171 b81e543e623a
parent 11169 c1eb5a676c80
child 11767 432f87a63057
equal deleted inserted replaced
11170:d034791621ad 11171:b81e543e623a
   468         entity.eid = self.rows[row][col]
   468         entity.eid = self.rows[row][col]
   469         # cache entity
   469         # cache entity
   470         self.req.set_entity_cache(entity)
   470         self.req.set_entity_cache(entity)
   471         return entity
   471         return entity
   472 
   472 
   473     def _build_entity(self, row, col):
   473     def _build_entity(self, row, col, seen=None):
   474         """internal method to get a single entity, returns a partially
   474         """internal method to get a single entity, returns a partially
   475         initialized Entity instance.
   475         initialized Entity instance.
   476 
   476 
   477         partially means that only attributes selected in the RQL query will be
   477         partially means that only attributes selected in the RQL query will be
   478         directly assigned to the entity.
   478         directly assigned to the entity.
   482           row and col numbers localizing the entity among the result's table
   482           row and col numbers localizing the entity among the result's table
   483 
   483 
   484         :return: the partially initialized `Entity` instance
   484         :return: the partially initialized `Entity` instance
   485         """
   485         """
   486         req = self.req
   486         req = self.req
   487         if req is None:
   487         assert req is not None, 'do not call get_entity with no req on the result set'
   488             raise AssertionError('dont call get_entity with no req on the result set')
   488 
   489         rowvalues = self.rows[row]
   489         rowvalues = self.rows[row]
   490         eid = rowvalues[col]
   490         eid = rowvalues[col]
   491         assert eid is not None
   491         assert eid is not None
   492         try:
   492         try:
   493             entity = req.entity_cache(eid)
   493             entity = req.entity_cache(eid)
   494             if entity.cw_rset is self:
       
   495                 # return entity as is, avoiding recursion
       
   496                 return entity
       
   497         except KeyError:
   494         except KeyError:
   498             entity = self._make_entity(row, col)
   495             entity = self._make_entity(row, col)
   499         else:
   496         else:
   500             if entity.cw_rset is None:
   497             if entity.cw_rset is None:
   501                 # entity has no rset set, this means entity has been created by
   498                 # entity has no rset set, this means entity has been created by
   502                 # the querier (req is a repository session) and so has no rset
   499                 # the querier (req is a repository session) and so has no rset
   503                 # info. Add it.
   500                 # info. Add it.
   504                 entity.cw_rset = self
   501                 entity.cw_rset = self
   505                 entity.cw_row = row
   502                 entity.cw_row = row
   506                 entity.cw_col = col
   503                 entity.cw_col = col
       
   504         # avoid recursion
       
   505         if seen is None:
       
   506             seen = set()
       
   507         if col in seen:
       
   508             return entity
       
   509         seen.add(col)
   507         # try to complete the entity if there are some additional columns
   510         # try to complete the entity if there are some additional columns
   508         if len(rowvalues) > 1:
   511         if len(rowvalues) > 1:
   509             eschema = entity.e_schema
   512             eschema = entity.e_schema
   510             eid_col, attr_cols, rel_cols = self._rset_structure(eschema, col)
   513             eid_col, attr_cols, rel_cols = self._rset_structure(eschema, col)
   511             entity.eid = rowvalues[eid_col]
   514             entity.eid = rowvalues[eid_col]
   519                     else:
   522                     else:
   520                         rql = 'Any Y WHERE Y %s X, X eid %s'
   523                         rql = 'Any Y WHERE Y %s X, X eid %s'
   521                     rrset = ResultSet([], rql % (rtype, entity.eid))
   524                     rrset = ResultSet([], rql % (rtype, entity.eid))
   522                     rrset.req = req
   525                     rrset.req = req
   523                 else:
   526                 else:
   524                     rrset = self._build_entity(row, col_idx).as_rset()
   527                     rrset = self._build_entity(row, col_idx, seen).as_rset()
   525                 entity.cw_set_relation_cache(rtype, role, rrset)
   528                 entity.cw_set_relation_cache(rtype, role, rrset)
   526         return entity
   529         return entity
   527 
   530 
   528     @cached
   531     @cached
   529     def _rset_structure(self, eschema, entity_col):
   532     def _rset_structure(self, eschema, entity_col):