# Buggy code
def upgrade():
    try:
        op.create_table(
            "tokenowner",
            sa.Column("id", sa.Integer()),
            sa.Column("token_id", sa.Integer(), nullable=True),
            sa.Column("resolver", sa.Unicode(length=120), nullable=True),
            sa.Column("user_id", sa.Unicode(length=320), nullable=True),
            sa.Column("realm_id", sa.Integer(), nullable=True),
            sa.ForeignKeyConstraint(
                ["realm_id"],
                ["realm.id"],
            ),
            sa.ForeignKeyConstraint(
                ["token_id"],
                ["token.id"],
            ),
            sa.PrimaryKeyConstraint("id"),
        )
        op.create_index(
            op.f("ix_tokenowner_resolver"), "tokenowner", ["resolver"], unique=False
        )
        op.create_index(
            op.f("ix_tokenowner_user_id"), "tokenowner", ["user_id"], unique=False
        )
    except Exception as exx:
        print("Can not create table 'tokenowner'. It probably already exists")
        print(exx)

    try:
        bind = op.get_bind()
        session = orm.Session(bind=bind)
        # For each token, that has an owner, create a tokenowner entry
        for token in session.query(Token).filter(Token.user_id):
            token_realms = TokenRealm.query.filter(
                TokenRealm.token_id == token.id
            ).all()
            realm_id = None
            if not token_realms:
                sys.stderr.write(
                    "{serial!s}, {userid!s}, {resolver!s}, "
                    "Error while migrating token assignment. "
                    "This token has no realm assignments!".format(
                        serial=token.serial,
                        userid=token.user_id,
                        resolver=token.resolver,
                    )
                )
            elif len(token_realms) == 1:
                realm_id = token_realms[0].realm_id
            elif len(token_realms) > 1:
                # If the resolver is only contained in one realm, we fetch the realms:
                reso_realms = ResolverRealm.query.filter(
                    ResolverRealm.resolver == token.resolver
                ).all()
                if not reso_realms:
                    sys.stderr.write(
                        "{serial!s}, {userid!s}, {resolver!s}, "
                        "The token is assigned, but the assigned resolver is not "
                        "contained in any realm!".format(
                            serial=token.serial,
                            userid=token.user_id,
                            resolver=token.resolver,
                        )
                    )
                elif len(reso_realms) == 1:
                    # The resolver is only in one realm, so this is the new realm of the token!
                    realm_id = reso_realms[0].realm_id
                elif len(reso_realms) > 1:
                    # The resolver is contained in two realms, we have to apply more logic between the realms in which
                    # the resolver is contained and the realms, to which the token is assigend.
                    found_realm_ids = []
                    for token_realm in token_realms:
                        if token_realm.realm_id in [r.realm_id for r in reso_realms]:
                            # The token realm, that also fits the resolver_realm is used as owner realm
                            found_realm_ids.append(realm_id)
                        if len(found_realm_ids) > 1:
                            sys.stderr.write(
                                "{serial!s}, {userid!s}, {resolver!s}, "
                                "Your realm configuration for the token is not distinct!. "
                                "The tokenowner could be in multiple realms! "
                                "The token is assigned to the following realms and the resolver is also "
                                "contained in these realm IDs: {realms!s}.".format(
                                    serial=token.serial,
                                    userid=token.user_id,
                                    resolver=token.resolver,
                                    realms=found_realm_ids,
                                )
                            )
                        elif len(found_realm_ids) == 1:
                            realm_id = found_realm_ids[0]
                        else:
                            sys.stderr.write(
                                "{serial!s}, {userid!s}, {resolver!s}, "
                                "Can not assign token. The resolver is not contained in any "
                                "realms, to which the token is assigned!"
                            )

            to = TokenOwner(
                token_id=token.id,
                user_id=token.user_id,
                resolver=token.resolver,
                realm_id=realm_id,
            )
            session.add(to)
        session.commit()

        # Now we drop the columns
        op.drop_column("token", "user_id")
        op.drop_column("token", "resolver")
        op.drop_column("token", "resolver_type")

    except Exception as exx:
        session.rollback()
        print("Failed to migrate token assignment data!")
        print(exx)


# Traceback (OperationalError)
ERROR [sqlalchemy.pool.QueuePool] Exception during reset or similar
Traceback (most recent call last):
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/pool.py", line 742, in _finalize_fairy
fairy._reset(pool)
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/pool.py", line 927, in _reset
self._reset_agent.rollback()
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1697, in rollback
self._do_rollback()
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1735, in _do_rollback
self.connection._rollback_impl()
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 733, in _rollback_impl
self._handle_dbapi_exception(e, None, None, None, None)
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1458, in _handle_dbapi_exception
util.raise_from_cause(sqlalchemy_exception, exc_info)
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 296, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 731, in _rollback_impl
self.engine.dialect.do_rollback(self.connection)
File "/opt/venv/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py", line 2148, in do_rollback
dbapi_connection.rollback()
File "/opt/venv/lib/python2.7/site-packages/pymysql/connections.py", line 809, in rollback
self._read_ok_packet()
File "/opt/venv/lib/python2.7/site-packages/pymysql/connections.py", line 773, in _read_ok_packet
pkt = self._read_packet()
File "/opt/venv/lib/python2.7/site-packages/pymysql/connections.py", line 1032, in _read_packet
packet_header = self._read_bytes(4)
File "/opt/venv/lib/python2.7/site-packages/pymysql/connections.py", line 1078, in _read_bytes
CR.CR_SERVER_LOST, "Lost connection to MySQL server during query")
OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') (Background on this error at: http://sqlalche.me/e/e3q8)

# Fixed code
def upgrade():
    try:
        op.create_table(
            "tokenowner",
            sa.Column("id", sa.Integer()),
            sa.Column("token_id", sa.Integer(), nullable=True),
            sa.Column("resolver", sa.Unicode(length=120), nullable=True),
            sa.Column("user_id", sa.Unicode(length=320), nullable=True),
            sa.Column("realm_id", sa.Integer(), nullable=True),
            sa.ForeignKeyConstraint(
                ["realm_id"],
                ["realm.id"],
            ),
            sa.ForeignKeyConstraint(
                ["token_id"],
                ["token.id"],
            ),
            sa.PrimaryKeyConstraint("id"),
        )
        op.create_index(
            op.f("ix_tokenowner_resolver"), "tokenowner", ["resolver"], unique=False
        )
        op.create_index(
            op.f("ix_tokenowner_user_id"), "tokenowner", ["user_id"], unique=False
        )
    except Exception as exx:
        print("Can not create table 'tokenowner'. It probably already exists")
        print(exx)

    try:
        bind = op.get_bind()
        session = orm.Session(bind=bind)
        # For each token, that has an owner, create a tokenowner entry
        for token in session.query(Token).filter(Token.user_id):
            token_realms = (
                session.query(TokenRealm).filter(TokenRealm.token_id == token.id).all()
            )
            realm_id = None
            if not token_realms:
                sys.stderr.write(
                    "{serial!s}, {userid!s}, {resolver!s}, "
                    "Error while migrating token assignment. "
                    "This token has no realm assignments!".format(
                        serial=token.serial,
                        userid=token.user_id,
                        resolver=token.resolver,
                    )
                )
            elif len(token_realms) == 1:
                realm_id = token_realms[0].realm_id
            elif len(token_realms) > 1:
                # If the resolver is only contained in one realm, we fetch the realms:
                reso_realms = (
                    session.query(ResolverRealm)
                    .filter(ResolverRealm.resolver == token.resolver)
                    .all()
                )
                if not reso_realms:
                    sys.stderr.write(
                        "{serial!s}, {userid!s}, {resolver!s}, "
                        "The token is assigned, but the assigned resolver is not "
                        "contained in any realm!".format(
                            serial=token.serial,
                            userid=token.user_id,
                            resolver=token.resolver,
                        )
                    )
                elif len(reso_realms) == 1:
                    # The resolver is only in one realm, so this is the new realm of the token!
                    realm_id = reso_realms[0].realm_id
                elif len(reso_realms) > 1:
                    # The resolver is contained in two realms, we have to apply more logic between the realms in which
                    # the resolver is contained and the realms, to which the token is assigend.
                    found_realm_ids = []
                    for token_realm in token_realms:
                        if token_realm.realm_id in [r.realm_id for r in reso_realms]:
                            # The token realm, that also fits the resolver_realm is used as owner realm
                            found_realm_ids.append(realm_id)
                        if len(found_realm_ids) > 1:
                            sys.stderr.write(
                                "{serial!s}, {userid!s}, {resolver!s}, "
                                "Your realm configuration for the token is not distinct!. "
                                "The tokenowner could be in multiple realms! "
                                "The token is assigned to the following realms and the resolver is also "
                                "contained in these realm IDs: {realms!s}.".format(
                                    serial=token.serial,
                                    userid=token.user_id,
                                    resolver=token.resolver,
                                    realms=found_realm_ids,
                                )
                            )
                        elif len(found_realm_ids) == 1:
                            realm_id = found_realm_ids[0]
                        else:
                            sys.stderr.write(
                                "{serial!s}, {userid!s}, {resolver!s}, "
                                "Can not assign token. The resolver is not contained in any "
                                "realms, to which the token is assigned!"
                            )

            to = TokenOwner(
                token_id=token.id,
                user_id=token.user_id,
                resolver=token.resolver,
                realm_id=realm_id,
            )
            session.add(to)
        session.commit()

        # Now we drop the columns
        op.drop_column("token", "user_id")
        op.drop_column("token", "resolver")
        op.drop_column("token", "resolver_type")

    except Exception as exx:
        session.rollback()
        print("Failed to migrate token assignment data!")
        print(exx)