29 #include "utils/fmgrprotos.h"
53 #define ITEM_SIZE(ndims) \
54 ((ndims) * (sizeof(uint16) + sizeof(bool)) + 2 * sizeof(double))
59 #define MinSizeOfMCVList \
60 (VARHDRSZ + sizeof(uint32) * 3 + sizeof(AttrNumber))
68 #define SizeOfMCVList(ndims,nitems) \
69 ((MinSizeOfMCVList + sizeof(Oid) * (ndims)) + \
70 ((ndims) * sizeof(DimensionInfo)) + \
71 ((nitems) * ITEM_SIZE(ndims)))
88 #define RESULT_MERGE(value, is_or, match) \
89 ((is_or) ? ((value) || (match)) : ((value) && (match)))
100 #define RESULT_IS_FINAL(value, is_or) ((is_or) ? (value) : (!(value)))
150 double n = samplerows;
151 double N = totalrows;
156 denom = N - n + 0.04 * n * (N - 1);
162 return numer / denom;
204 numattrs =
data->nattnums;
205 numrows =
data->numrows;
246 if (groups[
i].count < mincount)
273 nfreqs = (
int *)
palloc0(
sizeof(
int) * numattrs);
288 for (
i = 0;
i < numattrs;
i++)
298 item->
isnull = (
bool *)
palloc(
sizeof(
bool) * numattrs);
302 memcpy(item->
isnull, groups[
i].
isnull,
sizeof(
bool) * numattrs);
305 Assert((
i == 0) || (groups[
i - 1].count >= groups[
i].count));
308 item->
frequency = (double) groups[
i].count / numrows;
312 for (
j = 0;
j < numattrs;
j++)
350 int numattrs =
data->nattnums;
356 for (
i = 0;
i < numattrs;
i++)
363 elog(
ERROR,
"cache lookup failed for ordering operator for type %u",
385 for (
i = 1;
i < numrows;
i++)
434 groups[0] =
items[0];
437 for (
i = 1;
i < numrows;
i++)
459 *ndistinct = ngroups;
509 for (dim = 0; dim < mss->
ndims; dim++)
518 for (
i = 0;
i < ngroups;
i++)
536 for (
i = 1;
i < ngroups;
i++)
540 result[dim][ncounts[dim] - 1].
count += result[dim][
i].
count;
544 result[dim][ncounts[dim]] = result[dim][
i];
567 elog(
ERROR,
"cache lookup failed for statistics object %u", mvoid);
570 Anum_pg_statistic_ext_data_stxdmcv, &isnull);
574 "requested statistics kind \"%c\" is not yet built for statistics object %u",
575 STATS_EXT_MCV, mvoid);
639 int *counts = (
int *)
palloc0(
sizeof(
int) * ndims);
655 for (dim = 0; dim < ndims; dim++)
685 if (counts[dim] == 0)
705 for (
i = 1;
i < counts[dim];
i++)
729 if (info[dim].typbyval)
739 else if (info[dim].typlen > 0)
753 else if (info[dim].typlen == -1)
781 else if (info[dim].typlen == -2)
807 Assert(info[dim].nbytes > 0);
815 total_length = (3 *
sizeof(
uint32))
817 + (ndims *
sizeof(
Oid));
823 for (
i = 0;
i < ndims;
i++)
824 total_length += info[
i].nbytes;
840 endptr = ptr + total_length;
855 memcpy(ptr, mcvlist->
types,
sizeof(
Oid) * ndims);
856 ptr += (
sizeof(
Oid) * ndims);
863 for (dim = 0; dim < ndims; dim++)
872 if (info[dim].typbyval)
887 memcpy(ptr, &tmp, info[dim].typlen);
890 else if (info[dim].typlen > 0)
896 else if (info[dim].typlen == -1)
908 else if (info[dim].typlen == -2)
938 memcpy(ptr, mcvitem->
isnull,
sizeof(
bool) * ndims);
939 ptr +=
sizeof(bool) * ndims;
941 memcpy(ptr, &mcvitem->
frequency,
sizeof(
double));
942 ptr +=
sizeof(double);
945 ptr +=
sizeof(double);
948 for (dim = 0; dim < ndims; dim++)
954 if (!mcvitem->
isnull[dim])
1031 elog(
ERROR,
"invalid MCV size %zu (expected at least %zu)",
1038 raw = (
char *)
data;
1056 elog(
ERROR,
"invalid MCV magic %u (expected %u)",
1060 elog(
ERROR,
"invalid MCV type %u (expected %u)",
1064 elog(
ERROR,
"invalid zero-length dimension array in MCVList");
1067 elog(
ERROR,
"invalid length (%d) dimension array in MCVList",
1070 if (mcvlist->
nitems == 0)
1071 elog(
ERROR,
"invalid zero-length item array in MCVList");
1073 elog(
ERROR,
"invalid length (%u) item array in MCVList",
1092 elog(
ERROR,
"invalid MCV size %zu (expected %zu)",
1096 memcpy(mcvlist->
types, ptr,
sizeof(
Oid) * ndims);
1097 ptr += (
sizeof(
Oid) * ndims);
1106 for (dim = 0; dim < ndims; dim++)
1112 Assert(info[dim].nvalues >= 0);
1113 Assert(info[dim].nbytes >= 0);
1115 expected_size += info[dim].
nbytes;
1124 elog(
ERROR,
"invalid MCV size %zu (expected %zu)",
1139 for (dim = 0; dim < ndims; dim++)
1167 mcvlist =
repalloc(mcvlist, mcvlen);
1170 valuesptr = (
char *) mcvlist
1181 for (dim = 0; dim < ndims; dim++)
1186 if (info[dim].typbyval)
1193 memcpy(&v, ptr, info[dim].typlen);
1196 map[dim][
i] =
fetch_att(&v,
true, info[dim].typlen);
1207 if (info[dim].typlen > 0)
1211 memcpy(dataptr, ptr, info[dim].typlen);
1216 dataptr +=
MAXALIGN(info[dim].typlen);
1219 else if (info[dim].typlen == -1)
1242 else if (info[dim].typlen == -2)
1252 memcpy(dataptr, ptr,
len);
1265 Assert(dataptr <= ((
char *) mcvlist + mcvlen));
1273 Assert(dataptr == ((
char *) mcvlist + mcvlen));
1283 item->
isnull = (
bool *) isnullptr;
1284 isnullptr +=
MAXALIGN(
sizeof(
bool) * ndims);
1286 memcpy(item->
isnull, ptr,
sizeof(
bool) * ndims);
1287 ptr +=
sizeof(bool) * ndims;
1289 memcpy(&item->
frequency, ptr,
sizeof(
double));
1290 ptr +=
sizeof(double);
1293 ptr +=
sizeof(double);
1296 for (dim = 0; dim < ndims; dim++)
1317 for (dim = 0; dim < ndims; dim++)
1367 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1368 errmsg(
"function returning record called in context "
1369 "that cannot accept type record")));
1449 memset(nulls, 0,
sizeof(nulls));
1479 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1480 errmsg(
"cannot accept a value of type %s",
"pg_mcv_list")));
1510 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1511 errmsg(
"cannot accept a value of type %s",
"pg_mcv_list")));
1545 *
collid = var->varcollid;
1550 elog(
ERROR,
"variable not found in statistics object");
1566 if (
equal(expr, stat_expr))
1573 elog(
ERROR,
"expression not found in statistics object");
1613 memset(matches, !is_or,
sizeof(
bool) * mcvlist->
nitems);
1657 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1669 if (item->
isnull[
idx] || cst->constisnull)
1745 if (!cst->constisnull)
1749 &elmlen, &elmbyval, &elmalign);
1752 elmlen, elmbyval, elmalign,
1753 &elem_values, &elem_nulls, &num_elems);
1764 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1767 bool match = !expr->
useOr;
1775 if (item->
isnull[
idx] || cst->constisnull)
1789 for (
j = 0;
j < num_elems;
j++)
1791 Datum elem_value = elem_values[
j];
1792 bool elem_isnull = elem_nulls[
j];
1835 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1844 match = (item->
isnull[
idx]) ?
true : match;
1848 match = (!item->
isnull[
idx]) ?
true : match;
1862 List *bool_clauses = bool_clause->
args;
1865 bool *bool_matches = NULL;
1882 pfree(bool_matches);
1893 bool *not_matches = NULL;
1912 else if (
IsA(clause,
Var))
1916 Var *var = (
Var *) (clause);
1921 Assert(var->vartype == BOOLOID);
1928 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1954 for (
int i = 0;
i < mcvlist->
nitems;
i++)
2015 other_sel = simple_sel - mcv_basesel;
2019 if (other_sel > 1.0 - mcv_totalsel)
2020 other_sel = 1.0 - mcv_totalsel;
2023 sel = mcv_sel + other_sel;
2049 List *clauses,
int varRelid,
2060 bool *matches = NULL;
2076 if (matches[
i] !=
false)
2136 if (*or_matches == NULL)
2141 stat->exprs, mcv,
false);
2149 *overlap_mcvsel = 0.0;
2150 *overlap_basesel = 0.0;
2161 if ((*or_matches)[
i])
2169 (*or_matches)[
i] = (*or_matches)[
i] || new_matches[
i];
Datum idx(PG_FUNCTION_ARGS)
#define DatumGetArrayTypeP(X)
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Datum makeArrayResult(ArrayBuildState *astate, MemoryContext rcontext)
int bms_num_members(const Bitmapset *a)
int bms_member_index(Bitmapset *a, int x)
static Datum values[MAXATTR]
#define PG_USED_FOR_ASSERTS_ONLY
#define Assert(condition)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
bool equal(const void *a, const void *b)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
int compare_scalars_simple(const void *a, const void *b, void *arg)
SortItem * build_sorted_items(StatsBuildData *data, int *nitems, MultiSortSupport mss, int numattrs, AttrNumber *attnums)
int compare_datums_simple(Datum a, Datum b, SortSupport ssup)
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)
bool examine_opclause_args(List *args, Node **exprp, Const **cstp, bool *expronleftp)
MultiSortSupportData * MultiSortSupport
struct DimensionInfo DimensionInfo
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Datum Float8GetDatum(float8 X)
#define PG_DETOAST_DATUM(datum)
#define FunctionCall1(flinfo, arg1)
#define PG_GETARG_BYTEA_P(n)
#define DatumGetByteaP(X)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
#define HeapTupleIsValid(tuple)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
RegProcedure get_opcode(Oid opno)
static bool * mcv_get_match_bitmap(PlannerInfo *root, List *clauses, Bitmapset *keys, List *exprs, MCVList *mcvlist, bool is_or)
Datum pg_stats_ext_mcvlist_items(PG_FUNCTION_ARGS)
Datum pg_mcv_list_in(PG_FUNCTION_ARGS)
Selectivity mcv_clauselist_selectivity(PlannerInfo *root, StatisticExtInfo *stat, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Selectivity *basesel, Selectivity *totalsel)
static MultiSortSupport build_mss(StatsBuildData *data)
static int compare_sort_item_count(const void *a, const void *b, void *arg)
Datum pg_mcv_list_out(PG_FUNCTION_ARGS)
static int count_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss)
Datum pg_mcv_list_send(PG_FUNCTION_ARGS)
MCVList * statext_mcv_deserialize(bytea *data)
#define SizeOfMCVList(ndims, nitems)
#define RESULT_MERGE(value, is_or, match)
static double get_mincount_for_mcv_list(int samplerows, double totalrows)
Selectivity mcv_combine_selectivities(Selectivity simple_sel, Selectivity mcv_sel, Selectivity mcv_basesel, Selectivity mcv_totalsel)
Selectivity mcv_clause_selectivity_or(PlannerInfo *root, StatisticExtInfo *stat, MCVList *mcv, Node *clause, bool **or_matches, Selectivity *basesel, Selectivity *overlap_mcvsel, Selectivity *overlap_basesel, Selectivity *totalsel)
MCVList * statext_mcv_load(Oid mvoid, bool inh)
#define RESULT_IS_FINAL(value, is_or)
static int mcv_match_expression(Node *expr, Bitmapset *keys, List *exprs, Oid *collid)
MCVList * statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
Datum pg_mcv_list_recv(PG_FUNCTION_ARGS)
static int sort_item_compare(const void *a, const void *b, void *arg)
bytea * statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
static SortItem ** build_column_frequencies(SortItem *groups, int ngroups, MultiSortSupport mss, int *ncounts)
static SortItem * build_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss, int *ndistinct)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
void * repalloc(void *pointer, Size size)
Oid exprCollation(const Node *expr)
static bool is_andclause(const void *clause)
static bool is_orclause(const void *clause)
static bool is_opclause(const void *clause)
static bool is_notclause(const void *clause)
#define IsA(nodeptr, _type_)
static int list_length(const List *l)
void * bsearch_arg(const void *key, const void *base0, size_t nmemb, size_t size, int(*compar)(const void *, const void *, void *), void *arg)
void qsort_interruptible(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static bool DatumGetBool(Datum X)
static Datum PointerGetDatum(const void *X)
static char * DatumGetCString(Datum X)
static Datum BoolGetDatum(bool X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
static Datum Int32GetDatum(int32 X)
MemoryContextSwitchTo(old_ctx)
#define CLAMP_PROBABILITY(p)
void PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
struct SortSupportData SortSupportData
struct SortSupportData * SortSupport
static int ApplySortComparator(Datum datum1, bool isNull1, Datum datum2, bool isNull2, SortSupport ssup)
#define STATS_MCV_TYPE_BASIC
#define STATS_MCVLIST_MAX_ITEMS
#define STATS_MAX_DIMENSIONS
AttInMetadata * attinmeta
MemoryContext multi_call_memory_ctx
MCVItem items[FLEXIBLE_ARRAY_MEMBER]
Oid types[STATS_MAX_DIMENSIONS]
SortSupportData ssup[FLEXIBLE_ARRAY_MEMBER]
NullTestType nulltesttype
void ReleaseSysCache(HeapTuple tuple)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
static Datum fetch_att(const void *T, bool attbyval, int attlen)
static void store_att_byval(void *T, Datum newdatum, int attlen)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define SET_VARSIZE(PTR, len)
#define VARSIZE_ANY_EXHDR(PTR)
text * cstring_to_text(const char *s)
Datum byteaout(PG_FUNCTION_ARGS)
Datum byteasend(PG_FUNCTION_ARGS)