diff --git a/homeassistant/components/recorder/migration.py b/homeassistant/components/recorder/migration.py index 211e1646cca..4a5c456df28 100644 --- a/homeassistant/components/recorder/migration.py +++ b/homeassistant/components/recorder/migration.py @@ -351,7 +351,7 @@ def _drop_foreign_key_constraints(connection, engine, table, columns): ) -def _apply_update(engine, session, new_version, old_version): +def _apply_update(engine, session, new_version, old_version): # noqa: C901 """Perform operations to bring schema up to date.""" connection = session.connection() if new_version == 1: @@ -486,6 +486,21 @@ def _apply_update(engine, session, new_version, old_version): start = now.replace(minute=0, second=0, microsecond=0) start = start - timedelta(hours=1) session.add(StatisticsRuns(start=start)) + elif new_version == 20: + # This changed the precision of statistics from float to double + if engine.dialect.name in ["mysql", "oracle", "postgresql"]: + _modify_columns( + connection, + engine, + "statistics", + [ + "mean DOUBLE PRECISION", + "min DOUBLE PRECISION", + "max DOUBLE PRECISION", + "state DOUBLE PRECISION", + "sum DOUBLE PRECISION", + ], + ) else: raise ValueError(f"No schema migration defined for version {new_version}") diff --git a/homeassistant/components/recorder/models.py b/homeassistant/components/recorder/models.py index 1c56e9c8f79..6c532e92292 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -19,7 +19,7 @@ from sqlalchemy import ( Text, distinct, ) -from sqlalchemy.dialects import mysql +from sqlalchemy.dialects import mysql, oracle, postgresql from sqlalchemy.orm import declarative_base, relationship from sqlalchemy.orm.session import Session @@ -39,7 +39,7 @@ import homeassistant.util.dt as dt_util # pylint: disable=invalid-name Base = declarative_base() -SCHEMA_VERSION = 19 +SCHEMA_VERSION = 20 _LOGGER = logging.getLogger(__name__) @@ -66,6 +66,12 @@ ALL_TABLES = [ DATETIME_TYPE = DateTime(timezone=True).with_variant( mysql.DATETIME(timezone=True, fsp=6), "mysql" ) +DOUBLE_TYPE = ( + Float() + .with_variant(mysql.DOUBLE(asdecimal=False), "mysql") + .with_variant(oracle.DOUBLE_PRECISION(), "oracle") + .with_variant(postgresql.DOUBLE_PRECISION, "postgresql") +) class Events(Base): # type: ignore @@ -240,11 +246,11 @@ class Statistics(Base): # type: ignore index=True, ) start = Column(DATETIME_TYPE, index=True) - mean = Column(Float()) - min = Column(Float()) - max = Column(Float()) - state = Column(Float()) - sum = Column(Float()) + mean = Column(DOUBLE_TYPE) + min = Column(DOUBLE_TYPE) + max = Column(DOUBLE_TYPE) + state = Column(DOUBLE_TYPE) + sum = Column(DOUBLE_TYPE) @staticmethod def from_stats(metadata_id: str, start: datetime, stats: StatisticData): diff --git a/homeassistant/components/sensor/recorder.py b/homeassistant/components/sensor/recorder.py index 2cbca09c09d..8722fef0e99 100644 --- a/homeassistant/components/sensor/recorder.py +++ b/homeassistant/components/sensor/recorder.py @@ -293,10 +293,21 @@ def compile_statistics( reset = False if old_state is None: reset = True + _LOGGER.info( + "Compiling initial sum statistics for %s, zero point set to %s", + entity_id, + fstate, + ) elif state_class == STATE_CLASS_TOTAL_INCREASING and ( old_state is None or (new_state is not None and fstate < new_state) ): reset = True + _LOGGER.info( + "Detected new cycle for %s, zero point set to %s (old zero point %s)", + entity_id, + fstate, + new_state, + ) if reset: # The sensor has been reset, update the sum