11# -*- coding: utf-8 -*-
22import logging
33
4- from .helpers import model_of_table , table_of_model
5- from .pg import get_columns , get_fk , table_exists
6- from .records import ref
4+ from .helpers import table_of_model
5+ from .pg import SQLStr , format_query , table_exists
6+ from .records import ref , remove_records , replace_record_references_batch
77
88_logger = logging .getLogger (__name__ .rpartition ("." )[0 ])
99
@@ -25,77 +25,26 @@ def uniq_tags(cr, model, uniq_column="name", order="id"):
2525 you can prioritize tags in CamelCase/UPPERCASE.
2626 """
2727 table = table_of_model (cr , model )
28- upds = []
29- for ft , fc , _ , da in get_fk (cr , table ):
30- cols = get_columns (cr , ft , ignore = (fc ,))
31- is_many2one = False
32- is_many2many = da == "c" and len (cols ) == 1 # if ondelete=cascade fk and only 2 columns, it's a m2m
33- if not is_many2many :
34- cr .execute ("SELECT count(*) FROM ir_model_fields WHERE ttype = 'many2many' AND relation_table = %s" , [ft ])
35- [is_many2many ] = cr .fetchone ()
36- if not is_many2many :
37- f_model = model_of_table (cr , ft )
38- if f_model :
39- cr .execute (
40- """
41- SELECT count(*)
42- FROM ir_model_fields
43- WHERE model = %s
44- AND name = %s
45- AND ttype = 'many2one'
46- """ ,
47- [f_model , fc ],
48- )
49- [is_many2one ] = cr .fetchone ()
50- assert is_many2many or is_many2one , (
51- "Can't determine if column `%s` of table `%s` is a many2one or many2many" % (fc , ft )
52- )
53- if is_many2many :
54- upds .append (
55- """
56- INSERT INTO {rel}({c1}, {c2})
57- SELECT r.{c1}, d.id
58- FROM {rel} r
59- JOIN dups d ON (r.{c2} = ANY(d.others))
60- EXCEPT
61- SELECT r.{c1}, r.{c2}
62- FROM {rel} r
63- JOIN dups d ON (r.{c2} = d.id)
64- """ .format (rel = ft , c1 = cols [0 ], c2 = fc )
65- )
66- else :
67- upds .append (
68- """
69- UPDATE {rel} r
70- SET {c} = d.id
71- FROM dups d
72- WHERE r.{c} = ANY(d.others)
73- """ .format (rel = ft , c = fc )
74- )
75-
76- assert upds # if not m2m found, there is something wrong...
77-
78- updates = "," .join ("_upd_%s AS (%s)" % x for x in enumerate (upds ))
79- query = """
80- WITH dups AS (
81- SELECT (array_agg(id order by {order}))[1] as id,
82- (array_agg(id order by {order}))[2:array_length(array_agg(id), 1)] as others
28+
29+ query = format_query (
30+ cr ,
31+ """
32+ SELECT unnest((array_agg(id ORDER BY {order}))[2:]),
33+ (array_agg(id ORDER BY {order}))[1]
8334 FROM {table}
8435 GROUP BY {uniq_column}
8536 HAVING count(id) > 1
86- ),
87- _upd_imd AS (
88- UPDATE ir_model_data x
89- SET res_id = d.id
90- FROM dups d
91- WHERE x.model = %s
92- AND x.res_id = ANY(d.others)
93- ),
94- {updates}
95- DELETE FROM {table} WHERE id IN (SELECT unnest(others) FROM dups)
96- """ .format (** locals ())
97-
98- cr .execute (query , [model ])
37+ """ ,
38+ table = table ,
39+ order = SQLStr (order ),
40+ uniq_column = SQLStr (uniq_column ),
41+ )
42+ cr .execute (query )
43+ if not cr .rowcount :
44+ return
45+ mapping = dict (cr .fetchall ())
46+ replace_record_references_batch (cr , mapping , model )
47+ remove_records (cr , model , mapping .keys ())
9948
10049
10150def split_group (cr , from_groups , to_group ):
0 commit comments