Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

postgresql ExcludeConstraint behave differently with --autogenerate compare to sqlalchemy Base.metadata.create_all #1230

Closed
tc-yu opened this issue Apr 28, 2023 · 2 comments
Labels

Comments

@tc-yu
Copy link

tc-yu commented Apr 28, 2023

Describe the bug
when running alembic revision --autogenerate, on a table with

ExcludeConstraint(
    (func.tstzrange(effective_time, expiry_time), "&&"),
    using="gist",
)

it generates

    postgresql.ExcludeConstraint(('tstzrange(effective_time, expiry_time)', '&&'), using='gist'),

in the revision script, resulting in sqlalchemy.exc.ConstraintColumnNotFoundError: Can't create ExcludeConstraint on table 'time_slot': no column named 'tstzrange(effective_time, expiry_time)' is present.

Adding sqlalchemy.text around the string does fix the issue

Expected behavior
the table definition works with sqlalchemy's Base.metadata.create_all(bind=engine), creating

"time_slot_tstzrange_excl" EXCLUDE USING gist (tstzrange(effective_time, expiry_time) WITH &&)

in the database so I expect it works the same in alembic

To Reproduce

I setup a minimal example in this repo: https://github.com/tc-yu/alembic-pgsql-tztsrange

model:

from datetime import datetime

from sqlalchemy import DateTime, Identity, func
from sqlalchemy.dialects.postgresql import ExcludeConstraint
from sqlalchemy.orm import Mapped, declarative_base, mapped_column

class TimeSlot(Base):
    __tablename__ = "time_slot"

    id: Mapped[int] = mapped_column(Identity(), primary_key=True)

    effective_time: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), index=True
    )
    expiry_time: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), index=True
    )

    __table_args__ = (
        ExcludeConstraint(
            (func.tstzrange(effective_time, expiry_time), "&&"),
            using="gist",
        ),
    )

Error

sqlalchemy.exc.ConstraintColumnNotFoundError: Can't create ExcludeConstraint on table 'time_slot': no column named 'tstzrange(effective_time, expiry_time)' is present.

Versions.

  • OS: macOS
  • Python: 3.11.3
  • Alembic: 1.10.4
  • SQLAlchemy: 2.0.11
  • Database: postgresql 15.2
  • DBAPI: psycopg 3.1.8

Additional context
This is the first time I work with ExcludeConstraint, so it might just be me using the wrong way to define it in the model

Have a nice day!

@tc-yu tc-yu added the requires triage New issue that requires categorization label Apr 28, 2023
@CaselIT
Copy link
Member

CaselIT commented Apr 28, 2023

Hi,

Thanks for reporting.

@CaselIT CaselIT added bug Something isn't working autogenerate - rendering postgresql and removed requires triage New issue that requires categorization labels Apr 28, 2023
@sqla-tester
Copy link
Collaborator

Federico Caselli has proposed a fix for this issue in the main branch:

Fix ExcludeConstraint with func. https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/4591

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants