]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add length parameter in `Enum`
authorFederico Caselli <cfederico87@gmail.com>
Tue, 24 Mar 2020 20:06:04 +0000 (21:06 +0100)
committerFederico Caselli <cfederico87@gmail.com>
Mon, 6 Apr 2020 18:03:22 +0000 (20:03 +0200)
The `Enum` type now supports the parameter `Enum.length`
to specify the length of the VARCHAR column to create when using
non native enums by setting `Enum.native_enum` to `False`

Fixes: #5183
Change-Id: Iea05dc8cd9e33959bb968b394fb10a7dd068c873
(cherry picked from commit 3e2af98adfdcbf33ff5d8c2da15962c001344d64)

doc/build/changelog/unreleased_13/5183.rst [new file with mode: 0644]
lib/sqlalchemy/sql/sqltypes.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_13/5183.rst b/doc/build/changelog/unreleased_13/5183.rst
new file mode 100644 (file)
index 0000000..21265e0
--- /dev/null
@@ -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``
index ab05baebeaa38c421c303610a956e78c960bc992..2d800f77544eadc191bf991a630a40d4fa040e73 100644 (file)
@@ -1319,7 +1319,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),
@@ -1391,6 +1398,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)
@@ -1414,6 +1422,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__(
index 8e2a4372a0958725e91288e9a9d59923050a25ee..5be780beb3d7a05c02f6b726d1c5983c3b4d1a61 100644 (file)
@@ -1873,6 +1873,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