server/sources/rql2sql.py
changeset 7672 f31f9882c90f
parent 7642 64eee2a83bfa
child 7704 0f49dd8e76b5
equal deleted inserted replaced
7671:d911a73ac8c5 7672:f31f9882c90f
    54 
    54 
    55 from logilab.common.date import utcdatetime, utctime
    55 from logilab.common.date import utcdatetime, utctime
    56 from logilab.database import FunctionDescr, SQL_FUNCTIONS_REGISTRY
    56 from logilab.database import FunctionDescr, SQL_FUNCTIONS_REGISTRY
    57 
    57 
    58 from rql import BadRQLQuery, CoercionError
    58 from rql import BadRQLQuery, CoercionError
       
    59 from rql.utils import common_parent
    59 from rql.stmts import Union, Select
    60 from rql.stmts import Union, Select
    60 from rql.nodes import (SortTerm, VariableRef, Constant, Function, Variable, Or,
    61 from rql.nodes import (SortTerm, VariableRef, Constant, Function, Variable, Or,
    61                        Not, Comparison, ColumnAlias, Relation, SubQuery, Exists)
    62                        Not, Comparison, ColumnAlias, Relation, SubQuery, Exists)
    62 
    63 
    63 from cubicweb import QueryError
    64 from cubicweb import QueryError
   667                         ors.add(oor)
   668                         ors.add(oor)
   668                     break
   669                     break
   669             else:
   670             else:
   670                 tocheck.append(compnode)
   671                 tocheck.append(compnode)
   671         # tocheck hold a set of comparison not implying an aggregat function
   672         # tocheck hold a set of comparison not implying an aggregat function
   672         # put them in fakehaving if the don't share an Or node as ancestor
   673         # put them in fakehaving if they don't share an Or node as ancestor
   673         # with another comparison containing an aggregat function
   674         # with another comparison containing an aggregat function
   674         for compnode in tocheck:
   675         for compnode in tocheck:
   675             parents = set()
   676             parents = set()
   676             p = compnode.parent
   677             p = compnode.parent
   677             oor = None
   678             oor = None
   782         """
   783         """
   783         distinct = selectsortterms = select.need_distinct
   784         distinct = selectsortterms = select.need_distinct
   784         sorts = select.orderby
   785         sorts = select.orderby
   785         groups = select.groupby
   786         groups = select.groupby
   786         having = select.having
   787         having = select.having
   787         morerestr = extract_fake_having_terms(having)
   788         for restr in extract_fake_having_terms(having):
       
   789             scope = None
       
   790             for vref in restr.get_nodes(VariableRef):
       
   791                 vscope = vref.variable.scope
       
   792                 if vscope is select:
       
   793                     continue # ignore select scope, so restriction is added to
       
   794                              # the inner most scope possible
       
   795                 if scope is None:
       
   796                     scope = vscope
       
   797                 elif vscope is not scope:
       
   798                     scope = common_parent(scope, vscope).scope
       
   799             if scope is None:
       
   800                 scope = select
       
   801             scope.add_restriction(restr)
   788         # remember selection, it may be changed and have to be restored
   802         # remember selection, it may be changed and have to be restored
   789         origselection = select.selection[:]
   803         origselection = select.selection[:]
   790         # check if the query will have union subquery, if it need sort term
   804         # check if the query will have union subquery, if it need sort term
   791         # selection (union or distinct query) and wrapping (union with groups)
   805         # selection (union or distinct query) and wrapping (union with groups)
   792         needwrap = False
   806         needwrap = False
   827         if fneedwrap:
   841         if fneedwrap:
   828             needalias = True
   842             needalias = True
   829         self._in_wrapping_query = False
   843         self._in_wrapping_query = False
   830         self._state = state
   844         self._state = state
   831         try:
   845         try:
   832             sql = self._solutions_sql(select, morerestr, sols, distinct,
   846             sql = self._solutions_sql(select, sols, distinct,
   833                                       needalias or needwrap)
   847                                       needalias or needwrap)
   834             # generate groups / having before wrapping query selection to get
   848             # generate groups / having before wrapping query selection to get
   835             # correct column aliases
   849             # correct column aliases
   836             self._in_wrapping_query = needwrap
   850             self._in_wrapping_query = needwrap
   837             if groups:
   851             if groups:
   898                         update_source_cb_stack(state, select, vref, stack)
   912                         update_source_cb_stack(state, select, vref, stack)
   899                         state.subquery_source_cb[selectidx] = stack
   913                         state.subquery_source_cb[selectidx] = stack
   900                 except KeyError:
   914                 except KeyError:
   901                     continue
   915                     continue
   902 
   916 
   903     def _solutions_sql(self, select, morerestr, solutions, distinct, needalias):
   917     def _solutions_sql(self, select, solutions, distinct, needalias):
   904         sqls = []
   918         sqls = []
   905         for solution in solutions:
   919         for solution in solutions:
   906             self._state.reset(solution)
   920             self._state.reset(solution)
   907             # visit restriction subtree
   921             # visit restriction subtree
   908             if select.where is not None:
   922             if select.where is not None:
   909                 self._state.add_restriction(select.where.accept(self))
   923                 self._state.add_restriction(select.where.accept(self))
   910             for restriction in morerestr:
       
   911                 self._state.add_restriction(restriction.accept(self))
       
   912             sql = [self._selection_sql(select.selection, distinct, needalias)]
   924             sql = [self._selection_sql(select.selection, distinct, needalias)]
   913             if self._state.restrictions:
   925             if self._state.restrictions:
   914                 sql.append('WHERE %s' % ' AND '.join(self._state.restrictions))
   926                 sql.append('WHERE %s' % ' AND '.join(self._state.restrictions))
   915             self._state.merge_source_cbs(self._state._needs_source_cb)
   927             self._state.merge_source_cbs(self._state._needs_source_cb)
   916             # add required tables
   928             # add required tables