[rewrite] Fix crash when the main variable doesn't appear in the snippet's vargraph stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 13 Mar 2014 17:32:40 +0100
branchstable
changeset 9593 48a84fb4f301
parent 9592 6fd2651719bc
child 9594 e549ef4be945
[rewrite] Fix crash when the main variable doesn't appear in the snippet's vargraph Also, the added test discover another bug once the first has been fixed (erroneous argument given to .rewrite recursive call). Closes #3661918
rqlrewrite.py
test/unittest_rqlrewrite.py
--- a/rqlrewrite.py	Thu Mar 13 15:33:22 2014 +0100
+++ b/rqlrewrite.py	Thu Mar 13 17:32:40 2014 +0100
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -405,7 +405,7 @@
                     assert len(subquery.children) == 1
                     subselect = subquery.children[0]
                     RQLRewriter(self.session).rewrite(subselect, [(varmap, rqlexprs)],
-                                                      subselect.solutions, self.kwargs)
+                                                      self.kwargs)
                     return
                 if varexistsmap is None:
                     # build an index for quick access to relations
@@ -790,7 +790,7 @@
         vargraph = self.current_expr.vargraph
         for existingvar in self.existingvars:
             #path = has_path(vargraph, varname, existingvar)
-            if has_path(vargraph, varname, existingvar):
+            if not varname in vargraph or has_path(vargraph, varname, existingvar):
                 return True
         # no path from this variable to an existing variable
         return False
--- a/test/unittest_rqlrewrite.py	Thu Mar 13 15:33:22 2014 +0100
+++ b/test/unittest_rqlrewrite.py	Thu Mar 13 17:32:40 2014 +0100
@@ -1,4 +1,4 @@
-# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -555,5 +555,40 @@
                              'AC is CWUser, E is CWUser, X is IN(Division, Societe)',
                              union.as_string())
 
+    def test_question_mark_attribute_snippet(self):
+        # see #3661918
+        from cubicweb.rqlrewrite import RQLRewriter
+        from logilab.common.decorators import monkeypatch
+        repotest.undo_monkey_patch()
+        orig_insert_snippets = RQLRewriter.insert_snippets
+        # patch insert_snippets and not rewrite, insert_snippets is already
+        # monkey patches (see above setupModule/repotest)
+        @monkeypatch(RQLRewriter)
+        def insert_snippets(self, snippets, varexistsmap=None):
+            # crash occurs if snippets are processed in a specific order, force
+            # destiny
+            if snippets[0][0] != {u'N': 'X'}:
+                snippets = list(reversed(snippets))
+            return orig_insert_snippets(self, snippets, varexistsmap)
+        try:
+            with self.temporary_permissions(
+                    (self.schema['Affaire'],
+                     {'read': (ERQLExpression('X ref "blah"'), )}),
+                    (self.schema['Note'],
+                     {'read': (ERQLExpression(
+                         'EXISTS(X inlined_affaire Z), EXISTS(Z owned_by U)'), )}),
+            ):
+                union = self.process(
+                    'Any A,COUNT(N) GROUPBY A '
+                    'WHERE A is Affaire, N? inlined_affaire A')
+                self.assertEqual('Any A,COUNT(N) GROUPBY A WHERE A is Affaire '
+                                 'WITH N,A BEING (Any N,A WHERE N? inlined_affaire A, '
+                                 '(N is NULL) OR (EXISTS(EXISTS(N inlined_affaire B), '
+                                 'EXISTS(B owned_by %(E)s), B is Affaire)), '
+                                 'A is Affaire, N is Note, EXISTS(A ref "blah"))',
+                                 union.as_string())
+        finally:
+            RQLRewriter.insert_snippets = orig_insert_snippets
+
 if __name__ == '__main__':
     unittest_main()