diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-06-11 16:48:00 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2015-06-11 16:48:00 -0400 |
commit | e765c55e8cc71bb3773b86b5260df6cb69aff102 (patch) | |
tree | dcfa5fec47b29336b2bedb49f87e1772f3b23069 | |
parent | a463bb31ea8a93ffd15e4fb7cc71d84c4d206572 (diff) | |
download | sqlalchemy-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.rst | 13 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/query.py | 8 | ||||
-rw-r--r-- | test/ext/test_hybrid.py | 1 | ||||
-rw-r--r-- | test/orm/test_descriptor.py | 1 | ||||
-rw-r--r-- | test/orm/test_query.py | 19 |
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): |