Upgrade to sqlalchemy 1.4.11 (#49538)
This commit is contained in:
parent
303ab36c54
commit
c10836fcee
12 changed files with 84 additions and 74 deletions
|
@ -1,8 +1,8 @@
|
|||
"""Schema migration helpers."""
|
||||
import logging
|
||||
|
||||
import sqlalchemy
|
||||
from sqlalchemy import ForeignKeyConstraint, MetaData, Table, text
|
||||
from sqlalchemy.engine import reflection
|
||||
from sqlalchemy.exc import (
|
||||
InternalError,
|
||||
OperationalError,
|
||||
|
@ -50,13 +50,13 @@ def migrate_schema(instance, current_version):
|
|||
for version in range(current_version, SCHEMA_VERSION):
|
||||
new_version = version + 1
|
||||
_LOGGER.info("Upgrading recorder db schema to version %s", new_version)
|
||||
_apply_update(instance.engine, new_version, current_version)
|
||||
_apply_update(instance.engine, session, new_version, current_version)
|
||||
session.add(SchemaChanges(schema_version=new_version))
|
||||
|
||||
_LOGGER.info("Upgrade to version %s done", new_version)
|
||||
|
||||
|
||||
def _create_index(engine, table_name, index_name):
|
||||
def _create_index(connection, table_name, index_name):
|
||||
"""Create an index for the specified table.
|
||||
|
||||
The index name should match the name given for the index
|
||||
|
@ -78,7 +78,7 @@ def _create_index(engine, table_name, index_name):
|
|||
index_name,
|
||||
)
|
||||
try:
|
||||
index.create(engine)
|
||||
index.create(connection)
|
||||
except (InternalError, ProgrammingError, OperationalError) as err:
|
||||
lower_err_str = str(err).lower()
|
||||
|
||||
|
@ -92,7 +92,7 @@ def _create_index(engine, table_name, index_name):
|
|||
_LOGGER.debug("Finished creating %s", index_name)
|
||||
|
||||
|
||||
def _drop_index(engine, table_name, index_name):
|
||||
def _drop_index(connection, table_name, index_name):
|
||||
"""Drop an index from a specified table.
|
||||
|
||||
There is no universal way to do something like `DROP INDEX IF EXISTS`
|
||||
|
@ -108,7 +108,7 @@ def _drop_index(engine, table_name, index_name):
|
|||
|
||||
# Engines like DB2/Oracle
|
||||
try:
|
||||
engine.execute(text(f"DROP INDEX {index_name}"))
|
||||
connection.execute(text(f"DROP INDEX {index_name}"))
|
||||
except SQLAlchemyError:
|
||||
pass
|
||||
else:
|
||||
|
@ -117,7 +117,7 @@ def _drop_index(engine, table_name, index_name):
|
|||
# Engines like SQLite, SQL Server
|
||||
if not success:
|
||||
try:
|
||||
engine.execute(
|
||||
connection.execute(
|
||||
text(
|
||||
"DROP INDEX {table}.{index}".format(
|
||||
index=index_name, table=table_name
|
||||
|
@ -132,7 +132,7 @@ def _drop_index(engine, table_name, index_name):
|
|||
if not success:
|
||||
# Engines like MySQL, MS Access
|
||||
try:
|
||||
engine.execute(
|
||||
connection.execute(
|
||||
text(
|
||||
"DROP INDEX {index} ON {table}".format(
|
||||
index=index_name, table=table_name
|
||||
|
@ -163,7 +163,7 @@ def _drop_index(engine, table_name, index_name):
|
|||
)
|
||||
|
||||
|
||||
def _add_columns(engine, table_name, columns_def):
|
||||
def _add_columns(connection, table_name, columns_def):
|
||||
"""Add columns to a table."""
|
||||
_LOGGER.warning(
|
||||
"Adding columns %s to table %s. Note: this can take several "
|
||||
|
@ -176,7 +176,7 @@ def _add_columns(engine, table_name, columns_def):
|
|||
columns_def = [f"ADD {col_def}" for col_def in columns_def]
|
||||
|
||||
try:
|
||||
engine.execute(
|
||||
connection.execute(
|
||||
text(
|
||||
"ALTER TABLE {table} {columns_def}".format(
|
||||
table=table_name, columns_def=", ".join(columns_def)
|
||||
|
@ -191,7 +191,7 @@ def _add_columns(engine, table_name, columns_def):
|
|||
|
||||
for column_def in columns_def:
|
||||
try:
|
||||
engine.execute(
|
||||
connection.execute(
|
||||
text(
|
||||
"ALTER TABLE {table} {column_def}".format(
|
||||
table=table_name, column_def=column_def
|
||||
|
@ -209,7 +209,7 @@ def _add_columns(engine, table_name, columns_def):
|
|||
)
|
||||
|
||||
|
||||
def _modify_columns(engine, table_name, columns_def):
|
||||
def _modify_columns(connection, engine, table_name, columns_def):
|
||||
"""Modify columns in a table."""
|
||||
if engine.dialect.name == "sqlite":
|
||||
_LOGGER.debug(
|
||||
|
@ -242,7 +242,7 @@ def _modify_columns(engine, table_name, columns_def):
|
|||
columns_def = [f"MODIFY {col_def}" for col_def in columns_def]
|
||||
|
||||
try:
|
||||
engine.execute(
|
||||
connection.execute(
|
||||
text(
|
||||
"ALTER TABLE {table} {columns_def}".format(
|
||||
table=table_name, columns_def=", ".join(columns_def)
|
||||
|
@ -255,7 +255,7 @@ def _modify_columns(engine, table_name, columns_def):
|
|||
|
||||
for column_def in columns_def:
|
||||
try:
|
||||
engine.execute(
|
||||
connection.execute(
|
||||
text(
|
||||
"ALTER TABLE {table} {column_def}".format(
|
||||
table=table_name, column_def=column_def
|
||||
|
@ -268,9 +268,9 @@ def _modify_columns(engine, table_name, columns_def):
|
|||
)
|
||||
|
||||
|
||||
def _update_states_table_with_foreign_key_options(engine):
|
||||
def _update_states_table_with_foreign_key_options(connection, engine):
|
||||
"""Add the options to foreign key constraints."""
|
||||
inspector = reflection.Inspector.from_engine(engine)
|
||||
inspector = sqlalchemy.inspect(engine)
|
||||
alters = []
|
||||
for foreign_key in inspector.get_foreign_keys(TABLE_STATES):
|
||||
if foreign_key["name"] and (
|
||||
|
@ -297,25 +297,26 @@ def _update_states_table_with_foreign_key_options(engine):
|
|||
|
||||
for alter in alters:
|
||||
try:
|
||||
engine.execute(DropConstraint(alter["old_fk"]))
|
||||
connection.execute(DropConstraint(alter["old_fk"]))
|
||||
for fkc in states_key_constraints:
|
||||
if fkc.column_keys == alter["columns"]:
|
||||
engine.execute(AddConstraint(fkc))
|
||||
connection.execute(AddConstraint(fkc))
|
||||
except (InternalError, OperationalError):
|
||||
_LOGGER.exception(
|
||||
"Could not update foreign options in %s table", TABLE_STATES
|
||||
)
|
||||
|
||||
|
||||
def _apply_update(engine, new_version, old_version):
|
||||
def _apply_update(engine, session, new_version, old_version):
|
||||
"""Perform operations to bring schema up to date."""
|
||||
connection = session.connection()
|
||||
if new_version == 1:
|
||||
_create_index(engine, "events", "ix_events_time_fired")
|
||||
_create_index(connection, "events", "ix_events_time_fired")
|
||||
elif new_version == 2:
|
||||
# Create compound start/end index for recorder_runs
|
||||
_create_index(engine, "recorder_runs", "ix_recorder_runs_start_end")
|
||||
_create_index(connection, "recorder_runs", "ix_recorder_runs_start_end")
|
||||
# Create indexes for states
|
||||
_create_index(engine, "states", "ix_states_last_updated")
|
||||
_create_index(connection, "states", "ix_states_last_updated")
|
||||
elif new_version == 3:
|
||||
# There used to be a new index here, but it was removed in version 4.
|
||||
pass
|
||||
|
@ -325,41 +326,41 @@ def _apply_update(engine, new_version, old_version):
|
|||
|
||||
if old_version == 3:
|
||||
# Remove index that was added in version 3
|
||||
_drop_index(engine, "states", "ix_states_created_domain")
|
||||
_drop_index(connection, "states", "ix_states_created_domain")
|
||||
if old_version == 2:
|
||||
# Remove index that was added in version 2
|
||||
_drop_index(engine, "states", "ix_states_entity_id_created")
|
||||
_drop_index(connection, "states", "ix_states_entity_id_created")
|
||||
|
||||
# Remove indexes that were added in version 0
|
||||
_drop_index(engine, "states", "states__state_changes")
|
||||
_drop_index(engine, "states", "states__significant_changes")
|
||||
_drop_index(engine, "states", "ix_states_entity_id_created")
|
||||
_drop_index(connection, "states", "states__state_changes")
|
||||
_drop_index(connection, "states", "states__significant_changes")
|
||||
_drop_index(connection, "states", "ix_states_entity_id_created")
|
||||
|
||||
_create_index(engine, "states", "ix_states_entity_id_last_updated")
|
||||
_create_index(connection, "states", "ix_states_entity_id_last_updated")
|
||||
elif new_version == 5:
|
||||
# Create supporting index for States.event_id foreign key
|
||||
_create_index(engine, "states", "ix_states_event_id")
|
||||
_create_index(connection, "states", "ix_states_event_id")
|
||||
elif new_version == 6:
|
||||
_add_columns(
|
||||
engine,
|
||||
session,
|
||||
"events",
|
||||
["context_id CHARACTER(36)", "context_user_id CHARACTER(36)"],
|
||||
)
|
||||
_create_index(engine, "events", "ix_events_context_id")
|
||||
_create_index(engine, "events", "ix_events_context_user_id")
|
||||
_create_index(connection, "events", "ix_events_context_id")
|
||||
_create_index(connection, "events", "ix_events_context_user_id")
|
||||
_add_columns(
|
||||
engine,
|
||||
connection,
|
||||
"states",
|
||||
["context_id CHARACTER(36)", "context_user_id CHARACTER(36)"],
|
||||
)
|
||||
_create_index(engine, "states", "ix_states_context_id")
|
||||
_create_index(engine, "states", "ix_states_context_user_id")
|
||||
_create_index(connection, "states", "ix_states_context_id")
|
||||
_create_index(connection, "states", "ix_states_context_user_id")
|
||||
elif new_version == 7:
|
||||
_create_index(engine, "states", "ix_states_entity_id")
|
||||
_create_index(connection, "states", "ix_states_entity_id")
|
||||
elif new_version == 8:
|
||||
_add_columns(engine, "events", ["context_parent_id CHARACTER(36)"])
|
||||
_add_columns(engine, "states", ["old_state_id INTEGER"])
|
||||
_create_index(engine, "events", "ix_events_context_parent_id")
|
||||
_add_columns(connection, "events", ["context_parent_id CHARACTER(36)"])
|
||||
_add_columns(connection, "states", ["old_state_id INTEGER"])
|
||||
_create_index(connection, "events", "ix_events_context_parent_id")
|
||||
elif new_version == 9:
|
||||
# We now get the context from events with a join
|
||||
# since its always there on state_changed events
|
||||
|
@ -369,32 +370,36 @@ def _apply_update(engine, new_version, old_version):
|
|||
# and we would have to move to something like
|
||||
# sqlalchemy alembic to make that work
|
||||
#
|
||||
_drop_index(engine, "states", "ix_states_context_id")
|
||||
_drop_index(engine, "states", "ix_states_context_user_id")
|
||||
_drop_index(connection, "states", "ix_states_context_id")
|
||||
_drop_index(connection, "states", "ix_states_context_user_id")
|
||||
# This index won't be there if they were not running
|
||||
# nightly but we don't treat that as a critical issue
|
||||
_drop_index(engine, "states", "ix_states_context_parent_id")
|
||||
_drop_index(connection, "states", "ix_states_context_parent_id")
|
||||
# Redundant keys on composite index:
|
||||
# We already have ix_states_entity_id_last_updated
|
||||
_drop_index(engine, "states", "ix_states_entity_id")
|
||||
_create_index(engine, "events", "ix_events_event_type_time_fired")
|
||||
_drop_index(engine, "events", "ix_events_event_type")
|
||||
_drop_index(connection, "states", "ix_states_entity_id")
|
||||
_create_index(connection, "events", "ix_events_event_type_time_fired")
|
||||
_drop_index(connection, "events", "ix_events_event_type")
|
||||
elif new_version == 10:
|
||||
# Now done in step 11
|
||||
pass
|
||||
elif new_version == 11:
|
||||
_create_index(engine, "states", "ix_states_old_state_id")
|
||||
_update_states_table_with_foreign_key_options(engine)
|
||||
_create_index(connection, "states", "ix_states_old_state_id")
|
||||
_update_states_table_with_foreign_key_options(connection, engine)
|
||||
elif new_version == 12:
|
||||
if engine.dialect.name == "mysql":
|
||||
_modify_columns(engine, "events", ["event_data LONGTEXT"])
|
||||
_modify_columns(engine, "states", ["attributes LONGTEXT"])
|
||||
_modify_columns(connection, engine, "events", ["event_data LONGTEXT"])
|
||||
_modify_columns(connection, engine, "states", ["attributes LONGTEXT"])
|
||||
elif new_version == 13:
|
||||
if engine.dialect.name == "mysql":
|
||||
_modify_columns(
|
||||
engine, "events", ["time_fired DATETIME(6)", "created DATETIME(6)"]
|
||||
connection,
|
||||
engine,
|
||||
"events",
|
||||
["time_fired DATETIME(6)", "created DATETIME(6)"],
|
||||
)
|
||||
_modify_columns(
|
||||
connection,
|
||||
engine,
|
||||
"states",
|
||||
[
|
||||
|
@ -404,7 +409,7 @@ def _apply_update(engine, new_version, old_version):
|
|||
],
|
||||
)
|
||||
elif new_version == 14:
|
||||
_modify_columns(engine, "events", ["event_type VARCHAR(64)"])
|
||||
_modify_columns(connection, engine, "events", ["event_type VARCHAR(64)"])
|
||||
else:
|
||||
raise ValueError(f"No schema migration defined for version {new_version}")
|
||||
|
||||
|
@ -418,7 +423,7 @@ def _inspect_schema_version(engine, session):
|
|||
version 1 are present to make the determination. Eventually this logic
|
||||
can be removed and we can assume a new db is being created.
|
||||
"""
|
||||
inspector = reflection.Inspector.from_engine(engine)
|
||||
inspector = sqlalchemy.inspect(engine)
|
||||
indexes = inspector.get_indexes("events")
|
||||
|
||||
for index in indexes:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue