summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfw-bot <otis@odoo.com>2019-10-31 20:09:23 +0000
committerfw-bot <otis@odoo.com>2019-11-04 08:16:40 +0000
commit5e6e2184f55b51c1f55374570604dbeb9c601184 (patch)
tree7da8d2fa57ca1d5bceaa35268d6b8b88695a433b
parentbaba6be668d96d26ef2890617246cb4a6aa82f75 (diff)
[FIX] core: is_false has lots of false negatives over RPC
`is_false` relies on no small part on equality tests between the input triplets and either `TRUE_LEAF` or `FALSE_LEAF`. While these are defined as tuples, RPC domains will always be lists (as neither XML-RPC nor JSON have tuples, and their arrays deserialize to Python lists). This is an issue, because tuple and list never compare equal. As a result, while the in / not in predicates can succeed, the TRUE_LEAF / FALSE_LEAF never will, and thus domains which contain either and might shortcut (avoid a query entirely) will always go through the entire process. Fix by having domain normalization also ensure all triplets are tuples: that's the first thing `is_false` does, it should never cause issues and could fix / improve / shortcut other routines. Note: Also implements TRUE_LEAF and FALSE_LEAF handling in the SSF's modifiers evaluator. And fixes the ValueError to work correctly if it breaks on a tuple / dict. closes odoo/odoo#39706 X-original-commit: a44f008b918ee66742f7e943b00e4ee3d7fe2b78 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
-rw-r--r--odoo/osv/expression.py3
-rw-r--r--odoo/tests/common.py12
2 files changed, 11 insertions, 4 deletions
diff --git a/odoo/osv/expression.py b/odoo/osv/expression.py
index 38d503af0f9..221fd0ba6c9 100644
--- a/odoo/osv/expression.py
+++ b/odoo/osv/expression.py
@@ -199,11 +199,12 @@ def normalize_domain(domain):
if expected == 0: # more than expected, like in [A, B]
result[0:0] = [AND_OPERATOR] # put an extra '&' in front
expected = 1
- result.append(token)
if isinstance(token, (list, tuple)): # domain term
expected -= 1
+ token = tuple(token)
else:
expected += op_arity.get(token, 0) - 1
+ result.append(token)
assert expected == 0, 'This domain is syntactically not correct: %s' % (domain)
return result
diff --git a/odoo/tests/common.py b/odoo/tests/common.py
index 67cabbb4f10..3a58a4d44c8 100644
--- a/odoo/tests/common.py
+++ b/odoo/tests/common.py
@@ -33,7 +33,7 @@ from decorator import decorator
from lxml import etree, html
from odoo.models import BaseModel
-from odoo.osv.expression import normalize_domain
+from odoo.osv.expression import normalize_domain, TRUE_LEAF, FALSE_LEAF
from odoo.tools import float_compare, single_email_re
from odoo.tools.misc import find_in_path
from odoo.tools.safe_eval import safe_eval
@@ -1428,7 +1428,13 @@ class Form(object):
e1 = stack.pop()
e2 = stack.pop()
stack.append(e1 or e2)
- elif isinstance(it, list):
+ elif isinstance(it, tuple):
+ if it == TRUE_LEAF:
+ stack.append(True)
+ continue
+ elif it == FALSE_LEAF:
+ stack.append(False)
+ continue
f, op, val = it
# hack-ish handling of parent.<field> modifiers
f, n = re.subn(r'^parent\.', '', f, 1)
@@ -1452,7 +1458,7 @@ class Form(object):
stack.append(self._OPS[op](field_val, val))
else:
- raise ValueError("Unknown domain element %s" % it)
+ raise ValueError("Unknown domain element %s" % [it])
[result] = stack
return result
_OPS = {