rqlrewrite.py
branchstable
changeset 3826 0c0c051863cb
parent 3689 deb13e88e037
child 3877 7ca53fc72a0a
child 3934 d9a29a1fbe43
equal deleted inserted replaced
3825:b54c8d664dd6 3826:0c0c051863cb
    11 __docformat__ = "restructuredtext en"
    11 __docformat__ = "restructuredtext en"
    12 
    12 
    13 from rql import nodes as n, stmts, TypeResolverException
    13 from rql import nodes as n, stmts, TypeResolverException
    14 
    14 
    15 from logilab.common.compat import any
    15 from logilab.common.compat import any
       
    16 from logilab.common.graph import has_path
    16 
    17 
    17 from cubicweb import Unauthorized, typed_eid
    18 from cubicweb import Unauthorized, typed_eid
    18 
    19 
    19 
    20 
    20 def add_types_restriction(schema, rqlst, newroot=None, solutions=None):
    21 def add_types_restriction(schema, rqlst, newroot=None, solutions=None):
   132         except TypeResolverException:
   133         except TypeResolverException:
   133             raise Unsupported(str(self.select))
   134             raise Unsupported(str(self.select))
   134         if len(self.select.solutions) < len(self.solutions):
   135         if len(self.select.solutions) < len(self.solutions):
   135             raise Unsupported()
   136             raise Unsupported()
   136 
   137 
   137     def rewrite(self, select, snippets, solutions, kwargs):
   138     def rewrite(self, select, snippets, solutions, kwargs, existingvars=None):
   138         """
   139         """
   139         snippets: (varmap, list of rql expression)
   140         snippets: (varmap, list of rql expression)
   140                   with varmap a *tuple* (select var, snippet var)
   141                   with varmap a *tuple* (select var, snippet var)
   141         """
   142         """
   142         self.select = self.insert_scope = select
   143         self.select = self.insert_scope = select
   144         self.kwargs = kwargs
   145         self.kwargs = kwargs
   145         self.u_varname = None
   146         self.u_varname = None
   146         self.removing_ambiguity = False
   147         self.removing_ambiguity = False
   147         self.exists_snippet = {}
   148         self.exists_snippet = {}
   148         self.pending_keys = []
   149         self.pending_keys = []
       
   150         self.existingvars = existingvars
   149         # we have to annotate the rqlst before inserting snippets, even though
   151         # we have to annotate the rqlst before inserting snippets, even though
   150         # we'll have to redo it latter
   152         # we'll have to redo it latter
   151         self.annotate(select)
   153         self.annotate(select)
   152         self.insert_snippets(snippets)
   154         self.insert_snippets(snippets)
   153         if not self.exists_snippet and self.u_varname:
   155         if not self.exists_snippet and self.u_varname:
   211                 # no rql expression found matching rql solutions. User has no access right
   213                 # no rql expression found matching rql solutions. User has no access right
   212                 raise Unauthorized()
   214                 raise Unauthorized()
   213 
   215 
   214     def insert_snippet(self, varmap, snippetrqlst, parent=None):
   216     def insert_snippet(self, varmap, snippetrqlst, parent=None):
   215         new = snippetrqlst.where.accept(self)
   217         new = snippetrqlst.where.accept(self)
       
   218         existing = self.existingvars
       
   219         self.existingvars = None
       
   220         try:
       
   221             return self._insert_snippet(varmap, parent, new)
       
   222         finally:
       
   223             self.existingvars = existing
       
   224 
       
   225     def _insert_snippet(self, varmap, parent, new):
   216         if new is not None:
   226         if new is not None:
   217             if self.varinfo.get('stinfo', {}).get('optrelations'):
   227             if self.varinfo.get('stinfo', {}).get('optrelations'):
   218                 assert parent is None
   228                 assert parent is None
   219                 self.insert_scope = self.snippet_subquery(varmap, new)
   229                 self.insert_scope = self.snippet_subquery(varmap, new)
   220                 self.insert_pending()
   230                 self.insert_pending()
   476         return self._visit_unary(node, n.Not)
   486         return self._visit_unary(node, n.Not)
   477 
   487 
   478     def visit_exists(self, node):
   488     def visit_exists(self, node):
   479         return self._visit_unary(node, n.Exists)
   489         return self._visit_unary(node, n.Exists)
   480 
   490 
       
   491     def keep_var(self, varname):
       
   492         if varname in 'SO':
       
   493             return varname in self.existingvars
       
   494         if varname == 'U':
       
   495             return True
       
   496         vargraph = self.current_expr.vargraph
       
   497         for existingvar in self.existingvars:
       
   498             #path = has_path(vargraph, varname, existingvar)
       
   499             if has_path(vargraph, varname, existingvar):
       
   500                 return True
       
   501         # no path from this variable to an existing variable
       
   502         return False
       
   503 
   481     def visit_relation(self, node):
   504     def visit_relation(self, node):
   482         lhs, rhs = node.get_variable_parts()
   505         lhs, rhs = node.get_variable_parts()
       
   506         # remove relations where an unexistant variable and or a variable linked
       
   507         # to an unexistant variable is used.
       
   508         if self.existingvars:
       
   509             if not self.keep_var(lhs.name):
       
   510                 return
   483         if node.r_type in ('has_add_permission', 'has_update_permission',
   511         if node.r_type in ('has_add_permission', 'has_update_permission',
   484                            'has_delete_permission', 'has_read_permission'):
   512                            'has_delete_permission', 'has_read_permission'):
   485             assert lhs.name == 'U'
   513             assert lhs.name == 'U'
   486             action = node.r_type.split('_')[1]
   514             action = node.r_type.split('_')[1]
   487             key = (self.current_expr, self.varmap, rhs.name)
   515             key = (self.current_expr, self.varmap, rhs.name)
   488             self.pending_keys.append( (key, action) )
   516             self.pending_keys.append( (key, action) )
   489             return
   517             return
   490         if isinstance(rhs, n.VariableRef):
   518         if isinstance(rhs, n.VariableRef):
       
   519             if self.existingvars and not self.keep_var(rhs.name):
       
   520                 return
   491             if lhs.name in self.revvarmap and rhs.name != 'U':
   521             if lhs.name in self.revvarmap and rhs.name != 'U':
   492                 orel = self._may_be_shared_with(node, 'object', lhs.name)
   522                 orel = self._may_be_shared_with(node, 'object', lhs.name)
   493                 if orel is not None:
   523                 if orel is not None:
   494                     self._use_orig_term(rhs.name, orel.children[1].children[0])
   524                     self._use_orig_term(rhs.name, orel.children[1].children[0])
   495                     return
   525                     return