]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Repeat expressions in the columns clause of a select
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 20 Oct 2009 16:56:15 +0000 (16:56 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 20 Oct 2009 16:56:15 +0000 (16:56 +0000)
are deduped based on the identity of each clause element,
not the actual string.  This allows positional
elements to render correctly even if they all render
identically, such as "qmark" style bind parameters.
[ticket:1574]

CHANGES
lib/sqlalchemy/sql/compiler.py
test/sql/test_select.py

diff --git a/CHANGES b/CHANGES
index 231f97828f5db5ae903dcb9d28bb59d2f8c04c34..4a6b28bde30cc4e8fe18f8e5834a1feefa0232e6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -27,6 +27,13 @@ CHANGES
     - Fixed the "numeric" paramstyle, which apparently is the
       default paramstyle used by Informixdb.
       
+    - Repeat expressions in the columns clause of a select
+      are deduped based on the identity of each clause element,
+      not the actual string.  This allows positional 
+      elements to render correctly even if they all render
+      identically, such as "qmark" style bind parameters.
+      [ticket:1574]
+      
 - postgresql
     - Added support for reflecting the DOUBLE PRECISION type,
       via a new postgres.PGDoublePrecision object.  
index 9c06d99277ef0b57a460c677f294caac103184ac..5e2de5b0343c5c884eb8da2948cd25eb9495cc1c 100644 (file)
@@ -530,16 +530,16 @@ class DefaultCompiler(engine.Compiled):
             column_clause_args = {}
 
         # the actual list of columns to print in the SELECT column list.
-        inner_columns = util.unique_list(
+        inner_columns = [
             c for c in [
                 self.process(
                     self.label_select_column(select, co, asfrom=asfrom), 
                     within_columns_clause=True,
                     **column_clause_args) 
-                for co in select.inner_columns
+                for co in util.unique_list(select.inner_columns)
             ]
             if c is not None
-        )
+        ]
         
         text = "SELECT "  # we're off to a good start !
         if select._prefixes:
index 941973e5fbd1552aa495ffb772e9ecabf0bf07b2..51cdaeb52ce2ca4c4b96282737f01422b6e8a86a 100644 (file)
@@ -183,7 +183,49 @@ sq.myothertable_othername AS sq_myothertable_othername FROM (" + sqstring + ") A
             , dialect=default.DefaultDialect(paramstyle='pyformat')
         )
         
+    def test_dupe_columns(self):
+        """test that deduping is performed against clause element identity, not rendered result."""
         
+        self.assert_compile(
+            select([column('a'), column('a'), column('a')]),
+            "SELECT a, a, a"
+            , dialect=default.DefaultDialect()
+        )
+
+        c = column('a')
+        self.assert_compile(
+            select([c, c, c]),
+            "SELECT a"
+            , dialect=default.DefaultDialect()
+        )
+
+        a, b = column('a'), column('b')
+        self.assert_compile(
+            select([a, b, b, b, a, a]),
+            "SELECT a, b"
+            , dialect=default.DefaultDialect()
+        )
+        
+        self.assert_compile(
+            select([bindparam('a'), bindparam('b'), bindparam('c')]),
+            "SELECT :a, :b, :c"
+            , dialect=default.DefaultDialect(paramstyle='named')
+        )
+
+        self.assert_compile(
+            select([bindparam('a'), bindparam('b'), bindparam('c')]),
+            "SELECT ?, ?, ?"
+            , dialect=default.DefaultDialect(paramstyle='qmark'),
+        )
+
+        self.assert_compile(
+            select(["a", "a", "a"]),
+            "SELECT a, a, a"
+        )
+        
+        s = select([bindparam('a'), bindparam('b'), bindparam('c')])
+        s = s.compile(dialect=default.DefaultDialect(paramstyle='qmark'))
+        eq_(s.positiontup, ['a', 'b', 'c'])
         
     def test_nested_uselabels(self):
         """test nested anonymous label generation.  this