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
1 change: 1 addition & 0 deletions changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Unreleased
Bug fixes:
----------
* Include relation type/name titles in `\d` and `\d+` describe output so wildcard describe results retain per-relation context.
* Fix `\d table` not showing disabled triggers under a separate "Disabled triggers:" section.

2.2.1 (2025-04-27)
==================
Expand Down
5 changes: 3 additions & 2 deletions pgspecial/dbcommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -1670,10 +1670,11 @@ def describe_one_table_details(cur, schema_name, relation_name, oid, verbose):
# * disabled triggers and the two special ALWAYS and REPLICA
# * configurations.
# */
rows = cur.fetchall()
for category in range(4):
have_heading = False
list_trigger = False
for row in cur:
for row in rows:
list_trigger = False
# /*
# * Check if this trigger falls into the current category
# */
Expand Down
10 changes: 10 additions & 0 deletions tests/dbutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ def setup_db(conn):
cur.execute("create domain schema1.bigint_t bigint")
cur.execute("comment on domain schema1.bigint_t is 'a really large integer'")

# triggers
cur.execute("create table tbl_with_triggers(id integer)")
cur.execute(
"""create function trigger_noop() returns trigger language plpgsql as
$$ begin return new; end $$"""
)
cur.execute("create trigger trig_enabled after insert on tbl_with_triggers for each row execute procedure trigger_noop()")
cur.execute("create trigger trig_disabled after insert on tbl_with_triggers for each row execute procedure trigger_noop()")
cur.execute("alter table tbl_with_triggers disable trigger trig_disabled")

# privileges
cur.execute("CREATE ROLE test_role;")
cur.execute("ALTER DEFAULT PRIVILEGES IN SCHEMA schema1 GRANT SELECT ON TABLES TO test_role;")
Expand Down
34 changes: 30 additions & 4 deletions tests/test_specials.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ def test_slash_d(executor):
("public", "tbl2", "table", POSTGRES_USER),
("public", "tbl2_id2_seq", "sequence", POSTGRES_USER),
("public", "tbl3", "table", POSTGRES_USER),
("public", "tbl_with_triggers", "table", POSTGRES_USER),
("public", "vw1", "view", POSTGRES_USER),
]
headers = objects_listing_headers[:-2]
status = "SELECT 8"
status = "SELECT 9"
expected = [title, rows, headers, status]

assert results == expected
Expand All @@ -147,10 +148,11 @@ def test_slash_d_verbose(executor):
("public", "tbl2", "table", POSTGRES_USER, "8192 bytes", None),
("public", "tbl2_id2_seq", "sequence", POSTGRES_USER, "8192 bytes", None),
("public", "tbl3", "table", POSTGRES_USER, "0 bytes", None),
("public", "tbl_with_triggers", "table", POSTGRES_USER, "0 bytes", None),
("public", "vw1", "view", POSTGRES_USER, "0 bytes", None),
]
headers = objects_listing_headers
status = "SELECT 8"
status = "SELECT 9"
expected = [title, rows, headers, status]

assert results == expected
Expand Down Expand Up @@ -197,6 +199,7 @@ def test_slash_d_wildcard(executor):
'Sequence "public.tbl2_id2_seq"',
'Table "public.tbl3"',
'Index "public.tbl3_c3_excl"',
'Table "public.tbl_with_triggers"',
]


Expand Down Expand Up @@ -327,6 +330,23 @@ def test_slash_d_table_2_in_schema(executor):
assert results == expected


@dbtest
def test_slash_d_table_with_triggers(executor):
results = executor(r"\d tbl_with_triggers")
status = results[3]
assert "Triggers:" in status
assert "trig_enabled" in status
assert "Disabled triggers:" in status
assert "trig_disabled" in status
# trig_enabled must appear in the enabled section, trig_disabled must not
enabled_section = status[: status.index("Disabled triggers:")]
assert "trig_enabled" in enabled_section
assert "trig_disabled" not in enabled_section
# trig_disabled must appear in the disabled section
disabled_section = status[status.index("Disabled triggers:") :]
assert "trig_disabled" in disabled_section


@dbtest
def test_slash_dn(executor):
"""List all schemas."""
Expand Down Expand Up @@ -366,6 +386,7 @@ def test_slash_dp(executor):
("public", "tbl2", "table", None, "", ""),
("public", "tbl2_id2_seq", "sequence", None, "", ""),
("public", "tbl3", "table", None, "", ""),
("public", "tbl_with_triggers", "table", None, "", ""),
("public", "vw1", "view", None, "", ""),
]

Expand Down Expand Up @@ -491,6 +512,7 @@ def test_slash_dt(executor):
("public", "tbl1", "table", POSTGRES_USER),
("public", "tbl2", "table", POSTGRES_USER),
("public", "tbl3", "table", POSTGRES_USER),
("public", "tbl_with_triggers", "table", POSTGRES_USER),
]
headers = objects_listing_headers[:-2]
status = "SELECT %s" % len(rows)
Expand All @@ -509,6 +531,7 @@ def test_slash_dt_verbose(executor):
("public", "tbl1", "table", POSTGRES_USER, "8192 bytes", None),
("public", "tbl2", "table", POSTGRES_USER, "8192 bytes", None),
("public", "tbl3", "table", POSTGRES_USER, "0 bytes", None),
("public", "tbl_with_triggers", "table", POSTGRES_USER, "0 bytes", None),
]
headers = objects_listing_headers
status = "SELECT %s" % len(rows)
Expand Down Expand Up @@ -778,9 +801,12 @@ def test_slash_db_name(executor):
def test_slash_df(executor):
results = executor(r"\df")
title = None
rows = [("public", "func1", "integer", "", "normal")]
rows = [
("public", "func1", "integer", "", "normal"),
("public", "trigger_noop", "trigger", "", "trigger"),
]
headers = ["Schema", "Name", "Result data type", "Argument data types", "Type"]
status = "SELECT 1"
status = "SELECT 2"
expected = [title, rows, headers, status]
assert results == expected

Expand Down
Loading