rset.py
changeset 7285 39437617f3f0
parent 6915 99eb71b311e4
child 7397 6a9e66d788b3
equal deleted inserted replaced
7284:a474cb989546 7285:39437617f3f0
   473         entity = self.req.vreg['etypes'].etype_class(etype)(req, rset=self,
   473         entity = self.req.vreg['etypes'].etype_class(etype)(req, rset=self,
   474                                                             row=row, col=col)
   474                                                             row=row, col=col)
   475         entity.eid = eid
   475         entity.eid = eid
   476         # cache entity
   476         # cache entity
   477         req.set_entity_cache(entity)
   477         req.set_entity_cache(entity)
   478         eschema = entity.e_schema
       
   479         # try to complete the entity if there are some additional columns
   478         # try to complete the entity if there are some additional columns
   480         if len(rowvalues) > 1:
   479         if len(rowvalues) > 1:
   481             rqlst = self.syntax_tree()
   480             eschema = entity.e_schema
   482             if rqlst.TYPE == 'select':
   481             eid_col, attr_cols, rel_cols = self._rset_structure(eschema, col)
   483                 # UNION query, find the subquery from which this entity has been
   482             entity.eid = rowvalues[eid_col]
   484                 # found
   483             for attr, col_idx in attr_cols.items():
   485                 select, col = rqlst.locate_subquery(col, etype, self.args)
   484                 entity.cw_attr_cache[attr] = rowvalues[col_idx]
       
   485             for (rtype, role), col_idx in rel_cols.items():
       
   486                 value = rowvalues[col_idx]
       
   487                 if value is None:
       
   488                     if role == 'subject':
       
   489                         rql = 'Any Y WHERE X %s Y, X eid %s'
       
   490                     else:
       
   491                         rql = 'Any Y WHERE Y %s X, X eid %s'
       
   492                     rrset = ResultSet([], rql % (rtype, entity.eid))
       
   493                     rrset.req = req
       
   494                 else:
       
   495                     rrset = self._build_entity(row, col_idx).as_rset()
       
   496                 entity.cw_set_relation_cache(rtype, role, rrset)
       
   497         return entity
       
   498 
       
   499     @cached
       
   500     def _rset_structure(self, eschema, entity_col):
       
   501         eid_col = col = entity_col
       
   502         rqlst = self.syntax_tree()
       
   503         attr_cols = {}
       
   504         rel_cols = {}
       
   505         if rqlst.TYPE == 'select':
       
   506             # UNION query, find the subquery from which this entity has been
       
   507             # found
       
   508             select, col = rqlst.locate_subquery(entity_col, eschema.type, self.args)
       
   509         else:
       
   510             select = rqlst
       
   511         # take care, due to outer join support, we may find None
       
   512         # values for non final relation
       
   513         for i, attr, role in attr_desc_iterator(select, col, entity_col):
       
   514             if role == 'subject':
       
   515                 rschema = eschema.subjrels[attr]
   486             else:
   516             else:
   487                 select = rqlst
   517                 rschema = eschema.objrels[attr]
   488             # take care, due to outer join support, we may find None
   518             if rschema.final:
   489             # values for non final relation
   519                 if attr == 'eid':
   490             for i, attr, role in attr_desc_iterator(select, col, entity.cw_col):
   520                     eid_col = i
   491                 if role == 'subject':
       
   492                     rschema = eschema.subjrels[attr]
       
   493                     if rschema.final:
       
   494                         if attr == 'eid':
       
   495                             entity.eid = rowvalues[i]
       
   496                         else:
       
   497                             entity.cw_attr_cache[attr] = rowvalues[i]
       
   498                         continue
       
   499                 else:
   521                 else:
   500                     rschema = eschema.objrels[attr]
   522                     attr_cols[attr] = i
       
   523             else:
   501                 rdef = eschema.rdef(attr, role)
   524                 rdef = eschema.rdef(attr, role)
   502                 # only keep value if it can't be multivalued
   525                 # only keep value if it can't be multivalued
   503                 if rdef.role_cardinality(role) in '1?':
   526                 if rdef.role_cardinality(role) in '1?':
   504                     if rowvalues[i] is None:
   527                     rel_cols[(attr, role)] = i
   505                         if role == 'subject':
   528         return eid_col, attr_cols, rel_cols
   506                             rql = 'Any Y WHERE X %s Y, X eid %s'
       
   507                         else:
       
   508                             rql = 'Any Y WHERE Y %s X, X eid %s'
       
   509                         rrset = ResultSet([], rql % (attr, entity.eid))
       
   510                         rrset.req = req
       
   511                     else:
       
   512                         rrset = self._build_entity(row, i).as_rset()
       
   513                     entity.cw_set_relation_cache(attr, role, rrset)
       
   514         return entity
       
   515 
   529 
   516     @cached
   530     @cached
   517     def syntax_tree(self):
   531     def syntax_tree(self):
   518         """get the syntax tree for the source query.
   532         """get the syntax tree for the source query.
   519 
   533