Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e634132

Browse files
committed
Add functions to generate random numbers in a specified range.
This adds 3 new variants of the random() function: random(min integer, max integer) returns integer random(min bigint, max bigint) returns bigint random(min numeric, max numeric) returns numeric Each returns a random number x in the range min <= x <= max. For the numeric function, the number of digits after the decimal point is equal to the number of digits that "min" or "max" has after the decimal point, whichever has more. The main entry points for these functions are in a new C source file. The existing random(), random_normal(), and setseed() functions are moved there too, so that they can all share the same PRNG state, which is kept private to that file. Dean Rasheed, reviewed by Jian He, David Zhang, Aleksander Alekseev, and Tomas Vondra. Discussion: https://postgr.es/m/CAEZATCV89Vxuq93xQdmc0t-0Y2zeeNQTdsjbmV7dyFBPykbV4Q@mail.gmail.com
1 parent 818861e commit e634132

File tree

13 files changed

+1022
-101
lines changed

13 files changed

+1022
-101
lines changed

doc/src/sgml/func.sgml

+38-5
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,39 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in
18621862
</para></entry>
18631863
</row>
18641864

1865+
<row>
1866+
<entry role="func_table_entry"><para role="func_signature">
1867+
<indexterm>
1868+
<primary>random</primary>
1869+
</indexterm>
1870+
<function>random</function> ( <parameter>min</parameter> <type>integer</type>, <parameter>max</parameter> <type>integer</type> )
1871+
<returnvalue>integer</returnvalue>
1872+
</para>
1873+
<para role="func_signature">
1874+
<function>random</function> ( <parameter>min</parameter> <type>bigint</type>, <parameter>max</parameter> <type>bigint</type> )
1875+
<returnvalue>bigint</returnvalue>
1876+
</para>
1877+
<para role="func_signature">
1878+
<function>random</function> ( <parameter>min</parameter> <type>numeric</type>, <parameter>max</parameter> <type>numeric</type> )
1879+
<returnvalue>numeric</returnvalue>
1880+
</para>
1881+
<para>
1882+
Returns a random value in the range
1883+
<parameter>min</parameter> &lt;= x &lt;= <parameter>max</parameter>.
1884+
For type <type>numeric</type>, the result will have the same number of
1885+
fractional decimal digits as <parameter>min</parameter> or
1886+
<parameter>max</parameter>, whichever has more.
1887+
</para>
1888+
<para>
1889+
<literal>random(1, 10)</literal>
1890+
<returnvalue>7</returnvalue>
1891+
</para>
1892+
<para>
1893+
<literal>random(-0.499, 0.499)</literal>
1894+
<returnvalue>0.347</returnvalue>
1895+
</para></entry>
1896+
</row>
1897+
18651898
<row>
18661899
<entry role="func_table_entry"><para role="func_signature">
18671900
<indexterm>
@@ -1906,19 +1939,19 @@ SELECT NOT(ROW(table.*) IS NOT NULL) FROM TABLE; -- detect at least one null in
19061939
</table>
19071940

19081941
<para>
1909-
The <function>random()</function> function uses a deterministic
1910-
pseudo-random number generator.
1942+
The <function>random()</function> and <function>random_normal()</function>
1943+
functions listed in <xref linkend="functions-math-random-table"/> use a
1944+
deterministic pseudo-random number generator.
19111945
It is fast but not suitable for cryptographic
19121946
applications; see the <xref linkend="pgcrypto"/> module for a more
19131947
secure alternative.
19141948
If <function>setseed()</function> is called, the series of results of
1915-
subsequent <function>random()</function> calls in the current session
1949+
subsequent calls to these functions in the current session
19161950
can be repeated by re-issuing <function>setseed()</function> with the same
19171951
argument.
19181952
Without any prior <function>setseed()</function> call in the same
1919-
session, the first <function>random()</function> call obtains a seed
1953+
session, the first call to any of these functions obtains a seed
19201954
from a platform-dependent source of random bits.
1921-
These remarks hold equally for <function>random_normal()</function>.
19221955
</para>
19231956

19241957
<para>

src/backend/utils/adt/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ OBJS = \
8282
pg_lsn.o \
8383
pg_upgrade_support.o \
8484
pgstatfuncs.o \
85+
pseudorandomfuncs.o \
8586
pseudotypes.o \
8687
quote.o \
8788
rangetypes.o \

src/backend/utils/adt/float.c

-95
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@
2121

2222
#include "catalog/pg_type.h"
2323
#include "common/int.h"
24-
#include "common/pg_prng.h"
2524
#include "common/shortest_dec.h"
2625
#include "libpq/pqformat.h"
27-
#include "miscadmin.h"
2826
#include "utils/array.h"
2927
#include "utils/float.h"
3028
#include "utils/fmgrprotos.h"
@@ -64,10 +62,6 @@ float8 degree_c_sixty = 60.0;
6462
float8 degree_c_one_half = 0.5;
6563
float8 degree_c_one = 1.0;
6664

67-
/* State for drandom() and setseed() */
68-
static bool drandom_seed_set = false;
69-
static pg_prng_state drandom_seed;
70-
7165
/* Local function prototypes */
7266
static double sind_q1(double x);
7367
static double cosd_q1(double x);
@@ -2785,95 +2779,6 @@ derfc(PG_FUNCTION_ARGS)
27852779
}
27862780

27872781

2788-
/* ========== RANDOM FUNCTIONS ========== */
2789-
2790-
2791-
/*
2792-
* initialize_drandom_seed - initialize drandom_seed if not yet done
2793-
*/
2794-
static void
2795-
initialize_drandom_seed(void)
2796-
{
2797-
/* Initialize random seed, if not done yet in this process */
2798-
if (unlikely(!drandom_seed_set))
2799-
{
2800-
/*
2801-
* If possible, initialize the seed using high-quality random bits.
2802-
* Should that fail for some reason, we fall back on a lower-quality
2803-
* seed based on current time and PID.
2804-
*/
2805-
if (unlikely(!pg_prng_strong_seed(&drandom_seed)))
2806-
{
2807-
TimestampTz now = GetCurrentTimestamp();
2808-
uint64 iseed;
2809-
2810-
/* Mix the PID with the most predictable bits of the timestamp */
2811-
iseed = (uint64) now ^ ((uint64) MyProcPid << 32);
2812-
pg_prng_seed(&drandom_seed, iseed);
2813-
}
2814-
drandom_seed_set = true;
2815-
}
2816-
}
2817-
2818-
/*
2819-
* drandom - returns a random number
2820-
*/
2821-
Datum
2822-
drandom(PG_FUNCTION_ARGS)
2823-
{
2824-
float8 result;
2825-
2826-
initialize_drandom_seed();
2827-
2828-
/* pg_prng_double produces desired result range [0.0 - 1.0) */
2829-
result = pg_prng_double(&drandom_seed);
2830-
2831-
PG_RETURN_FLOAT8(result);
2832-
}
2833-
2834-
/*
2835-
* drandom_normal - returns a random number from a normal distribution
2836-
*/
2837-
Datum
2838-
drandom_normal(PG_FUNCTION_ARGS)
2839-
{
2840-
float8 mean = PG_GETARG_FLOAT8(0);
2841-
float8 stddev = PG_GETARG_FLOAT8(1);
2842-
float8 result,
2843-
z;
2844-
2845-
initialize_drandom_seed();
2846-
2847-
/* Get random value from standard normal(mean = 0.0, stddev = 1.0) */
2848-
z = pg_prng_double_normal(&drandom_seed);
2849-
/* Transform the normal standard variable (z) */
2850-
/* using the target normal distribution parameters */
2851-
result = (stddev * z) + mean;
2852-
2853-
PG_RETURN_FLOAT8(result);
2854-
}
2855-
2856-
/*
2857-
* setseed - set seed for the random number generator
2858-
*/
2859-
Datum
2860-
setseed(PG_FUNCTION_ARGS)
2861-
{
2862-
float8 seed = PG_GETARG_FLOAT8(0);
2863-
2864-
if (seed < -1 || seed > 1 || isnan(seed))
2865-
ereport(ERROR,
2866-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2867-
errmsg("setseed parameter %g is out of allowed range [-1,1]",
2868-
seed)));
2869-
2870-
pg_prng_fseed(&drandom_seed, seed);
2871-
drandom_seed_set = true;
2872-
2873-
PG_RETURN_VOID();
2874-
}
2875-
2876-
28772782

28782783
/*
28792784
* =========================

src/backend/utils/adt/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ backend_sources += files(
6969
'pg_lsn.c',
7070
'pg_upgrade_support.c',
7171
'pgstatfuncs.c',
72+
'pseudorandomfuncs.c',
7273
'pseudotypes.c',
7374
'quote.c',
7475
'rangetypes.c',

0 commit comments

Comments
 (0)