Eager loading on One-to-X foreign keys

In this changeset, I added ORM relationships to the DB models
concerning the already-declared foreign keys.
I also modified the DB query building to now handle a new 'eager'
parameter that, if True, is responsible to also fetch the data
relative to these 'parent' DB entities (no cascading).

Change-Id: Ieea181af9a4b173c54621dcc6c549161f5a35aeb
Partially-Implements: blueprint watcher-versioned-objects
This commit is contained in:
Vincent Françoise
2016-09-23 11:00:41 +02:00
parent aae3f79fef
commit 750e6bf213
13 changed files with 534 additions and 302 deletions

View File

@@ -245,12 +245,32 @@ class DbActionTestCase(base.DbTestCase):
def test_get_action_list(self):
uuids = []
for _ in range(1, 6):
for _ in range(1, 4):
action = utils.create_test_action(uuid=w_utils.generate_uuid())
uuids.append(six.text_type(action['uuid']))
res = self.dbapi.get_action_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
actions = self.dbapi.get_action_list(self.context)
action_uuids = [a.uuid for a in actions]
self.assertEqual(3, len(action_uuids))
self.assertEqual(sorted(uuids), sorted(action_uuids))
for action in actions:
self.assertIsNone(action.action_plan)
def test_get_action_list_eager(self):
_action_plan = utils.get_test_action_plan()
action_plan = self.dbapi.create_action_plan(_action_plan)
uuids = []
for i in range(1, 4):
action = utils.create_test_action(
id=i, uuid=w_utils.generate_uuid(),
action_plan_id=action_plan.id)
uuids.append(six.text_type(action['uuid']))
actions = self.dbapi.get_action_list(self.context, eager=True)
action_map = {a.uuid: a for a in actions}
self.assertEqual(sorted(uuids), sorted(action_map.keys()))
eager_action = action_map[action.uuid]
self.assertEqual(
action_plan.as_dict(), eager_action.action_plan.as_dict())
def test_get_action_list_with_filters(self):
audit = utils.create_test_audit(uuid=w_utils.generate_uuid())
@@ -299,8 +319,8 @@ class DbActionTestCase(base.DbTestCase):
self.context,
filters={'action_plan_uuid': action_plan['uuid']})
self.assertEqual(
[action1['id'], action3['id']].sort(),
[r.id for r in res].sort())
sorted([action1['id'], action3['id']]),
sorted([r.id for r in res]))
res = self.dbapi.get_action_list(
self.context,

View File

@@ -242,16 +242,40 @@ class DbActionPlanTestCase(base.DbTestCase):
def test_get_action_plan_list(self):
uuids = []
for i in range(1, 6):
audit = utils.create_test_action_plan(uuid=w_utils.generate_uuid())
uuids.append(six.text_type(audit['uuid']))
res = self.dbapi.get_action_plan_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
for _ in range(1, 4):
action_plan = utils.create_test_action_plan(
uuid=w_utils.generate_uuid())
uuids.append(six.text_type(action_plan['uuid']))
action_plans = self.dbapi.get_action_plan_list(self.context)
action_plan_uuids = [ap.uuid for ap in action_plans]
self.assertEqual(sorted(uuids), sorted(action_plan_uuids))
for action_plan in action_plans:
self.assertIsNone(action_plan.audit)
self.assertIsNone(action_plan.strategy)
def test_get_action_plan_list_eager(self):
_strategy = utils.get_test_strategy()
strategy = self.dbapi.create_strategy(_strategy)
_audit = utils.get_test_audit()
audit = self.dbapi.create_audit(_audit)
uuids = []
for _ in range(1, 4):
action_plan = utils.create_test_action_plan(
uuid=w_utils.generate_uuid())
uuids.append(six.text_type(action_plan['uuid']))
action_plans = self.dbapi.get_action_plan_list(
self.context, eager=True)
action_plan_map = {a.uuid: a for a in action_plans}
self.assertEqual(sorted(uuids), sorted(action_plan_map.keys()))
eager_action_plan = action_plan_map[action_plan.uuid]
self.assertEqual(
strategy.as_dict(), eager_action_plan.strategy.as_dict())
self.assertEqual(audit.as_dict(), eager_action_plan.audit.as_dict())
def test_get_action_plan_list_with_filters(self):
audit = self._create_test_audit(
id=1,
id=2,
audit_type='ONESHOT',
uuid=w_utils.generate_uuid(),
deadline=None,

View File

@@ -20,7 +20,7 @@ import six
from watcher.common import exception
from watcher.common import utils as w_utils
from watcher.objects import audit as audit_objects
from watcher import objects
from watcher.tests.db import base
from watcher.tests.db import utils
@@ -48,11 +48,11 @@ class TestDbAuditFilters(base.DbTestCase):
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.audit2 = utils.create_test_audit(
audit_template_id=self.audit_template.id, id=2, uuid=None,
state=audit_objects.State.FAILED)
state=objects.audit.State.FAILED)
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.audit3 = utils.create_test_audit(
audit_template_id=self.audit_template.id, id=3, uuid=None,
state=audit_objects.State.CANCELLED)
state=objects.audit.State.CANCELLED)
def _soft_delete_audits(self):
with freezegun.freeze_time(self.FAKE_TODAY):
@@ -66,15 +66,15 @@ class TestDbAuditFilters(base.DbTestCase):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.update_audit(
self.audit1.uuid,
values={"state": audit_objects.State.SUCCEEDED})
values={"state": objects.audit.State.SUCCEEDED})
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.dbapi.update_audit(
self.audit2.uuid,
values={"state": audit_objects.State.SUCCEEDED})
values={"state": objects.audit.State.SUCCEEDED})
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.dbapi.update_audit(
self.audit3.uuid,
values={"state": audit_objects.State.SUCCEEDED})
values={"state": objects.audit.State.SUCCEEDED})
def test_get_audit_list_filter_deleted_true(self):
with freezegun.freeze_time(self.FAKE_TODAY):
@@ -230,8 +230,8 @@ class TestDbAuditFilters(base.DbTestCase):
def test_get_audit_list_filter_state_in(self):
res = self.dbapi.get_audit_list(
self.context,
filters={'state__in': (audit_objects.State.FAILED,
audit_objects.State.CANCELLED)})
filters={'state__in': (objects.audit.State.FAILED,
objects.audit.State.CANCELLED)})
self.assertEqual(
[self.audit2['id'], self.audit3['id']],
@@ -240,8 +240,8 @@ class TestDbAuditFilters(base.DbTestCase):
def test_get_audit_list_filter_state_notin(self):
res = self.dbapi.get_audit_list(
self.context,
filters={'state__notin': (audit_objects.State.FAILED,
audit_objects.State.CANCELLED)})
filters={'state__notin': (objects.audit.State.FAILED,
objects.audit.State.CANCELLED)})
self.assertEqual(
[self.audit1['id']],
@@ -257,29 +257,52 @@ class DbAuditTestCase(base.DbTestCase):
def test_get_audit_list(self):
uuids = []
for _ in range(1, 6):
for _ in range(1, 4):
audit = utils.create_test_audit(uuid=w_utils.generate_uuid())
uuids.append(six.text_type(audit['uuid']))
res = self.dbapi.get_audit_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
audits = self.dbapi.get_audit_list(self.context)
audit_uuids = [a.uuid for a in audits]
self.assertEqual(sorted(uuids), sorted(audit_uuids))
for audit in audits:
self.assertIsNone(audit.goal)
self.assertIsNone(audit.strategy)
def test_get_audit_list_eager(self):
_goal = utils.get_test_goal()
goal = self.dbapi.create_goal(_goal)
_strategy = utils.get_test_strategy()
strategy = self.dbapi.create_strategy(_strategy)
uuids = []
for i in range(1, 4):
audit = utils.create_test_audit(
id=i, uuid=w_utils.generate_uuid(),
goal_id=goal.id, strategy_id=strategy.id)
uuids.append(six.text_type(audit['uuid']))
audits = self.dbapi.get_audit_list(self.context, eager=True)
audit_map = {a.uuid: a for a in audits}
self.assertEqual(sorted(uuids), sorted(audit_map.keys()))
eager_audit = audit_map[audit.uuid]
self.assertEqual(goal.as_dict(), eager_audit.goal.as_dict())
self.assertEqual(strategy.as_dict(), eager_audit.strategy.as_dict())
def test_get_audit_list_with_filters(self):
audit1 = self._create_test_audit(
id=1,
audit_type='ONESHOT',
audit_type=objects.audit.AuditType.ONESHOT.value,
uuid=w_utils.generate_uuid(),
deadline=None,
state=audit_objects.State.ONGOING)
state=objects.audit.State.ONGOING)
audit2 = self._create_test_audit(
id=2,
audit_type='CONTINUOUS',
uuid=w_utils.generate_uuid(),
deadline=None,
state=audit_objects.State.PENDING)
state=objects.audit.State.PENDING)
res = self.dbapi.get_audit_list(self.context,
filters={'audit_type': 'ONESHOT'})
res = self.dbapi.get_audit_list(
self.context,
filters={'audit_type': objects.audit.AuditType.ONESHOT.value})
self.assertEqual([audit1['id']], [r.id for r in res])
res = self.dbapi.get_audit_list(self.context,
@@ -288,12 +311,12 @@ class DbAuditTestCase(base.DbTestCase):
res = self.dbapi.get_audit_list(
self.context,
filters={'state': audit_objects.State.ONGOING})
filters={'state': objects.audit.State.ONGOING})
self.assertEqual([audit1['id']], [r.id for r in res])
res = self.dbapi.get_audit_list(
self.context,
filters={'state': audit_objects.State.PENDING})
filters={'state': objects.audit.State.PENDING})
self.assertEqual([audit2['id']], [r.id for r in res])
def test_get_audit_list_with_filter_by_uuid(self):

View File

@@ -232,14 +232,40 @@ class DbAuditTemplateTestCase(base.DbTestCase):
def test_get_audit_template_list(self):
uuids = []
for i in range(1, 6):
for i in range(1, 4):
audit_template = utils.create_test_audit_template(
id=i,
uuid=w_utils.generate_uuid(),
name='My Audit Template {0}'.format(i))
uuids.append(six.text_type(audit_template['uuid']))
res = self.dbapi.get_audit_template_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
audit_templates = self.dbapi.get_audit_template_list(self.context)
audit_template_uuids = [at.uuid for at in audit_templates]
self.assertEqual(sorted(uuids), sorted(audit_template_uuids))
for audit_template in audit_templates:
self.assertIsNone(audit_template.goal)
self.assertIsNone(audit_template.strategy)
def test_get_audit_template_list_eager(self):
_goal = utils.get_test_goal()
goal = self.dbapi.create_goal(_goal)
_strategy = utils.get_test_strategy()
strategy = self.dbapi.create_strategy(_strategy)
uuids = []
for i in range(1, 4):
audit_template = utils.create_test_audit_template(
id=i, uuid=w_utils.generate_uuid(),
name='My Audit Template {0}'.format(i),
goal_id=goal.id, strategy_id=strategy.id)
uuids.append(six.text_type(audit_template['uuid']))
audit_templates = self.dbapi.get_audit_template_list(
self.context, eager=True)
audit_template_map = {a.uuid: a for a in audit_templates}
self.assertEqual(sorted(uuids), sorted(audit_template_map.keys()))
eager_audit_template = audit_template_map[audit_template.uuid]
self.assertEqual(goal.as_dict(), eager_audit_template.goal.as_dict())
self.assertEqual(
strategy.as_dict(), eager_audit_template.strategy.as_dict())
def test_get_audit_template_list_with_filters(self):
audit_template1 = self._create_test_audit_template(

View File

@@ -256,14 +256,37 @@ class DbEfficacyIndicatorTestCase(base.DbTestCase):
def test_get_efficacy_indicator_list(self):
uuids = []
action_plan = self._create_test_action_plan()
for id_ in range(1, 6):
for id_ in range(1, 4):
efficacy_indicator = utils.create_test_efficacy_indicator(
action_plan_id=action_plan.id, id=id_, uuid=None,
name="efficacy_indicator", description="Test Indicator ")
uuids.append(six.text_type(efficacy_indicator['uuid']))
res = self.dbapi.get_efficacy_indicator_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
efficacy_indicators = self.dbapi.get_efficacy_indicator_list(
self.context)
efficacy_indicator_uuids = [ei.uuid for ei in efficacy_indicators]
self.assertEqual(sorted(uuids), sorted(efficacy_indicator_uuids))
for efficacy_indicator in efficacy_indicators:
self.assertIsNone(efficacy_indicator.action_plan)
def test_get_efficacy_indicator_list_eager(self):
_action_plan = utils.get_test_action_plan()
action_plan = self.dbapi.create_action_plan(_action_plan)
uuids = []
for i in range(1, 4):
efficacy_indicator = utils.create_test_efficacy_indicator(
id=i, uuid=w_utils.generate_uuid(),
action_plan_id=action_plan.id)
uuids.append(six.text_type(efficacy_indicator['uuid']))
efficacy_indicators = self.dbapi.get_efficacy_indicator_list(
self.context, eager=True)
efficacy_indicator_map = {a.uuid: a for a in efficacy_indicators}
self.assertEqual(sorted(uuids), sorted(efficacy_indicator_map.keys()))
eager_efficacy_indicator = efficacy_indicator_map[
efficacy_indicator.uuid]
self.assertEqual(
action_plan.as_dict(),
eager_efficacy_indicator.action_plan.as_dict())
def test_get_efficacy_indicator_list_with_filters(self):
audit = utils.create_test_audit(uuid=w_utils.generate_uuid())
@@ -311,8 +334,8 @@ class DbEfficacyIndicatorTestCase(base.DbTestCase):
self.context,
filters={'action_plan_uuid': action_plan['uuid']})
self.assertEqual(
[efficacy_indicator1['id'], efficacy_indicator3['id']].sort(),
[r.id for r in res].sort())
sorted([efficacy_indicator1['id'], efficacy_indicator3['id']]),
sorted([r.id for r in res]))
def test_get_efficacy_indicator_list_with_filter_by_uuid(self):
efficacy_indicator = self._create_test_efficacy_indicator()

View File

@@ -230,16 +230,16 @@ class DbGoalTestCase(base.DbTestCase):
def test_get_goal_list(self):
uuids = []
for i in range(1, 6):
for i in range(1, 4):
goal = utils.create_test_goal(
id=i,
uuid=w_utils.generate_uuid(),
name="GOAL_%s" % i,
display_name='My Goal %s' % i)
uuids.append(six.text_type(goal['uuid']))
res = self.dbapi.get_goal_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
goals = self.dbapi.get_goal_list(self.context)
goal_uuids = [g.uuid for g in goals]
self.assertEqual(sorted(uuids), sorted(goal_uuids))
def test_get_goal_list_with_filters(self):
goal1 = self._create_test_goal(

View File

@@ -235,7 +235,7 @@ class DbScoringEngineTestCase(base.DbTestCase):
def test_get_scoring_engine_list(self):
names = []
for i in range(1, 6):
for i in range(1, 4):
scoring_engine = utils.create_test_scoring_engine(
id=i,
uuid=w_utils.generate_uuid(),
@@ -243,9 +243,9 @@ class DbScoringEngineTestCase(base.DbTestCase):
description='My ScoringEngine {0}'.format(i),
metainfo='a{0}=b{0}'.format(i))
names.append(six.text_type(scoring_engine['name']))
res = self.dbapi.get_scoring_engine_list(self.context)
res_names = [r.name for r in res]
self.assertEqual(names.sort(), res_names.sort())
scoring_engines = self.dbapi.get_scoring_engine_list(self.context)
scoring_engines_names = [se.name for se in scoring_engines]
self.assertEqual(sorted(names), sorted(scoring_engines_names))
def test_get_scoring_engine_list_with_filters(self):
scoring_engine1 = self._create_test_scoring_engine(
@@ -310,7 +310,7 @@ class DbScoringEngineTestCase(base.DbTestCase):
self.assertRaises(exception.Invalid,
self.dbapi.update_scoring_engine,
scoring_engine['id'],
{'id': 5})
{'uuid': w_utils.generate_uuid()})
def test_update_scoring_engine_that_does_not_exist(self):
self.assertRaises(exception.ScoringEngineNotFound,

View File

@@ -18,7 +18,6 @@
"""Tests for manipulating Service via the DB API"""
import freezegun
import six
from oslo_utils import timeutils
@@ -237,15 +236,15 @@ class DbServiceTestCase(base.DbTestCase):
def test_get_service_list(self):
ids = []
for i in range(1, 6):
for i in range(1, 4):
service = utils.create_test_service(
id=i,
name="SERVICE_ID_%s" % i,
host="controller_{0}".format(i))
ids.append(six.text_type(service['id']))
res = self.dbapi.get_service_list(self.context)
res_ids = [r.id for r in res]
self.assertEqual(ids.sort(), res_ids.sort())
ids.append(service['id'])
services = self.dbapi.get_service_list(self.context)
service_ids = [s.id for s in services]
self.assertEqual(sorted(ids), sorted(service_ids))
def test_get_service_list_with_filters(self):
service1 = self._create_test_service(

View File

@@ -245,17 +245,37 @@ class DbStrategyTestCase(base.DbTestCase):
return strategy
def test_get_strategy_list(self):
ids = []
for i in range(1, 6):
uuids = []
for i in range(1, 4):
strategy = utils.create_test_strategy(
id=i,
uuid=w_utils.generate_uuid(),
name="STRATEGY_ID_%s" % i,
display_name='My Strategy {0}'.format(i))
ids.append(six.text_type(strategy['uuid']))
res = self.dbapi.get_strategy_list(self.context)
res_ids = [r.display_name for r in res]
self.assertEqual(ids.sort(), res_ids.sort())
uuids.append(six.text_type(strategy['uuid']))
strategies = self.dbapi.get_strategy_list(self.context)
strategy_uuids = [s.uuid for s in strategies]
self.assertEqual(sorted(uuids), sorted(strategy_uuids))
for strategy in strategies:
self.assertIsNone(strategy.goal)
def test_get_strategy_list_eager(self):
_goal = utils.get_test_goal()
goal = self.dbapi.create_goal(_goal)
uuids = []
for i in range(1, 4):
strategy = utils.create_test_strategy(
id=i,
uuid=w_utils.generate_uuid(),
name="STRATEGY_ID_%s" % i,
display_name='My Strategy {0}'.format(i),
goal_id=goal.id)
uuids.append(six.text_type(strategy['uuid']))
strategys = self.dbapi.get_strategy_list(self.context, eager=True)
strategy_map = {a.uuid: a for a in strategys}
self.assertEqual(sorted(uuids), sorted(strategy_map.keys()))
eager_strategy = strategy_map[strategy.uuid]
self.assertEqual(goal.as_dict(), eager_strategy.goal.as_dict())
def test_get_strategy_list_with_filters(self):
strategy1 = self._create_test_strategy(