Home Assistant Unofficial Reference 2024.12.1
queries.py
Go to the documentation of this file.
1 """Queries for the recorder."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Iterable
6 from datetime import datetime
7 
8 from sqlalchemy import delete, distinct, func, lambda_stmt, select, union_all, update
9 from sqlalchemy.sql.lambdas import StatementLambdaElement
10 from sqlalchemy.sql.selectable import Select
11 
12 from .db_schema import (
13  EventData,
14  Events,
15  EventTypes,
16  MigrationChanges,
17  RecorderRuns,
18  StateAttributes,
19  States,
20  StatesMeta,
21  Statistics,
22  StatisticsRuns,
23  StatisticsShortTerm,
24 )
25 
26 
27 def select_event_type_ids(event_types: tuple[str, ...]) -> Select:
28  """Generate a select for event type ids.
29 
30  This query is intentionally not a lambda statement as it is used inside
31  other lambda statements.
32  """
33  return select(EventTypes.event_type_id).where(
34  EventTypes.event_type.in_(event_types)
35  )
36 
37 
38 def get_shared_attributes(hashes: list[int]) -> StatementLambdaElement:
39  """Load shared attributes from the database."""
40  return lambda_stmt(
41  lambda: select(
42  StateAttributes.attributes_id, StateAttributes.shared_attrs
43  ).where(StateAttributes.hash.in_(hashes))
44  )
45 
46 
47 def get_shared_event_datas(hashes: list[int]) -> StatementLambdaElement:
48  """Load shared event data from the database."""
49  return lambda_stmt(
50  lambda: select(EventData.data_id, EventData.shared_data).where(
51  EventData.hash.in_(hashes)
52  )
53  )
54 
55 
56 def find_event_type_ids(event_types: Iterable[str]) -> StatementLambdaElement:
57  """Find an event_type id by event_type."""
58  return lambda_stmt(
59  lambda: select(EventTypes.event_type_id, EventTypes.event_type).filter(
60  EventTypes.event_type.in_(event_types)
61  )
62  )
63 
64 
65 def find_all_states_metadata_ids() -> StatementLambdaElement:
66  """Find all metadata_ids and entity_ids."""
67  return lambda_stmt(lambda: select(StatesMeta.metadata_id, StatesMeta.entity_id))
68 
69 
70 def find_states_metadata_ids(entity_ids: Iterable[str]) -> StatementLambdaElement:
71  """Find metadata_ids by entity_ids."""
72  return lambda_stmt(
73  lambda: select(StatesMeta.metadata_id, StatesMeta.entity_id).filter(
74  StatesMeta.entity_id.in_(entity_ids)
75  )
76  )
77 
78 
79 def _state_attrs_exist(attr: int | None) -> Select:
80  """Check if a state attributes id exists in the states table."""
81  return select(func.min(States.attributes_id)).where(States.attributes_id == attr)
82 
83 
85  attributes_ids: Iterable[int],
86 ) -> StatementLambdaElement:
87  """Find attributes ids that exist in the states table."""
88  return lambda_stmt(
89  lambda: select(distinct(States.attributes_id)).filter(
90  States.attributes_id.in_(attributes_ids)
91  )
92  )
93 
94 
96  attr1: int,
97  attr2: int | None,
98  attr3: int | None,
99  attr4: int | None,
100  attr5: int | None,
101  attr6: int | None,
102  attr7: int | None,
103  attr8: int | None,
104  attr9: int | None,
105  attr10: int | None,
106  attr11: int | None,
107  attr12: int | None,
108  attr13: int | None,
109  attr14: int | None,
110  attr15: int | None,
111  attr16: int | None,
112  attr17: int | None,
113  attr18: int | None,
114  attr19: int | None,
115  attr20: int | None,
116  attr21: int | None,
117  attr22: int | None,
118  attr23: int | None,
119  attr24: int | None,
120  attr25: int | None,
121  attr26: int | None,
122  attr27: int | None,
123  attr28: int | None,
124  attr29: int | None,
125  attr30: int | None,
126  attr31: int | None,
127  attr32: int | None,
128  attr33: int | None,
129  attr34: int | None,
130  attr35: int | None,
131  attr36: int | None,
132  attr37: int | None,
133  attr38: int | None,
134  attr39: int | None,
135  attr40: int | None,
136  attr41: int | None,
137  attr42: int | None,
138  attr43: int | None,
139  attr44: int | None,
140  attr45: int | None,
141  attr46: int | None,
142  attr47: int | None,
143  attr48: int | None,
144  attr49: int | None,
145  attr50: int | None,
146  attr51: int | None,
147  attr52: int | None,
148  attr53: int | None,
149  attr54: int | None,
150  attr55: int | None,
151  attr56: int | None,
152  attr57: int | None,
153  attr58: int | None,
154  attr59: int | None,
155  attr60: int | None,
156  attr61: int | None,
157  attr62: int | None,
158  attr63: int | None,
159  attr64: int | None,
160  attr65: int | None,
161  attr66: int | None,
162  attr67: int | None,
163  attr68: int | None,
164  attr69: int | None,
165  attr70: int | None,
166  attr71: int | None,
167  attr72: int | None,
168  attr73: int | None,
169  attr74: int | None,
170  attr75: int | None,
171  attr76: int | None,
172  attr77: int | None,
173  attr78: int | None,
174  attr79: int | None,
175  attr80: int | None,
176  attr81: int | None,
177  attr82: int | None,
178  attr83: int | None,
179  attr84: int | None,
180  attr85: int | None,
181  attr86: int | None,
182  attr87: int | None,
183  attr88: int | None,
184  attr89: int | None,
185  attr90: int | None,
186  attr91: int | None,
187  attr92: int | None,
188  attr93: int | None,
189  attr94: int | None,
190  attr95: int | None,
191  attr96: int | None,
192  attr97: int | None,
193  attr98: int | None,
194  attr99: int | None,
195  attr100: int | None,
196 ) -> StatementLambdaElement:
197  """Generate the find attributes select only once.
198 
199  https://docs.sqlalchemy.org/en/14/core/connections.html#quick-guidelines-for-lambdas
200  """
201  return lambda_stmt(
202  lambda: union_all(
203  _state_attrs_exist(attr1),
204  _state_attrs_exist(attr2),
205  _state_attrs_exist(attr3),
206  _state_attrs_exist(attr4),
207  _state_attrs_exist(attr5),
208  _state_attrs_exist(attr6),
209  _state_attrs_exist(attr7),
210  _state_attrs_exist(attr8),
211  _state_attrs_exist(attr9),
212  _state_attrs_exist(attr10),
213  _state_attrs_exist(attr11),
214  _state_attrs_exist(attr12),
215  _state_attrs_exist(attr13),
216  _state_attrs_exist(attr14),
217  _state_attrs_exist(attr15),
218  _state_attrs_exist(attr16),
219  _state_attrs_exist(attr17),
220  _state_attrs_exist(attr18),
221  _state_attrs_exist(attr19),
222  _state_attrs_exist(attr20),
223  _state_attrs_exist(attr21),
224  _state_attrs_exist(attr22),
225  _state_attrs_exist(attr23),
226  _state_attrs_exist(attr24),
227  _state_attrs_exist(attr25),
228  _state_attrs_exist(attr26),
229  _state_attrs_exist(attr27),
230  _state_attrs_exist(attr28),
231  _state_attrs_exist(attr29),
232  _state_attrs_exist(attr30),
233  _state_attrs_exist(attr31),
234  _state_attrs_exist(attr32),
235  _state_attrs_exist(attr33),
236  _state_attrs_exist(attr34),
237  _state_attrs_exist(attr35),
238  _state_attrs_exist(attr36),
239  _state_attrs_exist(attr37),
240  _state_attrs_exist(attr38),
241  _state_attrs_exist(attr39),
242  _state_attrs_exist(attr40),
243  _state_attrs_exist(attr41),
244  _state_attrs_exist(attr42),
245  _state_attrs_exist(attr43),
246  _state_attrs_exist(attr44),
247  _state_attrs_exist(attr45),
248  _state_attrs_exist(attr46),
249  _state_attrs_exist(attr47),
250  _state_attrs_exist(attr48),
251  _state_attrs_exist(attr49),
252  _state_attrs_exist(attr50),
253  _state_attrs_exist(attr51),
254  _state_attrs_exist(attr52),
255  _state_attrs_exist(attr53),
256  _state_attrs_exist(attr54),
257  _state_attrs_exist(attr55),
258  _state_attrs_exist(attr56),
259  _state_attrs_exist(attr57),
260  _state_attrs_exist(attr58),
261  _state_attrs_exist(attr59),
262  _state_attrs_exist(attr60),
263  _state_attrs_exist(attr61),
264  _state_attrs_exist(attr62),
265  _state_attrs_exist(attr63),
266  _state_attrs_exist(attr64),
267  _state_attrs_exist(attr65),
268  _state_attrs_exist(attr66),
269  _state_attrs_exist(attr67),
270  _state_attrs_exist(attr68),
271  _state_attrs_exist(attr69),
272  _state_attrs_exist(attr70),
273  _state_attrs_exist(attr71),
274  _state_attrs_exist(attr72),
275  _state_attrs_exist(attr73),
276  _state_attrs_exist(attr74),
277  _state_attrs_exist(attr75),
278  _state_attrs_exist(attr76),
279  _state_attrs_exist(attr77),
280  _state_attrs_exist(attr78),
281  _state_attrs_exist(attr79),
282  _state_attrs_exist(attr80),
283  _state_attrs_exist(attr81),
284  _state_attrs_exist(attr82),
285  _state_attrs_exist(attr83),
286  _state_attrs_exist(attr84),
287  _state_attrs_exist(attr85),
288  _state_attrs_exist(attr86),
289  _state_attrs_exist(attr87),
290  _state_attrs_exist(attr88),
291  _state_attrs_exist(attr89),
292  _state_attrs_exist(attr90),
293  _state_attrs_exist(attr91),
294  _state_attrs_exist(attr92),
295  _state_attrs_exist(attr93),
296  _state_attrs_exist(attr94),
297  _state_attrs_exist(attr95),
298  _state_attrs_exist(attr96),
299  _state_attrs_exist(attr97),
300  _state_attrs_exist(attr98),
301  _state_attrs_exist(attr99),
302  _state_attrs_exist(attr100),
303  )
304  )
305 
306 
308  data_ids: Iterable[int],
309 ) -> StatementLambdaElement:
310  """Find data ids that exist in the events table."""
311  return lambda_stmt(
312  lambda: select(distinct(Events.data_id)).filter(Events.data_id.in_(data_ids))
313  )
314 
315 
316 def _event_data_id_exist(data_id: int | None) -> Select:
317  """Check if a event data id exists in the events table."""
318  return select(func.min(Events.data_id)).where(Events.data_id == data_id)
319 
320 
322  id1: int,
323  id2: int | None,
324  id3: int | None,
325  id4: int | None,
326  id5: int | None,
327  id6: int | None,
328  id7: int | None,
329  id8: int | None,
330  id9: int | None,
331  id10: int | None,
332  id11: int | None,
333  id12: int | None,
334  id13: int | None,
335  id14: int | None,
336  id15: int | None,
337  id16: int | None,
338  id17: int | None,
339  id18: int | None,
340  id19: int | None,
341  id20: int | None,
342  id21: int | None,
343  id22: int | None,
344  id23: int | None,
345  id24: int | None,
346  id25: int | None,
347  id26: int | None,
348  id27: int | None,
349  id28: int | None,
350  id29: int | None,
351  id30: int | None,
352  id31: int | None,
353  id32: int | None,
354  id33: int | None,
355  id34: int | None,
356  id35: int | None,
357  id36: int | None,
358  id37: int | None,
359  id38: int | None,
360  id39: int | None,
361  id40: int | None,
362  id41: int | None,
363  id42: int | None,
364  id43: int | None,
365  id44: int | None,
366  id45: int | None,
367  id46: int | None,
368  id47: int | None,
369  id48: int | None,
370  id49: int | None,
371  id50: int | None,
372  id51: int | None,
373  id52: int | None,
374  id53: int | None,
375  id54: int | None,
376  id55: int | None,
377  id56: int | None,
378  id57: int | None,
379  id58: int | None,
380  id59: int | None,
381  id60: int | None,
382  id61: int | None,
383  id62: int | None,
384  id63: int | None,
385  id64: int | None,
386  id65: int | None,
387  id66: int | None,
388  id67: int | None,
389  id68: int | None,
390  id69: int | None,
391  id70: int | None,
392  id71: int | None,
393  id72: int | None,
394  id73: int | None,
395  id74: int | None,
396  id75: int | None,
397  id76: int | None,
398  id77: int | None,
399  id78: int | None,
400  id79: int | None,
401  id80: int | None,
402  id81: int | None,
403  id82: int | None,
404  id83: int | None,
405  id84: int | None,
406  id85: int | None,
407  id86: int | None,
408  id87: int | None,
409  id88: int | None,
410  id89: int | None,
411  id90: int | None,
412  id91: int | None,
413  id92: int | None,
414  id93: int | None,
415  id94: int | None,
416  id95: int | None,
417  id96: int | None,
418  id97: int | None,
419  id98: int | None,
420  id99: int | None,
421  id100: int | None,
422 ) -> StatementLambdaElement:
423  """Generate the find event data select only once.
424 
425  https://docs.sqlalchemy.org/en/14/core/connections.html#quick-guidelines-for-lambdas
426  """
427  return lambda_stmt(
428  lambda: union_all(
438  _event_data_id_exist(id10),
439  _event_data_id_exist(id11),
440  _event_data_id_exist(id12),
441  _event_data_id_exist(id13),
442  _event_data_id_exist(id14),
443  _event_data_id_exist(id15),
444  _event_data_id_exist(id16),
445  _event_data_id_exist(id17),
446  _event_data_id_exist(id18),
447  _event_data_id_exist(id19),
448  _event_data_id_exist(id20),
449  _event_data_id_exist(id21),
450  _event_data_id_exist(id22),
451  _event_data_id_exist(id23),
452  _event_data_id_exist(id24),
453  _event_data_id_exist(id25),
454  _event_data_id_exist(id26),
455  _event_data_id_exist(id27),
456  _event_data_id_exist(id28),
457  _event_data_id_exist(id29),
458  _event_data_id_exist(id30),
459  _event_data_id_exist(id31),
460  _event_data_id_exist(id32),
461  _event_data_id_exist(id33),
462  _event_data_id_exist(id34),
463  _event_data_id_exist(id35),
464  _event_data_id_exist(id36),
465  _event_data_id_exist(id37),
466  _event_data_id_exist(id38),
467  _event_data_id_exist(id39),
468  _event_data_id_exist(id40),
469  _event_data_id_exist(id41),
470  _event_data_id_exist(id42),
471  _event_data_id_exist(id43),
472  _event_data_id_exist(id44),
473  _event_data_id_exist(id45),
474  _event_data_id_exist(id46),
475  _event_data_id_exist(id47),
476  _event_data_id_exist(id48),
477  _event_data_id_exist(id49),
478  _event_data_id_exist(id50),
479  _event_data_id_exist(id51),
480  _event_data_id_exist(id52),
481  _event_data_id_exist(id53),
482  _event_data_id_exist(id54),
483  _event_data_id_exist(id55),
484  _event_data_id_exist(id56),
485  _event_data_id_exist(id57),
486  _event_data_id_exist(id58),
487  _event_data_id_exist(id59),
488  _event_data_id_exist(id60),
489  _event_data_id_exist(id61),
490  _event_data_id_exist(id62),
491  _event_data_id_exist(id63),
492  _event_data_id_exist(id64),
493  _event_data_id_exist(id65),
494  _event_data_id_exist(id66),
495  _event_data_id_exist(id67),
496  _event_data_id_exist(id68),
497  _event_data_id_exist(id69),
498  _event_data_id_exist(id70),
499  _event_data_id_exist(id71),
500  _event_data_id_exist(id72),
501  _event_data_id_exist(id73),
502  _event_data_id_exist(id74),
503  _event_data_id_exist(id75),
504  _event_data_id_exist(id76),
505  _event_data_id_exist(id77),
506  _event_data_id_exist(id78),
507  _event_data_id_exist(id79),
508  _event_data_id_exist(id80),
509  _event_data_id_exist(id81),
510  _event_data_id_exist(id82),
511  _event_data_id_exist(id83),
512  _event_data_id_exist(id84),
513  _event_data_id_exist(id85),
514  _event_data_id_exist(id86),
515  _event_data_id_exist(id87),
516  _event_data_id_exist(id88),
517  _event_data_id_exist(id89),
518  _event_data_id_exist(id90),
519  _event_data_id_exist(id91),
520  _event_data_id_exist(id92),
521  _event_data_id_exist(id93),
522  _event_data_id_exist(id94),
523  _event_data_id_exist(id95),
524  _event_data_id_exist(id96),
525  _event_data_id_exist(id97),
526  _event_data_id_exist(id98),
527  _event_data_id_exist(id99),
528  _event_data_id_exist(id100),
529  )
530  )
531 
532 
533 def disconnect_states_rows(state_ids: Iterable[int]) -> StatementLambdaElement:
534  """Disconnect states rows."""
535  return lambda_stmt(
536  lambda: update(States)
537  .where(States.old_state_id.in_(state_ids))
538  .values(old_state_id=None)
539  .execution_options(synchronize_session=False)
540  )
541 
542 
543 def delete_states_rows(state_ids: Iterable[int]) -> StatementLambdaElement:
544  """Delete states rows."""
545  return lambda_stmt(
546  lambda: delete(States)
547  .where(States.state_id.in_(state_ids))
548  .execution_options(synchronize_session=False)
549  )
550 
551 
552 def delete_event_data_rows(data_ids: Iterable[int]) -> StatementLambdaElement:
553  """Delete event_data rows."""
554  return lambda_stmt(
555  lambda: delete(EventData)
556  .where(EventData.data_id.in_(data_ids))
557  .execution_options(synchronize_session=False)
558  )
559 
560 
562  attributes_ids: Iterable[int],
563 ) -> StatementLambdaElement:
564  """Delete states_attributes rows."""
565  return lambda_stmt(
566  lambda: delete(StateAttributes)
567  .where(StateAttributes.attributes_id.in_(attributes_ids))
568  .execution_options(synchronize_session=False)
569  )
570 
571 
573  statistics_runs: Iterable[int],
574 ) -> StatementLambdaElement:
575  """Delete statistics_runs rows."""
576  return lambda_stmt(
577  lambda: delete(StatisticsRuns)
578  .where(StatisticsRuns.run_id.in_(statistics_runs))
579  .execution_options(synchronize_session=False)
580  )
581 
582 
584  short_term_statistics: Iterable[int],
585 ) -> StatementLambdaElement:
586  """Delete statistics_short_term rows."""
587  return lambda_stmt(
588  lambda: delete(StatisticsShortTerm)
589  .where(StatisticsShortTerm.id.in_(short_term_statistics))
590  .execution_options(synchronize_session=False)
591  )
592 
593 
595  event_ids: Iterable[int],
596 ) -> StatementLambdaElement:
597  """Delete event rows."""
598  return lambda_stmt(
599  lambda: delete(Events)
600  .where(Events.event_id.in_(event_ids))
601  .execution_options(synchronize_session=False)
602  )
603 
604 
606  purge_before: datetime, current_run_id: int
607 ) -> StatementLambdaElement:
608  """Delete recorder_runs rows."""
609  return lambda_stmt(
610  lambda: delete(RecorderRuns)
611  .filter(RecorderRuns.end.is_not(None))
612  .filter(RecorderRuns.end < purge_before)
613  .filter(RecorderRuns.run_id != current_run_id)
614  .execution_options(synchronize_session=False)
615  )
616 
617 
619  purge_before: float, max_bind_vars: int
620 ) -> StatementLambdaElement:
621  """Find events to purge."""
622  return lambda_stmt(
623  lambda: select(Events.event_id, Events.data_id)
624  .filter(Events.time_fired_ts < purge_before)
625  .limit(max_bind_vars)
626  )
627 
628 
630  purge_before: float, max_bind_vars: int
631 ) -> StatementLambdaElement:
632  """Find states to purge."""
633  return lambda_stmt(
634  lambda: select(States.state_id, States.attributes_id)
635  .filter(States.last_updated_ts < purge_before)
636  .limit(max_bind_vars)
637  )
638 
639 
640 def find_oldest_state() -> StatementLambdaElement:
641  """Find the last_updated_ts of the oldest state."""
642  return lambda_stmt(
643  lambda: select(States.last_updated_ts).where(
644  States.state_id.in_(select(func.min(States.state_id)))
645  )
646  )
647 
648 
650  purge_before: datetime, max_bind_vars: int
651 ) -> StatementLambdaElement:
652  """Find short term statistics to purge."""
653  purge_before_ts = purge_before.timestamp()
654  return lambda_stmt(
655  lambda: select(StatisticsShortTerm.id)
656  .filter(StatisticsShortTerm.start_ts < purge_before_ts)
657  .limit(max_bind_vars)
658  )
659 
660 
662  purge_before: datetime, max_bind_vars: int
663 ) -> StatementLambdaElement:
664  """Find statistics_runs to purge."""
665  return lambda_stmt(
666  lambda: select(StatisticsRuns.run_id)
667  .filter(StatisticsRuns.start < purge_before)
668  .limit(max_bind_vars)
669  )
670 
671 
672 def find_latest_statistics_runs_run_id() -> StatementLambdaElement:
673  """Find the latest statistics_runs run_id."""
674  return lambda_stmt(lambda: select(func.max(StatisticsRuns.run_id)))
675 
676 
678  purge_before: float, max_bind_vars: int
679 ) -> StatementLambdaElement:
680  """Find the latest row in the legacy format to purge."""
681  return lambda_stmt(
682  lambda: select(
683  Events.event_id, Events.data_id, States.state_id, States.attributes_id
684  )
685  .outerjoin(States, Events.event_id == States.event_id)
686  .filter(Events.time_fired_ts < purge_before)
687  .limit(max_bind_vars)
688  )
689 
690 
692  purge_before: float, max_bind_vars: int
693 ) -> StatementLambdaElement:
694  """Find states rows with event_id set but not linked event_id in Events."""
695  return lambda_stmt(
696  lambda: select(States.state_id, States.attributes_id)
697  .outerjoin(Events, States.event_id == Events.event_id)
698  .filter(States.event_id.isnot(None))
699  .filter(
700  (States.last_updated_ts < purge_before) | States.last_updated_ts.is_(None)
701  )
702  .filter(Events.event_id.is_(None))
703  .limit(max_bind_vars)
704  )
705 
706 
707 def find_legacy_row() -> StatementLambdaElement:
708  """Check if there are still states in the table with an event_id."""
709  return lambda_stmt(lambda: select(func.max(States.event_id)))
710 
711 
712 def find_events_context_ids_to_migrate(max_bind_vars: int) -> StatementLambdaElement:
713  """Find events context_ids to migrate."""
714  return lambda_stmt(
715  lambda: select(
716  Events.event_id,
717  Events.time_fired_ts,
718  Events.context_id,
719  Events.context_user_id,
720  Events.context_parent_id,
721  )
722  .filter(Events.context_id_bin.is_(None))
723  .limit(max_bind_vars)
724  )
725 
726 
727 def find_event_type_to_migrate(max_bind_vars: int) -> StatementLambdaElement:
728  """Find events event_type to migrate."""
729  return lambda_stmt(
730  lambda: select(
731  Events.event_id,
732  Events.event_type,
733  )
734  .filter(Events.event_type_id.is_(None))
735  .limit(max_bind_vars)
736  )
737 
738 
739 def find_entity_ids_to_migrate(max_bind_vars: int) -> StatementLambdaElement:
740  """Find entity_id to migrate."""
741  return lambda_stmt(
742  lambda: select(
743  States.state_id,
744  States.entity_id,
745  )
746  .filter(States.metadata_id.is_(None))
747  .limit(max_bind_vars)
748  )
749 
750 
751 def batch_cleanup_entity_ids() -> StatementLambdaElement:
752  """Find entity_id to cleanup."""
753  # Self join because This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
754  return lambda_stmt(
755  lambda: update(States)
756  .where(
757  States.state_id.in_(
758  select(States.state_id)
759  .join(
760  states_with_entity_ids := select(
761  States.state_id.label("state_id_with_entity_id")
762  )
763  .filter(States.entity_id.is_not(None))
764  .limit(5000)
765  .subquery(),
766  States.state_id == states_with_entity_ids.c.state_id_with_entity_id,
767  )
768  .alias("states_with_entity_ids")
769  .select()
770  )
771  )
772  .values(entity_id=None)
773  )
774 
775 
776 def has_used_states_entity_ids() -> StatementLambdaElement:
777  """Check if there are used entity_ids in the states table."""
778  return lambda_stmt(
779  lambda: select(States.state_id).filter(States.entity_id.isnot(None)).limit(1)
780  )
781 
782 
783 def has_used_states_event_ids() -> StatementLambdaElement:
784  """Check if there are used event_ids in the states table."""
785  return lambda_stmt(
786  lambda: select(States.state_id).filter(States.event_id.isnot(None)).limit(1)
787  )
788 
789 
790 def has_events_context_ids_to_migrate() -> StatementLambdaElement:
791  """Check if there are events context ids to migrate."""
792  return lambda_stmt(
793  lambda: select(Events.event_id).filter(Events.context_id_bin.is_(None)).limit(1)
794  )
795 
796 
797 def has_states_context_ids_to_migrate() -> StatementLambdaElement:
798  """Check if there are states context ids to migrate."""
799  return lambda_stmt(
800  lambda: select(States.state_id).filter(States.context_id_bin.is_(None)).limit(1)
801  )
802 
803 
804 def has_event_type_to_migrate() -> StatementLambdaElement:
805  """Check if there are event_types to migrate."""
806  return lambda_stmt(
807  lambda: select(Events.event_id).filter(Events.event_type_id.is_(None)).limit(1)
808  )
809 
810 
811 def has_entity_ids_to_migrate() -> StatementLambdaElement:
812  """Check if there are entity_id to migrate."""
813  return lambda_stmt(
814  lambda: select(States.state_id).filter(States.metadata_id.is_(None)).limit(1)
815  )
816 
817 
818 def find_states_context_ids_to_migrate(max_bind_vars: int) -> StatementLambdaElement:
819  """Find events context_ids to migrate."""
820  return lambda_stmt(
821  lambda: select(
822  States.state_id,
823  States.last_updated_ts,
824  States.context_id,
825  States.context_user_id,
826  States.context_parent_id,
827  )
828  .filter(States.context_id_bin.is_(None))
829  .limit(max_bind_vars)
830  )
831 
832 
833 def get_migration_changes() -> StatementLambdaElement:
834  """Query the database for previous migration changes."""
835  return lambda_stmt(
836  lambda: select(MigrationChanges.migration_id, MigrationChanges.version)
837  )
838 
839 
840 def find_event_types_to_purge() -> StatementLambdaElement:
841  """Find event_type_ids to purge."""
842  return lambda_stmt(
843  lambda: select(EventTypes.event_type_id, EventTypes.event_type).where(
844  EventTypes.event_type_id.not_in(
845  select(EventTypes.event_type_id).join(
846  used_event_type_ids := select(
847  distinct(Events.event_type_id).label("used_event_type_id")
848  ).subquery(),
849  EventTypes.event_type_id
850  == used_event_type_ids.c.used_event_type_id,
851  )
852  )
853  )
854  )
855 
856 
857 def find_entity_ids_to_purge() -> StatementLambdaElement:
858  """Find entity_ids to purge."""
859  return lambda_stmt(
860  lambda: select(StatesMeta.metadata_id, StatesMeta.entity_id).where(
861  StatesMeta.metadata_id.not_in(
862  select(StatesMeta.metadata_id).join(
863  used_states_metadata_id := select(
864  distinct(States.metadata_id).label("used_states_metadata_id")
865  ).subquery(),
866  StatesMeta.metadata_id
867  == used_states_metadata_id.c.used_states_metadata_id,
868  )
869  )
870  )
871  )
872 
873 
874 def delete_event_types_rows(event_type_ids: Iterable[int]) -> StatementLambdaElement:
875  """Delete EventTypes rows."""
876  return lambda_stmt(
877  lambda: delete(EventTypes)
878  .where(EventTypes.event_type_id.in_(event_type_ids))
879  .execution_options(synchronize_session=False)
880  )
881 
882 
883 def delete_states_meta_rows(metadata_ids: Iterable[int]) -> StatementLambdaElement:
884  """Delete StatesMeta rows."""
885  return lambda_stmt(
886  lambda: delete(StatesMeta)
887  .where(StatesMeta.metadata_id.in_(metadata_ids))
888  .execution_options(synchronize_session=False)
889  )
890 
891 
893  max_bind_vars: int,
894 ) -> StatementLambdaElement:
895  """Find unmigrated short term statistics rows."""
896  return lambda_stmt(
897  lambda: select(
898  StatisticsShortTerm.id,
899  StatisticsShortTerm.start,
900  StatisticsShortTerm.created,
901  StatisticsShortTerm.last_reset,
902  )
903  .filter(StatisticsShortTerm.start_ts.is_(None))
904  .filter(StatisticsShortTerm.start.isnot(None))
905  .limit(max_bind_vars)
906  )
907 
908 
909 def find_unmigrated_statistics_rows(max_bind_vars: int) -> StatementLambdaElement:
910  """Find unmigrated statistics rows."""
911  return lambda_stmt(
912  lambda: select(
913  Statistics.id, Statistics.start, Statistics.created, Statistics.last_reset
914  )
915  .filter(Statistics.start_ts.is_(None))
916  .filter(Statistics.start.isnot(None))
917  .limit(max_bind_vars)
918  )
919 
920 
922  statistic_id: int,
923  start_ts: float | None,
924  created_ts: float | None,
925  last_reset_ts: float | None,
926 ) -> StatementLambdaElement:
927  """Migrate a single short term statistics row to timestamp."""
928  return lambda_stmt(
929  lambda: update(StatisticsShortTerm)
930  .where(StatisticsShortTerm.id == statistic_id)
931  .values(
932  start_ts=start_ts,
933  start=None,
934  created_ts=created_ts,
935  created=None,
936  last_reset_ts=last_reset_ts,
937  last_reset=None,
938  )
939  .execution_options(synchronize_session=False)
940  )
941 
942 
944  statistic_id: int,
945  start_ts: float | None,
946  created_ts: float | None,
947  last_reset_ts: float | None,
948 ) -> StatementLambdaElement:
949  """Migrate a single statistics row to timestamp."""
950  return lambda_stmt(
951  lambda: update(Statistics)
952  .where(Statistics.id == statistic_id)
953  .values(
954  start_ts=start_ts,
955  start=None,
956  created_ts=created_ts,
957  created=None,
958  last_reset_ts=last_reset_ts,
959  last_reset=None,
960  )
961  .execution_options(synchronize_session=False)
962  )
963 
964 
966  statistic_id: int,
967 ) -> StatementLambdaElement:
968  """Delete a single duplicate short term statistics row."""
969  return lambda_stmt(
970  lambda: delete(StatisticsShortTerm)
971  .where(StatisticsShortTerm.id == statistic_id)
972  .execution_options(synchronize_session=False)
973  )
974 
975 
976 def delete_duplicate_statistics_row(statistic_id: int) -> StatementLambdaElement:
977  """Delete a single duplicate statistics row."""
978  return lambda_stmt(
979  lambda: delete(Statistics)
980  .where(Statistics.id == statistic_id)
981  .execution_options(synchronize_session=False)
982  )
web.Response delete(self, web.Request request, str config_key)
Definition: view.py:144
IssData update(pyiss.ISS iss)
Definition: __init__.py:33
Select _state_attrs_exist(int|None attr)
Definition: queries.py:79
StatementLambdaElement find_states_metadata_ids(Iterable[str] entity_ids)
Definition: queries.py:70
StatementLambdaElement delete_states_meta_rows(Iterable[int] metadata_ids)
Definition: queries.py:883
StatementLambdaElement find_oldest_state()
Definition: queries.py:640
StatementLambdaElement get_shared_attributes(list[int] hashes)
Definition: queries.py:38
StatementLambdaElement find_event_type_ids(Iterable[str] event_types)
Definition: queries.py:56
StatementLambdaElement find_legacy_detached_states_and_attributes_to_purge(float purge_before, int max_bind_vars)
Definition: queries.py:693
StatementLambdaElement find_short_term_statistics_to_purge(datetime purge_before, int max_bind_vars)
Definition: queries.py:651
StatementLambdaElement attributes_ids_exist_in_states(int attr1, int|None attr2, int|None attr3, int|None attr4, int|None attr5, int|None attr6, int|None attr7, int|None attr8, int|None attr9, int|None attr10, int|None attr11, int|None attr12, int|None attr13, int|None attr14, int|None attr15, int|None attr16, int|None attr17, int|None attr18, int|None attr19, int|None attr20, int|None attr21, int|None attr22, int|None attr23, int|None attr24, int|None attr25, int|None attr26, int|None attr27, int|None attr28, int|None attr29, int|None attr30, int|None attr31, int|None attr32, int|None attr33, int|None attr34, int|None attr35, int|None attr36, int|None attr37, int|None attr38, int|None attr39, int|None attr40, int|None attr41, int|None attr42, int|None attr43, int|None attr44, int|None attr45, int|None attr46, int|None attr47, int|None attr48, int|None attr49, int|None attr50, int|None attr51, int|None attr52, int|None attr53, int|None attr54, int|None attr55, int|None attr56, int|None attr57, int|None attr58, int|None attr59, int|None attr60, int|None attr61, int|None attr62, int|None attr63, int|None attr64, int|None attr65, int|None attr66, int|None attr67, int|None attr68, int|None attr69, int|None attr70, int|None attr71, int|None attr72, int|None attr73, int|None attr74, int|None attr75, int|None attr76, int|None attr77, int|None attr78, int|None attr79, int|None attr80, int|None attr81, int|None attr82, int|None attr83, int|None attr84, int|None attr85, int|None attr86, int|None attr87, int|None attr88, int|None attr89, int|None attr90, int|None attr91, int|None attr92, int|None attr93, int|None attr94, int|None attr95, int|None attr96, int|None attr97, int|None attr98, int|None attr99, int|None attr100)
Definition: queries.py:196
StatementLambdaElement delete_recorder_runs_rows(datetime purge_before, int current_run_id)
Definition: queries.py:607
StatementLambdaElement migrate_single_statistics_row_to_timestamp(int statistic_id, float|None start_ts, float|None created_ts, float|None last_reset_ts)
Definition: queries.py:948
StatementLambdaElement delete_duplicate_short_term_statistics_row(int statistic_id)
Definition: queries.py:967
StatementLambdaElement migrate_single_short_term_statistics_row_to_timestamp(int statistic_id, float|None start_ts, float|None created_ts, float|None last_reset_ts)
Definition: queries.py:926
StatementLambdaElement find_legacy_event_state_and_attributes_and_data_ids_to_purge(float purge_before, int max_bind_vars)
Definition: queries.py:679
StatementLambdaElement find_latest_statistics_runs_run_id()
Definition: queries.py:672
StatementLambdaElement find_all_states_metadata_ids()
Definition: queries.py:65
StatementLambdaElement delete_event_data_rows(Iterable[int] data_ids)
Definition: queries.py:552
StatementLambdaElement delete_event_rows(Iterable[int] event_ids)
Definition: queries.py:596
StatementLambdaElement batch_cleanup_entity_ids()
Definition: queries.py:751
StatementLambdaElement get_shared_event_datas(list[int] hashes)
Definition: queries.py:47
StatementLambdaElement has_used_states_entity_ids()
Definition: queries.py:776
StatementLambdaElement find_unmigrated_short_term_statistics_rows(int max_bind_vars)
Definition: queries.py:894
StatementLambdaElement has_states_context_ids_to_migrate()
Definition: queries.py:797
StatementLambdaElement has_used_states_event_ids()
Definition: queries.py:783
StatementLambdaElement has_events_context_ids_to_migrate()
Definition: queries.py:790
StatementLambdaElement find_statistics_runs_to_purge(datetime purge_before, int max_bind_vars)
Definition: queries.py:663
StatementLambdaElement find_states_context_ids_to_migrate(int max_bind_vars)
Definition: queries.py:818
StatementLambdaElement find_entity_ids_to_migrate(int max_bind_vars)
Definition: queries.py:739
StatementLambdaElement find_events_context_ids_to_migrate(int max_bind_vars)
Definition: queries.py:712
StatementLambdaElement delete_event_types_rows(Iterable[int] event_type_ids)
Definition: queries.py:874
StatementLambdaElement find_events_to_purge(float purge_before, int max_bind_vars)
Definition: queries.py:620
StatementLambdaElement delete_statistics_runs_rows(Iterable[int] statistics_runs)
Definition: queries.py:574
StatementLambdaElement delete_states_rows(Iterable[int] state_ids)
Definition: queries.py:543
StatementLambdaElement delete_states_attributes_rows(Iterable[int] attributes_ids)
Definition: queries.py:563
Select _event_data_id_exist(int|None data_id)
Definition: queries.py:316
StatementLambdaElement find_states_to_purge(float purge_before, int max_bind_vars)
Definition: queries.py:631
StatementLambdaElement find_legacy_row()
Definition: queries.py:707
Select select_event_type_ids(tuple[str,...] event_types)
Definition: queries.py:27
StatementLambdaElement find_unmigrated_statistics_rows(int max_bind_vars)
Definition: queries.py:909
StatementLambdaElement find_event_types_to_purge()
Definition: queries.py:840
StatementLambdaElement has_entity_ids_to_migrate()
Definition: queries.py:811
StatementLambdaElement attributes_ids_exist_in_states_with_fast_in_distinct(Iterable[int] attributes_ids)
Definition: queries.py:86
StatementLambdaElement disconnect_states_rows(Iterable[int] state_ids)
Definition: queries.py:533
StatementLambdaElement find_event_type_to_migrate(int max_bind_vars)
Definition: queries.py:727
StatementLambdaElement data_ids_exist_in_events_with_fast_in_distinct(Iterable[int] data_ids)
Definition: queries.py:309
StatementLambdaElement delete_statistics_short_term_rows(Iterable[int] short_term_statistics)
Definition: queries.py:585
StatementLambdaElement delete_duplicate_statistics_row(int statistic_id)
Definition: queries.py:976
StatementLambdaElement data_ids_exist_in_events(int id1, int|None id2, int|None id3, int|None id4, int|None id5, int|None id6, int|None id7, int|None id8, int|None id9, int|None id10, int|None id11, int|None id12, int|None id13, int|None id14, int|None id15, int|None id16, int|None id17, int|None id18, int|None id19, int|None id20, int|None id21, int|None id22, int|None id23, int|None id24, int|None id25, int|None id26, int|None id27, int|None id28, int|None id29, int|None id30, int|None id31, int|None id32, int|None id33, int|None id34, int|None id35, int|None id36, int|None id37, int|None id38, int|None id39, int|None id40, int|None id41, int|None id42, int|None id43, int|None id44, int|None id45, int|None id46, int|None id47, int|None id48, int|None id49, int|None id50, int|None id51, int|None id52, int|None id53, int|None id54, int|None id55, int|None id56, int|None id57, int|None id58, int|None id59, int|None id60, int|None id61, int|None id62, int|None id63, int|None id64, int|None id65, int|None id66, int|None id67, int|None id68, int|None id69, int|None id70, int|None id71, int|None id72, int|None id73, int|None id74, int|None id75, int|None id76, int|None id77, int|None id78, int|None id79, int|None id80, int|None id81, int|None id82, int|None id83, int|None id84, int|None id85, int|None id86, int|None id87, int|None id88, int|None id89, int|None id90, int|None id91, int|None id92, int|None id93, int|None id94, int|None id95, int|None id96, int|None id97, int|None id98, int|None id99, int|None id100)
Definition: queries.py:422
StatementLambdaElement has_event_type_to_migrate()
Definition: queries.py:804
StatementLambdaElement get_migration_changes()
Definition: queries.py:833
StatementLambdaElement find_entity_ids_to_purge()
Definition: queries.py:857