Skip to content

Commit 327a6f6

Browse files
committed
[FIX] spreadsheet: batch process spreadsheet_revision.commands
Some dbs have `spreadsheet_revision` records with over 10 millions characters in `commands`. If the number of record is high, this leads to memory errors. We use a named cursor so the fetching is done in postgres and data are processed in smaller batches by the upgrade process.
1 parent 86409e5 commit 327a6f6

File tree

1 file changed

+23
-22
lines changed

1 file changed

+23
-22
lines changed

src/util/spreadsheet/misc.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,33 @@
1-
from .. import json
1+
from .. import json, pg
22

33

44
def iter_commands(cr, like_all=(), like_any=()):
55
if not (bool(like_all) ^ bool(like_any)):
66
raise ValueError("Please specify `like_all` or `like_any`, not both")
7-
cr.execute(
8-
"""
9-
SELECT id,
10-
commands
11-
FROM spreadsheet_revision
12-
WHERE commands LIKE {}(%s::text[])
13-
""".format("ALL" if like_all else "ANY"),
14-
[list(like_all or like_any)],
15-
)
16-
for revision_id, data in cr.fetchall():
17-
data_loaded = json.loads(data)
18-
if "commands" not in data_loaded:
19-
continue
20-
data_old = json.dumps(data_loaded, sort_keys=True)
7+
with pg.named_cursor(cr, itersize=1) as ncr:
8+
ncr.execute(
9+
"""
10+
SELECT id,
11+
commands
12+
FROM spreadsheet_revision
13+
WHERE commands LIKE {}(%s::text[])
14+
""".format("ALL" if like_all else "ANY"),
15+
[list(like_all or like_any)],
16+
)
17+
for revision_id, data in ncr:
18+
data_loaded = json.loads(data)
19+
if "commands" not in data_loaded:
20+
continue
21+
data_old = json.dumps(data_loaded, sort_keys=True)
2122

22-
changed = yield data_loaded["commands"]
23-
if changed is None:
24-
changed = data_old != json.dumps(data_loaded, sort_keys=True)
23+
changed = yield data_loaded["commands"]
24+
if changed is None:
25+
changed = data_old != json.dumps(data_loaded, sort_keys=True)
2526

26-
if changed:
27-
cr.execute(
28-
"UPDATE spreadsheet_revision SET commands=%s WHERE id=%s", [json.dumps(data_loaded), revision_id]
29-
)
27+
if changed:
28+
cr.execute(
29+
"UPDATE spreadsheet_revision SET commands=%s WHERE id=%s", [json.dumps(data_loaded), revision_id]
30+
)
3031

3132

3233
def process_commands(cr, callback, *args, **kwargs):

0 commit comments

Comments
 (0)