Merge lp:~therp-nl/openupgrade-server/7.0-lp1131653_check_recursion_fix_false_positives into lp:openupgrade-server

Proposed by Stefan Rijnhart (Opener)
Status: Work in progress
Proposed branch: lp:~therp-nl/openupgrade-server/7.0-lp1131653_check_recursion_fix_false_positives
Merge into: lp:openupgrade-server
Diff against target: 47 lines (+17/-8)
1 file modified
openerp/osv/orm.py (+17/-8)
To merge this branch: bzr merge lp:~therp-nl/openupgrade-server/7.0-lp1131653_check_recursion_fix_false_positives
Reviewer Review Type Date Requested Status
Mohammad Alhashash (community) Needs Fixing
Holger Brunn (Therp) Needs Fixing
Review via email: mp+150053@code.launchpad.net

Description of the change

The bug that this branch aims to fix was discovered when testing the migration scripts for the base module.

To post a comment you must log in.
Revision history for this message
Holger Brunn (Therp) (hbrunn) wrote :

You can do that a lot simpler and save fetches by letting the server build a common table expression that checks for cycles:

create table rec_test (id int, parent_id int) -- that's just for the example

with recursive check_cycle(id, parent_id, is_cycle) as (select id, parent_id, False from rec_test union all select check_cycle.id, rec_test.parent_id, check_cycle.id = rec_test.parent_id from check_cycle join rec_test on check_cycle.parent_id=rec_test.id and rec_test.parent_id is not null and not is_cycle) select * from check_cycle -- that's the real thing

Filter for the ids to check in the non-recursive part, then select rows with is_cycle=True and you're done with just this statement.

review: Needs Fixing
Revision history for this message
Holger Brunn (Therp) (hbrunn) wrote :

PS: This fix should also go to lp:ocb-server, right?

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote :

Amazing, thanks! I had already set this branch to 'work in progress' because my fix still had the original flaw under different circumstances. I'd like to work this out but I will not have the time now. Maybe if the overhead of the workaround (https://code.launchpad.net/~therp-nl/openupgrade-server/7.0-lp1131653_workaround/+merge/150071) starts to bother me...

As for lp:ocb-server, I cannot say that it is affected by this issue as I only ever encountered it in the OpenUpgrade process. Note that the bug was never reported before while the code has been around for some time.

Revision history for this message
Mohammad Alhashash (alhashash) wrote :
review: Needs Fixing

Unmerged revisions

4605. By Stefan Rijnhart (Opener)

[FIX] _check_recursion gives false positive if ids include a parent/child pair

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openerp/osv/orm.py'
--- openerp/osv/orm.py 2013-02-19 21:32:25 +0000
+++ openerp/osv/orm.py 2013-02-22 14:20:30 +0000
@@ -1943,7 +1943,10 @@
1943 msg = "\n * ".join([r[0] for r in res])1943 msg = "\n * ".join([r[0] for r in res])
1944 msg += "\n\nEither you wrongly customized this view, or some modules bringing those views are not compatible with your current data model"1944 msg += "\n\nEither you wrongly customized this view, or some modules bringing those views are not compatible with your current data model"
1945 _logger.error(msg)1945 _logger.error(msg)
1946 raise except_orm('View error', msg)1946 # OpenUpgrade: do not raise for unknown fields, as these
1947 # can be triggered on old views that still have to be
1948 # replaced by the upgrade procedure
1949 # raise except_orm('View error', msg)
1947 return arch, fields1950 return arch, fields
19481951
1949 def _get_default_form_view(self, cr, user, context=None):1952 def _get_default_form_view(self, cr, user, context=None):
@@ -5084,18 +5087,24 @@
50845087
5085 if not parent:5088 if not parent:
5086 parent = self._parent_name5089 parent = self._parent_name
5087 ids_parent = ids[:]5090 # OpenUpgrade: include a fix for https://bugs.launchpad.net/bugs/1131653
5088 query = 'SELECT distinct "%s" FROM "%s" WHERE id IN %%s' % (parent, self._table)5091 # as this bug was discovered writing default values for new fields
5092 query = 'SELECT id, "%s" FROM "%s" WHERE id IN %%s' % (parent, self._table)
5093 ids_parent = ids
5094 hierarchy = []
5089 while ids_parent:5095 while ids_parent:
5090 ids_parent2 = []5096 ids_parent2 = []
5091 for i in range(0, len(ids), cr.IN_MAX):5097 for i in range(0, len(ids_parent), cr.IN_MAX):
5092 sub_ids_parent = ids_parent[i:i+cr.IN_MAX]5098 sub_ids_parent = ids_parent[i:i+cr.IN_MAX]
5093 cr.execute(query, (tuple(sub_ids_parent),))5099 cr.execute(query, (tuple(sub_ids_parent),))
5094 ids_parent2.extend(filter(None, map(lambda x: x[0], cr.fetchall())))5100 for row in cr.fetchall():
5101 if row[1]:
5102 if row in hierarchy:
5103 return False
5104 hierarchy.append(row)
5105 if row[1] not in ids_parent2:
5106 ids_parent2.append(row[1])
5095 ids_parent = ids_parent25107 ids_parent = ids_parent2
5096 for i in ids_parent:
5097 if i in ids:
5098 return False
5099 return True5108 return True
51005109
5101 def _get_external_ids(self, cr, uid, ids, *args, **kwargs):5110 def _get_external_ids(self, cr, uid, ids, *args, **kwargs):

Subscribers

People subscribed via source and target branches