comdab — Compare Database Schemas
comdab allows you to compare in depth two database schemas to find all differences: missing columns, different nullabilities or defaults, slight changes in function or triggers definitions...
[!WARNING]
comdab is still in development, only tested with PostgreSQL 14 — 18 to date.
All feedback and contributions are welcome!
Installation
Use pip to install comdab:
pip install comdab
Requirements
- Python
>= 3.13 - sqlalchemy
>= 2.0 - pydantic
>= 2.0
Goals
comdab allows you to compare in depth two database schemas to find all differences (missing columns, different nullabilities or defaults, slight changes in function or triggers definitions...) and turn these reports into model migrations.
comdab migration generation supercharges migration tools like Alembic to create migrations that, when applied to an existing database, produce the exact same schema than a new database created from scratch.
Indeed, while migration tools can auto-detect model changes and write automatically the migrations to apply to pre-existing databases, it does not cover the whole schema complexity, and does not prevent human errors (like modifying the model without re-generating migrations, or manually editing migrations in a slightly wrong way...)
This may cause dangerous and hard to spot bugs, especially if your unit tests and CI run on a fresh database created from the Python-written model, and not on pre-existing databases with the new migration applied.
By running comdab, you can ensure the two are the nearly-exact same.
comdab is based on the wonderful SQLAlchemy library to connect to the database, and for most of schema introspection.
Usage
Comparing database schemas
comdab main reporting function is
.compare_databases,
which needs already established SQLAlchemy connections to the two databases to compare:
from comdab import compare_databases
from sqlalchemy import create_engine
engine_1 = create_engine("postgresql://user:pass@host/foo")
engine_2 = create_engine("postgresql://user:pass@host/bar")
with engine_1.connect() as left_conn, engine_2.connect() as right_conn:
reports = compare_databases(left_conn, right_conn)
if reports:
print("❌ Database schemas are different:", reports)
else:
print("✅ Database schemas are the same!")
Generating migrations
To generate migrations, a user-defined
MigrationGeneratorPort /
PartialMigrationGeneratorPort
subclass is additionally needed:
from comdab import generate_migrations, PartialMigrationGeneratorPort
from comdab.models import ComdabTable
from sqlalchemy import create_engine
class MyMigrationGenerator(PartialMigrationGeneratorPort):
def __init__(self) -> None:
self.sql_text = ""
def create_table(self, *, table: ComdabTable) -> None:
self.sql_text += f"CREATE TABLE {table.name} [...];\n"
def drop_table(self, *, table: ComdabTable) -> None:
self.sql_text += f"DROP TABLE {table.name};\n"
...
generator = MyMigrationGenerator()
engine_1 = create_engine("postgresql://user:pass@host/source")
engine_2 = create_engine("postgresql://user:pass@host/target")
with engine_1.connect() as source_conn, engine_2.connect() as target_conn:
generate_migrations(source_conn, target_conn, generator)
print(generator.sql_text)
Advanced usage
See documentation for configuration and other details.
Contributing
Issues and pull requests are welcome!
License
This work is shared under the MIT license.
@ 2025 Loïc Simon (loic.simon@espci.org)
Metadata
Release files for comdab 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| comdab-0.4.1.tar.gz | 76.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| comdab-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 109.3 kB
Release files / comdab-0.4.1.tar.gz
| Download URL | comdab-0.4.1.tar.gz |
|---|---|
| Size | 76.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f8872df1f29ab199c5a0a99f2d107316a78c0b81470e85855704c62c1ba04285
|
|
BLAKE2b-256 checksum How to use checksums |
7480b81b209d8cd062491d46bf0b3cdc16ffdbd51ec8a79f1b7b2a73c42ba07f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 21, 2026.
Transparency logRelease files / comdab-0.4.1-py3-none-any.whl
| Download URL | comdab-0.4.1-py3-none-any.whl |
|---|---|
| Size | 32.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6e14b2482f6c23e4b86e258824c9adafa3331afaca4242b8ca15606f010d6b49
|
|
BLAKE2b-256 checksum How to use checksums |
faa7b7934d93b0df3a668c3cd6a651eea68fad24543b0efbf575091ff4280c6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 21, 2026.
Transparency log