summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2023-01-28 04:45:27 +0000
committerGerrit Code Review <gerrit@ci3.zzzcomputing.com>2023-01-28 04:45:27 +0000
commitecdaf44711f1feb002ad98b6e917cc575a1bd801 (patch)
treecb1a22031bd119e8f84e6ca99db19ecb026d93a9
parent75a66d8d41c882c1f480d1165880f95323b1c8d6 (diff)
parent31236f657f5febad85291f2a3344e3cf7af8501c (diff)
downloadsqlalchemy-ecdaf44711f1feb002ad98b6e917cc575a1bd801.tar.gz
Merge "fix regression based on mis-match of set/frozenset" into main
-rw-r--r--doc/build/changelog/unreleased_20/9164.rst9
-rw-r--r--lib/sqlalchemy/orm/mapper.py6
-rw-r--r--test/orm/inheritance/test_basic.py56
3 files changed, 70 insertions, 1 deletions
diff --git a/doc/build/changelog/unreleased_20/9164.rst b/doc/build/changelog/unreleased_20/9164.rst
new file mode 100644
index 000000000..b11a27fad
--- /dev/null
+++ b/doc/build/changelog/unreleased_20/9164.rst
@@ -0,0 +1,9 @@
+.. change::
+ :tags: bug, orm, regression
+ :tickets: 9164
+
+ Fixed regression where ORM models that used joined table inheritance with a
+ composite foreign key would encounter an internal error in the mapper
+ internals.
+
+
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index dd3aef8d6..a3b209e4a 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -3920,12 +3920,16 @@ class Mapper(
],
] = util.defaultdict(list)
+ def set_union(x, y):
+ return x.union(y)
+
for table in self._sorted_tables:
cols = set(table.c)
+
for m in self.iterate_to_root():
if m._inherits_equated_pairs and cols.intersection(
reduce(
- set.union, # type: ignore
+ set_union,
[l.proxy_set for l, r in m._inherits_equated_pairs],
)
):
diff --git a/test/orm/inheritance/test_basic.py b/test/orm/inheritance/test_basic.py
index 905f0c50d..37368f3ad 100644
--- a/test/orm/inheritance/test_basic.py
+++ b/test/orm/inheritance/test_basic.py
@@ -4,6 +4,7 @@ from sqlalchemy import column
from sqlalchemy import event
from sqlalchemy import exc as sa_exc
from sqlalchemy import ForeignKey
+from sqlalchemy import ForeignKeyConstraint
from sqlalchemy import func
from sqlalchemy import inspect
from sqlalchemy import Integer
@@ -22,6 +23,8 @@ from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import deferred
from sqlalchemy.orm import exc as orm_exc
from sqlalchemy.orm import joinedload
+from sqlalchemy.orm import Mapped
+from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import object_mapper
from sqlalchemy.orm import polymorphic_union
from sqlalchemy.orm import relationship
@@ -4056,6 +4059,59 @@ class UnexpectedPolymorphicIdentityTest(fixtures.DeclarativeMappedTest):
)
+class CompositeJoinedInTest(fixtures.DeclarativeMappedTest):
+ """test #9164"""
+
+ run_setup_mappers = "once"
+ __dialect__ = "default"
+
+ @classmethod
+ def setup_classes(cls):
+ Base = cls.DeclarativeBasic
+
+ class A(fixtures.ComparableEntity, Base):
+ __tablename__ = "table_a"
+
+ order_id: Mapped[str] = mapped_column(primary_key=True)
+ _sku: Mapped[str] = mapped_column(primary_key=True)
+
+ __mapper_args__ = {
+ "polymorphic_identity": "a",
+ "polymorphic_on": "type",
+ }
+
+ type: Mapped[str]
+
+ def __init__(self, order_id: str, sku: str):
+ self.order_id = order_id
+ self._sku = sku
+
+ class B(A):
+ __tablename__ = "table_b"
+
+ _increment_id: Mapped[str] = mapped_column(primary_key=True)
+ _sku: Mapped[str] = mapped_column(primary_key=True)
+
+ __table_args__ = (
+ ForeignKeyConstraint(
+ ["_increment_id", "_sku"],
+ ["table_a.order_id", "table_a._sku"],
+ ),
+ )
+
+ __mapper_args__ = {"polymorphic_identity": "b"}
+
+ def test_round_trip(self):
+ B = self.classes.B
+
+ sess = fixture_session()
+ b1 = B(order_id="iid1", sku="sku1")
+ sess.add(b1)
+ sess.commit()
+
+ eq_(sess.scalar(select(B)), b1)
+
+
class NameConflictTest(fixtures.MappedTest):
@classmethod
def define_tables(cls, metadata):