Skip to content

Commit fbb5ae7

Browse files
committed
[FIX] util/records:Mark records noupdate
If particular xml don't have noupdate marked but parent ``data`` node have noupdate in that case from update_records_from_xml creating record as noupdate ``false`` which is causing issue in future upgrade because it going for delete. For preventing such case adding noupdate flag to record and inherit created record acccoring to this commit odoo/odoo@ef709fd#diff-7144f88ea32f36feb17ce1b8dda7dee1631f5ada34075414587df3948c6b3d1bL4098-R4118 by that ``//data`` node or that ``xml node`` itself. use case: client db don't have the ``documents.document_internal_folder`` https://github.com/odoo/enterprise/blob/6c677f388c934e3fc545fc7cb2f9d65a958433da/documents/data/documents_document_data.xml#L2-L18 xmlid which is created when migrated to 18.0 from this script https://github.com/odoo/upgrade/blob/9327a2c12d9faf67d71f09bbe4d91e6105c75dca/migrations/documents/saas~17.5.1.4/post-migrate.py#L24 with noupdate false and because data node have noupdate true but particular xml don't have noupdate that is why it created as noupdate false and other inherit records also with noupdate and after migrating from onwards version related to that mail.alias records xml creating according to this https://github.com/odoo/odoo/blob/9822f5cd1fd3ac60689fc5e3101e5f6fa6a5722d/odoo/models.py#L5514 and later on version in 18.3 if related inherit model is changed but still some how use case of those records for preventing in that case. before upgrade ``` timer_test_document_test=# select * from ir_model_data where name like '%document_internal_folder%' ; id | create_uid | create_date | write_date | write_uid | res_id | noupdate | name | module | model ----+------------+-------------+------------+-----------+--------+----------+------+--------+------- (0 rows) ``` before fix ``` timer_test_document_test=# select * from ir_model_data where name like '%document_internal_folder%' ; id | create_uid | create_date | write_date | write_uid | res_id | noupdate | name | module | model -------+------------+----------------------------+----------------------------+-----------+--------+----------+-------------------------------------+-----------+-------------------- 39576 | | 2025-06-19 13:38:37.987267 | 2025-06-19 13:38:37.987267 | | 20 | f | document_internal_folder_mail_alias | documents | mail.alias 39577 | | 2025-06-19 13:38:37.987267 | 2025-06-19 13:38:37.987267 | | 20 | f | document_internal_folder | documents | documents.document ``` after fix ``` timer_test_document_test=# select * from ir_model_data where name like '%document_internal_folder%' ; id | create_uid | create_date | write_date | write_uid | res_id | noupdate | name | module | model -------+------------+----------------------------+----------------------------+-----------+--------+----------+-------------------------------------+-----------+-------------------- 39576 | | 2025-06-19 13:41:40.343454 | 2025-06-19 13:41:40.343454 | | 20 | t | document_internal_folder_mail_alias | documents | mail.alias 39577 | | 2025-06-19 13:41:40.343454 | 2025-06-19 13:41:40.343454 | | 20 | t | document_internal_folder | documents | documents.document ``` ``` Traceback (most recent call last): File "/home/odoo/src/odoo/saas-18.3/odoo/service/server.py", line 1396, in preload_registries registry = Registry.new(dbname, update_module=update_module, install_modules=config['init'], upgrade_modules=config['update']) File "<decorator-gen-6>", line 2, in new File "/home/odoo/src/odoo/saas-18.3/odoo/tools/func.py", line 83, in locked return func(inst, *args, **kwargs) File "/home/odoo/src/odoo/saas-18.3/odoo/orm/registry.py", line 167, in new load_modules( File "/home/odoo/src/odoo/saas-18.3/odoo/modules/loading.py", line 509, in load_modules env['ir.model.data']._process_end(registry.updated_modules) File "/tmp/tmp2ipekce9/migrations/base/0.0.0/pre-models-no-model-data-delete.py", line 108, in _process_end return super(IrModelData, self)._process_end(modules) File "/home/odoo/src/odoo/saas-18.3/odoo/addons/base/models/ir_model.py", line 2589, in _process_end self._process_end_unlink_record(record) File "/home/odoo/src/odoo/saas-18.3/addons/website/models/ir_model_data.py", line 35, in _process_end_unlink_record return super()._process_end_unlink_record(record) File "/home/odoo/src/odoo/saas-18.3/odoo/addons/base/models/ir_model.py", line 2518, in _process_end_unlink_record record.unlink() File "/home/odoo/src/odoo/saas-18.3/odoo/orm/models.py", line 3913, in unlink cr.execute(SQL( File "/home/odoo/src/odoo/saas-18.3/odoo/sql_db.py", line 422, in execute self._obj.execute(query, params) psycopg2.errors.ForeignKeyViolation: update or delete on table "mail_alias" violates foreign key constraint "documents_document_alias_id_fkey" on table "documents_document" DETAIL: Key (id)=(40) is still referenced from table "documents_document". ``` upg-2987024 opw-4874805
1 parent 6ba49a9 commit fbb5ae7

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

src/util/records.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,7 @@ def update_record_from_xml(
10171017
reset_translations=(),
10181018
ensure_references=False,
10191019
fields=None,
1020+
noupdate=None,
10201021
):
10211022
"""
10221023
Update a record based on its definition in the :doc:`/developer/reference/backend/data`.
@@ -1041,6 +1042,8 @@ def update_record_from_xml(
10411042
:param set(str) or None fields: optional list of fields to include in the XML declaration.
10421043
If set, all other fields will be ignored. When set, record
10431044
won't be created if missing.
1045+
:param bool or None noupdate: whether to set the `noupdate` of the xml_id to `True` or `False`.
1046+
By default, the existing `noupdate` value of the xml_id is preserved.
10441047
10451048
.. warning::
10461049
This functions uses the ORM, therefore it can only be used after **all** models
@@ -1062,6 +1065,7 @@ def update_record_from_xml(
10621065
ensure_references=ensure_references,
10631066
fields=fields,
10641067
done_refs=set(),
1068+
noupdate=None,
10651069
)
10661070

10671071

@@ -1075,6 +1079,7 @@ def __update_record_from_xml(
10751079
ensure_references,
10761080
fields,
10771081
done_refs,
1082+
noupdate=None,
10781083
):
10791084
from .modules import get_manifest
10801085

@@ -1099,15 +1104,16 @@ def __update_record_from_xml(
10991104
[module, name],
11001105
)
11011106
if cr.rowcount:
1102-
model, res_id, noupdate = cr.fetchone()
1107+
model, res_id, _noupdate = cr.fetchone()
1108+
noupdate = noupdate if noupdate is not None else _noupdate
11031109
if model == "ir.model":
11041110
return
11051111
elif not force_create:
11061112
_logger.warning("Record %r not found in database. Skip update.", xmlid)
11071113
return
11081114
else:
11091115
# The xmlid doesn't already exists, nothing to reset
1110-
reset_write_metadata = noupdate = reset_translations = False
1116+
reset_write_metadata = reset_translations = False
11111117
fields = None
11121118

11131119
write_data = None
@@ -1139,6 +1145,7 @@ def add_ref(ref):
11391145
elif ref.split(".")[0] == from_module:
11401146
extra_references.append(ref)
11411147

1148+
force_noupdate_to_record = False
11421149
for f in manifest.get("data", []):
11431150
if not f.endswith(".xml"):
11441151
continue
@@ -1153,6 +1160,12 @@ def add_ref(ref):
11531160
node.remove(fn)
11541161
new_root[0].append(node)
11551162

1163+
data_node = doc.find(".//data")
1164+
if (data_node is not None and eval(data_node.attrib.get("noupdate", "0"))) or (
1165+
eval(node.attrib.get("noupdate", "0"))
1166+
):
1167+
force_noupdate_to_record = True
1168+
11561169
if node.tag == "menuitem" and parent.tag == "menuitem" and "parent_id" not in node.attrib:
11571170
new_root[0].append(
11581171
lxml.builder.E.record(
@@ -1210,6 +1223,17 @@ def add_ref(ref):
12101223
if reset_write_metadata and write_data:
12111224
cr.execute("UPDATE {} SET write_uid=%s, write_date=%s WHERE id=%s".format(table), write_data)
12121225

1226+
# force noupdate newly created record and inherit records
1227+
if force_noupdate_to_record and noupdate is None:
1228+
cr.execute(
1229+
"""
1230+
UPDATE ir_model_data
1231+
SET noupdate = True
1232+
WHERE module = %s
1233+
AND name ILIKE %s
1234+
""",
1235+
[module, "{}%".format(name)],
1236+
)
12131237
if reset_translations:
12141238
if reset_translations is True:
12151239
if fields is None:

0 commit comments

Comments
 (0)