diff options
| -rw-r--r-- | doc/build/changelog/unreleased_13/5183.rst | 7 | ||||
| -rw-r--r-- | lib/sqlalchemy/sql/sqltypes.py | 19 | ||||
| -rw-r--r-- | test/sql/test_types.py | 29 |
3 files changed, 54 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_13/5183.rst b/doc/build/changelog/unreleased_13/5183.rst new file mode 100644 index 000000000..21265e0b2 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5183.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: types, enum + :tickets: 5183 + + The :class:`.Enum` type now supports the parameter :paramref:`.Enum.length` + to specify the length of the VARCHAR column to create when using + non native enums by setting :paramref:`.Enum.native_enum` to ``False`` diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index e106684bc..05d6ec36b 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -1303,7 +1303,14 @@ class Enum(Emulated, String, SchemaType): :param native_enum: Use the database's native ENUM type when available. Defaults to True. When False, uses VARCHAR + check - constraint for all backends. + constraint for all backends. The VARCHAR length can be controlled + with :paramref:`.Enum.length` + + :param length: Allows specifying a custom length for the VARCHAR + when :paramref:`.Enum.native_enum` is False. By default it uses the + length of the longest value. + + .. versionadded:: 1.3.16 :param schema: Schema name of this type. For types that exist on the target database as an independent schema construct (PostgreSQL), @@ -1375,6 +1382,7 @@ class Enum(Emulated, String, SchemaType): self.create_constraint = kw.pop("create_constraint", True) self.values_callable = kw.pop("values_callable", None) self._sort_key_function = kw.pop("sort_key_function", NO_ARG) + length_arg = kw.pop("length", NO_ARG) values, objects = self._parse_into_values(enums, kw) self._setup_for_values(values, objects, kw) @@ -1398,6 +1406,15 @@ class Enum(Emulated, String, SchemaType): length = max(len(x) for x in self.enums) else: length = 0 + if not self.native_enum and length_arg is not NO_ARG: + if length_arg < length: + raise ValueError( + "When provided, length must be larger or equal" + " than the length of the longest enum value. %s < %s" + % (length_arg, length) + ) + length = length_arg + self._valid_lookup[None] = self._object_lookup[None] = None super(Enum, self).__init__( diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 2af8cb325..0590bb5e3 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -1876,6 +1876,35 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest): "inherit_schema=True, native_enum=False)", ) + def test_length_native(self): + e = Enum("x", "y", "long", length=42) + + eq_(e.length, len("long")) + + # no error is raised + e = Enum("x", "y", "long", length=1) + eq_(e.length, len("long")) + + def test_length_raises(self): + assert_raises_message( + ValueError, + "When provided, length must be larger or equal.*", + Enum, + "x", + "y", + "long", + native_enum=False, + length=1, + ) + + def test_no_length_non_native(self): + e = Enum("x", "y", "long", native_enum=False) + eq_(e.length, len("long")) + + def test_length_non_native(self): + e = Enum("x", "y", "long", native_enum=False, length=42) + eq_(e.length, 42) + binary_table = MyPickleType = metadata = None |
