@@ -38,6 +38,9 @@ def get_bind( # type: ignore[override]
3838 """Select an engine based on the ``bind_key`` of the metadata associated with
3939 the model or table being queried. If no bind key is set, uses the default bind.
4040
41+ .. versionchanged:: 3.0.3
42+ Fix finding the bind for a joined inheritance model.
43+
4144 .. versionchanged:: 3.0
4245 The implementation more closely matches the base SQLAlchemy implementation.
4346
@@ -47,6 +50,8 @@ def get_bind( # type: ignore[override]
4750 if bind is not None :
4851 return bind
4952
53+ engines = self ._db .engines
54+
5055 if mapper is not None :
5156 try :
5257 mapper = sa .inspect (mapper )
@@ -56,26 +61,42 @@ def get_bind( # type: ignore[override]
5661
5762 raise
5863
59- clause = mapper .persist_selectable
64+ engine = _clause_to_engine ( mapper .local_table , engines )
6065
61- engines = self ._db .engines
62-
63- if isinstance (clause , sa .Table ) and "bind_key" in clause .metadata .info :
64- key = clause .metadata .info ["bind_key" ]
66+ if engine is not None :
67+ return engine
6568
66- if key not in engines :
67- raise sa .exc .UnboundExecutionError (
68- f"Bind key '{ key } ' is not in 'SQLALCHEMY_BINDS' config."
69- )
69+ if clause is not None :
70+ engine = _clause_to_engine (clause , engines )
7071
71- return engines [key ]
72+ if engine is not None :
73+ return engine
7274
7375 if None in engines :
7476 return engines [None ]
7577
7678 return super ().get_bind (mapper = mapper , clause = clause , bind = bind , ** kwargs )
7779
7880
81+ def _clause_to_engine (
82+ clause : t .Any | None , engines : t .Mapping [str | None , sa .engine .Engine ]
83+ ) -> sa .engine .Engine | None :
84+ """If the clause is a table, return the engine associated with the table's
85+ metadata's bind key.
86+ """
87+ if isinstance (clause , sa .Table ) and "bind_key" in clause .metadata .info :
88+ key = clause .metadata .info ["bind_key" ]
89+
90+ if key not in engines :
91+ raise sa .exc .UnboundExecutionError (
92+ f"Bind key '{ key } ' is not in 'SQLALCHEMY_BINDS' config."
93+ )
94+
95+ return engines [key ]
96+
97+ return None
98+
99+
79100def _app_ctx_id () -> int :
80101 """Get the id of the current Flask application context for the session scope."""
81102 return id (app_ctx ._get_current_object ()) # type: ignore[attr-defined]
0 commit comments