diff --git a/homeassistant/components/logbook/processor.py b/homeassistant/components/logbook/processor.py index 967d0f27ed2..0d3e38d5496 100644 --- a/homeassistant/components/logbook/processor.py +++ b/homeassistant/components/logbook/processor.py @@ -14,6 +14,7 @@ from homeassistant.components.recorder import get_instance from homeassistant.components.recorder.filters import Filters from homeassistant.components.recorder.models import ( bytes_to_uuid_hex_or_none, + extract_event_type_ids, extract_metadata_ids, process_datetime_to_timestamp, process_timestamp_to_utc_isoformat, @@ -153,17 +154,22 @@ class EventProcessor: with session_scope(hass=self.hass, read_only=True) as session: metadata_ids: list[int] | None = None + instance = get_instance(self.hass) if self.entity_ids: - instance = get_instance(self.hass) metadata_ids = extract_metadata_ids( instance.states_meta_manager.get_many( self.entity_ids, session, False ) ) + event_type_ids = tuple( + extract_event_type_ids( + instance.event_type_manager.get_many(self.event_types, session) + ) + ) stmt = statement_for_request( start_day, end_day, - self.event_types, + event_type_ids, self.entity_ids, metadata_ids, self.device_ids, diff --git a/homeassistant/components/logbook/queries/__init__.py b/homeassistant/components/logbook/queries/__init__.py index b83f7a4428a..29d89a4c22f 100644 --- a/homeassistant/components/logbook/queries/__init__.py +++ b/homeassistant/components/logbook/queries/__init__.py @@ -20,7 +20,7 @@ from .entities_and_devices import entities_devices_stmt def statement_for_request( start_day_dt: dt, end_day_dt: dt, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], entity_ids: list[str] | None = None, states_metadata_ids: Collection[int] | None = None, device_ids: list[str] | None = None, @@ -37,7 +37,7 @@ def statement_for_request( return all_stmt( start_day, end_day, - event_types, + event_type_ids, filters, context_id_bin, ) @@ -52,7 +52,7 @@ def statement_for_request( return entities_devices_stmt( start_day, end_day, - event_types, + event_type_ids, states_metadata_ids or [], [json_dumps(entity_id) for entity_id in entity_ids], [json_dumps(device_id) for device_id in device_ids], @@ -63,7 +63,7 @@ def statement_for_request( return entities_stmt( start_day, end_day, - event_types, + event_type_ids, states_metadata_ids or [], [json_dumps(entity_id) for entity_id in entity_ids], ) @@ -73,6 +73,6 @@ def statement_for_request( return devices_stmt( start_day, end_day, - event_types, + event_type_ids, [json_dumps(device_id) for device_id in device_ids], ) diff --git a/homeassistant/components/logbook/queries/all.py b/homeassistant/components/logbook/queries/all.py index 70214fbb04b..c6196687ac2 100644 --- a/homeassistant/components/logbook/queries/all.py +++ b/homeassistant/components/logbook/queries/all.py @@ -18,13 +18,13 @@ from .common import apply_states_filters, select_events_without_states, select_s def all_stmt( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], filters: Filters | None, context_id_bin: bytes | None = None, ) -> StatementLambdaElement: """Generate a logbook query for all entities.""" stmt = lambda_stmt( - lambda: select_events_without_states(start_day, end_day, event_types) + lambda: select_events_without_states(start_day, end_day, event_type_ids) ) if context_id_bin is not None: stmt += lambda s: s.where(Events.context_id_bin == context_id_bin).union_all( diff --git a/homeassistant/components/logbook/queries/common.py b/homeassistant/components/logbook/queries/common.py index 08bf1b8ab9b..c141f2ed1ec 100644 --- a/homeassistant/components/logbook/queries/common.py +++ b/homeassistant/components/logbook/queries/common.py @@ -23,7 +23,6 @@ from homeassistant.components.recorder.db_schema import ( StatesMeta, ) from homeassistant.components.recorder.filters import like_domain_matchers -from homeassistant.components.recorder.queries import select_event_type_ids from ..const import ALWAYS_CONTINUOUS_DOMAINS, CONDITIONALLY_CONTINUOUS_DOMAINS @@ -112,13 +111,13 @@ NOT_CONTEXT_ONLY = literal(value=None, type_=sqlalchemy.String).label("context_o def select_events_context_id_subquery( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], ) -> Select: """Generate the select for a context_id subquery.""" return ( select(Events.context_id_bin) .where((Events.time_fired_ts > start_day) & (Events.time_fired_ts < end_day)) - .where(Events.event_type_id.in_(select_event_type_ids(event_types))) + .where(Events.event_type_id.in_(event_type_ids)) .outerjoin(EventTypes, (Events.event_type_id == EventTypes.event_type_id)) .outerjoin(EventData, (Events.data_id == EventData.data_id)) ) @@ -145,13 +144,13 @@ def select_states_context_only() -> Select: def select_events_without_states( - start_day: float, end_day: float, event_types: tuple[str, ...] + start_day: float, end_day: float, event_type_ids: tuple[int, ...] ) -> Select: """Generate an events select that does not join states.""" return ( select(*EVENT_ROWS_NO_STATES, NOT_CONTEXT_ONLY) .where((Events.time_fired_ts > start_day) & (Events.time_fired_ts < end_day)) - .where(Events.event_type_id.in_(select_event_type_ids(event_types))) + .where(Events.event_type_id.in_(event_type_ids)) .outerjoin(EventTypes, (Events.event_type_id == EventTypes.event_type_id)) .outerjoin(EventData, (Events.data_id == EventData.data_id)) ) diff --git a/homeassistant/components/logbook/queries/devices.py b/homeassistant/components/logbook/queries/devices.py index a5c06dc84cf..75604de6104 100644 --- a/homeassistant/components/logbook/queries/devices.py +++ b/homeassistant/components/logbook/queries/devices.py @@ -31,12 +31,12 @@ from .common import ( def _select_device_id_context_ids_sub_query( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], json_quotable_device_ids: list[str], ) -> Select: """Generate a subquery to find context ids for multiple devices.""" inner = ( - select_events_context_id_subquery(start_day, end_day, event_types) + select_events_context_id_subquery(start_day, end_day, event_type_ids) .where(apply_event_device_id_matchers(json_quotable_device_ids)) .subquery() ) @@ -47,14 +47,14 @@ def _apply_devices_context_union( sel: Select, start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], json_quotable_device_ids: list[str], ) -> CompoundSelect: """Generate a CTE to find the device context ids and a query to find linked row.""" devices_cte: CTE = _select_device_id_context_ids_sub_query( start_day, end_day, - event_types, + event_type_ids, json_quotable_device_ids, ).cte() return sel.union_all( @@ -77,18 +77,18 @@ def _apply_devices_context_union( def devices_stmt( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], json_quotable_device_ids: list[str], ) -> StatementLambdaElement: """Generate a logbook query for multiple devices.""" stmt = lambda_stmt( lambda: _apply_devices_context_union( - select_events_without_states(start_day, end_day, event_types).where( + select_events_without_states(start_day, end_day, event_type_ids).where( apply_event_device_id_matchers(json_quotable_device_ids) ), start_day, end_day, - event_types, + event_type_ids, json_quotable_device_ids, ).order_by(Events.time_fired_ts) ) diff --git a/homeassistant/components/logbook/queries/entities.py b/homeassistant/components/logbook/queries/entities.py index ebb56befa50..95c1d565263 100644 --- a/homeassistant/components/logbook/queries/entities.py +++ b/homeassistant/components/logbook/queries/entities.py @@ -35,13 +35,13 @@ from .common import ( def _select_entities_context_ids_sub_query( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], states_metadata_ids: Collection[int], json_quoted_entity_ids: list[str], ) -> Select: """Generate a subquery to find context ids for multiple entities.""" union = union_all( - select_events_context_id_subquery(start_day, end_day, event_types).where( + select_events_context_id_subquery(start_day, end_day, event_type_ids).where( apply_event_entity_id_matchers(json_quoted_entity_ids) ), apply_entities_hints(select(States.context_id_bin)) @@ -57,7 +57,7 @@ def _apply_entities_context_union( sel: Select, start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], states_metadata_ids: Collection[int], json_quoted_entity_ids: list[str], ) -> CompoundSelect: @@ -65,7 +65,7 @@ def _apply_entities_context_union( entities_cte: CTE = _select_entities_context_ids_sub_query( start_day, end_day, - event_types, + event_type_ids, states_metadata_ids, json_quoted_entity_ids, ).cte() @@ -95,19 +95,19 @@ def _apply_entities_context_union( def entities_stmt( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], states_metadata_ids: Collection[int], json_quoted_entity_ids: list[str], ) -> StatementLambdaElement: """Generate a logbook query for multiple entities.""" return lambda_stmt( lambda: _apply_entities_context_union( - select_events_without_states(start_day, end_day, event_types).where( + select_events_without_states(start_day, end_day, event_type_ids).where( apply_event_entity_id_matchers(json_quoted_entity_ids) ), start_day, end_day, - event_types, + event_type_ids, states_metadata_ids, json_quoted_entity_ids, ).order_by(Events.time_fired_ts) diff --git a/homeassistant/components/logbook/queries/entities_and_devices.py b/homeassistant/components/logbook/queries/entities_and_devices.py index f7ffde4f81a..c465a343d61 100644 --- a/homeassistant/components/logbook/queries/entities_and_devices.py +++ b/homeassistant/components/logbook/queries/entities_and_devices.py @@ -35,14 +35,14 @@ from .entities import ( def _select_entities_device_id_context_ids_sub_query( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], states_metadata_ids: Collection[int], json_quoted_entity_ids: list[str], json_quoted_device_ids: list[str], ) -> Select: """Generate a subquery to find context ids for multiple entities and multiple devices.""" union = union_all( - select_events_context_id_subquery(start_day, end_day, event_types).where( + select_events_context_id_subquery(start_day, end_day, event_type_ids).where( _apply_event_entity_id_device_id_matchers( json_quoted_entity_ids, json_quoted_device_ids ) @@ -60,7 +60,7 @@ def _apply_entities_devices_context_union( sel: Select, start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], states_metadata_ids: Collection[int], json_quoted_entity_ids: list[str], json_quoted_device_ids: list[str], @@ -68,7 +68,7 @@ def _apply_entities_devices_context_union( devices_entities_cte: CTE = _select_entities_device_id_context_ids_sub_query( start_day, end_day, - event_types, + event_type_ids, states_metadata_ids, json_quoted_entity_ids, json_quoted_device_ids, @@ -103,7 +103,7 @@ def _apply_entities_devices_context_union( def entities_devices_stmt( start_day: float, end_day: float, - event_types: tuple[str, ...], + event_type_ids: tuple[int, ...], states_metadata_ids: Collection[int], json_quoted_entity_ids: list[str], json_quoted_device_ids: list[str], @@ -111,14 +111,14 @@ def entities_devices_stmt( """Generate a logbook query for multiple entities.""" stmt = lambda_stmt( lambda: _apply_entities_devices_context_union( - select_events_without_states(start_day, end_day, event_types).where( + select_events_without_states(start_day, end_day, event_type_ids).where( _apply_event_entity_id_device_id_matchers( json_quoted_entity_ids, json_quoted_device_ids ) ), start_day, end_day, - event_types, + event_type_ids, states_metadata_ids, json_quoted_entity_ids, json_quoted_device_ids, diff --git a/homeassistant/components/recorder/models/__init__.py b/homeassistant/components/recorder/models/__init__.py index 91dd80c4aa2..1a204e767e3 100644 --- a/homeassistant/components/recorder/models/__init__.py +++ b/homeassistant/components/recorder/models/__init__.py @@ -8,6 +8,7 @@ from .context import ( uuid_hex_to_bytes_or_none, ) from .database import DatabaseEngine, DatabaseOptimizer, UnsupportedDialect +from .event import extract_event_type_ids from .state import LazyState, extract_metadata_ids, row_to_compressed_state from .statistics import ( CalendarStatisticPeriod, @@ -43,6 +44,7 @@ __all__ = [ "bytes_to_ulid_or_none", "bytes_to_uuid_hex_or_none", "datetime_to_timestamp_or_none", + "extract_event_type_ids", "extract_metadata_ids", "process_datetime_to_timestamp", "process_timestamp", diff --git a/homeassistant/components/recorder/models/event.py b/homeassistant/components/recorder/models/event.py new file mode 100644 index 00000000000..1d644b62f46 --- /dev/null +++ b/homeassistant/components/recorder/models/event.py @@ -0,0 +1,13 @@ +"""Models events in for Recorder.""" +from __future__ import annotations + + +def extract_event_type_ids( + event_type_to_event_type_id: dict[str, int | None], +) -> list[int]: + """Extract event_type ids from event_type_to_event_type_id.""" + return [ + event_type_id + for event_type_id in event_type_to_event_type_id.values() + if event_type_id is not None + ]