199 """ |
199 """ |
200 # these are overridden by set_log_methods below |
200 # these are overridden by set_log_methods below |
201 # only defining here to prevent pylint from complaining |
201 # only defining here to prevent pylint from complaining |
202 info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None |
202 info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None |
203 # to be defined in concrete classes |
203 # to be defined in concrete classes |
204 rqlst = None |
|
205 predefined_variables = None |
204 predefined_variables = None |
206 full_rql = None |
|
207 |
205 |
208 def __init__(self, expression, mainvars, eid): |
206 def __init__(self, expression, mainvars, eid): |
209 """ |
207 """ |
210 :type mainvars: sequence of RQL variables' names. Can be provided as a |
208 :type mainvars: sequence of RQL variables' names. Can be provided as a |
211 comma separated string. |
209 comma separated string. |
219 elif not isinstance(mainvars, set): |
217 elif not isinstance(mainvars, set): |
220 mainvars = set(mainvars) |
218 mainvars = set(mainvars) |
221 self.mainvars = mainvars |
219 self.mainvars = mainvars |
222 self.expression = normalize_expression(expression) |
220 self.expression = normalize_expression(expression) |
223 try: |
221 try: |
224 self.full_rql = self.rqlst.as_string() |
222 # syntax tree used by read security (inserted in queries when necessary) |
|
223 self.snippet_rqlst = parse(self.minimal_rql, print_errors=False).children[0] |
225 except RQLSyntaxError: |
224 except RQLSyntaxError: |
226 raise RQLSyntaxError(expression) |
225 raise RQLSyntaxError(expression) |
227 for mainvar in mainvars: |
226 for mainvar in mainvars: |
228 # if variable is predefined, an extra reference is inserted |
227 if len(self.snippet_rqlst.defined_vars[mainvar].references()) < 2: |
229 # automatically (`VAR eid %(v)s`) |
|
230 if mainvar in self.predefined_variables: |
|
231 min_refs = 3 |
|
232 else: |
|
233 min_refs = 2 |
|
234 if len(self.rqlst.defined_vars[mainvar].references()) < min_refs: |
|
235 _LOGGER.warn('You did not use the %s variable in your RQL ' |
228 _LOGGER.warn('You did not use the %s variable in your RQL ' |
236 'expression %s', mainvar, self) |
229 'expression %s', mainvar, self) |
237 # syntax tree used by read security (inserted in queries when necessary) |
|
238 self.snippet_rqlst = parse(self.minimal_rql, print_errors=False).children[0] |
|
239 # graph of links between variables, used by rql rewriter |
230 # graph of links between variables, used by rql rewriter |
240 self.vargraph = vargraph(self.rqlst) |
231 self.vargraph = vargraph(self.snippet_rqlst) |
241 # useful for some instrumentation, e.g. localperms permcheck command |
232 # useful for some instrumentation, e.g. localperms permcheck command |
242 self.package = ybo.PACKAGE |
233 self.package = ybo.PACKAGE |
243 |
234 |
244 def __str__(self): |
235 def __str__(self): |
245 return self.full_rql |
236 return self.rqlst.as_string() |
|
237 |
246 def __repr__(self): |
238 def __repr__(self): |
247 return '%s(%s)' % (self.__class__.__name__, self.full_rql) |
239 return '%s(%s)' % (self.__class__.__name__, self.expression) |
248 |
240 |
249 def __lt__(self, other): |
241 def __lt__(self, other): |
250 if hasattr(other, 'expression'): |
242 if hasattr(other, 'expression'): |
251 return self.expression < other.expression |
243 return self.expression < other.expression |
252 return True |
244 return True |
337 return _cw.local_perm_cache[key] |
329 return _cw.local_perm_cache[key] |
338 except KeyError: |
330 except KeyError: |
339 pass |
331 pass |
340 rql, has_perm_defs, keyarg = self.transform_has_permission() |
332 rql, has_perm_defs, keyarg = self.transform_has_permission() |
341 # when creating an entity, expression related to X satisfied |
333 # when creating an entity, expression related to X satisfied |
342 if creating and 'X' in self.rqlst.defined_vars: |
334 if creating and 'X' in self.snippet_rqlst.defined_vars: |
343 return True |
335 return True |
344 if keyarg is None: |
336 if keyarg is None: |
345 kwargs.setdefault('u', _cw.user.eid) |
337 kwargs.setdefault('u', _cw.user.eid) |
346 try: |
338 try: |
347 rset = _cw.execute(rql, kwargs, build_descr=True) |
339 rset = _cw.execute(rql, kwargs, build_descr=True) |
402 |
394 |
403 def __init__(self, expression, mainvars=None, eid=None): |
395 def __init__(self, expression, mainvars=None, eid=None): |
404 RQLExpression.__init__(self, expression, mainvars or 'X', eid) |
396 RQLExpression.__init__(self, expression, mainvars or 'X', eid) |
405 |
397 |
406 def check(self, _cw, eid=None, creating=False, **kwargs): |
398 def check(self, _cw, eid=None, creating=False, **kwargs): |
407 if 'X' in self.rqlst.defined_vars: |
399 if 'X' in self.snippet_rqlst.defined_vars: |
408 if eid is None: |
400 if eid is None: |
409 if creating: |
401 if creating: |
410 return self._check(_cw, creating=True, **kwargs) |
402 return self._check(_cw, creating=True, **kwargs) |
411 return False |
403 return False |
412 assert creating == False |
404 assert creating == False |
477 mainvars = guess_rrqlexpr_mainvars(expression) |
469 mainvars = guess_rrqlexpr_mainvars(expression) |
478 RQLExpression.__init__(self, expression, mainvars, eid) |
470 RQLExpression.__init__(self, expression, mainvars, eid) |
479 |
471 |
480 def check(self, _cw, fromeid=None, toeid=None): |
472 def check(self, _cw, fromeid=None, toeid=None): |
481 kwargs = {} |
473 kwargs = {} |
482 if 'S' in self.rqlst.defined_vars: |
474 if 'S' in self.snippet_rqlst.defined_vars: |
483 if fromeid is None: |
475 if fromeid is None: |
484 return False |
476 return False |
485 kwargs['s'] = fromeid |
477 kwargs['s'] = fromeid |
486 if 'O' in self.rqlst.defined_vars: |
478 if 'O' in self.snippet_rqlst.defined_vars: |
487 if toeid is None: |
479 if toeid is None: |
488 return False |
480 return False |
489 kwargs['o'] = toeid |
481 kwargs['o'] = toeid |
490 return self._check(_cw, **kwargs) |
482 return self._check(_cw, **kwargs) |
491 |
483 |
1249 expression = 'S eid %(s)s, ' + self.expression |
1241 expression = 'S eid %(s)s, ' + self.expression |
1250 args = {'s': eidfrom} |
1242 args = {'s': eidfrom} |
1251 else: |
1243 else: |
1252 expression = 'S eid %(s)s, O eid %(o)s, ' + self.expression |
1244 expression = 'S eid %(s)s, O eid %(o)s, ' + self.expression |
1253 args = {'s': eidfrom, 'o': eidto} |
1245 args = {'s': eidfrom, 'o': eidto} |
1254 if 'U' in self.rqlst.defined_vars: |
1246 if 'U' in self.snippet_rqlst.defined_vars: |
1255 expression = 'U eid %(u)s, ' + expression |
1247 expression = 'U eid %(u)s, ' + expression |
1256 args['u'] = _cw.user.eid |
1248 args['u'] = _cw.user.eid |
1257 rql = 'Any %s WHERE %s' % (','.join(sorted(self.mainvars)), expression) |
1249 rql = 'Any %s WHERE %s' % (','.join(sorted(self.mainvars)), expression) |
1258 if self.distinct_query: |
1250 if self.distinct_query: |
1259 rql = 'DISTINCT ' + rql |
1251 rql = 'DISTINCT ' + rql |