Changed filter_by() to filter() during filtering instances in db API
When we use filter_by() fields for filtering are extracted from the primary entity of the query, or the last entity that was the target of a call to Query.join(). If db query contains filters 'project_id' and 'tags' (or 'tags-any') db error will be raised: Entity '<AliasedClass at 0x7fb09ba18b50; Tag>' has no property 'project_id' It happens because we use join(models.Tag) to filter instances by tags. Sqlalchemy try to find 'project_id' field in Tag model. To fix this issue we should use filter() instead of filter_by(). filter() works fine with join(). Closes-Bug: #1516546 Change-Id: Ibcac2a08aa51f698c690399f65c77130ff2de173
This commit is contained in:
@@ -2252,8 +2252,8 @@ def _exact_instance_filter(query, filters, legal_keys):
|
||||
|
||||
# Apply simple exact matches
|
||||
if filter_dict:
|
||||
query = query.filter_by(**filter_dict)
|
||||
|
||||
query = query.filter(*[getattr(models.Instance, k) == v
|
||||
for k, v in filter_dict.items()])
|
||||
return query
|
||||
|
||||
|
||||
|
||||
@@ -2589,6 +2589,33 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
ignored_keys=['deleted', 'deleted_at', 'metadata', 'extra',
|
||||
'system_metadata', 'info_cache', 'pci_devices'])
|
||||
|
||||
def test_instance_get_all_by_filters_tags_and_project_id(self):
|
||||
context1 = context.RequestContext('user1', 'p1')
|
||||
context2 = context.RequestContext('user2', 'p2')
|
||||
|
||||
inst1 = self.create_instance_with_args(context=context1,
|
||||
project_id='p1')
|
||||
inst2 = self.create_instance_with_args(context=context1,
|
||||
project_id='p1')
|
||||
inst3 = self.create_instance_with_args(context=context2,
|
||||
project_id='p2')
|
||||
t1 = u'tag1'
|
||||
t2 = u'tag2'
|
||||
t3 = u'tag3'
|
||||
t4 = u'tag4'
|
||||
|
||||
db.instance_tag_set(context1, inst1.uuid, [t1, t2])
|
||||
db.instance_tag_set(context1, inst2.uuid, [t1, t2, t4])
|
||||
db.instance_tag_set(context2, inst3.uuid, [t1, t2, t3, t4])
|
||||
|
||||
result = db.instance_get_all_by_filters(self.ctxt,
|
||||
{'tags': [t1, t2],
|
||||
'tags-any': [t3, t4],
|
||||
'project_id': 'p1'})
|
||||
self._assertEqualListsOfObjects([inst2], result,
|
||||
ignored_keys=['deleted', 'deleted_at', 'metadata', 'extra',
|
||||
'system_metadata', 'info_cache', 'pci_devices'])
|
||||
|
||||
def test_instance_get_all_by_host_and_node_no_join(self):
|
||||
instance = self.create_instance_with_args()
|
||||
result = db.instance_get_all_by_host_and_node(self.ctxt, 'h1', 'n1')
|
||||
|
||||
Reference in New Issue
Block a user