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 |
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() |