← Back to team overview

c2c-oerpscenario team mailing list archive

[Bug 659021] Re: inherit bug on orm : useless call of write method making openerp slow

 

Hello Sébastien,

It has been fixed by revision 2141
jvo@xxxxxxxxxxx-20101012192045-7zx1tgznp3greksl authored to you.

Thanks.

** Changed in: openobject-server
       Status: Confirmed => Fix Released

-- 
inherit bug on orm : useless call of write method making openerp slow
https://bugs.launchpad.net/bugs/659021
You received this bug notification because you are a member of C2C
OERPScenario, which is subscribed to OpenERP OpenObject.

Status in OpenObject Server: Fix Released

Bug description:
Hi

I am working on product_variant_multi for on of my customer, and I discover an bug.
(here is the branch, I will merge it soon : https://code.launchpad.net/~akretion-team/openobject-addons/product_variant_multi_improve)

What is product_variant_multi:
OpenERP is already supporting a product variants at the core level. But
without product_variant_multi, variants are only mono-axial. OpenERP indeed uses the product.tempate
as the model object and the product.variant as the instance variant.

Problem:
When I save a product_product (because I change the field "default_code", note that this field is an product_product field), the write method is also apply on the product_template. Indeed if the write method is called for product_product it will be always called for the product_template WITHOUT checking if a field of product_template have been changed.

In 95% of case this is not a problem because the write method is called with the parameter vals={}. So it's just an useless call.
But In my case I have a field on product_product (the field in variants) which is a function field stored.

Here is the definition of the field :

        'variants': fields.function(_variant_name_get, method=True, type='char', size=128, string='Variants', readonly=True,
            store={
                'product.variant.dimension.type': (_get_products_from_dimension, None, 10),
                'product.product': (_get_products_from_product, ['product_tmpl_id'], 10),
                'product.template': (_get_products_from_product_template, ['variant_model_name', 'variant_model_name_separator'], 10),
            }),


As you can see this field will be automatically re-calculated if there is any change on :
- one of the field of the object  'product.variant.dimension.type'
- the field 'product_tmpl_id' of the object product.product
- the fields 'variant_model_name' or 'variant_model_name_separator' of the product.template.

The BIG problem is that this useless call of the write function with vals = {}, will lask for re-calculating of  the stored field 'variants'.

We can easily resolve this bug by checking if vals is empty before calling the write method.

CODE: /bin/osv/orm.py
BEFORE
        for table in self._inherits:
            col = self._inherits[table]
            query = 'SELECT DISTINCT "%s" FROM "%s" WHERE id IN %%s' % (col, self._table)
            nids = []
            for i in range(0, len(ids), cr.IN_MAX):
                sub_ids = ids[i:i+cr.IN_MAX]
                cr.execute(query, (tuple(sub_ids),))
                nids.extend([x[0] for x in cr.fetchall()])

            v = {}
            for val in updend:
                if self._inherit_fields[val][0] == table:
                    v[val] = vals[val]
            self.pool.get(table).write(cr, user, nids, v, context)


AFTER :

        for table in self._inherits:
            col = self._inherits[table]
            query = 'SELECT DISTINCT "%s" FROM "%s" WHERE id IN %%s' % (col, self._table)
            nids = []
            for i in range(0, len(ids), cr.IN_MAX):
                sub_ids = ids[i:i+cr.IN_MAX]
                cr.execute(query, (tuple(sub_ids),))
                nids.extend([x[0] for x in cr.fetchall()])

            v = {}
            for val in updend:
                if self._inherit_fields[val][0] == table:
                    v[val] = vals[val]
            if v:                                                                                  #<===HERE check if where is something to write!!!
                self.pool.get(table).write(cr, user, nids, v, context)

For information when you have a lot of variant (6000 variants for one template) just saving a product (without this patch) will require more than 5s on a my computer (core i5, 6 Go ram...)!!!

I send a path

Thanks you