|
14 | 14 | from contextlib import contextmanager
|
15 | 15 | from functools import wraps
|
16 | 16 | from itertools import chain
|
17 |
| -from operator import itemgetter |
18 | 17 | from textwrap import dedent
|
19 | 18 |
|
20 | 19 | try:
|
|
43 | 42 | from .exceptions import MigrationError
|
44 | 43 | from .helpers import table_of_model
|
45 | 44 | from .misc import chunks, log_progress, version_between, version_gte
|
46 |
| -from .pg import column_exists, get_columns |
| 45 | +from .pg import column_exists, format_query, get_columns, named_cursor |
47 | 46 |
|
48 | 47 | # python3 shims
|
49 | 48 | try:
|
@@ -281,18 +280,31 @@ def recompute_fields(cr, model, fields, ids=None, logger=_logger, chunk_size=256
|
281 | 280 | assert strategy in {"flush", "commit", "auto"}
|
282 | 281 | Model = env(cr)[model] if isinstance(model, basestring) else model
|
283 | 282 | model = Model._name
|
| 283 | + |
| 284 | + def get_ids(): |
| 285 | + if ids is not None: |
| 286 | + for id_ in ids: |
| 287 | + yield id_ |
| 288 | + else: |
| 289 | + with named_cursor(cr, itersize=2**20) as ncr: |
| 290 | + ncr.execute(format_query(cr, "SELECT id FROM {t} ORDER BY id", t=table_of_model(cr, model))) |
| 291 | + for (id_,) in ncr: |
| 292 | + yield id_ |
| 293 | + |
284 | 294 | if ids is None:
|
285 |
| - cr.execute('SELECT id FROM "%s"' % table_of_model(cr, model)) |
286 |
| - ids = tuple(map(itemgetter(0), cr.fetchall())) |
| 295 | + cr.execute(format_query(cr, "SELECT COUNT(id) FROM {t}", t=table_of_model(cr, model))) |
| 296 | + (count,) = cr.fetchone() |
| 297 | + else: |
| 298 | + count = len(ids) |
287 | 299 |
|
288 | 300 | if strategy == "auto":
|
289 |
| - big_table = len(ids) > BIG_TABLE_THRESHOLD |
| 301 | + big_table = count > BIG_TABLE_THRESHOLD |
290 | 302 | any_tracked_field = any(getattr(Model._fields[f], _TRACKING_ATTR, False) for f in fields)
|
291 | 303 | strategy = "commit" if big_table and any_tracked_field else "flush"
|
292 | 304 |
|
293 |
| - size = (len(ids) + chunk_size - 1) / chunk_size |
| 305 | + size = (count + chunk_size - 1) / chunk_size |
294 | 306 | qual = "%s %d-bucket" % (model, chunk_size) if chunk_size != 1 else model
|
295 |
| - for subids in log_progress(chunks(ids, chunk_size, list), logger, qualifier=qual, size=size): |
| 307 | + for subids in log_progress(chunks(get_ids(), chunk_size, list), logger, qualifier=qual, size=size): |
296 | 308 | records = Model.browse(subids)
|
297 | 309 | for field_name in fields:
|
298 | 310 | field = records._fields[field_name]
|
|
0 commit comments