From bef89a244002e955b6971d7c788880e1d61593d8 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 14 Nov 2012 00:51:38 -0500 Subject: [PATCH] Fixed :meth:`.MetaData.reflect` to correctly use the given :class:`.Connection`, if given, without opening a second connection from that connection's :class:`.Engine`. [ticket:2604] --- doc/build/changelog/changelog_07.rst | 9 +++++++++ lib/sqlalchemy/schema.py | 18 ++++++++++++------ test/engine/test_reflection.py | 25 +++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/doc/build/changelog/changelog_07.rst b/doc/build/changelog/changelog_07.rst index 0bcdbca83..4623d08ef 100644 --- a/doc/build/changelog/changelog_07.rst +++ b/doc/build/changelog/changelog_07.rst @@ -8,6 +8,15 @@ :version: 0.7.10 :released: + .. change:: + :tags: engine, bug + :tickets: 2604 + + Fixed :meth:`.MetaData.reflect` to correctly use + the given :class:`.Connection`, if given, without + opening a second connection from that connection's + :class:`.Engine`. + .. change:: :tags: mssql, bug :tickets:2607 diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index b8c74c53c..8545a0f9b 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -2485,13 +2485,20 @@ class MetaData(SchemaItem): arguments and should return a true value for any table to reflect. """ - reflect_opts = {'autoload': True} if bind is None: bind = _bind_or_error(self) - conn = None + + if bind.engine is not bind: + conn = bind + close = False else: - reflect_opts['autoload_with'] = bind conn = bind.contextual_connect() + close = True + + reflect_opts = { + 'autoload': True, + 'autoload_with': bind + } if schema is None: schema = self.schema @@ -2504,7 +2511,7 @@ class MetaData(SchemaItem): connection=conn)) if views: available.update( - bind.dialect.get_view_names(conn or bind, schema) + bind.dialect.get_view_names(conn, schema) ) current = set(self.tables.iterkeys()) @@ -2527,8 +2534,7 @@ class MetaData(SchemaItem): for name in load: Table(name, self, **reflect_opts) finally: - if conn is not None and \ - conn is not bind: + if close: conn.close() def append_ddl_listener(self, event_name, listener): diff --git a/test/engine/test_reflection.py b/test/engine/test_reflection.py index f2fe9e349..e034402c2 100644 --- a/test/engine/test_reflection.py +++ b/test/engine/test_reflection.py @@ -700,6 +700,31 @@ class ReflectionTest(fixtures.TestBase, ComparesTables): table_b2 = Table('false', meta2, autoload=True) table_c2 = Table('is', meta2, autoload=True) + @testing.provide_metadata + def _test_reflect_uses_bind(self, fn): + from sqlalchemy.pool import AssertionPool + e = engines.testing_engine(options={"poolclass": AssertionPool}) + fn(e) + + def test_reflect_uses_bind_constructor_conn(self): + self._test_reflect_uses_bind(lambda e: MetaData(e.connect(), + reflect=True)) + + def test_reflect_uses_bind_constructor_engine(self): + self._test_reflect_uses_bind(lambda e: MetaData(e, reflect=True)) + + def test_reflect_uses_bind_constructor_conn_reflect(self): + self._test_reflect_uses_bind(lambda e: MetaData(e.connect()).reflect()) + + def test_reflect_uses_bind_constructor_engine_reflect(self): + self._test_reflect_uses_bind(lambda e: MetaData(e).reflect()) + + def test_reflect_uses_bind_conn_reflect(self): + self._test_reflect_uses_bind(lambda e: MetaData().reflect(e.connect())) + + def test_reflect_uses_bind_engine_reflect(self): + self._test_reflect_uses_bind(lambda e: MetaData().reflect(e)) + @testing.provide_metadata def test_reflect_all(self): existing = testing.db.table_names()