Commit Graph

1183 Commits

Author SHA1 Message Date
Christophe Simonis 2a65b8156d [FIX] base: run defined modifiers tests 2017-04-26 19:36:10 +02:00
Raphael Collet 6595cfdf0c [FIX] expression: avoid useless query when searching on x2many sub-field
Searching on a domain like `[('m2m.sub', operator, value)]` currently does
something like:

    right_ids = comodel.search([('sub', operator, value)]).ids
    table_ids = model.search([('m2m', 'in', right_ids)]).ids

and reduces the domain triple to `('id', 'in', table_ids)`.

The domain triple can actually be reduced to `('m2m', 'in', right_ids)`.  With
this reduction, the search on the field `m2m` will be done as part of the main
query.  And this will also enable the optimization of the former fix!
2017-04-06 16:46:46 +02:00
Raphael Collet 3c2065c89d [FIX] expression: use sub-select when searching on many2many field
Avoid pathological performance issue caused by injecting ids retrieved with
another query.

Consider a domain like `[('m2m', 'in', ids)]` on a many2many field.  The
current implementation will perform the subquery:

    SELECT m2m_id1 FROM m2m_table WHERE m2m_id2 IN (ids)

and inject its result into the main query as:

    SELECT id FROM ... WHERE id IN (result_ids)

The latter may be very slow if `result_ids` is a huge list of ids.

The fix injects the first query into the main query as:

    SELECT id FROM ... WHERE id IN (
        SELECT m2m_id1 FROM m2m_table WHERE m2m_id2 IN (ids)
    )

As a result, the database will typically JOIN both tables, and avoid generating
the whole list from the subquery.
2017-04-06 15:59:50 +02:00
Nicolas Lempereur cfcc37bca5 [FIX] expression: leaf in o2m with m2o inherits'd field
The reverse field of a one2many could be originating from an
inherits'd field, this was solved in some instance with f5e5bbda.

The issue could still happen in some instances when doing a comparison
of:

- the one2many field to a False value,
- the one2many with a negative operator and an empty set to negate,

With this change, the ORM is used in such a situation.

closes #15234
opw-704962
2017-01-26 16:47:52 +01:00
Jairo Llopis dd312e0da2 [FIX] fields: make [(5,)] with computed domain work (#13480)
* Failing test for one2many [(5,)] action, when domain is callable.

The problem is that `self` inside a callable domain becomes the comodel when at [(5,)].

* [FIX][fields] Make [(5,)] with computed domain work.

To reproduce this failure, declare a field like:

```
child_ids = fields.One2many(
    comodel_name="other.model",
    domain=lambda self: [("id", "in", self._ids_to_find())],
)
```

Now set some value to it.

Now unset them. Impossible because ``self`` becomes ``other.model`` in domain evaluation.
2016-10-11 15:14:05 +02:00
Raphael Collet ba5f5614f3 [FIX] expression: fix missing results in direct search on many2many fields
This case corresponds to searches like `[(field, 'ilike', name)]` where `field`
is a many2many field.  The domain processing performs a `name_search` on the
field's comodel, then makes the relation match the returned record ids.

Problem: the call to `name_search` uses the default limit (100), and this makes
the search return less results than expected.  Make the search complete by
forcing `limit=None`.
2016-04-29 15:48:19 +02:00
Olivier Dony bc26a49194 [MERGE] Forward-port 7.0 up to 4de3f4c4ba 2016-02-05 15:42:12 +01:00
Cedric Snauwaert 4de3f4c4ba [FIX] expression: fix search for o2m with non existing id
The result of searching on a o2m field for a missing ID was
the whole set of records which do not have any lines in the
o2m fields. This is definitely not the desired behavior,
and could lead to disatrous performance, because the
returned set could be extremely large.

One example of such behavior is for recomputing fields
in the env cache in 8.0+. When a o2m line gets deleted,
it triggers the recompute of any dependent fields.

In order to locate the records to recompute, the ORM
searches for the 'parent' records in the comodel table.
When this operation is done by 2 users concurrently
the o2m line may not exist anymore, and the bug
is triggered: dependent fields are recomputed on a possibly
very large set of records that did not need any recompute!
2016-02-04 17:10:08 +01:00
Olivier Dony cc724c2e61 [FIX] base: centralize custom data serialization for builtin types only 2016-02-02 22:42:31 +01:00
Raphael Collet f0646cb51b [IMP] fields: use a "lazy" cursor to compute attribute `digits`
Borrowing a cursor each time you access `field.digits` may be costly, because
of the connection reset.  Moreover, in most cases, the cursor is not used at
all, since the decimal precision are kept in cache.

For the installation of module `product` with its demo data, the number of
cursor allocations was reduced from ~1500 to about 50!
2016-01-29 09:37:27 +01:00
Yuriy A. Apollov 098c084eae [FIX] orm: iteration on `browse_null` object lasts forever 2016-01-26 17:34:39 +01:00
Holger Brunn 6fd57c2188 [FIX] allow searching for new style function
fields in a search path
2016-01-26 14:15:22 +01:00
Raphael Collet 152d9de6cf [FIX] fields: in many2many fields, command `5` removes accessible records only 2016-01-08 16:56:02 +01:00
Raphael Collet ece592dbf7 [FIX] fields: in many2many fields, avoid inserting duplicate entries in table 2016-01-08 16:55:43 +01:00
Raphael Collet 22d125fe96 [FIX] fields: in many2many fields, command `5` removes accessible records only 2016-01-08 16:53:18 +01:00
Raphael Collet 51e66711a9 [FIX] fields: in many2many fields, avoid inserting duplicate entries in table 2016-01-08 16:53:18 +01:00
Jeremy Kersten 3a1c693259 [FIX] osv: fix boolean in domain for custom field
When a new column has been added after that some data already exists,
the old lines will keep an empty/null value. So when we search is the new field
is equals to False or if it is different of True, we need to match the null
values.

Backport of de3b64018a
2015-12-04 18:22:32 +01:00
Jeremy Kersten de3b64018a [FIX] osv: fix boolean in domain for custom field
When a new column has been added after that some data already exists,
the old lines will keep an empty/null value. So when we search is the new field
is equals to False or if it is different of True, we need to match the null
values.

close #9925
2015-12-04 16:31:31 +01:00
Olivier Dony 051b2ce539 [FIX] tools: ignore unknown entities while parsing 2015-11-03 21:38:53 +01:00
Raphael Collet c28a28e69e [IMP] osv: use iteration for expression negating
The current code when applying negative operator on an expression used
recursion which in extreme case is not best friend with python.

e.g: on instance with a lot of wharehouse, some simple action could lead
to a domain with lot of elements which could easiliy go over the python
maximum recursion limit.

This commit fixes this by replacing recursion with iteration.

We have a stack of negation flags and loop on each token of the domain
as follow :

- when we iterate on a leaf, it consumes the top negation flag,

- after a '!' operator, the top token negation is inversed,

- after an '&' or '|' operator, the top negation flag is duplicated on
  the top of the stack.

closes #9433
opw-653802
2015-11-05 17:13:28 +01:00
Denis Ledoux 56c08e486f [FIX] expression: `child_of` domain with `parent_store` & non-existing parent
In the `product.template` model,
when searching products within a category that doesn't exist,
all products were returned, while none should be returned.

For instance,
In Sales > Products,
In the search input, search with internal category:
"A category that doesn't exist",
all products were returned.

opw-649548
2015-11-10 16:35:55 +01:00
Denis Ledoux 8558ecfdf3 [MERGE] forward port of branch saas-3 up to dd8cbf4 2015-11-06 16:08:30 +01:00
Denis Ledoux dd8cbf49ac [MERGE] forward port of branch 7.0 up to d24fcd1 2015-11-06 16:04:21 +01:00
Christophe Simonis 2e9b33b793 [MERGE] forward port of branch 7.0 up to 80c7209 2015-11-03 11:40:01 +01:00
Raphael Collet 780cfba3c6 [FIX] fields: make overriding a property field by a function/computed field work
Contribution by Adrien Peiffer (ACSONE).
2015-10-26 17:25:47 +01:00
Raphael Collet 8ea17a8cc9 [FIX] orm: always save boolean function fields, even when they are false
Fixes #4292: searching for records when a related boolean field is `False`
always returns nothing.
2015-10-12 16:38:17 +02:00
Raphael Collet 6dd5071952 [FIX] fields: in binary fields, pass `strip_style` parameter between APIs 2015-09-23 15:28:12 +02:00
Olivier Dony 2b1cdd551f [FIX] fields.float: avoid non-deterministic side-effects on other cursors
In 5efac22043 and
1cf5723835 the computation
of the decimal precision of float fields was modified to
reuse a random cursor from the request environments.
Environment.envs is a WeakSet, subject to unpredictable
garbage collections.

This could cause hard-to-diagnose problems by executing
a SELECT query in a cursor that is supposed to be
otherwise idle and untouched.

As an example, this could cause a transaction start in a
cursor that was just committed/rolled back,
and was waiting for another operation to complete.

One such case happened semi-randomly during a module
installation triggered from the web client, where the request
cursor is committed and waiting for the registry
initialization done with a different cursor,
in the middle of _button_immediate_function()

After the registry initialization, the request cursor is
used again to determine the next action (ir.actions.todo),
and this could cause a TransactionRollbackError if the
request cursor was used during the initialization.

Using a new cursor every time is much safer, simpler,
and will not cause any significant performance hit,
because it will usually grab an available connection
from the connection pool, rather than create a new one.

Fixes opw-649151
2015-09-15 19:38:19 +02:00
Raphael Collet 085875619f [FIX] fields: in `one2many.set`, replace incorrect query by ORM access
When linking a record into a `one2many` relation with command `(4, rid)`, a
query checks whether the record is already linked to the current record id:

    SELECT 1 FROM {inv_table} WHERE id={rid} AND {inv_field}={id}

where `inv_field` is the name of the inverse field, and `inv_table` is the
table where this field is stored.

The query is wrong if the inverse field is inherited, because the `rid` does
not belong to the table `inv_table`.

The test has been replaced by a plain ORM access:

    rec = obj.browse(cr, SUPERUSER_ID, rid)
    if int(rec[inv_field]) != id:
        ...

This fixes #4685.
2015-09-09 09:36:40 +02:00
Thomas Rehn 11f538fae6 [FIX] expression: table alias reaching 64 characters limits
Postgresql has a limit of 64 characters for tables, columns names
as well as for aliases names.

When generating an alias name, e.g. for group by and order
by clauses, if the alias is longer than 64 characters,
use hashing to force the alias length to be within this
64 chars limit.

Fixes #8094
Closes #8142
2015-09-08 11:53:18 +02:00
Raphael Collet f5e5bbdae0 [FIX] expression: fix search on one2many field with inherited inverse field
Consider the following setting:
 - on model A, field F is computed, stored, and depends on field G
 - on model A, field one2many G to model B, with inverse field H
 - on model B, field many2one H is inherited (_inherits) from model C
 - on model C, field many2one H is stored

When adding records of model B, the field F must be recomputed.  In order to
determine which records to recompute, one searches model A with a domain like
[(G, 'in', ids)].  In expression.py, this is resolved with an SQL query like

    select H from B where id in {ids}

This query fails, since the field H is not stored in model B.  This happens in
general if H is not stored (it may be any computed field).  In that case, one
should instead browse records from B, and read field H through the ORM.

A test case has been added: it introduces a many2one field in a parent model,
and a one2many field using the inherited many2one on a child model.  The test
checks whether one can search on the one2many field.
2015-09-04 13:25:51 +02:00
Christophe Simonis dac52e344c [FIX] models: "ORDER BY" on many2one fields
When ordering results on a many2one fields, results are ordered by
order of the target model. The code was wrongly assuming that this
`_order` attribute only contains `_classic_read` fields (that can be
directly read from the table in database). Now correctly generate the
"ORDER BY" clause using the current table alias.

`res.users` can now be sorted by name.
2015-08-14 15:42:37 +02:00
Olivier Dony 733cb3e76f [MERGE] Forward-port from 7.0 up to 8b3d69a0d7 2015-08-04 15:17:51 +02:00
Daniel Reis 8b3d69a0d7 [FIX] orm: performance of regex to check search `order` spec
This regex is used for a quick sanity check of
the order_spec in `search(order=<order_spec>)`.
Because it was build on the repetition of a
group ending with a series of optional patterns,
it could cause expensive backtracking when the
order spec did not actually match the regex
(the regex engine was trying all possible ways
to split the groups)

Forcing the repeating group to either end
with a comma or the end of the string prevents
prohibitive backtracking, while being even
more restrictive with regard to the syntax of
the order spec.

Closes #7755
2015-08-04 11:45:01 +02:00
Nicolas Lempereur e33baecfa3 [FIX] osv: binary size already in human format
In version 8.0, postgresql's pg_size_pretty function is used
(http://www.postgresql.org/docs/9.4/static/functions-admin.html) when
getting the size of a binary field when reading if `bin_size`
or `bin_size_[col_name]` is set in the context.

So in 8.0 the size of a binary field get units bytes, kB, MB, GB and TB
which was not taken into account. e.g: '5.3 GB'.

This fix uses the size of the string to choose to differenciate the two.

e.g: '10000 bytes' (the longest size) will be returned directly, but
for something longer the human size of the content length will be
returned.

There is a corner case if a file is shorter than 12 bytes but
it is an enough of a small scenario with small implications that it is
deemed acceptable.

closes #7485
opw-644085
2015-07-07 19:17:43 +02:00
Christophe Simonis 066e41b63d [MERGE] forward port of branch saas-3 up to 31f2a1b 2015-06-30 13:33:35 +02:00
Christophe Simonis 31f2a1bc38 [MERGE] forward port of branch 7.0 up to 1c0bc7c 2015-06-30 12:47:27 +02:00
Laetitia Gangloff 1511e788cf [FIX] fields: error if there is no value when convert a many2many relation
Closes #1165
2015-06-24 16:52:05 +02:00
Olivier Dony 9b1aa53f29 [MERGE] Forward-port saas-3 up to 9cdfb0696a 2015-06-23 15:18:00 +02:00
Olivier Dony 9cdfb0696a [MERGE] Forward-port 7.0 up to 6acd5ef91c 2015-06-23 15:13:47 +02:00
Olivier Dony 6acd5ef91c [FIX] expression: internal domain operators require different parsing
Ensure the absence of internal domain operators is correctly
propagated throughout the domain parsing.
2015-06-23 15:04:45 +02:00
Nicolas Lempereur 3269ad8f48 [FIX] fields: throw truthy values on old api field
In 7.0, a field overriding an inherited model would overwrite all the
previously set field attributes. In v8 the new API allow us to keep
previous attribute, and only overwrite attributes of our wish.

Following the commit 7b1ef708 (october 2014) an old api field overriding
could conserve previous attributes values in some cases (if the new value
is falsy (None, "", 0, False, (), {}, [], ...) when it should not. It
was partly an optimization to diminish the size of orm registries
dictionaries to save memory (this patch has been tested with all odoo
modules and added +/- 3M).

This commit (proposed by rco) should overwrite falsy value (so the
behavior of v7 for old api fields overwritting is re-introduced) and
get back the behavior of old api in V7.

closes #7035
opw-639712
2015-06-12 15:08:54 +02:00
Olivier Dony 8d745f9f50 [FIX] account, mail, etc.: uniformize evaluated expressions
opw-626694
2015-05-21 15:26:35 +02:00
Christophe Simonis 327e471c9b [MERGE] forward port of branch saas-3 up to b62ee07 2015-05-21 14:19:24 +02:00
Christophe Simonis b62ee0734c [MERGE] forward port of branch 7.0 up to eaaca65 2015-05-21 14:11:39 +02:00
Christophe Simonis 1cf5723835 Revert "Revert "[FIX] fields: `digits()` computation""
Thamks to parent commit, `request.env` doesn't raise `AttributeError`
anymore for requests without session bound to a database.

This exception was bubbling up to `digits` property (and `__getattr__`)

This reverts commit 49cb46fb78.
This reinstate commit eeedd2d9f5.
2015-05-21 13:13:23 +02:00
Denis Ledoux 49cb46fb78 Revert "[FIX] fields: `digits()` computation"
This reverts commit eeedd2d9f5.

This revision introduces an issue more serious than the ones
it fixes. This is no longer possible to receive an email
aimed a sale.order thread with catchall.

To reproduce the issue:
 - Create a new sale order
 - Send a message in the thread to the customer
 - Reply to the mail received in the customer mailbox
 - Traceback, AttributeError: digits

 opw-640370
2015-05-20 19:13:04 +02:00
Denis Ledoux 54a90179bb [FIX] expression: ensure tuple to compare leaf with TRUE/FALSE leaf
When setting a custom filter with as domain
[(0, '=', 1)]

the domain was rejected, because (0, '=', 1) wasn't
considered as a valid leaf, while it is.

This is because the Javascript converts this domain
using list instead of tuple
[(0, '=', 1)] -> [[0, '=', 1]]

And therefore, comparing the "list" leaf
to the TRUE/FALSE leaf tuple failed.

Ensuring "element" as a tuple solves the issue.

opw-640306
2015-05-20 15:33:35 +02:00
Christophe Simonis eeedd2d9f5 [FIX] fields: `digits()` computation
Ensure we always have an valid cursor when determining `digits()`.

fixes #6605, fixes #6650
2015-05-19 19:59:10 +02:00
Raphael Collet 5efac22043 [FIX] fields: when determining `digits()`, make sure to use a valid cursor 2015-05-07 16:56:26 +02:00