24
24
explode_execute ,
25
25
explode_query_range ,
26
26
format_query ,
27
+ get_columns ,
27
28
get_m2m_tables ,
28
29
get_value_or_en_translation ,
29
30
parallel_execute ,
30
31
table_exists ,
32
+ target_of ,
31
33
view_exists ,
32
34
)
33
35
@@ -268,7 +270,7 @@ def _replace_model_in_computed_custom_fields(cr, source, target):
268
270
)
269
271
270
272
271
- def rename_model (cr , old , new , rename_table = True ):
273
+ def rename_model (cr , old , new , rename_table = True , ignore_m2m = () ):
272
274
"""
273
275
Rename a model.
274
276
@@ -285,6 +287,70 @@ def rename_model(cr, old, new, rename_table=True):
285
287
new_table = table_of_model (cr , new )
286
288
if new_table != old_table :
287
289
pg_rename_table (cr , old_table , new_table )
290
+ m2m_tables = [t for t in get_m2m_tables (cr , new_table ) if t not in ignore_m2m ]
291
+ cr .execute (
292
+ """
293
+ SELECT relation_table,
294
+ ARRAY_AGG(id)
295
+ FROM ir_model_fields
296
+ WHERE ttype = 'many2many'
297
+ AND relation_table = ANY(%s)
298
+ AND ( model = %s
299
+ OR relation = %s)
300
+ GROUP BY relation_table
301
+ ORDER BY relation_table
302
+ """ ,
303
+ [m2m_tables , old , old ],
304
+ )
305
+ for m2m_table , field_ids in cr .fetchall ():
306
+ if not table_exists (cr , m2m_table ):
307
+ # Possibly handled in the upgrade scripts already
308
+ continue
309
+ new_m2m_table = m2m_table
310
+ m = re .match (r"(\w+)_{}_rel" .format (old_table ), m2m_table ) or re .match (
311
+ r"{}_(\w+)_rel" .format (old_table ), m2m_table
312
+ )
313
+ if m :
314
+ new_m2m_table = "{}_{}_rel" .format (* sorted ([m .group (1 ), new_table ]))
315
+ # For long table names the FK constraint is dropped when renaming the table
316
+ # We need the constraint to correctly identify the FK targets
317
+ # They will be dropped and recreated anyway here below
318
+ pg_rename_table (cr , m2m_table , new_m2m_table , remove_constraints = False )
319
+ _logger .info ("Renamed m2m table %s to %s" , m2m_table , new_m2m_table )
320
+ cr .execute (
321
+ "UPDATE ir_model_fields SET relation_table = %s WHERE id IN %s" ,
322
+ [new_m2m_table , tuple (field_ids )],
323
+ )
324
+ for m2m_col in get_columns (cr , new_m2m_table ).iter_unquoted ():
325
+ col_info = target_of (cr , new_m2m_table , m2m_col )
326
+ if col_info and col_info [0 ] == new_table and col_info [1 ] == "id" :
327
+ old_col , new_col = map ("{}_id" .format , [old_table , new_table ])
328
+ if m2m_col == old_col :
329
+ query = format_query (
330
+ cr ,
331
+ """
332
+ ALTER TABLE {m2m_table}
333
+ RENAME COLUMN {old_col} TO {new_col};
334
+
335
+ ALTER TABLE {m2m_table}
336
+ DROP CONSTRAINT {old_constraint_name},
337
+ ADD FOREIGN KEY ({new_col}) REFERENCES {new_table} (id)
338
+ """ ,
339
+ m2m_table = new_m2m_table ,
340
+ old_col = old_col ,
341
+ new_col = new_col ,
342
+ old_constraint_name = col_info [2 ],
343
+ new_table = new_table ,
344
+ )
345
+ cr .execute (query )
346
+ _logger .info ("Renamed m2m column of table %s from %s to %s" , m2m_table , old_col , new_col )
347
+ else :
348
+ _logger .warning (
349
+ "Possibly missing rename: the column %s of m2m table %s references the table %s" ,
350
+ m2m_col ,
351
+ m2m_table ,
352
+ new_table ,
353
+ )
288
354
289
355
updates = [("wkf" , "osv" )] if table_exists (cr , "wkf" ) else []
290
356
updates += [(ir .table , ir .res_model ) for ir in indirect_references (cr ) if ir .res_model ]
0 commit comments