feat: Enhance IN/NOT IN operator handling for empty lists
Added logic to return appropriate criteria for empty lists in IN and NOT IN operators. An empty list with IN now returns 0 results (1=0), while NOT IN returns all results (1=1). Updated tests to verify this behavior.
This commit is contained in:
parent
9b84264fa5
commit
c6868b11c6
3 changed files with 34 additions and 1 deletions
|
|
@ -579,6 +579,20 @@ class Engine:
|
|||
v.strip().strip("'") for v in get_between_date_filter(_value, df).split(" AND ")
|
||||
)
|
||||
|
||||
# Handle empty lists for IN/NOT IN operators before conversion
|
||||
# IN with empty list should return 0 results (always False)
|
||||
# NOT IN with empty list should return all results (always True)
|
||||
if _operator.lower() in ("in", "not in"):
|
||||
if isinstance(_value, (list, tuple, set)) and len(_value) == 0:
|
||||
if _operator.lower() == "in":
|
||||
# Return a criterion that always evaluates to False (1=0)
|
||||
# This ensures IN with empty list returns 0 results
|
||||
return RawCriterion("1=0")
|
||||
else: # not in
|
||||
# Return a criterion that always evaluates to True (1=1)
|
||||
# NOT IN with empty set matches all rows since nothing is excluded
|
||||
return RawCriterion("1=1")
|
||||
|
||||
if not _value and isinstance(_value, list | tuple | set):
|
||||
_value = ("",)
|
||||
|
||||
|
|
|
|||
|
|
@ -868,6 +868,15 @@ from {tables}
|
|||
if f.operator.lower() == "in":
|
||||
can_be_null &= not f.value or any(v is None or v == "" for v in f.value)
|
||||
|
||||
# Handle empty lists for IN/NOT IN operators before processing
|
||||
# IN with empty list should return 0 results (always False: 1=0)
|
||||
# NOT IN with empty list should return all results (always True: 1=1)
|
||||
if isinstance(f.value, (list, tuple)) and len(f.value) == 0:
|
||||
if f.operator.lower() == "in":
|
||||
return "1=0"
|
||||
else: # not in
|
||||
return "1=1"
|
||||
|
||||
if value is None:
|
||||
values = f.value or ""
|
||||
if isinstance(values, str):
|
||||
|
|
|
|||
|
|
@ -410,12 +410,22 @@ class TestQuery(IntegrationTestCase):
|
|||
"SELECT `name` FROM `tabDocType` WHERE `name` IN ('ToDo','Note')",
|
||||
)
|
||||
|
||||
# Empty list with IN operator should return 0 results (1=0 condition)
|
||||
self.assertQueryEqual(
|
||||
frappe.qb.get_query(
|
||||
"DocType",
|
||||
filters={"name": ("in", [])},
|
||||
).get_sql(),
|
||||
"SELECT `name` FROM `tabDocType` WHERE `name` IN ('')",
|
||||
"SELECT `name` FROM `tabDocType` WHERE 1=0",
|
||||
)
|
||||
|
||||
# Empty list with NOT IN operator should return all results (1=1 condition)
|
||||
self.assertQueryEqual(
|
||||
frappe.qb.get_query(
|
||||
"DocType",
|
||||
filters={"name": ("not in", [])},
|
||||
).get_sql(),
|
||||
"SELECT `name` FROM `tabDocType` WHERE 1=1",
|
||||
)
|
||||
|
||||
self.assertQueryEqual(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue