Upgrade SQLAlchemy to 2.0.2 (#86436)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
93dafefd96
commit
94519de8dd
37 changed files with 583 additions and 430 deletions
|
@ -5,8 +5,7 @@ from typing import Final
|
|||
|
||||
import sqlalchemy
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Query
|
||||
from sqlalchemy.sql.elements import ClauseList
|
||||
from sqlalchemy.sql.elements import BooleanClauseList, ColumnElement
|
||||
from sqlalchemy.sql.expression import literal
|
||||
from sqlalchemy.sql.selectable import Select
|
||||
|
||||
|
@ -69,7 +68,7 @@ STATE_CONTEXT_ONLY_COLUMNS = (
|
|||
literal(value=None, type_=sqlalchemy.String).label("old_format_icon"),
|
||||
)
|
||||
|
||||
EVENT_COLUMNS_FOR_STATE_SELECT = [
|
||||
EVENT_COLUMNS_FOR_STATE_SELECT = (
|
||||
literal(value=None, type_=sqlalchemy.Text).label("event_id"),
|
||||
# We use PSEUDO_EVENT_STATE_CHANGED aka None for
|
||||
# state_changed events since it takes up less
|
||||
|
@ -84,7 +83,7 @@ EVENT_COLUMNS_FOR_STATE_SELECT = [
|
|||
States.context_user_id.label("context_user_id"),
|
||||
States.context_parent_id.label("context_parent_id"),
|
||||
literal(value=None, type_=sqlalchemy.Text).label("shared_data"),
|
||||
]
|
||||
)
|
||||
|
||||
EMPTY_STATE_COLUMNS = (
|
||||
literal(value=0, type_=sqlalchemy.Integer).label("state_id"),
|
||||
|
@ -103,8 +102,8 @@ EVENT_ROWS_NO_STATES = (
|
|||
|
||||
# Virtual column to tell logbook if it should avoid processing
|
||||
# the event as its only used to link contexts
|
||||
CONTEXT_ONLY = literal("1").label("context_only")
|
||||
NOT_CONTEXT_ONLY = literal(None).label("context_only")
|
||||
CONTEXT_ONLY = literal(value="1", type_=sqlalchemy.String).label("context_only")
|
||||
NOT_CONTEXT_ONLY = literal(value=None, type_=sqlalchemy.String).label("context_only")
|
||||
|
||||
|
||||
def select_events_context_id_subquery(
|
||||
|
@ -188,7 +187,7 @@ def legacy_select_events_context_id(
|
|||
)
|
||||
|
||||
|
||||
def apply_states_filters(query: Query, start_day: float, end_day: float) -> Query:
|
||||
def apply_states_filters(sel: Select, start_day: float, end_day: float) -> Select:
|
||||
"""Filter states by time range.
|
||||
|
||||
Filters states that do not have an old state or new state (added / removed)
|
||||
|
@ -196,7 +195,7 @@ def apply_states_filters(query: Query, start_day: float, end_day: float) -> Quer
|
|||
Filters states that do not have matching last_updated_ts and last_changed_ts.
|
||||
"""
|
||||
return (
|
||||
query.filter(
|
||||
sel.filter(
|
||||
(States.last_updated_ts > start_day) & (States.last_updated_ts < end_day)
|
||||
)
|
||||
.outerjoin(OLD_STATE, (States.old_state_id == OLD_STATE.state_id))
|
||||
|
@ -212,18 +211,18 @@ def apply_states_filters(query: Query, start_day: float, end_day: float) -> Quer
|
|||
)
|
||||
|
||||
|
||||
def _missing_state_matcher() -> sqlalchemy.and_:
|
||||
def _missing_state_matcher() -> ColumnElement[bool]:
|
||||
# The below removes state change events that do not have
|
||||
# and old_state or the old_state is missing (newly added entities)
|
||||
# or the new_state is missing (removed entities)
|
||||
return sqlalchemy.and_(
|
||||
OLD_STATE.state_id.isnot(None),
|
||||
OLD_STATE.state_id.is_not(None),
|
||||
(States.state != OLD_STATE.state),
|
||||
States.state.isnot(None),
|
||||
States.state.is_not(None),
|
||||
)
|
||||
|
||||
|
||||
def _not_continuous_entity_matcher() -> sqlalchemy.or_:
|
||||
def _not_continuous_entity_matcher() -> ColumnElement[bool]:
|
||||
"""Match non continuous entities."""
|
||||
return sqlalchemy.or_(
|
||||
# First exclude domains that may be continuous
|
||||
|
@ -236,7 +235,7 @@ def _not_continuous_entity_matcher() -> sqlalchemy.or_:
|
|||
)
|
||||
|
||||
|
||||
def _not_possible_continuous_domain_matcher() -> sqlalchemy.and_:
|
||||
def _not_possible_continuous_domain_matcher() -> ColumnElement[bool]:
|
||||
"""Match not continuous domains.
|
||||
|
||||
This matches domain that are always considered continuous
|
||||
|
@ -254,7 +253,7 @@ def _not_possible_continuous_domain_matcher() -> sqlalchemy.and_:
|
|||
).self_group()
|
||||
|
||||
|
||||
def _conditionally_continuous_domain_matcher() -> sqlalchemy.or_:
|
||||
def _conditionally_continuous_domain_matcher() -> ColumnElement[bool]:
|
||||
"""Match conditionally continuous domains.
|
||||
|
||||
This matches domain that are only considered
|
||||
|
@ -268,22 +267,22 @@ def _conditionally_continuous_domain_matcher() -> sqlalchemy.or_:
|
|||
).self_group()
|
||||
|
||||
|
||||
def _not_uom_attributes_matcher() -> ClauseList:
|
||||
def _not_uom_attributes_matcher() -> BooleanClauseList:
|
||||
"""Prefilter ATTR_UNIT_OF_MEASUREMENT as its much faster in sql."""
|
||||
return ~StateAttributes.shared_attrs.like(
|
||||
UNIT_OF_MEASUREMENT_JSON_LIKE
|
||||
) | ~States.attributes.like(UNIT_OF_MEASUREMENT_JSON_LIKE)
|
||||
|
||||
|
||||
def apply_states_context_hints(query: Query) -> Query:
|
||||
def apply_states_context_hints(sel: Select) -> Select:
|
||||
"""Force mysql to use the right index on large context_id selects."""
|
||||
return query.with_hint(
|
||||
return sel.with_hint(
|
||||
States, f"FORCE INDEX ({STATES_CONTEXT_ID_INDEX})", dialect_name="mysql"
|
||||
)
|
||||
|
||||
|
||||
def apply_events_context_hints(query: Query) -> Query:
|
||||
def apply_events_context_hints(sel: Select) -> Select:
|
||||
"""Force mysql to use the right index on large context_id selects."""
|
||||
return query.with_hint(
|
||||
return sel.with_hint(
|
||||
Events, f"FORCE INDEX ({EVENTS_CONTEXT_ID_INDEX})", dialect_name="mysql"
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue