[FIX] fields: in many2many fields, avoid inserting duplicate entries in table

This commit is contained in:
Raphael Collet 2016-01-06 16:27:37 +01:00
parent 4f1bd899ef
commit ece592dbf7
1 changed files with 11 additions and 6 deletions

View File

@ -761,6 +761,15 @@ class many2many(_column):
return
rel, id1, id2 = self._sql_names(model)
obj = model.pool.get(self._obj)
def link(ids):
# beware of duplicates when inserting
query = """ INSERT INTO {rel} ({id1}, {id2})
(SELECT %s, unnest(%s)) EXCEPT (SELECT {id1}, {id2} FROM {rel} WHERE {id1}=%s)
""".format(rel=rel, id1=id1, id2=id2)
for sub_ids in cr.split_for_in_conditions(ids):
cr.execute(query, (id, list(sub_ids), id))
for act in values:
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
continue
@ -774,10 +783,7 @@ class many2many(_column):
elif act[0] == 3:
cr.execute('delete from '+rel+' where ' + id1 + '=%s and '+ id2 + '=%s', (id, act[1]))
elif act[0] == 4:
# following queries are in the same transaction - so should be relatively safe
cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+' = %s and '+id2+' = %s', (id, act[1]))
if not cr.fetchone():
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s,%s)', (id, act[1]))
link([act[1]])
elif act[0] == 5:
cr.execute('delete from '+rel+' where ' + id1 + ' = %s', (id,))
elif act[0] == 6:
@ -789,8 +795,7 @@ class many2many(_column):
d1 = ''
cr.execute('delete from '+rel+' where '+id1+'=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2)
for act_nbr in act[2]:
cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s, %s)', (id, act_nbr))
link(act[2])
#
# TODO: use a name_search