diff --git a/homeassistant/components/recorder/migration.py b/homeassistant/components/recorder/migration.py index 5ab2d909172..fa93f615561 100644 --- a/homeassistant/components/recorder/migration.py +++ b/homeassistant/components/recorder/migration.py @@ -206,6 +206,16 @@ def _add_columns(engine, table_name, columns_def): def _modify_columns(engine, table_name, columns_def): """Modify columns in a table.""" + if engine.dialect.name == "sqlite": + _LOGGER.debug( + "Skipping to modify columns %s in table %s; " + "Modifying column length in SQLite is unnecessary, " + "it does not impose any length restrictions", + ", ".join(column.split(" ")[0] for column in columns_def), + table_name, + ) + return + _LOGGER.warning( "Modifying columns %s in table %s. Note: this can take several " "minutes on large databases and slow computers. Please " @@ -213,7 +223,18 @@ def _modify_columns(engine, table_name, columns_def): ", ".join(column.split(" ")[0] for column in columns_def), table_name, ) - columns_def = [f"MODIFY {col_def}" for col_def in columns_def] + + if engine.dialect.name == "postgresql": + columns_def = [ + "ALTER {column} TYPE {type}".format( + **dict(zip(["column", "type"], col_def.split(" ", 1))) + ) + for col_def in columns_def + ] + elif engine.dialect.name == "mssql": + columns_def = [f"ALTER COLUMN {col_def}" for col_def in columns_def] + else: + columns_def = [f"MODIFY {col_def}" for col_def in columns_def] try: engine.execute( @@ -377,6 +398,8 @@ def _apply_update(engine, new_version, old_version): "created DATETIME(6)", ], ) + elif new_version == 14: + _modify_columns(engine, "events", ["event_type VARCHAR(64)"]) 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 a547f315133..b26c523ce40 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -26,7 +26,7 @@ import homeassistant.util.dt as dt_util # pylint: disable=invalid-name Base = declarative_base() -SCHEMA_VERSION = 13 +SCHEMA_VERSION = 14 _LOGGER = logging.getLogger(__name__) @@ -53,7 +53,7 @@ class Events(Base): # type: ignore } __tablename__ = TABLE_EVENTS event_id = Column(Integer, primary_key=True) - event_type = Column(String(32)) + event_type = Column(String(64)) event_data = Column(Text().with_variant(mysql.LONGTEXT, "mysql")) origin = Column(String(32)) time_fired = Column(DATETIME_TYPE, index=True) diff --git a/tests/components/recorder/test_migrate.py b/tests/components/recorder/test_migrate.py index 3bde17ab8ef..c4e0d32adcf 100644 --- a/tests/components/recorder/test_migrate.py +++ b/tests/components/recorder/test_migrate.py @@ -76,6 +76,26 @@ def test_invalid_update(): migration._apply_update(None, -1, 0) +@pytest.mark.parametrize( + ["engine_type", "substr"], + [ + ("postgresql", "ALTER event_type TYPE VARCHAR(64)"), + ("mssql", "ALTER COLUMN event_type VARCHAR(64)"), + ("mysql", "MODIFY event_type VARCHAR(64)"), + ("sqlite", None), + ], +) +def test_modify_column(engine_type, substr): + """Test that modify column generates the expected query.""" + engine = Mock() + engine.dialect.name = engine_type + migration._modify_columns(engine, "events", ["event_type VARCHAR(64)"]) + if substr: + assert substr in engine.execute.call_args[0][0].text + else: + assert not engine.execute.called + + def test_forgiving_add_column(): """Test that add column will continue if column exists.""" engine = create_engine("sqlite://", poolclass=StaticPool)