Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
pseudorandomfuncs.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pseudorandomfuncs.c
4 * Functions giving SQL access to a pseudorandom number generator.
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * IDENTIFICATION
10 * src/backend/utils/adt/pseudorandomfuncs.c
11 *
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include <math.h>
17
18#include "common/pg_prng.h"
19#include "miscadmin.h"
20#include "utils/date.h"
21#include "utils/fmgrprotos.h"
22#include "utils/numeric.h"
23#include "utils/timestamp.h"
24
25/* Shared PRNG state used by all the random functions */
27static bool prng_seed_set = false;
28
29/*
30 * Macro for checking the range bounds of random(min, max) functions. Throws
31 * an error if they're the wrong way round.
32 */
33#define CHECK_RANGE_BOUNDS(rmin, rmax) \
34 do { \
35 if ((rmin) > (rmax)) \
36 ereport(ERROR, \
37 errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
38 errmsg("lower bound must be less than or equal to upper bound")); \
39 } while (0)
40
41/*
42 * initialize_prng() -
43 *
44 * Initialize (seed) the PRNG, if not done yet in this process.
45 */
46static void
48{
50 {
51 /*
52 * If possible, seed the PRNG using high-quality random bits. Should
53 * that fail for some reason, we fall back on a lower-quality seed
54 * based on current time and PID.
55 */
57 {
59 uint64 iseed;
60
61 /* Mix the PID with the most predictable bits of the timestamp */
62 iseed = (uint64) now ^ ((uint64) MyProcPid << 32);
63 pg_prng_seed(&prng_state, iseed);
64 }
65 prng_seed_set = true;
66 }
67}
68
69/*
70 * setseed() -
71 *
72 * Seed the PRNG from a specified value in the range [-1.0, 1.0].
73 */
76{
77 float8 seed = PG_GETARG_FLOAT8(0);
78
79 if (seed < -1 || seed > 1 || isnan(seed))
81 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
82 errmsg("setseed parameter %g is out of allowed range [-1,1]",
83 seed));
84
86 prng_seed_set = true;
87
89}
90
91/*
92 * drandom() -
93 *
94 * Returns a random number chosen uniformly in the range [0.0, 1.0).
95 */
98{
99 float8 result;
100
102
103 /* pg_prng_double produces desired result range [0.0, 1.0) */
104 result = pg_prng_double(&prng_state);
105
106 PG_RETURN_FLOAT8(result);
107}
108
109/*
110 * drandom_normal() -
111 *
112 * Returns a random number from a normal distribution.
113 */
114Datum
116{
117 float8 mean = PG_GETARG_FLOAT8(0);
118 float8 stddev = PG_GETARG_FLOAT8(1);
119 float8 result,
120 z;
121
123
124 /* Get random value from standard normal(mean = 0.0, stddev = 1.0) */
126 /* Transform the normal standard variable (z) */
127 /* using the target normal distribution parameters */
128 result = (stddev * z) + mean;
129
130 PG_RETURN_FLOAT8(result);
131}
132
133/*
134 * int4random() -
135 *
136 * Returns a random 32-bit integer chosen uniformly in the specified range.
137 */
138Datum
140{
141 int32 rmin = PG_GETARG_INT32(0);
142 int32 rmax = PG_GETARG_INT32(1);
143 int32 result;
144
145 CHECK_RANGE_BOUNDS(rmin, rmax);
146
148
149 result = (int32) pg_prng_int64_range(&prng_state, rmin, rmax);
150
151 PG_RETURN_INT32(result);
152}
153
154/*
155 * int8random() -
156 *
157 * Returns a random 64-bit integer chosen uniformly in the specified range.
158 */
159Datum
161{
162 int64 rmin = PG_GETARG_INT64(0);
163 int64 rmax = PG_GETARG_INT64(1);
164 int64 result;
165
166 CHECK_RANGE_BOUNDS(rmin, rmax);
167
169
170 result = pg_prng_int64_range(&prng_state, rmin, rmax);
171
172 PG_RETURN_INT64(result);
173}
174
175/*
176 * numeric_random() -
177 *
178 * Returns a random numeric value chosen uniformly in the specified range.
179 */
180Datum
182{
183 Numeric rmin = PG_GETARG_NUMERIC(0);
184 Numeric rmax = PG_GETARG_NUMERIC(1);
185 Numeric result;
186
187 /* Leave range bound checking to random_numeric() */
188
190
191 result = random_numeric(&prng_state, rmin, rmax);
192
193 PG_RETURN_NUMERIC(result);
194}
195
196
197/*
198 * date_random() -
199 *
200 * Returns a random date chosen uniformly in the specified range.
201 */
202Datum
204{
205 int32 rmin = (int32) PG_GETARG_DATEADT(0);
206 int32 rmax = (int32) PG_GETARG_DATEADT(1);
207 DateADT result;
208
209 CHECK_RANGE_BOUNDS(rmin, rmax);
210
211 if (DATE_IS_NOBEGIN(rmin) || DATE_IS_NOEND(rmax))
213 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
214 errmsg("lower and upper bounds must be finite"));
215
217
218 result = (DateADT) pg_prng_int64_range(&prng_state, rmin, rmax);
219
220 PG_RETURN_DATEADT(result);
221}
222
223/*
224 * timestamp_random() -
225 *
226 * Returns a random timestamp chosen uniformly in the specified range.
227 */
228Datum
230{
231 int64 rmin = (int64) PG_GETARG_TIMESTAMP(0);
232 int64 rmax = (int64) PG_GETARG_TIMESTAMP(1);
233 Timestamp result;
234
235 CHECK_RANGE_BOUNDS(rmin, rmax);
236
237 if (TIMESTAMP_IS_NOBEGIN(rmin) || TIMESTAMP_IS_NOEND(rmax))
239 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
240 errmsg("lower and upper bounds must be finite"));
241
243
244 result = (Timestamp) pg_prng_int64_range(&prng_state, rmin, rmax);
245
246 PG_RETURN_TIMESTAMP(result);
247}
248
249/*
250 * timestamptz_random() -
251 *
252 * Returns a random timestamptz chosen uniformly in the specified range.
253 */
254Datum
256{
259 TimestampTz result;
260
261 CHECK_RANGE_BOUNDS(rmin, rmax);
262
263 if (TIMESTAMP_IS_NOBEGIN(rmin) || TIMESTAMP_IS_NOEND(rmax))
265 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
266 errmsg("lower and upper bounds must be finite"));
267
269
270 result = (TimestampTz) pg_prng_int64_range(&prng_state, rmin, rmax);
271
272 PG_RETURN_TIMESTAMPTZ(result);
273}
Numeric random_numeric(pg_prng_state *state, Numeric rmin, Numeric rmax)
Definition: numeric.c:4205
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1645
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1609
int64_t int64
Definition: c.h:536
double float8
Definition: c.h:636
int32_t int32
Definition: c.h:535
uint64_t uint64
Definition: c.h:540
#define unlikely(x)
Definition: c.h:403
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:167
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:162
#define DATE_IS_NOEND(j)
Definition: date.h:42
#define PG_RETURN_DATEADT(x)
Definition: date.h:93
#define DATE_IS_NOBEGIN(j)
Definition: date.h:40
int32 DateADT
Definition: date.h:23
#define PG_GETARG_DATEADT(n)
Definition: date.h:89
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_FLOAT8(n)
Definition: fmgr.h:282
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
int MyProcPid
Definition: globals.c:47
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:81
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:83
int64 pg_prng_int64_range(pg_prng_state *state, int64 rmin, int64 rmax)
Definition: pg_prng.c:192
double pg_prng_double(pg_prng_state *state)
Definition: pg_prng.c:268
void pg_prng_seed(pg_prng_state *state, uint64 seed)
Definition: pg_prng.c:89
double pg_prng_double_normal(pg_prng_state *state)
Definition: pg_prng.c:290
void pg_prng_fseed(pg_prng_state *state, double fseed)
Definition: pg_prng.c:102
#define pg_prng_strong_seed(state)
Definition: pg_prng.h:46
uint64_t Datum
Definition: postgres.h:70
static void initialize_prng(void)
Datum numeric_random(PG_FUNCTION_ARGS)
static pg_prng_state prng_state
Datum timestamp_random(PG_FUNCTION_ARGS)
Datum date_random(PG_FUNCTION_ARGS)
Datum int4random(PG_FUNCTION_ARGS)
Datum timestamptz_random(PG_FUNCTION_ARGS)
Datum setseed(PG_FUNCTION_ARGS)
static bool prng_seed_set
Datum drandom(PG_FUNCTION_ARGS)
#define CHECK_RANGE_BOUNDS(rmin, rmax)
Datum drandom_normal(PG_FUNCTION_ARGS)
Datum int8random(PG_FUNCTION_ARGS)
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:63
#define PG_RETURN_TIMESTAMP(x)
Definition: timestamp.h:67
#define PG_GETARG_TIMESTAMPTZ(n)
Definition: timestamp.h:64
#define PG_RETURN_TIMESTAMPTZ(x)
Definition: timestamp.h:68