From 9426047021651d8d7b6595c1377aef1909afcacd Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 7 Aug 2000 00:51:42 +0000 Subject: [PATCH] Clean up bogosities in use of random(3) and srandom(3) --- do not assume that RAND_MAX applies to them, since it doesn't. Instead add a config.h parameter MAX_RANDOM_VALUE. This is currently set at 2^31-1 but could be auto-configured if that ever proves necessary. Also fix some outright bugs like calling srand() where srandom() is appropriate. --- doc/src/sgml/func.sgml | 12 ++++++++++++ doc/src/sgml/ref/set.sgml | 6 +++--- src/backend/optimizer/geqo/geqo_main.c | 6 +++--- src/backend/postmaster/postmaster.c | 5 ++--- src/backend/utils/adt/float.c | 6 +++--- src/backend/utils/adt/misc.c | 14 ++++++++------ src/include/config.h.in | 11 ++++++++++- src/include/optimizer/geqo_random.h | 12 ++++++------ 8 files changed, 47 insertions(+), 25 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 2e7144b147..aa7e2b0989 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -171,6 +171,18 @@ convert floating point to integer integer(2.0) + + random() + float8 + random value in the range 0.0 to 1.0 + random() + + + setseed(float8) + int + set seed for subsequent random() calls + setseed(0.54823) + diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml index 7f36aae9d7..b76570d5de 100644 --- a/doc/src/sgml/ref/set.sgml +++ b/doc/src/sgml/ref/set.sgml @@ -1,5 +1,5 @@ @@ -194,9 +194,9 @@ SET TIME ZONE { 'timezone' | LOCAL The value for the seed to be used by the - random catalog function. Significant + random function. Allowed values are floating point numbers between 0 and 1, which - are then multiplied by RAND_MAX. This product will + are then multiplied by 2^31-1. This product will silently overflow if a number outside the range is used. diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c index 4f2f63572c..eb99c2478f 100644 --- a/src/backend/optimizer/geqo/geqo_main.c +++ b/src/backend/optimizer/geqo/geqo_main.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: geqo_main.c,v 1.22 2000/06/28 03:31:45 tgl Exp $ + * $Id: geqo_main.c,v 1.23 2000/08/07 00:51:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -106,9 +106,9 @@ geqo(Query *root) /* seed random number generator */ /* XXX why is this done every time around? */ if (Geqo_random_seed >= 0) - srandom(Geqo_random_seed); + srandom((unsigned int) Geqo_random_seed); else - srandom(time(NULL)); + srandom((unsigned int) time(NULL)); /* allocate genetic pool memory */ pool = alloc_pool(pool_size, number_of_rels); diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 629ab48e8c..9626f3bcf8 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.158 2000/07/28 02:13:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.159 2000/08/07 00:51:30 tgl Exp $ * * NOTES * @@ -1850,7 +1850,7 @@ DoBackend(Port *port) */ random_seed = 0; gettimeofday(&now, &tz); - srandom(now.tv_usec); + srandom((unsigned int) now.tv_usec); /* ---------------- * Now, build the argv vector that will be given to PostgresMain. @@ -2029,7 +2029,6 @@ RandomSalt(char *salt) static long PostmasterRandom(void) { - static bool initialized = false; if (!initialized) diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 54735191a9..7c06e31ed8 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.67 2000/08/01 18:29:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.68 2000/08/07 00:51:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1315,7 +1315,7 @@ drandom(PG_FUNCTION_ARGS) float8 result; /* result 0.0-1.0 */ - result = ((double) random()) / RAND_MAX; + result = ((double) random()) / ((double) MAX_RANDOM_VALUE); PG_RETURN_FLOAT8(result); } @@ -1328,7 +1328,7 @@ Datum setseed(PG_FUNCTION_ARGS) { float8 seed = PG_GETARG_FLOAT8(0); - int iseed = (seed * RAND_MAX); + int iseed = (int) (seed * MAX_RANDOM_VALUE); srandom((unsigned int) iseed); diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 7e3b8b167b..7711cf7cdd 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v 1.19 2000/06/05 07:28:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v 1.20 2000/08/07 00:51:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,15 +45,18 @@ nonnullvalue(PG_FUNCTION_ARGS) /* * oidrand (oid o, int4 X)- - * takes in an oid and a int4 X, and will return 'true' - * about 1/X of the time. + * Takes in an oid and a int4 X, and will return 'true' about 1/X of + * the time. If X == 0, this will always return true. * Useful for doing random sampling or subsetting. - * if X == 0, this will always return true; * * Example use: * select * from TEMP where oidrand(TEMP.oid, 10) * will return about 1/10 of the tuples in TEMP * + * NOTE: the OID input is not used at all. It is there just because of + * an old optimizer bug: a qual expression containing no variables was + * mistakenly assumed to be a constant. Pretending to access the row's OID + * prevented the optimizer from treating the oidrand() result as constant. */ static bool random_initialized = false; @@ -61,7 +64,6 @@ static bool random_initialized = false; Datum oidrand(PG_FUNCTION_ARGS) { - /* XXX seems like we ought to be using the oid for something? */ #ifdef NOT_USED Oid o = PG_GETARG_OID(0); #endif @@ -96,7 +98,7 @@ oidsrand(PG_FUNCTION_ARGS) { int32 X = PG_GETARG_INT32(0); - srand(X); + srandom((unsigned int) X); random_initialized = true; PG_RETURN_BOOL(true); } diff --git a/src/include/config.h.in b/src/include/config.h.in index 7e5413994f..63c7c21b7b 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -8,7 +8,7 @@ * or in config.h afterwards. Of course, if you edit config.h, then your * changes will be overwritten the next time you run configure. * - * $Id: config.h.in,v 1.128 2000/07/28 02:13:40 tgl Exp $ + * $Id: config.h.in,v 1.129 2000/08/07 00:51:38 tgl Exp $ */ #ifndef CONFIG_H @@ -484,6 +484,15 @@ extern long random(void); extern void srandom(unsigned int seed); #endif +/* The random() function is expected to yield values 0 .. MAX_RANDOM_VALUE */ +/* Currently, all known implementations yield 0..2^31-1, so we just hardwire + * this constant. We could do a configure test if it proves to be necessary. + * CAUTION: Think not to replace this with RAND_MAX. RAND_MAX defines the + * maximum value of the older rand() function, which is often different from + * --- and considerably inferior to --- random(). + */ +#define MAX_RANDOM_VALUE (0x7FFFFFFF) + /* Set to 1 if you have libz.a */ #undef HAVE_LIBZ diff --git a/src/include/optimizer/geqo_random.h b/src/include/optimizer/geqo_random.h index c005b331b6..a2203367e7 100644 --- a/src/include/optimizer/geqo_random.h +++ b/src/include/optimizer/geqo_random.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: geqo_random.h,v 1.6 2000/01/26 05:58:20 momjian Exp $ + * $Id: geqo_random.h,v 1.7 2000/08/07 00:51:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,13 +26,13 @@ #include -#define GEQOMASK 2147483647 +/* geqo_rand returns a random float value between 0 and 1 inclusive */ -#define geqo_rand() ((double)random()/GEQOMASK) +#define geqo_rand() (((double) random()) / ((double) MAX_RANDOM_VALUE)) -/* geqo_randint returns integer value - between lower and upper inclusive */ +/* geqo_randint returns integer value between lower and upper inclusive */ -#define geqo_randint(upper,lower) ( (int) floor( geqo_rand()*((upper-lower)+0.999999) ) + lower ) +#define geqo_randint(upper,lower) \ + ( (int) floor( geqo_rand()*(((upper)-(lower))+0.999999) ) + (lower) ) #endif /* GEQO_RANDOM_H */ -- 2.40.0