Skip to content

Commit cc21d21

Browse files
committed
Add contrib/pgbench extension exposing benchmark functions in SCHEMA pgbench
Add a new contrib extension `pgbench` that exposes the extracted distribution, permutation, and hashing functions as SQL-callable routines in schema `pgbench`: - pgbench.random(min, max) - pgbench.random_gaussian(min, max, parameter) - pgbench.random_exponential(min, max, parameter) - pgbench.random_zipfian(min, max, parameter) - pgbench.random_poisson(center) - pgbench.hash_murmur2(val, seed) - pgbench.hash_fnv1a(val, seed) - pgbench.hash(val, seed) - pgbench.permute(val, size, seed) - pgbench.setseed(seed) Includes regression test suite and build definitions for both Make and Meson.
1 parent adc8f34 commit cc21d21

12 files changed

Lines changed: 819 additions & 0 deletions

File tree

‎contrib/Makefile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ SUBDIRS = \
4444
pgstattuple \
4545
pg_visibility \
4646
pg_walinspect \
47+
pgbench \
4748
postgres_fdw \
4849
seg \
4950
spi \

‎contrib/meson.build‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ subdir('pg_surgery')
5858
subdir('pg_trgm')
5959
subdir('pg_visibility')
6060
subdir('pg_walinspect')
61+
subdir('pgbench')
6162
subdir('postgres_fdw')
6263
subdir('seg')
6364
subdir('sepgsql')

‎contrib/pgbench/Makefile‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# contrib/pgbench/Makefile
2+
3+
MODULE_big = pgbench
4+
OBJS = \
5+
$(WIN32RES) \
6+
pgbench.o \
7+
pgbench_funcs.o
8+
9+
EXTENSION = pgbench
10+
DATA = pgbench--1.0.sql
11+
PGFILEDESC = "pgbench - random distributions and benchmarking utilities"
12+
13+
REGRESS = pgbench
14+
15+
EXTRA_CLEAN = pgbench_funcs.c
16+
17+
ifdef USE_PGXS
18+
PG_CONFIG = pg_config
19+
PGXS := $(shell $(PG_CONFIG) --pgxs)
20+
include $(PGXS)
21+
else
22+
subdir = contrib/pgbench
23+
top_builddir = ../..
24+
include $(top_builddir)/src/Makefile.global
25+
include $(top_srcdir)/contrib/contrib-global.mk
26+
endif
27+
28+
# pgbench_funcs.c is shared from src/common
29+
pgbench_funcs.c: % : $(top_srcdir)/src/common/%
30+
rm -f $@ && $(LN_S) $< .
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
CREATE EXTENSION pgbench;
2+
-- Check schema and functions
3+
\dx+ pgbench
4+
Objects in extension "pgbench"
5+
Object description
6+
---------------------------------------------------------------------
7+
function pgbench.hash(bigint,bigint)
8+
function pgbench.hash_fnv1a(bigint,bigint)
9+
function pgbench.hash_murmur2(bigint,bigint)
10+
function pgbench.permute(bigint,bigint,bigint)
11+
function pgbench.random(bigint,bigint)
12+
function pgbench.random_exponential(bigint,bigint,double precision)
13+
function pgbench.random_gaussian(bigint,bigint,double precision)
14+
function pgbench.random_poisson(double precision)
15+
function pgbench.random_zipfian(bigint,bigint,double precision)
16+
function pgbench.setseed(bigint)
17+
function pgbench.setseed(double precision)
18+
(11 rows)
19+
20+
-- Test Hashing functions
21+
SELECT pgbench.hash_murmur2(12345, 0);
22+
hash_murmur2
23+
----------------------
24+
-8599128181304237022
25+
(1 row)
26+
27+
SELECT pgbench.hash_murmur2(12345, 42);
28+
hash_murmur2
29+
---------------------
30+
-591810079667318857
31+
(1 row)
32+
33+
SELECT pgbench.hash_fnv1a(12345, 0);
34+
hash_fnv1a
35+
----------------------
36+
-1792800413050876852
37+
(1 row)
38+
39+
SELECT pgbench.hash_fnv1a(12345, 42);
40+
hash_fnv1a
41+
----------------------
42+
-5267424053501251834
43+
(1 row)
44+
45+
-- pgbench.hash is alias for hash_murmur2
46+
SELECT pgbench.hash(12345, 0) = pgbench.hash_murmur2(12345, 0);
47+
?column?
48+
----------
49+
t
50+
(1 row)
51+
52+
SELECT pgbench.hash(12345, 42) = pgbench.hash_murmur2(12345, 42);
53+
?column?
54+
----------
55+
t
56+
(1 row)
57+
58+
-- Test Permutation function (bijective mapping over 0..9)
59+
SELECT array_agg(pgbench.permute(i, 10, 42) ORDER BY i) FROM generate_series(0, 9) i;
60+
array_agg
61+
-----------------------
62+
{1,7,0,4,3,8,6,5,9,2}
63+
(1 row)
64+
65+
SELECT count(DISTINCT pgbench.permute(i, 10, 42)) = 10 FROM generate_series(0, 9) i;
66+
?column?
67+
----------
68+
t
69+
(1 row)
70+
71+
SELECT count(DISTINCT pgbench.permute(i, 100, 12345)) = 100 FROM generate_series(0, 99) i;
72+
?column?
73+
----------
74+
t
75+
(1 row)
76+
77+
-- Test setseed and reproducibility
78+
SELECT pgbench.setseed(0.5);
79+
setseed
80+
---------
81+
82+
(1 row)
83+
84+
SELECT pgbench.random(1, 100) AS r_unif,
85+
pgbench.random_gaussian(1, 100, 2.5) AS r_gauss,
86+
pgbench.random_exponential(1, 100, 3.0) AS r_exp,
87+
pgbench.random_zipfian(1, 100, 1.5) AS r_zipf,
88+
pgbench.random_poisson(50.0) AS r_poiss;
89+
r_unif | r_gauss | r_exp | r_zipf | r_poiss
90+
--------+---------+-------+--------+---------
91+
17 | 60 | 61 | 50 | 36
92+
(1 row)
93+
94+
-- Reset seed and verify exact same values
95+
SELECT pgbench.setseed(0.5);
96+
setseed
97+
---------
98+
99+
(1 row)
100+
101+
SELECT pgbench.random(1, 100) AS r_unif,
102+
pgbench.random_gaussian(1, 100, 2.5) AS r_gauss,
103+
pgbench.random_exponential(1, 100, 3.0) AS r_exp,
104+
pgbench.random_zipfian(1, 100, 1.5) AS r_zipf,
105+
pgbench.random_poisson(50.0) AS r_poiss;
106+
r_unif | r_gauss | r_exp | r_zipf | r_poiss
107+
--------+---------+-------+--------+---------
108+
17 | 60 | 61 | 50 | 36
109+
(1 row)
110+
111+
-- Test bigint setseed
112+
SELECT pgbench.setseed(123456789::bigint);
113+
setseed
114+
---------
115+
116+
(1 row)
117+
118+
SELECT pgbench.random(1, 100);
119+
random
120+
--------
121+
41
122+
(1 row)
123+
124+
SELECT pgbench.setseed(123456789::bigint);
125+
setseed
126+
---------
127+
128+
(1 row)
129+
130+
SELECT pgbench.random(1, 100);
131+
random
132+
--------
133+
41
134+
(1 row)
135+
136+
-- Error cases: parameter boundaries
137+
SELECT pgbench.random(10, 5);
138+
ERROR: empty range given to random: lower bound 10 is greater than upper bound 5
139+
SELECT pgbench.random_gaussian(1, 10, 1.5);
140+
ERROR: gaussian parameter must be at least 2.000000 (not 1.500000)
141+
SELECT pgbench.random_exponential(1, 10, 0.0);
142+
ERROR: exponential parameter must be greater than zero (not 0.000000)
143+
SELECT pgbench.random_zipfian(1, 10, 1.0);
144+
ERROR: zipfian parameter must be in range [1.001, 1000] (not 1.000000)
145+
SELECT pgbench.random_zipfian(1, 10, 1001.0);
146+
ERROR: zipfian parameter must be in range [1.001, 1000] (not 1001.000000)
147+
SELECT pgbench.random_poisson(0.0);
148+
ERROR: poisson center parameter must be greater than zero (not 0.000000)
149+
SELECT pgbench.permute(5, 0, 42);
150+
ERROR: permute size parameter must be greater than zero
151+
SELECT pgbench.setseed(1.5);
152+
ERROR: setseed parameter 1.5 is out of allowed range [-1,1]
153+
DROP EXTENSION pgbench;

‎contrib/pgbench/meson.build‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright (c) 2026, PostgreSQL Global Development Group
2+
3+
pgbench_ext_sources = files(
4+
'pgbench.c',
5+
'../../src/common/pgbench_funcs.c',
6+
)
7+
8+
if host_system == 'windows'
9+
pgbench_ext_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
10+
'--NAME', 'pgbench',
11+
'--FILEDESC', 'pgbench - random distributions and benchmarking utilities',])
12+
endif
13+
14+
pgbench_ext = shared_module('pgbench',
15+
pgbench_ext_sources,
16+
c_pch: pch_postgres_h,
17+
kwargs: contrib_mod_args,
18+
)
19+
contrib_targets += pgbench_ext
20+
21+
install_data(
22+
'pgbench.control',
23+
'pgbench--1.0.sql',
24+
kwargs: contrib_data_args,
25+
)
26+
27+
tests += {
28+
'name': 'pgbench_ext',
29+
'sd': meson.current_source_dir(),
30+
'bd': meson.current_build_dir(),
31+
'regress': {
32+
'sql': [
33+
'pgbench',
34+
],
35+
},
36+
}

‎contrib/pgbench/pgbench--1.0.sql‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* contrib/pgbench/pgbench--1.0.sql */
2+
3+
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
4+
\echo Use "CREATE EXTENSION pgbench" to load this file. \quit
5+
6+
-- PRNG Seeding
7+
CREATE FUNCTION setseed(seed double precision)
8+
RETURNS void
9+
AS 'MODULE_PATHNAME', 'pgbench_setseed_double'
10+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
11+
12+
CREATE FUNCTION setseed(seed bigint)
13+
RETURNS void
14+
AS 'MODULE_PATHNAME', 'pgbench_setseed_int64'
15+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
16+
17+
-- Uniform Random
18+
CREATE FUNCTION random(min bigint, max bigint)
19+
RETURNS bigint
20+
AS 'MODULE_PATHNAME', 'pgbench_random_int64'
21+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
22+
23+
-- Gaussian (Normal) Random
24+
CREATE FUNCTION random_gaussian(min bigint, max bigint, parameter double precision)
25+
RETURNS bigint
26+
AS 'MODULE_PATHNAME', 'pgbench_random_gaussian_int64'
27+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
28+
29+
-- Exponential Random
30+
CREATE FUNCTION random_exponential(min bigint, max bigint, parameter double precision)
31+
RETURNS bigint
32+
AS 'MODULE_PATHNAME', 'pgbench_random_exponential_int64'
33+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
34+
35+
-- Zipfian Random
36+
CREATE FUNCTION random_zipfian(min bigint, max bigint, parameter double precision)
37+
RETURNS bigint
38+
AS 'MODULE_PATHNAME', 'pgbench_random_zipfian_int64'
39+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
40+
41+
-- Poisson Random
42+
CREATE FUNCTION random_poisson(center double precision)
43+
RETURNS bigint
44+
AS 'MODULE_PATHNAME', 'pgbench_random_poisson_int64'
45+
LANGUAGE C STRICT VOLATILE PARALLEL RESTRICTED;
46+
47+
-- MurmurHash2 (64-bit)
48+
CREATE FUNCTION hash_murmur2(val bigint, seed bigint DEFAULT 0)
49+
RETURNS bigint
50+
AS 'MODULE_PATHNAME', 'pgbench_hash_murmur2_int64'
51+
LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
52+
53+
-- FNV-1a Hash (64-bit)
54+
CREATE FUNCTION hash_fnv1a(val bigint, seed bigint DEFAULT 0)
55+
RETURNS bigint
56+
AS 'MODULE_PATHNAME', 'pgbench_hash_fnv1a_int64'
57+
LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
58+
59+
-- Alias for hash_murmur2
60+
CREATE FUNCTION hash(val bigint, seed bigint DEFAULT 0)
61+
RETURNS bigint
62+
AS 'MODULE_PATHNAME', 'pgbench_hash_murmur2_int64'
63+
LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
64+
65+
-- Pseudorandom Permutation
66+
CREATE FUNCTION permute(val bigint, size bigint, seed bigint DEFAULT 0)
67+
RETURNS bigint
68+
AS 'MODULE_PATHNAME', 'pgbench_permute_int64'
69+
LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;

0 commit comments

Comments
 (0)