diff --git a/trytond/osv/fields.py b/trytond/osv/fields.py index 473d463520..5ed1836cfe 100644 --- a/trytond/osv/fields.py +++ b/trytond/osv/fields.py @@ -52,7 +52,7 @@ class Column(object): def __init__(self, string='unknown', required=False, readonly=False, domain=None, context='', states=None, priority=0, - change_default=False, size=None, ondelete="set null", + change_default=False, size=None, ondelete="SET NULL", translate=False, select=0, on_change=None, on_change_with=None, **args): self.states = states or {} @@ -447,13 +447,16 @@ class Many2Many(Column): _classic_write = False _type = 'many2many' - def __init__(self, obj, rel, id1, id2, string='unknown', limit=None, - order=None, **args): + def __init__(self, obj, rel, origin, target, string='unknown', limit=None, + order=None, ondelete_origin='CASCADE', ondelete_target='RESTRICT', + **args): Column.__init__(self, string=string, **args) self._obj = obj self._rel = rel - self._id1 = id1 - self._id2 = id2 + self.origin = origin + self.ondelete_origin = ondelete_origin + self.target = target + self.ondelete_target = ondelete_target self._limit = limit self._order = order @@ -476,12 +479,12 @@ class Many2Many(Column): domain1 = ' and '+domain1 #TODO fix order: can have many fields - cursor.execute('SELECT ' + self._rel + '.' + self._id2 + ', ' + \ - self._rel + '.' + self._id1 + ' ' \ + cursor.execute('SELECT ' + self._rel + '.' + self.target + ', ' + \ + self._rel + '.' + self.origin + ' ' \ 'FROM "' + self._rel + '" , "' + obj._table + '" ' \ 'WHERE ' + \ - self._rel + '.' + self._id1 + ' IN (' + ids_s + ') ' \ - 'AND ' + self._rel + '.' + self._id2 + ' = ' + \ + self._rel + '.' + self.origin + ' IN (' + ids_s + ') ' \ + 'AND ' + self._rel + '.' + self.target + ' = ' + \ obj._table + '.id ' + domain1 + \ limit_str + ' ORDER BY ' + \ ','.join([obj._table + '.' + x[0] + ' ' + x[1] \ @@ -499,7 +502,7 @@ class Many2Many(Column): if act[0] == 'create': idnew = obj.create(cursor, user, act[1], context=context) cursor.execute('INSERT INTO "' + self._rel + '" ' \ - '(' + self._id1 + ', ' + self._id2 + ') ' \ + '(' + self.origin + ', ' + self.target + ') ' \ 'VALUES (%s, %s)', (obj_id, idnew)) elif act[0] == 'write': obj.write(cursor, user, act[1] , act[2], context=context) @@ -513,8 +516,8 @@ class Many2Many(Column): if not ids: continue cursor.execute('DELETE FROM "' + self._rel + '" ' \ - 'WHERE "' + self._id1 + '" = %s ' \ - 'AND "'+ self._id2 + '" IN (' \ + 'WHERE "' + self.origin + '" = %s ' \ + 'AND "'+ self.target + '" IN (' \ + ','.join(['%s' for x in ids]) + ')', [obj_id] + ids) elif act[0] == 'add': @@ -522,10 +525,10 @@ class Many2Many(Column): ids = [act[1]] else: ids = list(act[1]) - cursor.execute('SELECT "' + self._id2 + '" ' \ + cursor.execute('SELECT "' + self.target + '" ' \ 'FROM "' + self._rel + '" ' \ - 'WHERE ' + self._id1 + ' = %s ' \ - 'AND ' + self._id2 + ' IN (' + \ + 'WHERE ' + self.origin + ' = %s ' \ + 'AND ' + self.target + ' IN (' + \ ','.join(['%s' for x in ids]) + ')', [obj_id] + ids) existing_ids = [] @@ -534,12 +537,12 @@ class Many2Many(Column): new_ids = [x for x in ids if x not in existing_ids] for new_id in new_ids: cursor.execute('INSERT INTO "' + self._rel + '" ' \ - '("' + self._id1 + '", "' + self._id2 + '") ' \ + '("' + self.origin + '", "' + self.target + '") ' \ 'VALUES (%s, %s)', (obj_id, new_id)) elif act[0] == 'unlink_all': cursor.execute('UPDATE "' + self._rel + '" ' \ - 'SET "' + self._id2 + '" = NULL ' \ - 'WHERE "' + self._id2 + '" = %s', (obj_id,)) + 'SET "' + self.target + '" = NULL ' \ + 'WHERE "' + self.target + '" = %s', (obj_id,)) elif act[0] == 'set': if not act[1]: ids = [] @@ -550,18 +553,18 @@ class Many2Many(Column): if domain1: domain1 = ' AND ' + domain1 cursor.execute('DELETE FROM "' + self._rel + '" ' \ - 'WHERE "' + self._id1 + '" = %s ' \ - 'AND "' + self._id2 + '" IN (' \ - 'SELECT ' + self._rel + '.' + self._id2 + ' ' \ + 'WHERE "' + self.origin + '" = %s ' \ + 'AND "' + self.target + '" IN (' \ + 'SELECT ' + self._rel + '.' + self.target + ' ' \ 'FROM "' + self._rel + '", "' + obj._table + '" ' \ - 'WHERE ' + self._rel + '.' + self._id1 + ' = %s ' \ - 'AND ' + self._rel + '.' + self._id2 + ' = ' + \ + 'WHERE ' + self._rel + '.' + self.origin + ' = %s ' \ + 'AND ' + self._rel + '.' + self.target + ' = ' + \ obj._table + '.id ' + domain1 + ')', [obj_id, obj_id] + domain2) for new_id in ids: cursor.execute('INSERT INTO "' + self._rel + '" ' \ - '("' + self._id1 + '", "' + self._id2 + '") ' \ + '("' + self.origin + '", "' + self.target + '") ' \ 'VALUES (%s, %s)', (obj_id, new_id)) else: raise Exception('Bad arguments') diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index 49bb97a8bd..6f58f0e9a8 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -537,7 +537,9 @@ class ORM(object): ref = field._obj.replace('.','_') else: ref = self.pool.get(field._obj)._table - table.add_m2m(field_name, ref, field._rel, field._id1, field._id2) + table.add_m2m(field_name, ref, field._rel, field.origin, + field.target, field.ondelete_origin, + field.ondelete_target) elif not isinstance(field, (fields.One2Many, fields.Function)): raise Exception('Unknow field type !') @@ -2427,9 +2429,9 @@ class ORM(object): ids2 = self.pool.get(field._obj).search(cursor, user, [(args[i][3], 'child_of', ids2)], context=context) - query1 = 'SELECT "' + field._id1 + '" ' \ + query1 = 'SELECT "' + field.origin + '" ' \ 'FROM "' + field._rel + '" ' \ - 'WHERE "' + field._id2 + '" IN (' + \ + 'WHERE "' + field.target + '" IN (' + \ ','.join(['%s' for x in ids2]) + ')' query2 = [str(x) for x in ids2] args[i] = ('id', 'inselect', (query1, query2)) @@ -2444,7 +2446,7 @@ class ORM(object): else: res_ids = args[i][2] if res_ids == True or res_ids == False: - query1 = 'SELECT "' + field._id1 + '" ' \ + query1 = 'SELECT "' + field.origin + '" ' \ 'FROM "' + field._rel + '"' query2 = [] clause = 'inselect' @@ -2454,9 +2456,9 @@ class ORM(object): elif not res_ids: args[i] = ('id', '=', '0') else: - query1 = 'SELECT "' + field._id1 + '" ' \ + query1 = 'SELECT "' + field.origin + '" ' \ 'FROM "' + field._rel + '" ' \ - 'WHERE "' + field._id2 + '" IN (' + \ + 'WHERE "' + field.target + '" IN (' + \ ','.join(['%s' for x in res_ids]) + ')' query2 = [str(x) for x in res_ids] args[i] = ('id', 'inselect', (query1, query2)) diff --git a/trytond/sql_db.py b/trytond/sql_db.py index 361d50f2c5..1308711681 100644 --- a/trytond/sql_db.py +++ b/trytond/sql_db.py @@ -388,7 +388,8 @@ class table_handler: self.update_definitions() - def add_m2m(self, column_name, other_table, relation_table, rtable_from, rtable_to): + def add_m2m(self, column_name, other_table, relation_table, rtable_from, rtable_to, + on_delete_from, on_delete_to): if not table_exist(self.cursor, other_table): raise Exception("table %s not found"%other_table) rtable = table_handler( @@ -397,8 +398,8 @@ class table_handler: from osv.fields import Integer rtable.add_raw_column(rtable_from, ('int4', 'int4'), Integer._symbol_set) rtable.add_raw_column(rtable_to, ('int4', 'int4'), Integer._symbol_set) - rtable.add_fk(rtable_from, self.table_name) - rtable.add_fk(rtable_to, other_table) + rtable.add_fk(rtable_from, self.table_name, on_delete=on_delete_from) + rtable.add_fk(rtable_to, other_table, on_delete=on_delete_to) rtable.not_null_action(rtable_from) rtable.not_null_action(rtable_to) rtable.index_action(rtable_from, 'add')