]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added a new accessor :attr:`.Table.foreign_key_constraints`
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 1 Jan 2015 18:24:32 +0000 (13:24 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 1 Jan 2015 18:39:42 +0000 (13:39 -0500)
to complement the :attr:`.Table.foreign_keys` collection,
as well as :attr:`.ForeignKeyConstraint.referred_table`.

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/sql/schema.py
test/sql/test_metadata.py

index 3564ecde184aadfa0f6121f160d4117a81437b80..4b3a17367f946a1a1f7f23cab706f99ad0bd830a 100644 (file)
     series as well.  For changes that are specific to 1.0 with an emphasis
     on compatibility concerns, see :doc:`/changelog/migration_10`.
 
+    .. change::
+        :tags: feature, schema
+
+        Added a new accessor :attr:`.Table.foreign_key_constraints`
+        to complement the :attr:`.Table.foreign_keys` collection,
+        as well as :attr:`.ForeignKeyConstraint.referred_table`.
+
     .. change::
         :tags: bug, sqlite
         :tickets: 3244, 3261
index b134b305395ca4b0b0958451779838fd13ca282b..71a0c2780a814d11205c86c7eef536fc1db85df6 100644 (file)
@@ -516,6 +516,19 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
         """
         return sorted(self.constraints, key=lambda c: c._creation_order)
 
+    @property
+    def foreign_key_constraints(self):
+        """:class:`.ForeignKeyConstraint` objects referred to by this
+        :class:`.Table`.
+
+        This list is produced from the collection of :class:`.ForeignKey`
+        objects currently associated.
+
+        .. versionadded:: 1.0.0
+
+        """
+        return set(fkc.constraint for fkc in self.foreign_keys)
+
     def _init_existing(self, *args, **kwargs):
         autoload_with = kwargs.pop('autoload_with', None)
         autoload = kwargs.pop('autoload', autoload_with is not None)
@@ -2632,6 +2645,20 @@ class ForeignKeyConstraint(ColumnCollectionConstraint):
         else:
             return None
 
+    @property
+    def referred_table(self):
+        """The :class:`.Table` object to which this
+        :class:`.ForeignKeyConstraint references.
+
+        This is a dynamically calculated attribute which may not be available
+        if the constraint and/or parent table is not yet associated with
+        a metadata collection that contains the referred table.
+
+        .. versionadded:: 1.0.0
+
+        """
+        return self.elements[0].column.table
+
     def _validate_dest_table(self, table):
         table_keys = set([elem._table_key()
                           for elem in self.elements])
index 52ecf88c54e669bbbca948bf12bb5a41f5035968..cc7d0eb4f50684ed509d8ff6901789111b6b5b79 100644 (file)
@@ -1196,6 +1196,30 @@ class TableTest(fixtures.TestBase, AssertsCompiledSQL):
             t.info['bar'] = 'zip'
             assert t.info['bar'] == 'zip'
 
+    def test_foreign_key_constraints_collection(self):
+        metadata = MetaData()
+        t1 = Table('foo', metadata, Column('a', Integer))
+        eq_(t1.foreign_key_constraints, set())
+
+        fk1 = ForeignKey('q.id')
+        fk2 = ForeignKey('j.id')
+        fk3 = ForeignKeyConstraint(['b', 'c'], ['r.x', 'r.y'])
+
+        t1.append_column(Column('b', Integer, fk1))
+        eq_(
+            t1.foreign_key_constraints,
+            set([fk1.constraint]))
+
+        t1.append_column(Column('c', Integer, fk2))
+        eq_(
+            t1.foreign_key_constraints,
+            set([fk1.constraint, fk2.constraint]))
+
+        t1.append_constraint(fk3)
+        eq_(
+            t1.foreign_key_constraints,
+            set([fk1.constraint, fk2.constraint, fk3]))
+
     def test_c_immutable(self):
         m = MetaData()
         t1 = Table('t', m, Column('x', Integer), Column('y', Integer))
@@ -1947,6 +1971,22 @@ class ConstraintTest(fixtures.TestBase):
         assert s1.c.a.references(t1.c.a)
         assert not s1.c.a.references(t1.c.b)
 
+    def test_referred_table_accessor(self):
+        t1, t2, t3 = self._single_fixture()
+        fkc = list(t2.foreign_key_constraints)[0]
+        is_(fkc.referred_table, t1)
+
+    def test_referred_table_accessor_not_available(self):
+        t1 = Table('t', MetaData(), Column('x', ForeignKey('q.id')))
+        fkc = list(t1.foreign_key_constraints)[0]
+        assert_raises_message(
+            exc.InvalidRequestError,
+            "Foreign key associated with column 't.x' could not find "
+            "table 'q' with which to generate a foreign key to target "
+            "column 'id'",
+            getattr, fkc, "referred_table"
+        )
+
     def test_related_column_not_present_atfirst_ok(self):
         m = MetaData()
         base_table = Table("base", m,