Describe the bug
batch_alter_table(naming_convention=...) reflects the existing table into a
MetaData that carries the convention. Reflected constraints already have names,
but a ck convention containing %(constraint_name)s is re-applied to them, so
the existing name gets prefixed a second time.
Only conventions using the %(constraint_name)s token are affected; uq/fk/pk
conventions don't include it, so reflected names pass through unchanged there.
To Reproduce
from alembic.migration import MigrationContext
from alembic.operations import Operations
from sqlalchemy import CheckConstraint, Column, Integer, MetaData, Table, create_engine
naming = {"ck": "ck_%(table_name)s_%(constraint_name)s"}
m = MetaData(naming_convention=naming)
Table(
"user",
m,
Column("id", Integer, primary_key=True),
Column("age", Integer),
CheckConstraint("age > 0", name="positive_age"),
)
e = create_engine("sqlite://")
m.create_all(e)
with e.begin() as conn:
print("before:", conn.exec_driver_sql(
"select sql from sqlite_master where name='user'").scalar())
op = Operations(MigrationContext.configure(conn))
with op.batch_alter_table(
"user", naming_convention=naming, recreate="always"
) as batch_op:
batch_op.add_column(Column("y", Integer))
print("after: ", conn.exec_driver_sql(
"select sql from sqlite_master where name='user'").scalar())
Expected behavior
The reflected constraint keeps its existing name; the convention should only supply
names for constraints that don't have one.
Actual behavior
before: CREATE TABLE user (
id INTEGER NOT NULL,
age INTEGER,
PRIMARY KEY (id),
CONSTRAINT ck_user_positive_age CHECK (age > 0)
)
after: CREATE TABLE "user" (
id INTEGER NOT NULL,
age INTEGER,
y INTEGER,
PRIMARY KEY (id),
CONSTRAINT ck_user_ck_user_positive_age CHECK (age > 0)
)
The prefix accumulates on every recreate.
Additional context
The renaming happens at reflection time in BatchOperationsImpl.flush(), where the
table is reflected into MetaData(naming_convention=self.naming_convention).
Discovered while investigating #1768; related to #1844.
Versions
- Alembic: 1.19.1 (main)
- SQLAlchemy: 2.1
- Database: SQLite
Describe the bug
batch_alter_table(naming_convention=...)reflects the existing table into aMetaDatathat carries the convention. Reflected constraints already have names,but a
ckconvention containing%(constraint_name)sis re-applied to them, sothe existing name gets prefixed a second time.
Only conventions using the
%(constraint_name)stoken are affected;uq/fk/pkconventions don't include it, so reflected names pass through unchanged there.
To Reproduce
Expected behavior
The reflected constraint keeps its existing name; the convention should only supply
names for constraints that don't have one.
Actual behavior
The prefix accumulates on every recreate.
Additional context
The renaming happens at reflection time in
BatchOperationsImpl.flush(), where thetable is reflected into
MetaData(naming_convention=self.naming_convention).Discovered while investigating #1768; related to #1844.
Versions