summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-06-11 16:48:00 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-06-11 16:48:00 -0400
commite765c55e8cc71bb3773b86b5260df6cb69aff102 (patch)
treedcfa5fec47b29336b2bedb49f87e1772f3b23069
parenta463bb31ea8a93ffd15e4fb7cc71d84c4d206572 (diff)
downloadsqlalchemy-e765c55e8cc71bb3773b86b5260df6cb69aff102.tar.gz
- Fixed an unexpected-use regression whereby custom :class:`.Comparator`
objects that made use of the ``__clause_element__()`` method and returned an object that was an ORM-mapped :class:`.InstrumentedAttribute` and not explicitly a :class:`.ColumnElement` would fail to be correctly handled when passed as an expression to :meth:`.Session.query`. The logic in 0.9 happened to succeed on this, so this use case is now supported. fixes #3448
-rw-r--r--doc/build/changelog/changelog_10.rst13
-rw-r--r--lib/sqlalchemy/orm/query.py8
-rw-r--r--test/ext/test_hybrid.py1
-rw-r--r--test/orm/test_descriptor.py1
-rw-r--r--test/orm/test_query.py19
5 files changed, 40 insertions, 2 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst
index 3436a0ca6..f44886559 100644
--- a/doc/build/changelog/changelog_10.rst
+++ b/doc/build/changelog/changelog_10.rst
@@ -19,6 +19,19 @@
:version: 1.0.6
.. change::
+ :tags: bug, orm
+ :tickets: 3448
+
+ Fixed an unexpected-use regression whereby custom :class:`.Comparator`
+ objects that made use of the ``__clause_element__()`` method and
+ returned an object that was an ORM-mapped
+ :class:`.InstrumentedAttribute` and not explicitly a
+ :class:`.ColumnElement` would fail to be correctly
+ handled when passed as an expression to :meth:`.Session.query`.
+ The logic in 0.9 happened to succeed on this, so this use case is now
+ supported.
+
+ .. change::
:tags: bug, sql
:tickets: 3445
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index 8421e42ac..4f8c86a14 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -3539,11 +3539,13 @@ class _ColumnEntity(_QueryEntity):
self.expr = column
self.namespace = namespace
search_entities = True
+ check_column = False
if isinstance(column, util.string_types):
column = sql.literal_column(column)
self._label_name = column.name
search_entities = False
+ check_column = True
_entity = None
elif isinstance(column, (
attributes.QueryableAttribute,
@@ -3554,10 +3556,12 @@ class _ColumnEntity(_QueryEntity):
search_entities = False
self._label_name = column.key
column = column._query_clause_element()
+ check_column = True
if isinstance(column, Bundle):
_BundleEntity(query, column)
return
- elif not isinstance(column, sql.ColumnElement):
+
+ if not isinstance(column, sql.ColumnElement):
if hasattr(column, '_select_iterable'):
# break out an object like Table into
# individual columns
@@ -3572,7 +3576,7 @@ class _ColumnEntity(_QueryEntity):
"SQL expression, column, or mapped entity "
"expected - got '%r'" % (column, )
)
- else:
+ elif not check_column:
self._label_name = getattr(column, 'key', None)
search_entities = True
diff --git a/test/ext/test_hybrid.py b/test/ext/test_hybrid.py
index b895d2fb2..e36b8f7e9 100644
--- a/test/ext/test_hybrid.py
+++ b/test/ext/test_hybrid.py
@@ -7,6 +7,7 @@ from sqlalchemy.testing import eq_, AssertsCompiledSQL, assert_raises_message
from sqlalchemy.testing import fixtures
from sqlalchemy import inspect
+
class PropertyComparatorTest(fixtures.TestBase, AssertsCompiledSQL):
__dialect__ = 'default'
diff --git a/test/orm/test_descriptor.py b/test/orm/test_descriptor.py
index 2134d87b2..d9aca30e5 100644
--- a/test/orm/test_descriptor.py
+++ b/test/orm/test_descriptor.py
@@ -125,3 +125,4 @@ class DescriptorInstrumentationTest(fixtures.ORMTest):
str(aliased(Foo).foo == 'ed'),
"foobar(foo_1.name) = foobar(:foobar_1)"
)
+
diff --git a/test/orm/test_query.py b/test/orm/test_query.py
index 6a1eb57b4..41c0e2a21 100644
--- a/test/orm/test_query.py
+++ b/test/orm/test_query.py
@@ -1718,6 +1718,25 @@ class ColumnPropertyTest(_fixtures.FixtureTest, AssertsCompiledSQL):
)
+class ComparatorTest(QueryTest):
+ def test_clause_element_query_resolve(self):
+ from sqlalchemy.orm.properties import ColumnProperty
+ User = self.classes.User
+
+ class Comparator(ColumnProperty.Comparator):
+ def __init__(self, expr):
+ self.expr = expr
+
+ def __clause_element__(self):
+ return self.expr
+
+ sess = Session()
+ eq_(
+ sess.query(Comparator(User.id)).order_by(Comparator(User.id)).all(),
+ [(7, ), (8, ), (9, ), (10, )]
+ )
+
+
# more slice tests are available in test/orm/generative.py
class SliceTest(QueryTest):
def test_first(self):