@@ -1351,6 +1351,80 @@ def create_m2m(cr, m2m, fk1, fk2, col1=None, col2=None):
1351
1351
)
1352
1352
1353
1353
1354
+ def update_m2m_tables (cr , old_table , new_table , ignored_m2ms = ()):
1355
+ """
1356
+ Update m2m table names and columns.
1357
+
1358
+ :param str from_model: model for which the underlying table changed
1359
+ :param str old_table: former table of the model
1360
+ :param str new_table: new table of the model
1361
+ :param list(str) ignored_m2ms: explicit list of m2m tables to ignore
1362
+
1363
+ :meta private: exclude from online docs
1364
+ """
1365
+ if old_table == new_table or not version_gte ("10.0" ):
1366
+ return
1367
+ ignored_m2ms = set (ignored_m2ms )
1368
+ for orig_m2m_table in get_m2m_tables (cr , new_table ):
1369
+ if orig_m2m_table in ignored_m2ms :
1370
+ continue
1371
+ m = re .match (r"^(\w+)_{0}_rel|{0}_(\w+)_rel$" .format (re .escape (old_table )), orig_m2m_table )
1372
+ if m :
1373
+ m2m_table = "{}_{}_rel" .format (* sorted ([m .group (1 ) or m .group (2 ), new_table ]))
1374
+ # Due to the 63 chars limit in generated constraint names, for long table names the FK
1375
+ # constraint is dropped when renaming the table. We need the constraint to correctly
1376
+ # identify the FK targets. The FK constraints will be dropped and recreated below.
1377
+ rename_table (cr , orig_m2m_table , m2m_table , remove_constraints = False )
1378
+ _logger .info ("Renamed m2m table %s to %s" , orig_m2m_table , m2m_table )
1379
+ else :
1380
+ m2m_table = orig_m2m_table
1381
+ for m2m_col in get_columns (cr , m2m_table ).iter_unquoted ():
1382
+ col_info = target_of (cr , m2m_table , m2m_col )
1383
+ if not col_info or col_info [0 ] != new_table or col_info [1 ] != "id" :
1384
+ continue
1385
+ old_col , new_col = map ("{}_id" .format , [old_table , new_table ])
1386
+ if m2m_col != old_col :
1387
+ _logger .warning (
1388
+ "Possibly missing rename: the column %s of m2m table %s references the table %s" ,
1389
+ m2m_col ,
1390
+ m2m_table ,
1391
+ new_table ,
1392
+ )
1393
+ continue
1394
+ old_constraint = col_info [2 ]
1395
+ cr .execute (
1396
+ """
1397
+ SELECT c.confdeltype
1398
+ FROM pg_constraint c
1399
+ JOIN pg_class t
1400
+ ON c.conrelid = t.oid
1401
+ WHERE t.relname = %s
1402
+ AND c.conname = %s
1403
+ """ ,
1404
+ [m2m_table , old_constraint ],
1405
+ )
1406
+ on_delete = cr .fetchone ()[0 ][0 ]
1407
+ query = format_query (
1408
+ cr ,
1409
+ """
1410
+ ALTER TABLE {m2m_table}
1411
+ RENAME COLUMN {old_col} TO {new_col};
1412
+
1413
+ ALTER TABLE {m2m_table}
1414
+ DROP CONSTRAINT {old_constraint},
1415
+ ADD FOREIGN KEY ({new_col}) REFERENCES {new_table} (id) ON DELETE {del_action}
1416
+ """ ,
1417
+ m2m_table = m2m_table ,
1418
+ old_col = old_col ,
1419
+ new_col = new_col ,
1420
+ old_constraint = old_constraint ,
1421
+ new_table = new_table ,
1422
+ del_action = SQLStr ("RESTRICT" ) if on_delete == "r" else SQLStr ("CASCADE" ),
1423
+ )
1424
+ cr .execute (query )
1425
+ _logger .info ("Renamed m2m column of table %s from %s to %s" , m2m_table , old_col , new_col )
1426
+
1427
+
1354
1428
def fixup_m2m (cr , m2m , fk1 , fk2 , col1 = None , col2 = None ):
1355
1429
if col1 is None :
1356
1430
col1 = "%s_id" % fk1
0 commit comments