entity.py
changeset 5174 78438ad513ca
parent 5144 5a09bea07302
child 5201 2b4267157f85
equal deleted inserted replaced
5173:73760bbb66bd 5174:78438ad513ca
   498             # object (inlined relation) or inserting some inconsistency
   498             # object (inlined relation) or inserting some inconsistency
   499             if rdef.cardinality[1] in '?1':
   499             if rdef.cardinality[1] in '?1':
   500                 continue
   500                 continue
   501             rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % (
   501             rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % (
   502                 rschema.type, rschema.type)
   502                 rschema.type, rschema.type)
   503             execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y'))
   503             execute(rql, {'x': self.eid, 'y': ceid})
   504             self.clear_related_cache(rschema.type, 'subject')
   504             self.clear_related_cache(rschema.type, 'subject')
   505         for rschema in self.e_schema.object_relations():
   505         for rschema in self.e_schema.object_relations():
   506             if rschema.meta:
   506             if rschema.meta:
   507                 continue
   507                 continue
   508             # skip already defined relations
   508             # skip already defined relations
   516             # object (inlined relation) or inserting some inconsistency
   516             # object (inlined relation) or inserting some inconsistency
   517             if rdef.cardinality[0] in '?1':
   517             if rdef.cardinality[0] in '?1':
   518                 continue
   518                 continue
   519             rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % (
   519             rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % (
   520                 rschema.type, rschema.type)
   520                 rschema.type, rschema.type)
   521             execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y'))
   521             execute(rql, {'x': self.eid, 'y': ceid})
   522             self.clear_related_cache(rschema.type, 'object')
   522             self.clear_related_cache(rschema.type, 'object')
   523 
   523 
   524     # data fetching methods ###################################################
   524     # data fetching methods ###################################################
   525 
   525 
   526     @cached
   526     @cached
   618         if selected:
   618         if selected:
   619             # select V, we need it as the left most selected variable
   619             # select V, we need it as the left most selected variable
   620             # if some outer join are included to fetch inlined relations
   620             # if some outer join are included to fetch inlined relations
   621             rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected),
   621             rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected),
   622                                     ','.join(rql))
   622                                     ','.join(rql))
   623             rset = self._cw.execute(rql, {'x': self.eid}, 'x',
   623             rset = self._cw.execute(rql, {'x': self.eid}, build_descr=False)[0]
   624                                     build_descr=False)[0]
       
   625             # handle attributes
   624             # handle attributes
   626             for i in xrange(1, lastattr):
   625             for i in xrange(1, lastattr):
   627                 self[str(selected[i-1][0])] = rset[i]
   626                 self[str(selected[i-1][0])] = rset[i]
   628             # handle relations
   627             # handle relations
   629             for i in xrange(lastattr, len(rset)):
   628             for i in xrange(lastattr, len(rset)):
   648         except KeyError:
   647         except KeyError:
   649             if not self.is_saved():
   648             if not self.is_saved():
   650                 return None
   649                 return None
   651             rql = "Any A WHERE X eid %%(x)s, X %s A" % name
   650             rql = "Any A WHERE X eid %%(x)s, X %s A" % name
   652             try:
   651             try:
   653                 rset = self._cw.execute(rql, {'x': self.eid}, 'x')
   652                 rset = self._cw.execute(rql, {'x': self.eid})
   654             except Unauthorized:
   653             except Unauthorized:
   655                 self[name] = value = None
   654                 self[name] = value = None
   656             else:
   655             else:
   657                 assert rset.rowcount <= 1, (self, rql, rset.rowcount)
   656                 assert rset.rowcount <= 1, (self, rql, rset.rowcount)
   658                 try:
   657                 try:
   679             return self.related_cache(rtype, role, entities, limit)
   678             return self.related_cache(rtype, role, entities, limit)
   680         except KeyError:
   679         except KeyError:
   681             pass
   680             pass
   682         assert self.has_eid()
   681         assert self.has_eid()
   683         rql = self.related_rql(rtype, role)
   682         rql = self.related_rql(rtype, role)
   684         rset = self._cw.execute(rql, {'x': self.eid}, 'x')
   683         rset = self._cw.execute(rql, {'x': self.eid})
   685         self.set_related_cache(rtype, role, rset)
   684         self.set_related_cache(rtype, role, rset)
   686         return self.related(rtype, role, limit, entities)
   685         return self.related(rtype, role, limit, entities)
   687 
   686 
   688     def related_rql(self, rtype, role='subject', targettypes=None):
   687     def related_rql(self, rtype, role='subject', targettypes=None):
   689         rschema = self._cw.vreg.schema[rtype]
   688         rschema = self._cw.vreg.schema[rtype]
   805         except Unauthorized:
   804         except Unauthorized:
   806             return self._cw.empty_rset()
   805             return self._cw.empty_rset()
   807         if limit is not None:
   806         if limit is not None:
   808             before, after = rql.split(' WHERE ', 1)
   807             before, after = rql.split(' WHERE ', 1)
   809             rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
   808             rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
   810         return self._cw.execute(rql, args, tuple(args))
   809         return self._cw.execute(rql, args)
   811 
   810 
   812     # relations cache handling ################################################
   811     # relations cache handling ################################################
   813 
   812 
   814     def relation_cached(self, rtype, role):
   813     def relation_cached(self, rtype, role):
   815         """return true if the given relation is already cached on the instance
   814         """return true if the given relation is already cached on the instance
   888         for key in kwargs:
   887         for key in kwargs:
   889             relations.append('X %s %%(%s)s' % (key, key))
   888             relations.append('X %s %%(%s)s' % (key, key))
   890         # and now update the database
   889         # and now update the database
   891         kwargs['x'] = self.eid
   890         kwargs['x'] = self.eid
   892         self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
   891         self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
   893                          kwargs, 'x')
   892                          kwargs)
   894         kwargs.pop('x')
   893         kwargs.pop('x')
   895         # update current local object _after_ the rql query to avoid
   894         # update current local object _after_ the rql query to avoid
   896         # interferences between the query execution itself and the
   895         # interferences between the query execution itself and the
   897         # edited_attributes / skip_security_attributes machinery
   896         # edited_attributes / skip_security_attributes machinery
   898         self.update(kwargs)
   897         self.update(kwargs)
   911                 restr = 'Y %s X' % attr[len('reverse_'):]
   910                 restr = 'Y %s X' % attr[len('reverse_'):]
   912             else:
   911             else:
   913                 restr = 'X %s Y' % attr
   912                 restr = 'X %s Y' % attr
   914             if values is None:
   913             if values is None:
   915                 self._cw.execute('DELETE %s WHERE X eid %%(x)s' % restr,
   914                 self._cw.execute('DELETE %s WHERE X eid %%(x)s' % restr,
   916                                  {'x': self.eid}, 'x')
   915                                  {'x': self.eid})
   917                 continue
   916                 continue
   918             if not isinstance(values, (tuple, list, set, frozenset)):
   917             if not isinstance(values, (tuple, list, set, frozenset)):
   919                 values = (values,)
   918                 values = (values,)
   920             self._cw.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
   919             self._cw.execute('SET %s WHERE X eid %%(x)s, Y eid IN (%s)' % (
   921                 restr, ','.join(str(r.eid) for r in values)),
   920                 restr, ','.join(str(r.eid) for r in values)),
   922                              {'x': self.eid}, 'x')
   921                              {'x': self.eid})
   923 
   922 
   924     def delete(self, **kwargs):
   923     def delete(self, **kwargs):
   925         assert self.has_eid(), self.eid
   924         assert self.has_eid(), self.eid
   926         self._cw.execute('DELETE %s X WHERE X eid %%(x)s' % self.e_schema,
   925         self._cw.execute('DELETE %s X WHERE X eid %%(x)s' % self.e_schema,
   927                          {'x': self.eid}, **kwargs)
   926                          {'x': self.eid}, **kwargs)