cubicweb/schema.py
changeset 11343 892e4c12f03f
parent 11215 4e79acdc36a6
child 11344 847ab4bdd985
equal deleted inserted replaced
11342:62a7100d774b 11343:892e4c12f03f
   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