replace get_variable_variables mecanism which can't work with some UNION queries, with get_variable_indices (eg working on selection indices instead of variable names)
--- a/stmts.py Wed Jun 09 12:02:54 2010 +0200
+++ b/stmts.py Wed Jun 09 14:19:55 2010 +0200
@@ -271,14 +271,27 @@
# union specific methods ##################################################
+ # XXX for bw compat, should now use get_variable_indices (cw > 3.8.4)
def get_variable_variables(self):
- """return the set of variable names which take different type according
- to the solutions
+ change = set()
+ for idx in self.get_variable_indices():
+ for vref in self.children[0].selection[idx].iget_nodes(VariableRef):
+ change.add(vref.name)
+ return change
+
+ def get_variable_indices(self):
+ """return the set of selection indexes which take different types
+ according to the solutions
"""
change = set()
values = {}
for select in self.children:
- change.update(select.get_variable_variables(values))
+ for descr in select.get_selection_solutions():
+ for i, etype in enumerate(descr):
+ values.setdefault(i, set()).add(etype)
+ for idx, etypes in values.iteritems():
+ if len(etypes) > 1:
+ change.add(idx)
return change
def _locate_subquery(self, col, etype, kwargs):
@@ -623,20 +636,20 @@
newsolutions.append(asol)
self.solutions = newsolutions
- def get_variable_variables(self, _values=None):
+ def get_selection_solutions(self):
"""return the set of variable names which take different type according
to the solutions
"""
- change = set()
- if _values is None:
- _values = {}
+ descriptions = set()
for solution in self.solutions:
- for vname, etype in solution.iteritems():
- if not vname in _values:
- _values[vname] = etype
- elif _values[vname] != etype:
- change.add(vname)
- return change
+ descr = []
+ for term in self.selection:
+ try:
+ descr.append(term.get_type(solution=solution))
+ except CoercionError:
+ pass
+ descriptions.add(tuple(descr))
+ return descriptions
# quick accessors #########################################################
--- a/test/unittest_nodes.py Wed Jun 09 12:02:54 2010 +0200
+++ b/test/unittest_nodes.py Wed Jun 09 14:19:55 2010 +0200
@@ -355,12 +355,31 @@
self.assertEquals(tree.defined_vars['X'].selected_index(), 0)
self.assertEquals(tree.defined_vars['N'].selected_index(), None)
- def test_get_variable_variables(self):
- dummy = self._simpleparse("Any X")
- dummy.solutions = [{'A': 'String', 'B': 'EUser', 'C': 'EGroup'},
- {'A': 'String', 'B': 'Personne', 'C': 'EGroup'},
- {'A': 'String', 'B': 'EUser', 'C': 'Societe'}]
- self.assertEquals(dummy.get_variable_variables(), set(['B', 'C']))
+ def test_get_variable_indices_1(self):
+ dummy = self._parse("Any A,B,C")
+ dummy.children[0].solutions = [{'A': 'String', 'B': 'EUser', 'C': 'EGroup'},
+ {'A': 'String', 'B': 'Personne', 'C': 'EGroup'},
+ {'A': 'String', 'B': 'EUser', 'C': 'Societe'}]
+ self.assertEquals(dummy.get_variable_indices(), set([1, 2]))
+
+ def test_get_variable_indices_2(self):
+ dummy = self._parse("Any A,B WHERE B relation C")
+ dummy.children[0].solutions = [{'A': 'String', 'B': 'EUser', 'C': 'EGroup'},
+ {'A': 'String', 'B': 'Personne', 'C': 'EGroup'},
+ {'A': 'String', 'B': 'EUser', 'C': 'Societe'}]
+ self.assertEquals(dummy.get_variable_indices(), set([1]))
+
+ def test_get_variable_indices_3(self):
+ dummy = self._parse("(Any X WHERE X is EGroup) UNION (Any C WHERE C is EUser)")
+ dummy.children[0].solutions = [{'X': 'EGroup'}]
+ dummy.children[1].solutions = [{'C': 'EUser'}]
+ self.assertEquals(dummy.get_variable_indices(), set([0]))
+
+ def test_get_variable_indices_4(self):
+ dummy = self._parse("(Any X,XN WHERE X is EGroup, X name XN) UNION (Any C,CL WHERE C is EUser, C login CL)")
+ dummy.children[0].solutions = [{'X': 'EGroup', 'XN': 'String'}]
+ dummy.children[1].solutions = [{'C': 'EUser', 'CL': 'String'}]
+ self.assertEquals(dummy.get_variable_indices(), set([0]))
# insertion tests #########################################################