diff options
Diffstat (limited to 'contrib/pg_freespacemap')
-rw-r--r-- | contrib/pg_freespacemap/.gitignore | 4 | ||||
-rw-r--r-- | contrib/pg_freespacemap/Makefile | 29 | ||||
-rw-r--r-- | contrib/pg_freespacemap/expected/pg_freespacemap.out | 85 | ||||
-rw-r--r-- | contrib/pg_freespacemap/meson.build | 42 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap--1.0--1.1.sql | 7 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap--1.1--1.2.sql | 7 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap--1.1.sql | 25 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap.c | 42 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap.conf | 1 | ||||
-rw-r--r-- | contrib/pg_freespacemap/pg_freespacemap.control | 5 | ||||
-rw-r--r-- | contrib/pg_freespacemap/sql/pg_freespacemap.sql | 32 |
11 files changed, 279 insertions, 0 deletions
diff --git a/contrib/pg_freespacemap/.gitignore b/contrib/pg_freespacemap/.gitignore new file mode 100644 index 0000000..5dcb3ff --- /dev/null +++ b/contrib/pg_freespacemap/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/pg_freespacemap/Makefile b/contrib/pg_freespacemap/Makefile new file mode 100644 index 0000000..b48e4b2 --- /dev/null +++ b/contrib/pg_freespacemap/Makefile @@ -0,0 +1,29 @@ +# contrib/pg_freespacemap/Makefile + +MODULE_big = pg_freespacemap +OBJS = \ + $(WIN32RES) \ + pg_freespacemap.o + +EXTENSION = pg_freespacemap +DATA = pg_freespacemap--1.1.sql pg_freespacemap--1.1--1.2.sql \ + pg_freespacemap--1.0--1.1.sql +PGFILEDESC = "pg_freespacemap - monitoring of free space map" + +REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_freespacemap/pg_freespacemap.conf +REGRESS = pg_freespacemap + +# Disabled because these tests require "autovacuum=off", which +# typical installcheck users do not have (e.g. buildfarm clients). +NO_INSTALLCHECK = 1 + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/pg_freespacemap +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/pg_freespacemap/expected/pg_freespacemap.out b/contrib/pg_freespacemap/expected/pg_freespacemap.out new file mode 100644 index 0000000..eb574c2 --- /dev/null +++ b/contrib/pg_freespacemap/expected/pg_freespacemap.out @@ -0,0 +1,85 @@ +CREATE EXTENSION pg_freespacemap; +CREATE TABLE freespace_tab (c1 int) WITH (autovacuum_enabled = off); +CREATE INDEX freespace_brin ON freespace_tab USING brin (c1); +CREATE INDEX freespace_btree ON freespace_tab USING btree (c1); +CREATE INDEX freespace_hash ON freespace_tab USING hash (c1); +-- report all the sizes of the FSMs for all the relation blocks. +WITH rel AS (SELECT oid::regclass AS id FROM pg_class WHERE relname ~ 'freespace') + SELECT rel.id, fsm.blkno, (fsm.avail > 0) AS is_avail + FROM rel, LATERAL pg_freespace(rel.id) AS fsm + ORDER BY 1, 2; + id | blkno | is_avail +-----------------+-------+---------- + freespace_brin | 0 | f + freespace_brin | 1 | f + freespace_brin | 2 | t + freespace_btree | 0 | f + freespace_hash | 0 | f + freespace_hash | 1 | f + freespace_hash | 2 | f + freespace_hash | 3 | f + freespace_hash | 4 | f + freespace_hash | 5 | f + freespace_hash | 6 | f + freespace_hash | 7 | f + freespace_hash | 8 | f + freespace_hash | 9 | f +(14 rows) + +INSERT INTO freespace_tab VALUES (1); +VACUUM freespace_tab; +WITH rel AS (SELECT oid::regclass AS id FROM pg_class WHERE relname ~ 'freespace') + SELECT rel.id, fsm.blkno, (fsm.avail > 0) AS is_avail + FROM rel, LATERAL pg_freespace(rel.id) AS fsm + ORDER BY 1, 2; + id | blkno | is_avail +-----------------+-------+---------- + freespace_tab | 0 | t + freespace_brin | 0 | f + freespace_brin | 1 | f + freespace_brin | 2 | t + freespace_btree | 0 | f + freespace_btree | 1 | f + freespace_hash | 0 | f + freespace_hash | 1 | f + freespace_hash | 2 | f + freespace_hash | 3 | f + freespace_hash | 4 | f + freespace_hash | 5 | f + freespace_hash | 6 | f + freespace_hash | 7 | f + freespace_hash | 8 | f + freespace_hash | 9 | f +(16 rows) + +DELETE FROM freespace_tab; +VACUUM freespace_tab; +WITH rel AS (SELECT oid::regclass AS id FROM pg_class WHERE relname ~ 'freespace') + SELECT rel.id, fsm.blkno, (fsm.avail > 0) AS is_avail + FROM rel, LATERAL pg_freespace(rel.id) AS fsm + ORDER BY 1, 2; + id | blkno | is_avail +-----------------+-------+---------- + freespace_brin | 0 | f + freespace_brin | 1 | f + freespace_brin | 2 | t + freespace_btree | 0 | f + freespace_btree | 1 | f + freespace_hash | 0 | f + freespace_hash | 1 | f + freespace_hash | 2 | f + freespace_hash | 3 | f + freespace_hash | 4 | f + freespace_hash | 5 | f + freespace_hash | 6 | f + freespace_hash | 7 | f + freespace_hash | 8 | f + freespace_hash | 9 | f +(15 rows) + +-- failures with incorrect block number +SELECT * FROM pg_freespace('freespace_tab', -1); +ERROR: invalid block number +SELECT * FROM pg_freespace('freespace_tab', 4294967295); +ERROR: invalid block number +DROP TABLE freespace_tab; diff --git a/contrib/pg_freespacemap/meson.build b/contrib/pg_freespacemap/meson.build new file mode 100644 index 0000000..a91dc45 --- /dev/null +++ b/contrib/pg_freespacemap/meson.build @@ -0,0 +1,42 @@ +# Copyright (c) 2022-2023, PostgreSQL Global Development Group + +pg_freespacemap_sources = files( + 'pg_freespacemap.c', +) + +if host_system == 'windows' + pg_freespacemap_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'pg_freespacemap', + '--FILEDESC', 'pg_freespacemap - monitoring of free space map',]) +endif + +pg_freespacemap = shared_module('pg_freespacemap', + pg_freespacemap_sources, + kwargs: contrib_mod_args, +) +contrib_targets += pg_freespacemap + +install_data( + 'pg_freespacemap--1.0--1.1.sql', + 'pg_freespacemap--1.1--1.2.sql', + 'pg_freespacemap--1.1.sql', + 'pg_freespacemap.control', + kwargs: contrib_data_args, +) + +tests += { + 'name': 'pg_freespacemap', + 'sd': meson.current_source_dir(), + 'bd': meson.current_build_dir(), + 'regress': { + 'sql': [ + 'pg_freespacemap', + ], + 'regress_args': [ + '--temp-config', files('pg_freespacemap.conf') + ], + # Disabled because these tests require "autovacuum=off", which + # typical runningcheck users do not have (e.g. buildfarm clients). + 'runningcheck': false, + }, +} diff --git a/contrib/pg_freespacemap/pg_freespacemap--1.0--1.1.sql b/contrib/pg_freespacemap/pg_freespacemap--1.0--1.1.sql new file mode 100644 index 0000000..52d6576 --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap--1.0--1.1.sql @@ -0,0 +1,7 @@ +/* contrib/pg_freespacemap/pg_freespacemap--1.0--1.1.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pg_freespacemap UPDATE TO '1.1'" to load this file. \quit + +ALTER FUNCTION pg_freespace(regclass, bigint) PARALLEL SAFE; +ALTER FUNCTION pg_freespace(regclass) PARALLEL SAFE; diff --git a/contrib/pg_freespacemap/pg_freespacemap--1.1--1.2.sql b/contrib/pg_freespacemap/pg_freespacemap--1.1--1.2.sql new file mode 100644 index 0000000..f558def --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap--1.1--1.2.sql @@ -0,0 +1,7 @@ +/* contrib/pg_freespacemap/pg_freespacemap--1.1--1.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pg_freespacemap UPDATE TO '1.2'" to load this file. \quit + +GRANT EXECUTE ON FUNCTION pg_freespace(regclass, bigint) TO pg_stat_scan_tables; +GRANT EXECUTE ON FUNCTION pg_freespace(regclass) TO pg_stat_scan_tables; diff --git a/contrib/pg_freespacemap/pg_freespacemap--1.1.sql b/contrib/pg_freespacemap/pg_freespacemap--1.1.sql new file mode 100644 index 0000000..e1b8242 --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap--1.1.sql @@ -0,0 +1,25 @@ +/* contrib/pg_freespacemap/pg_freespacemap--1.1.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION pg_freespacemap" to load this file. \quit + +-- Register the C function. +CREATE FUNCTION pg_freespace(regclass, bigint) +RETURNS int2 +AS 'MODULE_PATHNAME', 'pg_freespace' +LANGUAGE C STRICT PARALLEL SAFE; + +-- pg_freespace shows the recorded space avail at each block in a relation +CREATE FUNCTION + pg_freespace(rel regclass, blkno OUT bigint, avail OUT int2) +RETURNS SETOF RECORD +AS $$ + SELECT blkno, pg_freespace($1, blkno) AS avail + FROM generate_series(0, pg_relation_size($1) / current_setting('block_size')::bigint - 1) AS blkno; +$$ +LANGUAGE SQL PARALLEL SAFE; + + +-- Don't want these to be available to public. +REVOKE ALL ON FUNCTION pg_freespace(regclass, bigint) FROM PUBLIC; +REVOKE ALL ON FUNCTION pg_freespace(regclass) FROM PUBLIC; diff --git a/contrib/pg_freespacemap/pg_freespacemap.c b/contrib/pg_freespacemap/pg_freespacemap.c new file mode 100644 index 0000000..b82cab2 --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap.c @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------- + * + * pg_freespacemap.c + * display contents of a free space map + * + * contrib/pg_freespacemap/pg_freespacemap.c + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include "access/relation.h" +#include "funcapi.h" +#include "storage/freespace.h" + +PG_MODULE_MAGIC; + +/* + * Returns the amount of free space on a given page, according to the + * free space map. + */ +PG_FUNCTION_INFO_V1(pg_freespace); + +Datum +pg_freespace(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + int64 blkno = PG_GETARG_INT64(1); + int16 freespace; + Relation rel; + + rel = relation_open(relid, AccessShareLock); + + if (blkno < 0 || blkno > MaxBlockNumber) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid block number"))); + + freespace = GetRecordedFreeSpace(rel, blkno); + + relation_close(rel, AccessShareLock); + PG_RETURN_INT16(freespace); +} diff --git a/contrib/pg_freespacemap/pg_freespacemap.conf b/contrib/pg_freespacemap/pg_freespacemap.conf new file mode 100644 index 0000000..96b1ed8 --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap.conf @@ -0,0 +1 @@ +autovacuum = off diff --git a/contrib/pg_freespacemap/pg_freespacemap.control b/contrib/pg_freespacemap/pg_freespacemap.control new file mode 100644 index 0000000..ac8fc50 --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap.control @@ -0,0 +1,5 @@ +# pg_freespacemap extension +comment = 'examine the free space map (FSM)' +default_version = '1.2' +module_pathname = '$libdir/pg_freespacemap' +relocatable = true diff --git a/contrib/pg_freespacemap/sql/pg_freespacemap.sql b/contrib/pg_freespacemap/sql/pg_freespacemap.sql new file mode 100644 index 0000000..06275d8 --- /dev/null +++ b/contrib/pg_freespacemap/sql/pg_freespacemap.sql @@ -0,0 +1,32 @@ +CREATE EXTENSION pg_freespacemap; + +CREATE TABLE freespace_tab (c1 int) WITH (autovacuum_enabled = off); +CREATE INDEX freespace_brin ON freespace_tab USING brin (c1); +CREATE INDEX freespace_btree ON freespace_tab USING btree (c1); +CREATE INDEX freespace_hash ON freespace_tab USING hash (c1); + +-- report all the sizes of the FSMs for all the relation blocks. +WITH rel AS (SELECT oid::regclass AS id FROM pg_class WHERE relname ~ 'freespace') + SELECT rel.id, fsm.blkno, (fsm.avail > 0) AS is_avail + FROM rel, LATERAL pg_freespace(rel.id) AS fsm + ORDER BY 1, 2; + +INSERT INTO freespace_tab VALUES (1); +VACUUM freespace_tab; +WITH rel AS (SELECT oid::regclass AS id FROM pg_class WHERE relname ~ 'freespace') + SELECT rel.id, fsm.blkno, (fsm.avail > 0) AS is_avail + FROM rel, LATERAL pg_freespace(rel.id) AS fsm + ORDER BY 1, 2; + +DELETE FROM freespace_tab; +VACUUM freespace_tab; +WITH rel AS (SELECT oid::regclass AS id FROM pg_class WHERE relname ~ 'freespace') + SELECT rel.id, fsm.blkno, (fsm.avail > 0) AS is_avail + FROM rel, LATERAL pg_freespace(rel.id) AS fsm + ORDER BY 1, 2; + +-- failures with incorrect block number +SELECT * FROM pg_freespace('freespace_tab', -1); +SELECT * FROM pg_freespace('freespace_tab', 4294967295); + +DROP TABLE freespace_tab; |