Isolate the sql integration with a separate query cache (#90438)

* Isolate the sql integration with a seperate query cache

If there were a lot of sql integrations they could affect
the performance of the recorder/logbook/history since they
were sharing the same LRU and since the sql sensor updates
frequently it would evict the recorder queries from the
LRU.

* generate in stmt

* avoid double gen

* Revert "avoid double gen"

This reverts commit 6a5aa65268.
pull/90442/head
J. Nick Koston 2023-03-28 17:54:03 -10:00 committed by GitHub
parent 5dc96a6952
commit 8096be768d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 13 additions and 1 deletions

View File

@ -6,9 +6,12 @@ import decimal
import logging
import sqlalchemy
from sqlalchemy import lambda_stmt
from sqlalchemy.engine import Result
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session, scoped_session, sessionmaker
from sqlalchemy.sql.lambdas import StatementLambdaElement
from sqlalchemy.util import LRUCache
from homeassistant.components.recorder import CONF_DB_URL, get_instance
from homeassistant.components.sensor import (
@ -38,6 +41,8 @@ from .util import resolve_db_url
_LOGGER = logging.getLogger(__name__)
_SQL_LAMBDA_CACHE: LRUCache = LRUCache(1000)
def redact_credentials(data: str) -> str:
"""Redact credentials from string data."""
@ -202,6 +207,12 @@ def _validate_and_get_session_maker_for_db_url(db_url: str) -> scoped_session |
sess.close()
def _generate_lambda_stmt(query: str) -> StatementLambdaElement:
"""Generate the lambda statement."""
text = sqlalchemy.text(query)
return lambda_stmt(lambda: text, lambda_cache=_SQL_LAMBDA_CACHE)
class SQLSensor(SensorEntity):
"""Representation of an SQL sensor."""
@ -234,6 +245,7 @@ class SQLSensor(SensorEntity):
self._attr_extra_state_attributes = {}
self._attr_unique_id = unique_id
self._use_database_executor = use_database_executor
self._lambda_stmt = _generate_lambda_stmt(query)
if not yaml and unique_id:
self._attr_device_info = DeviceInfo(
entry_type=DeviceEntryType.SERVICE,
@ -255,7 +267,7 @@ class SQLSensor(SensorEntity):
self._attr_extra_state_attributes = {}
sess: scoped_session = self.sessionmaker()
try:
result: Result = sess.execute(sqlalchemy.text(self._query))
result: Result = sess.execute(self._lambda_stmt)
except SQLAlchemyError as err:
_LOGGER.error(
"Error executing query %s: %s",