Skip to content

render table .info in create table, also fix typing for rewriter #1329

@zzzeek

Description

@zzzeek

Discussed in #1328

Originally posted by BayerSe October 19, 2023
Hi,

our Oracle db requires partitions for some of the tables, which we used to add using alembic with the following steps. These are based on the proposal of @zzzeek here (for nicer formatting see here).

It's been a long time since I needed a change in the schema, so I only now realized that there seems to have been a regression / change in behavior.

Main code:

from sqlalchemy import MetaData, Column, String
from sqlalchemy.ext.declarative import declarative_base

metadata = MetaData()
Base = declarative_base(metadata=metadata)


class Table(Base):
    __tablename__ = 'Table'
    name = Column(String(10), primary_key=True)
    __table_args__ = {'info': {'oracle_partition': "PARTITION BY ..."}}

This rewriter is added as process_revision_directives of context.configure in env.py with the goal of adding the info dict to the create_table statement:

writer = rewriter.Rewriter()

@writer.rewrites(ops.CreateTableOp)
def add_info_to_table(context, revision, op):
    op.kw["info"] = op.columns[0].table.info
    return ops.CreateTableOp(
            table_name=op.table_name,
            columns=op.columns,
            schema=op.schema,
            _namespace_metadata=op._namespace_metadata,
            _constraints_included=op._constraints_included,
            **op.kw,
        )

We add this to the migration scripts, which adds the partition command to the created statement:

import sqlalchemy as sa
from alembic import op
import textwrap

@sa.ext.compiler.compiles(sa.schema.CreateTable, "oracle")
def _add_suffixes(element, compiler, **kw):  # type: ignore
    text = compiler.visit_create_table(element, **kw)
    if "oracle_partition" in element.element.info:
        text += textwrap.dedent(element.element.info["oracle_partition"]).strip()
    return text

For alembic==1.6.5 and sqlalchemy==1.3.24 this result in the following auto-generated update command:

op.create_table(
    "Table",
    sa.Column("name", sa.String(length=10), nullable=False),
    sa.PrimaryKeyConstraint("name"),
    info={"oracle_partition": "PARTITION BY ..."},
)

However, for alembic==1.12.0 and sqlalchemy==2.0.22, the info is not added anymore, i.e. I just get

op.create_table(
    "Table",
    sa.Column("name", sa.String(length=10), nullable=False),
    sa.PrimaryKeyConstraint("name"),
)

I checked version alembic==1.7.0 as well, it broke between 1.6.5 and 1.7.0. In the changelog I found this comment, could that be related?

Thanks and regards
Sebastian

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions