Escape underscore char for "contains" query filter
since underscore has special meaning for LIKE clause
This commit is contained in:
		
							parent
							
								
									666c16b74e
								
							
						
					
					
						commit
						d0d568b3a5
					
				
					 1 changed files with 34 additions and 16 deletions
				
			
		|  | @ -2,7 +2,7 @@ | |||
| ################################################################################ | ||||
| # | ||||
| #  Rattail -- Retail Software Framework | ||||
| #  Copyright © 2010-2023 Lance Edgar | ||||
| #  Copyright © 2010-2024 Lance Edgar | ||||
| # | ||||
| #  This file is part of Rattail. | ||||
| # | ||||
|  | @ -484,9 +484,13 @@ class AlchemyStringFilter(AlchemyGridFilter): | |||
|         """ | ||||
|         if value is None or value == '': | ||||
|             return query | ||||
|         return query.filter(sa.and_( | ||||
|             *[self.column.ilike(self.encode_value('%{}%'.format(v))) | ||||
|               for v in value.split()])) | ||||
| 
 | ||||
|         criteria = [] | ||||
|         for val in value.split(): | ||||
|             val = val.replace('_', r'\_') | ||||
|             val = self.encode_value(f'%{val}%') | ||||
|             criteria.append(self.column.ilike(val)) | ||||
|         return query.filter(sa.and_(*criteria)) | ||||
| 
 | ||||
|     def filter_does_not_contain(self, query, value): | ||||
|         """ | ||||
|  | @ -495,14 +499,17 @@ class AlchemyStringFilter(AlchemyGridFilter): | |||
|         if value is None or value == '': | ||||
|             return query | ||||
| 
 | ||||
|         criteria = [] | ||||
|         for val in value.split(): | ||||
|             val = val.replace('_', r'\_') | ||||
|             val = self.encode_value(f'%{val}%') | ||||
|             criteria.append(~self.column.ilike(val)) | ||||
| 
 | ||||
|         # When saying something is 'not like' something else, we must also | ||||
|         # include things which are nothing at all, in our result set. | ||||
|         return query.filter(sa.or_( | ||||
|             self.column == None, | ||||
|             sa.and_( | ||||
|                 *[~self.column.ilike(self.encode_value('%{}%'.format(v))) | ||||
|                   for v in value.split()]), | ||||
|         )) | ||||
|             sa.and_(*criteria))) | ||||
| 
 | ||||
|     def filter_contains_any_of(self, query, value): | ||||
|         """ | ||||
|  | @ -531,9 +538,12 @@ class AlchemyStringFilter(AlchemyGridFilter): | |||
| 
 | ||||
|         conditions = [] | ||||
|         for value in values: | ||||
|             conditions.append(sa.and_( | ||||
|                 *[self.column.ilike(self.encode_value('%{}%'.format(v))) | ||||
|                   for v in value.split()])) | ||||
|             criteria = [] | ||||
|             for val in value.split(): | ||||
|                 val = val.replace('_', r'\_') | ||||
|                 val = self.encode_value(f'%{val}%') | ||||
|                 criteria.append(self.column.ilike(val)) | ||||
|             conditions.append(sa.and_(*criteria)) | ||||
| 
 | ||||
|         return query.filter(sa.or_(*conditions)) | ||||
| 
 | ||||
|  | @ -588,8 +598,13 @@ class AlchemyByteStringFilter(AlchemyStringFilter): | |||
|         """ | ||||
|         if value is None or value == '': | ||||
|             return query | ||||
|         return query.filter(sa.and_( | ||||
|             *[self.column.ilike(b'%{}%'.format(v)) for v in value.split()])) | ||||
| 
 | ||||
|         criteria = [] | ||||
|         for val in value.split(): | ||||
|             val = val.replace('_', r'\_') | ||||
|             val = b'%{}%'.format(val) | ||||
|             criteria.append(self.column.ilike(val)) | ||||
|         return query.filters(sa.and_(*criteria)) | ||||
| 
 | ||||
|     def filter_does_not_contain(self, query, value): | ||||
|         """ | ||||
|  | @ -598,13 +613,16 @@ class AlchemyByteStringFilter(AlchemyStringFilter): | |||
|         if value is None or value == '': | ||||
|             return query | ||||
| 
 | ||||
|         for val in value.split(): | ||||
|             val = val.replace('_', '\_') | ||||
|             val = b'%{}%'.format(val) | ||||
|             criteria.append(~self.column.ilike(val)) | ||||
| 
 | ||||
|         # When saying something is 'not like' something else, we must also | ||||
|         # include things which are nothing at all, in our result set. | ||||
|         return query.filter(sa.or_( | ||||
|             self.column == None, | ||||
|             sa.and_( | ||||
|                 *[~self.column.ilike(b'%{}%'.format(v)) for v in value.split()]), | ||||
|         )) | ||||
|             sa.and_(*criteria))) | ||||
| 
 | ||||
| 
 | ||||
| class AlchemyNumericFilter(AlchemyGridFilter): | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar