def _rename_column_in_table_if_needed( table: Type[Model], old_column_name: str, new_column_name: str, ) -> bool: column_name = old_column_name.lower() table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if new_column_name in cols: log.info(f'Column {new_column_name} already exists in {table}') return False if old_column_name not in cols: log.info(f'Column {old_column_name} not exists in {table}') return False log.info(f'Changing {column_name} -> {new_column_name} in {table}') migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate( migrator.rename_column( table_name, old_column_name, new_column_name, ), ) db_config.database.commit() return True
def _add_not_null(table: Type[Model], column_name: str) -> bool: table_name = table.__name__.lower() migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate(migrator.add_not_null(table_name, column_name)) db_config.database.commit() return True
def _migrate_column_in_table_if_needed( table: Type[Model], field_instance: Field, *, field_name: Optional[str] = None, **kwargs: Any, ) -> bool: column_name = field_name or field_instance.name table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if column_name in cols: log.info(f'Column {column_name} already exists in {table}') return False log.info(f'Create {column_name} field in {table}') migrator = db_config.get_migrator_instance() with db_config.database.transaction(): try: migrate( migrator.add_column( table=table_name, column_name=column_name, field=field_instance, **kwargs, )) except (OperationalError, ProgrammingError) as e: if 'does not exist' in str(e): log.info(f'Column {field_name} already exists: {e}') else: raise db_config.database.commit() return True
def _alter_column_type_if_needed( table: Type[Model], field_instance: Field, new_type: Field, ) -> bool: field_type_name = new_type.__class__.__name__ current_type = field_instance.__class__.__name__ column_name = field_instance.name.lower() table_name = table.__name__.lower() if field_type_name.lower() == current_type.lower(): log.info(f'Column {column_name} is already {field_type_name}') return False log.info( f'Changing {column_name} from {current_type} ' f'to {field_type_name} in {table}', ) migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate( migrator.alter_column_type(table_name, column_name, new_type), ) db_config.database.commit() return True
def _add_user_course_constaint() -> bool: migrator = db_config.get_migrator_instance() with db_config.database.transaction(): try: migrate( migrator.add_index( 'usercourse', ('user_id', 'course_id'), True, ), ) except (OperationalError, ProgrammingError) as e: log.info(f'Index usercourse user and course already exists: {e}') db_config.database.commit()
def _add_exercise_course_id_and_number_columns_constraint() -> bool: Exercise = models.Exercise migrator = db_config.get_migrator_instance() with db_config.database.transaction(): _add_not_null_column(Exercise, Exercise.course) _add_not_null_column(Exercise, Exercise.number) try: migrate( migrator.add_index('exercise', ('course_id', 'number'), True), ) except (OperationalError, ProgrammingError) as e: log.info(f'Index exercise course and number already exists: {e}') db_config.database.commit()
def _migrate_copy_column(table: Type[Model], source: str, dest: str) -> bool: table_name = table.__name__.lower() migrator = db_config.get_migrator_instance() with db_config.database.transaction(): (db_config.database.execute_sql( migrator.make_context().literal('UPDATE ').sql( Entity(table_name)).literal(' SET ').sql( Expression( Entity(dest), OP.EQ, SQL(' solution_id'), flat=True, ), ).query()[0], )) return True
def _drop_constraint_if_needed(table: Type[Model], column_name: str) -> bool: table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if column_name not in cols: log.info(f'Column {column_name} not exists in {table}') return False log.info(f'Drop foreign key on {table}.{column_name}') migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate(migrator.drop_constraint(table_name, column_name)) db_config.database.commit() return True
def _add_not_null_column( table: Model, column: Field, run_before_adding_not_null: Callable[[Model, Field], None] = None, ) -> bool: already_exists, table_name, column_name = get_details(table, column) log.info(f'Adding {table_name}.{column_name}, if needed.') if already_exists: log.info(f'Column {column_name} already exists in {table_name}.') return False migrator = db_config.get_migrator_instance() with db_config.database.transaction(): column.null = True migrate(migrator.add_column(table_name, column_name, field=column)) if callable(run_before_adding_not_null): run_before_adding_not_null(table, column) migrate(migrator.drop_not_null(table_name, column_name)) db_config.database.commit() return True
def _drop_index_if_needed( table: Type[Model], field_instance: Field, foreign_key: bool = False, ) -> None: table_name = table.__name__.lower() suffix = '_id' if foreign_key else '' column_name = f'{table_name}_{field_instance.name}{suffix}' migrator = db_config.get_migrator_instance() log.info(f"Drop index from '{column_name}' field in '{table_name}'") with db_config.database.transaction(): try: migrate(migrator.drop_index(table_name, column_name)) except (OperationalError, ProgrammingError) as e: if 'does not exist' in str(e): log.info('Index already exists.') else: raise db_config.database.commit()
def _drop_column_from_module_if_needed( table: Type[Model], column_name: str, ) -> bool: table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if column_name not in cols: print(f'Column {column_name} not exists in {table}') # noqa: T001 return False print(f'Drop {column_name} field in {table}') # noqa: T001 migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate(migrator.drop_column( table_name, column_name, )) db_config.database.commit() return True
def _migrate_column_in_table_if_needed( table: Type[Model], field_instance: Field, ) -> bool: column_name = field_instance.name table_name = table.__name__.lower() cols = {col.name for col in db_config.database.get_columns(table_name)} if column_name in cols: print(f'Column {column_name} already exists in {table}') # noqa: T001 return False print(f'Create {column_name} field in {table}') # noqa: T001 migrator = db_config.get_migrator_instance() with db_config.database.transaction(): migrate(migrator.add_column( table_name, field_instance.name, field_instance, )) db_config.database.commit() return True
def _add_index_if_needed( table: Type[Model], field_instance: Field, is_unique_constraint: bool = False, ) -> None: column_name = field_instance.name table_name = table.__name__.lower() migrator = db_config.get_migrator_instance() log.info(f"Add index to '{column_name}' field in '{table_name}'") with db_config.database.transaction(): try: migrate( migrator.add_index( table_name, (column_name, ), is_unique_constraint, ), ) except (OperationalError, ProgrammingError) as e: if 'already exists' in str(e): log.info('Index already exists.') else: raise db_config.database.commit()