From: Mike Bayer Date: Tue, 21 Oct 2014 21:58:51 +0000 (-0400) Subject: - changelog for pullreq github:139 X-Git-Tag: rel_1_0_0b1~70^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56d5732fbdf09508784df6dc4c04e5b39ac6be85;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - changelog for pullreq github:139 - add support for self-referential foreign keys to move over as well when the table name is changed. --- diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index 5a2852783c..f2b1b9a6c3 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -21,6 +21,18 @@ 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 diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 54cf1f5292..96cabbf4f2 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -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, diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 2328e7f73a..3c55242fd6 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -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