summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Hayes <pfhayes@gmail.com>2019-10-24 10:11:52 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-10-27 11:49:15 -0400
commite55e749e182e257fcc60db383751d5afbe52ddfb (patch)
tree0d90683728796a38c5a7f22d5103c6948e67e7b4
parent38b695748557f4987ef79600ee6267725c0db6dc (diff)
downloadsqlalchemy-e55e749e182e257fcc60db383751d5afbe52ddfb.tar.gz
Add public accessor `is_single_entity` to Query
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
-rw-r--r--doc/build/changelog/unreleased_13/4934.rst11
-rw-r--r--lib/sqlalchemy/orm/loading.py6
-rw-r--r--lib/sqlalchemy/orm/query.py32
-rw-r--r--test/orm/test_query.py20
4 files changed, 55 insertions, 14 deletions
diff --git a/doc/build/changelog/unreleased_13/4934.rst b/doc/build/changelog/unreleased_13/4934.rst
new file mode 100644
index 000000000..3f279a430
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/4934.rst
@@ -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.
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index 8de7d5a8b..25ba8a398 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -42,11 +42,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:
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 92f9ee952..1a36349f3 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -640,14 +640,40 @@ class Query(Generative):
@_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
diff --git a/test/orm/test_query.py b/test/orm/test_query.py
index d2c4f5bc7..cdbeba138 100644
--- a/test/orm/test_query.py
+++ b/test/orm/test_query.py
@@ -55,7 +55,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
@@ -96,32 +98,38 @@ 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, collections_abc.Sequence)
def test_multiple_entity_false(self):
User = self.classes.User
- row = (
+ query = (
create_session()
.query(User.id, User)
.only_return_tuples(False)
- .first()
)
+ is_false(query.is_single_entity)
+ row = query.first()
assert isinstance(row, collections_abc.Sequence)
def test_multiple_entity_true(self):
User = self.classes.User
- row = (
+ query = (
create_session()
.query(User.id, User)
.only_return_tuples(True)
- .first()
)
+ is_false(query.is_single_entity)
+ row = query.first()
assert isinstance(row, collections_abc.Sequence)