[IMP] fields: speedup of `convert_to_cache` for x2many fields
The algorithm's complexity changed from O(n²) to O(n).
This commit is contained in:
parent
9e8d29c986
commit
0939738479
|
@ -30,7 +30,7 @@ import logging
|
||||||
import pytz
|
import pytz
|
||||||
import xmlrpclib
|
import xmlrpclib
|
||||||
|
|
||||||
from openerp.tools import float_round, frozendict, html_sanitize, ustr
|
from openerp.tools import float_round, frozendict, html_sanitize, ustr, OrderedSet
|
||||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
|
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
|
||||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
|
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
|
||||||
|
|
||||||
|
@ -1606,34 +1606,33 @@ class _RelationalMulti(_Relational):
|
||||||
return value.with_env(record.env)
|
return value.with_env(record.env)
|
||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
# value is a list of record ids or commands
|
# value is a list of record ids or commands
|
||||||
if not record.id:
|
comodel = record.env[self.comodel_name]
|
||||||
record = record.browse() # new record has no value
|
ids = OrderedSet(record[self.name].ids)
|
||||||
result = record[self.name]
|
# modify ids with the commands
|
||||||
# modify result with the commands;
|
|
||||||
# beware to not introduce duplicates in result
|
|
||||||
for command in value:
|
for command in value:
|
||||||
if isinstance(command, (tuple, list)):
|
if isinstance(command, (tuple, list)):
|
||||||
if command[0] == 0:
|
if command[0] == 0:
|
||||||
result += result.new(command[2])
|
ids.add(comodel.new(command[2]).id)
|
||||||
elif command[0] == 1:
|
elif command[0] == 1:
|
||||||
result.browse(command[1]).update(command[2])
|
comodel.browse(command[1]).update(command[2])
|
||||||
result += result.browse(command[1]) - result
|
ids.add(command[1])
|
||||||
elif command[0] == 2:
|
elif command[0] == 2:
|
||||||
# note: the record will be deleted by write()
|
# note: the record will be deleted by write()
|
||||||
result -= result.browse(command[1])
|
ids.discard(command[1])
|
||||||
elif command[0] == 3:
|
elif command[0] == 3:
|
||||||
result -= result.browse(command[1])
|
ids.discard(command[1])
|
||||||
elif command[0] == 4:
|
elif command[0] == 4:
|
||||||
result += result.browse(command[1]) - result
|
ids.add(command[1])
|
||||||
elif command[0] == 5:
|
elif command[0] == 5:
|
||||||
result = result.browse()
|
ids.clear()
|
||||||
elif command[0] == 6:
|
elif command[0] == 6:
|
||||||
result = result.browse(command[2])
|
ids = OrderedSet(command[2])
|
||||||
elif isinstance(command, dict):
|
elif isinstance(command, dict):
|
||||||
result += result.new(command)
|
ids.add(comodel.new(command).id)
|
||||||
else:
|
else:
|
||||||
result += result.browse(command) - result
|
ids.add(command)
|
||||||
return result
|
# return result as a recordset
|
||||||
|
return comodel.browse(list(ids))
|
||||||
elif not value:
|
elif not value:
|
||||||
return self.null(record.env)
|
return self.null(record.env)
|
||||||
raise ValueError("Wrong value for %s: %s" % (self, value))
|
raise ValueError("Wrong value for %s: %s" % (self, value))
|
||||||
|
|
|
@ -37,7 +37,7 @@ import threading
|
||||||
import time
|
import time
|
||||||
import werkzeug.utils
|
import werkzeug.utils
|
||||||
import zipfile
|
import zipfile
|
||||||
from collections import defaultdict, Mapping
|
from collections import defaultdict, Mapping, OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from itertools import islice, izip, groupby
|
from itertools import islice, izip, groupby
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
@ -1271,6 +1271,17 @@ class frozendict(dict):
|
||||||
def update(self, *args, **kwargs):
|
def update(self, *args, **kwargs):
|
||||||
raise NotImplementedError("'update' not supported on frozendict")
|
raise NotImplementedError("'update' not supported on frozendict")
|
||||||
|
|
||||||
|
class OrderedSet(OrderedDict):
|
||||||
|
""" A simple collection that remembers the elements insertion order. """
|
||||||
|
def __init__(self, seq=()):
|
||||||
|
super(OrderedSet, self).__init__([(x, None) for x in seq])
|
||||||
|
|
||||||
|
def add(self, elem):
|
||||||
|
self[elem] = None
|
||||||
|
|
||||||
|
def discard(self, elem):
|
||||||
|
self.pop(elem, None)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def ignore(*exc):
|
def ignore(*exc):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue