]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
warn for result.columns() method
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 21 Apr 2022 17:27:16 +0000 (13:27 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 21 Apr 2022 17:36:51 +0000 (13:36 -0400)
A warning is emitted when calling upon the :meth:`.Result.columns` method
with only one index, in particular ORM related cases, indicating that the
current behavior of :meth:`.Result.columns` is broken in this case and
will be changed in 2.0.  To receive a collection of scalar values,
use the :meth:`.Result.scalars` method.

Fixes: #7953
Change-Id: I3c4ca3eecc2bfc85ad1c38000e5990d6dde80d22
(cherry picked from commit fe2045fb1c767436ed1e32359fe005dabead504a)

doc/build/changelog/unreleased_14/7953.rst [new file with mode: 0644]
lib/sqlalchemy/engine/result.py
test/base/test_result.py

diff --git a/doc/build/changelog/unreleased_14/7953.rst b/doc/build/changelog/unreleased_14/7953.rst
new file mode 100644 (file)
index 0000000..d4e5037
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, engine
+    :tickets: 7953
+
+    A warning is emitted when calling upon the :meth:`.Result.columns` method
+    with only one index, in particular ORM related cases, indicating that the
+    current behavior of :meth:`.Result.columns` is broken in this case and
+    will be changed in 2.0.  To receive a collection of scalar values,
+    use the :meth:`.Result.scalars` method.
+
index f8006ac53df08ef1872a76a5620f5f5daa0e2922..cb6906f0368762745718758e1e41bad410d8bd8f 100644 (file)
@@ -648,6 +648,15 @@ class ResultInternal(InPlaceGenerative):
         real_result = self._real_result if self._real_result else self
 
         if real_result._source_supports_scalars and len(indexes) == 1:
+            util.warn_deprecated(
+                "The Result.columns() method has a bug in SQLAlchemy 1.4 that "
+                "is causing it to yield scalar values, rather than Row "
+                "objects, in the case where a single index is passed and the "
+                "result is against ORM mapped objects.  In SQLAlchemy 2.0, "
+                "Result will continue yield Row objects in this scenario.  "
+                "Use the Result.scalars() method to yield scalar values.",
+                "2.0",
+            )
             self._generate_rows = False
         else:
             self._generate_rows = True
index 8c9eb398e1540fccf354001274c3ff70cf1a739b..76156db1c3894990327f2f6588ca4efc58c77173 100644 (file)
@@ -5,6 +5,7 @@ from sqlalchemy.engine.row import Row
 from sqlalchemy.testing import assert_raises
 from sqlalchemy.testing import assert_raises_message
 from sqlalchemy.testing import eq_
+from sqlalchemy.testing import expect_deprecated
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing import is_false
 from sqlalchemy.testing import is_true
@@ -1054,12 +1055,49 @@ class OnlyScalarsTest(fixtures.TestBase):
             metadata, no_tuple_fixture, source_supports_scalars=True
         )
 
-        r = r.columns(0).mappings()
+        with expect_deprecated(
+            r"The Result.columns\(\) method has a bug in SQLAlchemy 1.4 "
+            r"that is causing it to yield scalar values"
+        ):
+            r = r.columns(0).mappings()
         eq_(
             list(r),
             [{"a": 1}, {"a": 2}, {"a": 1}, {"a": 1}, {"a": 4}],
         )
 
+    def test_scalar_mode_columns0_plain(self, no_tuple_fixture):
+        """test #7953"""
+
+        metadata = result.SimpleResultMetaData(["a", "b", "c"])
+
+        r = result.ChunkedIteratorResult(
+            metadata, no_tuple_fixture, source_supports_scalars=True
+        )
+
+        with expect_deprecated(
+            r"The Result.columns\(\) method has a bug in SQLAlchemy 1.4 "
+            r"that is causing it to yield scalar values"
+        ):
+            r = r.columns(0)
+        eq_(
+            list(r),
+            [1, 2, 1, 1, 4],
+            # [(1,), (2,), (1,), (1,), (4,)],  # correct result
+        )
+
+    def test_scalar_mode_scalars0(self, no_tuple_fixture):
+        metadata = result.SimpleResultMetaData(["a", "b", "c"])
+
+        r = result.ChunkedIteratorResult(
+            metadata, no_tuple_fixture, source_supports_scalars=True
+        )
+
+        r = r.scalars(0)
+        eq_(
+            list(r),
+            [1, 2, 1, 1, 4],
+        )
+
     def test_scalar_mode_but_accessed_nonscalar_result(self, no_tuple_fixture):
         metadata = result.SimpleResultMetaData(["a", "b", "c"])