Skip to content

SQLAlchemy Enum type breaks #844

@sebastian-correa

Description

@sebastian-correa

I'm trying to use sqlmodel to handle a BigQuery dataset. The model I'm using has an Enum field, declared from a Python Enum. Table creation fails.

Environment details

  • MacOS 12.6.3 on an Intel Macbook Pro 13.
  • Python 3.10.8.
  • pip 22.3 (using poetry 1.2.2).
  • sqlalchemy-bigquery version:
      Name: sqlalchemy-bigquery
      Version: 1.6.1
      Summary: SQLAlchemy dialect for BigQuery
      Home-page: https://github.com/googleapis/python-bigquery-sqlalchemy
      Author: The Sqlalchemy-Bigquery Authors
      Author-email: googleapis-packages@google.com
      License: 
      Location: /Users/me/Dev/myproj/.venv/lib/python3.10/site-packages
      Requires: future, google-api-core, google-auth, google-cloud-bigquery, google-cloud-bigquery-storage, packaging, pyarrow, 
      sqlalchemy
      Required-by:
    

Steps to reproduce

  1. Have a SQLAlchemy model with an Enum column declared from a python Enum.
  2. Run create_all or try to add and commit to a hand-made table in BigQuery (the code Enum column mapped to a column with the same name, of type string with length = max Enum member length).

Code example

from enum import Enum

from sqlmodel import Column
from sqlmodel import Enum as DbEnum
from sqlmodel import Field, SQLModel, create_engine


class ValidMembers(str, Enum):
    member_1 = "member 1"
    member_2 = "member 2"
    member_3 = "member 3"


class TestTable(SQLModel, table=True):
    __tablename__ = "test_table"

    id: int | None = Field(default=None, primary_key=True)
    member: ValidMembers = Field(
        sa_column=Column(
            DbEnum(ValidMembers),
            nullable=False,
        )
    )


ENGINE = create_engine(url="bigquery://<project_id>/<default_dataset>", credentials_path="path/to/credentials-sa.json")


def create_db_and_tables():
    SQLModel.metadata.create_all(ENGINE)


if __name__ == "__main__":
    create_db_and_tables()

Stack trace

Traceback (most recent call last):
  File "/Users/me/Dev/myproj/test.py", line 34, in <module>
    create_db_and_tables()
  File "/Users/me/Dev/myproj/test.py", line 30, in create_db_and_tables
    SQLModel.metadata.create_all(ENGINE)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/schema.py", line 4917, in create_all
    bind._run_ddl_visitor(
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/future/engine.py", line 342, in _run_ddl_visitor
    conn._run_ddl_visitor(visitorcallable, element, **kwargs)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2211, in _run_ddl_visitor
    visitorcallable(self.dialect, self, **kwargs).traverse_single(element)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/visitors.py", line 524, in traverse_single
    return meth(obj, **kw)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/ddl.py", line 838, in visit_metadata
    metadata.dispatch.before_create(
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/event/attr.py", line 334, in __call__
    fn(*args, **kw)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 875, in __call__
    return getattr(self.target, self.name)(*arg, **kw)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/sqltypes.py", line 1203, in _on_metadata_create
    t = self.dialect_impl(bind.dialect)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/type_api.py", line 649, in dialect_impl
    return self._dialect_info(dialect)["impl"]
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/type_api.py", line 726, in _dialect_info
    impl = self._gen_dialect_impl(dialect)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/type_api.py", line 735, in _gen_dialect_impl
    return dialect.type_descriptor(self)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 578, in type_descriptor
    return sqltypes.adapt_type(typeobj, self.colspecs)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/type_api.py", line 1974, in adapt_type
    return typeobj.adapt(impltype)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/sqltypes.py", line 1711, in adapt
    return super(Enum, self).adapt(impltype, **kw)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/type_api.py", line 1134, in adapt
    return super(Emulated, self).adapt(impltype, **kw)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/sql/type_api.py", line 759, in adapt
    return util.constructor_copy(self, cls, **kw)
  File "/Users/me/Dev/myproj/.venv/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 1325, in constructor_copy
    return cls(*args, **kw)
TypeError: String.__init__() got an unexpected keyword argument '_enums'

Metadata

Metadata

Assignees

No one assigned

    Labels

    api: bigqueryIssues related to the googleapis/python-bigquery-sqlalchemy API.priority: p3Desirable enhancement or fix. May not be included in next release.status: will not fixInvalid (untrue/unsound/erroneous), inconsistent with product, not on roadmap.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions