entity.py
changeset 3378 2f25f701301d
parent 3376 f5c69485381f
child 3382 435286b8fe10
equal deleted inserted replaced
3377:dd9d292b6a6d 3378:2f25f701301d
   164                 # (card == '?')  *or if the entity is being added*, since in
   164                 # (card == '?')  *or if the entity is being added*, since in
   165                 # that case the relation may still be missing. As we miss this
   165                 # that case the relation may still be missing. As we miss this
   166                 # later information here, systematically add it.
   166                 # later information here, systematically add it.
   167                 restrictions[-1] += '?'
   167                 restrictions[-1] += '?'
   168                 # XXX user.req.vreg iiiirk
   168                 # XXX user.req.vreg iiiirk
   169                 destcls = user.req.vreg['etypes'].etype_class(desttype)
   169                 destcls = user._cw.vreg['etypes'].etype_class(desttype)
   170                 destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs,
   170                 destcls._fetch_restrictions(var, varmaker, destcls.fetch_attrs,
   171                                             selection, orderby, restrictions,
   171                                             selection, orderby, restrictions,
   172                                             user, ordermethod, visited=visited)
   172                                             user, ordermethod, visited=visited)
   173             orderterm = getattr(cls, ordermethod)(attr, var)
   173             orderterm = getattr(cls, ordermethod)(attr, var)
   174             if orderterm:
   174             if orderterm:
   245         """
   245         """
   246         return self.has_eid() and self._is_saved
   246         return self.has_eid() and self._is_saved
   247 
   247 
   248     @cached
   248     @cached
   249     def metainformation(self):
   249     def metainformation(self):
   250         res = dict(zip(('type', 'source', 'extid'), self.req.describe(self.eid)))
   250         res = dict(zip(('type', 'source', 'extid'), self._cw.describe(self.eid)))
   251         res['source'] = self.req.source_defs()[res['source']]
   251         res['source'] = self._cw.source_defs()[res['source']]
   252         return res
   252         return res
   253 
   253 
   254     def clear_local_perm_cache(self, action):
   254     def clear_local_perm_cache(self, action):
   255         for rqlexpr in self.e_schema.get_rqlexprs(action):
   255         for rqlexpr in self.e_schema.get_rqlexprs(action):
   256             self.req.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None)
   256             self._cw.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None)
   257 
   257 
   258     def check_perm(self, action):
   258     def check_perm(self, action):
   259         self.e_schema.check_perm(self.req, action, self.eid)
   259         self.e_schema.check_perm(self._cw, action, self.eid)
   260 
   260 
   261     def has_perm(self, action):
   261     def has_perm(self, action):
   262         return self.e_schema.has_perm(self.req, action, self.eid)
   262         return self.e_schema.has_perm(self._cw, action, self.eid)
   263 
   263 
   264     def view(self, vid, __registry='views', **kwargs):
   264     def view(self, vid, __registry='views', **kwargs):
   265         """shortcut to apply a view on this entity"""
   265         """shortcut to apply a view on this entity"""
   266         return self.vreg[__registry].render(vid, self.req, rset=self.rset,
   266         return self._cw.vreg[__registry].render(
   267                                             row=self.row, col=self.col, **kwargs)
   267             vid, self._cw, rset=self.rset, row=self.row, col=self.col, **kwargs)
   268 
   268 
   269     def absolute_url(self, *args, **kwargs):
   269     def absolute_url(self, *args, **kwargs):
   270         """return an absolute url to view this entity"""
   270         """return an absolute url to view this entity"""
   271         # use *args since we don't want first argument to be "anonymous" to
   271         # use *args since we don't want first argument to be "anonymous" to
   272         # avoid potential clash with kwargs
   272         # avoid potential clash with kwargs
   276         else:
   276         else:
   277             method = None
   277             method = None
   278         # in linksearch mode, we don't want external urls else selecting
   278         # in linksearch mode, we don't want external urls else selecting
   279         # the object for use in the relation is tricky
   279         # the object for use in the relation is tricky
   280         # XXX search_state is web specific
   280         # XXX search_state is web specific
   281         if getattr(self.req, 'search_state', ('normal',))[0] == 'normal':
   281         if getattr(self._cw, 'search_state', ('normal',))[0] == 'normal':
   282             kwargs['base_url'] = self.metainformation()['source'].get('base-url')
   282             kwargs['base_url'] = self.metainformation()['source'].get('base-url')
   283         if method in (None, 'view'):
   283         if method in (None, 'view'):
   284             try:
   284             try:
   285                 kwargs['_restpath'] = self.rest_path(kwargs.get('base_url'))
   285                 kwargs['_restpath'] = self.rest_path(kwargs.get('base_url'))
   286             except TypeError:
   286             except TypeError:
   287                 warn('%s: rest_path() now take use_ext_eid argument, '
   287                 warn('%s: rest_path() now take use_ext_eid argument, '
   288                      'please update' % self.__regid__, DeprecationWarning)
   288                      'please update' % self.__regid__, DeprecationWarning)
   289                 kwargs['_restpath'] = self.rest_path()
   289                 kwargs['_restpath'] = self.rest_path()
   290         else:
   290         else:
   291             kwargs['rql'] = 'Any X WHERE X eid %s' % self.eid
   291             kwargs['rql'] = 'Any X WHERE X eid %s' % self.eid
   292         return self.req.build_url(method, **kwargs)
   292         return self._cw.build_url(method, **kwargs)
   293 
   293 
   294     def rest_path(self, use_ext_eid=False):
   294     def rest_path(self, use_ext_eid=False):
   295         """returns a REST-like (relative) path for this entity"""
   295         """returns a REST-like (relative) path for this entity"""
   296         mainattr, needcheck = self._rest_attr_info()
   296         mainattr, needcheck = self._rest_attr_info()
   297         etype = str(self.e_schema)
   297         etype = str(self.e_schema)
   303                 path += '/eid'
   303                 path += '/eid'
   304             elif needcheck:
   304             elif needcheck:
   305                 # make sure url is not ambiguous
   305                 # make sure url is not ambiguous
   306                 rql = 'Any COUNT(X) WHERE X is %s, X %s %%(value)s' % (
   306                 rql = 'Any COUNT(X) WHERE X is %s, X %s %%(value)s' % (
   307                     etype, mainattr)
   307                     etype, mainattr)
   308                 nbresults = self.req.execute(rql, {'value' : value})[0][0]
   308                 nbresults = self._cw.execute(rql, {'value' : value})[0][0]
   309                 if nbresults != 1: # ambiguity?
   309                 if nbresults != 1: # ambiguity?
   310                     mainattr = 'eid'
   310                     mainattr = 'eid'
   311                     path += '/eid'
   311                     path += '/eid'
   312         if mainattr == 'eid':
   312         if mainattr == 'eid':
   313             if use_ext_eid:
   313             if use_ext_eid:
   314                 value = self.metainformation()['extid']
   314                 value = self.metainformation()['extid']
   315             else:
   315             else:
   316                 value = self.eid
   316                 value = self.eid
   317         return '%s/%s' % (path, self.req.url_quote(value))
   317         return '%s/%s' % (path, self._cw.url_quote(value))
   318 
   318 
   319     def attr_metadata(self, attr, metadata):
   319     def attr_metadata(self, attr, metadata):
   320         """return a metadata for an attribute (None if unspecified)"""
   320         """return a metadata for an attribute (None if unspecified)"""
   321         value = getattr(self, '%s_%s' % (attr, metadata), None)
   321         value = getattr(self, '%s_%s' % (attr, metadata), None)
   322         if value is None and metadata == 'encoding':
   322         if value is None and metadata == 'encoding':
   323             value = self.vreg.property_value('ui.encoding')
   323             value = self._cw.vreg.property_value('ui.encoding')
   324         return value
   324         return value
   325 
   325 
   326     def printable_value(self, attr, value=_marker, attrtype=None,
   326     def printable_value(self, attr, value=_marker, attrtype=None,
   327                         format='text/html', displaytime=True):
   327                         format='text/html', displaytime=True):
   328         """return a displayable value (i.e. unicode string) which may contains
   328         """return a displayable value (i.e. unicode string) which may contains
   340         props = self.e_schema.rproperties(attr)
   340         props = self.e_schema.rproperties(attr)
   341         if attrtype == 'String':
   341         if attrtype == 'String':
   342             # internalinalized *and* formatted string such as schema
   342             # internalinalized *and* formatted string such as schema
   343             # description...
   343             # description...
   344             if props.get('internationalizable'):
   344             if props.get('internationalizable'):
   345                 value = self.req._(value)
   345                 value = self._cw._(value)
   346             attrformat = self.attr_metadata(attr, 'format')
   346             attrformat = self.attr_metadata(attr, 'format')
   347             if attrformat:
   347             if attrformat:
   348                 return self.mtc_transform(value, attrformat, format,
   348                 return self.mtc_transform(value, attrformat, format,
   349                                           self.req.encoding)
   349                                           self._cw.encoding)
   350         elif attrtype == 'Bytes':
   350         elif attrtype == 'Bytes':
   351             attrformat = self.attr_metadata(attr, 'format')
   351             attrformat = self.attr_metadata(attr, 'format')
   352             if attrformat:
   352             if attrformat:
   353                 encoding = self.attr_metadata(attr, 'encoding')
   353                 encoding = self.attr_metadata(attr, 'encoding')
   354                 return self.mtc_transform(value.getvalue(), attrformat, format,
   354                 return self.mtc_transform(value.getvalue(), attrformat, format,
   355                                           encoding)
   355                                           encoding)
   356             return u''
   356             return u''
   357         value = printable_value(self.req, attrtype, value, props,
   357         value = printable_value(self._cw, attrtype, value, props,
   358                                 displaytime=displaytime)
   358                                 displaytime=displaytime)
   359         if format == 'text/html':
   359         if format == 'text/html':
   360             value = xml_escape(value)
   360             value = xml_escape(value)
   361         return value
   361         return value
   362 
   362 
   363     def mtc_transform(self, data, format, target_format, encoding,
   363     def mtc_transform(self, data, format, target_format, encoding,
   364                       _engine=ENGINE):
   364                       _engine=ENGINE):
   365         trdata = TransformData(data, format, encoding, appobject=self)
   365         trdata = TransformData(data, format, encoding, appobject=self)
   366         data = _engine.convert(trdata, target_format).decode()
   366         data = _engine.convert(trdata, target_format).decode()
   367         if format == 'text/html':
   367         if format == 'text/html':
   368             data = soup2xhtml(data, self.req.encoding)
   368             data = soup2xhtml(data, self._cw.encoding)
   369         return data
   369         return data
   370 
   370 
   371     # entity cloning ##########################################################
   371     # entity cloning ##########################################################
   372 
   372 
   373     def copy_relations(self, ceid):
   373     def copy_relations(self, ceid):
   375 
   375 
   376         By default meta and composite relations are skipped.
   376         By default meta and composite relations are skipped.
   377         Overrides this if you want another behaviour
   377         Overrides this if you want another behaviour
   378         """
   378         """
   379         assert self.has_eid()
   379         assert self.has_eid()
   380         execute = self.req.execute
   380         execute = self._cw.execute
   381         for rschema in self.e_schema.subject_relations():
   381         for rschema in self.e_schema.subject_relations():
   382             if rschema.is_final() or rschema.meta:
   382             if rschema.is_final() or rschema.meta:
   383                 continue
   383                 continue
   384             # skip already defined relations
   384             # skip already defined relations
   385             if getattr(self, rschema.type):
   385             if getattr(self, rschema.type):
   420     @cached
   420     @cached
   421     def as_rset(self):
   421     def as_rset(self):
   422         """returns a resultset containing `self` information"""
   422         """returns a resultset containing `self` information"""
   423         rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
   423         rset = ResultSet([(self.eid,)], 'Any X WHERE X eid %(x)s',
   424                          {'x': self.eid}, [(self.__regid__,)])
   424                          {'x': self.eid}, [(self.__regid__,)])
   425         return self.req.decorate_rset(rset)
   425         return self._cw.decorate_rset(rset)
   426 
   426 
   427     def to_complete_relations(self):
   427     def to_complete_relations(self):
   428         """by default complete final relations to when calling .complete()"""
   428         """by default complete final relations to when calling .complete()"""
   429         for rschema in self.e_schema.subject_relations():
   429         for rschema in self.e_schema.subject_relations():
   430             if rschema.is_final():
   430             if rschema.is_final():
   432             if len(rschema.objects(self.e_schema)) > 1:
   432             if len(rschema.objects(self.e_schema)) > 1:
   433                 # ambigous relations, the querier doesn't handle
   433                 # ambigous relations, the querier doesn't handle
   434                 # outer join correctly in this case
   434                 # outer join correctly in this case
   435                 continue
   435                 continue
   436             if rschema.inlined:
   436             if rschema.inlined:
   437                 matching_groups = self.req.user.matching_groups
   437                 matching_groups = self._cw.user.matching_groups
   438                 if matching_groups(rschema.get_groups('read')) and \
   438                 if matching_groups(rschema.get_groups('read')) and \
   439                    all(matching_groups(es.get_groups('read'))
   439                    all(matching_groups(es.get_groups('read'))
   440                        for es in rschema.objects(self.e_schema)):
   440                        for es in rschema.objects(self.e_schema)):
   441                     yield rschema, 'subject'
   441                     yield rschema, 'subject'
   442 
   442 
   447                 continue
   447                 continue
   448             attr = rschema.type
   448             attr = rschema.type
   449             if attr == 'eid':
   449             if attr == 'eid':
   450                 continue
   450                 continue
   451             # password retreival is blocked at the repository server level
   451             # password retreival is blocked at the repository server level
   452             if not self.req.user.matching_groups(rschema.get_groups('read')) \
   452             if not self._cw.user.matching_groups(rschema.get_groups('read')) \
   453                    or attrschema.type == 'Password':
   453                    or attrschema.type == 'Password':
   454                 self[attr] = None
   454                 self[attr] = None
   455                 continue
   455                 continue
   456             yield attr
   456             yield attr
   457 
   457 
   507         if selected:
   507         if selected:
   508             # select V, we need it as the left most selected variable
   508             # select V, we need it as the left most selected variable
   509             # if some outer join are included to fetch inlined relations
   509             # if some outer join are included to fetch inlined relations
   510             rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected),
   510             rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected),
   511                                     ','.join(rql))
   511                                     ','.join(rql))
   512             execute = getattr(self.req, 'unsafe_execute', self.req.execute)
   512             execute = getattr(self._cw, 'unsafe_execute', self._cw.execute)
   513             rset = execute(rql, {'x': self.eid}, 'x', build_descr=False)[0]
   513             rset = execute(rql, {'x': self.eid}, 'x', build_descr=False)[0]
   514             # handle attributes
   514             # handle attributes
   515             for i in xrange(1, lastattr):
   515             for i in xrange(1, lastattr):
   516                 self[str(selected[i-1][0])] = rset[i]
   516                 self[str(selected[i-1][0])] = rset[i]
   517             # handle relations
   517             # handle relations
   518             for i in xrange(lastattr, len(rset)):
   518             for i in xrange(lastattr, len(rset)):
   519                 rtype, role = selected[i-1][0]
   519                 rtype, role = selected[i-1][0]
   520                 value = rset[i]
   520                 value = rset[i]
   521                 if value is None:
   521                 if value is None:
   522                     rrset = ResultSet([], rql, {'x': self.eid})
   522                     rrset = ResultSet([], rql, {'x': self.eid})
   523                     self.req.decorate_rset(rrset)
   523                     self._cw.decorate_rset(rrset)
   524                 else:
   524                 else:
   525                     rrset = self.req.eid_rset(value)
   525                     rrset = self._cw.eid_rset(value)
   526                 self.set_related_cache(rtype, role, rrset)
   526                 self.set_related_cache(rtype, role, rrset)
   527 
   527 
   528     def get_value(self, name):
   528     def get_value(self, name):
   529         """get value for the attribute relation <name>, query the repository
   529         """get value for the attribute relation <name>, query the repository
   530         to get the value if necessary.
   530         to get the value if necessary.
   538             if not self.is_saved():
   538             if not self.is_saved():
   539                 return None
   539                 return None
   540             rql = "Any A WHERE X eid %%(x)s, X %s A" % name
   540             rql = "Any A WHERE X eid %%(x)s, X %s A" % name
   541             # XXX should we really use unsafe_execute here? I think so (syt),
   541             # XXX should we really use unsafe_execute here? I think so (syt),
   542             # see #344874
   542             # see #344874
   543             execute = getattr(self.req, 'unsafe_execute', self.req.execute)
   543             execute = getattr(self._cw, 'unsafe_execute', self._cw.execute)
   544             try:
   544             try:
   545                 rset = execute(rql, {'x': self.eid}, 'x')
   545                 rset = execute(rql, {'x': self.eid}, 'x')
   546             except Unauthorized:
   546             except Unauthorized:
   547                 self[name] = value = None
   547                 self[name] = value = None
   548             else:
   548             else:
   553                     # probably a multisource error
   553                     # probably a multisource error
   554                     self.critical("can't get value for attribute %s of entity with eid %s",
   554                     self.critical("can't get value for attribute %s of entity with eid %s",
   555                                   name, self.eid)
   555                                   name, self.eid)
   556                     if self.e_schema.destination(name) == 'String':
   556                     if self.e_schema.destination(name) == 'String':
   557                         # XXX (syt) imo emtpy string is better
   557                         # XXX (syt) imo emtpy string is better
   558                         self[name] = value = self.req._('unaccessible')
   558                         self[name] = value = self._cw._('unaccessible')
   559                     else:
   559                     else:
   560                         self[name] = value = None
   560                         self[name] = value = None
   561         return value
   561         return value
   562 
   562 
   563     def related(self, rtype, role='subject', limit=None, entities=False):
   563     def related(self, rtype, role='subject', limit=None, entities=False):
   573             pass
   573             pass
   574         assert self.has_eid()
   574         assert self.has_eid()
   575         rql = self.related_rql(rtype, role)
   575         rql = self.related_rql(rtype, role)
   576         # XXX should we really use unsafe_execute here? I think so (syt),
   576         # XXX should we really use unsafe_execute here? I think so (syt),
   577         # see #344874
   577         # see #344874
   578         execute = getattr(self.req, 'unsafe_execute', self.req.execute)
   578         execute = getattr(self._cw, 'unsafe_execute', self._cw.execute)
   579         rset = execute(rql, {'x': self.eid}, 'x')
   579         rset = execute(rql, {'x': self.eid}, 'x')
   580         self.set_related_cache(rtype, role, rset)
   580         self.set_related_cache(rtype, role, rset)
   581         return self.related(rtype, role, limit, entities)
   581         return self.related(rtype, role, limit, entities)
   582 
   582 
   583     def related_rql(self, rtype, role='subject', targettypes=None):
   583     def related_rql(self, rtype, role='subject', targettypes=None):
   584         rschema = self.req.vreg.schema[rtype]
   584         rschema = self._cw.vreg.schema[rtype]
   585         if role == 'subject':
   585         if role == 'subject':
   586             if targettypes is None:
   586             if targettypes is None:
   587                 targettypes = rschema.objects(self.e_schema)
   587                 targettypes = rschema.objects(self.e_schema)
   588             restriction = 'E eid %%(x)s, E %s X' % rtype
   588             restriction = 'E eid %%(x)s, E %s X' % rtype
   589             card = greater_card(rschema, (self.e_schema,), targettypes, 0)
   589             card = greater_card(rschema, (self.e_schema,), targettypes, 0)
   593             restriction = 'E eid %%(x)s, X %s E' % rtype
   593             restriction = 'E eid %%(x)s, X %s E' % rtype
   594             card = greater_card(rschema, targettypes, (self.e_schema,), 1)
   594             card = greater_card(rschema, targettypes, (self.e_schema,), 1)
   595         if len(targettypes) > 1:
   595         if len(targettypes) > 1:
   596             fetchattrs_list = []
   596             fetchattrs_list = []
   597             for ttype in targettypes:
   597             for ttype in targettypes:
   598                 etypecls = self.vreg['etypes'].etype_class(ttype)
   598                 etypecls = self._cw.vreg['etypes'].etype_class(ttype)
   599                 fetchattrs_list.append(set(etypecls.fetch_attrs))
   599                 fetchattrs_list.append(set(etypecls.fetch_attrs))
   600             fetchattrs = reduce(set.intersection, fetchattrs_list)
   600             fetchattrs = reduce(set.intersection, fetchattrs_list)
   601             rql = etypecls.fetch_rql(self.req.user, [restriction], fetchattrs,
   601             rql = etypecls.fetch_rql(self._cw.user, [restriction], fetchattrs,
   602                                      settype=False)
   602                                      settype=False)
   603         else:
   603         else:
   604             etypecls = self.vreg['etypes'].etype_class(targettypes[0])
   604             etypecls = self._cw.vreg['etypes'].etype_class(targettypes[0])
   605             rql = etypecls.fetch_rql(self.req.user, [restriction], settype=False)
   605             rql = etypecls.fetch_rql(self._cw.user, [restriction], settype=False)
   606         # optimisation: remove ORDERBY if cardinality is 1 or ? (though
   606         # optimisation: remove ORDERBY if cardinality is 1 or ? (though
   607         # greater_card return 1 for those both cases)
   607         # greater_card return 1 for those both cases)
   608         if card == '1':
   608         if card == '1':
   609             if ' ORDERBY ' in rql:
   609             if ' ORDERBY ' in rql:
   610                 rql = '%s WHERE %s' % (rql.split(' ORDERBY ', 1)[0],
   610                 rql = '%s WHERE %s' % (rql.split(' ORDERBY ', 1)[0],
   624         Consider relation permissions so that returned entities may be actually
   624         Consider relation permissions so that returned entities may be actually
   625         linked by `rtype`.
   625         linked by `rtype`.
   626         """
   626         """
   627         ordermethod = ordermethod or 'fetch_unrelated_order'
   627         ordermethod = ordermethod or 'fetch_unrelated_order'
   628         if isinstance(rtype, basestring):
   628         if isinstance(rtype, basestring):
   629             rtype = self.req.vreg.schema.rschema(rtype)
   629             rtype = self._cw.vreg.schema.rschema(rtype)
   630         if role == 'subject':
   630         if role == 'subject':
   631             evar, searchedvar = 'S', 'O'
   631             evar, searchedvar = 'S', 'O'
   632             subjtype, objtype = self.e_schema, targettype
   632             subjtype, objtype = self.e_schema, targettype
   633         else:
   633         else:
   634             searchedvar, evar = 'S', 'O'
   634             searchedvar, evar = 'S', 'O'
   643         else:
   643         else:
   644             restriction = []
   644             restriction = []
   645             args = {}
   645             args = {}
   646             securitycheck_args = {}
   646             securitycheck_args = {}
   647         insertsecurity = (rtype.has_local_role('add') and not
   647         insertsecurity = (rtype.has_local_role('add') and not
   648                           rtype.has_perm(self.req, 'add', **securitycheck_args))
   648                           rtype.has_perm(self._cw, 'add', **securitycheck_args))
   649         constraints = rtype.rproperty(subjtype, objtype, 'constraints')
   649         constraints = rtype.rproperty(subjtype, objtype, 'constraints')
   650         if vocabconstraints:
   650         if vocabconstraints:
   651             # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
   651             # RQLConstraint is a subclass for RQLVocabularyConstraint, so they
   652             # will be included as well
   652             # will be included as well
   653             restriction += [cstr.restriction for cstr in constraints
   653             restriction += [cstr.restriction for cstr in constraints
   654                             if isinstance(cstr, RQLVocabularyConstraint)]
   654                             if isinstance(cstr, RQLVocabularyConstraint)]
   655         else:
   655         else:
   656             restriction += [cstr.restriction for cstr in constraints
   656             restriction += [cstr.restriction for cstr in constraints
   657                             if isinstance(cstr, RQLConstraint)]
   657                             if isinstance(cstr, RQLConstraint)]
   658         etypecls = self.vreg['etypes'].etype_class(targettype)
   658         etypecls = self._cw.vreg['etypes'].etype_class(targettype)
   659         rql = etypecls.fetch_rql(self.req.user, restriction,
   659         rql = etypecls.fetch_rql(self._cw.user, restriction,
   660                                  mainvar=searchedvar, ordermethod=ordermethod)
   660                                  mainvar=searchedvar, ordermethod=ordermethod)
   661         # ensure we have an order defined
   661         # ensure we have an order defined
   662         if not ' ORDERBY ' in rql:
   662         if not ' ORDERBY ' in rql:
   663             before, after = rql.split(' WHERE ', 1)
   663             before, after = rql.split(' WHERE ', 1)
   664             rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after)
   664             rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after)
   665         if insertsecurity:
   665         if insertsecurity:
   666             rqlexprs = rtype.get_rqlexprs('add')
   666             rqlexprs = rtype.get_rqlexprs('add')
   667             rewriter = RQLRewriter(self.req)
   667             rewriter = RQLRewriter(self._cw)
   668             rqlst = self.req.vreg.parse(self.req, rql, args)
   668             rqlst = self._cw.vreg.parse(self._cw, rql, args)
   669             for select in rqlst.children:
   669             for select in rqlst.children:
   670                 rewriter.rewrite(select, [((searchedvar, searchedvar), rqlexprs)],
   670                 rewriter.rewrite(select, [((searchedvar, searchedvar), rqlexprs)],
   671                                  select.solutions, args)
   671                                  select.solutions, args)
   672             rql = rqlst.as_string()
   672             rql = rqlst.as_string()
   673         return rql, args
   673         return rql, args
   678         by a given relation, with self as subject or object
   678         by a given relation, with self as subject or object
   679         """
   679         """
   680         try:
   680         try:
   681             rql, args = self.unrelated_rql(rtype, targettype, role, ordermethod)
   681             rql, args = self.unrelated_rql(rtype, targettype, role, ordermethod)
   682         except Unauthorized:
   682         except Unauthorized:
   683             return self.req.empty_rset()
   683             return self._cw.empty_rset()
   684         if limit is not None:
   684         if limit is not None:
   685             before, after = rql.split(' WHERE ', 1)
   685             before, after = rql.split(' WHERE ', 1)
   686             rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
   686             rql = '%s LIMIT %s WHERE %s' % (before, limit, after)
   687         return self.req.execute(rql, args, tuple(args))
   687         return self._cw.execute(rql, args, tuple(args))
   688 
   688 
   689     # relations cache handling ################################################
   689     # relations cache handling ################################################
   690 
   690 
   691     def relation_cached(self, rtype, role):
   691     def relation_cached(self, rtype, role):
   692         """return true if the given relation is already cached on the instance
   692         """return true if the given relation is already cached on the instance
   707 
   707 
   708     def set_related_cache(self, rtype, role, rset, col=0):
   708     def set_related_cache(self, rtype, role, rset, col=0):
   709         """set cached values for the given relation"""
   709         """set cached values for the given relation"""
   710         if rset:
   710         if rset:
   711             related = list(rset.entities(col))
   711             related = list(rset.entities(col))
   712             rschema = self.req.vreg.schema.rschema(rtype)
   712             rschema = self._cw.vreg.schema.rschema(rtype)
   713             if role == 'subject':
   713             if role == 'subject':
   714                 rcard = rschema.rproperty(self.e_schema, related[0].e_schema,
   714                 rcard = rschema.rproperty(self.e_schema, related[0].e_schema,
   715                                           'cardinality')[1]
   715                                           'cardinality')[1]
   716                 target = 'object'
   716                 target = 'object'
   717             else:
   717             else:
   750         # update current local object
   750         # update current local object
   751         self.update(kwargs)
   751         self.update(kwargs)
   752         # and now update the database
   752         # and now update the database
   753         kwargs['x'] = self.eid
   753         kwargs['x'] = self.eid
   754         if _cw_unsafe:
   754         if _cw_unsafe:
   755             self.req.unsafe_execute(
   755             self._cw.unsafe_execute(
   756                 'SET %s WHERE X eid %%(x)s' % ','.join(relations), kwargs, 'x')
   756                 'SET %s WHERE X eid %%(x)s' % ','.join(relations), kwargs, 'x')
   757         else:
   757         else:
   758             self.req.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
   758             self._cw.execute('SET %s WHERE X eid %%(x)s' % ','.join(relations),
   759                              kwargs, 'x')
   759                              kwargs, 'x')
   760 
   760 
   761     def delete(self):
   761     def delete(self):
   762         assert self.has_eid(), self.eid
   762         assert self.has_eid(), self.eid
   763         self.req.execute('DELETE %s X WHERE X eid %%(x)s' % self.e_schema,
   763         self._cw.execute('DELETE %s X WHERE X eid %%(x)s' % self.e_schema,
   764                          {'x': self.eid})
   764                          {'x': self.eid})
   765 
   765 
   766     # server side utilities ###################################################
   766     # server side utilities ###################################################
   767 
   767 
   768     def set_defaults(self):
   768     def set_defaults(self):
   777         """check this entity against its schema. Only final relation
   777         """check this entity against its schema. Only final relation
   778         are checked here, constraint on actual relations are checked in hooks
   778         are checked here, constraint on actual relations are checked in hooks
   779         """
   779         """
   780         # necessary since eid is handled specifically and yams require it to be
   780         # necessary since eid is handled specifically and yams require it to be
   781         # in the dictionary
   781         # in the dictionary
   782         if self.req is None:
   782         if self._cw is None:
   783             _ = unicode
   783             _ = unicode
   784         else:
   784         else:
   785             _ = self.req._
   785             _ = self._cw._
   786         self.e_schema.check(self, creation=creation, _=_)
   786         self.e_schema.check(self, creation=creation, _=_)
   787 
   787 
   788     def fti_containers(self, _done=None):
   788     def fti_containers(self, _done=None):
   789         if _done is None:
   789         if _done is None:
   790             _done = set()
   790             _done = set()