Skip to content

Commit 9e27157

Browse files
committed
Internally represent conditions items as a list rather than as a dict
1 parent 4dec2ed commit 9e27157

1 file changed

Lines changed: 44 additions & 33 deletions

File tree

src/icat/query.py

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def __init__(self, client, entity,
200200

201201
self.setAttributes(attributes)
202202
self.setAggregate(aggregate)
203-
self.conditions = dict()
203+
self.conditions = []
204204
self.addConditions(conditions)
205205
self.includes = set()
206206
self.addIncludes(includes)
@@ -276,7 +276,7 @@ def _dosubst(self, obj, subst, addas=True):
276276
def _get_subst(self):
277277
if self._subst is None:
278278
joinattrs = ( self._order_attrs |
279-
set(self.conditions.keys()) |
279+
self._conditions_attrs |
280280
set(self.attributes) )
281281
self._subst = self._makesubst(joinattrs)
282282
return self._subst
@@ -417,7 +417,7 @@ def setOrder(self, order):
417417
for (pattr, attrInfo, rclass) in self._attrpath(item.attr):
418418
if attrInfo.relType == "ONE":
419419
if (not attrInfo.notNullable and
420-
pattr not in self.conditions and
420+
pattr not in self._conditions_attrs and
421421
pattr not in self.join_specs):
422422
sl = 3 if self._init else 2
423423
warn(QueryNullableOrderWarning(pattr),
@@ -445,34 +445,45 @@ def addConditions(self, conditions):
445445
"""Add conditions to the constraints to build the WHERE clause from.
446446
447447
:param conditions: the conditions to restrict the search
448-
result. This must be a mapping of attribute names to
449-
conditions on that attribute. The latter may either be a
450-
string with a single condition or a list of strings to add
451-
more then one condition on a single attribute. The
452-
attribute name (the key of the condition) can be wrapped
453-
with a JPQL function (such as "UPPER(title)"). If the
454-
query already has a condition on a given attribute, the
455-
previous condition(s) will be retained and the new
456-
condition(s) added to that.
457-
:type conditions: :class:`dict`
458-
:raise ValueError: if any key in `conditions` is not valid.
448+
result. This must be a list of tuples with a pair of an
449+
attribute name and a condition on that attribute
450+
respectively. The attribute name may be wrapped with a
451+
JPQL function (such as "UPPER(title)").
452+
453+
For backward compatibility with previous versions, this
454+
may alternatively be a mapping of attribute names to a
455+
(lists of) conditions.
456+
:type conditions: :class:`list` of :class:`tuple` or :class:`dict`
457+
:raise ValueError: if any attribute in `conditions` is not valid.
459458
460459
.. versionchanged:: 0.20.0
461460
allow a JPQL function in the attribute.
461+
462+
.. versionchanged:: 2.0.0
463+
expect a :class:`list` of :class:`tuple` in the
464+
`conditions` argument.
465+
.. deprecated:: 2.0.0
466+
accept a :class:`dict` in the `conditions` argument.
462467
"""
463468
if conditions:
464469
self._subst = None
465-
for k in conditions.keys():
466-
if isinstance(conditions[k], str):
467-
conds = [conditions[k]]
468-
else:
469-
conds = conditions[k]
470-
for rhs in conds:
471-
item = ConditionItem(k, rhs)
472-
for (pattr, attrInfo, rclass) in self._attrpath(item.attr):
473-
pass
474-
l = self.conditions.setdefault(item.attr, [])
475-
l.append(item)
470+
471+
if isinstance(conditions, Mapping):
472+
# Convert the conditions argument to a list of tuples.
473+
conds = []
474+
for obj,v in conditions.items():
475+
if isinstance(v, str):
476+
conds.append( (obj,v) )
477+
else:
478+
for rhs in v:
479+
conds.append( (obj,rhs) )
480+
conditions = conds
481+
482+
for obj,rhs in conditions:
483+
item = ConditionItem(obj, rhs)
484+
for (pattr, attrInfo, rclass) in self._attrpath(item.attr):
485+
pass
486+
self.conditions.append(item)
476487

477488
def addIncludes(self, includes):
478489
"""Add related objects to build the INCLUDE clause from.
@@ -512,6 +523,10 @@ def setLimit(self, limit):
512523
def _order_attrs(self):
513524
return { item.attr for item in self.order }
514525

526+
@property
527+
def _conditions_attrs(self):
528+
return { item.attr for item in self.conditions }
529+
515530
@property
516531
def select_clause(self):
517532
"""The SELECT clause of the query.
@@ -564,11 +579,9 @@ def where_clause(self):
564579
"""
565580
if self.conditions:
566581
subst = self._get_subst()
567-
conds = []
568-
for a in sorted(self.conditions.keys()):
569-
attr = self._dosubst(a, subst, False)
570-
for c in self.conditions[a]:
571-
conds.append(c.formatstr % attr)
582+
sortkey = lambda item: item.attr
583+
conds = [ item.formatstr % self._dosubst(item.attr, subst, False)
584+
for item in sorted(self.conditions, key=sortkey) ]
572585
return "WHERE " + " AND ".join(conds)
573586
else:
574587
return None
@@ -645,9 +658,7 @@ def copy(self):
645658
q.attributes = list(self.attributes)
646659
q.aggregate = self.aggregate
647660
q.order = self.order.copy()
648-
q.conditions = dict()
649-
for k, v in self.conditions.items():
650-
q.conditions[k] = self.conditions[k].copy()
661+
q.conditions = self.conditions.copy()
651662
q.includes = self.includes.copy()
652663
q.limit = self.limit
653664
q.join_specs = self.join_specs.copy()

0 commit comments

Comments
 (0)