Compare commits

...

1 Commits

Author SHA1 Message Date
Evan
4a6a2ff253 fix(db_engine_specs): stop filtering out Postgres schemas prefixed with pg
SQLAlchemy's Postgres dialect excludes system schemas with
`nspname NOT LIKE 'pg_%'`, but `_` is a single-character wildcard in
SQL LIKE patterns, so it silently drops any user-defined schema that
starts with `pg` plus one more character (e.g. `pgsql`, `pgstats`),
not just the real `pg_` system schemas. Override `get_schema_names` in
PostgresBaseEngineSpec with a Python-side prefix check instead.

Fixes #30678
2026-07-22 09:02:29 -07:00
2 changed files with 52 additions and 0 deletions

View File

@@ -793,6 +793,28 @@ WHERE datistemplate = false;
)
}
@classmethod
def get_schema_names(cls, inspector: Inspector) -> set[str]:
"""
Return all schema names, excluding actual Postgres system schemas.
SQLAlchemy's Postgres dialect filters out system schemas with the
query ``nspname NOT LIKE 'pg_%'``. Since ``_`` is a single-character
wildcard in SQL ``LIKE`` patterns, this unintentionally excludes any
user-defined schema that merely starts with ``pg`` followed by any
other character (e.g. ``pgsql``, ``pgstats``), not only the actual
Postgres system schemas, which are always prefixed with the literal
string ``pg_`` (e.g. ``pg_catalog``, ``pg_toast``).
"""
with inspector.engine.connect() as conn:
return {
name
for (name,) in conn.execute(
text("SELECT nspname FROM pg_namespace ORDER BY nspname")
)
if not name.startswith("pg_")
}
@classmethod
def get_table_names(
cls, database: Database, inspector: PGInspector, schema: str | None

View File

@@ -403,3 +403,33 @@ def test_interval_type_mutator() -> None:
assert mutator(True) is None
assert mutator([1, 2, 3]) is None
assert mutator({"days": 1}) is None
def test_get_schema_names_excludes_only_actual_system_schemas(
mocker: MockerFixture,
) -> None:
"""
DB Eng Specs (postgres): Test ``get_schema_names``
User-defined schemas that merely start with ``pg`` (but are not
actual Postgres system schemas, which always start with the literal
``pg_``) must not be filtered out. See SIP/issue #30678.
"""
inspector = mocker.MagicMock()
inspector.engine.connect().__enter__().execute.return_value = [
("public",),
("pgsql",),
("pgstats",),
("pg_catalog",),
("pg_toast",),
("information_schema",),
]
schemas = spec.get_schema_names(inspector)
assert schemas == {
"public",
"pgsql",
"pgstats",
"information_schema",
}