From: Tobias Pfeiffer Date: Tue, 15 Nov 2022 07:14:05 +0000 (+0900) Subject: add predicate into dialect_options X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6893ebe374b0141c5b534af850d39ac02a51b915;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git add predicate into dialect_options --- diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index 99d84ae162..cda8c7687e 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -2643,6 +2643,20 @@ class SQLiteDialect(default.DefaultDialect): ) indexes = [] + # regular expression to extract the filter predicate of a partial index. + # this could fail to extract the predicate correctly on indexes created like + # CREATE INDEX i ON t (col || ') where') WHERE col <> '' + # but as this function does not support expression-based indexes this case + # does not occur. + partial_pred_re = re.compile(r"\)\s+where\s+(.+)", re.IGNORECASE) + + if schema: + schema_expr = "%s." % self.identifier_preparer.quote_identifier( + schema + ) + else: + schema_expr = "" + include_auto_indexes = kw.pop("include_auto_indexes", False) for row in pragma_indexes: # ignore implicit primary key index. @@ -2653,10 +2667,25 @@ class SQLiteDialect(default.DefaultDialect): continue indexes.append( dict( - name=row[1], column_names=[], unique=row[2], partial=row[4] + name=row[1], + column_names=[], + unique=row[2], + dialect_options={}, ) ) + # check partial indexes + if row[4]: + s = ( + "SELECT sql FROM %(schema)ssqlite_master " + "WHERE name = ? " + "AND type = 'index'" % {"schema": schema_expr} + ) + rs = connection.exec_driver_sql(s, (row[1],)) + index_sql = rs.scalar() + predicate = partial_pred_re.search(index_sql).group(1) + indexes[-1]["dialect_options"]["sqlite_where"] = predicate + # loop thru unique indexes to get the column names. for idx in list(indexes): pragma_index = self._get_table_pragma( @@ -2673,6 +2702,7 @@ class SQLiteDialect(default.DefaultDialect): break else: idx["column_names"].append(row[2]) + indexes.sort(key=lambda d: d["name"] or "~") # sort None as last if indexes: return indexes diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py index 1d88f49459..a5e24b382d 100644 --- a/test/dialect/test_sqlite.py +++ b/test/dialect/test_sqlite.py @@ -2282,7 +2282,7 @@ class ConstraintReflectionTest(fixtures.TestBase): "unique": 1, "name": "sqlite_autoindex_o_1", "column_names": ["foo"], - "partial": False, + "dialect_options": {}, } ], ) @@ -2298,7 +2298,7 @@ class ConstraintReflectionTest(fixtures.TestBase): "unique": 0, "name": "ix_main_l_bar", "column_names": ["bar"], - "partial": False, + "dialect_options": {}, } ], ) @@ -2323,13 +2323,13 @@ class ConstraintReflectionTest(fixtures.TestBase): "unique": 1, "name": "ix_no_partial", "column_names": ["x"], - "partial": False, + "dialect_options": {}, }, { "unique": 1, "name": "ix_partial", "column_names": ["x"], - "partial": True, + "dialect_options": {"sqlite_where": "y > 10"}, }, ], )