diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-02-26 00:20:39 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2016-02-26 00:20:39 -0500 |
commit | 0210695bd97e76f58d8781b69337816501482fb0 (patch) | |
tree | 8d86db3143a258142c92ad7820f62a61a24409e2 | |
parent | f8914288f012c4ef635531f09a0e13bcacacdb2a (diff) | |
download | sqlalchemy-0210695bd97e76f58d8781b69337816501482fb0.tar.gz |
- Anonymous labeling is applied to a :attr:`.func` construct that is
passed to :func:`.column_property`, so that if the same attribute
is referred to as a column expression twice the names are de-duped,
thus avoiding "ambiguous column" errors. Previously, the
``.label(None)`` would need to be applied in order for the name
to be de-anonymized.
fixes #3663
-rw-r--r-- | doc/build/changelog/changelog_10.rst | 11 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/elements.py | 2 | ||||
-rw-r--r-- | test/orm/test_query.py | 59 |
3 files changed, 70 insertions, 2 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index 36152c236..209f13bdc 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -19,6 +19,17 @@ :version: 1.0.13 .. change:: + :tags: bug, orm + :tickets: 3663 + + Anonymous labeling is applied to a :attr:`.func` construct that is + passed to :func:`.column_property`, so that if the same attribute + is referred to as a column expression twice the names are de-duped, + thus avoiding "ambiguous column" errors. Previously, the + ``.label(None)`` would need to be applied in order for the name + to be de-anonymized. + + .. change:: :tags: bug, py3k :tickets: 3660 diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index ca822d310..67a442b0c 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -4006,7 +4006,7 @@ def _cloned_difference(a, b): def _labeled(element): - if not hasattr(element, 'name'): + if not hasattr(element, 'name') or not getattr(element, '_label', None): return element.label(None) else: return element diff --git a/test/orm/test_query.py b/test/orm/test_query.py index c4c62c319..cdc4ac2c2 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -484,7 +484,7 @@ class RawSelectTest(QueryTest, AssertsCompiledSQL): self.assert_compile( select([Foo]).where(Foo.foob == 'somename').order_by(Foo.foob), "SELECT users.id, users.name FROM users " - "WHERE coalesce(users.name) = :coalesce_1 " + "WHERE coalesce(users.name) = :param_1 " "ORDER BY coalesce(users.name)" ) @@ -1593,6 +1593,63 @@ class ColumnPropertyTest(_fixtures.FixtureTest, AssertsCompiledSQL): }, with_polymorphic="*" if polymorphic else None) mapper(Address, addresses) + def _func_fixture(self, label=False): + User = self.classes.User + users = self.tables.users + + if label: + mapper(User, users, properties={ + "foobar": column_property( + func.foob(users.c.name).label(None) + ) + }) + else: + mapper(User, users, properties={ + "foobar": column_property( + func.foob(users.c.name) + ) + }) + + def test_anon_label_function_auto(self): + self._func_fixture() + User = self.classes.User + + s = Session() + + u1 = aliased(User) + self.assert_compile( + s.query(User.foobar, u1.foobar), + "SELECT foob(users.name) AS foob_1, foob(users_1.name) AS foob_2 " + "FROM users, users AS users_1" + ) + + def test_anon_label_function_manual(self): + self._func_fixture(label=True) + User = self.classes.User + + s = Session() + + u1 = aliased(User) + self.assert_compile( + s.query(User.foobar, u1.foobar), + "SELECT foob(users.name) AS foob_1, foob(users_1.name) AS foob_2 " + "FROM users, users AS users_1" + ) + + def test_anon_label_ad_hoc_labeling(self): + self._func_fixture() + User = self.classes.User + + s = Session() + + u1 = aliased(User) + self.assert_compile( + s.query(User.foobar.label('x'), u1.foobar.label('y')), + "SELECT foob(users.name) AS x, foob(users_1.name) AS y " + "FROM users, users AS users_1" + ) + + def test_order_by_column_prop_string(self): User, Address = self.classes("User", "Address") self._fixture(label=True) |