Merge pull request #22114 from gavindsouza/doc-bulk_insert-include_child

fix: Handle child record insertions via bulk_insert
This commit is contained in:
mergify[bot] 2023-08-25 13:57:38 +00:00 committed by GitHub
commit fdcfb82f47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 13 deletions

View file

@ -1643,12 +1643,32 @@ def bulk_insert(
- Documents can be any iterable / generator containing Document objects
"""
columns = frappe.get_meta(doctype).get_valid_columns()
values = _document_values_generator(documents, columns)
doctype_meta = frappe.get_meta(doctype)
documents = list(documents)
frappe.db.bulk_insert(
doctype, columns, values, ignore_duplicates=ignore_duplicates, chunk_size=chunk_size
)
valid_column_map = {
doctype: doctype_meta.get_valid_columns(),
}
values_map = {
doctype: _document_values_generator(documents, valid_column_map[doctype]),
}
for child_table in doctype_meta.get_table_fields():
valid_column_map[child_table.options] = frappe.get_meta(child_table.options).get_valid_columns()
values_map[child_table.options] = _document_values_generator(
(
ch_doc
for ch_doc in (
child_docs for doc in documents for child_docs in doc.get(child_table.fieldname)
)
),
valid_column_map[child_table.options],
)
for dt, docs in values_map.items():
frappe.db.bulk_insert(
dt, valid_column_map[dt], docs, ignore_duplicates=ignore_duplicates, chunk_size=chunk_size
)
def _document_values_generator(

View file

@ -521,17 +521,34 @@ class TestDocumentWebView(FrappeTestCase):
def test_bulk_inserts(self):
from frappe.model.document import bulk_insert
doctype = "ToDo"
sent_todo = set()
doctype = "Role Profile"
child_field = "roles"
child_doctype = frappe.get_meta(doctype).get_field(child_field).options
sent_docs = set()
sent_child_docs = set()
def doc_generator():
for i in range(690):
for _ in range(21):
doc = frappe.new_doc(doctype)
doc.name = doc.description = frappe.generate_hash()
sent_todo.add(doc.name)
doc.role_profile = frappe.generate_hash()
doc.append("roles", {"role": "System Manager"})
doc.set_new_name()
doc.set_parent_in_children()
sent_docs.add(doc.name)
sent_child_docs.add(doc.roles[0].name)
yield doc
bulk_insert(doctype, doc_generator(), chunk_size=100)
bulk_insert(doctype, doc_generator(), chunk_size=5)
all_todos = set(frappe.get_all("ToDo", pluck="name"))
self.assertEqual(sent_todo - all_todos, set(), "All docs should be inserted")
all_docs = set(frappe.get_all(doctype, pluck="name"))
all_child_docs = set(
frappe.get_all(
child_doctype, filters={"parenttype": doctype, "parentfield": child_field}, pluck="name"
)
)
self.assertEqual(sent_docs - all_docs, set(), "All docs should be inserted")
self.assertEqual(sent_child_docs - all_child_docs, set(), "All child docs should be inserted")