summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2016-02-26 00:20:39 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2016-02-26 00:20:39 -0500
commit0210695bd97e76f58d8781b69337816501482fb0 (patch)
tree8d86db3143a258142c92ad7820f62a61a24409e2
parentf8914288f012c4ef635531f09a0e13bcacacdb2a (diff)
downloadsqlalchemy-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.rst11
-rw-r--r--lib/sqlalchemy/sql/elements.py2
-rw-r--r--test/orm/test_query.py59
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)