autogenerate: alembic keeps creating tables that return False on `include_name`
puilp0502 opened this issue · comments
Describe the bug
alembic revision --autogenerate
always creates create_table
op regardless of the table's existence, if the include_name
function returns False
for that table.
Expected behavior
alembic revision --autogenerate
should not generate create_table
op for tables which return False on include_name
To Reproduce
Please try to provide a Minimal, Complete, and Verifiable example, with the migration script and/or the SQLAlchemy tables or models involved.
See also Reporting Bugs on the website.
The code for reproduction is available here.
The repo has the following setup:
- Basic postgresql container via
docker-compose.yml
- Alembic configuration, with custom
include_name
function - Sample model definition
The model.py
contains two models, namely Unmanaged
and User
.
We tell alembic not to track Unmanged
table via include_name
here.
However, when we run alembic revision --autogenerate
to generate the migrations, it creates a create_table
op for unmanaged
table:
...
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('app_user',
sa.Column('username', sa.String(length=32), nullable=False),
sa.Column('password', sa.String(length=512), nullable=False),
sa.PrimaryKeyConstraint('username')
)
op.create_table('unmanaged',
sa.Column('key', sa.String(length=64), nullable=False),
sa.Column('value', sa.String(length=1024), nullable=False),
sa.PrimaryKeyConstraint('key')
)
# ### end Alembic commands ###
...
Additionally, if we re-run alembic revision --autogenerate
(after applying migrations via alembic upgrade head
), it tries to re-create the unmanaged
table:
...
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('unmanaged',
sa.Column('key', sa.String(length=64), nullable=False),
sa.Column('value', sa.String(length=1024), nullable=False),
sa.PrimaryKeyConstraint('key')
)
# ### end Alembic commands ###
...
Versions
- OS: macOS 14.2.1
- Python: Python 3.10, Python 3.12
- Alembic:
alembic 1.13.1
- SQLAlchemy: 2.0.23
- Database:
PostgreSQL 15.4 (Debian 15.4-2.pgdg120+1)
- DBAPI: psycopg2 2.9.9
Additional context
I believe the root cause is that autogen_context.run_name_filters
is not called for tables present in the AutogenContext object here, even though we're filtering the table list retrieved via inspector
, thus leaving unmanaged tables in a perpetual no-yet-created status.
If my diagnosis is correct, then the fix also seems trivial. I can provide a PR if you want.
Have a nice day!
the include_name hook only applies to reflected tables, not model metadata tables.
to omit model tables from autogenerate the best approach is to use a separate MetaData
collection for "unmanaged" tables. Otherwise the include_object hook applies to model and reflected objects equally.