94 from logilab.common.compat import any |
94 from logilab.common.compat import any |
95 from logilab.common.decorators import cached |
95 from logilab.common.decorators import cached |
96 |
96 |
97 from rql.stmts import Union, Select |
97 from rql.stmts import Union, Select |
98 from rql.nodes import (VariableRef, Comparison, Relation, Constant, Variable, |
98 from rql.nodes import (VariableRef, Comparison, Relation, Constant, Variable, |
99 Not, Exists) |
99 Not, Exists, SortTerm, Function) |
100 |
100 |
101 from cubicweb import server |
101 from cubicweb import server |
102 from cubicweb.utils import make_uid |
102 from cubicweb.utils import make_uid |
103 from cubicweb.server.utils import cleanup_solutions |
103 from cubicweb.server.utils import cleanup_solutions |
104 from cubicweb.server.ssplanner import (SSPlanner, OneFetchStep, |
104 from cubicweb.server.ssplanner import (SSPlanner, OneFetchStep, |
1328 for node in rqlst.orderby: |
1328 for node in rqlst.orderby: |
1329 rqlst = self._rqlst_accept(rqlst, node, newroot, terms, |
1329 rqlst = self._rqlst_accept(rqlst, node, newroot, terms, |
1330 orderby.append) |
1330 orderby.append) |
1331 if orderby: |
1331 if orderby: |
1332 newroot.set_orderby(orderby) |
1332 newroot.set_orderby(orderby) |
|
1333 elif rqlst.orderby: |
|
1334 for sortterm in rqlst.orderby: |
|
1335 if any(f for f in sortterm.iget_nodes(Function) if f.name == 'FTIRANK'): |
|
1336 newnode, oldnode = sortterm.accept(self, newroot, terms) |
|
1337 if newnode is not None: |
|
1338 newroot.add_sort_term(newnode) |
1333 self.process_selection(newroot, terms, rqlst) |
1339 self.process_selection(newroot, terms, rqlst) |
1334 elif not newroot.where: |
1340 elif not newroot.where: |
1335 # no restrictions have been copied, just select terms and add |
1341 # no restrictions have been copied, just select terms and add |
1336 # type restriction (done later by add_types_restriction) |
1342 # type restriction (done later by add_types_restriction) |
1337 for v in terms: |
1343 for v in terms: |
1528 # ignore comparison operator when fetching non final query |
1534 # ignore comparison operator when fetching non final query |
1529 if not self.final and isinstance(node.children[0], VariableRef): |
1535 if not self.final and isinstance(node.children[0], VariableRef): |
1530 copy.operator = '=' |
1536 copy.operator = '=' |
1531 return copy, node |
1537 return copy, node |
1532 |
1538 |
|
1539 def visit_function(self, node, newroot, terms): |
|
1540 if node.name == 'FTIRANK': |
|
1541 # FTIRANK is somewhat special... Rank function should be included in |
|
1542 # the same query has the has_text relation, potentially added to |
|
1543 # selection for latter usage |
|
1544 if not self.hasaggrstep and self.final and node not in self.skip: |
|
1545 return self.visit_default(node, newroot, terms) |
|
1546 elif any(s for s in self.sources if s.uri != 'system'): |
|
1547 return None, node |
|
1548 # p = node.parent |
|
1549 # while p is not None and not isinstance(p, SortTerm): |
|
1550 # p = p.parent |
|
1551 # if isinstance(p, SortTerm): |
|
1552 if not self.hasaggrstep and self.final and node in self.skip: |
|
1553 return Constant(self.skip[node], 'Int'), node |
|
1554 # XXX only if not yet selected |
|
1555 newroot.append_selected(node.copy(newroot)) |
|
1556 self.skip[node] = len(newroot.selection) |
|
1557 return None, node |
|
1558 return self.visit_default(node, newroot, terms) |
|
1559 |
1533 def visit_default(self, node, newroot, terms): |
1560 def visit_default(self, node, newroot, terms): |
1534 subparts, node = self._visit_children(node, newroot, terms) |
1561 subparts, node = self._visit_children(node, newroot, terms) |
1535 return copy_node(newroot, node, subparts), node |
1562 return copy_node(newroot, node, subparts), node |
1536 |
1563 |
1537 visit_mathexpression = visit_constant = visit_function = visit_default |
1564 visit_mathexpression = visit_constant = visit_default |
1538 visit_sort = visit_sortterm = visit_default |
1565 |
|
1566 def visit_sortterm(self, node, newroot, terms): |
|
1567 subparts, node = self._visit_children(node, newroot, terms) |
|
1568 if not subparts: |
|
1569 return None, node |
|
1570 return copy_node(newroot, node, subparts), node |
1539 |
1571 |
1540 def _visit_children(self, node, newroot, terms): |
1572 def _visit_children(self, node, newroot, terms): |
1541 subparts = [] |
1573 subparts = [] |
1542 for i in xrange(len(node.children)): |
1574 for i in xrange(len(node.children)): |
1543 child = node.children[i] |
1575 child = node.children[i] |