Skip to content
pg_kpart

pg_kpart

pg_kpart : Reject full partition scans that omit the partition key

Overview

ID Extension Package Version Category License Language
7450
pg_kpart
pg_kpart
1.0
SEC
ISC
C
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
--sL--r
No
Yes
Yes
No
yes
no
Relationships
See Also
pg_partman
pg_fkpart
plan_filter
pg_hint_plan
citus
timescaledb

Planner hook must be loaded through shared_preload_libraries or session_preload_libraries; CREATE EXTENSION is optional.

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT
PIGSTY
1.0
18
17
16
15
14
pg_kpart -
RPM
PIGSTY
1.0
18
17
16
15
14
pg_kpart_$v -
DEB
PIGSTY
1.0
18
17
16
15
14
postgresql-$v-pg-kpart -
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
el8.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
el9.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
el9.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
el10.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
el10.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
d12.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
d12.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
d13.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
d13.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
u22.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
u22.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
u24.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
u24.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
u26.x86_64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
u26.aarch64
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
PIGSTY 1.0
Package Version OS ORG SIZE File URL
pg_kpart_18 1.0 el8.x86_64 pigsty 16.9 KiB pg_kpart_18-1.0-1PIGSTY.el8.x86_64.rpm
pg_kpart_18 1.0 el8.aarch64 pigsty 17.1 KiB pg_kpart_18-1.0-1PIGSTY.el8.aarch64.rpm
pg_kpart_18 1.0 el9.x86_64 pigsty 16.9 KiB pg_kpart_18-1.0-1PIGSTY.el9.x86_64.rpm
pg_kpart_18 1.0 el9.aarch64 pigsty 17.0 KiB pg_kpart_18-1.0-1PIGSTY.el9.aarch64.rpm
pg_kpart_18 1.0 el10.x86_64 pigsty 17.0 KiB pg_kpart_18-1.0-1PIGSTY.el10.x86_64.rpm
pg_kpart_18 1.0 el10.aarch64 pigsty 17.3 KiB pg_kpart_18-1.0-1PIGSTY.el10.aarch64.rpm
postgresql-18-pg-kpart 1.0 d12.x86_64 pigsty 18.8 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~bookworm_amd64.deb
postgresql-18-pg-kpart 1.0 d12.aarch64 pigsty 18.9 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~bookworm_arm64.deb
postgresql-18-pg-kpart 1.0 d13.x86_64 pigsty 18.7 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~trixie_amd64.deb
postgresql-18-pg-kpart 1.0 d13.aarch64 pigsty 18.9 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~trixie_arm64.deb
postgresql-18-pg-kpart 1.0 u22.x86_64 pigsty 19.8 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~jammy_amd64.deb
postgresql-18-pg-kpart 1.0 u22.aarch64 pigsty 19.8 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~jammy_arm64.deb
postgresql-18-pg-kpart 1.0 u24.x86_64 pigsty 19.5 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~noble_amd64.deb
postgresql-18-pg-kpart 1.0 u24.aarch64 pigsty 19.7 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~noble_arm64.deb
postgresql-18-pg-kpart 1.0 u26.x86_64 pigsty 19.5 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~resolute_amd64.deb
postgresql-18-pg-kpart 1.0 u26.aarch64 pigsty 19.5 KiB postgresql-18-pg-kpart_1.0-1PIGSTY~resolute_arm64.deb

Source

pig build pkg pg_kpart;		# build rpm/deb

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 pg_kpart;		# install via package name, for the active PG version

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

Config this extension to shared_preload_libraries:

shared_preload_libraries = 'pg_kpart';

This extension does not need CREATE EXTENSION DDL command

Usage

Sources:

pg_kpart prevents accidental queries that would scan every leaf partition of a partitioned table without effective partition pruning. Its planner hook can raise, warn, or log before execution. The functional unit is the preloaded library; there are no SQL objects to create, and upstream describes CREATE EXTENSION only as optional catalog registration.

Enable and Roll Out

For cluster-wide enforcement, preload the library and restart PostgreSQL:

shared_preload_libraries = 'pg_kpart'

It can also be loaded for selected sessions or databases without a server restart:

session_preload_libraries = 'pg_kpart'

Start in audit mode before enforcing errors:

ALTER SYSTEM SET pg_kpart.message_level = 'warning';
SELECT pg_reload_conf();

Once the observed queries are understood, set pg_kpart.message_level = 'error'.

Scope and Behavior

-- Check only these tables and their sub-partitions.
ALTER SYSTEM SET pg_kpart.blacklisted =
    'public.measurement, public.orders';

-- Or check all partitioned tables except selected hierarchies.
ALTER SYSTEM SET pg_kpart.whitelisted = 'public.audit_log';
SELECT pg_reload_conf();
-- Partition key is logdate.
SELECT * FROM measurement WHERE city_id = 5;              -- violation
SELECT * FROM measurement WHERE logdate = DATE '2026-07-01'; -- pruned, allowed
SELECT * FROM measurement WHERE logdate = $1;             -- runtime pruning, allowed

Violations use SQLSTATE FS001, which applications can trap when message_level is error.

Configuration Index and Caveats

  • pg_kpart.enabled: master switch; default on.
  • pg_kpart.message_level: error, warning, notice, log, and other PostgreSQL message levels.
  • pg_kpart.min_partitions: minimum leaf-partition count to check; default 2.
  • pg_kpart.check_superuser: superusers bypass checks by default.
  • pg_kpart.blacklisted: when nonempty, only named hierarchies are checked and whitelisted is ignored.
  • pg_kpart.whitelisted: hierarchies exempt from checking when no blacklist is set.
  • A predicate whose range still includes every partition is treated as a full scan and rejected, even if it mentions the partition key.
  • The hook also applies to UPDATE, DELETE, and EXPLAIN without ANALYZE. It relies on PostgreSQL’s planned pruning result, not textual inspection of WHERE clauses.
  • Upstream v1.0 is tested on PostgreSQL 14 and newer.
Last updated on