]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Remove same-named relationship warning
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 19 Jul 2016 16:36:21 +0000 (12:36 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 19 Jul 2016 16:36:21 +0000 (12:36 -0400)
Removed a warning that dates back to 0.4 which emits when a same-named
relationship is placed on two mappers that inherits via joined or
single table inheritance.   The warning does not apply to the
current unit of work implementation.

Change-Id: If528ec3a2f4dc60712d9044fd1ec6c4dfbf0eadb
Fixes: #3749
doc/build/changelog/changelog_11.rst
doc/build/changelog/migration_11.rst
lib/sqlalchemy/orm/relationships.py
test/orm/inheritance/test_relationship.py

index 593cbb3caf11d2705d8ad031ccf9e275e3f4bfc8..982119982765c78453b1b17005fb189e496ca82d 100644 (file)
 .. changelog::
     :version: 1.1.0b3
 
+    .. change::
+        :tags: change, orm
+        :tickets: 3749
+
+        Removed a warning that dates back to 0.4 which emits when a same-named
+        relationship is placed on two mappers that inherits via joined or
+        single table inheritance.   The warning does not apply to the
+        current unit of work implementation.
+
+        .. seealso::
+
+            :ref:`change_3749`
+
+
     .. change::
         :tags: bug, sql
         :tickets: 3745
index d0f73b726747a9ff086349690c2815ff251c3ada..36c5ead3c22ca49684bafabe920432a95b7176af 100644 (file)
@@ -588,6 +588,47 @@ for an attribute being replaced.
 
 :ticket:`3630`
 
+.. _change_3749:
+
+Same-named relationships on inheriting mappers no longer warn
+--------------------------------------------------------------
+
+When creating two mappers in an inheritance scenario, placing a relationship
+on both with the same name would emit the warning
+"relationship '<name>' on mapper <name> supersedes the same relationship
+on inherited mapper '<name>'; this can cause dependency issues during flush".
+An example is as follows::
+
+    class A(Base):
+        __tablename__ = 'a'
+        id = Column(Integer, primary_key=True)
+        bs = relationship("B")
+
+
+    class ASub(A):
+        __tablename__ = 'a_sub'
+        id = Column(Integer, ForeignKey('a.id'), primary_key=True)
+        bs = relationship("B")
+
+
+    class B(Base):
+        __tablename__ = 'b'
+        id = Column(Integer, primary_key=True)
+        a_id = Column(ForeignKey('a.id'))
+
+
+This warning dates back to the 0.4 series in 2007 and is based on a version of
+the unit of work code that has since been entirely rewritten. Currently, there
+is no known issue with the same-named relationships being placed on a base
+class and a descendant class, so the warning is lifted.   However, note that
+this use case is likely not prevalent in real world use due to the warning.
+While rudimentary test support is added for this use case, it is possible that
+some new issue with this pattern may be identified.
+
+.. versionadded:: 1.1.0b3
+
+:ticket:`3749`
+
 .. _change_3653:
 
 Hybrid properties and methods now propagate the docstring as well as .info
index 4d5e5d29dbc5c7aa4da17bb8f526b58a53fdf15a..e8a2992b0635a1eac6d9b9f5ba07e721c9e1160f 100644 (file)
@@ -1742,17 +1742,6 @@ class RelationshipProperty(StrategizedProperty):
                 (self.key, self.parent.class_.__name__,
                  self.parent.class_.__name__))
 
-        # check for conflicting relationship() on superclass
-        if not self.parent.concrete:
-            for inheriting in self.parent.iterate_to_root():
-                if inheriting is not self.parent \
-                        and inheriting.has_property(self.key):
-                    util.warn("Warning: relationship '%s' on mapper "
-                              "'%s' supersedes the same relationship "
-                              "on inherited mapper '%s'; this can "
-                              "cause dependency issues during flush"
-                              % (self.key, self.parent, inheriting))
-
     def _get_cascade(self):
         """Return the current cascade setting for this
         :class:`.RelationshipProperty`.
index 379d8f7e46a198ec0856bd454c0da2afbda30bef..0bbb138b04b87fdd1fa73b5cd172d607361fca53 100644 (file)
@@ -1856,4 +1856,73 @@ class MultipleAdaptUsesEntityOverTableTest(AssertsCompiledSQL, fixtures.MappedTe
             "(a AS a_1 JOIN c AS c_1 ON a_1.id = c_1.id) ON c_1.bid = b.id "
             "JOIN (a AS a_2 JOIN d AS d_1 ON a_2.id = d_1.id) "
             "ON d_1.cid = c_1.id"
-        )
\ No newline at end of file
+        )
+
+
+class SameNameOnJoined(fixtures.MappedTest):
+
+    run_setup_mappers = 'once'
+    run_inserts = None
+    run_deletes = None
+
+    @classmethod
+    def define_tables(cls, metadata):
+        Table(
+            'a', metadata,
+            Column(
+                'id', Integer, primary_key=True,
+                test_needs_autoincrement=True)
+        )
+        Table(
+            'a_sub', metadata,
+            Column('id', Integer, ForeignKey('a.id'), primary_key=True)
+        )
+        Table(
+            'b', metadata,
+            Column('id', Integer, primary_key=True,
+                   test_needs_autoincrement=True),
+            Column('a_id', Integer, ForeignKey('a.id'))
+
+        )
+
+    @classmethod
+    def setup_mappers(cls):
+        class A(cls.Comparable):
+            pass
+
+        class ASub(A):
+            pass
+
+        class B(cls.Comparable):
+            pass
+
+        mapper(A, cls.tables.a, properties={
+            'bs': relationship(B, cascade="all, delete-orphan")
+        })
+
+        mapper(ASub, cls.tables.a_sub, inherits=A, properties={
+            'bs': relationship(B, cascade="all, delete-orphan")
+        })
+
+        mapper(B, cls.tables.b)
+
+    def test_persist(self):
+        A, ASub, B = self.classes('A', 'ASub', 'B')
+
+        s = Session(testing.db)
+
+        s.add_all([
+            A(bs=[B(), B(), B()]),
+            ASub(bs=[B(), B(), B()])
+        ])
+        s.commit()
+
+        eq_(s.query(B).count(), 6)
+
+        for a in s.query(A):
+            eq_(len(a.bs), 3)
+            s.delete(a)
+
+        s.commit()
+
+        eq_(s.query(B).count(), 0)