summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2014-10-21 17:58:51 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2014-10-21 17:58:51 -0400
commit56d5732fbdf09508784df6dc4c04e5b39ac6be85 (patch)
tree0f69a2bfea355cac186dcc44847f8e49ace213cd
parent0ae140aa989ea3868c01af23adfcdcc79b7cb22e (diff)
downloadsqlalchemy-56d5732fbdf09508784df6dc4c04e5b39ac6be85.tar.gz
- changelog for pullreq github:139
- add support for self-referential foreign keys to move over as well when the table name is changed.
-rw-r--r--doc/build/changelog/changelog_10.rst12
-rw-r--r--lib/sqlalchemy/sql/schema.py26
-rw-r--r--test/sql/test_metadata.py36
3 files changed, 70 insertions, 4 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst
index 5a2852783..f2b1b9a6c 100644
--- a/doc/build/changelog/changelog_10.rst
+++ b/doc/build/changelog/changelog_10.rst
@@ -22,6 +22,18 @@
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 54cf1f529..96cabbf4f 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 2328e7f73..3c55242fd 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