Guard against selecting all invalid entity_ids in history (#89929)
If all the entity_ids that were provided do not exist we would end up passing an empty list of ids to the SQL query which would do an unbounded selectpull/89941/head^2
parent
5ffb233004
commit
7f3e4cb3af
|
@ -14,6 +14,7 @@ from homeassistant.components.recorder import get_instance
|
||||||
from homeassistant.components.recorder.filters import Filters
|
from homeassistant.components.recorder.filters import Filters
|
||||||
from homeassistant.components.recorder.models import (
|
from homeassistant.components.recorder.models import (
|
||||||
bytes_to_uuid_hex_or_none,
|
bytes_to_uuid_hex_or_none,
|
||||||
|
extract_metadata_ids,
|
||||||
process_datetime_to_timestamp,
|
process_datetime_to_timestamp,
|
||||||
process_timestamp_to_utc_isoformat,
|
process_timestamp_to_utc_isoformat,
|
||||||
)
|
)
|
||||||
|
@ -154,14 +155,11 @@ class EventProcessor:
|
||||||
metadata_ids: list[int] | None = None
|
metadata_ids: list[int] | None = None
|
||||||
if self.entity_ids:
|
if self.entity_ids:
|
||||||
instance = get_instance(self.hass)
|
instance = get_instance(self.hass)
|
||||||
entity_id_to_metadata_id = instance.states_meta_manager.get_many(
|
metadata_ids = extract_metadata_ids(
|
||||||
self.entity_ids, session, False
|
instance.states_meta_manager.get_many(
|
||||||
|
self.entity_ids, session, False
|
||||||
|
)
|
||||||
)
|
)
|
||||||
metadata_ids = [
|
|
||||||
metadata_id
|
|
||||||
for metadata_id in entity_id_to_metadata_id.values()
|
|
||||||
if metadata_id is not None
|
|
||||||
]
|
|
||||||
stmt = statement_for_request(
|
stmt = statement_for_request(
|
||||||
start_day,
|
start_day,
|
||||||
end_day,
|
end_day,
|
||||||
|
|
|
@ -23,7 +23,12 @@ import homeassistant.util.dt as dt_util
|
||||||
from ... import recorder
|
from ... import recorder
|
||||||
from ..db_schema import RecorderRuns, StateAttributes, States, StatesMeta
|
from ..db_schema import RecorderRuns, StateAttributes, States, StatesMeta
|
||||||
from ..filters import Filters
|
from ..filters import Filters
|
||||||
from ..models import LazyState, process_timestamp, row_to_compressed_state
|
from ..models import (
|
||||||
|
LazyState,
|
||||||
|
extract_metadata_ids,
|
||||||
|
process_timestamp,
|
||||||
|
row_to_compressed_state,
|
||||||
|
)
|
||||||
from ..util import execute_stmt_lambda_element, session_scope
|
from ..util import execute_stmt_lambda_element, session_scope
|
||||||
from .const import (
|
from .const import (
|
||||||
IGNORE_DOMAINS_ENTITY_ID_LIKE,
|
IGNORE_DOMAINS_ENTITY_ID_LIKE,
|
||||||
|
@ -232,14 +237,12 @@ def get_significant_states_with_session(
|
||||||
entity_id_to_metadata_id: dict[str, int | None] | None = None
|
entity_id_to_metadata_id: dict[str, int | None] | None = None
|
||||||
if entity_ids:
|
if entity_ids:
|
||||||
instance = recorder.get_instance(hass)
|
instance = recorder.get_instance(hass)
|
||||||
entity_id_to_metadata_id = instance.states_meta_manager.get_many(
|
if not (
|
||||||
entity_ids, session, False
|
entity_id_to_metadata_id := instance.states_meta_manager.get_many(
|
||||||
)
|
entity_ids, session, False
|
||||||
metadata_ids = [
|
)
|
||||||
metadata_id
|
) or not (metadata_ids := extract_metadata_ids(entity_id_to_metadata_id)):
|
||||||
for metadata_id in entity_id_to_metadata_id.values()
|
return {}
|
||||||
if metadata_id is not None
|
|
||||||
]
|
|
||||||
stmt = _significant_states_stmt(
|
stmt = _significant_states_stmt(
|
||||||
start_time,
|
start_time,
|
||||||
end_time,
|
end_time,
|
||||||
|
@ -569,14 +572,9 @@ def _get_rows_with_session(
|
||||||
# We have more than one entity to look at so we need to do a query on states
|
# We have more than one entity to look at so we need to do a query on states
|
||||||
# since the last recorder run started.
|
# since the last recorder run started.
|
||||||
if entity_ids:
|
if entity_ids:
|
||||||
if not entity_id_to_metadata_id:
|
if not entity_id_to_metadata_id or not (
|
||||||
return []
|
metadata_ids := extract_metadata_ids(entity_id_to_metadata_id)
|
||||||
metadata_ids = [
|
):
|
||||||
metadata_id
|
|
||||||
for metadata_id in entity_id_to_metadata_id.values()
|
|
||||||
if metadata_id is not None
|
|
||||||
]
|
|
||||||
if not metadata_ids:
|
|
||||||
return []
|
return []
|
||||||
stmt = _get_states_for_entities_stmt(
|
stmt = _get_states_for_entities_stmt(
|
||||||
run.start, utc_point_in_time, metadata_ids, no_attributes
|
run.start, utc_point_in_time, metadata_ids, no_attributes
|
||||||
|
|
|
@ -8,7 +8,7 @@ from .context import (
|
||||||
uuid_hex_to_bytes_or_none,
|
uuid_hex_to_bytes_or_none,
|
||||||
)
|
)
|
||||||
from .database import DatabaseEngine, DatabaseOptimizer, UnsupportedDialect
|
from .database import DatabaseEngine, DatabaseOptimizer, UnsupportedDialect
|
||||||
from .state import LazyState, row_to_compressed_state
|
from .state import LazyState, extract_metadata_ids, row_to_compressed_state
|
||||||
from .statistics import (
|
from .statistics import (
|
||||||
CalendarStatisticPeriod,
|
CalendarStatisticPeriod,
|
||||||
FixedStatisticPeriod,
|
FixedStatisticPeriod,
|
||||||
|
@ -43,6 +43,7 @@ __all__ = [
|
||||||
"bytes_to_ulid_or_none",
|
"bytes_to_ulid_or_none",
|
||||||
"bytes_to_uuid_hex_or_none",
|
"bytes_to_uuid_hex_or_none",
|
||||||
"datetime_to_timestamp_or_none",
|
"datetime_to_timestamp_or_none",
|
||||||
|
"extract_metadata_ids",
|
||||||
"process_datetime_to_timestamp",
|
"process_datetime_to_timestamp",
|
||||||
"process_timestamp",
|
"process_timestamp",
|
||||||
"process_timestamp_to_utc_isoformat",
|
"process_timestamp_to_utc_isoformat",
|
||||||
|
|
|
@ -24,6 +24,17 @@ from .time import process_timestamp
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_metadata_ids(
|
||||||
|
entity_id_to_metadata_id: dict[str, int | None],
|
||||||
|
) -> list[int]:
|
||||||
|
"""Extract metadata ids from entity_id_to_metadata_id."""
|
||||||
|
return [
|
||||||
|
metadata_id
|
||||||
|
for metadata_id in entity_id_to_metadata_id.values()
|
||||||
|
if metadata_id is not None
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class LazyState(State):
|
class LazyState(State):
|
||||||
"""A lazy version of core State after schema 31."""
|
"""A lazy version of core State after schema 31."""
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue