31
31
resolve_model_fields_path ,
32
32
table_of_model ,
33
33
)
34
+ from .inconsistencies import break_recursive_loops
34
35
from .indirect_references import indirect_references
35
36
from .inherit import direct_inherit_parents , for_each_inherit
36
37
from .misc import Sentinel , chunks , parse_version , version_gte
@@ -1423,7 +1424,7 @@ def delete_unused(cr, *xmlids, **kwargs):
1423
1424
return deleted
1424
1425
1425
1426
1426
- def replace_record_references (cr , old , new , replace_xmlid = True ):
1427
+ def replace_record_references (cr , old , new , replace_xmlid = True , parent_field = "parent_id" ):
1427
1428
"""
1428
1429
Replace all (in)direct references of a record by another.
1429
1430
@@ -1436,10 +1437,12 @@ def replace_record_references(cr, old, new, replace_xmlid=True):
1436
1437
if not old [1 ]:
1437
1438
return None
1438
1439
1439
- return replace_record_references_batch (cr , {old [1 ]: new [1 ]}, old [0 ], new [0 ], replace_xmlid )
1440
+ return replace_record_references_batch (cr , {old [1 ]: new [1 ]}, old [0 ], new [0 ], replace_xmlid , parent_field )
1440
1441
1441
1442
1442
- def replace_record_references_batch (cr , id_mapping , model_src , model_dst = None , replace_xmlid = True , ignores = ()):
1443
+ def replace_record_references_batch (
1444
+ cr , id_mapping , model_src , model_dst = None , replace_xmlid = True , ignores = (), parent_field = "parent_id"
1445
+ ):
1443
1446
"""
1444
1447
Replace all references to records.
1445
1448
@@ -1456,6 +1459,9 @@ def replace_record_references_batch(cr, id_mapping, model_src, model_dst=None, r
1456
1459
the source records
1457
1460
:param list(str) ignores: list of **table** names to skip when updating the referenced
1458
1461
values
1462
+ :paream str parent_field: when the target and source model are the same, and the model
1463
+ table has `parent_path` column, this field will be used to
1464
+ update it.
1459
1465
"""
1460
1466
_validate_model (model_src )
1461
1467
if model_dst is None :
@@ -1781,6 +1787,20 @@ def replace_record_references_batch(cr, id_mapping, model_src, model_dst=None, r
1781
1787
)
1782
1788
1783
1789
cr .execute ("DROP TABLE _upgrade_rrr" )
1790
+ if parent_field and model_dst == model_src :
1791
+ if column_exists (cr , model_src_table , "parent_path" ):
1792
+ fk_target = target_of (cr , model_src_table , parent_field )
1793
+ if fk_target :
1794
+ if fk_target [0 ] != model_src_table :
1795
+ _logger .warning (
1796
+ "`%s` has a `parent_path` but `%s` is not a self-referencing FK" , model_src_table , parent_field
1797
+ )
1798
+ else :
1799
+ update_parent_path (cr , model_src , parent_field )
1800
+ elif parent_field != "parent_id" : # check non-default value
1801
+ _logger .error ("`%s` in `%s` is not a self-referencing FK" , parent_field , model_src_table )
1802
+ elif column_exists (cr , model_src_table , "parent_left" ):
1803
+ _logger .warning ("Possibly missing update of parent_left/right in `%s`" , model_src_table )
1784
1804
1785
1805
1786
1806
def replace_in_all_jsonb_values (cr , table , column , old , new , extra_filter = None ):
@@ -1935,3 +1955,43 @@ def _remove_redundant_tcalls(cr, match):
1935
1955
vid ,
1936
1956
match ,
1937
1957
)
1958
+
1959
+
1960
+ def update_parent_path (cr , model , parent_field = "parent_id" ):
1961
+ """
1962
+ Trigger the update of parent paths in a model.
1963
+
1964
+ :meta private: exclude from online docs
1965
+ """
1966
+ if not version_gte ("saas~11.3" ):
1967
+ _logger .error ("parent_left and parent_right must be computed via the ORM" )
1968
+ return
1969
+ table = table_of_model (cr , model )
1970
+ name_field = "name" if column_exists (cr , table , "name" ) else "id"
1971
+ break_recursive_loops (cr , model , parent_field , name_field )
1972
+ query = format_query (
1973
+ cr ,
1974
+ """
1975
+ WITH RECURSIVE __parent_store_compute(id, parent_path) AS (
1976
+ SELECT row.id,
1977
+ concat(row.id, '/')
1978
+ FROM {table} row
1979
+ WHERE row.{parent_field} IS NULL
1980
+
1981
+ UNION
1982
+
1983
+ SELECT row.id,
1984
+ concat(comp.parent_path, row.id, '/')
1985
+ FROM {table} row
1986
+ JOIN __parent_store_compute comp
1987
+ ON row.{parent_field} = comp.id
1988
+ )
1989
+ UPDATE {table} row
1990
+ SET parent_path = comp.parent_path
1991
+ FROM __parent_store_compute comp
1992
+ WHERE row.id = comp.id
1993
+ """ ,
1994
+ table = table ,
1995
+ parent_field = parent_field ,
1996
+ )
1997
+ cr .execute (query )
0 commit comments