Skip to content

Commit a095146

Browse files
committed
[IMP] orm: iter_browse accept generator or query as ids
This allows the caller to be memory efficient on huge numbers of ids, allowing for even more millions of records to be browsed.
1 parent 1316e45 commit a095146

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

src/util/orm.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,9 @@ class iter_browse(object):
362362
363363
:param model: the model to iterate
364364
:type model: :class:`odoo.model.Model`
365-
:param list(int) ids: list of IDs of the records to iterate
365+
:param iterable(int) ids: iterable of IDs of the records to iterate
366+
:param str query: alternative to ids, SQL query that can produce them.
367+
Can also be a DML statement with a RETURNING clause.
366368
:param int chunk_size: number of records to load in each iteration chunk, `200` by
367369
default
368370
:param logger: logger used to report the progress, by default
@@ -375,23 +377,35 @@ class iter_browse(object):
375377
See also :func:`~odoo.upgrade.util.orm.env`
376378
"""
377379

378-
__slots__ = ("_chunk_size", "_cr_uid", "_it", "_logger", "_model", "_patch", "_size", "_strategy")
380+
__slots__ = ("_chunk_size", "_cr_uid", "_ids", "_it", "_logger", "_model", "_patch", "_query", "_size", "_strategy")
379381

380382
def __init__(self, model, *args, **kw):
381383
assert len(args) in [1, 3] # either (cr, uid, ids) or (ids,)
382384
self._model = model
383385
self._cr_uid = args[:-1]
384-
ids = args[-1]
385-
self._size = len(ids)
386+
self._ids = args[-1]
387+
self._size = kw.pop("size", None)
388+
self._query = kw.pop("query", None)
386389
self._chunk_size = kw.pop("chunk_size", 200) # keyword-only argument
387390
self._logger = kw.pop("logger", _logger)
388391
self._strategy = kw.pop("strategy", "flush")
389392
assert self._strategy in {"flush", "commit"}
390393
if kw:
391394
raise TypeError("Unknown arguments: %s" % ", ".join(kw))
392395

396+
if not (self._ids is None) ^ (self._query is None):
397+
raise TypeError("Must be initialized using exactly one of `ids` or `query`")
398+
399+
if self._query:
400+
self._ids = query_ids(self._model.env.cr, self._query, itersize=self._chunk_size)
401+
402+
if not self._size:
403+
try:
404+
self._size = len(self._ids)
405+
except TypeError:
406+
raise ValueError("When passing ids as a generator, the size kwarg is mandatory")
393407
self._patch = None
394-
self._it = chunks(ids, self._chunk_size, fmt=self._browse)
408+
self._it = chunks(self._ids, self._chunk_size, fmt=self._browse)
395409

396410
def _browse(self, ids):
397411
next(self._end(), None)

0 commit comments

Comments
 (0)