move to queries

This commit is contained in:
J. Nick Koston
2026-04-11 11:56:34 -10:00
parent e7adeb616a
commit f987b1485f
2 changed files with 32 additions and 11 deletions

View File

@@ -10,13 +10,11 @@ import time
from typing import TYPE_CHECKING, Any
from lru import LRU
from sqlalchemy import select
from sqlalchemy.engine import Result
from sqlalchemy.engine.row import Row
from sqlalchemy.orm import Session
from homeassistant.components.recorder import get_instance
from homeassistant.components.recorder.db_schema import Events
from homeassistant.components.recorder.filters import Filters
from homeassistant.components.recorder.models import (
bytes_to_uuid_hex_or_none,
@@ -85,7 +83,10 @@ from .models import (
async_event_to_row,
)
from .queries import statement_for_request
from .queries.common import PSEUDO_EVENT_STATE_CHANGED
from .queries.common import (
PSEUDO_EVENT_STATE_CHANGED,
select_context_user_ids_for_context_ids,
)
_LOGGER = logging.getLogger(__name__)
@@ -253,16 +254,16 @@ class EventProcessor:
query_parent_user_ids: dict[bytes, bytes] = {}
for pending_chunk in chunked_or_all(pending, max_bind_vars):
# Both columns are nullable in the schema but the WHERE clauses
# guarantee non-null at runtime; the explicit checks satisfy
# the type checker.
# in the lambda statement guarantee non-null at runtime; the
# explicit checks satisfy the type checker.
query_parent_user_ids.update(
{
parent_id: user_id
for parent_id, user_id in session.execute(
select(Events.context_id_bin, Events.context_user_id_bin)
.where(Events.context_id_bin.in_(pending_chunk))
.where(Events.context_user_id_bin.is_not(None))
).all()
for parent_id, user_id in execute_stmt_lambda_element(
session,
select_context_user_ids_for_context_ids(pending_chunk),
orm_rows=False,
)
if parent_id is not None and user_id is not None
}
)

View File

@@ -2,12 +2,14 @@
from __future__ import annotations
from collections.abc import Collection
from typing import Final
import sqlalchemy
from sqlalchemy import select
from sqlalchemy import lambda_stmt, select
from sqlalchemy.sql.elements import BooleanClauseList, ColumnElement
from sqlalchemy.sql.expression import literal
from sqlalchemy.sql.lambdas import StatementLambdaElement
from sqlalchemy.sql.selectable import Select
from homeassistant.components.recorder.db_schema import (
@@ -122,6 +124,24 @@ def select_events_context_id_subquery(
)
def select_context_user_ids_for_context_ids(
context_ids: Collection[bytes],
) -> StatementLambdaElement:
"""Select context_id_bin and context_user_id_bin from events for the given context ids.
Used by the logbook processor to resolve parent-context user attribution
for child contexts whose parent service_call event isn't in the filtered
row stream. Hits the existing ix_events_context_id_bin index.
"""
return lambda_stmt(
lambda: (
select(Events.context_id_bin, Events.context_user_id_bin)
.where(Events.context_id_bin.in_(context_ids))
.where(Events.context_user_id_bin.is_not(None))
)
)
def select_events_context_only() -> Select:
"""Generate an events query that mark them as for context_only.