changeset 05235e67b280 in trytond:default
details: https://hg.tryton.org/trytond?cmd=changeset&node=05235e67b280
description:
        Use global cache for Function fields in readonly transactions

        issue10491
        review352081002
diffstat:

 CHANGELOG                     |   1 +
 trytond/model/modelsql.py     |  17 ++++++++++++++---
 trytond/model/modelstorage.py |  14 ++++++++++----
 3 files changed, 25 insertions(+), 7 deletions(-)

diffs (93 lines):

diff -r f04093042cc4 -r 05235e67b280 CHANGELOG
--- a/CHANGELOG Mon Oct 11 11:38:37 2021 +0200
+++ b/CHANGELOG Mon Oct 11 11:52:42 2021 +0200
@@ -1,3 +1,4 @@
+* Use global cache for Function fields in readonly transactions
 * Add format method to DictSchemaMixin
 * Allow modify record name on the reports
 * Add methods to format number and symbol on Lang
diff -r f04093042cc4 -r 05235e67b280 trytond/model/modelsql.py
--- a/trytond/model/modelsql.py Mon Oct 11 11:38:37 2021 +0200
+++ b/trytond/model/modelsql.py Mon Oct 11 11:52:42 2021 +0200
@@ -835,8 +835,8 @@
         getter_fields = [f for f in all_fields
             if f in cls._fields and hasattr(cls._fields[f], 'get')]
 
+        cache = transaction.get_cache()[cls.__name__]
         if getter_fields and cachable_fields:
-            cache = transaction.get_cache()[cls.__name__]
             for row in result:
                 for fname in cachable_fields:
                     cache[row['id']][fname] = row[fname]
@@ -879,13 +879,24 @@
                 for sub_results in grouped_slice(
                         result, record_cache_size(transaction)):
                     sub_results = list(sub_results)
-                    sub_ids = [r['id'] for r in sub_results]
+                    sub_ids = []
+                    for row in sub_results:
+                        if (row['id'] not in cache
+                                or any(f not in cache[row['id']]
+                                    for f in field_list)):
+                            sub_ids.append(row['id'])
+                        else:
+                            for fname in field_list:
+                                row[fname] = cache[row['id']][fname]
                     getter_results = field.get(
                         sub_ids, cls, field_list, values=sub_results)
                     for fname in field_list:
                         getter_result = getter_results[fname]
                         for row in sub_results:
-                            row[fname] = getter_result[row['id']]
+                            if row['id'] in sub_ids:
+                                row[fname] = getter_result[row['id']]
+                                if transaction.readonly:
+                                    cache[row['id']][fname] = row[fname]
 
         def read_related(field, Target, rows, fields):
             name = field.name
diff -r f04093042cc4 -r 05235e67b280 trytond/model/modelstorage.py
--- a/trytond/model/modelstorage.py     Mon Oct 11 11:38:37 2021 +0200
+++ b/trytond/model/modelstorage.py     Mon Oct 11 11:52:42 2021 +0200
@@ -1515,7 +1515,10 @@
             raise AttributeError('"%s" has no attribute "%s"' % (self, name))
 
         try:
-            if field._type not in ('many2one', 'reference'):
+            if field._type not in (
+                    'many2one', 'reference',
+                    'one2many', 'many2many', 'one2one',
+                    ):
                 # fill local cache for quicker access later
                 value \
                         = self._local_cache[self.id][name] \
@@ -1667,7 +1670,7 @@
                 self._transaction.set_user(self._user), \
                 self._transaction.reset_context(), \
                 self._transaction.set_context(
-                    self._context, _check_access=False):
+                    self._context, _check_access=False) as transaction:
             if (self.id in self._cache and name in self._cache[self.id]
                     and not require_context_field):
                 # Use values from cache
@@ -1684,7 +1687,9 @@
                 read_data = self.read(list(index.keys()), list(ffields.keys()))
                 read_data.sort(key=lambda r: index[r['id']])
             # create browse records for 'remote' models
-            no_local_cache = {'one2one', 'one2many', 'many2many', 'binary'}
+            no_local_cache = {'binary'}
+            if not transaction.readonly:
+                no_local_cache |= {'one2one', 'one2many', 'many2many'}
             for data in read_data:
                 id_ = data['id']
                 to_delete = set()
@@ -1705,7 +1710,8 @@
                     if (field._type in no_local_cache
                             or field.context
                             or getattr(field, 'datetime_field', None)
-                            or isinstance(field, fields.Function)):
+                            or (isinstance(field, fields.Function)
+                                and not transaction.readonly)):
                         to_delete.add(fname)
                 self._cache[id_]._update(
                     **{k: v for k, v in data.items() if k not in to_delete})

Reply via email to