List PostgreSQL Extension Objects with pg_describe_object
List PostgreSQL Extension Objects with pg_describe_object
You ran CREATE EXTENSION fuzzystrmatch, and before you move, dump or drop it you need to know what it put in the database. In psql, \dx+ fuzzystrmatch lists every object that belongs to the extension. That command runs one query against pg_depend. The query returns one row per member object, and pg_describe_object turns each one into a readable label.
Purpose and Overview
Extensions group database objects so that you can manage them as one unit. When it runs, CREATE EXTENSION records the identity of every object it creates, so that DROP EXTENSION can remove them later. That record lives in pg_depend, the catalog that stores dependency relationships between database objects. Each member object gets a row that points at the extension's row in pg_extension, with deptype set to 'e'.
PostgreSQL will not let you drop one member on its own; only dropping the whole extension removes it. pg_dump also skips the members and writes a single CREATE EXTENSION command in their place. If someone edited a member's definition by hand, that edit is not in the dump.
The query returns one column, Object description, with a text label for each member, sorted alphabetically. It returns no OIDs and no owners. Members are not limited to functions and views. An extension script can also create data types, operators and index support methods, and each of those gets its own row.
Sample Code
The query psql runs for \dx+, aimed at one extension by name:
1SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS "Object description"
2FROM pg_catalog.pg_depend
3WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass
4 AND refobjid = (SELECT oid FROM pg_catalog.pg_extension WHERE extname = 'fuzzystrmatch')
5 AND deptype = 'e'
6ORDER BY 1;
7
8-- Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
9-- Portions Copyright (c) 1994, The Regents of the University of California
10-- PostgreSQL Licence: https://raw.githubusercontent.com/postgres/postgres/master/COPYRIGHT
The same filter across every installed extension, joined to pg_extension for the name and version:
1SELECT e.extname,
2 e.extversion,
3 pg_catalog.pg_describe_object(d.classid, d.objid, 0) AS "Object description"
4FROM pg_catalog.pg_depend d
5JOIN pg_catalog.pg_extension e ON e.oid = d.refobjid
6WHERE d.refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass
7 AND d.deptype = 'e'
8ORDER BY 1, 3;
Notes: Both blocks need PostgreSQL 9.1 or later, the release where pg_extension and pg_describe_object first appear. In the first block, psql's column-alias placeholder becomes "Object description", and the extension OID it passes in becomes a lookup on extname. To inspect a different extension, change 'fuzzystrmatch' to its name. If that extension is not installed, the subquery returns NULL and the query returns no rows. For fuzzystrmatch, the result names the module's functions, among them soundex, difference, levenshtein, metaphone, dmetaphone and dmetaphone_alt.
Code Breakdown
The query is a single filtered read of pg_depend.
The pg_depend columns
Each row in pg_depend pairs a dependent object with a referenced object. classid is the OID of the system catalog that holds the dependent object, and objid is the OID of the object itself. refclassid and refobjid do the same for the referenced side. In a member row, the dependent is the function, type or other member object, and the referenced object is the extension.
objsubid holds a column number when the dependent is a table column, and zero for every other object type. The query passes a literal 0 as the sub-object ID, so each label describes the whole object.
refclassid and the regclass cast
A bare OID in refobjid does not say which catalog it belongs to. refclassid supplies that. The cast 'pg_catalog.pg_extension'::pg_catalog.regclass converts the catalog's name to its OID, so the filter compares OID to OID. With both columns pinned, the referenced object must be an extension, and it must be the one you named.
Every name in the query carries the pg_catalog. prefix. This ties each lookup to the system catalog instead of whatever the search path finds first.
deptype = 'e' versus 'x'
'e' is DEPENDENCY_EXTENSION. The dependent object is a member of the extension and can be dropped only through DROP EXTENSION. It works the same way as an INTERNAL dependency, but PostgreSQL keeps it as a separate type for clarity and to make pg_dump simpler.
'x' is DEPENDENCY_AUTO_EXTENSION, and it does not mean membership. The object cannot work without the extension and is dropped automatically along with it. It is not a member, so pg_dump still dumps it. The query filters on 'e' alone, so it lists the objects whose definitions pg_dump leaves out. Configuration tables and sequences that the extension script marks with pg_extension_config_dump are still in this list, but pg_dump writes out their contents. To see the 'x' objects as well, change the filter to deptype IN ('e', 'x') and add deptype to the select list.
pg_describe_object
pg_describe_object(classid, objid, objsubid) returns a text description of the object identified by a catalog OID, an object OID and a sub-object ID. The text is meant for people to read, and depending on server configuration it might be translated. Do not parse it in scripts. For undefined objects the function returns NULL. When a script needs stable output, pg_identify_object returns machine-readable information that is never translated.
Key Extension Dependency Concepts
Member objects
An extension's name is unqualified and must be unique across the database. The extension itself does not live in a schema, but its member objects can. Objects that span the whole database cluster, such as databases, roles and tablespaces, cannot be extension members, so they never appear in this list.
DROP EXTENSION and RESTRICT
DROP EXTENSION drops the member objects as well. It also drops any routine marked as dependent with ALTER ROUTINE ... DEPENDS ON EXTENSION. Only the extension's owner can run it. With RESTRICT, the drop is refused if any object depends on the extension other than the extension itself, its members and those explicitly dependent routines.
Schema placement with CREATE EXTENSION ... SCHEMA
If an extension allows its contents to be relocated, the SCHEMA clause chooses where its objects go, as in CREATE EXTENSION hstore SCHEMA addons;. The named schema must already exist. With no SCHEMA clause and no schema in the control file, PostgreSQL uses the current default creation schema. If the control file names a schema, a SCHEMA clause cannot override it.
The relocatable control-file setting defaults to false. For a relocatable extension, ALTER EXTENSION ... SET SCHEMA moves every member into the new schema in one command.
Trusted extensions and ownership
An extension marked trusted in its control file can be installed by any user who has CREATE privilege on the current database. fuzzystrmatch is a trusted module. In a trusted install, the member objects belong to the bootstrap superuser, not the user who ran CREATE EXTENSION, unless the extension's script assigns them to that user.
Practical Applications
Each scenario below starts from the first block for one extension, or the second block when you need every extension in the database at once.
Pre-drop impact check
Run the first block before you drop anything. The output lists the extension's member objects, all of which DROP EXTENSION removes. The drop also removes objects with deptype = 'x' and routines marked DEPENDS ON EXTENSION, and the 'e' filter does not show them. To list the 'x' objects too, widen the filter to deptype IN ('e', 'x'), as described in the deptype breakdown above. Then run the drop with RESTRICT. If objects outside the extension depend on it, the command fails, and you can deal with those objects before you try again.
Auditing a trusted install
On a server where non-superusers install trusted extensions such as fuzzystrmatch, the member list shows what entered the database. Those members belong to the bootstrap superuser. Check that the target schema is one where untrusted users do not have, and will not get, CREATE privilege.
Dump and migration review
A dump includes a CREATE EXTENSION command for each extension instead of the member definitions. On restore, those objects come from the extension's own install script. Any hand edits to a member are lost. Compare the member list against your change history before a migration. Two kinds of object are exceptions. Objects with deptype = 'x' are dumped normally. Configuration tables marked with pg_extension_config_dump keep their contents in the dump, but not their definitions.
Encoding check before using fuzzystrmatch on UTF-8 data
The member list confirms which fuzzystrmatch functions are present. Four of them, soundex, metaphone, dmetaphone and dmetaphone_alt, do not work well with multibyte encodings such as UTF-8. Check the database encoding before building matching logic on those functions.
Version Compatibility
Extensions and the pg_describe_object function both arrived in PostgreSQL 9.1. The 9.1 function reference lists pg_describe_object with the same three arguments the query passes. Both blocks therefore run on 9.1 and every later release.
PostgreSQL 13 changed two things that affect extension work. It removed the FROM option of CREATE EXTENSION, so installations still using unpackaged extensions had to move to a packaged version before upgrading to 13. It also added trusted extensions, which non-superusers with CREATE on the database can install.
Best Practices
- List members before every drop — run the query first, so the effect of
DROP EXTENSIONis known before you run it. - Write RESTRICT on DROP EXTENSION — the drop then fails while objects outside the extension still depend on it.
- Give relocatable extensions their own schema — create the schema first, then install with
CREATE EXTENSION ... SCHEMA. - Keep CREATE on that schema away from untrusted users — never grant it to untrusted users now or later.
- Leave member objects unedited —
pg_dumpdoes not dump changes to member definitions. - Check pg_available_extensions before installing — it and
pg_available_extension_versionsshow what this server can load.
References
- pg_depend — pg_depend columns, deptype 'e' membership and 'x' auto-drop
- CREATE EXTENSION — recorded object identities, SCHEMA clause rules, trusted installs and ownership, pg_available_extensions, schema security advice
- DROP EXTENSION — member drop, DEPENDS ON EXTENSION routines, owner requirement, RESTRICT
- Packaging Related Objects into an Extension — member object types (data types, operators, index support), no single-member drop, pg_dump writes a CREATE EXTENSION command instead of members, configuration table contents, cluster-wide objects, relocatable default, ALTER EXTENSION SET SCHEMA
- System Information Functions and Operators — pg_describe_object output and NULL handling, pg_identify_object
- System Information Functions (PostgreSQL 9.1) — pg_describe_object in 9.1
- Release 9.1 — extensions and pg_describe_object added in 9.1
- psql — \dx+ lists all objects in each matching extension
- fuzzystrmatch — trusted module, function names, multibyte caution
- Release 13 — removal of CREATE EXTENSION FROM, trusted extensions
- Waiting for 9.1 – Extensions (depesz) — extensions group database objects for easy handling
- PostgreSQL COPYRIGHT — licence and copyright notice kept in the script
- psql describe.c (listOneExtensionContents) — the source of the \dx+ query
Posts in this series
- How Many Connections Can Your PostgreSQL Database Handle?
- PostgreSQL Backend Connections via pg_stat_database
- pg_blocking_pids — Find Blocking Queries in PostgreSQL
- List PostgreSQL Databases by Size with Access Check
- Assess PostgreSQL Database Sizes Quickly and Easily
- Unveiling Your PostgreSQL Server - A Diagnostic Powerhouse
- Keep Your PostgreSQL Database Clean, Identify Idle Connections
- Query the PostgreSQL Configuration
- pg_is_in_recovery — Monitor PostgreSQL Standby Status
- ALTER SEQUENCE RESTART WITH in PostgreSQL — Examples
- Monitor Running Queries in PostgreSQL using pg_stat_activity
- Monitor PostgreSQL Active Sessions with pg_stat_activity
- PostgreSQL Error Handling Settings via pg_settings
- PostgreSQL File Location Settings Query via pg_settings
- Inspect PostgreSQL Lock Management Settings with pg_settings
- PostgreSQL Logging Configuration Query via pg_settings
- Monitor PostgreSQL Memory Settings with pg_settings
- PostgreSQL Table Row Count Estimates with SQL
- List PostgreSQL Tables by Size with SQL
- PostgreSQL WAL Settings Query Guide
- log_parser_stats, log_planner_stats, log_executor_stats — PostgreSQL
- PostgreSQL SSL Settings Query Guide
- PostgreSQL Resource Settings Query Guide
- PostgreSQL Replication Settings Query Guide
- PostgreSQL Query Planning Settings Query Guide
- PostgreSQL Preset Options Settings Query Guide
- PostgreSQL Miscellaneous Settings Query Guide
- Count PostgreSQL Sessions by State with SQL
- Kill Idle PostgreSQL Sessions with SQL
- GRANT SELECT on All Tables in PostgreSQL — with Examples
- pg_stat_user_tables — Find Insert-Only Tables in PostgreSQL
- Detect Soft Delete Patterns in PostgreSQL
- List PostgreSQL Object Comments with SQL
- List Foreign Key Constraints in PostgreSQL
- List PostgreSQL Enum Types and Their Values with SQL
- List All Views in a PostgreSQL Database with SQL
- Find PostgreSQL Tables Without a Primary Key
- List PostgreSQL Partitioned Tables with SQL
- List All Schemas in Your PostgreSQL Database
- pg_stat_database — Query PostgreSQL Database Statistics
- List PostgreSQL Roles and Their Privileges
- Scrubbing Email PII in PostgreSQL for GDPR Compliance
- List Installed Extensions in PostgreSQL
- List PostgreSQL Collations with pg_collation and ICU
- PostgreSQL Replica Identity for Logical Replication
- Monitor PostgreSQL Vacuum Progress with pg_stat_progress_vacuum
- Monitor PostgreSQL Wait Events Using pg_stat_activity
- Monitor PostgreSQL Replication Lag with pg_stat_replication
- List PostgreSQL Wait Events with the pg_wait_events View
- PostgreSQL Column-Level Permissions Audit Query
- List All PostgreSQL Triggers with Their State
- timestamptz and tzdata: Avoid Shifted PostgreSQL Timestamps
- Inspect PostgreSQL Sequences with the pg_sequences View
- List PostgreSQL Functions with pg_proc
- Query PostgreSQL Tablespace Info with pg_tablespace
- Audit PostgreSQL Authentication with pg_hba_file_rules
- List PostgreSQL Materialized Views with pg_matviews
- Audit Row-Level Security Policies with pg_policies
- List PostgreSQL Extension Objects with pg_describe_object