From a19b2f419cd876b561a3b3c21ebed5c223192883 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 10 Nov 2014 17:37:26 -0500 Subject: [PATCH] - The :attr:`.Column.key` attribute is now used as the source of anonymous bound parameter names within expressions, to match the existing use of this value as the key when rendered in an INSERT or UPDATE statement. This allows :attr:`.Column.key` to be used as a "substitute" string to work around a difficult column name that doesn't translate well into a bound parameter name. Note that the paramstyle is configurable on :func:`.create_engine` in any case, and most DBAPIs today support a named and positional style. fixes #3245 --- doc/build/changelog/changelog_10.rst | 13 +++++++++++++ lib/sqlalchemy/sql/elements.py | 4 ++-- test/dialect/mssql/test_reflection.py | 4 ++-- test/sql/test_compiler.py | 13 +++++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index e63e023d90..4e5e1ba1d9 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -21,6 +21,19 @@ series as well. For changes that are specific to 1.0 with an emphasis on compatibility concerns, see :doc:`/changelog/migration_10`. + .. change:: + :tags: bug, sql + :tickets: 3245 + + The :attr:`.Column.key` attribute is now used as the source of + anonymous bound parameter names within expressions, to match the + existing use of this value as the key when rendered in an INSERT + or UPDATE statement. This allows :attr:`.Column.key` to be used + as a "substitute" string to work around a difficult column name + that doesn't translate well into a bound parameter name. Note that + the paramstyle is configurable on :func:`.create_engine` in any case, + and most DBAPIs today support a named and positional style. + .. change:: :tags: bug, sql :pullreq: github:146 diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index fa9b660247..734f78632b 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -1092,7 +1092,7 @@ class BindParameter(ColumnElement): """ if isinstance(key, ColumnClause): type_ = key.type - key = key.name + key = key.key if required is NO_ARG: required = (value is NO_ARG and callable_ is None) if value is NO_ARG: @@ -3335,7 +3335,7 @@ class ColumnClause(Immutable, ColumnElement): return name def _bind_param(self, operator, obj): - return BindParameter(self.name, obj, + return BindParameter(self.key, obj, _compared_to_operator=operator, _compared_to_type=self.type, unique=True) diff --git a/test/dialect/mssql/test_reflection.py b/test/dialect/mssql/test_reflection.py index e93162a8e9..0ef69f656e 100644 --- a/test/dialect/mssql/test_reflection.py +++ b/test/dialect/mssql/test_reflection.py @@ -187,7 +187,7 @@ class InfoCoerceUnicodeTest(fixtures.TestBase, AssertsCompiledSQL): stmt = tables.c.table_name == 'somename' self.assert_compile( stmt, - "[TABLES_1].[TABLE_NAME] = :TABLE_NAME_1", + "[TABLES_1].[TABLE_NAME] = :table_name_1", dialect=dialect ) @@ -197,7 +197,7 @@ class InfoCoerceUnicodeTest(fixtures.TestBase, AssertsCompiledSQL): stmt = tables.c.table_name == 'somename' self.assert_compile( stmt, - "[TABLES_1].[TABLE_NAME] = CAST(:TABLE_NAME_1 AS NVARCHAR(max))", + "[TABLES_1].[TABLE_NAME] = CAST(:table_name_1 AS NVARCHAR(max))", dialect=dialect ) diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index bfafed599f..5d1afe6162 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -435,6 +435,19 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): dialect=default.DefaultDialect(paramstyle='pyformat') ) + def test_anon_param_name_on_keys(self): + self.assert_compile( + keyed.insert(), + "INSERT INTO keyed (x, y, z) VALUES (%(colx)s, %(coly)s, %(z)s)", + dialect=default.DefaultDialect(paramstyle='pyformat') + ) + self.assert_compile( + keyed.c.coly == 5, + "keyed.y = %(coly_1)s", + checkparams={'coly_1': 5}, + dialect=default.DefaultDialect(paramstyle='pyformat') + ) + def test_dupe_columns(self): """test that deduping is performed against clause element identity, not rendered result.""" -- 2.47.3