summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/activity/pgstat.c11
-rw-r--r--src/backend/utils/activity/pgstat_shmem.c28
-rw-r--r--src/backend/utils/adt/jsonbsubs.c2
-rw-r--r--src/backend/utils/adt/pseudorandomfuncs.c104
-rw-r--r--src/backend/utils/misc/guc_parameters.dat6
-rw-r--r--src/backend/utils/misc/guc_tables.c1
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample1
7 files changed, 143 insertions, 10 deletions
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index ffb5b8cce34..f8e91484e36 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -1975,6 +1975,17 @@ pgstat_read_statsfile(void)
header = pgstat_init_entry(key.kind, p);
dshash_release_lock(pgStatLocal.shared_hash, p);
+ if (header == NULL)
+ {
+ /*
+ * It would be tempting to switch this ERROR to a
+ * WARNING, but it would mean that all the statistics
+ * are discarded when the environment fails on OOM.
+ */
+ elog(ERROR, "could not allocate entry %u/%u/%" PRIu64 " of type %c",
+ key.kind, key.dboid,
+ key.objid, t);
+ }
if (!read_chunk(fpin,
pgstat_get_entry_data(key.kind, header),
diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c
index 62de3474453..9dc3212f7dd 100644
--- a/src/backend/utils/activity/pgstat_shmem.c
+++ b/src/backend/utils/activity/pgstat_shmem.c
@@ -289,6 +289,13 @@ pgstat_detach_shmem(void)
* ------------------------------------------------------------
*/
+/*
+ * Initialize entry newly-created.
+ *
+ * Returns NULL in the event of an allocation failure, so as callers can
+ * take cleanup actions as the entry initialized is already inserted in the
+ * shared hashtable.
+ */
PgStatShared_Common *
pgstat_init_entry(PgStat_Kind kind,
PgStatShared_HashEntry *shhashent)
@@ -311,7 +318,12 @@ pgstat_init_entry(PgStat_Kind kind,
pg_atomic_init_u32(&shhashent->generation, 0);
shhashent->dropped = false;
- chunk = dsa_allocate0(pgStatLocal.dsa, pgstat_get_kind_info(kind)->shared_size);
+ chunk = dsa_allocate_extended(pgStatLocal.dsa,
+ pgstat_get_kind_info(kind)->shared_size,
+ DSA_ALLOC_ZERO | DSA_ALLOC_NO_OOM);
+ if (chunk == InvalidDsaPointer)
+ return NULL;
+
shheader = dsa_get_address(pgStatLocal.dsa, chunk);
shheader->magic = 0xdeadbeef;
@@ -509,6 +521,20 @@ pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create,
if (!shfound)
{
shheader = pgstat_init_entry(kind, shhashent);
+ if (shheader == NULL)
+ {
+ /*
+ * Failed the allocation of a new entry, so clean up the
+ * shared hashtable before giving up.
+ */
+ dshash_delete_entry(pgStatLocal.shared_hash, shhashent);
+
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed while allocating entry %u/%u/%" PRIu64 ".",
+ key.kind, key.dboid, key.objid)));
+ }
pgstat_acquire_entry_ref(entry_ref, shhashent, shheader);
if (created_entry != NULL)
diff --git a/src/backend/utils/adt/jsonbsubs.c b/src/backend/utils/adt/jsonbsubs.c
index de64d498512..e8626d3b4fc 100644
--- a/src/backend/utils/adt/jsonbsubs.c
+++ b/src/backend/utils/adt/jsonbsubs.c
@@ -51,7 +51,7 @@ jsonb_subscript_transform(SubscriptingRef *sbsref,
/*
* Transform and convert the subscript expressions. Jsonb subscripting
- * does not support slices, look only and the upper index.
+ * does not support slices, look only at the upper index.
*/
foreach(idx, indirection)
{
diff --git a/src/backend/utils/adt/pseudorandomfuncs.c b/src/backend/utils/adt/pseudorandomfuncs.c
index e7b8045f925..1d2a981491b 100644
--- a/src/backend/utils/adt/pseudorandomfuncs.c
+++ b/src/backend/utils/adt/pseudorandomfuncs.c
@@ -17,6 +17,7 @@
#include "common/pg_prng.h"
#include "miscadmin.h"
+#include "utils/date.h"
#include "utils/fmgrprotos.h"
#include "utils/numeric.h"
#include "utils/timestamp.h"
@@ -26,6 +27,18 @@ static pg_prng_state prng_state;
static bool prng_seed_set = false;
/*
+ * Macro for checking the range bounds of random(min, max) functions. Throws
+ * an error if they're the wrong way round.
+ */
+#define CHECK_RANGE_BOUNDS(rmin, rmax) \
+ do { \
+ if ((rmin) > (rmax)) \
+ ereport(ERROR, \
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
+ errmsg("lower bound must be less than or equal to upper bound")); \
+ } while (0)
+
+/*
* initialize_prng() -
*
* Initialize (seed) the PRNG, if not done yet in this process.
@@ -129,10 +142,7 @@ int4random(PG_FUNCTION_ARGS)
int32 rmax = PG_GETARG_INT32(1);
int32 result;
- if (rmin > rmax)
- ereport(ERROR,
- errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("lower bound must be less than or equal to upper bound"));
+ CHECK_RANGE_BOUNDS(rmin, rmax);
initialize_prng();
@@ -153,10 +163,7 @@ int8random(PG_FUNCTION_ARGS)
int64 rmax = PG_GETARG_INT64(1);
int64 result;
- if (rmin > rmax)
- ereport(ERROR,
- errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("lower bound must be less than or equal to upper bound"));
+ CHECK_RANGE_BOUNDS(rmin, rmax);
initialize_prng();
@@ -177,9 +184,90 @@ numeric_random(PG_FUNCTION_ARGS)
Numeric rmax = PG_GETARG_NUMERIC(1);
Numeric result;
+ /* Leave range bound checking to random_numeric() */
+
initialize_prng();
result = random_numeric(&prng_state, rmin, rmax);
PG_RETURN_NUMERIC(result);
}
+
+
+/*
+ * date_random() -
+ *
+ * Returns a random date chosen uniformly in the specified range.
+ */
+Datum
+date_random(PG_FUNCTION_ARGS)
+{
+ int32 rmin = (int32) PG_GETARG_DATEADT(0);
+ int32 rmax = (int32) PG_GETARG_DATEADT(1);
+ DateADT result;
+
+ CHECK_RANGE_BOUNDS(rmin, rmax);
+
+ if (DATE_IS_NOBEGIN(rmin) || DATE_IS_NOEND(rmax))
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("lower and upper bounds must be finite"));
+
+ initialize_prng();
+
+ result = (DateADT) pg_prng_int64_range(&prng_state, rmin, rmax);
+
+ PG_RETURN_DATEADT(result);
+}
+
+/*
+ * timestamp_random() -
+ *
+ * Returns a random timestamp chosen uniformly in the specified range.
+ */
+Datum
+timestamp_random(PG_FUNCTION_ARGS)
+{
+ int64 rmin = (int64) PG_GETARG_TIMESTAMP(0);
+ int64 rmax = (int64) PG_GETARG_TIMESTAMP(1);
+ Timestamp result;
+
+ CHECK_RANGE_BOUNDS(rmin, rmax);
+
+ if (TIMESTAMP_IS_NOBEGIN(rmin) || TIMESTAMP_IS_NOEND(rmax))
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("lower and upper bounds must be finite"));
+
+ initialize_prng();
+
+ result = (Timestamp) pg_prng_int64_range(&prng_state, rmin, rmax);
+
+ PG_RETURN_TIMESTAMP(result);
+}
+
+/*
+ * timestamptz_random() -
+ *
+ * Returns a random timestamptz chosen uniformly in the specified range.
+ */
+Datum
+timestamptz_random(PG_FUNCTION_ARGS)
+{
+ int64 rmin = (int64) PG_GETARG_TIMESTAMPTZ(0);
+ int64 rmax = (int64) PG_GETARG_TIMESTAMPTZ(1);
+ TimestampTz result;
+
+ CHECK_RANGE_BOUNDS(rmin, rmax);
+
+ if (TIMESTAMP_IS_NOBEGIN(rmin) || TIMESTAMP_IS_NOEND(rmax))
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("lower and upper bounds must be finite"));
+
+ initialize_prng();
+
+ result = (TimestampTz) pg_prng_int64_range(&prng_state, rmin, rmax);
+
+ PG_RETURN_TIMESTAMPTZ(result);
+}
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index a157cec3c4d..0da01627cfe 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -414,6 +414,12 @@
ifdef => 'DEBUG_NODE_TESTS_ENABLED',
},
+{ name => 'debug_print_raw_parse', type => 'bool', context => 'PGC_USERSET', group => 'LOGGING_WHAT',
+ short_desc => 'Logs each query\'s raw parse tree.',
+ variable => 'Debug_print_raw_parse',
+ boot_val => 'false',
+},
+
{ name => 'debug_print_parse', type => 'bool', context => 'PGC_USERSET', group => 'LOGGING_WHAT',
short_desc => 'Logs each query\'s parse tree.',
variable => 'Debug_print_parse',
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 787933a9e5a..00c8376cf4d 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -507,6 +507,7 @@ bool AllowAlterSystem = true;
bool log_duration = false;
bool Debug_print_plan = false;
bool Debug_print_parse = false;
+bool Debug_print_raw_parse = false;
bool Debug_print_rewritten = false;
bool Debug_pretty_print = true;
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index a9d8293474a..26c08693564 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -581,6 +581,7 @@
# - What to Log -
+#debug_print_raw_parse = off
#debug_print_parse = off
#debug_print_rewritten = off
#debug_print_plan = off