Support for custom DDL in Alembic autogenerate command.
Project description
Alembic Dumb DDL
A plugin for Alembic DB migration tool which add support for arbitrary DDL scripts in autogenerate command.
Why is it dumb?
Because it doesn't try to be smart. It's really hard to compare arbitrary DDL scripts in the database with their sources in the project folder, because the scripts can contain multiple DDL statements, they may use version-specific features of a DBMS and they can be written for different DBMSs.
Alembic Dumb DDL doesn't check the state of the objects in the database, it only checks if the source code of the script has changed, comparing to the previous revision. And that's why Alembic Dumb DDL supports all databases and any kind of DDL scripts.
Quick start
Step 1: save your DDL script in a file, and make sure that it overwrites the entities, instead of just creating them (e.g. starts with DROP ... IF EXISTS
or similar construct for your DBMS).
-- myapp/scripts/last_month_orders.sql
DROP VIEW IF EXISTS last_month_orders;
CREATE VIEW last_month_orders AS
SELECT *
FROM orders
WHERE order_date > current_date - interval '30 days';
Step 2: Wrap your script in a DDL
class:
# myapp/models.py
from alembic_dddl import DDL
from pathlib import Path
SCRIPTS = Path(__file__).parent / "scripts"
def load_sql(filename: str) -> str:
"""Helper function to load the contents of a file from a `scripts` directory"""
return (SCRIPTS / filename).read_text()
my_ddl = DDL(
# will be used in revision filename
name="last_month_orders",
# DDL script SQL code, will be used in upgrade command
sql=load_sql("last_month_orders.sql"),
# Cleanup SQL code, will be used in the first downgrade command
down_sql="DROP VIEW IF EXISTS last_month_orders;",
)
Step 3: Register your ddl in alembic's env.py
:
# migrations/env.py
from myapp.models import my_ddl
from alembic_dddl import register_ddl
register_ddl(my_ddl)
# ...
# the rest of the env.py file
That's it, from now on the alembic autogenerate command will keep track of last_month_orders.sql
, and if it changes — automatically add update code to your migration scripts to update your entities.
The first run of the autogenerate command:
$ alembic revision --autogenerate -m "last_month_orders"
INFO [alembic.runtime.migration] Context impl SQLiteImpl.
INFO [alembic.runtime.migration] Will assume non-transactional DDL.
INFO [alembic_dddl.dddl] Loaded scripts location from config: migrations/versions/ddl
INFO [alembic_dddl.dddl] Detected new DDL "last_month_orders"
Generating /Users/user/Projects/Python/alembic_custom_ddl/example/migrations/versions/2024_01_08_0955-0c897e9399a9_last_month_orders.py ... done
For more detailed example see Example Project.
Installation
You can install Alembic Dumb DDL from pip:
pip install alembic_dddl
How does it work
Take a look at the example project.
Alembic Dumb DDL stores revisions of your DDL scripts in a folder inside versions
directory (by default the folder is called versions/ddl
). When you run alembic revision --autogenerate
command Alembic Dumb DDL checks if any new DDL scripts were added, or if any of the existing ones are changed. For each such changed script its copy will be saved in the versions/ddl
folder. This is the state against which the new changes in DDL scripts will be detected.
Along with creating the revisioned copy of the changed or added DDL scripts, Alembic Dumb DDL will also add upgrade and downgrade commands into the migration script itself.
The upgrade command will look like this:
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.run_ddl_script('2024_01_08_1045_order_details_060d60b5c278.sql')
run_ddl_script
is an operation added to alembic by Alembic Dumb DDL. All it does is executes each statement in the script against the database.
There are two variations of the downgrade command.
For the new DDL scripts (without existing revisions) it will be copied from the DDL.down_sql
, as you defined it:
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute('DROP VIEW IF EXISTS order_details;')
If DDL script already existed and was changed in this revision, the downgrade command will look similar to the upgrade command, but for previous version of the script:
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.run_ddl_script('2024_01_08_1016_order_details_af80846764cd.sql')
Because each DDL script is used for both upgrade and downgrade commands, it's important that the script is overwriting entities, not just creating them. i.e. it should start with
DROP ... IF EXISTS
or similar construct for your DBMS.
Configuration
Alembic Dumb DDL has several configuration options. To set them, add [alembic_dddl]
section to alembic.ini
.
Here are the options and their default values:
[alembic_dddl]
# where the revisioned copies of DDL scripts will be stored
scripts_location = migrations/versions/ddl
# use timestamps instead of datetime in revisioned scripts file format
use_timestamps = False
# whether the comments should be ignored when comparing DDL scripts
ignore_comments = False
Setting up Logging
Alembic Dumb DDL shows some useful log messages when the autogenerate command is running. To enable logging, add the following to your alembic.ini
:
[loggers]
# add alembic_dddl to the `keys` option:
keys = root,sqlalchemy,alembic,alembic_dddl
# add the `logger_alembic` section:
[logger_alembic]
level = INFO
handlers =
qualname = alembic
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file alembic_dddl-0.1.0.tar.gz
.
File metadata
- Download URL: alembic_dddl-0.1.0.tar.gz
- Upload date:
- Size: 12.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.10.13 Darwin/23.2.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e388eb259ebe8fe9838de03ad3ce03caedc1980b28c6ae2dd83e60bebc865eaf |
|
MD5 | 387083932ffb3e751c3383f9a8cbf705 |
|
BLAKE2b-256 | 9f52cead7c1ea551f6e198a30efb7587e16e4016be8418210bc5b3b37d533ab5 |
File details
Details for the file alembic_dddl-0.1.0-py3-none-any.whl
.
File metadata
- Download URL: alembic_dddl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.10.13 Darwin/23.2.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | d8bf93dd565d98abc28f0edf2c8900cafdb38c2c7dce847c0cf2b3f4cf27aa53 |
|
MD5 | cd522642ad953bc64de37e443e193b22 |
|
BLAKE2b-256 | 76e2b65fa717609f7ebb026c66c2b0e4036e1c97f33170ac0677a73348ce8a7b |