Add 'like' filter to string fields
Change-Id: I2437de4b7c298ee735dc6e645d164b0245b398b7
This commit is contained in:
parent
2f5a95cf1d
commit
88d5d7f416
|
@ -421,13 +421,7 @@ def _do_query_filters(filters):
|
|||
tags = utils.split_filter_value_for_quotes(value)
|
||||
tag_conds.append([models.ArtifactTag.value.in_(tags)])
|
||||
elif field_name in BASE_ARTIFACT_PROPERTIES:
|
||||
if op != 'in':
|
||||
fn = op_mappings[op]
|
||||
if field_name == 'version':
|
||||
value = semver_db.parse(value)
|
||||
basic_conds.append([fn(getattr(models.Artifact, field_name),
|
||||
value)])
|
||||
else:
|
||||
if op == 'in':
|
||||
if field_name == 'version':
|
||||
value = [semver_db.parse(val) for val in value]
|
||||
basic_conds.append(
|
||||
|
@ -436,6 +430,15 @@ def _do_query_filters(filters):
|
|||
else:
|
||||
basic_conds.append(
|
||||
[getattr(models.Artifact, field_name).in_(value)])
|
||||
elif op == 'like':
|
||||
basic_conds.append(
|
||||
[getattr(models.Artifact, field_name).like(value)])
|
||||
else:
|
||||
fn = op_mappings[op]
|
||||
if field_name == 'version':
|
||||
value = semver_db.parse(value)
|
||||
basic_conds.append([fn(getattr(models.Artifact, field_name),
|
||||
value)])
|
||||
else:
|
||||
conds = [models.ArtifactProperty.name == field_name]
|
||||
if key_name is not None:
|
||||
|
@ -446,13 +449,16 @@ def _do_query_filters(filters):
|
|||
conds.extend(
|
||||
[models.ArtifactProperty.key_name.in_(key_name)])
|
||||
if value is not None:
|
||||
if op != 'in':
|
||||
if op == 'in':
|
||||
conds.extend([getattr(models.ArtifactProperty,
|
||||
field_type + '_value').in_(value)])
|
||||
elif op == 'like':
|
||||
conds.extend(
|
||||
[models.ArtifactProperty.string_value.like(value)])
|
||||
else:
|
||||
fn = op_mappings[op]
|
||||
conds.extend([fn(getattr(models.ArtifactProperty,
|
||||
field_type + '_value'), value)])
|
||||
else:
|
||||
conds.extend([getattr(models.ArtifactProperty,
|
||||
field_type + '_value').in_(value)])
|
||||
|
||||
prop_conds.append(conds)
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ from glare.objects.meta import validators as val_lib
|
|||
|
||||
FILTERS = (
|
||||
FILTER_EQ, FILTER_NEQ, FILTER_IN, FILTER_GT, FILTER_GTE, FILTER_LT,
|
||||
FILTER_LTE) = ('eq', 'neq', 'in', 'gt', 'gte', 'lt', 'lte')
|
||||
FILTER_LTE, FILTER_LIKE) = ('eq', 'neq', 'in', 'gt', 'gte', 'lt', 'lte',
|
||||
'like')
|
||||
|
||||
DEFAULT_MAX_BLOB_SIZE = 10485760 # 10 Megabytes
|
||||
DEFAULT_MAX_FOLDER_SIZE = 2673868800 # 2550 Megabytes
|
||||
|
@ -83,15 +84,17 @@ class Field(object):
|
|||
self.sortable = sortable
|
||||
|
||||
try:
|
||||
default_ops = self.get_allowed_filter_ops(self.element_type)
|
||||
default_ops = self.get_default_filter_ops(self.element_type)
|
||||
allowed_ops = self.get_allowed_filter_ops(self.element_type)
|
||||
except AttributeError:
|
||||
default_ops = self.get_allowed_filter_ops(field_class)
|
||||
default_ops = self.get_default_filter_ops(field_class)
|
||||
allowed_ops = self.get_allowed_filter_ops(self.field_class)
|
||||
|
||||
if filter_ops is None:
|
||||
self.filter_ops = default_ops
|
||||
else:
|
||||
for op in filter_ops:
|
||||
if op not in default_ops:
|
||||
if op not in allowed_ops:
|
||||
raise exc.IncorrectArtifactType(
|
||||
"Incorrect filter operator '%s'. "
|
||||
"Only %s are allowed" % (op, ', '.join(default_ops)))
|
||||
|
@ -104,7 +107,7 @@ class Field(object):
|
|||
@staticmethod
|
||||
def get_allowed_filter_ops(field):
|
||||
if field in (fields.StringField, fields.String):
|
||||
return [FILTER_EQ, FILTER_NEQ, FILTER_IN]
|
||||
return [FILTER_EQ, FILTER_NEQ, FILTER_IN, FILTER_LIKE]
|
||||
elif field in (fields.IntegerField, fields.Integer, fields.FloatField,
|
||||
fields.Float, glare_fields.VersionField):
|
||||
return FILTERS
|
||||
|
@ -116,6 +119,22 @@ class Field(object):
|
|||
elif field is fields.DateTimeField:
|
||||
return [FILTER_LT, FILTER_GT]
|
||||
|
||||
@staticmethod
|
||||
def get_default_filter_ops(field):
|
||||
if field in (fields.StringField, fields.String):
|
||||
return [FILTER_EQ, FILTER_NEQ, FILTER_IN]
|
||||
elif field in (fields.IntegerField, fields.Integer, fields.FloatField,
|
||||
fields.Float, glare_fields.VersionField):
|
||||
return [FILTER_EQ, FILTER_NEQ, FILTER_IN, FILTER_GT, FILTER_GTE,
|
||||
FILTER_LT, FILTER_LTE]
|
||||
elif field in (fields.FlexibleBooleanField, fields.FlexibleBoolean,
|
||||
glare_fields.Link, glare_fields.LinkFieldType):
|
||||
return [FILTER_EQ, FILTER_NEQ]
|
||||
elif field in (glare_fields.BlobField, glare_fields.BlobFieldType):
|
||||
return []
|
||||
elif field is fields.DateTimeField:
|
||||
return [FILTER_LT, FILTER_GT]
|
||||
|
||||
def get_default_validators(self):
|
||||
default = []
|
||||
if issubclass(self.field_class, fields.StringField):
|
||||
|
|
|
@ -422,7 +422,8 @@ fixtures = {
|
|||
u'required_on_activate': False,
|
||||
u'type': [u'object',
|
||||
u'null']},
|
||||
u'str1': {u'filter_ops': [u'eq',
|
||||
u'str1': {u'filter_ops': [u'like',
|
||||
u'eq',
|
||||
u'neq',
|
||||
u'in'],
|
||||
u'glareType': u'String',
|
||||
|
|
|
@ -61,6 +61,10 @@ class SampleArtifact(base_artifact.BaseArtifact):
|
|||
sortable=True,
|
||||
required_on_activate=False),
|
||||
'str1': Field(fields.StringField,
|
||||
filter_ops=(wrappers.FILTER_LIKE,
|
||||
wrappers.FILTER_EQ,
|
||||
wrappers.FILTER_NEQ,
|
||||
wrappers.FILTER_IN),
|
||||
sortable=True,
|
||||
required_on_activate=False),
|
||||
'list_of_str': List(fields.String,
|
||||
|
|
|
@ -584,3 +584,30 @@ class TestArtifactList(base.BaseTestArtifactAPI):
|
|||
exc.BadRequest, self.controller.list,
|
||||
self.req, 'sample_artifact',
|
||||
[], sort=[(name, sort_dir)])
|
||||
|
||||
def test_list_like_filter(self):
|
||||
val = {'name': '0', 'str1': 'banana'}
|
||||
art0 = self.controller.create(self.req, 'sample_artifact', val)
|
||||
val = {'name': '1', 'str1': 'nan'}
|
||||
art1 = self.controller.create(self.req, 'sample_artifact', val)
|
||||
val = {'name': '2', 'str1': 'anab'}
|
||||
self.controller.create(self.req, 'sample_artifact', val)
|
||||
|
||||
filters = [('str1', 'like:%banana%')]
|
||||
res = self.controller.list(self.req, 'sample_artifact', filters)
|
||||
self.assertEqual(1, len(res['artifacts']))
|
||||
self.assertIn(art0, res['artifacts'])
|
||||
|
||||
filters = [('str1', 'like:%nan%')]
|
||||
res = self.controller.list(self.req, 'sample_artifact', filters)
|
||||
self.assertEqual(2, len(res['artifacts']))
|
||||
self.assertIn(art0, res['artifacts'])
|
||||
self.assertIn(art1, res['artifacts'])
|
||||
|
||||
filters = [('str1', 'like:%na%')]
|
||||
res = self.controller.list(self.req, 'sample_artifact', filters)
|
||||
self.assertEqual(3, len(res['artifacts']))
|
||||
|
||||
filters = [('str1', 'like:%haha%')]
|
||||
res = self.controller.list(self.req, 'sample_artifact', filters)
|
||||
self.assertEqual(0, len(res['artifacts']))
|
||||
|
|
Loading…
Reference in New Issue