Skip to content
plpgsql_check

plpgsql_check

plpgsql_check : extended check for plpgsql functions

Overview

ID Extension Package Version Category License Language
3060
plpgsql_check
plpgsql_check
2.9.1
LANG
MIT
C
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
--sLd--
No
Yes
Yes
Yes
no
no
Relationships
Requires
plpgsql
See Also
pldbgapi
plprofiler
pg_hint_plan
pgtap
auto_explain
plv8
plperl
plpython3u

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT
MIXED
2.9.1
18
17
16
15
14
plpgsql_check plpgsql
RPM
PIGSTY
2.9.1
18
17
16
15
14
plpgsql_check_$v -
DEB
PGDG
2.9.1
18
17
16
15
14
postgresql-$v-plpgsql-check -
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
el8.aarch64
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
el9.x86_64
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
el9.aarch64
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
el10.x86_64
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
el10.aarch64
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
PIGSTY 2.9.1
d12.x86_64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
d12.aarch64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
d13.x86_64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
d13.aarch64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
u22.x86_64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
u22.aarch64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
u24.x86_64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
u24.aarch64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
u26.x86_64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
u26.aarch64
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
PGDG 2.9.1
Package Version OS ORG SIZE File URL
plpgsql_check_18 2.9.1 el8.x86_64 pigsty 117.5 KiB plpgsql_check_18-2.9.1-1PIGSTY.el8.x86_64.rpm
plpgsql_check_18 2.9.1 el8.x86_64 pgdg 120.1 KiB plpgsql_check_18-2.9.1-1PGDG.rhel8.10.x86_64.rpm
plpgsql_check_18 2.8.10 el8.x86_64 pgdg 116.7 KiB plpgsql_check_18-2.8.10-1PGDG.rhel8.10.x86_64.rpm
plpgsql_check_18 2.8.8 el8.x86_64 pgdg 116.5 KiB plpgsql_check_18-2.8.8-1PGDG.rhel8.10.x86_64.rpm
plpgsql_check_18 2.8.5 el8.x86_64 pgdg 114.2 KiB plpgsql_check_18-2.8.5-1PGDG.rhel8.10.x86_64.rpm
plpgsql_check_18 2.8.4 el8.x86_64 pgdg 113.9 KiB plpgsql_check_18-2.8.4-1PGDG.rhel8.10.x86_64.rpm
plpgsql_check_18 2.8.3 el8.x86_64 pgdg 113.8 KiB plpgsql_check_18-2.8.3-1PGDG.rhel8.x86_64.rpm
plpgsql_check_18 2.8.2 el8.x86_64 pgdg 113.0 KiB plpgsql_check_18-2.8.2-1PGDG.rhel8.x86_64.rpm
plpgsql_check_18 2.9.1 el8.aarch64 pigsty 108.9 KiB plpgsql_check_18-2.9.1-1PIGSTY.el8.aarch64.rpm
plpgsql_check_18 2.9.1 el8.aarch64 pgdg 111.2 KiB plpgsql_check_18-2.9.1-1PGDG.rhel8.10.aarch64.rpm
plpgsql_check_18 2.8.10 el8.aarch64 pgdg 108.2 KiB plpgsql_check_18-2.8.10-1PGDG.rhel8.10.aarch64.rpm
plpgsql_check_18 2.8.8 el8.aarch64 pgdg 107.9 KiB plpgsql_check_18-2.8.8-1PGDG.rhel8.10.aarch64.rpm
plpgsql_check_18 2.8.5 el8.aarch64 pgdg 105.5 KiB plpgsql_check_18-2.8.5-1PGDG.rhel8.10.aarch64.rpm
plpgsql_check_18 2.8.4 el8.aarch64 pgdg 105.4 KiB plpgsql_check_18-2.8.4-1PGDG.rhel8.10.aarch64.rpm
plpgsql_check_18 2.8.3 el8.aarch64 pgdg 105.2 KiB plpgsql_check_18-2.8.3-1PGDG.rhel8.aarch64.rpm
plpgsql_check_18 2.8.2 el8.aarch64 pgdg 104.4 KiB plpgsql_check_18-2.8.2-1PGDG.rhel8.aarch64.rpm
plpgsql_check_18 2.9.1 el9.x86_64 pigsty 111.1 KiB plpgsql_check_18-2.9.1-1PIGSTY.el9.x86_64.rpm
plpgsql_check_18 2.9.1 el9.x86_64 pgdg 115.6 KiB plpgsql_check_18-2.9.1-1PGDG.rhel9.8.x86_64.rpm
plpgsql_check_18 2.8.11 el9.x86_64 pgdg 113.1 KiB plpgsql_check_18-2.8.11-1PGDG.rhel9.8.x86_64.rpm
plpgsql_check_18 2.9.1 el9.aarch64 pigsty 106.7 KiB plpgsql_check_18-2.9.1-1PIGSTY.el9.aarch64.rpm
plpgsql_check_18 2.9.1 el9.aarch64 pgdg 111.1 KiB plpgsql_check_18-2.9.1-1PGDG.rhel9.8.aarch64.rpm
plpgsql_check_18 2.8.11 el9.aarch64 pgdg 108.1 KiB plpgsql_check_18-2.8.11-1PGDG.rhel9.8.aarch64.rpm
plpgsql_check_18 2.9.1 el10.x86_64 pigsty 113.2 KiB plpgsql_check_18-2.9.1-1PIGSTY.el10.x86_64.rpm
plpgsql_check_18 2.9.1 el10.x86_64 pgdg 117.5 KiB plpgsql_check_18-2.9.1-1PGDG.rhel10.2.x86_64.rpm
plpgsql_check_18 2.8.11 el10.x86_64 pgdg 114.5 KiB plpgsql_check_18-2.8.11-1PGDG.rhel10.2.x86_64.rpm
plpgsql_check_18 2.9.1 el10.aarch64 pigsty 107.9 KiB plpgsql_check_18-2.9.1-1PIGSTY.el10.aarch64.rpm
plpgsql_check_18 2.9.1 el10.aarch64 pgdg 112.0 KiB plpgsql_check_18-2.9.1-1PGDG.rhel10.2.aarch64.rpm
plpgsql_check_18 2.8.11 el10.aarch64 pgdg 109.1 KiB plpgsql_check_18-2.8.11-1PGDG.rhel10.2.aarch64.rpm
postgresql-18-plpgsql-check 2.9.1 d12.x86_64 pgdg 303.6 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg12+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 d12.x86_64 pigsty 301.6 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~bookworm_amd64.deb
postgresql-18-plpgsql-check 2.9.0 d12.x86_64 pgdg 299.1 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg12+1_amd64.deb
postgresql-18-plpgsql-check 2.8.11 d12.x86_64 pgdg 292.6 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg12+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 d12.aarch64 pgdg 293.0 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg12+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 d12.aarch64 pigsty 290.6 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~bookworm_arm64.deb
postgresql-18-plpgsql-check 2.9.0 d12.aarch64 pgdg 288.8 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg12+1_arm64.deb
postgresql-18-plpgsql-check 2.8.11 d12.aarch64 pgdg 281.5 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg12+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 d13.x86_64 pgdg 304.0 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg13+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 d13.x86_64 pigsty 302.0 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~trixie_amd64.deb
postgresql-18-plpgsql-check 2.9.0 d13.x86_64 pgdg 299.8 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg13+1_amd64.deb
postgresql-18-plpgsql-check 2.8.11 d13.x86_64 pgdg 293.1 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg13+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 d13.aarch64 pgdg 293.7 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg13+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 d13.aarch64 pigsty 291.8 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~trixie_arm64.deb
postgresql-18-plpgsql-check 2.9.0 d13.aarch64 pgdg 289.2 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg13+1_arm64.deb
postgresql-18-plpgsql-check 2.8.11 d13.aarch64 pgdg 282.5 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg13+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 u22.x86_64 pgdg 313.5 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg22.04+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 u22.x86_64 pigsty 328.1 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~jammy_amd64.deb
postgresql-18-plpgsql-check 2.9.0 u22.x86_64 pgdg 308.4 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg22.04+1_amd64.deb
postgresql-18-plpgsql-check 2.8.11 u22.x86_64 pgdg 301.7 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg22.04+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 u22.aarch64 pgdg 302.7 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg22.04+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 u22.aarch64 pigsty 321.6 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~jammy_arm64.deb
postgresql-18-plpgsql-check 2.9.0 u22.aarch64 pgdg 298.0 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg22.04+1_arm64.deb
postgresql-18-plpgsql-check 2.8.11 u22.aarch64 pgdg 291.1 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg22.04+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 u24.x86_64 pgdg 303.0 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg24.04+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 u24.x86_64 pigsty 314.4 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~noble_amd64.deb
postgresql-18-plpgsql-check 2.9.0 u24.x86_64 pgdg 298.7 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg24.04+1_amd64.deb
postgresql-18-plpgsql-check 2.8.11 u24.x86_64 pgdg 291.9 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg24.04+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 u24.aarch64 pgdg 291.9 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg24.04+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 u24.aarch64 pigsty 308.1 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~noble_arm64.deb
postgresql-18-plpgsql-check 2.9.0 u24.aarch64 pgdg 287.5 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg24.04+1_arm64.deb
postgresql-18-plpgsql-check 2.8.11 u24.aarch64 pgdg 280.7 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg24.04+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 u26.x86_64 pgdg 300.4 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg26.04+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 u26.x86_64 pigsty 312.3 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~resolute_amd64.deb
postgresql-18-plpgsql-check 2.9.0 u26.x86_64 pgdg 295.6 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg26.04+1_amd64.deb
postgresql-18-plpgsql-check 2.8.11 u26.x86_64 pgdg 290.6 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg26.04+1_amd64.deb
postgresql-18-plpgsql-check 2.9.1 u26.aarch64 pgdg 288.8 KiB postgresql-18-plpgsql-check_2.9.1-1.pgdg26.04+1_arm64.deb
postgresql-18-plpgsql-check 2.9.1 u26.aarch64 pigsty 305.5 KiB postgresql-18-plpgsql-check_2.9.1-1PIGSTY~resolute_arm64.deb
postgresql-18-plpgsql-check 2.9.0 u26.aarch64 pgdg 284.0 KiB postgresql-18-plpgsql-check_2.9.0-1.pgdg26.04+1_arm64.deb
postgresql-18-plpgsql-check 2.8.11 u26.aarch64 pgdg 278.6 KiB postgresql-18-plpgsql-check_2.8.11-1.pgdg26.04+1_arm64.deb

Source

pig build pkg plpgsql_check;		# build rpm

Install

Make sure PGDG and PIGSTY repo available:

pig repo add pgsql -u   # add both repo and update cache

Install this extension with pig:

pig install plpgsql_check;		# install via package name, for the active PG version

pig install plpgsql_check -v 18;   # install for PG 18
pig install plpgsql_check -v 17;   # install for PG 17
pig install plpgsql_check -v 16;   # install for PG 16
pig install plpgsql_check -v 15;   # install for PG 15
pig install plpgsql_check -v 14;   # install for PG 14

Config this extension to shared_preload_libraries:

shared_preload_libraries = 'plpgsql_check';

Create this extension with:

CREATE EXTENSION plpgsql_check CASCADE; -- requires plpgsql

Usage

Sources: official README, v2.9.1 release notes, local package metadata.

plpgsql_check is a PL/pgSQL checker, linter, profiler, tracer, and coverage tool. It detects many errors during development instead of waiting for runtime failures.

CREATE EXTENSION plpgsql_check;

Check A Function

SELECT * FROM plpgsql_check_function('my_function()');
SELECT * FROM plpgsql_check_function('my_function(int, text)');
SELECT * FROM plpgsql_check_function('my_function()', fatal_errors := false);

The table-returning variant is useful for structured reports:

SELECT *
FROM plpgsql_check_function_tb('my_function()');

Output Formats

SELECT * FROM plpgsql_check_function('fx()', format := 'text');
SELECT * FROM plpgsql_check_function('fx()', format := 'json');
SELECT * FROM plpgsql_check_function('fx()', format := 'xml');

Check Trigger Functions

SELECT * FROM plpgsql_check_function('my_trigger_func()', 'my_table');

SELECT * FROM plpgsql_check_function(
  'my_trigger_func()',
  'my_table',
  newtable := 'newtab',
  oldtable := 'oldtab'
);

Warning Categories

SELECT * FROM plpgsql_check_function(
  'fx()',
  extra_warnings := true,
  performance_warnings := true,
  security_warnings := true,
  compatibility_warnings := true
);
  • extra_warnings covers issues such as missing returns, dead code, and unused arguments.
  • performance_warnings covers performance-related checks.
  • security_warnings includes checks such as SQL injection risk.
  • compatibility_warnings reports obsolete or version-sensitive PL/pgSQL patterns.

Batch Check All Functions

SELECT p.oid, p.proname, plpgsql_check_function(p.oid)
FROM pg_catalog.pg_namespace n
JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid
JOIN pg_catalog.pg_language l ON p.prolang = l.oid
WHERE l.lanname = 'plpgsql'
  AND p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype;

Passive Mode

Passive mode checks functions when they start. It is intended for development or preproduction because it adds overhead.

LOAD 'plpgsql_check';
SET plpgsql_check.mode = 'every_start';

Common settings:

plpgsql_check.mode = [ disabled | by_function | fresh_start | every_start ]
plpgsql_check.fatal_errors = [ yes | no ]
plpgsql_check.show_nonperformance_warnings = false
plpgsql_check.show_performance_warnings = false

Profiler

SELECT plpgsql_check_profiler(true);

SELECT my_function();

SELECT lineno, avg_time, source
FROM plpgsql_profiler_function_tb('my_function()');

SELECT stmtid, parent_stmtid, lineno, exec_stmts, stmtname
FROM plpgsql_profiler_function_statements_tb('my_function()');

SELECT * FROM plpgsql_profiler_functions_all();
SELECT plpgsql_profiler_reset_all();

For shared profiler statistics, preload plpgsql before plpgsql_check:

shared_preload_libraries = 'plpgsql,plpgsql_check'

Without shared preload, profiler data is limited to the active session.

Tracer

Tracing emits notices for function and statement entry/exit and can expose variable values. It is disabled by default and should be enabled only with superuser-controlled settings.

SET plpgsql_check.enable_tracer = on;
SELECT plpgsql_check_tracer(true);
SET plpgsql_check.tracer_verbosity = terse;

Dependency Tracking

SELECT *
FROM plpgsql_show_dependency_tb('my_function(int)');

Coverage Metrics

SELECT * FROM plpgsql_coverage_statements('my_function()');
SELECT * FROM plpgsql_coverage_branches('my_function()');

Pragma Directives

Use pragma calls inside functions to tell plpgsql_check about dynamic SQL, temporary tables, inferred record types, or local check settings:

CREATE OR REPLACE FUNCTION fx(anyelement) RETURNS text AS $$
BEGIN
  PERFORM plpgsql_check_pragma('type: r (id int, processed bool)');
  RETURN $1::text;
END;
$$ LANGUAGE plpgsql;

Caveats

  • Pigsty packages plpgsql_check 2.9.1 for PostgreSQL 14-18 as RPMs; DEB packages come from PGDG.
  • The extension requires plpgsql. Preloading is optional for active checking, but needed for shared profiler storage and reliable early tracer/profiler initialization.
  • v2.9.1 fixes a possible crash when a traced inline block fails; no new user-facing SQL API was documented for this patch release.
  • The tracer can expose function arguments or variable values. Use it carefully around security-definer functions or sensitive data.
Last updated on