Skip to content

Postgresql ENUM lookup by string change in 2.0 #9621

@al-dpopowich

Description

@al-dpopowich

Describe the bug

In 1.4.x, selecting records by comparing ENUM column with a string worked.

In 2.0, I get a ProgrammingError exception stating there's no operator for enum == character varying.

I do not see any documentation stating this change from 1.4 to 2.0.

Optional link from https://docs.sqlalchemy.org which documents the behavior that is expected

No response

SQLAlchemy Version in Use

2.0.9

DBAPI (i.e. the database driver)

asyncpg==0.27.0

Database Vendor and Major Version

PostgreSQL 14.2

Python Version

3.11

Operating system

Linux

To Reproduce

# stdlib imports
import asyncio
import enum

# venv imports
from sqlalchemy import (
   Column,
   exc,
   insert,
   Integer,
   MetaData,
   select,
   Table,
   text,
   __version__ as sqla_version,
)
from sqlalchemy.dialects.postgresql import (
   ENUM
)
from sqlalchemy.ext.asyncio import create_async_engine

# assert the version for this test
assert sqla_version == '2.0.9'

meta = MetaData()

class AppGroup(enum.Enum):
   """Application groups"""
   ADMIN = 'admin'
   STAFF = 'staff'
   CUST = 'customer'


Group = Table(
   'mygroup',
   meta,
   Column('id', Integer, primary_key=True),
   Column('name', ENUM(AppGroup, name=AppGroup.__name__.lower()),
          nullable=False,
          unique=True),
)

DBURI = 'postgresql+asyncpg://tcp:pass4TCP!@postgres/foo'

async def main():
   engine = create_async_engine(DBURI, future=True, echo=True)

   async with engine.begin() as conn:
      await conn.run_sync(meta.create_all)

      await conn.execute(insert(Group).values([dict(name=grp) for grp in AppGroup]))

      # using the enum works with both 1.4 and 2.0
      stmt = select(Group).where(Group.c.name==AppGroup.ADMIN)
      result = await conn.execute(stmt)
      print('>>>>>>>>>>>>>> Found group ADMIN:', result.fetchall())

      # strings of course work in raw SQL
      stmt = text("select id, name from mygroup where name = 'ADMIN'")
      result = await conn.execute(stmt)
      print('>>>>>>>>>>>>>> Found group ADMIN:', result.fetchall())

      # searching by string works in 1.4, but raises a
      # ProgrammingError in 2.0, "operator does not exist: appgroup = character varying"
      try:
         stmt = select(Group).where(Group.c.name=='ADMIN')
         result = await conn.execute(stmt)
         print('>>>>>>>>>>>>>> Found group ADMIN:', result.fetchall())
      except exc.ProgrammingError as error:
         print('!!!!!!!!!!!!!!!!!!!!', error)


      await conn.rollback()

asyncio.run(main())

Error

(sqlalchemy.dialects.postgresql.asyncpg.ProgrammingError) <class 'asyncpg.exceptions.UndefinedFunctionError'>: operator does not exist: appgroup = character varying
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
[SQL: SELECT mygroup.id, mygroup.name 
FROM mygroup 
WHERE mygroup.name = $1::VARCHAR]
[parameters: ('ADMIN',)]

Additional context

In my tests I used asyncpg==0.27.0 for both 1.4.40 and 2.0.9, so asyncpg can be ruled out as the change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdatatypesthings to do with database types, like VARCHAR and otherspostgresqlregressionsomething worked and was broken by a change

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions