Skip to content

Ensuring predictable column order in migration #827

Description

@shamiradjaku

Describe your question
I am using Alembic with SqlAlchemy to autogenerate migrations. The column order in the migration file doesn't always match the order in the SqlAlchemy class. Is there a way to ensure this?

**Example **
I started with a class like this.

class SampleData(PublicSchemaBase):
    __tablename__ = "sample_data"

    user_id = Column(Integer, primary_key=True)
    name = Column(String(765))
    age = Column(Integer)
    country = Column(String(765))

Alembic generated an upgrade script like

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "sample_data",
        sa.Column("user_id", sa.Integer(), nullable=False),
        sa.Column("name", sa.String(length=765), nullable=True),
        sa.Column("age", sa.Integer(), nullable=True),
        sa.Column("country", sa.String(length=765), nullable=True),
        sa.PrimaryKeyConstraint("user_id"),
        schema="public",
    )
    # ### end Alembic commands ###

Here the column order in the migration matches the class.

I then added some more columns to the class to look like below

class SampleData(PublicSchemaBase):
    __tablename__ = "sample_data"

    user_id = Column(Integer, primary_key=True)
    name = Column(String(765))
    age = Column(Integer)
    country = Column(String(765))
    column_1 = Column(Integer)
    column_4 = Column(Integer)
    column_17 = Column(Integer)
    column_11 = Column(BigInteger)
    column_10 = Column(Integer)
    column_21 = Column(Integer)
    column_91 = Column(Integer)
    column_100 = Column(BigInteger)
    column_111 = Column(Integer)

The generated upgrade script looks like

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column("sample_data", sa.Column("column_1", sa.Integer(), nullable=True))
    op.add_column("sample_data", sa.Column("column_10", sa.Integer(), nullable=True))
    op.add_column("sample_data", sa.Column("column_100", sa.BigInteger(), nullable=True))
    op.add_column("sample_data", sa.Column("column_11", sa.BigInteger(), nullable=True))
    op.add_column("sample_data", sa.Column("column_111", sa.Integer(), nullable=True))
    op.add_column("sample_data", sa.Column("column_17", sa.Integer(), nullable=True))
    op.add_column("sample_data", sa.Column("column_21", sa.Integer(), nullable=True))
    op.add_column("sample_data", sa.Column("column_4", sa.Integer(), nullable=True))
    op.add_column("sample_data", sa.Column("column_91", sa.Integer(), nullable=True))
    # ### end Alembic commands ###

Here the new column's order doesn't match the class at all but is sorted alphabetically.

Is there a way to ensure that the columns will always be in order as they are in the class?

Additional context
Working with

  • SQLAlchemy = 1.3.18
  • alembic = 1.4.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    autogenerate - renderinguse casenot quite a feature and not quite a bug, something we just didn't think of

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions