From 48359d6375ceb3655afbb9847ddae14288a8daea Mon Sep 17 00:00:00 2001 From: Nikita Glukhov Date: Wed, 7 Dec 2016 16:12:55 +0300 Subject: [PATCH 2/6] Add stats_form_tuple() --- src/backend/utils/adt/selfuncs.c | 55 ++++++++++++++++++++++++++++++++++++++++ src/include/utils/selfuncs.h | 22 ++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 2f9e0a2..03af7cc 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -7986,3 +7986,58 @@ brincostestimate(PlannerInfo *root, IndexPath *path, double loop_count, *indexPages = index->pages; } + +/* + * stats_form_tuple - Form pg_statistic tuple from StatsData. + * + * If 'data' parameter is NULL, form all-NULL tuple (nullfrac = 1.0). + */ +HeapTuple +stats_form_tuple(StatsData *data) +{ + Relation rel; + HeapTuple tuple; + Datum values[Natts_pg_statistic]; + bool nulls[Natts_pg_statistic]; + int i; + + for (i = 0; i < Natts_pg_statistic; ++i) + nulls[i] = false; + + values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(InvalidOid); + values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(0); + values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(false); + values[Anum_pg_statistic_stanullfrac - 1] = + Float4GetDatum(data ? data->nullfrac : 1.0); + values[Anum_pg_statistic_stawidth - 1] = + Int32GetDatum(data ? data->width : 0); + values[Anum_pg_statistic_stadistinct - 1] = + Float4GetDatum(data ? data->distinct : 0); + + for (i = 0; i < STATISTIC_NUM_SLOTS; i++) + { + StatsSlot *slot = data ? &data->slots[i] : NULL; + + values[Anum_pg_statistic_stakind1 + i - 1] = + Int16GetDatum(slot ? slot->kind : 0); + + values[Anum_pg_statistic_staop1 + i - 1] = + ObjectIdGetDatum(slot ? slot->opid : InvalidOid); + + if (slot && DatumGetPointer(slot->numbers)) + values[Anum_pg_statistic_stanumbers1 + i - 1] = slot->numbers; + else + nulls[Anum_pg_statistic_stanumbers1 + i - 1] = true; + + if (slot && DatumGetPointer(slot->values)) + values[Anum_pg_statistic_stavalues1 + i - 1] = slot->values; + else + nulls[Anum_pg_statistic_stavalues1 + i - 1] = true; + } + + rel = table_open(StatisticRelationId, AccessShareLock); + tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); + table_close(rel, NoLock); + + return tuple; +} diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h index c313a08..cb7d510 100644 --- a/src/include/utils/selfuncs.h +++ b/src/include/utils/selfuncs.h @@ -16,6 +16,7 @@ #define SELFUNCS_H #include "access/htup.h" +#include "catalog/pg_statistic.h" #include "fmgr.h" #include "nodes/pathnodes.h" @@ -133,6 +134,24 @@ typedef struct double num_sa_scans; /* # indexscans from ScalarArrayOpExprs */ } GenericCosts; +/* Single pg_statistic slot */ +typedef struct StatsSlot +{ + int16 kind; /* stakindN: statistic kind (STATISTIC_KIND_XXX) */ + Oid opid; /* staopN: associated operator, if needed */ + Datum numbers; /* stanumbersN: float4 array of numbers */ + Datum values; /* stavaluesN: anyarray of values */ +} StatsSlot; + +/* Deformed pg_statistic tuple */ +typedef struct StatsData +{ + float4 nullfrac; /* stanullfrac: fraction of NULL values */ + float4 distinct; /* stadistinct: number of distinct non-NULL values */ + int32 width; /* stawidth: average width in bytes of non-NULL values */ + StatsSlot slots[STATISTIC_NUM_SLOTS]; /* slots for different statistic types */ +} StatsData; + /* Hooks for plugins to get control when we ask for stats */ typedef bool (*get_relation_stats_hook_type) (PlannerInfo *root, RangeTblEntry *rte, @@ -236,6 +255,9 @@ extern void genericcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, GenericCosts *costs); +extern HeapTuple stats_form_tuple(StatsData *data); + + /* Functions in array_selfuncs.c */ extern Selectivity scalararraysel_containment(PlannerInfo *root, -- 1.8.3.1