From d3f768fef9b96c91a7a04e2454ca6d94c1236635 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 8 Feb 2022 10:41:20 +0530 Subject: [PATCH 1/5] feat(db/pg): ability to ignore pk colission --- frappe/model/base_document.py | 32 ++++++++++++++++++++++++-------- frappe/model/document.py | 6 +----- frappe/tests/test_db.py | 10 ++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py index 307d95e84b..2f0a9d4943 100644 --- a/frappe/model/base_document.py +++ b/frappe/model/base_document.py @@ -375,12 +375,24 @@ class BaseDocument(object): fieldname = [df.fieldname for df in self.meta.get_table_fields() if df.options==doctype] return fieldname[0] if fieldname else None - def db_insert(self): - """INSERT the document (with valid columns) in the database.""" + def db_insert(self, ignore_if_duplicate=False): + """INSERT the document (with valid columns) in the database. + + args: + ignore_if_duplicate: ignore primary key collision + at database level (postgres) + in python (mariadb) + """ if not self.name: # name will be set by document class in most cases set_new_name(self) + conflict_handler = "" + # On postgres we can't implcitly ignore PK collision + # So instruct pg to ignore `name` field conflicts + if ignore_if_duplicate and frappe.db.db_type == "postgres": + conflict_handler = "on conflict (name) do nothing" + if not self.creation: self.creation = self.modified = now() self.created_by = self.modified_by = frappe.session.user @@ -391,10 +403,11 @@ class BaseDocument(object): columns = list(d) try: frappe.db.sql("""INSERT INTO `tab{doctype}` ({columns}) - VALUES ({values})""".format( - doctype = self.doctype, - columns = ", ".join("`"+c+"`" for c in columns), - values = ", ".join(["%s"] * len(columns)) + VALUES ({values}) {conflict_handler}""".format( + doctype=self.doctype, + columns=", ".join("`"+c+"`" for c in columns), + values=", ".join(["%s"] * len(columns)), + conflict_handler=conflict_handler ), list(d.values())) except Exception as e: if frappe.db.is_primary_key_violation(e): @@ -407,8 +420,11 @@ class BaseDocument(object): self.db_insert() return - frappe.msgprint(_("{0} {1} already exists").format(self.doctype, frappe.bold(self.name)), title=_("Duplicate Name"), indicator="red") - raise frappe.DuplicateEntryError(self.doctype, self.name, e) + if not ignore_if_duplicate: + frappe.msgprint(_("{0} {1} already exists") + .format(self.doctype, frappe.bold(self.name)), + title=_("Duplicate Name"), indicator="red") + raise frappe.DuplicateEntryError(self.doctype, self.name, e) elif frappe.db.is_unique_key_violation(e): # unique constraint diff --git a/frappe/model/document.py b/frappe/model/document.py index f7ba9250fa..85603587cd 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -249,11 +249,7 @@ class Document(BaseDocument): if getattr(self.meta, "issingle", 0): self.update_single(self.get_valid_dict()) else: - try: - self.db_insert() - except frappe.DuplicateEntryError as e: - if not ignore_if_duplicate: - raise e + self.db_insert(ignore_if_duplicate=ignore_if_duplicate) # children for d in self.get_all_children(): diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py index 6e96849b35..bbd09590be 100644 --- a/frappe/tests/test_db.py +++ b/frappe/tests/test_db.py @@ -291,6 +291,16 @@ class TestDB(unittest.TestCase): frappe.db.MAX_WRITES_PER_TRANSACTION = Database.MAX_WRITES_PER_TRANSACTION + def test_pk_collision_ignoring(self): + # note has `name` generated from title + for _ in range(3): + frappe.get_doc(doctype="Note", title="duplicate name").insert(ignore_if_duplicate=True) + + with savepoint(): + self.assertRaises(frappe.DuplicateEntryError, frappe.get_doc(doctype="Note", title="duplicate name").insert) + # recover transaction to continue other tests + raise Exception + @run_only_if(db_type_is.MARIADB) class TestDDLCommandsMaria(unittest.TestCase): From 1439e667b2e5f65b974a36dc4eb5debf138deb75 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 8 Feb 2022 11:04:50 +0530 Subject: [PATCH 2/5] chore: add debug status temporarily --- frappe/database/database.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/database/database.py b/frappe/database/database.py index 9fa1ff161c..c833bdeed3 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -177,6 +177,8 @@ class Database(object): raise frappe.QueryTimeoutError(e) elif frappe.conf.db_type == 'postgres': + # TODO: added temporarily + print(e) raise if ignore_ddl and (self.is_missing_column(e) or self.is_missing_table(e) or self.cant_drop_field_or_key(e)): From 954b932c10f5448810a33b447468522777ad3084 Mon Sep 17 00:00:00 2001 From: Wolfram Schmidt Date: Mon, 14 Feb 2022 11:48:17 +0100 Subject: [PATCH 3/5] added menu translations (#15879) added menu translations when navigating over avater --- frappe/translations/de.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/translations/de.csv b/frappe/translations/de.csv index f682a51e17..4a856131ab 100644 --- a/frappe/translations/de.csv +++ b/frappe/translations/de.csv @@ -148,6 +148,8 @@ More Information,Mehr Informationen, More...,Mehr..., Move,Bewegen, My Account,Mein Konto, +My Profile,Mein Profil, +My Settings,Meine Einstellungen, New Address,Neue Adresse, New Contact,Neuer Kontakt, Next,Weiter, From 16ef2d3b135718a30f1bc9df2116f71cc0e0b279 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Mon, 14 Feb 2022 17:48:20 +0530 Subject: [PATCH 4/5] ci(Mergify): Configuration update (#15968) --- .mergify.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 0bd9641d5b..63fe1a0086 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -48,3 +48,7 @@ pull_request_rules: actions: merge: method: squash + commit_message_template: | + {{ title }} (#{{ number }}) + + {{ body }} From 8995bbb8339561b4663734eba3970c7195aac701 Mon Sep 17 00:00:00 2001 From: Wolfram Schmidt Date: Mon, 14 Feb 2022 13:25:27 +0100 Subject: [PATCH 5/5] fix: Update translations (#15886) For better understanding on what this does. For "Submit" the german word "Buchen" or "gebucht" ist used mostly in the system. ![grafik](https://user-images.githubusercontent.com/22279621/152641036-ee89f81d-4a10-4686-8f67-646af6a8087f.png) --- frappe/translations/de.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/translations/de.csv b/frappe/translations/de.csv index 4a856131ab..17151a14eb 100644 --- a/frappe/translations/de.csv +++ b/frappe/translations/de.csv @@ -408,7 +408,7 @@ Allow Self Approval,Erlaube Selbstgenehmigung, Allow approval for creator of the document,Genehmigung für den Ersteller des Dokuments zulassen, Allow events in timeline,Ereignisse in der Zeitleiste zulassen, Allow in Quick Entry,In Schnelleingabe zulassen, -Allow on Submit,Beim Übertragen zulassen, +Allow on Submit,Änderungen zulassen wenn gebucht, Allow only one session per user,Nur eine Sitzung pro Benutzer zulassen, Allow page break inside tables,Seitenumbruch innerhalb von Tabellen erlauben, Allow saving if mandatory fields are not filled,Speichern trotz leerer Pflichtfelder zulassen,