Skip to content

Commit 2162f8e

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 30020ce commit 2162f8e

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

src/util/orm.py

Lines changed: 31 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 bool yield_chunks: when iterating, yield records in chunks of `chunk_size` instead of one by one.
@@ -377,14 +379,27 @@ class iter_browse(object):
377379
See also :func:`~odoo.upgrade.util.orm.env`
378380
"""
379381

380-
__slots__ = ("_chunk_size", "_cr_uid", "_it", "_logger", "_model", "_patch", "_size", "_strategy", "_yield_chunks")
382+
__slots__ = (
383+
"_chunk_size",
384+
"_cr_uid",
385+
"_ids",
386+
"_it",
387+
"_logger",
388+
"_model",
389+
"_patch",
390+
"_query",
391+
"_size",
392+
"_strategy",
393+
"_yield_chunks",
394+
)
381395

382396
def __init__(self, model, *args, **kw):
383397
assert len(args) in [1, 3] # either (cr, uid, ids) or (ids,)
384398
self._model = model
385399
self._cr_uid = args[:-1]
386-
ids = args[-1]
387-
self._size = len(ids)
400+
self._ids = args[-1]
401+
self._size = kw.pop("size", None)
402+
self._query = kw.pop("query", None)
388403
self._chunk_size = kw.pop("chunk_size", 200) # keyword-only argument
389404
self._yield_chunks = kw.pop("yield_chunks", False)
390405
self._logger = kw.pop("logger", _logger)
@@ -393,8 +408,19 @@ def __init__(self, model, *args, **kw):
393408
if kw:
394409
raise TypeError("Unknown arguments: %s" % ", ".join(kw))
395410

411+
if not (self._ids is None) ^ (self._query is None):
412+
raise TypeError("Must be initialized using exactly one of `ids` or `query`")
413+
414+
if self._query:
415+
self._ids = query_ids(self._model.env.cr, self._query, itersize=self._chunk_size)
416+
417+
if not self._size:
418+
try:
419+
self._size = len(self._ids)
420+
except TypeError:
421+
raise ValueError("When passing ids as a generator, the size kwarg is mandatory")
396422
self._patch = None
397-
self._it = chunks(ids, self._chunk_size, fmt=self._browse)
423+
self._it = chunks(self._ids, self._chunk_size, fmt=self._browse)
398424

399425
def _browse(self, ids):
400426
next(self._end(), None)

0 commit comments

Comments
 (0)