# HG changeset patch # User Sylvain Thénault # Date 1394728360 -3600 # Node ID 48a84fb4f301c3f76efa3a5069479fb1228ea500 # Parent 6fd2651719bcf002f018ac1bb799b5e672560920 [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 diff -r 6fd2651719bc -r 48a84fb4f301 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 diff -r 6fd2651719bc -r 48a84fb4f301 test/unittest_rqlrewrite.py --- 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()