diff --git a/frappe/database/schema.py b/frappe/database/schema.py index 5920d14c3d..9e689f8c3c 100644 --- a/frappe/database/schema.py +++ b/frappe/database/schema.py @@ -17,18 +17,18 @@ class DBTable: self.doctype = doctype self.table_name = f"tab{doctype}" self.meta = meta or frappe.get_meta(doctype, False) - self.columns = {} + self.columns: dict[str, DbColumn] = {} self.current_columns = {} # lists for change - self.add_column = [] - self.change_type = [] - self.change_name = [] - self.add_unique = [] - self.add_index = [] - self.drop_unique = [] - self.drop_index = [] - self.set_default = [] + self.add_column: list[DbColumn] = [] + self.change_type: list[DbColumn] = [] + self.change_name: list[DbColumn] = [] + self.add_unique: list[DbColumn] = [] + self.add_index: list[DbColumn] = [] + self.drop_unique: list[DbColumn] = [] + self.drop_index: list[DbColumn] = [] + self.set_default: list[DbColumn] = [] # load self.get_columns_from_docfields() diff --git a/frappe/tests/test_db_update.py b/frappe/tests/test_db_update.py index bbb10aec2c..0cc0de065c 100644 --- a/frappe/tests/test_db_update.py +++ b/frappe/tests/test_db_update.py @@ -1,4 +1,5 @@ import frappe +from frappe.core.doctype.doctype.test_doctype import new_doctype from frappe.core.utils import find from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.tests.utils import FrappeTestCase @@ -87,6 +88,36 @@ class TestDBUpdate(FrappeTestCase): email_sig_column = get_table_column("User", "email_signature") self.assertEqual(email_sig_column.index, 1) + def check_unique_indexes(self, doctype: str, field: str): + indexes = frappe.db.sql( + f"""show index from `tab{doctype}` where column_name = '{field}' and Non_unique = 0""", + as_dict=1, + ) + self.assertEqual( + len(indexes), 1, msg=f"There should be 1 index on {doctype}.{field}, found {indexes}" + ) + + def test_unique_index_on_install(self): + """Only one unique index should be added""" + for dt in frappe.get_all("DocType", {"is_virtual": 0, "issingle": 0}, pluck="name"): + doctype = frappe.get_meta(dt) + fields = doctype.get("fields", filters={"unique": 1}) + for field in fields: + with self.subTest(f"Checking index {doctype.name} - {field.fieldname}"): + self.check_unique_indexes(doctype.name, field.fieldname) + + def test_unique_index_on_alter(self): + """Only one unique index should be added""" + + doctype = new_doctype(unique=1).insert() + field = "some_fieldname" + + doctype.fields[0].length = 142 + doctype.save() + + doctype.delete() + self.check_unique_indexes(doctype.name, field) + def get_fieldtype_from_def(field_def): fieldtuple = frappe.db.type_map.get(field_def.fieldtype, ("", 0))