345 raise NotAnEntity(etype) |
345 raise NotAnEntity(etype) |
346 except KeyError: |
346 except KeyError: |
347 raise NotAnEntity(etype) |
347 raise NotAnEntity(etype) |
348 return self._build_entity(row, col) |
348 return self._build_entity(row, col) |
349 |
349 |
350 def _build_entity(self, row, col, _localcache=None): |
350 def _build_entity(self, row, col): |
351 """internal method to get a single entity, returns a |
351 """internal method to get a single entity, returns a |
352 partially initialized Entity instance. |
352 partially initialized Entity instance. |
353 |
353 |
354 partially means that only attributes selected in the RQL |
354 partially means that only attributes selected in the RQL |
355 query will be directly assigned to the entity. |
355 query will be directly assigned to the entity. |
368 assert eid is not None |
368 assert eid is not None |
369 # return cached entity if exists. This also avoids potential recursion |
369 # return cached entity if exists. This also avoids potential recursion |
370 # XXX should we consider updating a cached entity with possible |
370 # XXX should we consider updating a cached entity with possible |
371 # new attributes found in this resultset ? |
371 # new attributes found in this resultset ? |
372 try: |
372 try: |
373 if hasattr(req, 'is_super_session'): |
373 return req.entity_cache(eid) |
374 # this is a Session object which is not caching entities, so we |
|
375 # have to use a local cache to avoid recursion pb |
|
376 if _localcache is None: |
|
377 _localcache = {} |
|
378 return _localcache[eid] |
|
379 else: |
|
380 return req.entity_cache(eid) |
|
381 except KeyError: |
374 except KeyError: |
382 pass |
375 pass |
383 # build entity instance |
376 # build entity instance |
384 etype = self.description[row][col] |
377 etype = self.description[row][col] |
385 entity = self.vreg.etype_class(etype)(req, self, row, col) |
378 entity = self.vreg.etype_class(etype)(req, self, row, col) |
386 entity.set_eid(eid) |
379 entity.set_eid(eid) |
387 # cache entity |
380 # cache entity |
388 if _localcache is not None: |
|
389 _localcache[eid] = entity |
|
390 req.set_entity_cache(entity) |
381 req.set_entity_cache(entity) |
391 eschema = entity.e_schema |
382 eschema = entity.e_schema |
392 # try to complete the entity if there are some additional columns |
383 # try to complete the entity if there are some additional columns |
393 if len(rowvalues) > 1: |
384 if len(rowvalues) > 1: |
394 rqlst = self.syntax_tree() |
385 rqlst = self.syntax_tree() |
418 else: |
409 else: |
419 rql = 'Any Y WHERE Y %s X, X eid %s' |
410 rql = 'Any Y WHERE Y %s X, X eid %s' |
420 rrset = ResultSet([], rql % (attr, entity.eid)) |
411 rrset = ResultSet([], rql % (attr, entity.eid)) |
421 req.decorate_rset(rrset) |
412 req.decorate_rset(rrset) |
422 else: |
413 else: |
423 rrset = self._build_entity(row, i, _localcache).as_rset() |
414 rrset = self._build_entity(row, i).as_rset() |
424 entity.set_related_cache(attr, x, rrset) |
415 entity.set_related_cache(attr, x, rrset) |
425 return entity |
416 return entity |
426 |
417 |
427 @cached |
418 @cached |
428 def syntax_tree(self): |
419 def syntax_tree(self): |