Merge lp:~cedric-lebrouster/openobject-server/7.0-bug-1253052-parent-order into lp:openobject-server/7.0

Proposed by Cedric Le Brouster(OpenFire)
Status: Needs review
Proposed branch: lp:~cedric-lebrouster/openobject-server/7.0-bug-1253052-parent-order
Merge into: lp:openobject-server/7.0
Diff against target: 138 lines (+59/-36)
2 files modified
openerp/addons/base/test/base_test.yml (+13/-1)
openerp/osv/orm.py (+46/-35)
To merge this branch: bzr merge lp:~cedric-lebrouster/openobject-server/7.0-bug-1253052-parent-order
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+209670@code.launchpad.net

Description of the change

Fixes parent_left and parent_right recomputation in write/create methods ( bug lp:1253052 )

To post a comment you must log in.
5190. By Cedric Le Brouster(OpenFire)

Add tests for _parent_order

5191. By Cedric Le Brouster(OpenFire)

[FIX] orm: fix miscalculation of _parent_left and _parent_right in create() method for some special case.
(i.e. when new object parent's _parent_left value is 0)

Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

Unmerged revisions

5191. By Cedric Le Brouster(OpenFire)

[FIX] orm: fix miscalculation of _parent_left and _parent_right in create() method for some special case.
(i.e. when new object parent's _parent_left value is 0)

5190. By Cedric Le Brouster(OpenFire)

Add tests for _parent_order

5189. By Cedric Le Brouster(OpenFire)

[FIX] orm: wrong parent_left and parent_right recomputation in write/create methods (see bug 1253052)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openerp/addons/base/test/base_test.yml'
--- openerp/addons/base/test/base_test.yml 2014-04-16 11:22:39 +0000
+++ openerp/addons/base/test/base_test.yml 2014-06-13 10:05:21 +0000
@@ -137,7 +137,19 @@
137 assert len(old_struct) == 4, "After duplication, previous record must have old childs records only"137 assert len(old_struct) == 4, "After duplication, previous record must have old childs records only"
138 assert (not set(new_struct).intersection(old_struct)), "After duplication, nodes should not be mixed"138 assert (not set(new_struct).intersection(old_struct)), "After duplication, nodes should not be mixed"
139-139-
140 6. Restore pool state after the test140 6. Tests on _parent_order.
141-
142 !python {model: res.partner.category }: |
143 another_root = self.create(cr, uid, {'name':'Root categ'})
144 struct = self.search(cr, uid, [('id','in',(ref('test_categ_root'),another_root))])
145 assert struct[0]==another_root, "Root partner categories should be sorted."
146 struct = self.search(cr, uid, [('id','in',(ref('test_categ_1'),ref('test_categ_2')))])
147 assert struct[0]==ref('test_categ_1'), "Partner categories should be sorted."
148 self.write(cr, uid, ref('test_categ_1'), {'name':'Child 3'})
149 struct = self.search(cr, uid, [('id','in',(ref('test_categ_1'),ref('test_categ_2')))])
150 assert struct[0]==ref('test_categ_2'), "Partner categories should be re-sorted after name update."
151-
152 7. Restore pool state after the test
141-153-
142 !python {model: res.partner.category}: |154 !python {model: res.partner.category}: |
143 self.pool._init = True155 self.pool._init = True
144156
=== modified file 'openerp/osv/orm.py'
--- openerp/osv/orm.py 2014-05-19 16:12:41 +0000
+++ openerp/osv/orm.py 2014-06-13 10:05:21 +0000
@@ -4176,22 +4176,31 @@
41764176
4177 parents_changed = []4177 parents_changed = []
4178 parent_order = self._parent_order or self._order4178 parent_order = self._parent_order or self._order
4179 if self._parent_store and (self._parent_name in vals):4179 if self._parent_store:
4180 # The parent_left/right computation may take up to4180 # The parent_left/right computation may take up to
4181 # 5 seconds. No need to recompute the values if the4181 # 5 seconds. No need to recompute the values if the
4182 # parent is the same.4182 # parent and order field are the same.
4183 # Note: to respect parent_order, nodes must be processed in4183 # Note: to respect parent_order, nodes must be processed in
4184 # order, so ``parents_changed`` must be ordered properly.4184 # order, so ``parents_changed`` must be ordered properly.
4185 parent_val = vals[self._parent_name]4185 query = "SELECT id FROM %s WHERE id IN %%s" % (self._table,)
4186 if parent_val:4186 query_params = [tuple(ids)]
4187 query = "SELECT id FROM %s WHERE id IN %%s AND (%s != %%s OR %s IS NULL) ORDER BY %s" % \4187 query_clause = ""
4188 (self._table, self._parent_name, self._parent_name, parent_order)4188 parent_params = [self._parent_name]
4189 cr.execute(query, (tuple(ids), parent_val))4189 for param in parent_order.split(','):
4190 else:4190 parent_params.append(param.strip())
4191 query = "SELECT id FROM %s WHERE id IN %%s AND (%s IS NOT NULL) ORDER BY %s" % \4191 for parent_param in parent_params:
4192 (self._table, self._parent_name, parent_order)4192 if parent_param in vals:
4193 cr.execute(query, (tuple(ids),))4193 parents_changed = True
4194 parents_changed = map(operator.itemgetter(0), cr.fetchall())4194 parent_val = vals[parent_param]
4195 if parent_val:
4196 query_clause += (query_clause and ' OR ' or '') + "%s != %%s OR %s IS NULL" % (parent_param,parent_param)
4197 query_params.append(parent_val)
4198 else:
4199 query_clause += (query_clause and ' OR ' or '') + "%s IS NOT NULL" % (parent_param,)
4200 if parents_changed:
4201 query += (query_clause and (' AND (' + query_clause + ')') or '') + " ORDER BY %s" % (self._parent_order,)
4202 cr.execute(query, tuple(query_params))
4203 parents_changed = map(operator.itemgetter(0), cr.fetchall())
41954204
4196 upd0 = []4205 upd0 = []
4197 upd1 = []4206 upd1 = []
@@ -4289,18 +4298,16 @@
4289 if self.pool._init:4298 if self.pool._init:
4290 self.pool._init_parent[self._name] = True4299 self.pool._init_parent[self._name] = True
4291 else:4300 else:
4292 order = self._parent_order or self._order
4293 parent_val = vals[self._parent_name]
4294 if parent_val:
4295 clause, params = '%s=%%s' % (self._parent_name,), (parent_val,)
4296 else:
4297 clause, params = '%s IS NULL' % (self._parent_name,), ()
4298
4299 for id in parents_changed:4301 for id in parents_changed:
4300 cr.execute('SELECT parent_left, parent_right FROM %s WHERE id=%%s' % (self._table,), (id,))4302 cr.execute('SELECT parent_left, parent_right, %s FROM %s WHERE id=%%s' % (self._parent_name, self._table,), (id,))
4301 pleft, pright = cr.fetchone()4303 pleft, pright, parent_val = cr.fetchone()
4302 distance = pright - pleft + 14304 distance = pright - pleft + 1
43034305
4306 if parent_val:
4307 clause, params = '%s=%%s' % (self._parent_name,), (parent_val,)
4308 else:
4309 clause, params = '%s IS NULL' % (self._parent_name,), ()
4310
4304 # Positions of current siblings, to locate proper insertion point;4311 # Positions of current siblings, to locate proper insertion point;
4305 # this can _not_ be fetched outside the loop, as it needs to be refreshed4312 # this can _not_ be fetched outside the loop, as it needs to be refreshed
4306 # after each update, in case several nodes are sequentially inserted one4313 # after each update, in case several nodes are sequentially inserted one
@@ -4520,21 +4527,25 @@
4520 self.pool._init_parent[self._name] = True4527 self.pool._init_parent[self._name] = True
4521 else:4528 else:
4522 parent = vals.get(self._parent_name, False)4529 parent = vals.get(self._parent_name, False)
4530 where_clause = ' where '+self._parent_name
4523 if parent:4531 if parent:
4524 cr.execute('select parent_right from '+self._table+' where '+self._parent_name+'=%s order by '+(self._parent_order or self._order), (parent,))4532 where_clause += '=%s'
4525 pleft_old = None4533 where_params = (parent,)
4526 result_p = cr.fetchall()4534 else:
4527 for (pleft,) in result_p:4535 where_clause += ' is null'
4528 if not pleft:4536 where_params = tuple()
4529 break4537 cr.execute('select parent_right from '+self._table + where_clause+' order by '+(self._parent_order or self._order), where_params)
4530 pleft_old = pleft4538 pleft_old = None
4531 if not pleft_old:4539 result_p = cr.fetchall()
4532 cr.execute('select parent_left from '+self._table+' where id=%s', (parent,))4540 for (pleft,) in result_p:
4533 pleft_old = cr.fetchone()[0]4541 if not pleft:
4534 pleft = pleft_old4542 break
4535 else:4543 pleft_old = pleft
4536 cr.execute('select max(parent_right) from '+self._table)4544 if not pleft_old and parent:
4537 pleft = cr.fetchone()[0] or 04545 cr.execute('select parent_left from '+self._table+' where id=%s', (parent,))
4546 pleft = cr.fetchone()[0]
4547 else:
4548 pleft = pleft_old or -1
4538 cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%s', (pleft,))4549 cr.execute('update '+self._table+' set parent_left=parent_left+2 where parent_left>%s', (pleft,))
4539 cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%s', (pleft,))4550 cr.execute('update '+self._table+' set parent_right=parent_right+2 where parent_right>%s', (pleft,))
4540 cr.execute('update '+self._table+' set parent_left=%s,parent_right=%s where id=%s', (pleft+1, pleft+2, id_new))4551 cr.execute('update '+self._table+' set parent_left=%s,parent_right=%s where id=%s', (pleft+1, pleft+2, id_new))