# Alembic Dumb DDL
[![](https://img.shields.io/pypi/v/alembic-dddl.svg)](https://pypi.org/project/alembic-dddl/) [![](https://img.shields.io/github/v/tag/Vanderhoof/alembic-dddl.svg?label=GitHub)](https://github.com/Vanderhoof/alembic-dddl) ![tests](https://github.com/Vanderhoof/alembic-dddl/actions/workflows/tests.yml/badge.svg) [![codecov](https://codecov.io/gh/Vanderhoof/alembic-dddl/graph/badge.svg?token=BQJBA9PXPN)](https://codecov.io/gh/Vanderhoof/alembic-dddl)
A plugin for [Alembic](https://alembic.sqlalchemy.org/en/latest/) DB migration tool that adds support for arbitrary user-defined objects like views, functions, triggers, etc. in autogenerate command.
Alembic DDDL _does not_ compare the objects in the code with their state in the database. Instead, it **only tracks if the source code of the script has changed**, compared to the previous revision.
## Installation
You can install Alembic Dumb DDL from pip:
```shell
pip install alembic-dddl
```
## Quick start
Step 1: save your DDL script in a file, and make sure that it overwrites the entities, not just creates them (e.g. start with `DROP ... IF EXISTS` or a similar construct for your DBMS).
```sql
-- 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:
```python
# 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 the 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 script in alembic's `env.py`:
```python
# migrations/env.py
from myapp.models import my_ddl
from alembic_dddl import register_ddl
register_ddl(my_ddl) # also supports a list
# ...
# the rest of the env.py file
```
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.
Run the migration:
```shell
$ alembic revision --autogenerate -m "last_month_orders"
...
INFO [alembic_dddl.dddl] Detected new DDL "last_month_orders"
Generating myapp/migrations/versions/2024_01_08_0955-0c897e9399a9_last_month_orders.py ... done
```
The generated revision script:
```python
# migrations/versions/2024_01_08_0955-0c897e9399a9_last_month_orders.py
...
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.run_ddl_script("2024_01_08_0955_last_month_orders_0c897e9399a9.sql")
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.execute("DROP VIEW IF EXISTS last_month_orders;")
# ### end Alembic commands ###
```
For more info see [tutorial](docs/tutorial.md) or take a look at the [Example Project](https://github.com/Vanderhoof/alembic-dddl/tree/master/example/).
## Why do it this way?
Managing your custom entities with Alembic DDDL has several benefits:
1. The DDL scripts are defined in one place in the source code, any change to them is reflected in git history through direct diffs.
2. Any kind of SQL script and any DBMS is supported because the plugin does not interact with the database.
3. The migrations for your DDL scripts are fully autogenerated, they are also clean and concise.
# Further reading
* [Tutorial](docs/tutorial.md)
* [How it Works](docs/how_it_works.md)
* [Configuration](docs/configuration.md)
* [Setting up Logging](docs/logging.md)
Raw data
{
"_id": null,
"home_page": "https://github.com/Vanderhoof/alembic-dddl",
"name": "alembic-dddl",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8.1,<4.0.0",
"maintainer_email": "",
"keywords": "alembic,sqlalchemy,autogenerate,DDL,alembic-extension,migration",
"author": "Daniil Minukhin",
"author_email": "ddddsa@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/54/52/3e66d0688ee06b55154e9f1631e596c85490d1ed8095220d47bbeb10f66e/alembic_dddl-0.1.2.tar.gz",
"platform": null,
"description": "# Alembic Dumb DDL\n\n[![](https://img.shields.io/pypi/v/alembic-dddl.svg)](https://pypi.org/project/alembic-dddl/) [![](https://img.shields.io/github/v/tag/Vanderhoof/alembic-dddl.svg?label=GitHub)](https://github.com/Vanderhoof/alembic-dddl) ![tests](https://github.com/Vanderhoof/alembic-dddl/actions/workflows/tests.yml/badge.svg) [![codecov](https://codecov.io/gh/Vanderhoof/alembic-dddl/graph/badge.svg?token=BQJBA9PXPN)](https://codecov.io/gh/Vanderhoof/alembic-dddl)\n\nA plugin for [Alembic](https://alembic.sqlalchemy.org/en/latest/) DB migration tool that adds support for arbitrary user-defined objects like views, functions, triggers, etc. in autogenerate command.\n\nAlembic DDDL _does not_ compare the objects in the code with their state in the database. Instead, it **only tracks if the source code of the script has changed**, compared to the previous revision.\n\n## Installation\n\nYou can install Alembic Dumb DDL from pip:\n\n```shell\npip install alembic-dddl\n```\n\n## Quick start\n\nStep 1: save your DDL script in a file, and make sure that it overwrites the entities, not just creates them (e.g. start with `DROP ... IF EXISTS` or a similar construct for your DBMS).\n\n```sql\n-- myapp/scripts/last_month_orders.sql\n\nDROP VIEW IF EXISTS last_month_orders;\n\nCREATE VIEW last_month_orders AS\n SELECT *\n FROM orders\n WHERE order_date > current_date - interval '30 days';\n```\n\nStep 2: Wrap your script in a `DDL` class:\n\n```python\n# myapp/models.py\n\nfrom alembic_dddl import DDL\nfrom pathlib import Path\n\nSCRIPTS = Path(__file__).parent / \"scripts\"\n\n\ndef load_sql(filename: str) -> str:\n \"\"\"Helper function to load the contents of a file from a `scripts` directory\"\"\"\n return (SCRIPTS / filename).read_text()\n\n\nmy_ddl = DDL(\n # will be used in revision filename\n name=\"last_month_orders\",\n # DDL script SQL code, will be used in the upgrade command\n sql=load_sql(\"last_month_orders.sql\"),\n # Cleanup SQL code, will be used in the first downgrade command\n down_sql=\"DROP VIEW IF EXISTS last_month_orders;\",\n)\n```\n\nStep 3: Register your script in alembic's `env.py`:\n\n```python\n# migrations/env.py\n\nfrom myapp.models import my_ddl\nfrom alembic_dddl import register_ddl\n\nregister_ddl(my_ddl) # also supports a list\n\n# ...\n# the rest of the env.py file\n```\n\nFrom now on the alembic autogenerate command will keep track of `last_month_orders.sql`, and if it changes \u2014 automatically add update code to your migration scripts to update your entities.\n\nRun the migration:\n\n```shell\n$ alembic revision --autogenerate -m \"last_month_orders\"\n...\nINFO [alembic_dddl.dddl] Detected new DDL \"last_month_orders\"\n Generating myapp/migrations/versions/2024_01_08_0955-0c897e9399a9_last_month_orders.py ... done\n```\n\nThe generated revision script:\n\n```python\n# migrations/versions/2024_01_08_0955-0c897e9399a9_last_month_orders.py\n...\n\ndef upgrade() -> None:\n # ### commands auto generated by Alembic - please adjust! ###\n op.run_ddl_script(\"2024_01_08_0955_last_month_orders_0c897e9399a9.sql\")\n # ### end Alembic commands ###\n\n\ndef downgrade() -> None:\n # ### commands auto generated by Alembic - please adjust! ###\n op.execute(\"DROP VIEW IF EXISTS last_month_orders;\")\n # ### end Alembic commands ###\n\n```\n\nFor more info see [tutorial](docs/tutorial.md) or take a look at the [Example Project](https://github.com/Vanderhoof/alembic-dddl/tree/master/example/).\n\n## Why do it this way?\n\nManaging your custom entities with Alembic DDDL has several benefits:\n\n1. The DDL scripts are defined in one place in the source code, any change to them is reflected in git history through direct diffs.\n2. Any kind of SQL script and any DBMS is supported because the plugin does not interact with the database.\n3. The migrations for your DDL scripts are fully autogenerated, they are also clean and concise.\n\n# Further reading\n\n* [Tutorial](docs/tutorial.md)\n* [How it Works](docs/how_it_works.md)\n* [Configuration](docs/configuration.md)\n* [Setting up Logging](docs/logging.md)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Alembic extension that adds support for arbitrary user-defined objects like views or functions in autogenerate command.",
"version": "0.1.2",
"project_urls": {
"Homepage": "https://github.com/Vanderhoof/alembic-dddl",
"Repository": "https://github.com/Vanderhoof/alembic-dddl"
},
"split_keywords": [
"alembic",
"sqlalchemy",
"autogenerate",
"ddl",
"alembic-extension",
"migration"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "00d658bb3c87c39cf80f12f969c5b207a7969b20af026bf7ae942811d8c8d21b",
"md5": "93c667a19f55ea7e5d8c33989e988bb8",
"sha256": "8fcc72fc8f5c35057a7738d22bd2d52a60ad8405b0b43c910d62c89bc26b4f5c"
},
"downloads": -1,
"filename": "alembic_dddl-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "93c667a19f55ea7e5d8c33989e988bb8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8.1,<4.0.0",
"size": 12275,
"upload_time": "2024-01-16T08:16:00",
"upload_time_iso_8601": "2024-01-16T08:16:00.463169Z",
"url": "https://files.pythonhosted.org/packages/00/d6/58bb3c87c39cf80f12f969c5b207a7969b20af026bf7ae942811d8c8d21b/alembic_dddl-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "54523e66d0688ee06b55154e9f1631e596c85490d1ed8095220d47bbeb10f66e",
"md5": "71c9d27f362aab054dde258674bd93db",
"sha256": "23a9cb8029ed0aab1fcc85d08c08c055830d6c722347eb22256351b4f54deb66"
},
"downloads": -1,
"filename": "alembic_dddl-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "71c9d27f362aab054dde258674bd93db",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8.1,<4.0.0",
"size": 10783,
"upload_time": "2024-01-16T08:16:02",
"upload_time_iso_8601": "2024-01-16T08:16:02.303110Z",
"url": "https://files.pythonhosted.org/packages/54/52/3e66d0688ee06b55154e9f1631e596c85490d1ed8095220d47bbeb10f66e/alembic_dddl-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-16 08:16:02",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Vanderhoof",
"github_project": "alembic-dddl",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "alembic-dddl"
}