# HG changeset patch # User Philippe Pepiot # Date 1465293861 -7200 # Node ID 892e4c12f03f1f2ed4d787601312ca1d588a7e39 # Parent 62a7100d774ba4e66e687ae09bb10a577449b339 [schema] Avoid parsing RQL expressions twice on schema loading Kill full_rql (unnecessary) Use snippet_rql rather than rqlst when possible Don't access to rqlst cachedproperty from __init__ Deserializing schema is ~40% faster with a lot (> 4000) expressions like those generated by cubicweb-container. diff -r 62a7100d774b -r 892e4c12f03f cubicweb/schema.py --- a/cubicweb/schema.py Wed Jun 22 10:22:37 2016 +0200 +++ b/cubicweb/schema.py Tue Jun 07 12:04:21 2016 +0200 @@ -201,9 +201,7 @@ # only defining here to prevent pylint from complaining info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None # to be defined in concrete classes - rqlst = None predefined_variables = None - full_rql = None def __init__(self, expression, mainvars, eid): """ @@ -221,30 +219,24 @@ self.mainvars = mainvars self.expression = normalize_expression(expression) try: - self.full_rql = self.rqlst.as_string() + # syntax tree used by read security (inserted in queries when necessary) + self.snippet_rqlst = parse(self.minimal_rql, print_errors=False).children[0] except RQLSyntaxError: raise RQLSyntaxError(expression) for mainvar in mainvars: - # if variable is predefined, an extra reference is inserted - # automatically (`VAR eid %(v)s`) - if mainvar in self.predefined_variables: - min_refs = 3 - else: - min_refs = 2 - if len(self.rqlst.defined_vars[mainvar].references()) < min_refs: + if len(self.snippet_rqlst.defined_vars[mainvar].references()) < 2: _LOGGER.warn('You did not use the %s variable in your RQL ' 'expression %s', mainvar, self) - # syntax tree used by read security (inserted in queries when necessary) - self.snippet_rqlst = parse(self.minimal_rql, print_errors=False).children[0] # graph of links between variables, used by rql rewriter - self.vargraph = vargraph(self.rqlst) + self.vargraph = vargraph(self.snippet_rqlst) # useful for some instrumentation, e.g. localperms permcheck command self.package = ybo.PACKAGE def __str__(self): - return self.full_rql + return self.rqlst.as_string() + def __repr__(self): - return '%s(%s)' % (self.__class__.__name__, self.full_rql) + return '%s(%s)' % (self.__class__.__name__, self.expression) def __lt__(self, other): if hasattr(other, 'expression'): @@ -339,7 +331,7 @@ pass rql, has_perm_defs, keyarg = self.transform_has_permission() # when creating an entity, expression related to X satisfied - if creating and 'X' in self.rqlst.defined_vars: + if creating and 'X' in self.snippet_rqlst.defined_vars: return True if keyarg is None: kwargs.setdefault('u', _cw.user.eid) @@ -404,7 +396,7 @@ RQLExpression.__init__(self, expression, mainvars or 'X', eid) def check(self, _cw, eid=None, creating=False, **kwargs): - if 'X' in self.rqlst.defined_vars: + if 'X' in self.snippet_rqlst.defined_vars: if eid is None: if creating: return self._check(_cw, creating=True, **kwargs) @@ -479,11 +471,11 @@ def check(self, _cw, fromeid=None, toeid=None): kwargs = {} - if 'S' in self.rqlst.defined_vars: + if 'S' in self.snippet_rqlst.defined_vars: if fromeid is None: return False kwargs['s'] = fromeid - if 'O' in self.rqlst.defined_vars: + if 'O' in self.snippet_rqlst.defined_vars: if toeid is None: return False kwargs['o'] = toeid @@ -1251,7 +1243,7 @@ else: expression = 'S eid %(s)s, O eid %(o)s, ' + self.expression args = {'s': eidfrom, 'o': eidto} - if 'U' in self.rqlst.defined_vars: + if 'U' in self.snippet_rqlst.defined_vars: expression = 'U eid %(u)s, ' + expression args['u'] = _cw.user.eid rql = 'Any %s WHERE %s' % (','.join(sorted(self.mainvars)), expression)