Skip to content

Commit 8edf672

Browse files
committed
[IMP] util.uniq_tags
Rewrite function to use `replace_record_references_batch`. closes #274 Signed-off-by: Christophe Simonis (chs) <[email protected]>
1 parent 4d8a67f commit 8edf672

File tree

1 file changed

+20
-71
lines changed

1 file changed

+20
-71
lines changed

src/util/data.py

Lines changed: 20 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# -*- coding: utf-8 -*-
22
import 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

10150
def split_group(cr, from_groups, to_group):

0 commit comments

Comments
 (0)