server/querier.py
changeset 4737 64143d458495
parent 4722 9c13d5db03d9
child 4759 af2e6c377c71
equal deleted inserted replaced
4622:790181bfd19c 4737:64143d458495
    10 
    10 
    11 from itertools import repeat
    11 from itertools import repeat
    12 
    12 
    13 from logilab.common.cache import Cache
    13 from logilab.common.cache import Cache
    14 from logilab.common.compat import any
    14 from logilab.common.compat import any
    15 from rql import RQLHelper, RQLSyntaxError
    15 from rql import RQLSyntaxError
    16 from rql.stmts import Union, Select
    16 from rql.stmts import Union, Select
    17 from rql.nodes import Relation, VariableRef, Constant, SubQuery
    17 from rql.nodes import Relation, VariableRef, Constant, SubQuery
    18 
    18 
    19 from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid
    19 from cubicweb import Unauthorized, QueryError, UnknownEid, typed_eid
    20 from cubicweb import server
    20 from cubicweb import server
    24 from cubicweb.server.rqlannotation import SQLGenAnnotator, set_qdata
    24 from cubicweb.server.rqlannotation import SQLGenAnnotator, set_qdata
    25 from cubicweb.server.ssplanner import add_types_restriction
    25 from cubicweb.server.ssplanner import add_types_restriction
    26 
    26 
    27 READ_ONLY_RTYPES = set(('eid', 'has_text', 'is', 'is_instance_of', 'identity'))
    27 READ_ONLY_RTYPES = set(('eid', 'has_text', 'is', 'is_instance_of', 'identity'))
    28 
    28 
    29 def empty_rset(session, rql, args, rqlst=None):
    29 def empty_rset(rql, args, rqlst=None):
    30     """build an empty result set object"""
    30     """build an empty result set object"""
    31     return ResultSet([], rql, args, rqlst=rqlst)
    31     return ResultSet([], rql, args, rqlst=rqlst)
    32 
    32 
    33 def update_varmap(varmap, selected, table):
    33 def update_varmap(varmap, selected, table):
    34     """return a sql schema to store RQL query result"""
    34     """return a sql schema to store RQL query result"""
   208         set_qdata(self.schema.rschema, union, noinvariant)
   208         set_qdata(self.schema.rschema, union, noinvariant)
   209         if union.has_text_query:
   209         if union.has_text_query:
   210             self.cache_key = None
   210             self.cache_key = None
   211 
   211 
   212     def _insert_security(self, union, noinvariant):
   212     def _insert_security(self, union, noinvariant):
   213         rh = self.rqlhelper
       
   214         for select in union.children[:]:
   213         for select in union.children[:]:
   215             for subquery in select.with_:
   214             for subquery in select.with_:
   216                 self._insert_security(subquery.query, noinvariant)
   215                 self._insert_security(subquery.query, noinvariant)
   217             localchecks, restricted = self._check_permissions(select)
   216             localchecks, restricted = self._check_permissions(select)
   218             if any(localchecks):
   217             if any(localchecks):
   570 
   569 
   571     def execute(self, session, rql, args=None, eid_key=None, build_descr=True):
   570     def execute(self, session, rql, args=None, eid_key=None, build_descr=True):
   572         """execute a rql query, return resulting rows and their description in
   571         """execute a rql query, return resulting rows and their description in
   573         a `ResultSet` object
   572         a `ResultSet` object
   574 
   573 
   575         * `rql` should be an unicode string or a plain ascii string
   574         * `rql` should be an Unicode string or a plain ASCII string
   576         * `args` the optional parameters dictionary associated to the query
   575         * `args` the optional parameters dictionary associated to the query
   577         * `build_descr` is a boolean flag indicating if the description should
   576         * `build_descr` is a boolean flag indicating if the description should
   578           be built on select queries (if false, the description will be en empty
   577           be built on select queries (if false, the description will be en empty
   579           list)
   578           list)
   580         * `eid_key` must be both a key in args and a substitution in the rql
   579         * `eid_key` must be both a key in args and a substitution in the rql
   581           query. It should be used to enhance cacheability of rql queries.
   580           query. It should be used to enhance cacheability of rql queries.
   582           It may be a tuple for keys in args.
   581           It may be a tuple for keys in args.
   583           eid_key must be providen in case where a eid substitution is providen
   582           `eid_key` must be provided in cases where a eid substitution is provided
   584           and resolve some ambiguity in the possible solutions infered for each
   583           and resolves ambiguities in the possible solutions inferred for each
   585           variable in the query.
   584           variable in the query.
   586 
   585 
   587         on INSERT queries, there will be on row with the eid of each inserted
   586         on INSERT queries, there will be one row with the eid of each inserted
   588         entity
   587         entity
   589 
   588 
   590         result for DELETE and SET queries is undefined yet
   589         result for DELETE and SET queries is undefined yet
   591 
   590 
   592         to maximize the rql parsing/analyzing cache performance, you should
   591         to maximize the rql parsing/analyzing cache performance, you should
   593         always use substitute arguments in queries (eg avoid query such as
   592         always use substitute arguments in queries (i.e. avoid query such as
   594         'Any X WHERE X eid 123'!)
   593         'Any X WHERE X eid 123'!)
   595         """
   594         """
   596         if server.DEBUG & (server.DBG_RQL | server.DBG_SQL):
   595         if server.DEBUG & (server.DBG_RQL | server.DBG_SQL):
   597             if server.DEBUG & (server.DBG_MORE | server.DBG_SQL):
   596             if server.DEBUG & (server.DBG_MORE | server.DBG_SQL):
   598                 print '*'*80
   597                 print '*'*80
   611                     raise QueryError('bad cache key %s (value: %r)' % (
   610                     raise QueryError('bad cache key %s (value: %r)' % (
   612                         key, args[key]))
   611                         key, args[key]))
   613                 except UnknownEid:
   612                 except UnknownEid:
   614                     # we want queries such as "Any X WHERE X eid 9999"
   613                     # we want queries such as "Any X WHERE X eid 9999"
   615                     # return an empty result instead of raising UnknownEid
   614                     # return an empty result instead of raising UnknownEid
   616                     return empty_rset(session, rql, args)
   615                     return empty_rset(rql, args)
   617                 cachekey.append(etype)
   616                 cachekey.append(etype)
   618                 # ensure eid is correctly typed in args
   617                 # ensure eid is correctly typed in args
   619                 args[key] = typed_eid(args[key])
   618                 args[key] = typed_eid(args[key])
   620             cachekey = tuple(cachekey)
   619             cachekey = tuple(cachekey)
   621         else:
   620         else:
   629             try:
   628             try:
   630                 self.solutions(session, rqlst, args)
   629                 self.solutions(session, rqlst, args)
   631             except UnknownEid:
   630             except UnknownEid:
   632                 # we want queries such as "Any X WHERE X eid 9999"
   631                 # we want queries such as "Any X WHERE X eid 9999"
   633                 # return an empty result instead of raising UnknownEid
   632                 # return an empty result instead of raising UnknownEid
   634                 return empty_rset(session, rql, args, rqlst)
   633                 return empty_rset(rql, args, rqlst)
   635             self._rql_cache[cachekey] = rqlst
   634             self._rql_cache[cachekey] = rqlst
   636         orig_rqlst = rqlst
   635         orig_rqlst = rqlst
   637         if not rqlst.TYPE == 'select':
   636         if not rqlst.TYPE == 'select':
   638             if not session.is_super_session:
   637             if not session.is_super_session:
   639                 check_no_password_selected(rqlst)
   638                 check_no_password_selected(rqlst)