I have a certain SQLAlchemy declarative Base that I create on a sqlite memory DB:
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
I'm using this for unit testing logic.
With this I have my tables in the DB. But now I wish to migrate certain things using alembic.
AFAIK alembic migrations use the env.py
run_migrations_online and there uses a SQLAlchemy function called engine_from_config
creating a new engine here.
The problem I wish to solve is to have a way to use the previously created connection, which holds the recently created tables, for the alembic migrations.
I used this on my test scripts: Using Alembic API from inside application code, so that my script does the following after the previous create_all
call:
import alembic.config
alembicArgs = ['--raiseerr', '-x', 'dbPath=sqlite:///:memory:', 'upgrade', 'head']
alembic.config.main(argv=alembicArgs
[Please mind, I would just create my schemas with the Base.metadata.create_all(engine)
call but my alembic versions not only hold schema changes, they also have some filling of catalog tables data, that's why I intend to use alembic here. In fact, if my alembic migrations hold some "create tables" logic, these two would conflict. So I can safely remove the create_all
call and depend on alembic alone to create my schemas here.]
Having already modified my alembic's env.py
:
def run_migrations_online():
ini_section = config.get_section(config.config_ini_section)
db_path = context.get_x_argument(as_dictionary=True).get('dbPath')
if db_path:
ini_section['sqlalchemy.url'] = db_path
connectable = engine_from_config(
ini_section,
prefix ... # everything from here the same as default env.py
As far as I can tell the connectable=engine_from_config
creates a connection to a new engine on a new sqlite:///:memory:
database, and that's why I can't upgrade via alembic the previously created DB on my script with create_all(engine)
.
So... TLDR; is there a way to pass my previously existing engine connection (with my created tables) to alembic so that it can migrate it? (I'm pretty sure that the dbPath arg I created is useless here, in fact, I'm just copying what the other post I referenced uses).
Usage of Alembic starts with creation of the Migration Environment. This is a directory of scripts that is specific to a particular application. The migration environment is created just once, and is then maintained along with the application's source code itself.
The sqlalchemy migrations are one of the features, and it migrates to provide a way of dealing with the database schema and its changes in the sqlalchemy projects; it migrates the data with the help of some tools like alembic is one of the data migration tools that offer the Alter statement to the specific database to ...
The autogenerate process scans across all table objects within the database that is referred towards by the current database connection in use. The list of objects that are scanned in the target database connection include: The “default” schema currently referred towards by the database connection.
Show activity on this post. Delete (or move to another folder) the specific migration file (in migrations/versions folder). The head will automatically revert to the most recent remaining migration. Using stamp will set the db version value to the specified revision; not alter the head revision number.
You can create an alembic config instance and do operations on it:
def migrate_in_memory(migrations_path, alembic_ini_path=None, connection=None, revision="head"):
config = alembic.config.Config(alembic_ini_path)
config.set_main_option('script_location', migrations_path)
config.set_main_option('sqlalchemy.url', 'sqlite:///:memory:')
if connection is not None:
config.attributes['connection'] = connection
alembic.command.upgrade(config, revision)
It might take some fine tuning, but that's the general gist of things.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With