diff --git a/bin/addons/base/base.sql b/bin/addons/base/base.sql index 90da118f475..802e71cfeb6 100644 --- a/bin/addons/base/base.sql +++ b/bin/addons/base/base.sql @@ -161,7 +161,8 @@ CREATE TABLE res_groups ( CREATE TABLE res_groups_users_rel ( uid integer NOT NULL references res_users on delete cascade, - gid integer NOT NULL references res_groups on delete cascade + gid integer NOT NULL references res_groups on delete cascade, + UNIQUE("uid","gid") ); create index res_groups_users_rel_uid_idx on res_groups_users_rel (uid); diff --git a/bin/osv/fields.py b/bin/osv/fields.py index 423bd9cf1d1..63886e17e6a 100644 --- a/bin/osv/fields.py +++ b/bin/osv/fields.py @@ -615,7 +615,10 @@ class many2many(_column): elif act[0] == 3: cr.execute('delete from '+self._rel+' where ' + self._id1 + '=%s and '+ self._id2 + '=%s', (id, act[1])) elif act[0] == 4: - cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, act[1])) + # following queries are in the same transaction - so should be relatively safe + cr.execute('SELECT 1 FROM '+self._rel+' WHERE '+self._id1+' = %s and '+self._id2+' = %s', (id, act[1])) + if not cr.fetchone(): + cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, act[1])) elif act[0] == 5: cr.execute('update '+self._rel+' set '+self._id2+'=null where '+self._id2+'=%s', (id,)) elif act[0] == 6: diff --git a/bin/osv/orm.py b/bin/osv/orm.py index f929ee6a544..92a67326e4e 100644 --- a/bin/osv/orm.py +++ b/bin/osv/orm.py @@ -2551,7 +2551,7 @@ class orm(orm_template): raise except_orm('Programming Error', ('There is no reference available for %s') % (f._obj,)) ref = self.pool.get(f._obj)._table # ref = f._obj.replace('.', '_') - cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE, "%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE) WITH OIDS' % (f._rel, f._id1, self._table, f._id2, ref)) + cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE, "%s" INTEGER NOT NULL REFERENCES "%s" ON DELETE CASCADE, UNIQUE("%s","%s")) WITH OIDS' % (f._rel, f._id1, self._table, f._id2, ref, f._id1, f._id2)) cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id1, f._rel, f._id1)) cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id2, f._rel, f._id2)) cr.execute("COMMENT ON TABLE \"%s\" IS 'RELATION BETWEEN %s AND %s'" % (f._rel, self._table, ref))