[rql2sql] add test for rql bug #37423, which triggered a cw bug fixed by this changeset (infinite loop with some queries...) stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Mon, 02 Aug 2010 12:35:24 +0200
branchstable
changeset 6050 20af96a6fffc
parent 6049 f0ae98fa85a1
child 6051 d40ffe6c8be0
[rql2sql] add test for rql bug #37423, which triggered a cw bug fixed by this changeset (infinite loop with some queries...)
server/sources/rql2sql.py
server/test/unittest_querier.py
--- a/server/sources/rql2sql.py	Mon Aug 02 10:09:29 2010 +0200
+++ b/server/sources/rql2sql.py	Mon Aug 02 12:35:24 2010 +0200
@@ -101,15 +101,12 @@
     subquery. This function check this and rewrite the rql syntax tree if
     necessary (in place). Return a boolean telling if the tree has been modified
     """
-    torewrite = set()
     modified = False
     for varname in tuple(unstable):
         var = select.defined_vars[varname]
         if not var.stinfo.get('optrelations'):
             continue
-        modified = True
         unstable.remove(varname)
-        torewrite.add(var)
         newselect = Select()
         newselect.need_distinct = False
         myunion = Union()
@@ -139,10 +136,17 @@
                 var.stinfo['rhsrelations'].add(newrel)
                 if rel.optional in ('right', 'both'):
                     var.add_optional_relation(newrel)
+        if not select.where and not modified:
+            # oops, generated the same thing as the original select....
+            # restore original query, else we'll indefinitly loop
+            for var, rel in towrap_rels:
+                select.add_restriction(rel)
+            continue
+        modified = True
         # extract subquery solutions
         mysolutions = [sol.copy() for sol in solutions]
         cleanup_solutions(newselect, mysolutions)
-        newselect.set_possible_types(solutions)
+        newselect.set_possible_types(mysolutions)
         # full sub-query
         aliases = [VariableRef(select.get_variable(avar.name, i))
                    for i, avar in enumerate(newselect.selection)]
--- a/server/test/unittest_querier.py	Mon Aug 02 10:09:29 2010 +0200
+++ b/server/test/unittest_querier.py	Mon Aug 02 12:35:24 2010 +0200
@@ -836,7 +836,7 @@
         rset = self.execute('Any X, NOW - CD WHERE X is Personne, X creation_date CD')
         self.failUnlessEqual(rset.description[0][1], 'Interval')
 
-    def test_select_subquery_aggregat(self):
+    def test_select_subquery_aggregat_1(self):
         # percent users by groups
         self.execute('SET X in_group G WHERE G name "users"')
         rset = self.execute('Any GN, COUNT(X)*100/T GROUPBY GN ORDERBY 2,1'
@@ -845,6 +845,17 @@
         self.assertEquals(rset.rows, [[u'guests', 50], [u'managers', 50], [u'users', 100]])
         self.assertEquals(rset.description, [('String', 'Int'), ('String', 'Int'), ('String', 'Int')])
 
+    def test_select_subquery_aggregat_2(self):
+        expected = self.execute('Any X, 0, COUNT(T) GROUPBY X '
+                                'WHERE X is Workflow, T transition_of X').rows
+        rset = self.execute('''
+Any P1,B,E WHERE P1 identity P2 WITH
+  P1,B BEING (Any P,COUNT(T) GROUPBY P WHERE P is Workflow, T is Transition,
+              T? transition_of P, T type "auto"),
+  P2,E BEING (Any P,COUNT(T) GROUPBY P WHERE P is Workflow, T is Transition,
+              T? transition_of P, T type "normal")''')
+        self.assertEquals(sorted(rset.rows), sorted(expected))
+
     def test_select_subquery_const(self):
         rset = self.execute('Any X WITH X BEING ((Any NULL) UNION (Any "toto"))')
         self.assertEquals(rset.rows, [[None], ['toto']])