From 9f110637242a684c7c23eebb623e0765d8e698e1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 24 Apr 2022 18:47:21 -1000 Subject: [PATCH] Fix state_changes_during_period bakery caching for limit and descending (#70610) --- homeassistant/components/recorder/history.py | 15 +++++-- tests/components/recorder/test_history.py | 42 ++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/recorder/history.py b/homeassistant/components/recorder/history.py index 6731e409f65..8e9d5370832 100644 --- a/homeassistant/components/recorder/history.py +++ b/homeassistant/components/recorder/history.py @@ -343,15 +343,22 @@ def state_changes_during_period( StateAttributes, States.attributes_id == StateAttributes.attributes_id ) - last_updated = States.last_updated.desc() if descending else States.last_updated - baked_query += lambda q: q.order_by(States.entity_id, last_updated) + if descending: + baked_query += lambda q: q.order_by( + States.entity_id, States.last_updated.desc() + ) + else: + baked_query += lambda q: q.order_by(States.entity_id, States.last_updated) if limit: - baked_query += lambda q: q.limit(limit) + baked_query += lambda q: q.limit(bindparam("limit")) states = execute( baked_query(session).params( - start_time=start_time, end_time=end_time, entity_id=entity_id + start_time=start_time, + end_time=end_time, + entity_id=entity_id, + limit=limit, ) ) diff --git a/tests/components/recorder/test_history.py b/tests/components/recorder/test_history.py index e70d15e730c..09759add23f 100644 --- a/tests/components/recorder/test_history.py +++ b/tests/components/recorder/test_history.py @@ -268,6 +268,48 @@ def test_state_changes_during_period(hass_recorder, attributes, no_attributes, l assert states[:limit] == hist[entity_id] +def test_state_changes_during_period_descending(hass_recorder): + """Test state change during period descending.""" + hass = hass_recorder() + entity_id = "media_player.test" + + def set_state(state): + """Set the state.""" + hass.states.set(entity_id, state, {"any": 1}) + wait_recording_done(hass) + return hass.states.get(entity_id) + + start = dt_util.utcnow() + point = start + timedelta(seconds=1) + end = point + timedelta(seconds=1) + + with patch("homeassistant.components.recorder.dt_util.utcnow", return_value=start): + set_state("idle") + set_state("YouTube") + + with patch("homeassistant.components.recorder.dt_util.utcnow", return_value=point): + states = [ + set_state("idle"), + set_state("Netflix"), + set_state("Plex"), + set_state("YouTube"), + ] + + with patch("homeassistant.components.recorder.dt_util.utcnow", return_value=end): + set_state("Netflix") + set_state("Plex") + + hist = history.state_changes_during_period( + hass, start, end, entity_id, no_attributes=False, descending=False + ) + assert states == hist[entity_id] + + hist = history.state_changes_during_period( + hass, start, end, entity_id, no_attributes=False, descending=True + ) + assert states == list(reversed(list(hist[entity_id]))) + + def test_get_last_state_changes(hass_recorder): """Test number of state changes.""" hass = hass_recorder()