From 0d2c8796b4aabd97ec8ab1376e27813630a8b324 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Mon, 25 Oct 2010 12:05:40 +0200 Subject: [PATCH] [FIX] orm._check_concurrency: pop values from context after check to avoid false positives (e.g. nested writes) - one check per transaction is enough bzr revid: odo@openerp.com-20101025100540-oy374900sveb2o5f --- bin/osv/orm.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/bin/osv/orm.py b/bin/osv/orm.py index c24de8c07c2..a639a775b01 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -3191,15 +3191,17 @@ class orm(orm_template): return if not (context.get(self.CONCURRENCY_CHECK_FIELD) and self._log_access): return - def key(oid): - return "%s,%s" % (self._name, oid) - santa = "(id = %s AND %s < COALESCE(write_date, create_date, now())::timestamp)" - for i in range(0, len(ids), cr.IN_MAX): - sub_ids = tools.flatten(((oid, context[self.CONCURRENCY_CHECK_FIELD][key(oid)]) - for oid in ids[i:i+cr.IN_MAX] - if key(oid) in context[self.CONCURRENCY_CHECK_FIELD])) - if not sub_ids: continue - cr.execute("SELECT 1 FROM %s WHERE %s" % (self._table, " OR ".join([santa]*(len(sub_ids)/2))), sub_ids) + check_clause = "(id = %s AND %s < COALESCE(write_date, create_date, now())::timestamp)" + for sub_ids in cr.split_for_in_conditions(ids): + ids_to_check = [] + for id in sub_ids: + id_ref = "%s,%s" % (self._name, id) + update_date = context[self.CONCURRENCY_CHECK_FIELD].pop(id_ref, None) + if update_date: + ids_to_check.extend([id, update_date]) + if not ids_to_check: + continue + cr.execute("SELECT 1 FROM %s WHERE %s" % (self._table, " OR ".join([check_clause]*(len(ids_to_check)/2))), tuple(ids_to_check)) if cr.fetchone(): raise except_orm('ConcurrencyException', _('Records were modified in the meanwhile'))