Add auto repairs for events schema (#90136)

* Add auto repairs for events schema

* Add auto repairs for events schema

* Add auto repairs for events schema

* Add auto repairs for events schema

* Add auto repairs for events schema

* fix bug - wrong table
This commit is contained in:
J. Nick Koston 2023-03-22 15:17:36 -10:00 committed by GitHub
parent 31c988c4f0
commit 8a591fa16e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 8 deletions

View file

@ -0,0 +1 @@
"""events repairs for Recorder."""

View file

@ -0,0 +1,31 @@
"""Events schema repairs."""
from __future__ import annotations
from typing import TYPE_CHECKING
from ...db_schema import EventData, Events
from ..schema import (
correct_db_schema_precision,
correct_db_schema_utf8,
validate_db_schema_precision,
validate_table_schema_supports_utf8,
)
if TYPE_CHECKING:
from ... import Recorder
def validate_db_schema(instance: Recorder) -> set[str]:
"""Do some basic checks for common schema errors caused by manual migration."""
return validate_table_schema_supports_utf8(
instance, EventData, (EventData.shared_data,)
) | validate_db_schema_precision(instance, Events)
def correct_db_schema(
instance: Recorder,
schema_errors: set[str],
) -> None:
"""Correct issues detected by validate_db_schema."""
correct_db_schema_utf8(instance, EventData, schema_errors)
correct_db_schema_precision(instance, Events, schema_errors)

View file

@ -28,6 +28,10 @@ from homeassistant.core import HomeAssistant
from homeassistant.util.enum import try_parse_enum
from homeassistant.util.ulid import ulid_to_bytes
from .auto_repairs.events.schema import (
correct_db_schema as events_correct_db_schema,
validate_db_schema as events_validate_db_schema,
)
from .auto_repairs.states.schema import (
correct_db_schema as states_correct_db_schema,
validate_db_schema as states_validate_db_schema,
@ -199,6 +203,7 @@ def _find_schema_errors(
schema_errors: set[str] = set()
schema_errors |= statistics_validate_db_schema(instance)
schema_errors |= states_validate_db_schema(instance)
schema_errors |= events_validate_db_schema(instance)
return schema_errors
@ -250,6 +255,7 @@ def migrate_schema(
)
statistics_correct_db_schema(instance, schema_errors)
states_correct_db_schema(instance, schema_errors)
events_correct_db_schema(instance, schema_errors)
if current_version != SCHEMA_VERSION:
instance.queue_task(PostSchemaMigrationTask(current_version, SCHEMA_VERSION))

View file

@ -0,0 +1 @@
"""Tests for Recorder component."""

View file

@ -0,0 +1,76 @@
"""The test repairing events schema."""
# pylint: disable=invalid-name
from unittest.mock import ANY, patch
import pytest
from homeassistant.core import HomeAssistant
from ...common import async_wait_recording_done
from tests.typing import RecorderInstanceGenerator
@pytest.mark.parametrize("enable_schema_validation", [True])
@pytest.mark.parametrize("db_engine", ("mysql", "postgresql"))
async def test_validate_db_schema_fix_float_issue(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
db_engine,
) -> None:
"""Test validating DB schema with postgresql and mysql.
Note: The test uses SQLite, the purpose is only to exercise the code.
"""
with patch(
"homeassistant.components.recorder.core.Recorder.dialect_name", db_engine
), patch(
"homeassistant.components.recorder.auto_repairs.schema._validate_db_schema_precision",
return_value={"events.double precision"},
), patch(
"homeassistant.components.recorder.migration._modify_columns"
) as modify_columns_mock:
await async_setup_recorder_instance(hass)
await async_wait_recording_done(hass)
assert "Schema validation failed" not in caplog.text
assert (
"Database is about to correct DB schema errors: events.double precision"
in caplog.text
)
modification = [
"time_fired_ts DOUBLE PRECISION",
]
modify_columns_mock.assert_called_once_with(ANY, ANY, "events", modification)
@pytest.mark.parametrize("enable_schema_validation", [True])
async def test_validate_db_schema_fix_utf8_issue_event_data(
async_setup_recorder_instance: RecorderInstanceGenerator,
hass: HomeAssistant,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test validating DB schema with MySQL.
Note: The test uses SQLite, the purpose is only to exercise the code.
"""
with patch(
"homeassistant.components.recorder.core.Recorder.dialect_name", "mysql"
), patch(
"homeassistant.components.recorder.auto_repairs.schema._validate_table_schema_supports_utf8",
return_value={"event_data.4-byte UTF-8"},
):
await async_setup_recorder_instance(hass)
await async_wait_recording_done(hass)
assert "Schema validation failed" not in caplog.text
assert (
"Database is about to correct DB schema errors: event_data.4-byte UTF-8"
in caplog.text
)
assert (
"Updating character set and collation of table event_data to utf8mb4"
in caplog.text
)

View file

@ -1,5 +1 @@
"""Tests for Recorder component."""
import pytest
pytest.register_assert_rewrite("tests.components.recorder.common")

View file

@ -1,5 +1 @@
"""Tests for Recorder component."""
import pytest
pytest.register_assert_rewrite("tests.components.recorder.common")