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})