2022-05-18 06:58:30 +00:00
|
|
|
"""All queries for logbook."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
2022-06-23 18:59:55 +00:00
|
|
|
from sqlalchemy import lambda_stmt
|
|
|
|
from sqlalchemy.sql.lambdas import StatementLambdaElement
|
2023-02-08 14:17:32 +00:00
|
|
|
from sqlalchemy.sql.selectable import Select
|
2022-05-18 06:58:30 +00:00
|
|
|
|
2022-06-07 12:41:43 +00:00
|
|
|
from homeassistant.components.recorder.db_schema import (
|
2023-01-02 23:26:08 +00:00
|
|
|
LAST_UPDATED_INDEX_TS,
|
2022-06-07 12:41:43 +00:00
|
|
|
Events,
|
|
|
|
States,
|
|
|
|
)
|
2023-03-28 18:50:10 +00:00
|
|
|
from homeassistant.components.recorder.filters import Filters
|
2022-05-18 06:58:30 +00:00
|
|
|
|
2023-03-20 02:05:07 +00:00
|
|
|
from .common import apply_states_filters, select_events_without_states, select_states
|
2022-05-18 06:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
def all_stmt(
|
2023-01-02 23:26:08 +00:00
|
|
|
start_day: float,
|
|
|
|
end_day: float,
|
2023-04-18 03:40:03 +00:00
|
|
|
event_type_ids: tuple[int, ...],
|
2023-03-28 18:50:10 +00:00
|
|
|
filters: Filters | None,
|
2023-03-09 00:51:45 +00:00
|
|
|
context_id_bin: bytes | None = None,
|
2022-06-23 18:59:55 +00:00
|
|
|
) -> StatementLambdaElement:
|
2022-05-18 06:58:30 +00:00
|
|
|
"""Generate a logbook query for all entities."""
|
2022-06-23 18:59:55 +00:00
|
|
|
stmt = lambda_stmt(
|
2023-04-18 03:40:03 +00:00
|
|
|
lambda: select_events_without_states(start_day, end_day, event_type_ids)
|
2022-06-23 18:59:55 +00:00
|
|
|
)
|
2023-03-09 00:51:45 +00:00
|
|
|
if context_id_bin is not None:
|
|
|
|
stmt += lambda s: s.where(Events.context_id_bin == context_id_bin).union_all(
|
2023-02-08 14:17:32 +00:00
|
|
|
_states_query_for_context_id(
|
|
|
|
start_day,
|
|
|
|
end_day,
|
|
|
|
# https://github.com/python/mypy/issues/2608
|
2023-03-09 00:51:45 +00:00
|
|
|
context_id_bin, # type:ignore[arg-type]
|
2023-02-08 14:17:32 +00:00
|
|
|
),
|
2022-05-18 06:58:30 +00:00
|
|
|
)
|
2023-03-28 18:50:10 +00:00
|
|
|
elif filters and filters.has_config:
|
|
|
|
stmt = stmt.add_criteria(
|
|
|
|
lambda q: q.filter(filters.events_entity_filter()).union_all( # type: ignore[union-attr]
|
2023-02-08 14:17:32 +00:00
|
|
|
_states_query_for_all(start_day, end_day).where(
|
2023-03-28 18:50:10 +00:00
|
|
|
filters.states_metadata_entity_filter() # type: ignore[union-attr]
|
2023-02-08 14:17:32 +00:00
|
|
|
)
|
2023-03-28 18:50:10 +00:00
|
|
|
),
|
|
|
|
track_on=[filters],
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
stmt += lambda s: s.union_all(_states_query_for_all(start_day, end_day))
|
2022-05-26 01:17:08 +00:00
|
|
|
|
2023-01-02 23:26:08 +00:00
|
|
|
stmt += lambda s: s.order_by(Events.time_fired_ts)
|
2022-06-23 18:59:55 +00:00
|
|
|
return stmt
|
2022-05-18 06:58:30 +00:00
|
|
|
|
|
|
|
|
2023-02-08 14:17:32 +00:00
|
|
|
def _states_query_for_all(start_day: float, end_day: float) -> Select:
|
2022-05-18 06:58:30 +00:00
|
|
|
return apply_states_filters(_apply_all_hints(select_states()), start_day, end_day)
|
|
|
|
|
|
|
|
|
2023-02-08 14:17:32 +00:00
|
|
|
def _apply_all_hints(sel: Select) -> Select:
|
2022-05-18 06:58:30 +00:00
|
|
|
"""Force mysql to use the right index on large selects."""
|
2023-02-08 14:17:32 +00:00
|
|
|
return sel.with_hint(
|
2023-01-02 23:26:08 +00:00
|
|
|
States, f"FORCE INDEX ({LAST_UPDATED_INDEX_TS})", dialect_name="mysql"
|
2023-03-09 00:51:45 +00:00
|
|
|
).with_hint(
|
|
|
|
States, f"FORCE INDEX ({LAST_UPDATED_INDEX_TS})", dialect_name="mariadb"
|
2022-05-18 06:58:30 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-01-02 23:26:08 +00:00
|
|
|
def _states_query_for_context_id(
|
2023-03-09 00:51:45 +00:00
|
|
|
start_day: float, end_day: float, context_id_bin: bytes
|
2023-02-08 14:17:32 +00:00
|
|
|
) -> Select:
|
2022-05-18 06:58:30 +00:00
|
|
|
return apply_states_filters(select_states(), start_day, end_day).where(
|
2023-03-09 00:51:45 +00:00
|
|
|
States.context_id_bin == context_id_bin
|
2022-05-18 06:58:30 +00:00
|
|
|
)
|