Skip to content

Commit 7ed53e2

Browse files
apeterschrabyrd
authored andcommitted
fixes #9019, #9021, #9026 in stable/7.1.1
1 parent 75ce8f7 commit 7ed53e2

File tree

2 files changed

+126
-118
lines changed

2 files changed

+126
-118
lines changed

arches/app/models/concept.py

Lines changed: 108 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
from django.utils.translation import ugettext as _
3333
from django.utils.translation import get_language
3434
from django.db import IntegrityError
35+
from psycopg2.extensions import AsIs
36+
3537
import logging
3638

3739

@@ -505,13 +507,12 @@ def get_child_edges(
505507
except:
506508
return []
507509

508-
languageid = get_language() if languageid is None else languageid
510+
# this interpolation is safe because `relationtypes` is hardcoded in all calls, and not accessible via the API
509511
relationtypes = " or ".join(["r.relationtype = '%s'" % (relationtype) for relationtype in relationtypes])
510-
depth_limit = "and depth < %s" % depth_limit if depth_limit else ""
511-
child_valuetypes = ("','").join(
512-
child_valuetypes if child_valuetypes else models.DValueType.objects.filter(category="label").values_list("valuetype", flat=True)
513-
)
514-
limit_clause = " limit %s offset %s" % (limit, offset) if offset is not None else ""
512+
offset_clause = " limit %(limit)s offset %(offset)s" if offset else ""
513+
depth_clause = " and depth < %(depth_limit)s" if depth_limit else ""
514+
515+
cursor = connection.cursor()
515516

516517
if order_hierarchically:
517518
sql = """
@@ -525,9 +526,9 @@ def get_child_edges(
525526
WHERE conceptid=r.conceptidto
526527
AND valuetype in ('prefLabel')
527528
ORDER BY (
528-
CASE WHEN languageid = '{languageid}' THEN 10
529-
WHEN languageid like '{short_languageid}%' THEN 5
530-
WHEN languageid like '{default_languageid}%' THEN 2
529+
CASE WHEN languageid = %(languageid)s THEN 10
530+
WHEN languageid like %(short_languageid)s THEN 5
531+
WHEN languageid like %(default_languageid)s THEN 2
531532
ELSE 0
532533
END
533534
) desc limit 1
@@ -547,8 +548,8 @@ def get_child_edges(
547548
limit 1
548549
) as collector
549550
FROM relations r
550-
WHERE r.conceptidfrom = '{conceptid}'
551-
and ({relationtypes})
551+
WHERE r.conceptidfrom = %(conceptid)s
552+
and (%(relationtypes)s)
552553
ORDER BY sortorder, valuesto
553554
)
554555
UNION
@@ -559,9 +560,9 @@ def get_child_edges(
559560
WHERE conceptid=r.conceptidto
560561
AND valuetype in ('prefLabel')
561562
ORDER BY (
562-
CASE WHEN languageid = '{languageid}' THEN 10
563-
WHEN languageid like '{short_languageid}%' THEN 5
564-
WHEN languageid like '{default_languageid}%' THEN 2
563+
CASE WHEN languageid = %(languageid)s THEN 10
564+
WHEN languageid like %(short_languageid)s THEN 5
565+
WHEN languageid like %(default_languageid)s THEN 2
565566
ELSE 0
566567
END
567568
) desc limit 1
@@ -582,7 +583,7 @@ def get_child_edges(
582583
) as collector
583584
FROM relations r
584585
JOIN ordered_relationships b ON(b.conceptidto = r.conceptidfrom)
585-
WHERE ({relationtypes})
586+
WHERE (%(relationtypes)s)
586587
ORDER BY sortorder, valuesto
587588
)
588589
),
@@ -593,17 +594,17 @@ def get_child_edges(
593594
r.collector,
594595
1 AS depth ---|NonRecursive Part
595596
FROM ordered_relationships r
596-
WHERE r.conceptidfrom = '{conceptid}'
597-
and ({relationtypes})
597+
WHERE r.conceptidfrom = %(conceptid)s
598+
and (%(relationtypes)s)
598599
UNION
599600
SELECT r.conceptidfrom, r.conceptidto,
600601
row || '-' || to_char(row_number() OVER (), 'fm000000'),
601602
r.collector,
602603
depth+1 ---|RecursivePart
603604
FROM ordered_relationships r
604605
JOIN children b ON(b.conceptidto = r.conceptidfrom)
605-
WHERE ({relationtypes})
606-
{depth_limit}
606+
WHERE (%(relationtypes)s)
607+
{depth_clause}
607608
)
608609
609610
{subquery}
@@ -614,70 +615,73 @@ def get_child_edges(
614615
FROM (
615616
SELECT *
616617
FROM values
617-
WHERE conceptid={recursive_table}.conceptidto
618+
WHERE conceptid=%(recursive_table)s.conceptidto
618619
AND valuetype in ('prefLabel')
619620
ORDER BY (
620-
CASE WHEN languageid = '{languageid}' THEN 10
621-
WHEN languageid like '{short_languageid}%' THEN 5
622-
WHEN languageid like '{default_languageid}%' THEN 2
621+
CASE WHEN languageid = %(languageid)s THEN 10
622+
WHEN languageid like %(short_languageid)s THEN 5
623+
WHEN languageid like %(default_languageid)s THEN 2
623624
ELSE 0
624625
END
625626
) desc limit 1
626627
) d
627628
) as valueto,
628629
depth, collector, count(*) OVER() AS full_count
629630
630-
FROM {recursive_table} order by row {limit_clause};
631-
631+
FROM %(recursive_table)s order by row {offset_clause};
632632
"""
633633

634-
subquery = (
635-
""", results as (
636-
SELECT c.conceptidfrom, c.conceptidto, c.row, c.depth, c.collector
637-
FROM children c
638-
JOIN values ON(values.conceptid = c.conceptidto)
639-
WHERE LOWER(values.value) like '%%%s%%'
640-
AND values.valuetype in ('prefLabel')
641-
UNION
642-
SELECT c.conceptidfrom, c.conceptidto, c.row, c.depth, c.collector
643-
FROM children c
644-
JOIN results r on (r.conceptidfrom=c.conceptidto)
645-
)"""
646-
% query.lower()
647-
if query is not None
648-
else ""
649-
)
634+
if query:
635+
subquery = """
636+
, results as (
637+
SELECT c.conceptidfrom, c.conceptidto, c.row, c.depth, c.collector
638+
FROM children c
639+
JOIN values ON(values.conceptid = c.conceptidto)
640+
WHERE LOWER(values.value) like %(query)s
641+
AND values.valuetype in ('prefLabel')
642+
UNION
643+
SELECT c.conceptidfrom, c.conceptidto, c.row, c.depth, c.collector
644+
FROM children c
645+
JOIN results r on (r.conceptidfrom=c.conceptidto)
646+
)
647+
"""
648+
else:
649+
subquery = ""
650+
651+
sql = sql.format(subquery=subquery, offset_clause=offset_clause, depth_clause=depth_clause)
650652

651653
recursive_table = "results" if query else "children"
654+
languageid = get_language() if languageid is None else languageid
652655

653-
sql = sql.format(
654-
conceptid=conceptid,
655-
relationtypes=relationtypes,
656-
child_valuetypes=child_valuetypes,
657-
parent_valuetype=parent_valuetype,
658-
depth_limit=depth_limit,
659-
limit_clause=limit_clause,
660-
subquery=subquery,
661-
recursive_table=recursive_table,
662-
languageid=languageid,
663-
short_languageid=languageid.split("-")[0],
664-
default_languageid=settings.LANGUAGE_CODE,
656+
cursor.execute(
657+
sql,
658+
{
659+
"conceptid": conceptid,
660+
"relationtypes": AsIs(relationtypes),
661+
"depth_limit": depth_limit,
662+
"limit": limit,
663+
"offset": offset,
664+
"query": "%" + query.lower() + "%",
665+
"recursive_table": AsIs(recursive_table),
666+
"languageid": languageid,
667+
"short_languageid": languageid.split("-")[0] + "%",
668+
"default_languageid": settings.LANGUAGE_CODE + "%",
669+
},
665670
)
666-
667671
else:
668672
sql = """
669673
WITH RECURSIVE
670674
children AS (
671675
SELECT r.conceptidfrom, r.conceptidto, r.relationtype, 1 AS depth
672676
FROM relations r
673-
WHERE r.conceptidfrom = '{conceptid}'
674-
AND ({relationtypes})
677+
WHERE r.conceptidfrom = %(conceptid)s
678+
AND (%(relationtypes)s)
675679
UNION
676680
SELECT r.conceptidfrom, r.conceptidto, r.relationtype, depth+1
677681
FROM relations r
678682
JOIN children c ON(c.conceptidto = r.conceptidfrom)
679-
WHERE ({relationtypes})
680-
{depth_limit}
683+
WHERE (%(relationtypes)s)
684+
{depth_clause}
681685
),
682686
results AS (
683687
SELECT
@@ -692,14 +696,15 @@ def get_child_edges(
692696
JOIN children c ON(c.conceptidto = valueto.conceptid)
693697
JOIN values valuefrom ON(c.conceptidfrom = valuefrom.conceptid)
694698
JOIN d_value_types dtypesfrom ON(dtypesfrom.valuetype = valuefrom.valuetype)
695-
WHERE valueto.valuetype in ('{child_valuetypes}')
696-
AND valuefrom.valuetype in ('{child_valuetypes}')
699+
WHERE valueto.valuetype in (%(child_valuetypes)s)
700+
AND valuefrom.valuetype in (%(child_valuetypes)s)
697701
)
698-
SELECT distinct {columns}
699-
FROM results {limit_clause}
700-
702+
SELECT distinct %(columns)s
703+
FROM results {offset_clause}
701704
"""
702705

706+
sql = sql.format(offset_clause=offset_clause, depth_clause=depth_clause)
707+
703708
if not columns:
704709
columns = """
705710
conceptidfrom::text, conceptidto::text,
@@ -710,19 +715,24 @@ def get_child_edges(
710715
categoryfrom, categoryto
711716
"""
712717

713-
sql = sql.format(
714-
conceptid=conceptid,
715-
relationtypes=relationtypes,
716-
child_valuetypes=child_valuetypes,
717-
columns=columns,
718-
depth_limit=depth_limit,
719-
limit_clause=limit_clause,
718+
cursor.execute(
719+
sql,
720+
{
721+
"conceptid": conceptid,
722+
"relationtypes": AsIs(relationtypes),
723+
"child_valuetypes": ("','").join(
724+
child_valuetypes
725+
if child_valuetypes
726+
else models.DValueType.objects.filter(category="label").values_list("valuetype", flat=True)
727+
),
728+
"columns": AsIs(columns),
729+
"depth_limit": depth_limit,
730+
"limit": limit,
731+
"offset": offset,
732+
},
720733
)
721734

722-
cursor = connection.cursor()
723-
cursor.execute(sql)
724-
rows = cursor.fetchall()
725-
return rows
735+
return cursor.fetchall()
726736

727737
def traverse(self, func, direction="down", scope=None, **kwargs):
728738
"""
@@ -1176,30 +1186,31 @@ def get_e55_domain(self, conceptid):
11761186
11771187
"""
11781188
cursor = connection.cursor()
1179-
1180-
sql = """
1181-
WITH RECURSIVE children AS (
1182-
SELECT d.conceptidfrom, d.conceptidto, c2.value, c2.valueid as valueid, c.value as valueto, c.valueid as valueidto, c.valuetype as vtype, 1 AS depth, array[d.conceptidto] AS conceptpath, array[c.valueid] AS idpath ---|NonRecursive Part
1183-
FROM relations d
1184-
JOIN values c ON(c.conceptid = d.conceptidto)
1185-
JOIN values c2 ON(c2.conceptid = d.conceptidfrom)
1186-
WHERE d.conceptidfrom = '{0}'
1187-
and c2.valuetype = 'prefLabel'
1188-
and c.valuetype in ('prefLabel', 'sortorder', 'collector')
1189-
and (d.relationtype = 'member' or d.relationtype = 'hasTopConcept')
1190-
UNION
1191-
SELECT d.conceptidfrom, d.conceptidto, v2.value, v2.valueid as valueid, v.value as valueto, v.valueid as valueidto, v.valuetype as vtype, depth+1, (conceptpath || d.conceptidto), (idpath || v.valueid) ---|RecursivePart
1192-
FROM relations d
1193-
JOIN children b ON(b.conceptidto = d.conceptidfrom)
1194-
JOIN values v ON(v.conceptid = d.conceptidto)
1195-
JOIN values v2 ON(v2.conceptid = d.conceptidfrom)
1196-
WHERE v2.valuetype = 'prefLabel'
1197-
and v.valuetype in ('prefLabel','sortorder', 'collector')
1198-
and (d.relationtype = 'member' or d.relationtype = 'hasTopConcept')
1199-
) SELECT conceptidfrom::text, conceptidto::text, value, valueid::text, valueto, valueidto::text, depth, idpath::text, conceptpath::text, vtype FROM children ORDER BY depth, conceptpath;
1200-
""".format(
1201-
conceptid
1189+
cursor.execute(
1190+
"""
1191+
WITH RECURSIVE children AS (
1192+
SELECT d.conceptidfrom, d.conceptidto, c2.value, c2.valueid as valueid, c.value as valueto, c.valueid as valueidto, c.valuetype as vtype, 1 AS depth, array[d.conceptidto] AS conceptpath, array[c.valueid] AS idpath ---|NonRecursive Part
1193+
FROM relations d
1194+
JOIN values c ON(c.conceptid = d.conceptidto)
1195+
JOIN values c2 ON(c2.conceptid = d.conceptidfrom)
1196+
WHERE d.conceptidfrom = %s
1197+
and c2.valuetype = 'prefLabel'
1198+
and c.valuetype in ('prefLabel', 'sortorder', 'collector')
1199+
and (d.relationtype = 'member' or d.relationtype = 'hasTopConcept')
1200+
UNION
1201+
SELECT d.conceptidfrom, d.conceptidto, v2.value, v2.valueid as valueid, v.value as valueto, v.valueid as valueidto, v.valuetype as vtype, depth+1, (conceptpath || d.conceptidto), (idpath || v.valueid) ---|RecursivePart
1202+
FROM relations d
1203+
JOIN children b ON(b.conceptidto = d.conceptidfrom)
1204+
JOIN values v ON(v.conceptid = d.conceptidto)
1205+
JOIN values v2 ON(v2.conceptid = d.conceptidfrom)
1206+
WHERE v2.valuetype = 'prefLabel'
1207+
and v.valuetype in ('prefLabel','sortorder', 'collector')
1208+
and (d.relationtype = 'member' or d.relationtype = 'hasTopConcept')
1209+
) SELECT conceptidfrom::text, conceptidto::text, value, valueid::text, valueto, valueidto::text, depth, idpath::text, conceptpath::text, vtype FROM children ORDER BY depth, conceptpath;
1210+
""",
1211+
[conceptid],
12021212
)
1213+
rows = cursor.fetchall()
12031214

12041215
column_names = [
12051216
"conceptidfrom",
@@ -1213,8 +1224,6 @@ def get_e55_domain(self, conceptid):
12131224
"conceptpath",
12141225
"vtype",
12151226
]
1216-
cursor.execute(sql)
1217-
rows = cursor.fetchall()
12181227

12191228
class Val(object):
12201229
def __init__(self, conceptid):

arches/app/views/concept.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,7 @@ def dropdown(request):
380380

381381
def paged_dropdown(request):
382382
conceptid = request.GET.get("conceptid")
383-
query = request.GET.get("query", None)
384-
query = None if query == "" else query
383+
query = request.GET.get("query", "")
385384
page = int(request.GET.get("page", 1))
386385
limit = 50
387386
offset = (page - 1) * limit
@@ -405,25 +404,25 @@ def paged_dropdown(request):
405404
found = True
406405
break
407406
if not found:
408-
sql = """
409-
SELECT value, valueid
410-
FROM
411-
(
412-
SELECT *, CASE WHEN LOWER(languageid) = '{languageid}' THEN 10
413-
WHEN LOWER(languageid) like '{short_languageid}%' THEN 5
414-
ELSE 0
415-
END score
416-
FROM values
417-
) as vals
418-
WHERE LOWER(value)='{query}' AND score > 0
419-
AND valuetype in ('prefLabel')
420-
ORDER BY score desc limit 1
421-
"""
422-
423407
languageid = get_language().lower()
424-
sql = sql.format(query=query.lower(), languageid=languageid, short_languageid=languageid.split("-")[0])
425408
cursor = connection.cursor()
426-
cursor.execute(sql)
409+
cursor.execute(
410+
"""
411+
SELECT value, valueid
412+
FROM
413+
(
414+
SELECT *, CASE WHEN LOWER(languageid) = %(languageid)s THEN 10
415+
WHEN LOWER(languageid) like %(short_languageid)s THEN 5
416+
ELSE 0
417+
END score
418+
FROM values
419+
) as vals
420+
WHERE LOWER(value)=%(query)s AND score > 0
421+
AND valuetype in ('prefLabel')
422+
ORDER BY score desc limit 1
423+
""",
424+
{"languageid": languageid, "short_languageid": languageid.split("-")[0] + "%", "query": query.lower()},
425+
)
427426
rows = cursor.fetchall()
428427

429428
if len(rows) == 1:

0 commit comments

Comments
 (0)