diff --git a/homeassistant/components/recorder/migration.py b/homeassistant/components/recorder/migration.py index aeb62cc111d..e730b1af239 100644 --- a/homeassistant/components/recorder/migration.py +++ b/homeassistant/components/recorder/migration.py @@ -204,6 +204,44 @@ def _add_columns(engine, table_name, columns_def): ) +def _modify_columns(engine, table_name, columns_def): + """Modify columns in a table.""" + _LOGGER.warning( + "Modifying columns %s in table %s. Note: this can take several " + "minutes on large databases and slow computers. Please " + "be patient!", + ", ".join(column.split(" ")[0] for column in columns_def), + table_name, + ) + columns_def = [f"MODIFY {col_def}" for col_def in columns_def] + + try: + engine.execute( + text( + "ALTER TABLE {table} {columns_def}".format( + table=table_name, columns_def=", ".join(columns_def) + ) + ) + ) + return + except (InternalError, OperationalError): + _LOGGER.info("Unable to use quick column modify. Modifying 1 by 1") + + for column_def in columns_def: + try: + engine.execute( + text( + "ALTER TABLE {table} {column_def}".format( + table=table_name, column_def=column_def + ) + ) + ) + except (InternalError, OperationalError): + _LOGGER.exception( + "Could not modify column %s in table %s", column_def, table_name + ) + + def _update_states_table_with_foreign_key_options(engine): """Add the options to foreign key constraints.""" inspector = reflection.Inspector.from_engine(engine) @@ -321,6 +359,10 @@ def _apply_update(engine, new_version, old_version): elif new_version == 11: _create_index(engine, "states", "ix_states_old_state_id") _update_states_table_with_foreign_key_options(engine) + elif new_version == 12: + if engine.dialect.name == "mysql": + _modify_columns(engine, "events", ["event_data LONGTEXT"]) + _modify_columns(engine, "states", ["attributes LONGTEXT"]) 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 69e2115ce34..551abeac15a 100644 --- a/homeassistant/components/recorder/models.py +++ b/homeassistant/components/recorder/models.py @@ -13,6 +13,7 @@ from sqlalchemy import ( Text, distinct, ) +from sqlalchemy.dialects import mysql from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship from sqlalchemy.orm.session import Session @@ -25,7 +26,7 @@ import homeassistant.util.dt as dt_util # pylint: disable=invalid-name Base = declarative_base() -SCHEMA_VERSION = 11 +SCHEMA_VERSION = 12 _LOGGER = logging.getLogger(__name__) @@ -49,7 +50,7 @@ class Events(Base): # type: ignore __tablename__ = TABLE_EVENTS event_id = Column(Integer, primary_key=True) event_type = Column(String(32)) - event_data = Column(Text) + event_data = Column(Text().with_variant(mysql.LONGTEXT, "mysql")) origin = Column(String(32)) time_fired = Column(DateTime(timezone=True), index=True) created = Column(DateTime(timezone=True), default=dt_util.utcnow) @@ -109,7 +110,7 @@ class States(Base): # type: ignore domain = Column(String(64)) entity_id = Column(String(255)) state = Column(String(255)) - attributes = Column(Text) + attributes = Column(Text().with_variant(mysql.LONGTEXT, "mysql")) event_id = Column( Integer, ForeignKey("events.event_id", ondelete="CASCADE"), index=True )