diff -Naur --exclude='*.pyc' --exclude='*.~*' --exclude=build roundup-1.4.21/roundup/backends/back_postgresql.py roundup-1.4.21.like/roundup/backends/back_postgresql.py --- roundup-1.4.21/roundup/backends/back_postgresql.py 2012-04-12 03:29:34.000000000 -0700 +++ roundup-1.4.21.like/roundup/backends/back_postgresql.py 2013-05-09 08:40:34.437013352 -0700 @@ -285,6 +285,7 @@ class PostgresqlClass: order_by_null_values = '(%s is not NULL)' + case_insensitive_like = 'ILIKE' class Class(PostgresqlClass, rdbms_common.Class): pass diff -Naur --exclude='*.pyc' --exclude='*.~*' --exclude=build roundup-1.4.21/roundup/backends/rdbms_common.py roundup-1.4.21.like/roundup/backends/rdbms_common.py --- roundup-1.4.21/roundup/backends/rdbms_common.py 2012-08-16 10:49:10.000000000 -0700 +++ roundup-1.4.21.like/roundup/backends/rdbms_common.py 2013-05-09 08:39:54.143013468 -0700 @@ -2317,6 +2317,10 @@ multilink_table, ','.join([self.db.arg] * len(v))) return where, v, True # True to indicate original + # Many databases treat LIKE ignoring case. Postgres and Oracle have + # an ILIKE operator to support this. + case_insensitive_like = 'LIKE' + def _filter_sql (self, search_matches, filterspec, srt=[], grp=[], retr=0): """ Compute the proptree and the SQL/ARGS for a filter. For argument description see filter below. @@ -2434,7 +2438,11 @@ # now add to the where clause where.append('(' - +' and '.join(["_%s._%s LIKE '%s'"%(pln, k, s) for s in v]) + +' and '.join(["_%s._%s %s '%s'"%( + pln, + k, + self.case_insensitive_like, + s) for s in v]) +')') # note: args are embedded in the query string now if 'sort' in p.need_for: diff -Naur --exclude='*.pyc' --exclude='*.~*' --exclude=build roundup-1.4.21/test/db_test_base.py roundup-1.4.21.like/test/db_test_base.py --- roundup-1.4.21/test/db_test_base.py 2012-12-21 02:50:14.000000000 -0800 +++ roundup-1.4.21.like/test/db_test_base.py 2013-05-09 08:19:54.755014541 -0700 @@ -1237,6 +1237,23 @@ ae(filt(None, {'title': ['one', 'two']}, ('+','id'), (None,None)), []) + def testFilteringStringCase(self): + """ + Similar to testFilteringString except the search parameters + have different capitalization. + """ + ae, filter, filter_iter = self.filteringSetup() + for filt in filter, filter_iter: + ae(filt(None, {'title': ['One']}, ('+','id'), (None,None)), ['1']) + ae(filt(None, {'title': ['Issue One']}, ('+','id'), (None,None)), + ['1']) + ae(filt(None, {'title': ['ISSUE', 'ONE']}, ('+','id'), (None,None)), + ['1']) + ae(filt(None, {'title': ['iSSUE']}, ('+','id'), (None,None)), + ['1','2','3']) + ae(filt(None, {'title': ['One', 'Two']}, ('+','id'), (None,None)), + []) + def testFilteringLink(self): ae, filter, filter_iter = self.filteringSetup() a = 'assignedto'