]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
honor enum length in all cases
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 10 Jun 2022 16:42:54 +0000 (12:42 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 10 Jun 2022 17:21:26 +0000 (13:21 -0400)
The :paramref:`.Enum.length` parameter, which sets the length of the
``VARCHAR`` column for non-native enumeration types, is now used
unconditionally when emitting DDL for the ``VARCHAR`` datatype, including
when the :paramref:`.Enum.native_enum` parameter is set to ``True`` for
target backends that continue to use ``VARCHAR``. Previously the parameter
would be erroneously ignored in this case. The warning previously emitted
for this case is now removed.

Fixes: #7791
Change-Id: I91764546b56e9416479949be8a118cdc91ac5ed9

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

diff --git a/doc/build/changelog/unreleased_20/7791.rst b/doc/build/changelog/unreleased_20/7791.rst
new file mode 100644 (file)
index 0000000..4673a87
--- /dev/null
@@ -0,0 +1,11 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 7791
+
+    The :paramref:`.Enum.length` parameter, which sets the length of the
+    ``VARCHAR`` column for non-native enumeration types, is now used
+    unconditionally when emitting DDL for the ``VARCHAR`` datatype, including
+    when the :paramref:`.Enum.native_enum` parameter is set to ``True`` for
+    target backends that continue to use ``VARCHAR``. Previously the parameter
+    would be erroneously ignored in this case. The warning previously emitted
+    for this case is now removed.
index 50cb325033b37752f7f9045349a05fdc3af46c37..7b18fda7228c537475dd0af217fef966f05ca61a 100644 (file)
@@ -1316,10 +1316,14 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
            ignored if native_enum=True.
 
         :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.
+           when a non-native enumeration datatype is used.  By default it uses
+           the length of the longest value.
+
+           .. versionchanged:: 2.0.0 The :paramref:`.Enum.length` parameter
+              is used unconditionally for ``VARCHAR`` rendering regardless of
+              the :paramref:`.Enum.native_enum` parameter, for those backends
+              where ``VARCHAR`` is used for enumerated datatypes.
 
-           .. 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),
@@ -1419,22 +1423,13 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]):
             self._default_length = length = 0
 
         if length_arg is not NO_ARG:
-            if self.native_enum:
-                if not _disable_warnings:
-                    util.warn(
-                        "Enum 'length' argument is currently ignored unless "
-                        "native_enum is specified as False, including for DDL "
-                        "that renders VARCHAR in any case.  This may change "
-                        "in a future release."
-                    )
-            else:
-                if not _disable_warnings and 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
+            if not _disable_warnings and 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
 
index b2afa2dbabaf3485f4bd388577e70290ae2ed540..ef39157269c9064a81585fa46406561ad1590b78 100644 (file)
@@ -83,7 +83,6 @@ from sqlalchemy.testing import AssertsExecutionResults
 from sqlalchemy.testing import engines
 from sqlalchemy.testing import eq_
 from sqlalchemy.testing import expect_raises
-from sqlalchemy.testing import expect_warnings
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing import is_
 from sqlalchemy.testing import is_not
@@ -2394,18 +2393,26 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         eq_(e1_vc.adapt(ENUM).name, "someotherenum")
         eq_(e1_vc.adapt(ENUM).enums, ["1", "2", "3", "a", "b"])
 
-    def test_adapt_length(self):
+    @testing.combinations(True, False, argnames="native_enum")
+    def test_adapt_length(self, native_enum):
         from sqlalchemy.dialects.postgresql import ENUM
 
-        e1 = Enum("one", "two", "three", length=50, native_enum=False)
-        eq_(e1.adapt(ENUM).length, 50)
+        e1 = Enum("one", "two", "three", length=50, native_enum=native_enum)
+
+        if not native_enum:
+            eq_(e1.adapt(ENUM).length, 50)
+
         eq_(e1.adapt(Enum).length, 50)
 
+        self.assert_compile(e1, "VARCHAR(50)", dialect="default")
+
         e1 = Enum("one", "two", "three")
         eq_(e1.length, 5)
         eq_(e1.adapt(ENUM).length, 5)
         eq_(e1.adapt(Enum).length, 5)
 
+        self.assert_compile(e1, "VARCHAR(5)", dialect="default")
+
     @testing.provide_metadata
     def test_create_metadata_bound_no_crash(self):
         m1 = self.metadata
@@ -2502,32 +2509,20 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         )
 
     def test_repr_four(self):
-        with expect_warnings(
-            "Enum 'length' argument is currently ignored unless native_enum"
-        ):
-            e = Enum("x", "y", length=255)
-        # length is currently ignored if native_enum is not False
+        e = Enum("x", "y", length=255)
         eq_(
             repr(e),
-            "Enum('x', 'y')",
+            "Enum('x', 'y', length=255)",
         )
 
     def test_length_native(self):
-        with expect_warnings(
-            "Enum 'length' argument is currently ignored unless native_enum"
-        ):
-            e = Enum("x", "y", "long", length=42)
-
-        eq_(e.length, len("long"))
+        e = Enum("x", "y", "long", length=42)
+        eq_(e.length, 42)
 
-        # no error is raised
-        with expect_warnings(
-            "Enum 'length' argument is currently ignored unless native_enum"
-        ):
-            e = Enum("x", "y", "long", length=1)
+        e = Enum("x", "y", "long")
         eq_(e.length, len("long"))
 
-    def test_length_raises(self):
+    def test_length_too_short_raises(self):
         assert_raises_message(
             ValueError,
             "When provided, length must be larger or equal.*",