Skip to content

Commit 40fefc4

Browse files
committed
fixup! [ADD] util.fields: handle ir.exports model/fields renames/removal
1 parent 162fed3 commit 40fefc4

File tree

2 files changed

+48
-63
lines changed

2 files changed

+48
-63
lines changed

src/util/fields.py

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import psycopg2
1818
from psycopg2 import sql
19-
from psycopg2.extras import Json, execute_values
19+
from psycopg2.extras import Json
2020

2121
try:
2222
from odoo import release
@@ -142,63 +142,6 @@ def _get_resolved_ir_exports(cr, models=None, fields=None):
142142
return result
143143

144144

145-
def rename_ir_exports_fields(cr, models_fields_map):
146-
"""
147-
Rename fields references in ir.exports.line records.
148-
149-
:param dict[str, dict[str, str]] models_fields_map: a dict of models to the fields rename dict,
150-
like: `{"model.name": {"old_field": "new_field", ...}, ...}`
151-
152-
:meta private: exclude from online docs
153-
"""
154-
matching_exports = _get_resolved_ir_exports(
155-
cr,
156-
fields=[(model, field) for model, fields_map in models_fields_map.items() for field in fields_map],
157-
)
158-
if not matching_exports:
159-
return
160-
_logger.debug("Renaming %d export template lines with renamed fields", len(matching_exports))
161-
fixed_lines_paths = {}
162-
for line_id, resolved_paths in matching_exports.items():
163-
for path_part in resolved_paths:
164-
assert path_part.field_model in models_fields_map
165-
fields_map = models_fields_map[path_part.field_model]
166-
assert path_part.field_name in fields_map
167-
assert path_part.path[path_part.part_index - 1] == path_part.field_name
168-
new_field_name = fields_map[path_part.field_name]
169-
fixed_path = fixed_lines_paths.get(line_id, list(path_part.path))
170-
fixed_path[path_part.part_index - 1] = new_field_name
171-
fixed_lines_paths[line_id] = fixed_path
172-
execute_values(
173-
cr,
174-
"""
175-
UPDATE ir_exports_line el
176-
SET name = v.name
177-
FROM (VALUES %s) AS v(id, name)
178-
WHERE el.id = v.id
179-
""",
180-
[(k, "/".join(v)) for k, v in fixed_lines_paths.items()],
181-
)
182-
183-
184-
def remove_ir_exports_lines(cr, models=None, fields=None):
185-
"""
186-
Delete ir.exports.line records that reference models or fields that are/will be removed.
187-
188-
Only one of ``models`` or ``fields`` arguments should be provided.
189-
190-
:param list[str] models: a list of model names to match in exports
191-
:param list[(str, str)] fields: a list of (model, field) tuples to match in exports
192-
193-
:meta private: exclude from online docs
194-
"""
195-
matching_exports = _get_resolved_ir_exports(cr, models=models, fields=fields)
196-
if not matching_exports:
197-
return
198-
_logger.debug("Deleting %d export template lines with removed models/fields", len(matching_exports))
199-
cr.execute("DELETE FROM ir_exports_line WHERE id IN %s", [tuple(matching_exports.keys())])
200-
201-
202145
def ensure_m2o_func_field_data(cr, src_table, column, dst_table):
203146
"""
204147
Fix broken m2o relations.
@@ -323,7 +266,9 @@ def clean_context(context):
323266
)
324267

325268
# ir.exports.line
326-
remove_ir_exports_lines(cr, fields=[(model, fieldname)])
269+
matching_exports = _get_resolved_ir_exports(cr, fields=[(model, fieldname)])
270+
if matching_exports:
271+
cr.execute("DELETE FROM ir_exports_line WHERE id IN %s", [tuple(matching_exports.keys())])
327272

328273
def adapter(leaf, is_or, negated):
329274
# replace by TRUE_LEAF, unless negated or in a OR operation but not negated
@@ -1195,7 +1140,31 @@ def _update_field_usage_multi(cr, models, old, new, domain_adapter=None, skip_in
11951140

11961141
# ir.exports.line
11971142
if only_models:
1198-
rename_ir_exports_fields(cr, {model: {old: new} for model in only_models})
1143+
cr.execute(
1144+
"""
1145+
SELECT el.id,
1146+
e.resource,
1147+
STRING_TO_ARRAY(el.name, '/')
1148+
FROM ir_exports_line el
1149+
JOIN ir_exports e
1150+
ON el.export_id = e.id
1151+
WHERE el.name ~ %s
1152+
""",
1153+
[r"\y{}\y".format(old)],
1154+
)
1155+
fixed_lines_paths = {}
1156+
for line_id, model, path in cr.fetchall():
1157+
new_path = [
1158+
new if x.field_name == old and x.field_model in only_models else x.field_name
1159+
for x in resolve_model_fields_path(cr, model, path)
1160+
]
1161+
if len(new_path) == len(path) and new_path != path:
1162+
fixed_lines_paths[line_id] = "/".join(new_path)
1163+
if fixed_lines_paths:
1164+
cr.execute(
1165+
"UPDATE ir_exports_line SET name = (%s::jsonb)->>(id::text) WHERE id IN %s",
1166+
[Json(fixed_lines_paths), tuple(fixed_lines_paths)],
1167+
)
11991168

12001169
# mail.alias
12011170
if column_exists(cr, "mail_alias", "alias_defaults"):

src/util/models.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
import re
1111

1212
from .const import ENVIRON
13-
from .fields import IMD_FIELD_PATTERN, remove_field, remove_ir_exports_lines
14-
from .helpers import _ir_values_value, _validate_model, model_of_table, table_of_model
13+
from .fields import IMD_FIELD_PATTERN, remove_field
14+
from .helpers import _ir_values_value, _validate_model, model_of_table, resolve_model_fields_path, table_of_model
1515
from .indirect_references import indirect_references
1616
from .inherit import for_each_inherit, inherit_parents
1717
from .misc import _cached, chunks, log_progress
@@ -130,7 +130,23 @@ def remove_model(cr, model, drop_table=True, ignore_m2m=()):
130130
notify = notify or bool(cr.rowcount)
131131

132132
# for ir.exports.line we have to take care of "nested" references in fields "paths"
133-
remove_ir_exports_lines(cr, models=[model])
133+
cr.execute(
134+
"""
135+
SELECT el.id,
136+
e.resource AS model,
137+
string_to_array(el.name, '/') AS path
138+
FROM ir_exports e
139+
JOIN ir_exports_line el
140+
ON e.id = el.export_id
141+
""",
142+
)
143+
to_rem = [
144+
line_id
145+
for line_id, line_model, line_path in cr.fetchall()
146+
if any(x.field_model == model for x in resolve_model_fields_path(cr, line_model, line_path))
147+
]
148+
if to_rem:
149+
cr.execute("DELETE FROM ir_exports_line WHERE id IN %s", [tuple(to_rem)])
134150

135151
_rm_refs(cr, model)
136152

0 commit comments

Comments
 (0)