]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed issue in new :meth:`.TextClause.columns` method where the ordering
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 26 Feb 2014 18:28:14 +0000 (13:28 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 26 Feb 2014 18:28:14 +0000 (13:28 -0500)
of columns given positionally would not be preserved.   This could
have potential impact in positional situations such as applying the
resulting :class:`.TextAsFrom` object to a union.

doc/build/changelog/changelog_09.rst
lib/sqlalchemy/sql/elements.py
test/sql/test_selectable.py
test/sql/test_text.py

index c29db6f9261cae047404c39c5c805a6e0995e7a1..a6245bdb774bab6bd9402925472640dc967a779b 100644 (file)
 .. changelog::
     :version: 0.9.4
 
+    .. change::
+        :tags: bug, sql
+
+        Fixed issue in new :meth:`.TextClause.columns` method where the ordering
+        of columns given positionally would not be preserved.   This could
+        have potential impact in positional situations such as applying the
+        resulting :class:`.TextAsFrom` object to a union.
+
     .. change::
         :tags: feature, sql
         :tickets: 2962, 2866
index 2846b3b51ff934b73d6e9543187ff8e6b0c394b9..1b49a7cd1c9cdfbfaf27ac13410fe5962c7d5bf6 100644 (file)
@@ -1446,13 +1446,13 @@ class TextClause(Executable, ClauseElement):
 
         """
 
-        col_by_name = dict(
-            (col.key, col) for col in cols
-        )
-        for key, type_ in types.items():
-            col_by_name[key] = ColumnClause(key, type_)
-
-        return selectable.TextAsFrom(self, list(col_by_name.values()))
+        input_cols = [
+            ColumnClause(col.key, types.pop(col.key))
+                if col.key in types
+                else col
+            for col in cols
+        ] + [ColumnClause(key, type_) for key, type_ in types.items()]
+        return selectable.TextAsFrom(self, input_cols)
 
     @property
     def type(self):
index dbd73a83672f102a69f7144da3ee4e7e113da843..9617cfdf7b5bc120819cd6ccf7ea35cf239c6f88 100644 (file)
@@ -388,6 +388,31 @@ class SelectableTest(fixtures.TestBase, AssertsExecutionResults, AssertsCompiled
         assert u.corresponding_column(s2.c.table2_coly) is u.c.coly
         assert s2.corresponding_column(u.c.coly) is s2.c.table2_coly
 
+    def test_union_of_alias(self):
+        s1 = select([table1.c.col1, table1.c.col2])
+        s2 = select([table1.c.col1, table1.c.col2]).alias()
+
+        u1 = union(s1, s2)
+        assert u1.corresponding_column(s1.c.col1) is u1.c.col1
+        assert u1.corresponding_column(s2.c.col1) is u1.c.col1
+
+        u2 = union(s2, s1)
+        assert u2.corresponding_column(s1.c.col1) is u2.c.col1
+        assert u2.corresponding_column(s2.c.col1) is u2.c.col1
+
+    def test_union_of_text(self):
+        s1 = select([table1.c.col1, table1.c.col2])
+        s2 = text("select col1, col2 from foo").columns(
+                            column('col1'), column('col2'))
+
+        u1 = union(s1, s2)
+        assert u1.corresponding_column(s1.c.col1) is u1.c.col1
+        assert u1.corresponding_column(s2.c.col1) is u1.c.col1
+
+        u2 = union(s2, s1)
+        assert u2.corresponding_column(s1.c.col1) is u2.c.col1
+        assert u2.corresponding_column(s2.c.col1) is u2.c.col1
+
     def test_select_union(self):
 
         # like testaliasunion, but off a Select off the union.
index 57dadfb160e278d0b6aac19cdf2d6c346c4036c5..ef63f9daad2d3e7761378e3489ca1115c6fa8d4c 100644 (file)
@@ -322,6 +322,20 @@ class AsFromTest(fixtures.TestBase, AssertsCompiledSQL):
             }
         )
 
+    def test_column_collection_ordered(self):
+        t = text("select a, b, c from foo").columns(column('a'),
+                            column('b'), column('c'))
+        eq_(t.c.keys(), ['a', 'b', 'c'])
+
+    def test_column_collection_pos_plus_bykey(self):
+        # overlapping positional names + type names
+        t = text("select a, b, c from foo").columns(column('a'),
+                            column('b'), b=Integer, c=String)
+        eq_(t.c.keys(), ['a', 'b', 'c'])
+        eq_(t.c.b.type._type_affinity, Integer)
+        eq_(t.c.c.type._type_affinity, String)
+
+
     def _xy_table_fixture(self):
         m = MetaData()
         t = Table('t', m, Column('x', Integer), Column('y', Integer))