]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add public accessor `is_single_entity` to Query
authorPatrick Hayes <pfhayes@gmail.com>
Thu, 24 Oct 2019 14:11:52 +0000 (10:11 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 27 Oct 2019 16:27:23 +0000 (12:27 -0400)
Added accessor :attr:`.Query.is_single_entity` to :class:`.Query`, which
will indicate if the results returned by this :class:`.Query` will be a
list of ORM entities, or a tuple of entities or column expressions.
SQLAlchemy hopes to improve upon the behavior of single entity / tuples in
future releases such that the behavior would be explicit up front, however
this attribute should be helpful with the current behavior.  Pull request
courtesy Patrick Hayes.

Fixes: #4934
Closes: #4935
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4935
Pull-request-sha: 98f72b40a896761a65b048cc3722ff2dac4cf2b1

Change-Id: If5db5db3ea46a93406d76ef90b5b588149ba2986
(cherry picked from commit e55e749e182e257fcc60db383751d5afbe52ddfb)

doc/build/changelog/unreleased_13/4934.rst [new file with mode: 0644]
lib/sqlalchemy/orm/loading.py
lib/sqlalchemy/orm/query.py
test/orm/test_query.py

diff --git a/doc/build/changelog/unreleased_13/4934.rst b/doc/build/changelog/unreleased_13/4934.rst
new file mode 100644 (file)
index 0000000..3f279a4
--- /dev/null
@@ -0,0 +1,11 @@
+.. change::
+    :tags: orm, usecase
+    :tickets: 4934
+
+    Added accessor :meth:`.Query.is_single_entity` to :class:`.Query`, which
+    will indicate if the results returned by this :class:`.Query` will be a
+    list of ORM entities, or a tuple of entities or column expressions.
+    SQLAlchemy hopes to improve upon the behavior of single entity / tuples in
+    future releases such that the behavior would be explicit up front, however
+    this attribute should be helpful with the current behavior.  Pull request
+    courtesy Patrick Hayes.
index fd283f432706f4fe152fde7c72db248def0034eb..78ad2eb3b9990eb0f355cbba53a337815e44686a 100644 (file)
@@ -40,11 +40,7 @@ def instances(query, cursor, context):
 
     filtered = query._has_mapper_entities
 
-    single_entity = (
-        not query._only_return_tuples
-        and len(query._entities) == 1
-        and query._entities[0].supports_single_entity
-    )
+    single_entity = query.is_single_entity
 
     if filtered:
         if single_entity:
index f4cf34458ca1d7dec083812a9422c1f1a0f4b865..d3629690ed57876a1585ce5108ac5c9702b3e6b1 100644 (file)
@@ -660,14 +660,40 @@ class Query(object):
 
     @_generative()
     def only_return_tuples(self, value):
-        """When set to True, the query results will always be a tuple,
-        specifically for single element queries. The default is False.
+        """When set to True, the query results will always be a tuple.
 
-    .   .. versionadded:: 1.2.5
+        This is specifically for single element queries. The default is False.
+
+        .. versionadded:: 1.2.5
+
+        .. seealso::
+
+            :meth:`.Query.is_single_entity`
 
         """
         self._only_return_tuples = value
 
+    @property
+    def is_single_entity(self):
+        """Indicates if this :class:`.Query` returns tuples or single entities.
+
+        Returns True if this query returns a single entity for each instance
+        in its result list, and False if this query returns a tuple of entities
+        for each result.
+
+        .. versionadded:: 1.3.11
+
+        .. seealso::
+
+            :meth:`.Query.only_return_tuples`
+
+        """
+        return (
+            not self._only_return_tuples
+            and len(self._entities) == 1
+            and self._entities[0].supports_single_entity
+        )
+
     @_generative()
     def enable_eagerloads(self, value):
         """Control whether or not eager joins and subqueries are
index 9ba5ed3b5b75ff65dea221ae80a344420b01e7bc..3cab1169f543f51a0b28b1a8906fad3535f1b743 100644 (file)
@@ -53,7 +53,9 @@ from sqlalchemy.sql import operators
 from sqlalchemy.testing import AssertsCompiledSQL
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing import is_
+from sqlalchemy.testing import is_false
 from sqlalchemy.testing import is_not_
+from sqlalchemy.testing import is_true
 from sqlalchemy.testing import mock
 from sqlalchemy.testing.assertions import assert_raises
 from sqlalchemy.testing.assertions import assert_raises_message
@@ -93,32 +95,30 @@ class MiscTest(QueryTest):
 class OnlyReturnTuplesTest(QueryTest):
     def test_single_entity_false(self):
         User = self.classes.User
-        row = create_session().query(User).only_return_tuples(False).first()
+        query = create_session().query(User).only_return_tuples(False)
+        is_true(query.is_single_entity)
+        row = query.first()
         assert isinstance(row, User)
 
     def test_single_entity_true(self):
         User = self.classes.User
-        row = create_session().query(User).only_return_tuples(True).first()
+        query = create_session().query(User).only_return_tuples(True)
+        is_false(query.is_single_entity)
+        row = query.first()
         assert isinstance(row, tuple)
 
     def test_multiple_entity_false(self):
         User = self.classes.User
-        row = (
-            create_session()
-            .query(User.id, User)
-            .only_return_tuples(False)
-            .first()
-        )
+        query = create_session().query(User.id, User).only_return_tuples(False)
+        is_false(query.is_single_entity)
+        row = query.first()
         assert isinstance(row, tuple)
 
     def test_multiple_entity_true(self):
         User = self.classes.User
-        row = (
-            create_session()
-            .query(User.id, User)
-            .only_return_tuples(True)
-            .first()
-        )
+        query = create_session().query(User.id, User).only_return_tuples(True)
+        is_false(query.is_single_entity)
+        row = query.first()
         assert isinstance(row, tuple)