summaryrefslogtreecommitdiff
path: root/odoo/osv
AgeCommit message (Collapse)Author
2021-05-12[FIX] expression: Better Binaries logsJérôme Vanhaudenard
When building a domain `(=|!=)` with a Binary field stored in attachment and the right part of the domain is not null, the full binary content is logged, giving the logs a huge size. Now, the content of the binary is cropped to 20 chars as it is useless to log more. opw-2527629 closes odoo/odoo#70699 X-original-commit: d54b30bb7feed52de86f4302dc4a01f2d4009782 Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com> Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2021-04-01[FIX] core/expression: fix distribute_not over thruty leafsAlvaro Fuentes
A domain with a negated thruty leaf raises an exception here https://github.com/odoo/odoo/blob/835197e48fbbee1c8ac35d52287537fa6f0bdd36/odoo/osv/expression.py#L614 due to https://github.com/odoo/odoo/blob/835197e48fbbee1c8ac35d52287537fa6f0bdd36/odoo/osv/expression.py#L670 and the fact that `FALSE_LEAF != (1, "!=", 1)` and `TRUE_LEAF != (0, "!=", 1)` Current wrong behaviour: ``` >>> distribute_not(['!', TRUE_LEAF]) [(1, '!=', 1)] >>> is_leaf((1, '!=', 1)) False ``` This issue was noticed when adapting domains for fields that have been removed during migration. Example (extract of) traceback: ``` Traceback (most recent call last): File "/home/odoo/src/odoo/13.0/odoo/http.py", line 624, in _handle_exception return super(JsonRequest, self)._handle_exception(exception) ... File "/home/odoo/src/odoo/13.0/odoo/osv/expression.py", line 677, in __init__ self.parse() File "/home/odoo/src/odoo/13.0/odoo/osv/expression.py", line 814, in parse self.stack = [ExtendedLeaf(leaf, self.root_model) for leaf in self.expression] File "/home/odoo/src/odoo/13.0/odoo/osv/expression.py", line 814, in <listcomp> self.stack = [ExtendedLeaf(leaf, self.root_model) for leaf in self.expression] File "/home/odoo/src/odoo/13.0/odoo/osv/expression.py", line 562, in __init__ self.check_leaf(internal) File "/home/odoo/src/odoo/13.0/odoo/osv/expression.py", line 618, in check_leaf raise ValueError("Invalid leaf %s" % str(self.leaf)) ValueError: Invalid leaf (0, '!=', 1) ``` closes odoo/odoo#68657 X-original-commit: e20c23658d15a135e5f35b0e8dec6e3202cecaab Signed-off-by: Christophe Simonis <chs@odoo.com>
2020-10-07[FIX] base: fix exception retro-compatibility-aidJulien Castiaux
Restore the old signature of except_orm. opw-2354525 opw-2355980 closes odoo/odoo#59443 Signed-off-by: Toufik Benjaa (tbe) <tbe@odoo.com>
2020-09-17[FIX] core: flush() domain returned by search methodRaphael Collet
Assume field B depends on A, and searching on B is rewritten as a domain that mentions A. If A is modified, and then we search on B, one has to flush A to the database before searching. closes odoo/odoo#57958 X-original-commit: b242b7b1382ee39ebefa58c556931b7dae77f669 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-09-17[FIX] core: use shortened table aliasing in get_join_conditions()Alex Hafner
Current behavior: Auto-generated SQL fails with ERROR: missing FROM-clause entry for table when table alias names exceed the target length of 63 characters. This is because odoo.osv.expression.py handles shortening the table name alias in generate_table_alias, but not in get_join_conditions. In the resulting SQL, shortened aliases are used in the FROM clause, whereas in the join conditions, the full alias is used, which is both exceeding the Postgres limit and not matching the table name alias in the FROM clause. Expected behavior: auto-generated SQL runs without errors. Implementation of fix: - refactor alias shortening into new function _shorten_alias to make it reusable - Use _shorten_alias in both generate_table_alias and get_join_conditions closes odoo/odoo#57909 X-original-commit: 9570f5ff4694a58035094ad52b4773433dbd018c Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-08-20[IMP] core: add models defined by a query instead of a table/viewwan
By adding a parameter `_table_query` on the Model, we can now have views that depend on the context. The query is used instead of the table name in ORM operations. This allows to pre-compute some values to improve performance, instead of storing context values in the database. Co-authored-by: william-andre <wan@odoo.com> Co-authored-by: rco-odoo <rco@odoo.com>
2020-08-18[IMP] core: introduce subqueries in searchRaphael Collet
Make the method `_search` return a `Query` object, and make that object generate a subquery when used on the right-hand side of a condition. closes odoo/odoo#52403 Related: odoo/enterprise#10945 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-08-18[REF] core: improve the API and implementation of QueryRaphael Collet
Introduce better methods for introducing tables, join clauses and where clauses to the Query object, and other methods to generate a complete SELECT query. The Query object can also behave as a tuple of ids, where the query is made on demand, and the result is memoized.
2020-08-18[IMP] core: use _search() and _name_search() for sub-searchesRaphael Collet
This avoids the formatting part of those methods (`browse` in the case of `search`, `display_name` in the case of `name_search`), which is useless in most cases. This also enables further optimizations where `_search` and `_name_search` return subqueries instead of record ids.
2020-08-18[IMP] core: inline SELECT many2one as subquery for one2many fieldsRaphael Collet
This avoids the standalone query with a SELECT DISTINCT, which is costly to execute, and enables potential optimizations in the query execution.
2020-08-03[FIX] odoo: one2many fields queries with res_id are narrowed by res_modeljerome hanke (jhk)
Steps to reproduce: - install helpdesk, hr_expense (the demo data has a clear example of the bug) - go to helpdesk > tickets > set a custom filter > "activities is set" Previous behavior: the results show the ticket with id=2 as if it had an activity set. Because the search sql query collides with other activities set on other models (hr.expense.sheet in this example) Current behavior: the sql query returns the proper result opw-2273680 closes odoo/odoo#55297 X-original-commit: 6e90c41413f6a726c08071c71d01c738a6538079 Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
2020-07-14[FIX] core: search on boolean field with operator `in`Raphael Collet
closes odoo/odoo#54457 X-original-commit: 363533b7d50448c06cef2baa68d6f4f634346252 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-06-25[FIX] expression: simplify sub-searches orderGuewen Baconnier
Performance fix: when parsing domains using special operators (`child_of`, ...), or with dotted field on the left value (`['partner_id.name', ...]`), the ORM starts by a first call on `search()` and builds a new domain so the final query has "IN (<ids found by sub-search>)". The sub-search issued on the comodel uses the default "order by". The order of the ids is irrelevant here, we only need to know the ids. A good example is when the sub-search happens on `product.product`, which is ordered by `default_code, name, id`. The field `name` is inherited and translated, so the ordering requires a JOIN on `product_template` and a LEFT JOIN on `ir_translation`. Ordering by `id` avoids these 2 JOINs. Some discussion took place about modifying `_generate_order_by()` to remove the `ORDER BY` clause when the `order` argument is False or ''. Apart the fact that it would be a breaking change, @odony has shown that sorting by `id` is so cheap that removing the `ORDER BY` might not bring significant performance boost [0]. [0] https://github.com/odoo/odoo/pull/52368#issuecomment-646643773 opw-2270690 closes odoo/odoo#53629 X-original-commit: fc91f7b4e8f9f8a95862df1ce95a9639cf7d1363 Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com> Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-05-20[FIX] core: searching through o2m with auto_joinXavier Morel
Replaces the auto_join scheme which is pretty fast but doesn't quite work (it's *completely* broken for read_group) by a subquery which is slower but has the same semantics as the ORM version. Ideally we'd use `EXISTS (select 1 from ...)` but that has no support inside the SQL compiler right now, so use `id in (select inverse_field from ...)`. Here are some measures of a `read_group` on a simple object with lines filtered on line values, similar to read_group([('order_line.product_uom', '=', xxx)], fields=['total_amount'], groupby=['user_id']) +-------+-------+-------+--------+ | | ORM | join |subquery| +-------+-------+-------+--------+ | large | 160 | 10 | 20 | +-------+-------+-------+--------+ | many | 36000 | 50 | 180 | +-------+-------+-------+--------+ * values of data fields (filtering, grouping and aggregating) randomly picked between 10 different values * "large" is 1000 objects with 1000~15000 lines each * "many" is 1000000 objects with 1~40 lines each closes odoo/odoo#48494 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-05-20[REF] core: avoid query.tables and replacements in query stringsRaphael Collet
Instead of merging Query objects (main domain and access rules domains), which requires renaming aliases in query strings, make `expression` push its result in an existing Query object. This removes tricky code. This also avoids using `IrRule.domain_get()`, which has become unsafe, since it returns a list of tables (for the FROM clause) which does not include the joins from the generated Query object. closes odoo/odoo#49999 Related: odoo/enterprise#10126 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-05-20[REF] expression: search on translated fieldsRaphael Collet
Use a LEFT JOIN on table `ir_translation` instead of a subquery, by using the same implementation as the one used for ordering by a translated field. In particular, this avoids having both the LEFT JOIN and subquery when searching and sorting on a given translated field.
2020-05-20[FIX] expression: auto_join now uses LEFT JOINRaphael Collet
This fixes some cases where search results are actually missing. For instance, searching with a domain like ['|', ('parent_id.name', '=', 'foo'), ('name', 'like', 'foo')] where `parent_id` is auto-joined, misses results where `parent_id` is NULL, because the actual query makes cartesian products for auto-joins: SELECT "res_partner".id FROM "res_partner", "res_partner" AS "res_partner__parent_id" WHERE ("res_partner"."parent_id" = "res_partner__parent_id"."id") AND ("res_partner__parent_id"."name" = 'foo' OR "res_partner"."name" == 'foo') Using LEFT JOIN instead of cartesian product above, the query includes all results where `parent_id` is NULL: SELECT "res_partner".id FROM "res_partner" LEFT JOIN "res_partner" AS "res_partner__parent_id" ON ("res_partner"."parent_id" = "res_partner__parent_id"."id") WHERE ("res_partner__parent_id"."name" = 'foo' OR "res_partner"."name" == 'foo')
2020-05-20[REF] expression: use and return a Query objectRaphael Collet
The management of the join contexts now relies on the `Query` object, that has all the necessary logic to do so. The refactoring also removes the class `ExtendedLeaf`, which is no longer necessary: the join contexts are all managed by a single `Query` object, and the parsing stack now only contains triples like (leaf, model, table_alias). Also inline directly the SQL translation made in `_to_sql`, which overall simplifies the management of SQL parameters in the domain compilation. The algorithm is illustrated in the code itself.
2020-05-20[IMP] core: better tests on queries made by searchRaphael Collet
2020-05-14[REV] base: restore removed deprecated osv and exceptionsJulien Castiaux
To ensure backward compatibility, stuff removed by ab4000fb3 have been restored. closes odoo/odoo#49603 Task: 2234749 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-04-22[FIX] *: collection.<ABC> is deprecatedXavier Morel
2020-04-08[REF] base: Remove deprecated exceptions and osvJulien Castiaux
TL;DR: remember `osv` and `except_orm` ? You can forget about them. * Deprecated `except_orm` dropped. * `UserError` elevated as super type of all user-related errors. * Unused `DeferredException` dropped. * Unused `QWebException` dropped (real one is in `qweb.py`). * `MailDeliveryException` made a python exception. * `name` legacy exception attribute made an alias of the python standard `args[0]` attribute and deprecated. * `value` legacy exception attribute dropped. * `exception_type` RPC error response key dropped. * Deprecated `osv` module dropped. * `--osv-memory-age-limit` cli option made an alias of `--transient-age-limit` and deprecated. The `odoo.exceptions.Warning` have long been a deprecated alias to `UserError`. It is going to be removed in a future version but first we explicitly deprecate it with a warning. The `odoo.exceptions.DeferredException` was a very old internal exception, it has been removed without deprecation notice as it is never raised. The `odoo.exceptions.except_orm` has been a deprecated exception type with deprecation warning for 5 years, it has been removed in favor of UserError which becomes the super class of all user-related errors. The `odoo.base.models.ir_mail_server.MailDeliveryException` was inheriting `except_orm`. As it is not related to a user error but is more of a problem an admin much take care of, the exception has been made a Python error. The `exception_type` JSON key in RPC error responses was holding an hardcoded value derived from the exception type. Its usage has been dropped in favor of the `name` JSON key that holds the precise exception name. Again as it was hardly used in the source code (beside the crash manager) it has been dropped without deprecation warning. Since we are here trying to clean odoo custom exceptions, we are also deprecating the `name` exception attribute in favor of the more standard `args[0]` attribute. The `name` (along with `value`) were two attributes used to raise `except_orm` exceptions before the introduction of `UserError`, `AccessError` and related exceptions. The `name` attribute, at the time, was holding the exception type/title. Nowadays it contains the error message. The `value` attribute, at the time, was holding the error message. Nowadays it is no more used. The `osv` module contains very old deprecated aliases. There is no simple way to log a deprecation warning for osv, osv_memory and osv_abstract but as they have not been in use for ages, they have been removed too. To be consistent, the `--osv-memory-age-limit` cli option has been made a deprecated alias to the `--transient-age-limit`. closes odoo/odoo#45723 Task: 2187728 Related: odoo/enterprise#9162 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-03-17[FIX] expression: 'select from not null' as subquery for x2manyRomain Derie
Before this commit, the query to fetch records with/without relations would be done in a separate query which results would be then passed to the main query. This commit adds this query as a subquery of the main query to do it in the same SQL query instead of separately. task-2211013 closes odoo/odoo#47729 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com> Signed-off-by: Romain Derie <rdeodoo@users.noreply.github.com>
2020-01-21[FIX] core: search on one2many fields with contextRaphael Collet
Consider an x2many field `foo_ids` with `context={'active_test': False}` in its definition, and a comodel with an active field. The value of the field includes inactive records. Now consider a search with a domain like `[('foo_ids.bar', op, value)]`. The search should return all the records with corecords that satisfy the domain `[('bar', op, value)]`, including inactive corecords, because the field's context explicitly disables filtering on the active field. closes odoo/odoo#43625 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2020-01-20[FIX] expression: performance of search on one2many fieldsRaphael Collet
We optimize the search on domains like `[('line_ids', 'in', ids)]`. The condition is rewritten `('id', 'in', ids1)` where `ids1` is the result of SELECT <many2one_field> FROM <comodel_table> WHERE id IN <ids> The issue is that the latter potentially returns many duplicate values. The fix consists in having as few duplicates as possible in `ids1`. Note that domains like `[('line_ids.foo', '=', 42)]` implicitly benefit from the optimization, as they are rewritten as the one above with ids = comodel.search([('foo', '=', 42)]).ids closes odoo/odoo#43574 X-original-commit: a13c05fa5df9c98504e8e1cdb09d8d4a8d13ea91 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2019-12-19[FIX] expression.py: avoid using TRUE_DOMAIN/FALSE_DOMAINNicolas Lempereur
Ensure that expression.OR and expression.AND and some other expression.py methods do not propagate or rely on TRUE_DOMAIN and FALSE_DOMAIN that may be muted on some instance. For example, if we did: self.search(expression.OR([])) then in the search method we do something like: received_domain.append(('res_field', '=', False)) before this commit, FALSE_DOMAIN would be altered for any succeeding code that try to use it in `[(0, '=', 1), ('res_field', '=', 'False')]`. Without the changeset, the added test would fail with: [(1, '=', 1), ('id', '=', 1)] != [(1, '=', 1)] [(0, '=', 1), ('id', '=', 1)] != [(0, '=', 1)] [(0, '=', 1), ('id', '=', 1)] != [(0, '=', 1)] [(1, '=', 1), ('id', '=', 1)] != [(1, '=', 1)] [(1, '=', 1), ('id', '=', 1)] != [(1, '=', 1)] note: another commit referenced in #41968 should make the TRUE_DOMAIN and FALSE_DOMAIN immutable. related to work on opw-2154448 closes #42107 closes odoo/odoo#42222 X-original-commit: 303ce32e6ccd7432b96ffae545e4a6eced68ae84 Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
2019-12-06[FIX] expression: use of `child_of` with `many2many`Nicolas Martinelli
- Go to Contacts - Search by 'Tag' with a non existing tag A crash occurs. This is because of an incorrect SQL: `WHERE "category_id" IN ()` In case of an empty list `ids2`, we fall back on `(None,)` Note that it appears only in v13 because `child_of` was added at [1], but the issue also exists in v12. [1] https://github.com/odoo/odoo/blob/b6325ae45b830a725f6ab6706b70f65c809be4a7/odoo/addons/base/views/res_partner_views.xml#L471 opw-2151129 closes odoo/odoo#41479 X-original-commit: 6372fba2cb93c92c41a6a55ede56a39dfc43f701 Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
2019-11-04[FIX] core: is_false has lots of false negatives over RPCfw-bot
`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>
2019-10-01[FIX] *: remove en_US as fallback for lang codewan
en_US may not be activated as it is possible to create a database in another language using the database manager. When trying to install a chart of account, the tax return entry tried to format a date at the installation of the module, with no lang in the context. The fallback was made on en_US but an error is raised if that language is not activated. As it is a very common scenario to retrieve a language from the context, add a generic tool method to do it. Replace and closes odoo/odoo#37629 closes odoo/odoo#37568 Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2019-08-07[IMP] *: fix typos in commentsmreficent
closes odoo/odoo#35404 Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2019-07-26[MOV] core: put things where they belongAdrian Torres
This commit moves some ir_ui_view specific functions into ir_ui_view.py and removes some old-api <-> new-api compatibility shims as well as removes orm.py since it has 0 to do with the Odoo ORM. closes odoo/odoo#34826 Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2019-07-04[ADD] api: flag `su` on environmentsRaphael Collet
The flag defines a "superuser mode" on environments, which allows to bypass access rights without changing the current user id.
2019-06-07[FIX] core: != / not ilike failing to match null recordsXavier Morel
As odoo makes little difference, one would expect `(field, !=, 'foo')` or `(field, 'not ilike', 'foo')` to have the same behaviour when field is empty, and provide the opposite result as the "positive" operators. However because NULL <OP> <value> returns NULL which is generally assimilated to false, the sections above would fail to match records whose field is null (they would match records whose field is *empty* though). Fix this by wrapping the operation in a coalesce falling back to (hopefully) the correct value if the result is null. See also: odoo/odoo#22879 closes odoo/odoo#33959 Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
2019-06-03[IMP] fields: add method to get a usable domain from a fieldRaphael Collet
closes odoo/odoo#33816 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2019-03-08[MERGE] forward port branch 12.0 up to c023d0784f2Christophe Simonis
2019-01-31[MERGE] forward port branch 12.0 up to cb8fefa8999Christophe Simonis
2018-12-20[FIX] osv: fix combination of unit domainlen-odoo
Combining a list of elements containing only the monoid's unit should return the unit. Since the unit is skipped, it would return an empty domain instead of the unit, meaning that (0, '=', 1) could not be used in a group rule. To test this, create a record rule on a model M with domain (0, '=', 1) that applies to group G. Log in with a user in group G and access model M; you can read everything (provided no other record rule applies) whereas you should see nothing. Because of expression.AND(global_domains + [expression.OR(group_domains)]) we want the empty domain to still be left untouched, even if it violates the OR's unit rules (i.e. OR(empty, OR(R)) = OR(R) <=> OR(empty) = unit). Meaning that no group rule would reduce to having a (0, '=' 1) group rule. So in the end we don't really care about all that algebraic nonsense. closes odoo/odoo#28765
2018-11-29[REF] *: replace deprecated pycompat helpers for builtinsAdrian Torres
This commit replaces calls to pycompat helpers that were intended for python 2 <-> python 3 interoperability for python 3 builtins, as python 2 is no longer officially supported by Odoo. This includes: * calls to imap/izip/ifilter replaced by map/zip/filter * uses of text_type replaced by str * uses of unichr replaced by chr * calls to implements_to_string, implements_iterator removed * string_types and integer_types replaced by str, int respectively * calls to to_native replaced by calls to to_text This is done in preparation to the removal of these deprecated helpers in the following commit.
2019-03-06[MERGE] forward port branch saas-11.3 up to 3e54704e669Christophe Simonis
2019-03-05[MERGE] forward port branch 11.0 up to 27081bf6f5fChristophe Simonis
2019-03-04[MERGE] forward port branch saas-15 up to 1f1fa35c072Christophe Simonis
2019-02-20[FIX] expression: properly handle {TRUE,FALSE}_LEAFAdrian Torres
Before this commit, doing expression.OR() with only FALSE_LEAF would yield [] which is equivalent to TRUE_LEAF and is therefore not correct. The same happened (to a lesser extent) with expression.AND() within an expression.OR(), since the former would return a [] which would be ignored by expression.OR(). See tests for a clearer view of the use cases. Fixes #30113, #26540 closes odoo/odoo#31202
2018-08-06[REF] *: use native date/datetime for Date/Datetime fieldsRaphael Collet
From this commit onwards, Date fields will return datetime.date objects and Datetime fields will return datetime.datetime objects, this implies a number of things that are clearly explained both in the ORM API for master. This commit also introduces a number of helper functions for dates and datetimes that are exposed in tools.date_utils and fields.Date[time], explained in the documentation as well. Task-ID: 47189
2018-06-04[FIX] expression: interpret `(X, 'child_of', False)` as falsePierre Masereel
Interpret such domains that do not really make sense as falsy, and log a warning when it occurs.
2018-04-06[FIX] osv.expression: normalize domains in combineAdrian Torres
Before this rev: * Take 2 domains that contain at least two leaves, and at least one of them must use the implicit `&` operator e.g.: d1 = [('so_line', 'in', [91]), ('amount', '<=', 0.0)] d2 = ['&', ('so_line', 'in', []), ('project_id', '!=', False)] * Perform osv.expression.OR() between both domains Expected result: d3 = ['|', d1, d2] Actual result (after normalization): d3 = ['&', '|', d1, d2] This is because, since the `&` is implicit for the first domain, when we OR it, we give it an explicit `|` operator, so when we pass this domain through the normalize_domain function, d1 no longer contains an implicit `&` operator but instead the implicit operator is the one between d1 and d2, therefore giving us a completely wrong domain. The `combine` function states that it only accepts normalized domains, however neither the OR nor AND functions do, this leads to a lot of developers putting non-normalized domains into these functions, and there's no error checking or anything that obviously indicates that the domain is incorrect, so we might as well normalize all domains being passed since it's already pretty optimized.
2018-02-28[REF] models: use `parent_path` to implement parent_storeRaphael Collet
This replaces the former modified preorder tree traversal (MPTT) with the fields `parent_left`/`parent_right`. Each record is associated to a string `parent_path`, that represents the path from its root node to itself. The path is made of the node ids suffixed with a slash: a node | id | parent_path / \ a | 42 | 42/ ... b b | 63 | 42/63/ / \ c | 84 | 42/63/84/ c d d | 85 | 42/63/85/ This field provides an efficient implementation for parent_of/child_of queries: the nodes in the subtree of record are the ones where `parent_path` starts with the `parent_path` of record. It is also more efficient to maintain than the MPTT fields, and less sensitive to concurrent updates, because the value of `parent_path` does not depend on sibling nodes.
2018-02-28[REF] never defer parent_store computationRaphael Collet
Simplify the implementation of parent_left/parent_right by removing this optimization.
2018-01-16[REF] models: improve code of `_create`/`_write`Raphael Collet
Also remove method `self._check_selection_field_value`, and perform the check in field method `convert_to_column`.
2017-09-29[IMP] web: x2m list: conditionnaly hide a columnfwi-odoo
This commit introduces a new way to hide a column in a x2m list view. The attribute 'tree_invisible' can be add in the field attrs in the x2m view definition. This attribute can use the 'parent' key to make a reference to the parent record (e.g. 'parent.id').
2017-09-29[FIX] models: skip an SQL query when its result is known to be emptyRaphael Collet
In method `search`, simply make an abstract interpretation of the domain to determine whether it is equivalent to false. In that case, skip the query.