@@ -38,6 +38,9 @@ def get_bind( # type: ignore[override]
38
38
"""Select an engine based on the ``bind_key`` of the metadata associated with
39
39
the model or table being queried. If no bind key is set, uses the default bind.
40
40
41
+ .. versionchanged:: 3.0.3
42
+ Fix finding the bind for a joined inheritance model.
43
+
41
44
.. versionchanged:: 3.0
42
45
The implementation more closely matches the base SQLAlchemy implementation.
43
46
@@ -47,6 +50,8 @@ def get_bind( # type: ignore[override]
47
50
if bind is not None :
48
51
return bind
49
52
53
+ engines = self ._db .engines
54
+
50
55
if mapper is not None :
51
56
try :
52
57
mapper = sa .inspect (mapper )
@@ -56,26 +61,42 @@ def get_bind( # type: ignore[override]
56
61
57
62
raise
58
63
59
- clause = mapper .persist_selectable
64
+ engine = _clause_to_engine ( mapper .local_table , engines )
60
65
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
65
68
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 )
70
71
71
- return engines [key ]
72
+ if engine is not None :
73
+ return engine
72
74
73
75
if None in engines :
74
76
return engines [None ]
75
77
76
78
return super ().get_bind (mapper = mapper , clause = clause , bind = bind , ** kwargs )
77
79
78
80
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
+
79
100
def _app_ctx_id () -> int :
80
101
"""Get the id of the current Flask application context for the session scope."""
81
102
return id (app_ctx ._get_current_object ()) # type: ignore[attr-defined]
0 commit comments