diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 50 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 27 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 23 | ||||
-rw-r--r-- | src/backend/utils/misc/sampling.c | 33 |
4 files changed, 124 insertions, 9 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 903e80aea35..298eebf5e67 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -32,6 +32,7 @@ #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" +#include "catalog/pg_tablesample_method.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" #include "commands/defrem.h" @@ -345,6 +346,8 @@ static void make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags); static void make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, int prettyFlags, int wrapColumn); +static void get_tablesample_def(TableSampleClause *tablesample, + deparse_context *context); static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, TupleDesc resultDesc, int prettyFlags, int wrapColumn, int startIndent); @@ -4220,6 +4223,50 @@ make_viewdef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc, heap_close(ev_relation, AccessShareLock); } +/* ---------- + * get_tablesample_def - Convert TableSampleClause back to SQL + * ---------- + */ +static void +get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) +{ + StringInfo buf = context->buf; + HeapTuple tuple; + Form_pg_tablesample_method tsm; + char *tsmname; + int nargs; + ListCell *l; + + /* Load the tablesample method */ + tuple = SearchSysCache1(TABLESAMPLEMETHODOID, ObjectIdGetDatum(tablesample->tsmid)); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("cache lookup failed for tablesample method %u", + tablesample->tsmid))); + + tsm = (Form_pg_tablesample_method) GETSTRUCT(tuple); + tsmname = NameStr(tsm->tsmname); + appendStringInfo(buf, " TABLESAMPLE %s (", quote_identifier(tsmname)); + + ReleaseSysCache(tuple); + + nargs = 0; + foreach(l, tablesample->args) + { + if (nargs++ > 0) + appendStringInfoString(buf, ", "); + get_rule_expr((Node *) lfirst(l), context, true); + } + appendStringInfoChar(buf, ')'); + + if (tablesample->repeatable != NULL) + { + appendStringInfoString(buf, " REPEATABLE ("); + get_rule_expr(tablesample->repeatable, context, true); + appendStringInfoChar(buf, ')'); + } +} /* ---------- * get_query_def - Parse back one query parsetree @@ -8529,6 +8576,9 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) only_marker(rte), generate_relation_name(rte->relid, context->namespaces)); + + if (rte->tablesample) + get_tablesample_def(rte->tablesample, context); break; case RTE_SUBQUERY: /* Subquery RTE */ diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 1dc293297d9..f259751e157 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -32,6 +32,7 @@ #include "catalog/pg_range.h" #include "catalog/pg_statistic.h" #include "catalog/pg_transform.h" +#include "catalog/pg_tablesample_method.h" #include "catalog/pg_type.h" #include "miscadmin.h" #include "nodes/makefuncs.h" @@ -2996,3 +2997,29 @@ get_range_subtype(Oid rangeOid) else return InvalidOid; } + +/* ---------- PG_TABLESAMPLE_METHOD CACHE ---------- */ + +/* + * get_tablesample_method_name - given a tablesample method OID, + * look up the name or NULL if not found + */ +char * +get_tablesample_method_name(Oid tsmid) +{ + HeapTuple tuple; + + tuple = SearchSysCache1(TABLESAMPLEMETHODOID, ObjectIdGetDatum(tsmid)); + if (HeapTupleIsValid(tuple)) + { + Form_pg_tablesample_method tup = + (Form_pg_tablesample_method) GETSTRUCT(tuple); + char *result; + + result = pstrdup(NameStr(tup->tsmname)); + ReleaseSysCache(tuple); + return result; + } + else + return NULL; +} diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index f58e1cebf2a..7def1be32ae 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -56,6 +56,7 @@ #include "catalog/pg_shseclabel.h" #include "catalog/pg_replication_origin.h" #include "catalog/pg_statistic.h" +#include "catalog/pg_tablesample_method.h" #include "catalog/pg_tablespace.h" #include "catalog/pg_transform.h" #include "catalog/pg_ts_config.h" @@ -666,6 +667,28 @@ static const struct cachedesc cacheinfo[] = { }, 128 }, + {TableSampleMethodRelationId, /* TABLESAMPLEMETHODNAME */ + TableSampleMethodNameIndexId, + 1, + { + Anum_pg_tablesample_method_tsmname, + 0, + 0, + 0, + }, + 2 + }, + {TableSampleMethodRelationId, /* TABLESAMPLEMETHODOID */ + TableSampleMethodOidIndexId, + 1, + { + ObjectIdAttributeNumber, + 0, + 0, + 0, + }, + 2 + }, {TableSpaceRelationId, /* TABLESPACEOID */ TablespaceOidIndexId, 1, diff --git a/src/backend/utils/misc/sampling.c b/src/backend/utils/misc/sampling.c index 1eeabaf1588..9becc63bf82 100644 --- a/src/backend/utils/misc/sampling.c +++ b/src/backend/utils/misc/sampling.c @@ -46,6 +46,8 @@ BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize, bs->n = samplesize; bs->t = 0; /* blocks scanned so far */ bs->m = 0; /* blocks selected so far */ + + sampler_random_init_state(randseed, bs->randstate); } bool @@ -92,7 +94,7 @@ BlockSampler_Next(BlockSampler bs) * less than k, which means that we cannot fail to select enough blocks. *---------- */ - V = sampler_random_fract(); + V = sampler_random_fract(bs->randstate); p = 1.0 - (double) k / (double) K; while (V < p) { @@ -126,8 +128,14 @@ BlockSampler_Next(BlockSampler bs) void reservoir_init_selection_state(ReservoirState rs, int n) { + /* + * Reservoir sampling is not used anywhere where it would need to return + * repeatable results so we can initialize it randomly. + */ + sampler_random_init_state(random(), rs->randstate); + /* Initial value of W (for use when Algorithm Z is first applied) */ - *rs = exp(-log(sampler_random_fract()) / n); + rs->W = exp(-log(sampler_random_fract(rs->randstate)) / n); } double @@ -142,7 +150,7 @@ reservoir_get_next_S(ReservoirState rs, double t, int n) double V, quot; - V = sampler_random_fract(); /* Generate V */ + V = sampler_random_fract(rs->randstate); /* Generate V */ S = 0; t += 1; /* Note: "num" in Vitter's code is always equal to t - n */ @@ -158,7 +166,7 @@ reservoir_get_next_S(ReservoirState rs, double t, int n) else { /* Now apply Algorithm Z */ - double W = *rs; + double W = rs->W; double term = t - (double) n + 1; for (;;) @@ -174,7 +182,7 @@ reservoir_get_next_S(ReservoirState rs, double t, int n) tmp; /* Generate U and X */ - U = sampler_random_fract(); + U = sampler_random_fract(rs->randstate); X = t * (W - 1.0); S = floor(X); /* S is tentatively set to floor(X) */ /* Test if U <= h(S)/cg(X) in the manner of (6.3) */ @@ -203,11 +211,11 @@ reservoir_get_next_S(ReservoirState rs, double t, int n) y *= numer / denom; denom -= 1; } - W = exp(-log(sampler_random_fract()) / n); /* Generate W in advance */ + W = exp(-log(sampler_random_fract(rs->randstate)) / n); /* Generate W in advance */ if (exp(log(y) / n) <= (t + X) / t) break; } - *rs = W; + rs->W = W; } return S; } @@ -217,10 +225,17 @@ reservoir_get_next_S(ReservoirState rs, double t, int n) * Random number generator used by sampling *---------- */ +void +sampler_random_init_state(long seed, SamplerRandomState randstate) +{ + randstate[0] = RAND48_SEED_0; + randstate[1] = (unsigned short) seed; + randstate[2] = (unsigned short) (seed >> 16); +} /* Select a random value R uniformly distributed in (0 - 1) */ double -sampler_random_fract() +sampler_random_fract(SamplerRandomState randstate) { - return ((double) random() + 1) / ((double) MAX_RANDOM_VALUE + 2); + return pg_erand48(randstate); } |