]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Lookup index columns in parent table by key for copy
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 15 Jun 2018 02:56:21 +0000 (22:56 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 15 Jun 2018 02:56:21 +0000 (22:56 -0400)
Fixed regression in 1.2 due to :ticket:`4147` where a :class:`.Table` that
has had some of its indexed columns redefined with new ones, as would occur
when overriding columns during reflection or when using
:paramref:`.Table.extend_existing`, such that the :meth:`.Table.tometadata`
method would fail when attempting to copy those indexes as they still
referred to the replaced column.   The copy logic now accommodates for this
condition.

Change-Id: I521aa2c9f3baa0e84598bbdd6ffe4bf07b6e3ba8
Fixes: #4279
doc/build/changelog/unreleased_12/4279.rst [new file with mode: 0644]
lib/sqlalchemy/sql/schema.py
test/sql/test_metadata.py

diff --git a/doc/build/changelog/unreleased_12/4279.rst b/doc/build/changelog/unreleased_12/4279.rst
new file mode 100644 (file)
index 0000000..f7cedbf
--- /dev/null
@@ -0,0 +1,12 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 4279
+
+    Fixed regression in 1.2 due to :ticket:`4147` where a :class:`.Table` that
+    has had some of its indexed columns redefined with new ones, as would occur
+    when overriding columns during reflection or when using
+    :paramref:`.Table.extend_existing`, such that the :meth:`.Table.tometadata`
+    method would fail when attempting to copy those indexes as they still
+    referred to the replaced column.   The copy logic now accommodates for this
+    condition.
+
index 1d6bc4c61fec52b969226b804720922e241e6e6a..88050b87e33c40cf8c0de04ca08d5741505fef3d 100644 (file)
@@ -69,7 +69,8 @@ def _get_table_key(name, schema):
 # break an import cycle
 def _copy_expression(expression, source_table, target_table):
     def replace(col):
-        if source_table.c.contains_column(col):
+        if isinstance(col, Column) and \
+                col.table is source_table and col.key in source_table.c:
             return target_table.c[col.key]
         else:
             return None
index 7d17e25f34ac0177f7806ea937c4560c3ac96147..da133b21ab6c1de17157eaf6f3a80400ed7c2091 100644 (file)
@@ -1066,6 +1066,38 @@ class ToMetaDataTest(fixtures.TestBase, ComparesTables):
             sorted([_get_key(i) for i in table_c.indexes])
         )
 
+    def test_indexes_with_col_redefine(self):
+        meta = MetaData()
+
+        table = Table('mytable', meta,
+                      Column('id', Integer, primary_key=True),
+                      Column('data1', Integer),
+                      Column('data2', Integer),
+                      Index('text', text('data1 + 1')),
+                      )
+        Index('multi', table.c.data1, table.c.data2)
+        Index('func', func.abs(table.c.data1))
+        Index('multi-func', table.c.data1, func.abs(table.c.data2))
+
+        table = Table('mytable', meta,
+                      Column('data1', Integer),
+                      Column('data2', Integer),
+                      extend_existing=True
+                      )
+
+        meta2 = MetaData()
+        table_c = table.tometadata(meta2)
+
+        def _get_key(i):
+            return [i.name, i.unique] + \
+                sorted(i.kwargs.items()) + \
+                [str(col) for col in i.expressions]
+
+        eq_(
+            sorted([_get_key(i) for i in table.indexes]),
+            sorted([_get_key(i) for i in table_c.indexes])
+        )
+
     @emits_warning("Table '.+' already exists within the given MetaData")
     def test_already_exists(self):