|
4 | 4 |
|
5 | 5 | import frappe |
6 | 6 | from frappe.core.doctype.doctype.test_doctype import new_doctype |
| 7 | +from frappe.database.operator_map import func_in |
7 | 8 | from frappe.query_builder import Case |
8 | 9 | from frappe.query_builder.builder import Function |
9 | 10 | from frappe.query_builder.custom import ConstantColumn |
@@ -503,3 +504,67 @@ def test_union(self): |
503 | 504 | roles = frappe.qb.from_(role).select(role.name) |
504 | 505 |
|
505 | 506 | self.assertEqual(set(users.run() + roles.run()), set((users + roles).run())) |
| 507 | + |
| 508 | + |
| 509 | +class TestOperatorIn(IntegrationTestCase): |
| 510 | + def test_func_in_without_empty_values(self): |
| 511 | + note = frappe.qb.DocType("Note") |
| 512 | + query = func_in(note.name, ["n1", "n2", "n3"]) |
| 513 | + sql_str = str(query).lower() |
| 514 | + |
| 515 | + self.assertIn("in", sql_str) |
| 516 | + self.assertNotIn("coalesce", sql_str) |
| 517 | + |
| 518 | + def test_func_in_with_none_converts_to_empty_string(self): |
| 519 | + note = frappe.qb.DocType("Note") |
| 520 | + query = func_in(note.name, [None, "user1"]) |
| 521 | + sql_str = str(query).lower() |
| 522 | + |
| 523 | + self.assertIn("coalesce", sql_str) |
| 524 | + self.assertIn("''", sql_str) |
| 525 | + |
| 526 | + def test_func_in_with_empty_string_uses_coalesce(self): |
| 527 | + note = frappe.qb.DocType("Note") |
| 528 | + query = func_in(note.name, ["", "user1"]) |
| 529 | + sql_str = str(query).lower() |
| 530 | + |
| 531 | + self.assertIn("coalesce", sql_str) |
| 532 | + self.assertIn("''", sql_str) |
| 533 | + |
| 534 | + def test_func_in_with_mixed_none_and_values(self): |
| 535 | + note = frappe.qb.DocType("Note") |
| 536 | + query = func_in(note.name, ["val1", None, "val2"]) |
| 537 | + sql_str = str(query).lower() |
| 538 | + |
| 539 | + self.assertIn("coalesce", sql_str) |
| 540 | + |
| 541 | + def test_in_filter_matches_null_and_empty_columns(self): |
| 542 | + test_doctype = new_doctype( |
| 543 | + fields=[ |
| 544 | + { |
| 545 | + "fieldname": "test_field", |
| 546 | + "fieldtype": "Data", |
| 547 | + "label": "Test Field", |
| 548 | + }, |
| 549 | + ], |
| 550 | + ) |
| 551 | + test_doctype.insert() |
| 552 | + self.test_doctype_name = test_doctype.name |
| 553 | + self.addCleanup(frappe.delete_doc, "DocType", self.test_doctype_name) |
| 554 | + |
| 555 | + doc_null = frappe.get_doc({"doctype": self.test_doctype_name, "test_field": None}) |
| 556 | + doc_null.insert() |
| 557 | + doc_empty = frappe.get_doc({"doctype": self.test_doctype_name, "test_field": ""}) |
| 558 | + doc_empty.insert() |
| 559 | + doc_user = frappe.get_doc({"doctype": self.test_doctype_name, "test_field": "user1"}) |
| 560 | + doc_user.insert() |
| 561 | + |
| 562 | + results = frappe.get_all( |
| 563 | + self.test_doctype_name, |
| 564 | + filters={"test_field": ["in", [None, "user1"]]}, |
| 565 | + pluck="test_field", |
| 566 | + ) |
| 567 | + |
| 568 | + self.assertIn(None, results) |
| 569 | + self.assertIn("", results) |
| 570 | + self.assertIn("user1", results) |
0 commit comments