|
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