Skip to content

Commit 64cc32c

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 64cc32c

File tree

1 file changed

+26
-3
lines changed

1 file changed

+26
-3
lines changed

src/util/records.py

Lines changed: 26 additions & 3 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,7 +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.
1044-
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
10451047
.. warning::
10461048
This functions uses the ORM, therefore it can only be used after **all** models
10471049
referenced in the data specs of the record are already **loaded**. In practice this
@@ -1062,6 +1064,7 @@ def update_record_from_xml(
10621064
ensure_references=ensure_references,
10631065
fields=fields,
10641066
done_refs=set(),
1067+
noupdate=None,
10651068
)
10661069

10671070

@@ -1075,6 +1078,7 @@ def __update_record_from_xml(
10751078
ensure_references,
10761079
fields,
10771080
done_refs,
1081+
noupdate=None,
10781082
):
10791083
from .modules import get_manifest
10801084

@@ -1099,15 +1103,16 @@ def __update_record_from_xml(
10991103
[module, name],
11001104
)
11011105
if cr.rowcount:
1102-
model, res_id, noupdate = cr.fetchone()
1106+
model, res_id, _noupdate = cr.fetchone()
1107+
noupdate = noupdate if noupdate is not None else _noupdate
11031108
if model == "ir.model":
11041109
return
11051110
elif not force_create:
11061111
_logger.warning("Record %r not found in database. Skip update.", xmlid)
11071112
return
11081113
else:
11091114
# The xmlid doesn't already exists, nothing to reset
1110-
reset_write_metadata = noupdate = reset_translations = False
1115+
reset_write_metadata = reset_translations = False
11111116
fields = None
11121117

11131118
write_data = None
@@ -1139,6 +1144,7 @@ def add_ref(ref):
11391144
elif ref.split(".")[0] == from_module:
11401145
extra_references.append(ref)
11411146

1147+
force_noupdate_to_record = False
11421148
for f in manifest.get("data", []):
11431149
if not f.endswith(".xml"):
11441150
continue
@@ -1153,6 +1159,12 @@ def add_ref(ref):
11531159
node.remove(fn)
11541160
new_root[0].append(node)
11551161

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

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

0 commit comments

Comments
 (0)