summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/engine/reflection.py27
-rw-r--r--lib/sqlalchemy/exc.py9
-rw-r--r--lib/sqlalchemy/sql/schema.py24
3 files changed, 39 insertions, 21 deletions
diff --git a/lib/sqlalchemy/engine/reflection.py b/lib/sqlalchemy/engine/reflection.py
index 7e1fca0e5..941590b13 100644
--- a/lib/sqlalchemy/engine/reflection.py
+++ b/lib/sqlalchemy/engine/reflection.py
@@ -1786,16 +1786,25 @@ class Inspector(inspection.Inspectable["Inspector"]):
else:
options = {}
- table.append_constraint(
- sa_schema.ForeignKeyConstraint(
- constrained_columns,
- refspec,
- conname,
- link_to_name=True,
- comment=fkey_d.get("comment"),
- **options,
+ try:
+ table.append_constraint(
+ sa_schema.ForeignKeyConstraint(
+ constrained_columns,
+ refspec,
+ conname,
+ link_to_name=True,
+ comment=fkey_d.get("comment"),
+ **options,
+ )
+ )
+ except exc.ConstraintColumnNotFoundError:
+ util.warn(
+ f"On reflected table {table.name}, skipping reflection of "
+ "foreign key constraint "
+ f"{conname}; one or more subject columns within "
+ f"name(s) {', '.join(constrained_columns)} are not "
+ "present in the table"
)
- )
_index_sort_exprs = {
"asc": operators.asc_op,
diff --git a/lib/sqlalchemy/exc.py b/lib/sqlalchemy/exc.py
index eb633ec8c..82d9d31ce 100644
--- a/lib/sqlalchemy/exc.py
+++ b/lib/sqlalchemy/exc.py
@@ -165,6 +165,15 @@ class AmbiguousForeignKeysError(ArgumentError):
between two selectables during a join."""
+class ConstraintColumnNotFoundError(ArgumentError):
+ """raised when a constraint refers to a string column name that
+ is not present in the table being constrained.
+
+ .. versionadded:: 2.0
+
+ """
+
+
class CircularDependencyError(SQLAlchemyError):
"""Raised by topological sorts when a circular dependency is detected.
diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py
index 62e962a32..5083940f0 100644
--- a/lib/sqlalchemy/sql/schema.py
+++ b/lib/sqlalchemy/sql/schema.py
@@ -4014,10 +4014,17 @@ class ColumnCollectionMixin:
assert len(result) == len(self._pending_colargs)
return result
else:
- return [
- parent.c[col] if isinstance(col, str) else col
- for col in self._pending_colargs
- ]
+ try:
+ return [
+ parent.c[col] if isinstance(col, str) else col
+ for col in self._pending_colargs
+ ]
+ except KeyError as ke:
+ raise exc.ConstraintColumnNotFoundError(
+ f"Can't create {self.__class__.__name__} "
+ f"on table '{parent.description}': no column "
+ f"named '{ke.args[0]}' is present."
+ ) from ke
def _set_parent(self, parent: SchemaEventTarget, **kw: Any) -> None:
assert isinstance(parent, (Table, Column))
@@ -4519,14 +4526,7 @@ class ForeignKeyConstraint(ColumnCollectionConstraint):
assert isinstance(table, Table)
Constraint._set_parent(self, table)
- try:
- ColumnCollectionConstraint._set_parent(self, table)
- except KeyError as ke:
- raise exc.ArgumentError(
- "Can't create ForeignKeyConstraint "
- "on table '%s': no column "
- "named '%s' is present." % (table.description, ke.args[0])
- ) from ke
+ ColumnCollectionConstraint._set_parent(self, table)
for col, fk in zip(self._columns, self.elements):
if not hasattr(fk, "parent") or fk.parent is not col: