<p dir="auto"><strong>Migrated issue, originally created by Denis Otkidach (<a href="https://github.com/ods">@ods</a>)</strong></p>
<p dir="auto">The list of tables is the only list of mapped data that automatically collected in <code class="notranslate">MetaData</code> object. So it's the simplest way to construct session with multiple connections where separate connection is used for each metadata. <code class="notranslate">Session.get_bind()</code> does look up based on <code class="notranslate">mapper.mapped_table</code>. This works for simple mapped classes, but doesn't work for classes mapped to join like subclasses with joined table inheritance.</p>
<p dir="auto">Test case:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from sqlalchemy import Column, Integer, ForeignKey, create_engine, orm
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class A(Base):
    __tablename__ = 'A'
    id = Column(Integer, primary_key=True)
    type = Column(Integer, nullable=False)
    __mapper_args__ = {'polymorphic_on': type}

class B(A):
    __tablename__ = 'B'
    id = Column(ForeignKey(A.id), primary_key=True)
    __mapper_args__ = {'polymorphic_identity': 1}

engine = create_engine('sqlite://')
binds = {table: engine for table in Base.metadata.sorted_tables}
db = orm.sessionmaker(binds=binds)()

print db.get_bind(A) # Engine(sqlite://)
print db.get_bind(B) # sqlalchemy.exc.UnboundExecutionError: Could not locate a bind configured on mapper Mapper|B|B or this Session"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">sqlalchemy</span> <span class="pl-k">import</span> <span class="pl-v">Column</span>, <span class="pl-v">Integer</span>, <span class="pl-v">ForeignKey</span>, <span class="pl-s1">create_engine</span>, <span class="pl-s1">orm</span>
<span class="pl-k">from</span> <span class="pl-s1">sqlalchemy</span>.<span class="pl-s1">ext</span>.<span class="pl-s1">declarative</span> <span class="pl-k">import</span> <span class="pl-s1">declarative_base</span>

<span class="pl-v">Base</span> <span class="pl-c1">=</span> <span class="pl-en">declarative_base</span>()

<span class="pl-k">class</span> <span class="pl-v">A</span>(<span class="pl-v">Base</span>):
    <span class="pl-s1">__tablename__</span> <span class="pl-c1">=</span> <span class="pl-s">'A'</span>
    <span class="pl-s1">id</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>(<span class="pl-v">Integer</span>, <span class="pl-s1">primary_key</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
    <span class="pl-s1">type</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>(<span class="pl-v">Integer</span>, <span class="pl-s1">nullable</span><span class="pl-c1">=</span><span class="pl-c1">False</span>)
    <span class="pl-s1">__mapper_args__</span> <span class="pl-c1">=</span> {<span class="pl-s">'polymorphic_on'</span>: <span class="pl-s1">type</span>}

<span class="pl-k">class</span> <span class="pl-v">B</span>(<span class="pl-v">A</span>):
    <span class="pl-s1">__tablename__</span> <span class="pl-c1">=</span> <span class="pl-s">'B'</span>
    <span class="pl-s1">id</span> <span class="pl-c1">=</span> <span class="pl-v">Column</span>(<span class="pl-v">ForeignKey</span>(<span class="pl-v">A</span>.<span class="pl-s1">id</span>), <span class="pl-s1">primary_key</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
    <span class="pl-s1">__mapper_args__</span> <span class="pl-c1">=</span> {<span class="pl-s">'polymorphic_identity'</span>: <span class="pl-c1">1</span>}

<span class="pl-s1">engine</span> <span class="pl-c1">=</span> <span class="pl-en">create_engine</span>(<span class="pl-s">'sqlite://'</span>)
<span class="pl-s1">binds</span> <span class="pl-c1">=</span> {<span class="pl-s1">table</span>: <span class="pl-s1">engine</span> <span class="pl-k">for</span> <span class="pl-s1">table</span> <span class="pl-c1">in</span> <span class="pl-v">Base</span>.<span class="pl-s1">metadata</span>.<span class="pl-s1">sorted_tables</span>}
<span class="pl-s1">db</span> <span class="pl-c1">=</span> <span class="pl-s1">orm</span>.<span class="pl-en">sessionmaker</span>(<span class="pl-s1">binds</span><span class="pl-c1">=</span><span class="pl-s1">binds</span>)()

<span class="pl-k">print</span> <span class="pl-s1">db</span>.<span class="pl-en">get_bind</span>(<span class="pl-v">A</span>) <span class="pl-c"># Engine(sqlite://)</span>
<span class="pl-k">print</span> <span class="pl-s1">db</span>.<span class="pl-en">get_bind</span>(<span class="pl-v">B</span>) <span class="pl-c"># sqlalchemy.exc.UnboundExecutionError: Could not locate a bind configured on mapper Mapper|B|B or this Session</span></pre></div>
<p dir="auto">Should we iterate through tables used in <code class="notranslate">Join</code> object <code class="notranslate">mapper.mapped_table</code> refers to?</p>
<p dir="auto"><strong>Migrated issue, originally created by Michael Bayer (<a href="https://github.com/zzzeek">@zzzeek</a>)</strong></p>
<p dir="auto">right now session.__binds uses mappers completely.  This makes it impossible to feed in abstract classes and also because it links to base_mapper it's not possible to change the bind along a class hierarchy either (like a concrete hierarchy).</p>
<p dir="auto">propose that __binds stores classes directly, and this can likely be a fallback in addition to what we have now.  this is kind of a proof of concept</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 89d9946..f63adfb 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -636,13 +636,20 @@ class Session(_SessionClassMethods):

         if binds is not None:
             for mapperortable, bind in binds.items():
-                insp = inspect(mapperortable)
-                if insp.is_selectable:
-                    self.bind_table(mapperortable, bind)
-                elif insp.is_mapper:
-                    self.bind_mapper(mapperortable, bind)
+                try:
+                    insp = inspect(mapperortable)
+                except exc.NoInspectionAvailable:
+                    if isinstance(mapperortable, type):
+                        self.bind_cls(mapperortable, bind)
+                    else:
+                        raise exc.ArgumentError(&quot;Not acceptable bind target: %s&quot; % mapperortable)
                 else:
-                    assert False
+                    if insp.is_selectable:
+                        self.bind_table(mapperortable, bind)
+                    elif insp.is_mapper:
+                        self.bind_mapper(mapperortable, bind)
+                    else:
+                        assert False


         if not self.autocommit:
@@ -1039,6 +1046,17 @@ class Session(_SessionClassMethods):
         for t in mapper._all_tables:
             self.__binds[t] = bind

+    def bind_class(self, cls, bind):
+        &quot;&quot;&quot;Bind operations for an unmapped class to a Connectable.
+
+        The behavior here is that a subclass of cls which is mapped
+        will be linked to this bind.
+
+        .. versionadded:: 1.0
+
+        &quot;&quot;&quot;
+        self.__binds[cls] = bind
+
     def bind_table(self, table, bind):
         &quot;&quot;&quot;Bind operations on a Table to a Connectable.

@@ -1124,6 +1142,12 @@ class Session(_SessionClassMethods):
                     return self.__binds[c_mapper.base_mapper]
                 elif c_mapper.mapped_table in self.__binds:
                     return self.__binds[c_mapper.mapped_table]
+                else:
+                    for cls in c_mapper.class_.__mro__:
+                        if cls in self.__binds:
+                            bind = self.__binds[cls]
+                            self.bind_mapper(c_mapper, bind)
+                            return bind
             if clause is not None:
                 for t in sql_util.find_tables(clause, include_crud=True):
                     if t in self.__binds:
"><pre class="notranslate"><code class="notranslate">diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index 89d9946..f63adfb 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -636,13 +636,20 @@ class Session(_SessionClassMethods):

         if binds is not None:
             for mapperortable, bind in binds.items():
-                insp = inspect(mapperortable)
-                if insp.is_selectable:
-                    self.bind_table(mapperortable, bind)
-                elif insp.is_mapper:
-                    self.bind_mapper(mapperortable, bind)
+                try:
+                    insp = inspect(mapperortable)
+                except exc.NoInspectionAvailable:
+                    if isinstance(mapperortable, type):
+                        self.bind_cls(mapperortable, bind)
+                    else:
+                        raise exc.ArgumentError("Not acceptable bind target: %s" % mapperortable)
                 else:
-                    assert False
+                    if insp.is_selectable:
+                        self.bind_table(mapperortable, bind)
+                    elif insp.is_mapper:
+                        self.bind_mapper(mapperortable, bind)
+                    else:
+                        assert False


         if not self.autocommit:
@@ -1039,6 +1046,17 @@ class Session(_SessionClassMethods):
         for t in mapper._all_tables:
             self.__binds[t] = bind

+    def bind_class(self, cls, bind):
+        """Bind operations for an unmapped class to a Connectable.
+
+        The behavior here is that a subclass of cls which is mapped
+        will be linked to this bind.
+
+        .. versionadded:: 1.0
+
+        """
+        self.__binds[cls] = bind
+
     def bind_table(self, table, bind):
         """Bind operations on a Table to a Connectable.

@@ -1124,6 +1142,12 @@ class Session(_SessionClassMethods):
                     return self.__binds[c_mapper.base_mapper]
                 elif c_mapper.mapped_table in self.__binds:
                     return self.__binds[c_mapper.mapped_table]
+                else:
+                    for cls in c_mapper.class_.__mro__:
+                        if cls in self.__binds:
+                            bind = self.__binds[cls]
+                            self.bind_mapper(c_mapper, bind)
+                            return bind
             if clause is not None:
                 for t in sql_util.find_tables(clause, include_crud=True):
                     if t in self.__binds:

</code></pre></div>
<p dir="auto">the tests here also need a rework, with an emphasis on straight unit testing of get_bind().  test_session -&gt; BindTest is really just integration tests.</p>