sqlalchemy / alembic

A database migrations tool for SQLAlchemy.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Naming conventions in metadata sequences are ignored

iurisilvio opened this issue · comments

Describe the bug

Metadata sequences were implemented in #38, only for auto generation, in 7d5f6ea.

The SchemaObjects.metadata() is older than the sequences implementation and don't check if it is a list. https://github.com/sqlalchemy/alembic/blob/main/alembic/operations/schemaobj.py#L193-L202

Expected behavior

Naming conventions should be respected with metadata sequences.

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.

from sqlalchemy import MetaData
from alembic.config import Config
from alembic.operations.schemaobj import SchemaObjects
from alembic.runtime.environment import EnvironmentContext
from alembic.script import ScriptDirectory

convention = {
    "ix": "foo_ix_%(table_name)s_%(column_0_name)s",
}

context = EnvironmentContext(Config(), ScriptDirectory("."))
context.configure(
    dialect_name="postgresql",
    target_metadata=[
        MetaData(naming_convention=convention),
        MetaData(),
    ],
)
# This is unexpectedly the default naming convention `immutabledict({'ix': 'ix_%(column_0_label)s'})`
print(SchemaObjects(context.get_context()).metadata().naming_convention)

context = EnvironmentContext(Config(), ScriptDirectory("."))
context.configure(
    dialect_name="postgresql",
    target_metadata=MetaData(naming_convention=convention),
)
# It works as expected
print(SchemaObjects(context.get_context()).metadata().naming_convention)

Error

There is no error, but it doesn't use my conventions.

Versions.

  • OS:
  • Python:
  • Alembic:
  • SQLAlchemy:
  • Database:
  • DBAPI:

Additional context

Have a nice day!

this is a little bit of a minor disaster and I think we might have to get away with doing something simple but not 100% of the cases, which is, "choose the naming convention from the first MetaData".

Expected behavior
Naming conventions should be respected with metadata sequences.

So this...is not really generalizable. what if you had a list with two MetaData objects where both have naming conventions, that are different? what is expected then?

the docs at https://alembic.sqlalchemy.org/en/latest/naming.html#integration-of-naming-conventions-into-operations-autogenerate definitely have to change to accommodate this. we might want to consider warnings if multiple metadatas are present and differing naming conventions are located.

For tests here we have to ensure autogenerate rendering takes this into account as we see in test_autogen_render->RenderNamingConventionTest, tested with two metadata objects with all combinations of naming conventions / ordering /present or not - the render should always be using the naming convention that applies to the object being rendered, which I think should be the case already right now.

then for the list issue here we would have to set up more tests in test_op_naming_convention.py

@CaselIT any ideas here

since it's something new I think it would make sense to either use the naming convention of the fist metadata or raise if the metadata have different non-empty naming conventions

I probably just don't understand the idea, but isn't it possible to match the table name with the metadata.tables? The AutogenContext has something like this.

I probably just don't understand the idea, but isn't it possible to match the table name with the metadata.tables? The AutogenContext has something like this.

that's interesting, I guess every op directive we have technically has a way to locate a table name which could then be searched in all the MetaData objects. If two of those MetaData objects have the same effective schema/table name, we'd assume we can just use the first one.

Would be a pretty big change all throughout how the op directive "impls" function since that context would need to be passed all the way through.