@@ -642,18 +642,44 @@ def view_exists(cr, view):
642
642
return bool (cr .rowcount )
643
643
644
644
645
- def remove_constraint (cr , table , name , cascade = False ):
645
+ def remove_constraint (cr , table , name , cascade = False , warn = True ):
646
+ """
647
+ Remove a table constraint.
648
+
649
+ This function removes the constraint `name` from `table`. It also removes records from
650
+ `ir_model_constraint` and its xml_ids. It logs not found constraints.
651
+
652
+ .. note::
653
+
654
+ If there is no constraint `name`, this function will attempt to remove
655
+ ``{table}_{name}``, the latter is the default name the ORM uses for constraints
656
+ created from `_sql_constraints`.
657
+
658
+ :param str table: table from where to remove the constraint
659
+ :param str name: name of the constraint to remove
660
+ :param bool cascade: cascade the constraint removal
661
+ :param bool warn: use warning level when logging not found constraints, otherwise use
662
+ info level
663
+ :return: whether the constraint was removed
664
+ :rtype: bool
665
+ """
646
666
_validate_table (table )
667
+ log = _logger .warning if warn else _logger .info
647
668
cascade = "CASCADE" if cascade else ""
648
669
cr .execute ('ALTER TABLE "{}" DROP CONSTRAINT IF EXISTS "{}" {}' .format (table , name , cascade ))
649
- # small exception: odoo specific action.
650
- # needs to be kept here to avoid resurive imports.
651
- # a solution would be to not do it now but adds an `end-` script that remove the invalid entries
652
- # from the `ir_model_constraint` table
670
+ # Exceptionally remove Odoo records, even if we are in PG land on this file. This is somehow
671
+ # valid because ir.model.constraint are ORM low-level objects that relate directly to table
672
+ # constraints.
653
673
cr .execute ("DELETE FROM ir_model_constraint WHERE name = %s RETURNING id" , [name ])
654
674
if cr .rowcount :
655
675
ids = tuple (c for (c ,) in cr .fetchall ())
656
676
cr .execute ("DELETE FROM ir_model_data WHERE model = 'ir.model.constraint' AND res_id IN %s" , [ids ])
677
+ return True
678
+ if name .startswith (table + "_" ):
679
+ log ("%r not found in ir_model_constraint, table=%r" , name , table )
680
+ return False
681
+ log ("%r not found in ir_model_constraint, attempting to remove with table %r prefix" , name , table )
682
+ return remove_constraint (cr , table , "{}_{}" .format (table , name ), cascade , warn )
657
683
658
684
659
685
def get_fk (cr , table , quote_ident = True ):
@@ -728,7 +754,7 @@ class IndexInfo(collections.namedtuple("IndexInfo", "name on isunique isconstrai
728
754
729
755
def drop (self , cr ):
730
756
if self .isconstraint :
731
- remove_constraint (cr , self .on , self .name )
757
+ remove_constraint (cr , self .on , self .name , warn = False )
732
758
else :
733
759
cr .execute ('DROP INDEX "%s"' % self .name )
734
760
@@ -1064,7 +1090,7 @@ def rename_table(cr, old_table, new_table, remove_constraints=True):
1064
1090
)
1065
1091
for (const ,) in cr .fetchall ():
1066
1092
_logger .info ("Dropping constraint %s on table %s" , const , new_table )
1067
- remove_constraint (cr , new_table , const )
1093
+ remove_constraint (cr , new_table , const , warn = False )
1068
1094
1069
1095
# rename fkeys
1070
1096
cr .execute (
0 commit comments