]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- merge 00380cf3c304ea7f1c7397f17b828166364c36ac from default
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 18 May 2011 16:12:00 +0000 (12:12 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 18 May 2011 16:12:00 +0000 (12:12 -0400)
- Fixed bug whereby nesting a label of a select()
with another label in it would produce incorrect
exported columns.   Among other things this would
break an ORM column_property() mapping against
another column_property().  [ticket:2167].

CHANGES
lib/sqlalchemy/orm/query.py
lib/sqlalchemy/sql/expression.py
test/orm/test_query.py
test/sql/test_selectable.py

diff --git a/CHANGES b/CHANGES
index 1b93682ad26756a524f6e2c61de9f813591c0ce2..5824d0b6446c6475c3865821a911ee6324378fb8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -53,6 +53,12 @@ CHANGES
     test coverage for all column default assignment
     patterns.  [ticket:2147]
 
+  - Fixed bug whereby nesting a label of a select()
+    with another label in it would produce incorrect
+    exported columns.   Among other things this would
+    break an ORM column_property() mapping against
+    another column_property().  [ticket:2167].
+
 0.6.7
 =====
 - orm
index 30dae14c2826bd2c66caf459dede62c9b4552cbb..c5bf59d6295110f29ff4a0bce20024b5e64f5c44 100644 (file)
@@ -2743,11 +2743,11 @@ class _ColumnEntity(_QueryEntity):
                 "expected - got '%r'" % column
             )
 
-        # if the Column is unnamed, give it a
+        # If the Column is unnamed, give it a
         # label() so that mutable column expressions
         # can be located in the result even
         # if the expression's identity has been changed
-        # due to adaption
+        # due to adaption.
         if not column._label:
             column = column.label(None)
 
index aea1504a41dc0cbc2961055c456c8516d9a37f08..75e33b6b4d34e8dfefbe2f5cfe17ee0a60a1b50c 100644 (file)
@@ -3493,11 +3493,7 @@ class _Label(ColumnElement):
         return self.element._from_objects
 
     def _make_proxy(self, selectable, name = None):
-        if isinstance(self.element, (Selectable, ColumnElement)):
-            e = self.element._make_proxy(selectable, name=self.name)
-        else:
-            e = column(self.name)._make_proxy(selectable=selectable)
-
+        e = self.element._make_proxy(selectable, name=name or self.name)
         e.proxies.append(self)
         return e
 
@@ -3606,6 +3602,12 @@ class ColumnClause(_Immutable, ColumnElement):
             return self.name
 
     def label(self, name):
+        # currently, anonymous labels don't occur for 
+        # ColumnClause.   The use at the moment
+        # is that they do not generate nicely for 
+        # is_literal clauses.   We would like to change
+        # this so that label(None) acts as would be expected.
+        # See [ticket:2168].
         if name is None:
             return self
         else:
index 43a415fde61e951dc50824b286fceef85b1ef57c..6067964ef138352f4a5935b594cbb6ceb3174174 100644 (file)
@@ -4517,6 +4517,26 @@ class ExternalColumnsTest(QueryTest):
             eq_(o1.address.user.count, 1)
         self.assert_sql_count(testing.db, go, 1)
 
+    def test_external_columns_compound(self):
+        # see [ticket:2167] for background
+
+        mapper(User, users, properties={
+            'fullname':column_property(users.c.name.label('x'))
+        })
+
+        mapper(Address, addresses, properties={
+            'username':column_property(
+                        select([User.fullname]).\
+                            where(User.id==addresses.c.user_id).label('y'))
+        })
+        sess = create_session()
+        a1 = sess.query(Address).first()
+        eq_(a1.username, "jack")
+
+        sess = create_session()
+        a1 = sess.query(Address).from_self().first()
+        eq_(a1.username, "jack")
+
 class TestOverlyEagerEquivalentCols(_base.MappedTest):
     @classmethod
     def define_tables(cls, metadata):
index 82df3b1d6b35e16e2630c9b430d44593d5a032ec..d67e721a0300bfdc149bb4e53bce65a45ba7f5ff 100644 (file)
@@ -26,7 +26,7 @@ table2 = Table('table2', metadata,
 )
 
 
-class SelectableTest(TestBase, AssertsExecutionResults):
+class SelectableTest(TestBase, AssertsExecutionResults, AssertsCompiledSQL):
 
     def test_indirect_correspondence_on_labels(self):
         # this test depends upon 'distance' to
@@ -371,6 +371,54 @@ class SelectableTest(TestBase, AssertsExecutionResults):
                               "side to a subquery using alias\(\)\?",
                               t1t2.join, t2t3.select(use_labels=True))
 
+    def test_multi_label_chain_naming_col(self):
+        # See [ticket:2167] for this one.
+        l1 = table1.c.col1.label('a')
+        l2 = select([l1]).label('b')
+        s = select([l2])
+        assert s.c.b is not None
+        self.assert_compile(
+            s.select(),
+            "SELECT b FROM (SELECT (SELECT table1.col1 AS a FROM table1) AS b)"
+        )
+
+        s2 = select([s.label('c')])
+        self.assert_compile(
+            s2.select(),
+            "SELECT c FROM (SELECT (SELECT (SELECT table1.col1 AS a FROM table1) AS b) AS c)"
+        )
+
+class AnonLabelTest(TestBase):
+    """Test behaviors that we hope to change with [ticket:2168]."""
+
+    def test_anon_labels_named_column(self):
+        c1 = column('x')
+
+        # surprising
+        assert c1.label(None) is c1
+        eq_(str(select([c1.label(None)])), "SELECT x")
+
+    def test_anon_labels_literal_column(self):
+        c1 = literal_column('x')
+        assert c1.label(None) is c1
+        eq_(str(select([c1.label(None)])), "SELECT x")
+
+    def test_anon_labels_func(self):
+        c1 = func.count('*')
+        assert c1.label(None) is not c1
+
+        eq_(str(select([c1])), "SELECT count(:param_1) AS count_1")
+        c2 = select([c1]).compile()
+
+        eq_(str(select([c1.label(None)])), "SELECT count(:param_1) AS count_1")
+
+    def test_named_labels_named_column(self):
+        c1 = column('x')
+        eq_(str(select([c1.label('y')])), "SELECT x AS y")
+
+    def test_named_labels_literal_column(self):
+        c1 = literal_column('x')
+        eq_(str(select([c1.label('y')])), "SELECT x AS y")
 
 class PrimaryKeyTest(TestBase, AssertsExecutionResults):