32 #include "utils/fmgroids.h"
33 #include "utils/fmgrprotos.h"
57 #define ITEM_SIZE(ndims) \
58 ((ndims) * (sizeof(uint16) + sizeof(bool)) + 2 * sizeof(double))
63 #define MinSizeOfMCVList \
64 (VARHDRSZ + sizeof(uint32) * 3 + sizeof(AttrNumber))
72 #define SizeOfMCVList(ndims,nitems) \
73 ((MinSizeOfMCVList + sizeof(Oid) * (ndims)) + \
74 ((ndims) * sizeof(DimensionInfo)) + \
75 ((nitems) * ITEM_SIZE(ndims)))
92 #define RESULT_MERGE(value, is_or, match) \
93 ((is_or) ? ((value) || (match)) : ((value) && (match)))
104 #define RESULT_IS_FINAL(value, is_or) ((is_or) ? (value) : (!(value)))
154 double n = samplerows;
155 double N = totalrows;
160 denom = N - n + 0.04 * n * (N - 1);
166 return numer / denom;
208 numattrs =
data->nattnums;
209 numrows =
data->numrows;
250 if (groups[
i].count < mincount)
277 nfreqs = (
int *)
palloc0(
sizeof(
int) * numattrs);
292 for (
i = 0;
i < numattrs;
i++)
302 item->
isnull = (
bool *)
palloc(
sizeof(
bool) * numattrs);
306 memcpy(item->
isnull, groups[
i].
isnull,
sizeof(
bool) * numattrs);
309 Assert((
i == 0) || (groups[
i - 1].count >= groups[
i].count));
312 item->
frequency = (double) groups[
i].count / numrows;
316 for (
j = 0;
j < numattrs;
j++)
354 int numattrs =
data->nattnums;
360 for (
i = 0;
i < numattrs;
i++)
367 elog(
ERROR,
"cache lookup failed for ordering operator for type %u",
389 for (
i = 1;
i < numrows;
i++)
438 groups[0] = items[0];
441 for (
i = 1;
i < numrows;
i++)
449 groups[++
j] = items[
i];
463 *ndistinct = ngroups;
513 for (dim = 0; dim < mss->
ndims; dim++)
522 for (
i = 0;
i < ngroups;
i++)
540 for (
i = 1;
i < ngroups;
i++)
544 result[dim][ncounts[dim] - 1].
count += result[dim][
i].
count;
548 result[dim][ncounts[dim]] = result[dim][
i];
571 elog(
ERROR,
"cache lookup failed for statistics object %u", mvoid);
574 Anum_pg_statistic_ext_data_stxdmcv, &isnull);
578 "requested statistics kind \"%c\" is not yet built for statistics object %u",
579 STATS_EXT_DEPENDENCIES, mvoid);
643 int *counts = (
int *)
palloc0(
sizeof(
int) * ndims);
659 for (dim = 0; dim < ndims; dim++)
689 if (counts[dim] == 0)
709 for (
i = 1;
i < counts[dim];
i++)
733 if (info[dim].typbyval)
743 else if (info[dim].typlen > 0)
757 else if (info[dim].typlen == -1)
785 else if (info[dim].typlen == -2)
811 Assert(info[dim].nbytes > 0);
819 total_length = (3 *
sizeof(
uint32))
821 + (ndims *
sizeof(
Oid));
827 for (
i = 0;
i < ndims;
i++)
828 total_length += info[
i].nbytes;
844 endptr = ptr + total_length;
859 memcpy(ptr, mcvlist->
types,
sizeof(
Oid) * ndims);
860 ptr += (
sizeof(
Oid) * ndims);
867 for (dim = 0; dim < ndims; dim++)
876 if (info[dim].typbyval)
891 memcpy(ptr, &tmp, info[dim].typlen);
894 else if (info[dim].typlen > 0)
900 else if (info[dim].typlen == -1)
912 else if (info[dim].typlen == -2)
926 Assert((ptr > start) && ((ptr - start) <= info[dim].nbytes));
930 Assert((ptr - start) == info[dim].nbytes);
942 memcpy(ptr, mcvitem->
isnull,
sizeof(
bool) * ndims);
943 ptr +=
sizeof(
bool) * ndims;
945 memcpy(ptr, &mcvitem->
frequency,
sizeof(
double));
946 ptr +=
sizeof(double);
949 ptr +=
sizeof(double);
952 for (dim = 0; dim < ndims; dim++)
958 if (!mcvitem->
isnull[dim])
1035 elog(
ERROR,
"invalid MCV size %zu (expected at least %zu)",
1042 raw = (
char *)
data;
1060 elog(
ERROR,
"invalid MCV magic %u (expected %u)",
1064 elog(
ERROR,
"invalid MCV type %u (expected %u)",
1068 elog(
ERROR,
"invalid zero-length dimension array in MCVList");
1071 elog(
ERROR,
"invalid length (%d) dimension array in MCVList",
1074 if (mcvlist->
nitems == 0)
1075 elog(
ERROR,
"invalid zero-length item array in MCVList");
1077 elog(
ERROR,
"invalid length (%u) item array in MCVList",
1096 elog(
ERROR,
"invalid MCV size %zu (expected %zu)",
1100 memcpy(mcvlist->
types, ptr,
sizeof(
Oid) * ndims);
1101 ptr += (
sizeof(
Oid) * ndims);
1110 for (dim = 0; dim < ndims; dim++)
1116 Assert(info[dim].nvalues >= 0);
1117 Assert(info[dim].nbytes >= 0);
1119 expected_size += info[dim].
nbytes;
1128 elog(
ERROR,
"invalid MCV size %zu (expected %zu)",
1143 for (dim = 0; dim < ndims; dim++)
1171 mcvlist =
repalloc(mcvlist, mcvlen);
1174 valuesptr = (
char *) mcvlist
1185 for (dim = 0; dim < ndims; dim++)
1190 if (info[dim].typbyval)
1197 memcpy(&v, ptr, info[dim].typlen);
1200 map[dim][
i] =
fetch_att(&v,
true, info[dim].typlen);
1203 Assert(ptr <= (start + info[dim].nbytes));
1211 if (info[dim].typlen > 0)
1215 memcpy(dataptr, ptr, info[dim].typlen);
1220 dataptr +=
MAXALIGN(info[dim].typlen);
1223 else if (info[dim].typlen == -1)
1246 else if (info[dim].typlen == -2)
1256 memcpy(dataptr, ptr,
len);
1266 Assert(ptr <= (start + info[dim].nbytes));
1269 Assert(dataptr <= ((
char *) mcvlist + mcvlen));
1273 Assert(ptr == (start + info[dim].nbytes));
1277 Assert(dataptr == ((
char *) mcvlist + mcvlen));
1287 item->
isnull = (
bool *) isnullptr;
1288 isnullptr +=
MAXALIGN(
sizeof(
bool) * ndims);
1290 memcpy(item->
isnull, ptr,
sizeof(
bool) * ndims);
1291 ptr +=
sizeof(
bool) * ndims;
1293 memcpy(&item->
frequency, ptr,
sizeof(
double));
1294 ptr +=
sizeof(double);
1297 ptr +=
sizeof(double);
1300 for (dim = 0; dim < ndims; dim++)
1321 for (dim = 0; dim < ndims; dim++)
1371 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1372 errmsg(
"function returning record called in context "
1373 "that cannot accept type record")));
1453 memset(nulls, 0,
sizeof(nulls));
1483 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1484 errmsg(
"cannot accept a value of type %s",
"pg_mcv_list")));
1514 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1515 errmsg(
"cannot accept a value of type %s",
"pg_mcv_list")));
1549 *
collid = var->varcollid;
1554 elog(
ERROR,
"variable not found in statistics object");
1570 if (
equal(expr, stat_expr))
1577 elog(
ERROR,
"expression not found in statistics object");
1617 memset(matches, !is_or,
sizeof(
bool) * mcvlist->
nitems);
1661 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1673 if (item->
isnull[
idx] || cst->constisnull)
1749 if (!cst->constisnull)
1753 &elmlen, &elmbyval, &elmalign);
1756 elmlen, elmbyval, elmalign,
1757 &elem_values, &elem_nulls, &num_elems);
1768 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1771 bool match = !expr->
useOr;
1779 if (item->
isnull[
idx] || cst->constisnull)
1793 for (
j = 0;
j < num_elems;
j++)
1795 Datum elem_value = elem_values[
j];
1796 bool elem_isnull = elem_nulls[
j];
1839 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1848 match = (item->
isnull[
idx]) ?
true : match;
1852 match = (!item->
isnull[
idx]) ?
true : match;
1866 List *bool_clauses = bool_clause->
args;
1869 bool *bool_matches = NULL;
1886 pfree(bool_matches);
1897 bool *not_matches = NULL;
1916 else if (
IsA(clause,
Var))
1920 Var *var = (
Var *) (clause);
1925 Assert(var->vartype == BOOLOID);
1932 for (
int i = 0;
i < mcvlist->
nitems;
i++)
1958 for (
int i = 0;
i < mcvlist->
nitems;
i++)
2019 other_sel = simple_sel - mcv_basesel;
2023 if (other_sel > 1.0 - mcv_totalsel)
2024 other_sel = 1.0 - mcv_totalsel;
2027 sel = mcv_sel + other_sel;
2053 List *clauses,
int varRelid,
2064 bool *matches = NULL;
2080 if (matches[
i] !=
false)
2140 if (*or_matches == NULL)
2145 stat->exprs, mcv,
false);
2153 *overlap_mcvsel = 0.0;
2154 *overlap_basesel = 0.0;
2165 if ((*or_matches)[
i])
2173 (*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
elog(ERROR, "%s: %s", p2, msg)
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, Datum *values, bool *isnull)
#define HeapTupleIsValid(tuple)
Assert(fmt[strlen(fmt) - 1] !='\n')
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 MemoryContext MemoryContextSwitchTo(MemoryContext context)
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)
#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)