Skip to content
Snippets Groups Projects
Commit 2137d2a6765f authored by Sylvain Thenault's avatar Sylvain Thenault
Browse files

set_possible_types() propagate to sub-queries since some additional

      type constraints may be set in the outer query
parent e899e6c2c5be
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* fix undoing of add_relation and variable name allocation on query using * fix undoing of add_relation and variable name allocation on query using
some subquery some subquery
* add missing selected_index() method on ColumnAlias * add missing selected_index() method on ColumnAlias
* set_possible_types() propagate to sub-queries since some additional
type constraints may be set in the outer query
2008-08-07 -- 0.19.1 2008-08-07 -- 0.19.1
* should not simplify variables used in the GROUPBY clause when there is a * should not simplify variables used in the GROUPBY clause when there is a
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
if True or self.debug: if True or self.debug:
ex_msg += '\n%s' % (solve_debug.getvalue(),) ex_msg += '\n%s' % (solve_debug.getvalue(),)
raise TypeResolverException(ex_msg) raise TypeResolverException(ex_msg)
node.set_possible_types(sols) node.set_possible_types(sols, self.kwargs)
def _visit(self, node, constraints=None): def _visit(self, node, constraints=None):
"""Recurse down the tree.""" """Recurse down the tree."""
...@@ -191,7 +191,7 @@ ...@@ -191,7 +191,7 @@
constraints.append(fd.make_expression(varnames, '%s in %s ' % ( constraints.append(fd.make_expression(varnames, '%s in %s ' % (
'=='.join(varnames), types))) '=='.join(varnames), types)))
self.solve(node, domains, constraints) self.solve(node, domains, constraints)
def visit_relation(self, relation, constraints): def visit_relation(self, relation, constraints):
"""extract constraints for an relation according to it's type""" """extract constraints for an relation according to it's type"""
rtype = relation.r_type rtype = relation.r_type
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
from rql.base import BaseNode, Node from rql.base import BaseNode, Node
from rql.utils import rqlvar_maker, build_visitor_stub from rql.utils import rqlvar_maker, build_visitor_stub
_MARKER = object()
def _check_references(defined, varrefs): def _check_references(defined, varrefs):
refs = {} refs = {}
for var in defined.values(): for var in defined.values():
...@@ -99,7 +100,7 @@ ...@@ -99,7 +100,7 @@
self.undo_manager.add_operation(MakeVarOperation(var)) self.undo_manager.add_operation(MakeVarOperation(var))
return var return var
def set_possible_types(self, solutions): def set_possible_types(self, solutions, kwargs=_MARKER):
self.solutions = solutions self.solutions = solutions
defined = self.defined_vars defined = self.defined_vars
for var in defined.itervalues(): for var in defined.itervalues():
...@@ -443,7 +444,26 @@ ...@@ -443,7 +444,26 @@
return new return new
# select specific methods ################################################# # select specific methods #################################################
def set_possible_types(self, solutions, kwargs=_MARKER):
super(Select, self).set_possible_types(solutions, kwargs)
for ca in self.aliases.itervalues():
ca.stinfo['possibletypes'] = capt = set()
for solution in solutions:
capt.add(solution[ca.name])
if kwargs is _MARKER:
continue
# propagage to subqueries in case we're introducing additional
# type constraints
for stmt in ca.query.children[:]:
term = stmt.selection[ca.colnum]
sols = [sol for sol in stmt.solutions
if term.get_type(sol, kwargs) in capt]
if not sols:
ca.query.remove_select(stmt)
else:
stmt.set_possible_types(sols)
def set_statement_type(self, etype): def set_statement_type(self, etype):
"""set the statement type for this selection """set the statement type for this selection
this method must be called last (i.e. once selected variables has been this method must be called last (i.e. once selected variables has been
......
...@@ -319,8 +319,8 @@ ...@@ -319,8 +319,8 @@
self.assertEqual(sols, [{'X': 'Person', self.assertEqual(sols, [{'X': 'Person',
'U': 'Person'}]) 'U': 'Person'}])
def test_subqueries(self): def test_subqueries_base(self):
node = self.helper.parse('Any L, Y, F WHERE Y located L ' node = self.helper.parse('Any L, Y, F WHERE Y located L '
'WITH Y,F BEING ((Any X,F WHERE X is Person, X firstname F) ' 'WITH Y,F BEING ((Any X,F WHERE X is Person, X firstname F) '
'UNION (Any X,F WHERE X is Company, X name F))') 'UNION (Any X,F WHERE X is Company, X name F))')
self.helper.compute_solutions(node, debug=DEBUG) self.helper.compute_solutions(node, debug=DEBUG)
...@@ -323,12 +323,11 @@ ...@@ -323,12 +323,11 @@
node = self.helper.parse('Any L, Y, F WHERE Y located L ' node = self.helper.parse('Any L, Y, F WHERE Y located L '
'WITH Y,F BEING ((Any X,F WHERE X is Person, X firstname F) ' 'WITH Y,F BEING ((Any X,F WHERE X is Person, X firstname F) '
'UNION (Any X,F WHERE X is Company, X name F))') 'UNION (Any X,F WHERE X is Company, X name F))')
self.helper.compute_solutions(node, debug=DEBUG) self.helper.compute_solutions(node, debug=DEBUG)
sols = sorted(node.children[0].solutions) self.assertEqual(node.children[0].with_[0].query.children[0].solutions,
self.assertEqual(node.children[0].with_[0].query.children[0].solutions, [{'X': 'Person', [{'X': 'Person', 'F': 'String'}])
'F': 'String'}]) self.assertEqual(node.children[0].with_[0].query.children[1].solutions,
self.assertEqual(node.children[0].with_[0].query.children[1].solutions, [{'X': 'Company', [{'X': 'Company', 'F': 'String'}])
'F': 'String'}])
sols = sorted(node.children[0].solutions) sols = sorted(node.children[0].solutions)
self.assertEqual(sols, [{'Y': 'Company', 'L': 'Address', self.assertEqual(sols, [{'Y': 'Company', 'L': 'Address',
'F': 'String'}, 'F': 'String'},
...@@ -345,6 +344,23 @@ ...@@ -345,6 +344,23 @@
self.assertEqual(node.children[0].solutions, [{'X': 'Person', 'Y': 'Person', self.assertEqual(node.children[0].solutions, [{'X': 'Person', 'Y': 'Person',
'L': 'Address'}]) 'L': 'Address'}])
def test_subqueries_outer_filter_type(self):
# this kind of query may be generated by erudi's facettes box
node = self.helper.parse('Any L, Y, F WHERE Y located L, Y is Person '
'WITH Y,F BEING ((Any X,F WHERE X is Person, X firstname F) '
'UNION (Any X,F WHERE X is Company, X name F))')
self.helper.compute_solutions(node, debug=DEBUG)
sols = sorted(node.children[0].solutions)
self.assertEqual(sols, [{'Y': 'Person', 'L': 'Address',
'F': 'String'}])
self.assertEqual(node.children[0].with_[0].query.children[0].solutions,
[{'X': 'Person', 'F': 'String'}])
# auto-simplification
self.assertEqual(len(node.children[0].with_[0].query.children), 1)
self.assertEquals(node.as_string(), 'Any L,Y,F WHERE Y located L, Y is Person WITH Y,F BEING (Any X,F WHERE X is Person, X firstname F)')
self.assertEqual(node.children[0].with_[0].query.children[0].solutions,
[{'X': 'Person', 'F': 'String'}])
def test_insert(self): def test_insert(self):
node = self.helper.parse('INSERT Person X : X name "toto", X work_for Y WHERE Y name "logilab"') node = self.helper.parse('INSERT Person X : X name "toto", X work_for Y WHERE Y name "logilab"')
self.helper.compute_solutions(node, debug=DEBUG) self.helper.compute_solutions(node, debug=DEBUG)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment