]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- changelog for pullreq github:139
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 21 Oct 2014 21:58:51 +0000 (17:58 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 21 Oct 2014 21:58:51 +0000 (17:58 -0400)
- add support for self-referential foreign keys to move over as well when
the table name is changed.

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

index 5a2852783c82ec4f721404ab525822145c47886b..f2b1b9a6c3989e25915ad0418e4faf83ae8e50fe 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, sql
+        :pullreq: github:139
+
+        Added a new parameter :paramref:`.Table.tometadata.name` to
+        the :meth:`.Table.tometadata` method.  Similar to
+        :paramref:`.Table.tometadata.schema`, this argument causes the newly
+        copied :class:`.Table` to take on the new name instead of
+        the existing one.  An interesting capability this adds is that of
+        copying a :class:`.Table` object to the *same* :class:`.MetaData`
+        target with a new name.  Pull request courtesy n.d. parker.
+
     .. change::
         :tags: bug, orm
         :pullreq: github:137
index 54cf1f5292063680e820620279c21ea3bacbeca0..96cabbf4f2c9777a17a2660d6aac461fae2de7e6 100644 (file)
@@ -786,7 +786,12 @@ class Table(DialectKWArgs, SchemaItem, TableClause):
          .. versionadded:: 0.9.2
 
         :param name: optional string name indicating the target table name.
-         If not specified or None, the table name is retained.
+         If not specified or None, the table name is retained.  This allows
+         a :class:`.Table` to be copied to the same :class:`.MetaData` target
+         with a new name.
+
+         .. versionadded:: 1.0.0
+
         """
         if name is None:
             name = self.name
@@ -1552,7 +1557,7 @@ class ForeignKey(DialectKWArgs, SchemaItem):
         )
         return self._schema_item_copy(fk)
 
-    def _get_colspec(self, schema=None):
+    def _get_colspec(self, schema=None, table_name=None):
         """Return a string based 'column specification' for this
         :class:`.ForeignKey`.
 
@@ -1562,7 +1567,15 @@ class ForeignKey(DialectKWArgs, SchemaItem):
         """
         if schema:
             _schema, tname, colname = self._column_tokens
+            if table_name is not None:
+                tname = table_name
             return "%s.%s.%s" % (schema, tname, colname)
+        elif table_name:
+            schema, tname, colname = self._column_tokens
+            if schema:
+                return "%s.%s.%s" % (schema, table_name, colname)
+            else:
+                return "%s.%s" % (table_name, colname)
         elif self._table_column is not None:
             return "%s.%s" % (
                 self._table_column.table.fullname, self._table_column.key)
@@ -2654,10 +2667,15 @@ class ForeignKeyConstraint(Constraint):
             event.listen(table.metadata, "before_drop",
                          ddl.DropConstraint(self, on=supports_alter))
 
-    def copy(self, schema=None, **kw):
+    def copy(self, schema=None, target_table=None, **kw):
         fkc = ForeignKeyConstraint(
             [x.parent.key for x in self._elements.values()],
-            [x._get_colspec(schema=schema)
+            [x._get_colspec(
+                schema=schema,
+                table_name=target_table.name
+                if target_table is not None
+                and x._table_key() == x.parent.table.key
+                else None)
              for x in self._elements.values()],
             name=self.name,
             onupdate=self.onupdate,
index 2328e7f73a60f7031d8ceff406400a13b68d6cc3..3c55242fd6349a096ae3899ea9f5730d0d707bc2 100644 (file)
@@ -722,6 +722,42 @@ class ToMetaDataTest(fixtures.TestBase, ComparesTables):
         eq_((table.key, table2.key),
             ('myschema.mytable', 'myschema.newtable'))
 
+    def test_change_name_selfref_fk_moves(self):
+        meta = MetaData()
+
+        referenced = Table('ref', meta,
+                           Column('id', Integer, primary_key=True),
+                           )
+        table = Table('mytable', meta,
+                      Column('id', Integer, primary_key=True),
+                      Column('parent_id', ForeignKey('mytable.id')),
+                      Column('ref_id', ForeignKey('ref.id'))
+                      )
+
+        table2 = table.tometadata(table.metadata, name='newtable')
+        assert table.metadata is table2.metadata
+        assert table2.c.ref_id.references(referenced.c.id)
+        assert table2.c.parent_id.references(table2.c.id)
+
+    def test_change_name_selfref_fk_moves_w_schema(self):
+        meta = MetaData()
+
+        referenced = Table('ref', meta,
+                           Column('id', Integer, primary_key=True),
+                           )
+        table = Table('mytable', meta,
+                      Column('id', Integer, primary_key=True),
+                      Column('parent_id', ForeignKey('mytable.id')),
+                      Column('ref_id', ForeignKey('ref.id'))
+                      )
+
+        table2 = table.tometadata(
+            table.metadata, name='newtable', schema='newschema')
+        ref2 = referenced.tometadata(table.metadata, schema='newschema')
+        assert table.metadata is table2.metadata
+        assert table2.c.ref_id.references(ref2.c.id)
+        assert table2.c.parent_id.references(table2.c.id)
+
     def _assert_fk(self, t2, schema, expected, referred_schema_fn=None):
         m2 = MetaData()
         existing_schema = t2.schema