From 404f43894a63cea858189240c4027a7451b87bf2 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 20 Oct 2009 17:12:58 +0000 Subject: [PATCH] merge r6418 from 0.5, dedupe expressions on clause ident, not string value [ticket:1574] --- CHANGES | 7 ++++++ lib/sqlalchemy/sql/compiler.py | 6 ++--- test/sql/test_select.py | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 850dcf8dbd..f83ea987a7 100644 --- a/CHANGES +++ b/CHANGES @@ -584,6 +584,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. diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index f07e6aca8c..4c31308796 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -584,16 +584,16 @@ class SQLCompiler(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: diff --git a/test/sql/test_select.py b/test/sql/test_select.py index 757dc52136..3dc09c9dfc 100644 --- a/test/sql/test_select.py +++ b/test/sql/test_select.py @@ -182,6 +182,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 -- 2.47.2