From de295f036df2cedec9de4c25f344ebb770f66e0a Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Wed, 28 Apr 2021 09:36:07 +0000 Subject: [PATCH] Do not include dynamically loaded values into OVO testing Those OVO values loaded dynamically (for example [1]) should not be added to the tested object. A dynamic column in a DB register is a ``sqlalchemy.orm.AppenderQuery`` object that represents the needed query to retrieve this value. These OVO fields, mapped from the DB object, should be considered as synthetic fields and not be included in ``_BaseObjectTestCase.obj_fields``. [1]https://github.com/openstack/neutron/blob/ff2464bf33f1c84bd8525eca68c5774f5e14f1f1/neutron/db/models/securitygroup.py#L103-L106 Closes-Bug: #1926399 Change-Id: I4b59dbc71316eede52b22c0788de5fd682fbff30 --- neutron/objects/base.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/neutron/objects/base.py b/neutron/objects/base.py index 41a24ee56b6..614082711e8 100644 --- a/neutron/objects/base.py +++ b/neutron/objects/base.py @@ -30,6 +30,7 @@ from oslo_versionedobjects import base as obj_base from oslo_versionedobjects import exception as obj_exception from oslo_versionedobjects import fields as obj_fields from sqlalchemy import orm +from sqlalchemy.orm import query as sqla_query from neutron._i18n import _ from neutron.db import standard_attr @@ -518,8 +519,14 @@ class NeutronDbObject(NeutronObject, metaclass=DeclarativeObject): # db.keys() so we must fetch data based on object fields definition potential_fields = (list(cls.fields.keys()) + list(cls.fields_need_translation.values())) - result = {field: db_obj[field] for field in potential_fields - if db_obj.get(field) is not None} + # NOTE(ralonsoh): fields dynamically loaded will be represented as + # ``sqla_query.Query``, because the value is load when needed executing + # a query to the DB. + result = { + field: db_obj[field] for field in potential_fields + if (db_obj.get(field) is not None and + not issubclass(db_obj.get(field).__class__, sqla_query.Query)) + } for field, field_db in cls.fields_need_translation.items(): if field_db in result: result[field] = result.pop(field_db) @@ -933,5 +940,5 @@ class NeutronDbObject(NeutronObject, metaclass=DeclarativeObject): cls.validate_filters(**kwargs) # Succeed if at least a single object matches; no need to fetch more return bool(obj_db_api.count( - cls, context, **cls.modify_fields_to_db(kwargs)) + cls, context, query_limit=1, **cls.modify_fields_to_db(kwargs)) )