# HG changeset patch
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1276085995 -7200
#      Wed Jun 09 14:19:55 2010 +0200
# Branch stable
# Node ID 20eeb140d658e854dfbb36b277e876d2d4c58e9e
# Parent  db05b88729b2113598f0089a1c1272aa9e131dca
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)

diff --git a/stmts.py b/stmts.py
--- a/stmts.py
+++ b/stmts.py
@@ -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 #########################################################
 
diff --git a/test/unittest_nodes.py b/test/unittest_nodes.py
--- a/test/unittest_nodes.py
+++ b/test/unittest_nodes.py
@@ -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 #########################################################