Skip to main content

A migration library for SQLAlchemy.

Project description

SQLAltery

A migration library for SQLAlchemy. A cleaner frontend to Alembic.

Guide

Set up management script

SQLAltery provides the "functional core". To use it in your project, you'll need to provide your own "imperative shell", but this is easy. Here's a starter managedb.py:

import sqlalchemy as sa
from sqlaltery import SQLAltery

def cmd_diff() -> None:
	# Show pending changes to schema
	salt = _get_sqlaltery()
	print(salt.diff(model.Base.metadata))

def cmd_commit() -> None:
	# Create a new migration file from pending changes (if any)
	salt = _get_sqlaltery()
	# TODO: print created file; `data: bool` flag
	salt.generate(model.Base.metadata)

def cmd_sync(*, revision: Optional[int] = None) -> None:
	# Migrate your DB to `revision`. If `None`, this means the latest.
	# `revision == 0` is a special revision that means an empty DB.
	salt = _get_sqlaltery()
	engine = _get_engine()
	with salt.connect_to(engine) as migrator:
		migrator.migrate(revision, initial = 0)

def _get_sqlaltery() -> SQLAltery:
	# choose where to store migration files
	from pathlib import Path
	migration_dir = Path(__file__).parent / 'migration'
	return SQLAltery(migration_dir)

def _get_engine() -> sa.Engine:
	# an engine pointing to the DB you want to migrate
	return sa.create_engine(sa.URL.create(...))

def _get_metadata() -> sa.MetaData:
	# return your model metadata
	from my_app import my_model
	return my_model.Base.metadata

if __name__ == '__main__':
	import funcli
	funcli.run({ 'diff': cmd_diff, 'commit': cmd_commit, 'sync': cmd_sync })

Terminology used here

You can name the operations anything, but this guide will use these terms:

  • commit: create a new migration (Django: py manage.py makemigrations)
  • sync: apply migrations (Django: py manage.py migrate)
  • sync --fake: fake migrations (Django: py manage.py migrate --fake); this updates only the migration metadata (table sqlaltery_migration)

Reset migrations

Assuming your database(s) are synced to latest, delete your migration dir, create a new migration, and do a fake sync:

rm -rf migration
py managedb.py commit
py managedb.py sync --fake

Data migrations

Data migrations usually involve a three-step process: expand, project, contract.

  • Expand the schema: T_old to T_exp \superset T_new, where T_exp is such that the underlying database can automatically project the data onto it (e.g., adding only nullable columns)
  • Project the data: apply a function T_exp -> T_new to the data
  • Contract the schema: T_exp to T_new
py managedb.py commit --data

Now, modify the newly created migration to and write code data migration code. Once you're done, sync:

py managedb.py sync

Status

  • MetaData diffing (sqlaltery/compare.py)
  • apply ops to MetaData (sqlaltery/ops.py:apply)
  • apply ops to Connection (sqlaltery/ops.py:apply); all the heavy lifting is passed to Alembic's DDL
  • write migration to a file (sqlaltery/command.py:_save_migration)
  • allow multiple migrations per file (OPS or OPS_{\d+}; OPS is treated as OPS_0; for multiple, they're expected to be sequential from 0)
  • generate(data: bool) that creates a new migration with expand/project/contract phases
  • tests (95%)
  • docs
    • document basic usage and show example script

Why not use Alembic directly?

  • Alembic diffs the head MD against current DB, not against latest migration
  • Alembic has split upgrade/downgrade
  • Alembic requires you to manually manage metadata in migrations (for doing queries)
  • Alembic creates a bunch of files (alembic.ini, env.py). The default case should be simple: just create an SQLAltery and use it; customize by passing arguments.

Internal use

How to publish:

py setup.py bdist_wheel
python -m twine upload dist/<file>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sqlaltery-0.5.0-py3-none-any.whl (13.2 kB view details)

Uploaded Python 3

File details

Details for the file sqlaltery-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: sqlaltery-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 13.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.3

File hashes

Hashes for sqlaltery-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2c2fe298876d82f3bddfbf08d202418f0d146479bf148c040ee749f3d36a2d61
MD5 53da95a051b381628ea74acc94f5c7cc
BLAKE2b-256 b458631788b8cb1c9be43d216af549e1c279cb068fcfc376eb058529950d7d15

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page