[rset] replace entity cw_rset on .limit(inplace=True) will avoid pb if the entity is still referenced by some other entity relations cache. Closes #2065643 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 03 Nov 2011 15:27:31 +0100
branchstable
changeset 8048 10a0f73d834d
parent 8047 972360b7677b
child 8049 a48301a44b50
child 8052 fbeb82fe45a4
[rset] replace entity cw_rset on .limit(inplace=True) will avoid pb if the entity is still referenced by some other entity relations cache. Closes #2065643 Also, drop '_resultset' from some test names on the way (redundant information, we're in ResultSetTC...)
rset.py
test/unittest_rset.py
--- a/rset.py	Thu Nov 03 11:44:02 2011 +0100
+++ b/rset.py	Thu Nov 03 15:27:31 2011 +0100
@@ -351,7 +351,8 @@
                     if offset <= entity.cw_row < stop:
                         entity.cw_row = entity.cw_row - offset
                     else:
-                        self.req.drop_entity_cache(entity.eid)
+                        entity.cw_rset = entity.as_rset()
+                        entity.cw_row = entity.cw_col = 0
         else:
             rset = self.copy(rows, descr)
             if not offset:
--- a/test/unittest_rset.py	Thu Nov 03 11:44:02 2011 +0100
+++ b/test/unittest_rset.py	Thu Nov 03 15:27:31 2011 +0100
@@ -107,7 +107,7 @@
         self.compare_urls(req.build_url('view', _restpath=''), baseurl)
 
 
-    def test_resultset_build(self):
+    def test_build(self):
         """test basic build of a ResultSet"""
         rs = ResultSet([1,2,3], 'CWGroup X', description=['CWGroup', 'CWGroup', 'CWGroup'])
         self.assertEqual(rs.rowcount, 3)
@@ -115,7 +115,7 @@
         self.assertEqual(rs.description, ['CWGroup', 'CWGroup', 'CWGroup'])
 
 
-    def test_resultset_limit(self):
+    def test_limit(self):
         rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
                        'Any U,L where U is CWUser, U login L',
                        description=[['CWUser', 'String']] * 3)
@@ -128,8 +128,30 @@
         self.assertEqual(rs.limit(2, offset=2).rows, [[14000, 'nico']])
         self.assertEqual(rs.limit(2, offset=3).rows, [])
 
+    def test_limit_2(self):
+        req = self.request()
+        # drop user from cache for the sake of this test
+        req.drop_entity_cache(req.user.eid)
+        rs = req.execute('Any E,U WHERE E is CWEType, E created_by U')
+        # get entity on row 9. This will fill its created_by relation cache,
+        # with cwuser on row 9 as well
+        e1 = rs.get_entity(9, 0)
+        # get entity on row 10. This will fill its created_by relation cache,
+        # with cwuser built on row 9
+        e2 = rs.get_entity(10, 0)
+        # limit result set from row 10
+        rs.limit(1, 10, inplace=True)
+        # get back eid
+        e = rs.get_entity(0, 0)
+        self.assertTrue(e2 is e)
+        # rs.limit has properly removed cwuser for request cache, but it's
+        # still referenced by e/e2 relation cache
+        u = e.created_by[0]
+        # now ensure this doesn't trigger IndexError because cwuser.cw_row is 9
+        # while now rset has only one row
+        u.cw_rset[u.cw_row]
 
-    def test_resultset_filter(self):
+    def test_filter(self):
         rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
                        'Any U,L where U is CWUser, U login L',
                        description=[['CWUser', 'String']] * 3)
@@ -142,7 +164,7 @@
         self.assertEqual(len(rs2), 2)
         self.assertEqual([login for _, login in rs2], ['adim', 'syt'])
 
-    def test_resultset_transform(self):
+    def test_transform(self):
         rs = ResultSet([[12, 'adim'], [13, 'syt'], [14, 'nico']],
                        'Any U,L where U is CWUser, U login L',
                        description=[['CWUser', 'String']] * 3)
@@ -154,7 +176,7 @@
         self.assertEqual(len(rs2), 3)
         self.assertEqual(list(rs2), [['adim'],['syt'],['nico']])
 
-    def test_resultset_sort(self):
+    def test_sort(self):
         rs = ResultSet([[12000, 'adim'], [13000, 'syt'], [14000, 'nico']],
                        'Any U,L where U is CWUser, U login L',
                        description=[['CWUser', 'String']] * 3)
@@ -179,7 +201,7 @@
         # make sure rs is unchanged
         self.assertEqual([login for _, login in rs], ['adim', 'syt', 'nico'])
 
-    def test_resultset_split(self):
+    def test_split(self):
         rs = ResultSet([[12000, 'adim', u'Adim chez les pinguins'],
                         [12000, 'adim', u'Jardiner facile'],
                         [13000, 'syt',  u'Le carrelage en 42 leçons'],