Skip to content

Extensions and other objects ​

The database's Objects tab (/db/<database>/objects) lists the objects that belong to the database but to no schema, as pgAdmin's database tree shows them: Extensions, Languages, Casts and Event triggers, then Foreign data wrappers, Foreign servers and User mappings. phpMyAdmin has no equivalent; these are PostgreSQL features. The foreign data sections are described on the Foreign data page.

The Objects tab of a new database: plpgsql in Extensions and Languages, and empty Casts, Event triggers and foreign data sections

How the sections work ​

Every section works the same way:

  • The Add … button opens an empty dialog.
  • Each row has Edit (the same dialog, filled in), Export (the DDL that recreates the object, with Copy to clipboard) and Drop.
  • Languages, foreign data wrappers and foreign servers also have Privileges: a dialog with the object's grantees of USAGE, Edit privileges, Revoke and Add privileges for a role, as on the Privileges tabs (GRANT USAGE ON LANGUAGE plpgsql TO bookshop_staff;).
  • Tick rows (or Check all) and use the Export or Drop button above the table for several objects at once. With nothing ticked you get No object selected.
  • Drop asks first, showing the statement, with Drop the objects that depend on it too (CASCADE).

The dialogs have Go, Preview SQL (the statements, not run) and Close. An error from PostgreSQL shows at the top of the page and leaves the dialog open.

In the navigation panel, the database's Extensions, Languages, Casts, Foreign Data Wrappers and Event Triggers folders lead here; clicking an object in them opens its Edit dialog.

Superuser territory

Most of these objects need a superuser: creating a language that is not trusted, every event trigger, every foreign data wrapper, and most extensions. As a role without superuser the dialogs still open, and PostgreSQL's permission denied message tells you what is missing.

Extensions ​

The list shows each installed extension's Name, Version, Schema and Comment. plpgsql is installed in every database.

Add an extension ​

The Add extension dialog with hstore chosen, schema public and the version list

FieldWhat it does
NameThe extensions the server has installed files for and that are not yet in this database (pg_available_extensions)
SchemaWhere its objects go. Empty uses the schema the extension's control file names, or else the first schema of the search_path. For an extension whose control file fixes the schema, the hint says so.
Version(default version) or any version the server can install
CascadeAlso installs the extensions this one requires
sql
CREATE EXTENSION hstore
    SCHEMA public;

Required extensions

earthdistance needs cube. Without Cascade you get required extension "cube" is not installed; with it, both are installed:

sql
CREATE EXTENSION earthdistance
    CASCADE;

Fixed-schema extensions

Some extensions must live in one schema. plperl (and the other procedural languages packaged as extensions) must go in pg_catalog: choosing another schema fails with extension "plperl" must be installed in schema "pg_catalog". The dialog's hint names the schema; leave Schema empty.

Who may install

Extensions marked trusted (such as hstore, pg_trgm, citext, plperl) can be installed by a role with CREATE on the database. The others (postgres_fdw, file_fdw, plpython3u, pldbgapi…) need a superuser. Extensions whose files are not installed on the server don't appear: install the operating system package (often postgresql-contrib) first.

Update or move an extension ​

Edit an extension to change its version or schema. The name cannot change.

Editing pg_trgm: schema dbo_ext and version 1.6

sql
ALTER EXTENSION pg_trgm
    SET SCHEMA dbo_ext;
ALTER EXTENSION pg_trgm
    UPDATE TO "1.6";

Relocatable extensions only

Schema is read-only for an extension that is not relocatable (such as plpgsql and plperl). PostgreSQL's SET SCHEMA moves all the extension's objects; code that called them with the old schema name, or relied on the old schema in search_path, stops finding them.

Version lists every version the server has scripts for. Choose a newer one to run the update scripts. Going back to an older version only works if the extension ships a downgrade script; most don't, and PostgreSQL answers that there is no update path.

Drop an extension ​

sql
DROP EXTENSION "hstore";

If a table has a column of the extension's type, the drop fails with cannot drop extension hstore because other objects depend on it. With CASCADE, PostgreSQL drops those columns (the tables stay, the columns go) and any other dependent object.

Languages ​

The list shows each procedural language's Name, whether it is Trusted, its Handler, Owner and Comment. Languages installed as extensions (plpgsql, plperl…) appear here too.

Prefer the extension

For the languages PostgreSQL ships (PL/Perl, PL/Python, PL/Tcl), add the extension (plperl, plpython3u, pltcl) in Extensions instead of using Add language. The extension creates the handler functions and the language together, and dropping the extension removes both.

Add or edit a language ​

The Add language dialog with name, owner, trusted, handler, inline and validator functions and a comment

FieldWhat it doesSQL
NameThe language name; on Edit, renames itALTER LANGUAGE … RENAME TO …
OwnerEmpty for the current roleALTER LANGUAGE … OWNER TO …
TrustedLets roles without superuser create functions in itCREATE TRUSTED LANGUAGE
Handler functionThe language_handler function that runs its code (required)HANDLER
Inline functionRuns anonymous DO blocksINLINE
Validator functionChecks a function body at CREATE FUNCTIONVALIDATOR
CommentCOMMENT ON LANGUAGE
sql
CREATE TRUSTED PROCEDURAL LANGUAGE dbo_lang
    HANDLER plpgsql_call_handler
    INLINE plpgsql_inline_handler
    VALIDATOR plpgsql_validator
;
COMMENT ON LANGUAGE dbo_lang
    IS 'A scratch language for the docs';

Each function list offers only the signatures CREATE LANGUAGE accepts: Handler function the functions returning language_handler with no arguments, Inline function those returning void from one internal argument and Validator function those returning void from one oid. Built-in functions and operator-class support functions with the same signatures are left out, so on a bare database the lists hold the …_call_handler, …_inline_handler and …_validator of the installed languages.

Changing trust or functions drops the language

ALTER LANGUAGE can only rename and change the owner. If you change Trusted or any of the three functions, the dialog's SQL starts with a warning and runs DROP LANGUAGE … CASCADE followed by CREATE LANGUAGE: every function written in the language is dropped. The new language gets the old owner, comment and (for a trusted language) USAGE grants back. Read the Preview SQL before you click Go.

Trusted and untrusted

A trusted language (plpgsql, plperl) runs in a sandbox, so any role with USAGE on it may write functions in it. An untrusted one (plpython3u, plperlu) can reach the file system and network, so only superusers can create functions in it, and only a superuser can create the language. GRANT USAGE ON LANGUAGE is not offered here: see Limitations.

Casts ​

The list shows user-defined casts: the name (source AS target), the Function that converts (or binary compatible), the Context and the Comment. The built-in casts are not listed.

Add a cast ​

The Add cast dialog from text to dbo_pair with a function, AS ASSIGNMENT and a comment

FieldWhat it doesSQL
Source type, Target typeThe types to convert betweenCREATE CAST (source AS target)
FunctionAfter both types are chosen, lists the functions that take the source and return the target. (binary compatible, WITHOUT FUNCTION) reuses the bytes as they are.WITH FUNCTION f(args) / WITHOUT FUNCTION
ContextExplicit (only with CAST/::), In assignments (also when storing into a column), Implicit (anywhere in expressions)(nothing) / AS ASSIGNMENT / AS IMPLICIT
CommentCOMMENT ON CAST
sql
CREATE CAST (text AS dbo_pair)
    WITH FUNCTION public.dbo_text_to_pair(text)
    AS ASSIGNMENT;
COMMENT ON CAST (text AS dbo_pair)
    IS 'text "a,b" to dbo_pair';

Only the comment can change afterwards: on Edit, the types, function and context are read-only. To change them, drop the cast and create it again.

WARNING

WITHOUT FUNCTION only works between types whose internal representation is the same (as text and varchar); otherwise PostgreSQL answers source and target data types are not physically compatible. You must own the source or the target type. Be sparing with Implicit: it can make operator and function calls ambiguous.

Event triggers ​

Event triggers fire on DDL commands in the database, where ordinary triggers fire on rows. The list shows each trigger's Event, Function, Tags and State.

The Event triggers section with dbo_et on ddl_command_end, its function, tags and state

Add an event trigger ​

First create a function that returns event_trigger, for example on a schema's Routines tab:

sql
CREATE FUNCTION dbo_et_fn() RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
  INSERT INTO dbo_et_log(tag) VALUES (tg_tag);
END $$;

Without one, the dialog says There is no function returning event_trigger yet.

The Add event trigger dialog: name, owner, event, function, tags, enabled state and comment

FieldWhat it does
NameThe trigger's name
OwnerEmpty for the current role. Must be a superuser.
EventDDL_COMMAND_START, DDL_COMMAND_END, SQL_DROP, TABLE_REWRITE, and LOGIN on PostgreSQL 17+
FunctionA function returning event_trigger
When tag inCommand tags separated by commas, such as CREATE TABLE, DROP TABLE; empty fires on every command
EnabledEnabled, Disabled, Replica or Always (below)
Comment
sql
CREATE EVENT TRIGGER dbo_et ON DDL_COMMAND_END
    WHEN TAG IN ('CREATE TABLE', 'DROP TABLE')
    EXECUTE FUNCTION public.dbo_et_fn();

COMMENT ON EVENT TRIGGER dbo_et
    IS 'Logs table DDL';

ALTER EVENT TRIGGER dbo_et
    OWNER TO postgres;

Enable, disable, replica, always ​

Change Enabled in the Edit dialog:

StateSQLFires
EnabledALTER EVENT TRIGGER t ENABLE;In normal sessions (session_replication_role = origin, the default)
DisabledALTER EVENT TRIGGER t DISABLE;Never
ReplicaALTER EVENT TRIGGER t ENABLE REPLICA;Only when session_replication_role = replica (logical replication apply)
AlwaysALTER EVENT TRIGGER t ENABLE ALWAYS;In both modes

Changing event, function or tags recreates the trigger

Renaming and changing the owner, comment or state are ALTERs. Changing Event, Function or When tag in makes the dialog run DROP EVENT TRIGGER IF EXISTS and CREATE EVENT TRIGGER (the Preview SQL starts with a warning). The owner, comment and state (disabled, replica or always) are set again on the new trigger.

Scope and ownership

An event trigger only fires for commands in the database it was created in, never server-wide. PostgreSQL requires its owner to be a superuser: choosing another role fails with permission denied to change owner of event trigger. A faulty ddl_command_start or login trigger can block DDL or sign-ins for everyone in the database; disable it from a superuser session (or start the server with event_triggers = off, PostgreSQL 17+).

pg_cron jobs ​

Job scheduling, which pgAdmin does with pgAgent, is done here with the pg_cron extension. In a database where pg_cron is installed (the one cron.database_name names, postgres by default), the navigation panel shows pg_cron Jobs under the database; anywhere else it is not shown at all. Its folder opens the pg_cron jobs page (/db/<database>/cron-jobs), a job its dialog there. pg_cron 1.4 or later is needed.

The list has each job's Name, Schedule, the Database it runs in, the role it runs as (Run as), whether it is Active, and its Last run (status and start time, the message on hover), with Runs, Edit, Export and Drop, and Export / Drop for the ticked jobs. Runs lists the job's last 50 runs from cron.job_run_details: status, start, end, database, role and message.

Add job and Edit open the job dialog:

Fieldpg_cron
Namejob_name; fixed once the job exists, since pg_cron cannot rename a job.
ScheduleFive cron fields (0 3 * * *, in GMT unless cron.timezone says otherwise), @daily and the like, or 30 seconds.
CommandThe SQL the job runs.
DatabaseWhere it runs; empty for this database.
Run asThe role it runs as; empty for yours. Another role needs a superuser.
ActiveUnticked, the job stays but does not run.

A new job is SELECT cron.schedule_in_database(…), a change SELECT cron.alter_job(…), a drop SELECT cron.unschedule(<id>); Preview SQL and Export show them. pg_cron lists only your own jobs unless you are a superuser.

Not tried against a live pg_cron

The local test server has no pg_cron. The page was checked against a stand-in cron schema with pg_cron's cron.job, cron.job_run_details and functions of the same signatures, so the statements match pg_cron 1.4's documented API but have not been run by pg_cron itself. pgAgent is not supported.

Limitations ​

  • Security labels and ALTER EXTENSION … ADD/DROP member are not offered.
  • A language, cast or event trigger that is part of an extension is listed like the others; drop the extension instead of the member.

Released under the MIT License.