From: Mike Bayer Date: Tue, 28 Feb 2017 19:03:47 +0000 (-0500) Subject: Only use schema_translate_map on SchemaItem subclasses X-Git-Tag: rel_1_1_7~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b4e880534e1e02815e95f105a4363bef8ee86130;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Only use schema_translate_map on SchemaItem subclasses Fixed bug in new "schema translate" feature where the translated schema name would be invoked in terms of an alias name when rendered along with a column expression; occurred only when the source translate name was "None". The "schema translate" feature now only takes effect for :class:`.SchemaItem` and :class:`.SchemaType` subclasses, that is, objects that correspond to a DDL-creatable structure in a database. Change-Id: Ie8cb35aeaba2c67efec8c8c57c219e4dd346e44a Fixes: #3924 --- diff --git a/doc/build/changelog/changelog_11.rst b/doc/build/changelog/changelog_11.rst index 645020c426..ffb4bce94a 100644 --- a/doc/build/changelog/changelog_11.rst +++ b/doc/build/changelog/changelog_11.rst @@ -21,6 +21,18 @@ .. changelog:: :version: 1.1.7 + .. change:: + :tags: bug, sql + :tickets: 3924 + + Fixed bug in new "schema translate" feature where the translated schema + name would be invoked in terms of an alias name when rendered along + with a column expression; occurred only when the source translate + name was "None". The "schema translate" feature now only takes + effect for :class:`.SchemaItem` and :class:`.SchemaType` subclasses, + that is, objects that correspond to a DDL-creatable structure in + a database. + .. changelog:: :version: 1.1.6 :released: February 28, 2017 diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 9bb0eee43f..08f23c4af7 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -114,6 +114,9 @@ class SchemaItem(SchemaEventTarget, visitors.Visitable): schema_item.dispatch._update(self.dispatch) return schema_item + def _translate_schema(self, effective_schema, map_): + return map_.get(effective_schema, effective_schema) + class Table(DialectKWArgs, SchemaItem, TableClause): r"""Represent a table in a database. @@ -3974,7 +3977,8 @@ class _SchemaTranslateMap(object): if map_ is not None: def schema_for_object(obj): effective_schema = self._default_schema_getter(obj) - effective_schema = map_.get(effective_schema, effective_schema) + effective_schema = obj._translate_schema( + effective_schema, map_) return effective_schema self.__call__ = schema_for_object self.hash_key = ";".join( diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 91a12bd33a..b69d667c63 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -351,6 +351,9 @@ class FromClause(Selectable): """ + def _translate_schema(self, effective_schema, map_): + return effective_schema + _memoized_property = util.group_expirable_memoized_property(["_columns"]) @util.deprecated( diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 78a130f623..bb39388ab4 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -997,6 +997,9 @@ class SchemaType(SchemaEventTarget): util.portable_instancemethod(self._on_metadata_drop) ) + def _translate_schema(self, effective_schema, map_): + return map_.get(effective_schema, effective_schema) + def _set_parent(self, column): column._on_table_attach(util.portable_instancemethod(self._set_table)) diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index e7504a748e..e65db2a36d 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -3374,6 +3374,12 @@ class SchemaTest(fixtures.TestBase, AssertsCompiledSQL): ) def test_schema_translate_select(self): + m = MetaData() + table1 = Table( + 'mytable', m, Column('myid', Integer), + Column('name', String), + Column('description', String) + ) schema_translate_map = {"remote_owner": "foob", None: 'bar'} self.assert_compile( @@ -3402,13 +3408,51 @@ class SchemaTest(fixtures.TestBase, AssertsCompiledSQL): "SELECT mytable.myid, mytable.name, mytable.description, " "foob.remotetable.rem_id, foob.remotetable.datatype_id, " "foob.remotetable.value FROM mytable JOIN foob.remotetable " - "ON foob.remotetable.rem_id = mytable.myid", + "ON mytable.myid = foob.remotetable.rem_id", + schema_translate_map=schema_translate_map + ) + + def test_schema_translate_aliases(self): + schema_translate_map = {None: 'bar'} + + m = MetaData() + table1 = Table( + 'mytable', m, Column('myid', Integer), + Column('name', String), + Column('description', String) + ) + table2 = Table( + 'myothertable', m, Column('otherid', Integer), + Column('othername', String), + ) + + alias = table1.alias() + + stmt = select([ + table2, alias + ]).select_from(table2.join(alias, table2.c.otherid == alias.c.myid)).\ + where(alias.c.name == 'foo') + + self.assert_compile( + stmt, + "SELECT bar.myothertable.otherid, bar.myothertable.othername, " + "mytable_1.myid, mytable_1.name, mytable_1.description " + "FROM bar.myothertable JOIN bar.mytable AS mytable_1 " + "ON bar.myothertable.otherid = mytable_1.myid " + "WHERE mytable_1.name = :name_1", schema_translate_map=schema_translate_map ) def test_schema_translate_crud(self): schema_translate_map = {"remote_owner": "foob", None: 'bar'} + m = MetaData() + table1 = Table( + 'mytable', m, + Column('myid', Integer), Column('name', String), + Column('description', String) + ) + self.assert_compile( table1.insert().values(description='foo'), "INSERT INTO bar.mytable (description) VALUES (:description)",