Use globale cache also for Many2One and Reference fields

review590007
This commit is contained in:
Cédric Krier committed 2012-12-10 16:15:24 +01:00
1 parent 8f5f4c6162
commit eb820df535
4 files changed
+72 -45

No files matched your search

+25 -16
View File
@@ -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
+4 -3
View File
@@ -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:
+37 -26
View File
@@ -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
+6
View File
@@ -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()