diff options
| author | Patrick Hayes <pfhayes@gmail.com> | 2019-10-24 10:11:52 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-10-27 11:49:15 -0400 |
| commit | e55e749e182e257fcc60db383751d5afbe52ddfb (patch) | |
| tree | 0d90683728796a38c5a7f22d5103c6948e67e7b4 | |
| parent | 38b695748557f4987ef79600ee6267725c0db6dc (diff) | |
| download | sqlalchemy-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.rst | 11 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/loading.py | 6 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 32 | ||||
| -rw-r--r-- | test/orm/test_query.py | 20 |
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) |
