Use globale cache also for Many2One and Reference fields
review590007
This commit is contained in:
1 parent
8f5f4c6162
commit
eb820df535
4 files changed
+72
-45
No files matched your search
+25
-16
@@ -522,10 +522,12 @@ class ActionReport(ModelSQL, ModelView):
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
report = super(ActionReport, cls).create(vals)
|
||||
new_id = report.action.id
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s ' \
|
||||
'WHERE id = %s', (report.action.id, report.id))
|
||||
cursor.update_auto_increment(cls._table, report.action.id)
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (report.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, report.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
report = cls(new_id)
|
||||
cls.write([report], later)
|
||||
return report
|
||||
@@ -734,10 +736,12 @@ class ActionActWindow(ModelSQL, ModelView):
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
act_window = super(ActionActWindow, cls).create(vals)
|
||||
new_id = act_window.action.id
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s ' \
|
||||
'WHERE id = %s', (act_window.action.id, act_window.id))
|
||||
cursor.update_auto_increment(cls._table, act_window.action.id)
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (act_window.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, act_window.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
act_window = cls(new_id)
|
||||
cls.write([act_window], later)
|
||||
return act_window
|
||||
@@ -874,10 +878,12 @@ class ActionWizard(ModelSQL, ModelView):
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
wizard = super(ActionWizard, cls).create(vals)
|
||||
new_id = wizard.action.id
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s ' \
|
||||
'WHERE id = %s', (wizard.action.id, wizard.id))
|
||||
cursor.update_auto_increment(cls._table, wizard.action.id)
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (wizard.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, wizard.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
wizard = cls(new_id)
|
||||
cls.write([wizard], later)
|
||||
return wizard
|
||||
@@ -943,10 +949,13 @@ class ActionURL(ModelSQL, ModelView):
|
||||
if cursor.nextid(cls._table):
|
||||
cursor.setnextid(cls._table, cursor.currid('ir_action'))
|
||||
url = super(ActionURL, cls).create(vals)
|
||||
new_id = url.action.id
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s ' \
|
||||
'WHERE id = %s', (url.action.id, url.id))
|
||||
cursor.update_auto_increment(cls._table, url.action.id)
|
||||
cursor.execute('SELECT action FROM "' + cls._table + '" '
|
||||
'WHERE id = %s', (url.id,))
|
||||
new_id, = cursor.fetchone()
|
||||
cls.write([url], {}) # simulate write to clear the cache
|
||||
cursor.execute('UPDATE "' + cls._table + '" SET id = %s '
|
||||
'WHERE id = %s', (new_id, url.id))
|
||||
cursor.update_auto_increment(cls._table, new_id)
|
||||
url = cls(new_id)
|
||||
cls.write([url], later)
|
||||
return url
|
||||
|
||||
@@ -1209,21 +1209,22 @@ class ModelSQL(ModelStorage):
|
||||
|
||||
rows = cursor.dictfetchmany(cursor.IN_MAX)
|
||||
cache = cursor.get_cache(Transaction().context)
|
||||
cache.setdefault(cls.__name__, LRUDict(RECORD_CACHE_SIZE))
|
||||
if cls.__name__ not in cache:
|
||||
cache[cls.__name__] = LRUDict(RECORD_CACHE_SIZE)
|
||||
delete_records = Transaction().delete_records.setdefault(cls.__name__,
|
||||
set())
|
||||
keys = None
|
||||
for data in islice(rows, 0, cache.size_limit):
|
||||
if data['id'] in delete_records:
|
||||
continue
|
||||
if not keys:
|
||||
if keys is None:
|
||||
keys = data.keys()
|
||||
for k in keys[:]:
|
||||
if k in ('_timestamp', '_datetime'):
|
||||
keys.remove(k)
|
||||
continue
|
||||
field = cls._fields[k]
|
||||
if field._type not in ('many2one',):
|
||||
if not getattr(field, 'datetime_field', None):
|
||||
keys.remove(k)
|
||||
continue
|
||||
for k in keys:
|
||||
|
||||
@@ -1154,14 +1154,6 @@ class ModelStorage(Model):
|
||||
if self._local_cache.counter != counter:
|
||||
self._local_cache.clear()
|
||||
self._local_cache.counter = counter
|
||||
try:
|
||||
return self._local_cache[self.id][name]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
return self._cache[self.id][name]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# fetch the definition of the field
|
||||
if name in self._fields:
|
||||
@@ -1172,6 +1164,16 @@ class ModelStorage(Model):
|
||||
raise AttributeError("'%s' Model has no attribute '%s'"
|
||||
% (self.__name__, name))
|
||||
|
||||
try:
|
||||
return self._local_cache[self.id][name]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
if field._type not in ('many2one', 'reference'):
|
||||
return self._cache[self.id][name]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# build the list of fields we will fetch
|
||||
ffields = {
|
||||
name: field,
|
||||
@@ -1233,18 +1235,12 @@ class ModelStorage(Model):
|
||||
ffields[field.datetime_field] = datetime_field
|
||||
|
||||
def filter_(id_):
|
||||
try:
|
||||
if name in self._local_cache[id_]:
|
||||
return False
|
||||
if name in self._cache[id_]:
|
||||
return False
|
||||
except KeyError:
|
||||
pass
|
||||
return True
|
||||
return (name not in self._cache.get(id_, {})
|
||||
and name not in self._local_cache.get(id_, {}))
|
||||
index = self._ids.index(self.id)
|
||||
ids = chain(islice(self._ids, index, None),
|
||||
islice(self._ids, 0, max(index - 1, 0)))
|
||||
ids = list(islice(ifilter(filter_, ids), self._cursor.IN_MAX))
|
||||
ids = islice(ifilter(filter_, ids), self._cursor.IN_MAX)
|
||||
|
||||
def instantiate(field, value, data):
|
||||
if field._type in ('many2one', 'one2one', 'reference'):
|
||||
@@ -1287,25 +1283,40 @@ class ModelStorage(Model):
|
||||
with contextlib.nested(Transaction().set_cursor(self._cursor),
|
||||
Transaction().set_user(self._user),
|
||||
Transaction().set_context(self._context)):
|
||||
if self.id in self._cache and name in self._cache[self.id]:
|
||||
# Use values from cache
|
||||
ids = islice(chain(islice(self._ids, index, None),
|
||||
islice(self._ids, 0, max(index - 1, 0))),
|
||||
self._cursor.IN_MAX)
|
||||
ffields = {name: ffields[name]}
|
||||
read_data = [{'id': i, name: self._cache[i][name]}
|
||||
for i in ids
|
||||
if i in self._cache and name in self._cache[i]]
|
||||
else:
|
||||
read_data = self.read(list(ids), ffields.keys())
|
||||
# create browse records for 'remote' models
|
||||
for data in self.read(ids, ffields.keys()):
|
||||
for data in read_data:
|
||||
for fname, field in ffields.iteritems():
|
||||
fvalue = data[fname]
|
||||
if field._type in ('many2one', 'one2one', 'one2many',
|
||||
'many2many', 'reference'):
|
||||
data[fname] = instantiate(field, data[fname], data)
|
||||
elif not isinstance(field, fields.Function):
|
||||
continue
|
||||
fvalue = instantiate(field, data[fname], data)
|
||||
if data['id'] == self.id and fname == name:
|
||||
value = data[fname]
|
||||
value = fvalue
|
||||
if (field._type not in ('many2one', 'one2one', 'one2many',
|
||||
'many2many', 'reference')
|
||||
and not isinstance(field, fields.Function)):
|
||||
continue
|
||||
if data['id'] not in self._local_cache:
|
||||
self._local_cache[data['id']] = {}
|
||||
self._local_cache[data['id']][fname] = data[fname]
|
||||
del data[fname]
|
||||
self._local_cache[data['id']][fname] = fvalue
|
||||
if (field._type not in ('many2one', 'reference')
|
||||
or getattr(field, 'datetime_field', None)
|
||||
or isinstance(field, fields.Function)):
|
||||
del data[fname]
|
||||
if data['id'] not in self._cache:
|
||||
self._cache[data['id']] = {}
|
||||
self._cache[data['id']].update(data)
|
||||
if data['id'] == self.id and name in data:
|
||||
value = data[name]
|
||||
return value
|
||||
|
||||
@property
|
||||
|
||||
@@ -221,6 +221,12 @@ class User(ModelSQL, ModelView):
|
||||
def write(cls, users, vals):
|
||||
vals = cls._convert_vals(vals)
|
||||
super(User, cls).write(users, vals)
|
||||
# Clean cursor cache as it could be filled by domain_get
|
||||
for cache in Transaction().cursor.cache.itervalues():
|
||||
if cls.__name__ in cache:
|
||||
for user in users:
|
||||
if user.id in cache[cls.__name__]:
|
||||
cache[cls.__name__][user.id].clear()
|
||||
# Restart the cache for domain_get method
|
||||
pool = Pool()
|
||||
pool.get('ir.rule')._domain_get_cache.clear()
|
||||
|
||||
Reference in new issue
Block a user