mirror of
https://github.com/home-assistant/core.git
synced 2025-08-15 18:41:44 +02:00
DRY
This commit is contained in:
@@ -22,7 +22,6 @@ from sqlalchemy import (
|
|||||||
from sqlalchemy.engine.row import Row
|
from sqlalchemy.engine.row import Row
|
||||||
from sqlalchemy.orm.properties import MappedColumn
|
from sqlalchemy.orm.properties import MappedColumn
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
from sqlalchemy.sql.expression import literal
|
|
||||||
|
|
||||||
from homeassistant.const import COMPRESSED_STATE_LAST_UPDATED, COMPRESSED_STATE_STATE
|
from homeassistant.const import COMPRESSED_STATE_LAST_UPDATED, COMPRESSED_STATE_STATE
|
||||||
from homeassistant.core import HomeAssistant, State, split_entity_id
|
from homeassistant.core import HomeAssistant, State, split_entity_id
|
||||||
@@ -46,29 +45,24 @@ from .const import (
|
|||||||
STATE_KEY,
|
STATE_KEY,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_QUERY_STATE_NO_ATTR_NO_LAST_CHANGED = (
|
||||||
|
States.metadata_id,
|
||||||
|
States.state,
|
||||||
|
States.last_updated_ts,
|
||||||
|
)
|
||||||
_QUERY_STATE_NO_ATTR = (
|
_QUERY_STATE_NO_ATTR = (
|
||||||
States.metadata_id,
|
*_QUERY_STATE_NO_ATTR_NO_LAST_CHANGED,
|
||||||
States.state,
|
|
||||||
States.last_changed_ts,
|
States.last_changed_ts,
|
||||||
States.last_updated_ts,
|
|
||||||
)
|
)
|
||||||
_QUERY_STATE_NO_ATTR_NO_LAST_CHANGED = ( # type: ignore[var-annotated]
|
_QUERY_ATTRIBUTES = (
|
||||||
States.metadata_id,
|
|
||||||
States.state,
|
|
||||||
literal(value=None).label("last_changed_ts"),
|
|
||||||
States.last_updated_ts,
|
|
||||||
)
|
|
||||||
_QUERY_STATES = (
|
|
||||||
*_QUERY_STATE_NO_ATTR,
|
|
||||||
# Remove States.attributes once all attributes are in StateAttributes.shared_attrs
|
# Remove States.attributes once all attributes are in StateAttributes.shared_attrs
|
||||||
States.attributes,
|
States.attributes,
|
||||||
StateAttributes.shared_attrs,
|
StateAttributes.shared_attrs,
|
||||||
)
|
)
|
||||||
|
_QUERY_STATES = (*_QUERY_STATE_NO_ATTR, *_QUERY_ATTRIBUTES)
|
||||||
_QUERY_STATES_NO_LAST_CHANGED = (
|
_QUERY_STATES_NO_LAST_CHANGED = (
|
||||||
*_QUERY_STATE_NO_ATTR_NO_LAST_CHANGED,
|
*_QUERY_STATE_NO_ATTR_NO_LAST_CHANGED,
|
||||||
# Remove States.attributes once all attributes are in StateAttributes.shared_attrs
|
*_QUERY_ATTRIBUTES,
|
||||||
States.attributes,
|
|
||||||
StateAttributes.shared_attrs,
|
|
||||||
)
|
)
|
||||||
_FIELD_MAP = {
|
_FIELD_MAP = {
|
||||||
cast(MappedColumn, field).name: idx
|
cast(MappedColumn, field).name: idx
|
||||||
@@ -94,15 +88,16 @@ def _stmt_and_join_attributes(
|
|||||||
|
|
||||||
|
|
||||||
def _select_from_subquery(
|
def _select_from_subquery(
|
||||||
subquery: Subquery | CompoundSelect, no_attributes: bool
|
subquery: Subquery | CompoundSelect, no_attributes: bool, include_last_changed: bool
|
||||||
) -> Select:
|
) -> Select:
|
||||||
"""Return the statement to select from the union."""
|
"""Return the statement to select from the union."""
|
||||||
base_select = select(
|
base_select = select(
|
||||||
subquery.c.metadata_id,
|
subquery.c.metadata_id,
|
||||||
subquery.c.state,
|
subquery.c.state,
|
||||||
subquery.c.last_changed_ts,
|
|
||||||
subquery.c.last_updated_ts,
|
subquery.c.last_updated_ts,
|
||||||
)
|
)
|
||||||
|
if include_last_changed:
|
||||||
|
base_select = base_select.add_columns(subquery.c.last_changed_ts)
|
||||||
if no_attributes:
|
if no_attributes:
|
||||||
return base_select
|
return base_select
|
||||||
return base_select.add_columns(subquery.c.attributes, subquery.c.shared_attrs)
|
return base_select.add_columns(subquery.c.attributes, subquery.c.shared_attrs)
|
||||||
@@ -149,9 +144,8 @@ def _significant_states_stmt(
|
|||||||
run_start_ts: float | None,
|
run_start_ts: float | None,
|
||||||
) -> Select | CompoundSelect:
|
) -> Select | CompoundSelect:
|
||||||
"""Query the database for significant state changes."""
|
"""Query the database for significant state changes."""
|
||||||
stmt = _stmt_and_join_attributes(
|
include_last_changed = not significant_changes_only
|
||||||
no_attributes, include_last_changed=not significant_changes_only
|
stmt = _stmt_and_join_attributes(no_attributes, include_last_changed)
|
||||||
)
|
|
||||||
if significant_changes_only:
|
if significant_changes_only:
|
||||||
# Since we are filtering on entity_id (metadata_id) we can avoid
|
# Since we are filtering on entity_id (metadata_id) we can avoid
|
||||||
# the join of the states_meta table since we already know which
|
# the join of the states_meta table since we already know which
|
||||||
@@ -182,12 +176,15 @@ def _significant_states_stmt(
|
|||||||
single_metadata_id,
|
single_metadata_id,
|
||||||
metadata_ids,
|
metadata_ids,
|
||||||
no_attributes,
|
no_attributes,
|
||||||
|
include_last_changed,
|
||||||
).subquery(),
|
).subquery(),
|
||||||
no_attributes,
|
no_attributes,
|
||||||
|
include_last_changed,
|
||||||
),
|
),
|
||||||
_select_from_subquery(stmt.subquery(), no_attributes),
|
_select_from_subquery(stmt.subquery(), no_attributes, include_last_changed),
|
||||||
).subquery(),
|
).subquery(),
|
||||||
no_attributes,
|
no_attributes,
|
||||||
|
include_last_changed,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -345,13 +342,15 @@ def _state_changed_during_period_stmt(
|
|||||||
union_all(
|
union_all(
|
||||||
_select_from_subquery(
|
_select_from_subquery(
|
||||||
_get_single_entity_start_time_stmt(
|
_get_single_entity_start_time_stmt(
|
||||||
start_time_ts, single_metadata_id, no_attributes
|
start_time_ts, single_metadata_id, no_attributes, False
|
||||||
).subquery(),
|
).subquery(),
|
||||||
no_attributes,
|
no_attributes,
|
||||||
|
False,
|
||||||
),
|
),
|
||||||
_select_from_subquery(stmt.subquery(), no_attributes),
|
_select_from_subquery(stmt.subquery(), no_attributes, False),
|
||||||
).subquery(),
|
).subquery(),
|
||||||
no_attributes,
|
no_attributes,
|
||||||
|
False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -499,11 +498,12 @@ def _get_start_time_state_for_entities_stmt(
|
|||||||
epoch_time: float,
|
epoch_time: float,
|
||||||
metadata_ids: list[int],
|
metadata_ids: list[int],
|
||||||
no_attributes: bool,
|
no_attributes: bool,
|
||||||
|
include_last_changed: bool,
|
||||||
) -> Select:
|
) -> Select:
|
||||||
"""Baked query to get states for specific entities."""
|
"""Baked query to get states for specific entities."""
|
||||||
# We got an include-list of entities, accelerate the query by filtering already
|
# We got an include-list of entities, accelerate the query by filtering already
|
||||||
# in the inner query.
|
# in the inner query.
|
||||||
stmt = _stmt_and_join_attributes(no_attributes, True).join(
|
stmt = _stmt_and_join_attributes(no_attributes, include_last_changed).join(
|
||||||
(
|
(
|
||||||
most_recent_states_for_entities_by_date := (
|
most_recent_states_for_entities_by_date := (
|
||||||
select(
|
select(
|
||||||
@@ -555,32 +555,29 @@ def _get_start_time_state_stmt(
|
|||||||
single_metadata_id: int | None,
|
single_metadata_id: int | None,
|
||||||
metadata_ids: list[int],
|
metadata_ids: list[int],
|
||||||
no_attributes: bool,
|
no_attributes: bool,
|
||||||
|
include_last_changed: bool,
|
||||||
) -> Select:
|
) -> Select:
|
||||||
"""Return the states at a specific point in time."""
|
"""Return the states at a specific point in time."""
|
||||||
if single_metadata_id:
|
if single_metadata_id:
|
||||||
# Use an entirely different (and extremely fast) query if we only
|
# Use an entirely different (and extremely fast) query if we only
|
||||||
# have a single entity id
|
# have a single entity id
|
||||||
return _get_single_entity_start_time_stmt(
|
return _get_single_entity_start_time_stmt(
|
||||||
epoch_time,
|
epoch_time, single_metadata_id, no_attributes, include_last_changed
|
||||||
single_metadata_id,
|
|
||||||
no_attributes,
|
|
||||||
)
|
)
|
||||||
# We have more than one entity to look at so we need to do a query on states
|
# We have more than one entity to look at so we need to do a query on states
|
||||||
# since the last recorder run started.
|
# since the last recorder run started.
|
||||||
return _get_start_time_state_for_entities_stmt(
|
return _get_start_time_state_for_entities_stmt(
|
||||||
run_start_ts, epoch_time, metadata_ids, no_attributes
|
run_start_ts, epoch_time, metadata_ids, no_attributes, include_last_changed
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_single_entity_start_time_stmt(
|
def _get_single_entity_start_time_stmt(
|
||||||
epoch_time: float,
|
epoch_time: float, metadata_id: int, no_attributes: bool, include_last_changed: bool
|
||||||
metadata_id: int,
|
|
||||||
no_attributes: bool,
|
|
||||||
) -> Select:
|
) -> Select:
|
||||||
# Use an entirely different (and extremely fast) query if we only
|
# Use an entirely different (and extremely fast) query if we only
|
||||||
# have a single entity id
|
# have a single entity id
|
||||||
stmt = (
|
stmt = (
|
||||||
_stmt_and_join_attributes(no_attributes, True)
|
_stmt_and_join_attributes(no_attributes, include_last_changed)
|
||||||
.filter(
|
.filter(
|
||||||
States.last_updated_ts < epoch_time,
|
States.last_updated_ts < epoch_time,
|
||||||
States.metadata_id == metadata_id,
|
States.metadata_id == metadata_id,
|
||||||
|
@@ -63,7 +63,7 @@ class LazyState(State):
|
|||||||
dt_util.utc_to_timestamp(start_time) if start_time else None
|
dt_util.utc_to_timestamp(start_time) if start_time else None
|
||||||
)
|
)
|
||||||
self._last_changed_ts: float | None = (
|
self._last_changed_ts: float | None = (
|
||||||
self._row.last_changed_ts or self._last_updated_ts
|
getattr(self._row, "last_changed_ts", None) or self._last_updated_ts
|
||||||
)
|
)
|
||||||
self._context: Context | None = None
|
self._context: Context | None = None
|
||||||
self.attr_cache = attr_cache
|
self.attr_cache = attr_cache
|
||||||
|
@@ -912,7 +912,7 @@ def test_execute_stmt_lambda_element(
|
|||||||
start_time_ts = dt_util.utcnow().timestamp()
|
start_time_ts = dt_util.utcnow().timestamp()
|
||||||
stmt = lambda_stmt(
|
stmt = lambda_stmt(
|
||||||
lambda: _get_single_entity_start_time_stmt(
|
lambda: _get_single_entity_start_time_stmt(
|
||||||
start_time_ts, metadata_id, False
|
start_time_ts, metadata_id, False, False
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
rows = util.execute_stmt_lambda_element(session, stmt)
|
rows = util.execute_stmt_lambda_element(session, stmt)
|
||||||
|
Reference in New Issue
Block a user