Do not include record with NULL field in nested negative clause on None

Since 87456218dcc9, record with NULL field is include in nested negative clause
but this should not applied if the operand is or contains None.

Closes #13911
This commit is contained in:
Cédric Krier
2025-03-09 11:23:43 +01:00
parent 13dec41635
commit 34686ae187
5 changed files with 43 additions and 2 deletions
+1
View File
@@ -40,6 +40,7 @@ by this pattern::
.. note::
Negative operators match records for which any of the field before the
last dot is empty.
Except if the operand is or contains ``None``.
.. warning::
For :class:`trytond.model.fields.Reference`, an extra ending clause is
+4 -1
View File
@@ -280,7 +280,10 @@ class Many2One(Field):
target_table, _ = target_tables[None]
_, expression = Target.search_domain(
target_domain, tables=target_tables)
if operator.startswith('not') or operator == '!=':
if ((operator.startswith('not') and not (
operator == 'not in'
and None in value))
or (operator == '!=' and value is not None)):
expression |= column == Null
return expression
+4 -1
View File
@@ -216,7 +216,10 @@ class Reference(SelectionMixin, Field):
expression = (
self.sql_id(column, Model).in_(query)
& column.like(target + ',%'))
if operator.startswith('not') or operator == '!=':
if ((operator.startswith('not') and not (
operator == 'not in'
and None in value))
or (operator == '!=' and value is not None)):
expression |= column == Null
return expression
@@ -220,6 +220,21 @@ class FieldMany2OneTestCase(TestCase):
])
self.assertListEqual(result, [record])
result = Many2One.search([
('many2one.value', '!=', None),
])
self.assertListEqual(result, [])
result = Many2One.search([
('many2one.value', 'not in', [1]),
])
self.assertListEqual(result, [record])
result = Many2One.search([
('many2one.value', 'not in', [1, None]),
])
self.assertListEqual(result, [])
@with_transaction()
def test_set_instance(self):
"Test set instance"
@@ -375,6 +375,25 @@ class FieldReferenceTestCase(TestCase):
self.assertListEqual(result, [reference])
result = Reference.search([
('reference.name', '!=', None, Target.__name__),
])
self.assertListEqual(result, [])
result = Reference.search([
('reference.name', 'not in', ["Target"], Target.__name__),
])
self.assertListEqual(result, [reference])
result = Reference.search([
('reference.name', 'not in', ["Target", None],
Target.__name__),
])
self.assertListEqual(result, [])
@with_transaction()
def test_write_string(self):
"Test write reference string"