Skip to content

Commit 3329b64

Browse files
stsnelalanking
authored andcommitted
[#234] Implement case-insensitive queries
1 parent bb03bb5 commit 3329b64

5 files changed

Lines changed: 294 additions & 15 deletions

File tree

README.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,16 @@ In this case since we are expecting only one row we can directly call ``query.ex
746746
| rods | 14 | 62262 |
747747
+--------------+-----------+-----------+
748748

749+
For a case-insensitive query, add a `case_sensitive=False` parameter to the query:
750+
751+
>>> with iRODSSession(irods_env_file=env_file) as session:
752+
... query = session.query(DataObject.name, case_sensitive=False).filter(Like(DataObject.name, "%oBjEcT"))
753+
... print(query.all())
754+
+---------------------+
755+
| DATA_NAME |
756+
+---------------------+
757+
| caseSENSITIVEobject |
758+
+---------------------+
749759

750760
Specific Queries
751761
----------------

irods/column.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,23 @@ class Criterion(object):
3333
def __init__(self, op, query_key, value):
3434
self.op = op
3535
self.query_key = query_key
36-
self._value = value
36+
self.value = value
3737

3838
@property
39-
def value(self):
40-
return self.query_key.column_type.to_irods(self._value)
39+
def irods_value(self):
40+
return self.query_key.column_type.to_irods(self.value)
41+
4142

4243
class In(Criterion):
4344

4445
def __init__(self, query_key, value):
4546
super(In, self).__init__('in', query_key, value)
4647

4748
@property
48-
def value(self):
49+
def irods_value(self):
4950
v = "("
5051
comma = ""
51-
for element in self._value:
52+
for element in self.value:
5253
v += "{}'{}'".format(comma,element)
5354
comma = ","
5455
v += ")"
@@ -72,8 +73,8 @@ def __init__(self, query_key, value):
7273
super(Between, self).__init__('between', query_key, value)
7374

7475
@property
75-
def value(self):
76-
lower_bound, upper_bound = self._value
76+
def irods_value(self):
77+
lower_bound, upper_bound = self.value
7778
return "{} {}".format(self.query_key.column_type.to_irods(lower_bound),
7879
self.query_key.column_type.to_irods(upper_bound))
7980

irods/query.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ def __init__(self, sess, *args, **kwargs):
3333
self.sess = sess
3434
self.columns = OrderedDict()
3535
self.criteria = []
36+
self.case_sensitive = kwargs.pop('case_sensitive', True)
3637
self._limit = -1
3738
self._offset = 0
3839
self._continue_index = 0
@@ -52,6 +53,7 @@ def _clone(self):
5253
new_q = Query(self.sess)
5354
new_q.columns = self.columns
5455
new_q.criteria = self.criteria
56+
new_q.case_sensitive = self.case_sensitive
5557
new_q._limit = self._limit
5658
new_q._offset = self._offset
5759
new_q._continue_index = self._continue_index
@@ -65,7 +67,28 @@ def add_keyword(self, keyword, value = ''):
6567

6668
def filter(self, *criteria):
6769
new_q = self._clone()
68-
new_q.criteria += list(criteria)
70+
71+
if self.case_sensitive:
72+
new_q.criteria += list(criteria)
73+
else:
74+
# In case-insensitive mode, all criterion values are converted
75+
# to uppercase here, and the UPPER_CASE_WHERE option is enabled
76+
# when creating a new GenQueryRequest in the _message function.
77+
# Converting both keys and values to uppercase results in
78+
# case-insensitive queries.
79+
for criterion in criteria:
80+
if type(criterion.value) == str:
81+
criterion.value = str.upper(
82+
criterion.value)
83+
elif type(criterion.value) == list:
84+
criterion.value = [str.upper(c) if type(c) == str
85+
else c for c in criterion.value]
86+
elif type(criterion.value) == tuple:
87+
criterion.value = tuple(
88+
[str.upper(c) if type(c) == str else c for c in
89+
list(criterion.value)])
90+
new_q.criteria.append(criterion)
91+
6992
return new_q
7093

7194
def order_by(self, column, order='asc'):
@@ -132,7 +155,7 @@ def _select_message(self):
132155
# lists
133156
def _conds_message(self):
134157
dct = _OrderedMultiMapping([
135-
(criterion.query_key.icat_id, criterion.op + ' ' + criterion.value)
158+
(criterion.query_key.icat_id, criterion.op + ' ' + criterion.irods_value)
136159
for criterion in self.criteria
137160
if isinstance(criterion.query_key, Column)
138161
])
@@ -141,7 +164,7 @@ def _conds_message(self):
141164
def _kw_message(self):
142165
dct = dict([
143166
(criterion.query_key.icat_key,
144-
criterion.op + ' ' + criterion.value)
167+
criterion.op + ' ' + criterion.irods_value)
145168
for criterion in self.criteria
146169
if isinstance(criterion.query_key, Keyword)
147170
])
@@ -155,7 +178,7 @@ def _message(self):
155178
'maxRows': max_rows,
156179
'continueInx': self._continue_index,
157180
'partialStartIndex': self._offset,
158-
'options': 0,
181+
'options': 0 if self.case_sensitive else query_number['UPPER_CASE_WHERE'],
159182
'KeyValPair_PI': self._kw_message(),
160183
'InxIvalPair_PI': self._select_message(),
161184
'InxValPair_PI': self._conds_message()

irods/session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ def configure(self, **kwargs):
238238
self.pool.connection_timeout = conn_timeout
239239
return account
240240

241-
def query(self, *args):
242-
return Query(self, *args)
241+
def query(self, *args, **kwargs):
242+
return Query(self, *args, **kwargs)
243243

244244
@property
245245
def username(self):

0 commit comments

Comments
 (0)