closes #67696: crash with undo/Exists nodes (unreproduced by test though :( )
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 25 May 2011 15:39:36 +0200
changeset 630 e54b9379fc7c
parent 629 e7e1fc35bad5
child 632 7108e8bc1696
closes #67696: crash with undo/Exists nodes (unreproduced by test though :( )
test/unittest_editextensions.py
undo.py
--- a/test/unittest_editextensions.py	Thu May 19 09:58:09 2011 +0200
+++ b/test/unittest_editextensions.py	Wed May 25 15:39:36 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of rql.
@@ -19,10 +19,11 @@
 from logilab.common.testlib import TestCase, unittest_main
 
 from rql import parse
+from rql.nodes import Exists
 from rql.editextensions import *
 
 class RQLUndoTestCase(TestCase):
-    
+
     def test_selected(self):
         rqlst = parse('Person X')
         orig = rqlst.as_string()
@@ -40,7 +41,7 @@
         self.assertEqual(rqlst.as_string(), orig)
         # check references after recovering
         rqlst.check_references()
-    
+
     def test_selected3(self):
         rqlst = parse('Any lower(N) WHERE X is Person, X name N')
         orig = rqlst.as_string()
@@ -58,7 +59,7 @@
         self.assertEqual(rqlst.as_string(), orig)
         # check references after recovering
         rqlst.check_references()
-        
+
     def test_undefine_1(self):
         rqlst = parse('Person X, Y WHERE X travaille_pour Y')
         orig = rqlst.as_string()
@@ -73,7 +74,7 @@
         self.assertEqual(rqlst.as_string(), orig)
         # check references after recovering
         rqlst.check_references()
-        
+
     def test_undefine_2(self):
         rqlst = parse('Person X')
         orig = rqlst.as_string()
@@ -90,7 +91,24 @@
         self.assertEqual(rqlst.as_string(), orig)
         # check references after recovering
         rqlst.check_references()
-        
-        
+
+
+    def test_remove_exists(self):
+        rqlst = parse('Any U,COUNT(P) GROUPBY U WHERE U is CWUser, P? patch_reviewer U, EXISTS(P in_state S AND S name "pouet")').children[0]
+        orig = rqlst.as_string()
+        rqlst.save_state()
+        n = [r for r in rqlst.get_nodes(Exists)][0].query
+        rqlst.remove_node(n)
+        # check operations
+        self.assertEqual(rqlst.as_string(), 'Any U,COUNT(P) GROUPBY U WHERE U is CWUser, P? patch_reviewer U')
+        # check references before recovering
+        rqlst.check_references()
+        rqlst.recover()
+        # check equivalence
+        self.assertEqual(rqlst.as_string(), orig)
+        # check references after recovering
+        rqlst.check_references()
+
+
 if __name__ == '__main__':
     unittest_main()
--- a/undo.py	Thu May 19 09:58:09 2011 +0200
+++ b/undo.py	Wed May 25 15:39:36 2011 +0200
@@ -1,4 +1,4 @@
-# copyright 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2004-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of rql.
@@ -19,7 +19,7 @@
 
 __docformat__ = "restructuredtext en"
 
-from rql.nodes import VariableRef, Variable, BinaryNode
+from rql.nodes import Exists, VariableRef, Variable, BinaryNode
 from rql.stmts import Select
 
 class SelectionManager(object):
@@ -142,8 +142,8 @@
     def __init__(self, node, parent, stmt, index):
         NodeOperation.__init__(self, node, stmt)
         self.node_parent = parent
-        #if isinstance(parent, Select):
-        #    assert self.node is parent.where
+        if index is None:
+            assert isinstance(parent, (Exists, Select)), (node, parent)
         self.index = index
         # XXX FIXME : find a better way to do that
         self.binary_remove = isinstance(node, BinaryNode)
@@ -152,9 +152,11 @@
         """undo the operation on the selection"""
         parent = self.node_parent
         if self.index is None:
-            assert isinstance(parent, Select)
-            sibling = parent.where = self.node
-            parent.where = self.node
+            if isinstance(parent, Select):
+                parent.where = self.node
+            else: # Exists
+                parent.query = self.node
+            sibling = self.node
         if self.binary_remove:
             # if 'parent' was a BinaryNode, then first reinsert the removed node
             # at the same pos in the original 'parent' Binary Node, and then