diff --git a/ceilometer/storage/impl_sqlalchemy.py b/ceilometer/storage/impl_sqlalchemy.py index 260ebfbc8..660a11bcc 100644 --- a/ceilometer/storage/impl_sqlalchemy.py +++ b/ceilometer/storage/impl_sqlalchemy.py @@ -890,17 +890,6 @@ class Connection(base.Connection): problem_events.append((api_models.Event.UNKNOWN_PROBLEM, event_model)) events.append(event) - - # Update the models with the underlying DB ID. - for model, actual in zip(event_models, events): - if not actual: - continue - actual_event, actual_traits = actual - model.id = actual_event.id - if model.traits and actual_traits: - for trait, actual_trait in zip(model.traits, actual_traits): - trait.id = actual_trait.id - return problem_events def get_events(self, event_filter): @@ -913,14 +902,18 @@ class Connection(base.Connection): end = utils.dt_to_decimal(event_filter.end) session = sqlalchemy_session.get_session() with session.begin(): + event_query_filters = [Event.generated >= start, + Event.generated <= end] sub_query = session.query(Event.id)\ - .join(Trait, Trait.event_id == Event.id)\ - .filter(Event.generated >= start, Event.generated <= end) + .join(Trait, Trait.event_id == Event.id) if event_filter.event_name: event_name = self._get_unique(session, event_filter.event_name) - sub_query = sub_query.filter(Event.unique_name == event_name) + event_query_filters.append(Event.unique_name == event_name) + sub_query = sub_query.filter(*event_query_filters) + + event_models_dict = {} if event_filter.traits: for key, value in event_filter.traits.iteritems(): if key == 'key': @@ -935,6 +928,15 @@ class Connection(base.Connection): sub_query = sub_query.filter(Trait.t_datetime == dt) elif key == 't_float': sub_query = sub_query.filter(Trait.t_datetime == value) + else: + # Pre-populate event_models_dict to cover Events without traits + events = session.query(Event).filter(*event_query_filters) + for db_event in events.all(): + generated = utils.decimal_to_dt(db_event.generated) + api_event = api_models.Event(db_event.message_id, + db_event.unique_name.key, + generated, []) + event_models_dict[db_event.id] = api_event sub_query = sub_query.subquery() @@ -942,7 +944,6 @@ class Connection(base.Connection): .join(sub_query, Trait.event_id == sub_query.c.id) # Now convert the sqlalchemy objects back into Models ... - event_models_dict = {} for trait in all_data.all(): event = event_models_dict.get(trait.event_id) if not event: diff --git a/tests/storage/test_storage_scenarios.py b/tests/storage/test_storage_scenarios.py index 2e6c7f592..607a57fc0 100644 --- a/tests/storage/test_storage_scenarios.py +++ b/tests/storage/test_storage_scenarios.py @@ -2093,35 +2093,6 @@ class EventTest(EventTestBase): bad = problem_events[0] self.assertEqual(models.Event.DUPLICATE, bad[0]) - def test_save_events_no_traits(self): - now = datetime.datetime.utcnow() - m = [models.Event("1", "Foo", now, None), - models.Event("2", "Zoo", now, [])] - self.conn.record_events(m) - for model in m: - self.assertTrue(model.id >= 0) - self.assertNotEqual(m[0].id, m[1].id) - - def test_save_events_traits(self): - event_models = [] - for event_name in ['Foo', 'Bar', 'Zoo']: - now = datetime.datetime.utcnow() - trait_models = \ - [models.Trait(name, dtype, value) - for name, dtype, value in [ - ('trait_A', models.Trait.TEXT_TYPE, "my_text"), - ('trait_B', models.Trait.INT_TYPE, 199), - ('trait_C', models.Trait.FLOAT_TYPE, 1.23456), - ('trait_D', models.Trait.DATETIME_TYPE, now)]] - event_models.append( - models.Event("id_%s" % event_name, - event_name, now, trait_models)) - - self.conn.record_events(event_models) - for model in event_models: - for trait in model.traits: - self.assertTrue(trait.id >= 0) - class GetEventTest(EventTestBase): def prepare_data(self): @@ -2178,3 +2149,14 @@ class GetEventTest(EventTestBase): self.assertEqual(1, len(events)) self.assertEqual(events[0].event_name, "Bar") self.assertEqual(4, len(events[0].traits)) + + def test_simple_get_no_traits(self): + new_events = [models.Event("id_notraits", "NoTraits", self.start, [])] + bad_events = self.conn.record_events(new_events) + event_filter = storage.EventFilter(self.start, self.end, "NoTraits") + events = self.conn.get_events(event_filter) + self.assertEquals(0, len(bad_events)) + self.assertEqual(1, len(events)) + self.assertEqual(events[0].message_id, "id_notraits") + self.assertEqual(events[0].event_name, "NoTraits") + self.assertEqual(0, len(events[0].traits))