From 0b628bc84d185fde14ddbcaa2766ed7d3e93534a Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 1 May 2020 20:30:18 -0400 Subject: [PATCH] Handle non-string, non column expression in index for deferred attach Fixed issue where an :class:`.Index` that is deferred in being associated with a table, such as as when it contains a :class:`.Column` that is not associated with any :class:`.Table` yet, would fail to attach correctly if it also contained a non table-oriented expession. Fixes: #5298 Change-Id: I0111c400f6bd4a9f31bf00a9957816c7a3fac783 (cherry picked from commit 45a334e38c1baab34d3195c899cb9ca617fb52a7) --- doc/build/changelog/unreleased_13/5298.rst | 9 +++++++++ lib/sqlalchemy/sql/schema.py | 5 +++-- test/sql/test_metadata.py | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 doc/build/changelog/unreleased_13/5298.rst diff --git a/doc/build/changelog/unreleased_13/5298.rst b/doc/build/changelog/unreleased_13/5298.rst new file mode 100644 index 0000000000..0b9af1258d --- /dev/null +++ b/doc/build/changelog/unreleased_13/5298.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: bug, schema + :tickets: 5298 + + Fixed issue where an :class:`.Index` that is deferred in being associated + with a table, such as as when it contains a :class:`.Column` that is not + associated with any :class:`.Table` yet, would fail to attach correctly if + it also contained a non table-oriented expession. + diff --git a/lib/sqlalchemy/sql/schema.py b/lib/sqlalchemy/sql/schema.py index 54a9b02366..1de9f39455 100644 --- a/lib/sqlalchemy/sql/schema.py +++ b/lib/sqlalchemy/sql/schema.py @@ -2900,7 +2900,6 @@ class ColumnCollectionMixin(object): cols_w_table = [c for c in col_objs if isinstance(c.table, Table)] cols_wo_table = set(col_objs).difference(cols_w_table) - if cols_wo_table: # feature #3341 - place event listeners for Column objects # such that when all those cols are attached, we autoattach. @@ -2908,7 +2907,9 @@ class ColumnCollectionMixin(object): # issue #3411 - don't do the per-column auto-attach if some of the # columns are specified as strings. - has_string_cols = set(self._pending_colargs).difference(col_objs) + has_string_cols = set( + c for c in self._pending_colargs if c is not None + ).difference(col_objs) if not has_string_cols: def _col_attached(column, table): diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 64cdf830c8..0780749e17 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -9,6 +9,7 @@ from sqlalchemy import Boolean from sqlalchemy import CheckConstraint from sqlalchemy import Column from sqlalchemy import ColumnDefault +from sqlalchemy import desc from sqlalchemy import Enum from sqlalchemy import event from sqlalchemy import exc @@ -2633,6 +2634,23 @@ class ConstraintTest(fixtures.TestBase): idx, ) + def test_non_attached_col_plus_string_expr(self): + # another one that declarative can lead towards + metadata = MetaData() + + t1 = Table("a", metadata, Column("id", Integer)) + + c2 = Column("x", Integer) + + # if we do it here, no problem + # t1.append_column(c2) + + idx = Index("foo", c2, desc("foo")) + + t1.append_column(c2) + + self._assert_index_col_x(t1, idx, columns=True) + def test_column_associated_w_lowercase_table(self): from sqlalchemy import table -- 2.39.5