34 #include "utils/fmgrprotos.h"
40 int k,
int *combination);
46 #define SizeOfHeader (3 * sizeof(uint32))
49 #define SizeOfItem(natts) \
50 (sizeof(double) + sizeof(int) + (natts) * sizeof(AttrNumber))
53 #define MinSizeOfItem SizeOfItem(2)
56 #define MinSizeOfItems(nitems) \
57 (SizeOfHeader + (nitems) * MinSizeOfItem)
94 int numattrs =
data->nattnums;
101 result->
nitems = numcombs;
104 for (k = 2; k <= numattrs; k++)
121 for (
j = 0;
j < k;
j++)
159 elog(
ERROR,
"cache lookup failed for statistics object %u", mvoid);
162 Anum_pg_statistic_ext_data_stxdndistinct, &isnull);
165 "requested statistics kind \"%c\" is not yet built for statistics object %u",
166 STATS_EXT_NDISTINCT, mvoid);
215 memcpy(tmp, &ndistinct->
type,
sizeof(
uint32));
228 memcpy(tmp, &item.
ndistinct,
sizeof(
double));
229 tmp +=
sizeof(double);
230 memcpy(tmp, &nmembers,
sizeof(
int));
264 elog(
ERROR,
"invalid MVNDistinct size %zu (expected at least %zu)",
279 elog(
ERROR,
"invalid ndistinct magic %08x (expected %08x)",
282 elog(
ERROR,
"invalid ndistinct type %d (expected %d)",
285 elog(
ERROR,
"invalid zero-length item array in MVNDistinct");
290 elog(
ERROR,
"invalid MVNDistinct size %zu (expected at least %zu)",
308 memcpy(&item->
ndistinct, tmp,
sizeof(
double));
309 tmp +=
sizeof(double);
343 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
344 errmsg(
"cannot accept a value of type %s",
"pg_ndistinct")));
396 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
397 errmsg(
"cannot accept a value of type %s",
"pg_ndistinct")));
427 int k,
int *combination)
438 int numrows =
data->numrows;
450 isnull = (
bool *)
palloc0(
sizeof(
bool) * numrows * k);
452 for (
i = 0;
i < numrows;
i++)
465 for (
i = 0;
i < k;
i++)
477 elog(
ERROR,
"cache lookup failed for ordering operator for type %u",
484 for (
j = 0;
j < numrows;
j++)
500 for (
i = 1;
i < numrows;
i++)
528 numer = (double) numrows * (
double) d;
530 denom = (double) (numrows -
f1) +
531 (double)
f1 * (
double) numrows / totalrows;
533 ndistinct = numer / denom;
536 if (ndistinct < (
double) d)
537 ndistinct = (
double) d;
539 if (ndistinct > totalrows)
540 ndistinct = totalrows;
542 return floor(ndistinct + 0.5);
556 Assert((k > 0) && (n >= k));
562 for (d = 1; d <= k; ++d)
578 return (1 << n) - (n + 1);
594 Assert((n >= k) && (k > 0));
602 state->combinations = (
int *)
palloc(
sizeof(
int) * k *
state->ncombinations);
659 int index,
int start,
int *current)
683 current,
state->k *
sizeof(
int));
#define AttributeNumberIsValid(attributeNumber)
static Datum values[MAXATTR]
elog(ERROR, "%s: %s", p2, msg)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
int multi_sort_compare(const void *a, const void *b, void *arg)
MultiSortSupport multi_sort_init(int ndims)
void multi_sort_add_dimension(MultiSortSupport mss, int sortdim, Oid oper, Oid collation)
#define PG_GETARG_BYTEA_PP(n)
#define DatumGetByteaPP(X)
#define PG_RETURN_CSTRING(x)
#define HeapTupleIsValid(tuple)
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
void * palloc0(Size size)
Datum pg_ndistinct_out(PG_FUNCTION_ARGS)
MVNDistinct * statext_ndistinct_load(Oid mvoid, bool inh)
static int n_choose_k(int n, int k)
Datum pg_ndistinct_in(PG_FUNCTION_ARGS)
struct CombinationGenerator CombinationGenerator
static double estimate_ndistinct(double totalrows, int numrows, int d, int f1)
bytea * statext_ndistinct_serialize(MVNDistinct *ndistinct)
static void generate_combinations_recurse(CombinationGenerator *state, int index, int start, int *current)
Datum pg_ndistinct_recv(PG_FUNCTION_ARGS)
static double ndistinct_for_combination(double totalrows, StatsBuildData *data, int k, int *combination)
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
static void generate_combinations(CombinationGenerator *state)
static int num_combinations(int n)
MVNDistinct * statext_ndistinct_build(double totalrows, StatsBuildData *data)
#define SizeOfItem(natts)
static void generator_free(CombinationGenerator *state)
static CombinationGenerator * generator_init(int n, int k)
Datum pg_ndistinct_send(PG_FUNCTION_ARGS)
#define MinSizeOfItems(nitems)
static int * generator_next(CombinationGenerator *state)
void qsort_interruptible(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
#define STATS_NDISTINCT_MAGIC
#define STATS_NDISTINCT_TYPE_BASIC
#define STATS_MAX_DIMENSIONS
void appendStringInfo(StringInfo str, const char *fmt,...)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
MVNDistinctItem items[FLEXIBLE_ARRAY_MEMBER]
void ReleaseSysCache(HeapTuple tuple)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define SET_VARSIZE(PTR, len)
#define VARSIZE_ANY_EXHDR(PTR)
Datum byteasend(PG_FUNCTION_ARGS)