diff --git a/homeassistant/components/logbook/models.py b/homeassistant/components/logbook/models.py index a7d3c517309..86dcfdf82c5 100644 --- a/homeassistant/components/logbook/models.py +++ b/homeassistant/components/logbook/models.py @@ -71,7 +71,7 @@ class LazyEventPartialState: # json decode process as we already have the data self.data = row.data return - source = cast(str, self.row.shared_data or self.row.event_data) + source = cast(str, self.row.event_data) if not source: self.data = {} elif event_data := self._event_data_cache.get(source): @@ -105,17 +105,14 @@ class EventAsRow: context: Context context_id_bin: bytes time_fired_ts: float - state_id: int + row_id: int event_data: str | None = None - old_format_icon: None = None - event_id: None = None entity_id: str | None = None icon: str | None = None context_user_id_bin: bytes | None = None context_parent_id_bin: bytes | None = None event_type: str | None = None state: str | None = None - shared_data: str | None = None context_only: None = None @@ -132,7 +129,7 @@ def async_event_to_row(event: Event) -> EventAsRow: context_user_id_bin=uuid_hex_to_bytes_or_none(context.user_id), context_parent_id_bin=ulid_to_bytes_or_none(context.parent_id), time_fired_ts=dt_util.utc_to_timestamp(event.time_fired), - state_id=hash(event), + row_id=hash(event), ) # States are prefiltered so we never get states # that are missing new_state or old_state @@ -148,6 +145,6 @@ def async_event_to_row(event: Event) -> EventAsRow: context_user_id_bin=uuid_hex_to_bytes_or_none(context.user_id), context_parent_id_bin=ulid_to_bytes_or_none(context.parent_id), time_fired_ts=dt_util.utc_to_timestamp(new_state.last_updated), - state_id=hash(event), + row_id=hash(event), icon=new_state.attributes.get(ATTR_ICON), ) diff --git a/homeassistant/components/logbook/processor.py b/homeassistant/components/logbook/processor.py index d1b8b0ab17c..3aa486272e1 100644 --- a/homeassistant/components/logbook/processor.py +++ b/homeassistant/components/logbook/processor.py @@ -227,7 +227,7 @@ def _humanify( } if include_entity_name: data[LOGBOOK_ENTRY_NAME] = entity_name_cache.get(entity_id) - if icon := row.icon or row.old_format_icon: + if icon := row.icon: data[LOGBOOK_ENTRY_ICON] = icon context_augmenter.augment(data, row, context_id_bin) @@ -358,15 +358,9 @@ class ContextAugmenter: def _rows_match(row: Row | EventAsRow, other_row: Row | EventAsRow) -> bool: """Check of rows match by using the same method as Events __hash__.""" - if ( - row is other_row - or (state_id := row.state_id) - and state_id == other_row.state_id - or (event_id := row.event_id) - and event_id == other_row.event_id - ): - return True - return False + return bool( + row is other_row or (row_id := row.row_id) and row_id == other_row.row_id + ) def _row_time_fired_isoformat(row: Row | EventAsRow) -> str: diff --git a/homeassistant/components/logbook/queries/common.py b/homeassistant/components/logbook/queries/common.py index c141f2ed1ec..cbbe8724ece 100644 --- a/homeassistant/components/logbook/queries/common.py +++ b/homeassistant/components/logbook/queries/common.py @@ -14,6 +14,7 @@ from homeassistant.components.recorder.db_schema import ( OLD_FORMAT_ATTRS_JSON, OLD_STATE, SHARED_ATTRS_JSON, + SHARED_DATA_OR_LEGACY_EVENT_DATA, STATES_CONTEXT_ID_BIN_INDEX, EventData, Events, @@ -36,6 +37,11 @@ ALWAYS_CONTINUOUS_ENTITY_ID_LIKE = like_domain_matchers(ALWAYS_CONTINUOUS_DOMAIN UNIT_OF_MEASUREMENT_JSON = '"unit_of_measurement":' UNIT_OF_MEASUREMENT_JSON_LIKE = f"%{UNIT_OF_MEASUREMENT_JSON}%" +ICON_OR_OLD_FORMAT_ICON_JSON = sqlalchemy.case( + (SHARED_ATTRS_JSON["icon"].is_(None), OLD_FORMAT_ATTRS_JSON["icon"].as_string()), + else_=SHARED_ATTRS_JSON["icon"].as_string(), +).label("icon") + PSEUDO_EVENT_STATE_CHANGED: Final = None # Since we don't store event_types and None # and we don't store state_changed in events @@ -45,9 +51,9 @@ PSEUDO_EVENT_STATE_CHANGED: Final = None # in the payload EVENT_COLUMNS = ( - Events.event_id.label("event_id"), + Events.event_id.label("row_id"), EventTypes.event_type.label("event_type"), - Events.event_data.label("event_data"), + SHARED_DATA_OR_LEGACY_EVENT_DATA, Events.time_fired_ts.label("time_fired_ts"), Events.context_id_bin.label("context_id_bin"), Events.context_user_id_bin.label("context_user_id_bin"), @@ -55,23 +61,19 @@ EVENT_COLUMNS = ( ) STATE_COLUMNS = ( - States.state_id.label("state_id"), States.state.label("state"), StatesMeta.entity_id.label("entity_id"), - SHARED_ATTRS_JSON["icon"].as_string().label("icon"), - OLD_FORMAT_ATTRS_JSON["icon"].as_string().label("old_format_icon"), + ICON_OR_OLD_FORMAT_ICON_JSON, ) STATE_CONTEXT_ONLY_COLUMNS = ( - States.state_id.label("state_id"), States.state.label("state"), StatesMeta.entity_id.label("entity_id"), literal(value=None, type_=sqlalchemy.String).label("icon"), - literal(value=None, type_=sqlalchemy.String).label("old_format_icon"), ) EVENT_COLUMNS_FOR_STATE_SELECT = ( - literal(value=None, type_=sqlalchemy.Text).label("event_id"), + States.state_id.label("row_id"), # We use PSEUDO_EVENT_STATE_CHANGED aka None for # state_changed events since it takes up less # space in the response and every row has to be @@ -84,21 +86,17 @@ EVENT_COLUMNS_FOR_STATE_SELECT = ( States.context_id_bin.label("context_id_bin"), States.context_user_id_bin.label("context_user_id_bin"), States.context_parent_id_bin.label("context_parent_id_bin"), - literal(value=None, type_=sqlalchemy.Text).label("shared_data"), ) EMPTY_STATE_COLUMNS = ( - literal(value=0, type_=sqlalchemy.Integer).label("state_id"), literal(value=None, type_=sqlalchemy.String).label("state"), literal(value=None, type_=sqlalchemy.String).label("entity_id"), literal(value=None, type_=sqlalchemy.String).label("icon"), - literal(value=None, type_=sqlalchemy.String).label("old_format_icon"), ) EVENT_ROWS_NO_STATES = ( *EVENT_COLUMNS, - EventData.shared_data.label("shared_data"), *EMPTY_STATE_COLUMNS, ) diff --git a/tests/components/logbook/common.py b/tests/components/logbook/common.py index 75e4cd40392..9fe6c2b60a8 100644 --- a/tests/components/logbook/common.py +++ b/tests/components/logbook/common.py @@ -29,7 +29,7 @@ class MockRow: ): """Init the fake row.""" self.event_type = event_type - self.shared_data = json.dumps(data, cls=JSONEncoder) + self.event_data = json.dumps(data, cls=JSONEncoder) self.data = data self.time_fired = dt_util.utcnow() self.time_fired_ts = dt_util.utc_to_timestamp(self.time_fired) @@ -42,8 +42,7 @@ class MockRow: self.context_id_bin = ulid_to_bytes_or_none(context.id) if context else None self.state = None self.entity_id = None - self.state_id = None - self.event_id = None + self.row_id = None self.shared_attrs = None self.attributes = None self.context_only = False diff --git a/tests/components/logbook/test_init.py b/tests/components/logbook/test_init.py index c4f2f0a9ee2..c961d40574d 100644 --- a/tests/components/logbook/test_init.py +++ b/tests/components/logbook/test_init.py @@ -352,7 +352,6 @@ def create_state_changed_event_from_old_new( row.context_id_bin = None row.friendly_name = None row.icon = None - row.old_format_icon = None row.context_user_id_bin = None row.context_parent_id_bin = None row.old_state_id = old_state and 1