I have multiple databases like account and meeting. There are relations between tables in different databases e.g. uuid which is present in account database user table has relation to meeting_info table in meeting database. my code structure goes as follows::
account.py
from sqlalchemy.ext.declarative import declarative_base
Base1 = declarative_base()
DATABASE = "vc_account_mdb"
class User(Base1):
__tablename__ = "users"
__table_args__ = {"schema": DATABASE}
uuid = Column(BigInteger, primary_key=True, nullable=False)
first_name = Column(String(32), nullable=False)
last_name = Column(String(32), nullable=True)
def __repr__(self):
return f"<User model {self.uuid}>"
meeting.py
from sqlalchemy.ext.declarative import declarative_base
Base2 = declarative_base()
DATABASE = "vc_meeting_mdb"
class MeetingInfo(Base2):
__tablename__ = "meeting_infos"
__table_args__ = {"schema": DATABASE}
meeting_info_id = Column(BigInteger, primary_key=True, nullable=False)
meeting_name = Column(String(64), nullable=False)
def __repr__(self):
return f"<Meeting model {self.uuid}>"
i am trying to generate migration using alembic as follows alembic revision --autogenerate -m "ver1" but i see migration getting generated only for one db even though change is present in both dbs
alembic.ini
revision_environment = true
databases=vc_account_mdb, vc_meeting_mdb
[vc_account_mdb]
sqlalchemy.url = mysql+pymysql://user:password@123.456.789.123:30002/vc_account_mdb
version_locations = ./migrations/account
[vc_meeting_mdb]
sqlalchemy.url = mysql+pymysql://user:password@123.456.789.123:30002/vc_meeting_mdb
version_locations = ./migrations/meeting
env.py
USE_TWOPHASE = False
db_names = config.get_main_option("vc_account_mdb","vc_meeting_mdb")
from account import Base1
from meeting import Base2
target_metadata = {
'vc_account_mdb':Base1.metadata,
'vc_meeting_mdb':Base2.metadata
}
def run_migrations_offline() -> None:
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
# for the --sql use case, run migrations for each URL into
# individual files.
engines = {}
for name in re.split(r",\s*", db_names):
engines[name] = rec = {}
rec["url"] = context.config.get_section_option(name, "sqlalchemy.url")
for name, rec in engines.items():
logger.info("Migrating database %s" % name)
file_ = "%s.sql" % name
logger.info("Writing output to %s" % file_)
with open(file_, "w") as buffer:
context.configure(
url=rec["url"],
output_buffer=buffer,
target_metadata=target_metadata.get(name),
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations(engine_name=name)
def run_migrations_online() -> None:
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
# for the direct-to-DB use case, start a transaction on all
# engines, then run all migrations, then commit all transactions.
engines = {}
for name in re.split(r",\s*", db_names):
engines[name] = rec = {}
rec["engine"] = engine_from_config(
context.config.get_section(name),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
for name, rec in engines.items():
engine = rec["engine"]
rec["connection"] = conn = engine.connect()
if USE_TWOPHASE:
rec["transaction"] = conn.begin_twophase()
else:
rec["transaction"] = conn.begin()
try:
for name, rec in engines.items():
logger.info("Migrating database %s" % name)
context.configure(
connection=rec["connection"],
upgrade_token="%s_upgrades" % name,
downgrade_token="%s_downgrades" % name,
target_metadata=target_metadata.get(name),
)
context.run_migrations(engine_name=name)
if USE_TWOPHASE:
for rec in engines.values():
rec["transaction"].prepare()
for rec in engines.values():
rec["transaction"].commit()
except:
for rec in engines.values():
rec["transaction"].rollback()
raise
finally:
for rec in engines.values():
rec["connection"].close()
Below is the generated version file
"""ver1
Revision ID: ca541d0cd39c
Revises:
Create Date: 2022-11-03 07:02:16.633969
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'ca541d0cd39c'
down_revision = None
branch_labels = None
depends_on = None
def upgrade(engine_name: str) -> None:
globals()["upgrade_%s" % engine_name]()
def downgrade(engine_name: str) -> None:
globals()["downgrade_%s" % engine_name]()
def upgrade_vc_account_mdb() -> None:
pass
def downgrade_vc_account_mdb() -> None:
pass
def upgrade_vc_meeting_mdb() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('meeting_infos',
sa.Column('meeting_info_id', sa.BigInteger(), nullable=False),
sa.Column('meeting_name', sa.String(length=64), nullable=False),
sa.PrimaryKeyConstraint('meeting_info_id'),
schema='vc_meeting_mdb'
)
# ### end Alembic commands ###
def downgrade_vc_meeting_mdb() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('meeting_infos', schema='vc_meeting_mdb')
# ### end Alembic commands ###
It is not clear why account db is empty and revision generated for it