Fix recorder Oracle DB models (#55564)

* Fix recorder models for Oracle DB

* Fix StatisticsRuns

* Update migration for Oracle Identity columns.

* Update migration logic

Migration to schema version 22 done only for engine dialect oracle

* Add missing table check in schema 22 migration
This commit is contained in:
Marcin Ciupak 2021-09-21 00:38:42 +02:00 committed by GitHub
parent 20ddd092f6
commit b9ffd74db5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 5 deletions

View file

@ -20,6 +20,7 @@ from .models import (
Statistics,
StatisticsMeta,
StatisticsRuns,
StatisticsShortTerm,
)
from .statistics import get_start_time
from .util import session_scope
@ -484,7 +485,7 @@ def _apply_update(engine, session, new_version, old_version): # noqa: C901
session.add(StatisticsRuns(start=get_start_time()))
elif new_version == 20:
# This changed the precision of statistics from float to double
if engine.dialect.name in ["mysql", "oracle", "postgresql"]:
if engine.dialect.name in ["mysql", "postgresql"]:
_modify_columns(
connection,
engine,
@ -513,6 +514,35 @@ def _apply_update(engine, session, new_version, old_version): # noqa: C901
"CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
)
)
elif new_version == 22:
# Recreate the all statistics tables for Oracle DB with Identity columns
#
# Order matters! Statistics has a relation with StatisticsMeta,
# so statistics need to be deleted before meta (or in pair depending
# on the SQL backend); and meta needs to be created before statistics.
if engine.dialect.name == "oracle":
if (
sqlalchemy.inspect(engine).has_table(StatisticsMeta.__tablename__)
or sqlalchemy.inspect(engine).has_table(Statistics.__tablename__)
or sqlalchemy.inspect(engine).has_table(StatisticsRuns.__tablename__)
or sqlalchemy.inspect(engine).has_table(
StatisticsShortTerm.__tablename__
)
):
Base.metadata.drop_all(
bind=engine,
tables=[
StatisticsShortTerm.__table__,
Statistics.__table__,
StatisticsMeta.__table__,
StatisticsRuns.__table__,
],
)
StatisticsRuns.__table__.create(engine)
StatisticsMeta.__table__.create(engine)
StatisticsShortTerm.__table__.create(engine)
Statistics.__table__.create(engine)
else:
raise ValueError(f"No schema migration defined for version {new_version}")

View file

@ -40,7 +40,7 @@ import homeassistant.util.dt as dt_util
# pylint: disable=invalid-name
Base = declarative_base()
SCHEMA_VERSION = 21
SCHEMA_VERSION = 22
_LOGGER = logging.getLogger(__name__)
@ -238,7 +238,7 @@ class StatisticData(TypedDict, total=False):
class StatisticsBase:
"""Statistics base class."""
id = Column(Integer, primary_key=True)
id = Column(Integer, Identity(), primary_key=True)
created = Column(DATETIME_TYPE, default=dt_util.utcnow)
@declared_attr
@ -309,7 +309,7 @@ class StatisticsMeta(Base): # type: ignore
{"mysql_default_charset": "utf8mb4", "mysql_collate": "utf8mb4_unicode_ci"},
)
__tablename__ = TABLE_STATISTICS_META
id = Column(Integer, primary_key=True)
id = Column(Integer, Identity(), primary_key=True)
statistic_id = Column(String(255), index=True)
source = Column(String(32))
unit_of_measurement = Column(String(255))
@ -406,7 +406,7 @@ class StatisticsRuns(Base): # type: ignore
"""Representation of statistics run."""
__tablename__ = TABLE_STATISTICS_RUNS
run_id = Column(Integer, primary_key=True)
run_id = Column(Integer, Identity(), primary_key=True)
start = Column(DateTime(timezone=True))
def __repr__(self) -> str: