Home Assistant Unofficial Reference 2024.12.1
devices.py
Go to the documentation of this file.
1 """Devices queries for logbook."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Iterable
6 
7 import sqlalchemy
8 from sqlalchemy import lambda_stmt, select
9 from sqlalchemy.sql.elements import BooleanClauseList
10 from sqlalchemy.sql.lambdas import StatementLambdaElement
11 from sqlalchemy.sql.selectable import CTE, CompoundSelect, Select
12 
14  DEVICE_ID_IN_EVENT,
15  EventData,
16  Events,
17  EventTypes,
18  States,
19  StatesMeta,
20 )
21 
22 from .common import (
23  apply_events_context_hints,
24  apply_states_context_hints,
25  select_events_context_id_subquery,
26  select_events_context_only,
27  select_events_without_states,
28  select_states_context_only,
29 )
30 
31 
33  start_day: float,
34  end_day: float,
35  event_type_ids: tuple[int, ...],
36  json_quotable_device_ids: list[str],
37 ) -> Select:
38  """Generate a subquery to find context ids for multiple devices."""
39  inner = (
40  select_events_context_id_subquery(start_day, end_day, event_type_ids)
41  .where(apply_event_device_id_matchers(json_quotable_device_ids))
42  .subquery()
43  )
44  return select(inner.c.context_id_bin).group_by(inner.c.context_id_bin)
45 
46 
48  sel: Select,
49  start_day: float,
50  end_day: float,
51  event_type_ids: tuple[int, ...],
52  json_quotable_device_ids: list[str],
53 ) -> CompoundSelect:
54  """Generate a CTE to find the device context ids and a query to find linked row."""
55  devices_cte: CTE = _select_device_id_context_ids_sub_query(
56  start_day,
57  end_day,
58  event_type_ids,
59  json_quotable_device_ids,
60  ).cte()
61  return sel.union_all(
64  .select_from(devices_cte)
65  .outerjoin(Events, devices_cte.c.context_id_bin == Events.context_id_bin)
66  .outerjoin(EventTypes, (Events.event_type_id == EventTypes.event_type_id))
67  .outerjoin(EventData, (Events.data_id == EventData.data_id)),
68  ),
71  .select_from(devices_cte)
72  .outerjoin(States, devices_cte.c.context_id_bin == States.context_id_bin)
73  .outerjoin(StatesMeta, (States.metadata_id == StatesMeta.metadata_id))
74  ),
75  )
76 
77 
79  start_day: float,
80  end_day: float,
81  event_type_ids: tuple[int, ...],
82  json_quotable_device_ids: list[str],
83 ) -> StatementLambdaElement:
84  """Generate a logbook query for multiple devices."""
85  return lambda_stmt(
87  select_events_without_states(start_day, end_day, event_type_ids).where(
88  apply_event_device_id_matchers(json_quotable_device_ids)
89  ),
90  start_day,
91  end_day,
92  event_type_ids,
93  json_quotable_device_ids,
94  ).order_by(Events.time_fired_ts)
95  )
96 
97 
99  json_quotable_device_ids: Iterable[str],
100 ) -> BooleanClauseList:
101  """Create matchers for the device_ids in the event_data."""
102  return DEVICE_ID_IN_EVENT.is_not(None) & sqlalchemy.cast(
103  DEVICE_ID_IN_EVENT, sqlalchemy.Text()
104  ).in_(json_quotable_device_ids)
Select select_events_without_states(float start_day, float end_day, tuple[int,...] event_type_ids)
Definition: common.py:147
Select select_events_context_id_subquery(float start_day, float end_day, tuple[int,...] event_type_ids)
Definition: common.py:114
CompoundSelect _apply_devices_context_union(Select sel, float start_day, float end_day, tuple[int,...] event_type_ids, list[str] json_quotable_device_ids)
Definition: devices.py:53
Select _select_device_id_context_ids_sub_query(float start_day, float end_day, tuple[int,...] event_type_ids, list[str] json_quotable_device_ids)
Definition: devices.py:37
StatementLambdaElement devices_stmt(float start_day, float end_day, tuple[int,...] event_type_ids, list[str] json_quotable_device_ids)
Definition: devices.py:83
BooleanClauseList apply_event_device_id_matchers(Iterable[str] json_quotable_device_ids)
Definition: devices.py:100