Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Unreleased
==========

Features:
---------
* Add ``\dS`` suffix metacommands (``\dtS``, ``\dvS``, ``\dmS``, ``\dsS``, ``\diS``, ``\dS``) to include system objects from pg_catalog and information_schema, matching psql behavior.

Bug fixes:
----------
* Include relation type/name titles in `\d` and `\d+` describe output so wildcard describe results retain per-relation context.
Expand Down
43 changes: 42 additions & 1 deletion pgspecial/dbcommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,14 +432,15 @@ def _describe_extension(cur, oid):
yield None, cur, headers, cur.statusmessage


def list_objects(cur, pattern, verbose, relkinds):
def list_objects(cur, pattern, verbose, relkinds, show_system=False):
"""
Returns (title, rows, header, status)

This method is used by list_tables, list_views, list_materialized views
and list_indexes

relkinds is a list of strings to filter pg_class.relkind
show_system includes pg_catalog and information_schema objects (S suffix)

"""
schema_pattern, table_pattern = sql_name_pattern(pattern)
Expand Down Expand Up @@ -478,6 +479,11 @@ def list_objects(cur, pattern, verbose, relkinds):

if schema_pattern:
params["schema_pattern"] = SQL(" AND n.nspname ~ {}").format(schema_pattern)
elif show_system:
params["schema_pattern"] = SQL(
"""
AND n.nspname !~ '^pg_toast' """
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the intent was to include both regular and system objects, right? Here, you're going to ignore user-provided pattern, and only show what matches your pattern. Tests would catch this, but the PR contains no tests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so the S modifier does this (from https://www.postgresql.org/docs/current/app-psql.html):

By default, only user-created objects are shown; supply a pattern or the S modifier to include system objects.

The fallback condition on lines 490-493 excludes system objects:

AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
AND pg_catalog.pg_table_is_visible(c.oid)

so in your elif show_system, you only want to keep this one:

AND pg_catalog.pg_table_is_visible(c.oid)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So my first comment was not accurate, I misread the condition. But the condition does not do what you want. And you still need tests.

Thanks!

)
else:
params["schema_pattern"] = SQL(
"""
Expand Down Expand Up @@ -506,26 +512,61 @@ def list_tables(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["r", "p", ""])


@special_command("\\dtS", "\\dtS[+] [pattern]", "List tables, including system tables.")
def list_tables_system(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["r", "p", ""], show_system=True)


@special_command("\\dv", "\\dv[+] [pattern]", "List views.")
def list_views(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["v", "s", ""])


@special_command("\\dvS", "\\dvS[+] [pattern]", "List views, including system views.")
def list_views_system(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["v", "s", ""], show_system=True)


@special_command("\\dm", "\\dm[+] [pattern]", "List materialized views.")
def list_materialized_views(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["m", "s", ""])


@special_command("\\dmS", "\\dmS[+] [pattern]", "List materialized views, including system.")
def list_materialized_views_system(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["m", "s", ""], show_system=True)


@special_command("\\ds", "\\ds[+] [pattern]", "List sequences.")
def list_sequences(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["S", "s", ""])


@special_command("\\dsS", "\\dsS[+] [pattern]", "List sequences, including system.")
def list_sequences_system(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["S", "s", ""], show_system=True)


@special_command("\\di", "\\di[+] [pattern]", "List indexes.")
def list_indexes(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["i", "s", ""])


@special_command("\\diS", "\\diS[+] [pattern]", "List indexes, including system indexes.")
def list_indexes_system(cur, pattern, verbose):
return list_objects(cur, pattern, verbose, ["i", "s", ""], show_system=True)


@special_command(
"\\dS", "\\dS[+] [pattern]", "List all relations, including system objects."
)
def list_all_system(cur, pattern, verbose):
return list_objects(
cur, pattern, verbose, ["r", "p", "v", "m", "S", "s", "f", "i", ""],
show_system=True,
)


@special_command("\\df", "\\df[+] [pattern]", "List functions.")
def list_functions(cur, pattern, verbose):
if verbose:
Expand Down
Loading