Fix migration failing when existing data has duplicates (#88712)

pull/88979/head
J. Nick Koston 2023-02-24 11:41:44 -06:00 committed by Paulus Schoutsen
parent e69271cb46
commit 0c6a469218
2 changed files with 26 additions and 5 deletions

View File

@ -13,6 +13,7 @@ from sqlalchemy import ForeignKeyConstraint, MetaData, Table, func, text
from sqlalchemy.engine import CursorResult, Engine
from sqlalchemy.exc import (
DatabaseError,
IntegrityError,
InternalError,
OperationalError,
ProgrammingError,
@ -778,9 +779,10 @@ def _apply_update( # noqa: C901
# Add name column to StatisticsMeta
_add_columns(session_maker, "statistics_meta", ["name VARCHAR(255)"])
elif new_version == 24:
_LOGGER.debug("Deleting duplicated statistics entries")
with session_scope(session=session_maker()) as session:
delete_statistics_duplicates(hass, session)
# This used to create the unique indices for start and statistic_id
# but we changed the format in schema 34 which will now take care
# of removing any duplicate if they still exist.
pass
elif new_version == 25:
_add_columns(session_maker, "states", [f"attributes_id {big_int}"])
_create_index(session_maker, "states", "ix_states_attributes_id")
@ -907,7 +909,26 @@ def _apply_update( # noqa: C901
"statistics_short_term",
"ix_statistics_short_term_statistic_id_start_ts",
)
_migrate_statistics_columns_to_timestamp(session_maker, engine)
try:
_migrate_statistics_columns_to_timestamp(session_maker, engine)
except IntegrityError as ex:
_LOGGER.error(
"Statistics table contains duplicate entries: %s; "
"Cleaning up duplicates and trying again; "
"This will take a while; "
"Please be patient!",
ex,
)
# There may be duplicated statistics entries, delete duplicates
# and try again
with session_scope(session=session_maker()) as session:
delete_statistics_duplicates(hass, session)
_migrate_statistics_columns_to_timestamp(session_maker, engine)
# Log at error level to ensure the user sees this message in the log
# since we logged the error above.
_LOGGER.error(
"Statistics migration successfully recovered after statistics table duplicate cleanup"
)
elif new_version == 35:
# Migration is done in two steps to ensure we can start using
# the new columns before we wipe the old ones.

View File

@ -125,7 +125,7 @@ def session_scope(
need_rollback = True
session.commit()
except Exception as err: # pylint: disable=broad-except
_LOGGER.error("Error executing query: %s", err)
_LOGGER.error("Error executing query: %s", err, exc_info=True)
if need_rollback:
session.rollback()
if not exception_filter or not exception_filter(err):