--- /dev/null
+.. change::
+ :tags: bug, sqlite
+ :tickets: 4431
+
+ Reflection of an index based on SQL expressions are now skipped with a
+ warning, in the same way as that of the Postgresql dialect, where we currently
+ do not support reflecting indexes that have SQL expressions within them.
+ Previously, an index with columns of None were produced which would break
+ tools like Alembic.
"sqlite_autoindex"
):
continue
-
indexes.append(dict(name=row[1], column_names=[], unique=row[2]))
# loop thru unique indexes to get the column names.
- for idx in indexes:
+ for idx in list(indexes):
pragma_index = self._get_table_pragma(
connection, "index_info", idx["name"]
)
for row in pragma_index:
- idx["column_names"].append(row[2])
+ if row[2] is None:
+ util.warn(
+ "Skipped unsupported reflection of "
+ "expression-based index %s" % idx["name"]
+ )
+ indexes.remove(idx)
+ break
+ else:
+ idx["column_names"].append(row[2])
return indexes
@reflection.cache
def index_reflection(self):
return exclusions.open()
+ @property
+ def indexes_with_expressions(self):
+ """target database supports CREATE INDEX against SQL expressions."""
+ return exclusions.closed()
+
@property
def unique_constraint_reflection(self):
"""target dialect supports reflection of unique constraints"""
from .. import config
from .. import engines
from .. import eq_
+from .. import expect_warnings
from .. import fixtures
from .. import is_
from ..schema import Column
def test_get_noncol_index_pk(self):
self._test_get_noncol_index("noncol_idx_test_pk", "noncol_idx_pk")
+ @testing.requires.indexes_with_expressions
+ @testing.provide_metadata
+ def test_reflect_expression_based_indexes(self):
+ Table(
+ "t",
+ self.metadata,
+ Column("x", String(30)),
+ Column("y", String(30)),
+ )
+ event.listen(
+ self.metadata,
+ "after_create",
+ DDL("CREATE INDEX t_idx ON t(lower(x), lower(y))"),
+ )
+ event.listen(
+ self.metadata, "after_create", DDL("CREATE INDEX t_idx_2 ON t(x)")
+ )
+ self.metadata.create_all()
+
+ insp = inspect(self.metadata.bind)
+
+ with expect_warnings(
+ "Skipped unsupported reflection of expression-based index t_idx"
+ ):
+ eq_(
+ insp.get_indexes("t"),
+ [{"name": "t_idx_2", "column_names": ["x"], "unique": 0}],
+ )
+
@testing.requires.unique_constraint_reflection
def test_get_unique_constraints(self):
self._test_get_unique_constraints()
"postgresql", "sqlite", "oracle", self._mariadb_102
)
+ @property
+ def indexes_with_expressions(self):
+ return only_on(["postgresql", "sqlite>=3.9.0"])
+
@property
def temp_table_names(self):
"""target dialect supports listing of temporary table names"""