Skip to content

Commit 81e900d

Browse files
committed
[FIX] util.{remove_records,replace_record_references_batch}
Correctly handle changes in company dependent jsonb columns. The injected Json should be escaped before query explosion. Also use `cr.mogrify` instead of manual formatting of the jsonpath argument of the query.
1 parent a402a8d commit 81e900d

File tree

1 file changed

+52
-32
lines changed

1 file changed

+52
-32
lines changed

src/util/records.py

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from operator import itemgetter
1010

1111
import lxml
12+
from psycopg2 import sql
1213
from psycopg2.extras import Json, execute_values
1314

1415
try:
@@ -414,29 +415,38 @@ def remove_records(cr, model, ids):
414415
query = 'DELETE FROM "{}" WHERE {} AND "{}" IN %s'.format(ir.table, ir.model_filter(), ir.res_id)
415416
cr.execute(query, [model, ids])
416417
elif ir.company_dependent_comodel == model:
417-
query = cr.mogrify(
418-
format_query(
419-
cr,
420-
"""
418+
json_path = cr.mogrify(
419+
"$.* ? ({})".format(" || ".join(["@ == %s"] * len(ids))),
420+
ids,
421+
).decode()
422+
query = (
423+
cr.mogrify(
424+
format_query(
425+
cr,
426+
"""
421427
UPDATE {table}
422-
SET {column} = (
423-
SELECT jsonb_object_agg(
424-
key,
425-
CASE
426-
WHEN value::int4 IN %s THEN NULL
427-
ELSE value::int4
428-
END)
429-
FROM jsonb_each_text({column})
430-
)
431-
WHERE {column} IS NOT NULL
432-
AND {column} @? %s
433-
AND {{parallel_filter}}
428+
SET {column} = (
429+
SELECT jsonb_object_agg(
430+
key,
431+
CASE
432+
WHEN value::int4 IN %s THEN NULL
433+
ELSE value::int4
434+
END)
435+
FROM jsonb_each_text({column})
436+
)
437+
WHERE {column} IS NOT NULL
438+
AND {column} @? {json_path}
434439
""",
435-
table=ir.table,
436-
column=ir.res_id,
437-
),
438-
[ids, "$.* ? ({})".format(" || ".join(map("@ == {}".format, ids)))],
439-
).decode()
440+
table=ir.table,
441+
column=ir.res_id,
442+
json_path=sql.Literal(json_path),
443+
),
444+
[ids],
445+
)
446+
.decode()
447+
.replace("{", "{{")
448+
.replace("}", "}}")
449+
)
440450
explode_execute(cr, query, table=ir.table)
441451
_rm_refs(cr, model, ids)
442452

@@ -1469,24 +1479,34 @@ def replace_record_references_batch(cr, id_mapping, model_src, model_dst=None, r
14691479
if ir.company_dependent_comodel:
14701480
if ir.company_dependent_comodel == model_src:
14711481
assert model_src == model_dst
1472-
query = cr.mogrify(
1473-
format_query(
1474-
cr,
1475-
"""
1482+
json_path = cr.mogrify(
1483+
"$.* ? ({})".format(" || ".join(["@ == %s"] * len(id_mapping))),
1484+
list(id_mapping),
1485+
).decode()
1486+
1487+
query = (
1488+
cr.mogrify(
1489+
format_query(
1490+
cr,
1491+
"""
14761492
UPDATE {table}
14771493
SET {column} = (
14781494
SELECT jsonb_object_agg(key, COALESCE((%s::jsonb->>value)::int, value::int))
14791495
FROM jsonb_each_text({column})
14801496
)
14811497
WHERE {column} IS NOT NULL
1482-
AND {column} @? %s
1483-
AND {{parallel_filter}}
1498+
AND {column} @? {json_path}
14841499
""",
1485-
table=ir.table,
1486-
column=ir.res_id,
1487-
),
1488-
[Json(id_mapping), "$.* ? ({})".format(" || ".join(map("@ == {}".format, id_mapping)))],
1489-
).decode()
1500+
table=ir.table,
1501+
column=ir.res_id,
1502+
json_path=sql.Literal(json_path),
1503+
),
1504+
[Json(id_mapping)],
1505+
)
1506+
.decode()
1507+
.replace("{", "{{")
1508+
.replace("}", "}}")
1509+
)
14901510
explode_execute(cr, query, table=ir.table)
14911511
continue
14921512
res_model_upd = []

0 commit comments

Comments
 (0)