LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - rangetypes_typanalyze.c (source / functions) Coverage Total Hit UBC GNC CBC EUB ECB DCB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 93.3 % 150 140 10 1 139 1
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 5 5 1 4
Baseline: lcov-20250906-005545-baseline Branches: 79.2 % 48 38 10 38 8 2
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 1 1 1
(30,360] days: 100.0 % 1 1 1
(360..) days: 93.2 % 148 138 10 138
Function coverage date bins:
(360..) days: 100.0 % 5 5 1 4
Branch coverage date bins:
(360..) days: 65.5 % 58 38 10 38 8 2

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * rangetypes_typanalyze.c
                                  4                 :                :  *    Functions for gathering statistics from range columns
                                  5                 :                :  *
                                  6                 :                :  * For a range type column, histograms of lower and upper bounds, and
                                  7                 :                :  * the fraction of NULL and empty ranges are collected.
                                  8                 :                :  *
                                  9                 :                :  * Both histograms have the same length, and they are combined into a
                                 10                 :                :  * single array of ranges. This has the same shape as the histogram that
                                 11                 :                :  * std_typanalyze would collect, but the values are different. Each range
                                 12                 :                :  * in the array is a valid range, even though the lower and upper bounds
                                 13                 :                :  * come from different tuples. In theory, the standard scalar selectivity
                                 14                 :                :  * functions could be used with the combined histogram.
                                 15                 :                :  *
                                 16                 :                :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                 17                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 18                 :                :  *
                                 19                 :                :  *
                                 20                 :                :  * IDENTIFICATION
                                 21                 :                :  *    src/backend/utils/adt/rangetypes_typanalyze.c
                                 22                 :                :  *
                                 23                 :                :  *-------------------------------------------------------------------------
                                 24                 :                :  */
                                 25                 :                : #include "postgres.h"
                                 26                 :                : 
                                 27                 :                : #include "catalog/pg_operator.h"
                                 28                 :                : #include "commands/vacuum.h"
                                 29                 :                : #include "utils/float.h"
                                 30                 :                : #include "utils/fmgrprotos.h"
                                 31                 :                : #include "utils/lsyscache.h"
                                 32                 :                : #include "utils/multirangetypes.h"
                                 33                 :                : #include "utils/rangetypes.h"
                                 34                 :                : #include "varatt.h"
                                 35                 :                : 
                                 36                 :                : static int  float8_qsort_cmp(const void *a1, const void *a2, void *arg);
                                 37                 :                : static int  range_bound_qsort_cmp(const void *a1, const void *a2, void *arg);
                                 38                 :                : static void compute_range_stats(VacAttrStats *stats,
                                 39                 :                :                                 AnalyzeAttrFetchFunc fetchfunc, int samplerows,
                                 40                 :                :                                 double totalrows);
                                 41                 :                : 
                                 42                 :                : /*
                                 43                 :                :  * range_typanalyze -- typanalyze function for range columns
                                 44                 :                :  */
                                 45                 :                : Datum
 4758 heikki.linnakangas@i       46                 :CBC          15 : range_typanalyze(PG_FUNCTION_ARGS)
                                 47                 :                : {
                                 48                 :             15 :     VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0);
                                 49                 :                :     TypeCacheEntry *typcache;
                                 50                 :                : 
                                 51                 :                :     /* Get information about range type; note column might be a domain */
 4275 tgl@sss.pgh.pa.us          52                 :             15 :     typcache = range_get_typcache(fcinfo, getBaseType(stats->attrtypid));
                                 53                 :                : 
  796 peter@eisentraut.org       54         [ +  - ]:             15 :     if (stats->attstattarget < 0)
                                 55                 :             15 :         stats->attstattarget = default_statistics_target;
                                 56                 :                : 
 4758 heikki.linnakangas@i       57                 :             15 :     stats->compute_stats = compute_range_stats;
                                 58                 :             15 :     stats->extra_data = typcache;
                                 59                 :                :     /* same as in std_typanalyze */
  796 peter@eisentraut.org       60                 :             15 :     stats->minrows = 300 * stats->attstattarget;
                                 61                 :                : 
 4758 heikki.linnakangas@i       62                 :             15 :     PG_RETURN_BOOL(true);
                                 63                 :                : }
                                 64                 :                : 
                                 65                 :                : /*
                                 66                 :                :  * multirange_typanalyze -- typanalyze function for multirange columns
                                 67                 :                :  *
                                 68                 :                :  * We do the same analysis as for ranges, but on the smallest range that
                                 69                 :                :  * completely includes the multirange.
                                 70                 :                :  */
                                 71                 :                : Datum
 1721 akorotkov@postgresql       72                 :              6 : multirange_typanalyze(PG_FUNCTION_ARGS)
                                 73                 :                : {
                                 74                 :              6 :     VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0);
                                 75                 :                :     TypeCacheEntry *typcache;
                                 76                 :                : 
                                 77                 :                :     /* Get information about multirange type; note column might be a domain */
                                 78                 :              6 :     typcache = multirange_get_typcache(fcinfo, getBaseType(stats->attrtypid));
                                 79                 :                : 
  796 peter@eisentraut.org       80         [ +  - ]:              6 :     if (stats->attstattarget < 0)
                                 81                 :              6 :         stats->attstattarget = default_statistics_target;
                                 82                 :                : 
 1721 akorotkov@postgresql       83                 :              6 :     stats->compute_stats = compute_range_stats;
                                 84                 :              6 :     stats->extra_data = typcache;
                                 85                 :                :     /* same as in std_typanalyze */
  796 peter@eisentraut.org       86                 :              6 :     stats->minrows = 300 * stats->attstattarget;
                                 87                 :                : 
 1721 akorotkov@postgresql       88                 :              6 :     PG_RETURN_BOOL(true);
                                 89                 :                : }
                                 90                 :                : 
                                 91                 :                : /*
                                 92                 :                :  * Comparison function for sorting float8s, used for range lengths.
                                 93                 :                :  */
                                 94                 :                : static int
 1152 tgl@sss.pgh.pa.us          95                 :          96174 : float8_qsort_cmp(const void *a1, const void *a2, void *arg)
                                 96                 :                : {
 4559 heikki.linnakangas@i       97                 :          96174 :     const float8 *f1 = (const float8 *) a1;
                                 98                 :          96174 :     const float8 *f2 = (const float8 *) a2;
                                 99                 :                : 
                                100         [ +  + ]:          96174 :     if (*f1 < *f2)
                                101                 :             57 :         return -1;
                                102         [ +  + ]:          96117 :     else if (*f1 == *f2)
                                103                 :          85254 :         return 0;
                                104                 :                :     else
                                105                 :          10863 :         return 1;
                                106                 :                : }
                                107                 :                : 
                                108                 :                : /*
                                109                 :                :  * Comparison function for sorting RangeBounds.
                                110                 :                :  */
                                111                 :                : static int
 4758                           112                 :        1493763 : range_bound_qsort_cmp(const void *a1, const void *a2, void *arg)
                                113                 :                : {
 4483 bruce@momjian.us          114                 :        1493763 :     RangeBound *b1 = (RangeBound *) a1;
                                115                 :        1493763 :     RangeBound *b2 = (RangeBound *) a2;
                                116                 :        1493763 :     TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
                                117                 :                : 
 4758 heikki.linnakangas@i      118                 :        1493763 :     return range_cmp_bounds(typcache, b1, b2);
                                119                 :                : }
                                120                 :                : 
                                121                 :                : /*
                                122                 :                :  * compute_range_stats() -- compute statistics for a range column
                                123                 :                :  */
                                124                 :                : static void
                                125                 :             21 : compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
                                126                 :                :                     int samplerows, double totalrows)
                                127                 :                : {
                                128                 :             21 :     TypeCacheEntry *typcache = (TypeCacheEntry *) stats->extra_data;
 1721 akorotkov@postgresql      129                 :             21 :     TypeCacheEntry *mltrng_typcache = NULL;
                                130                 :                :     bool        has_subdiff;
 4758 heikki.linnakangas@i      131                 :             21 :     int         null_cnt = 0;
                                132                 :             21 :     int         non_null_cnt = 0;
                                133                 :             21 :     int         non_empty_cnt = 0;
                                134                 :             21 :     int         empty_cnt = 0;
                                135                 :                :     int         range_no;
                                136                 :                :     int         slot_idx;
  796 peter@eisentraut.org      137                 :             21 :     int         num_bins = stats->attstattarget;
                                138                 :                :     int         num_hist;
                                139                 :                :     float8     *lengths;
                                140                 :                :     RangeBound *lowers,
                                141                 :                :                *uppers;
 4758 heikki.linnakangas@i      142                 :             21 :     double      total_width = 0;
                                143                 :                : 
 1721 akorotkov@postgresql      144         [ +  + ]:             21 :     if (typcache->typtype == TYPTYPE_MULTIRANGE)
                                145                 :                :     {
                                146                 :              6 :         mltrng_typcache = typcache;
                                147                 :              6 :         typcache = typcache->rngtype;
                                148                 :                :     }
                                149                 :                :     else
                                150         [ -  + ]:             15 :         Assert(typcache->typtype == TYPTYPE_RANGE);
                                151                 :             21 :     has_subdiff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
                                152                 :                : 
                                153                 :                :     /* Allocate memory to hold range bounds and lengths of the sample ranges. */
 4758 heikki.linnakangas@i      154                 :             21 :     lowers = (RangeBound *) palloc(sizeof(RangeBound) * samplerows);
                                155                 :             21 :     uppers = (RangeBound *) palloc(sizeof(RangeBound) * samplerows);
 4559                           156                 :             21 :     lengths = (float8 *) palloc(sizeof(float8) * samplerows);
                                157                 :                : 
                                158                 :                :     /* Loop over the sample ranges. */
 4758                           159         [ +  + ]:          66984 :     for (range_no = 0; range_no < samplerows; range_no++)
                                160                 :                :     {
                                161                 :                :         Datum       value;
                                162                 :                :         bool        isnull,
                                163                 :                :                     empty;
                                164                 :                :         MultirangeType *multirange;
                                165                 :                :         RangeType  *range;
                                166                 :                :         RangeBound  lower,
                                167                 :                :                     upper;
                                168                 :                :         float8      length;
                                169                 :                : 
  207 nathan@postgresql.or      170                 :          66963 :         vacuum_delay_point(true);
                                171                 :                : 
 4758 heikki.linnakangas@i      172                 :          66963 :         value = fetchfunc(stats, range_no, &isnull);
                                173         [ -  + ]:          66963 :         if (isnull)
                                174                 :                :         {
                                175                 :                :             /* range is null, just count that */
 4758 heikki.linnakangas@i      176                 :UBC           0 :             null_cnt++;
                                177                 :              0 :             continue;
                                178                 :                :         }
                                179                 :                : 
                                180                 :                :         /*
                                181                 :                :          * XXX: should we ignore wide values, like std_typanalyze does, to
                                182                 :                :          * avoid bloating the statistics table?
                                183                 :                :          */
 4758 heikki.linnakangas@i      184   [ -  +  -  -  :CBC       66963 :         total_width += VARSIZE_ANY(DatumGetPointer(value));
                                     -  -  -  -  +  
                                                 - ]
                                185                 :                : 
                                186                 :                :         /* Get range and deserialize it for further analysis. */
 1721 akorotkov@postgresql      187         [ +  + ]:          66963 :         if (mltrng_typcache != NULL)
                                188                 :                :         {
                                189                 :                :             /* Treat multiranges like a big range without gaps. */
                                190                 :          11133 :             multirange = DatumGetMultirangeTypeP(value);
                                191         [ +  + ]:          11133 :             if (!MultirangeIsEmpty(multirange))
                                192                 :                :             {
                                193                 :                :                 RangeBound  tmp;
                                194                 :                : 
                                195                 :           9621 :                 multirange_get_bounds(typcache, multirange, 0,
                                196                 :                :                                       &lower, &tmp);
                                197                 :           9621 :                 multirange_get_bounds(typcache, multirange,
                                198                 :           9621 :                                       multirange->rangeCount - 1,
                                199                 :                :                                       &tmp, &upper);
                                200                 :           9621 :                 empty = false;
                                201                 :                :             }
                                202                 :                :             else
                                203                 :                :             {
                                204                 :           1512 :                 empty = true;
                                205                 :                :             }
                                206                 :                :         }
                                207                 :                :         else
                                208                 :                :         {
                                209                 :          55830 :             range = DatumGetRangeTypeP(value);
                                210                 :          55830 :             range_deserialize(typcache, range, &lower, &upper, &empty);
                                211                 :                :         }
                                212                 :                : 
 4758 heikki.linnakangas@i      213         [ +  + ]:          66963 :         if (!empty)
                                214                 :                :         {
                                215                 :                :             /* Remember bounds and length for further usage in histograms */
                                216                 :          56448 :             lowers[non_empty_cnt] = lower;
                                217                 :          56448 :             uppers[non_empty_cnt] = upper;
                                218                 :                : 
 4559                           219   [ +  +  +  + ]:          56448 :             if (lower.infinite || upper.infinite)
                                220                 :                :             {
                                221                 :                :                 /* Length of any kind of an infinite range is infinite */
                                222                 :           2421 :                 length = get_float8_infinity();
                                223                 :                :             }
                                224         [ +  - ]:          54027 :             else if (has_subdiff)
                                225                 :                :             {
                                226                 :                :                 /*
                                227                 :                :                  * For an ordinary range, use subdiff function between upper
                                228                 :                :                  * and lower bound values.
                                229                 :                :                  */
 2046 alvherre@alvh.no-ip.      230                 :          54027 :                 length = DatumGetFloat8(FunctionCall2Coll(&typcache->rng_subdiff_finfo,
                                231                 :                :                                                           typcache->rng_collation,
                                232                 :                :                                                           upper.val, lower.val));
                                233                 :                :             }
                                234                 :                :             else
                                235                 :                :             {
                                236                 :                :                 /* Use default value of 1.0 if no subdiff is available. */
 4559 heikki.linnakangas@i      237                 :UBC           0 :                 length = 1.0;
                                238                 :                :             }
 4559 heikki.linnakangas@i      239                 :CBC       56448 :             lengths[non_empty_cnt] = length;
                                240                 :                : 
 4758                           241                 :          56448 :             non_empty_cnt++;
                                242                 :                :         }
                                243                 :                :         else
                                244                 :          10515 :             empty_cnt++;
                                245                 :                : 
                                246                 :          66963 :         non_null_cnt++;
                                247                 :                :     }
                                248                 :                : 
                                249                 :             21 :     slot_idx = 0;
                                250                 :                : 
                                251                 :                :     /* We can only compute real stats if we found some non-null values. */
                                252         [ +  - ]:             21 :     if (non_null_cnt > 0)
                                253                 :                :     {
                                254                 :                :         Datum      *bound_hist_values;
                                255                 :                :         Datum      *length_hist_values;
                                256                 :                :         int         pos,
                                257                 :                :                     posfrac,
                                258                 :                :                     delta,
                                259                 :                :                     deltafrac,
                                260                 :                :                     i;
                                261                 :                :         MemoryContext old_cxt;
                                262                 :                :         float4     *emptyfrac;
                                263                 :                : 
                                264                 :             21 :         stats->stats_valid = true;
                                265                 :                :         /* Do the simple null-frac and width stats */
                                266                 :             21 :         stats->stanullfrac = (double) null_cnt / (double) samplerows;
                                267                 :             21 :         stats->stawidth = total_width / (double) non_null_cnt;
                                268                 :                : 
                                269                 :                :         /* Estimate that non-null values are unique */
 3317 tgl@sss.pgh.pa.us         270                 :             21 :         stats->stadistinct = -1.0 * (1.0 - stats->stanullfrac);
                                271                 :                : 
                                272                 :                :         /* Must copy the target values into anl_context */
 4758 heikki.linnakangas@i      273                 :             21 :         old_cxt = MemoryContextSwitchTo(stats->anl_context);
                                274                 :                : 
                                275                 :                :         /*
                                276                 :                :          * Generate a bounds histogram slot entry if there are at least two
                                277                 :                :          * values.
                                278                 :                :          */
 4755                           279         [ +  - ]:             21 :         if (non_empty_cnt >= 2)
                                280                 :                :         {
                                281                 :                :             /* Sort bound values */
 1152 tgl@sss.pgh.pa.us         282                 :             21 :             qsort_interruptible(lowers, non_empty_cnt, sizeof(RangeBound),
                                283                 :                :                                 range_bound_qsort_cmp, typcache);
                                284                 :             21 :             qsort_interruptible(uppers, non_empty_cnt, sizeof(RangeBound),
                                285                 :                :                                 range_bound_qsort_cmp, typcache);
                                286                 :                : 
 4758 heikki.linnakangas@i      287                 :             21 :             num_hist = non_empty_cnt;
                                288         [ +  + ]:             21 :             if (num_hist > num_bins)
                                289                 :             12 :                 num_hist = num_bins + 1;
                                290                 :                : 
                                291                 :             21 :             bound_hist_values = (Datum *) palloc(num_hist * sizeof(Datum));
                                292                 :                : 
                                293                 :                :             /*
                                294                 :                :              * The object of this loop is to construct ranges from first and
                                295                 :                :              * last entries in lowers[] and uppers[] along with evenly-spaced
                                296                 :                :              * values in between. So the i'th value is a range of lowers[(i *
                                297                 :                :              * (nvals - 1)) / (num_hist - 1)] and uppers[(i * (nvals - 1)) /
                                298                 :                :              * (num_hist - 1)]. But computing that subscript directly risks
                                299                 :                :              * integer overflow when the stats target is more than a couple
                                300                 :                :              * thousand.  Instead we add (nvals - 1) / (num_hist - 1) to pos
                                301                 :                :              * at each step, tracking the integral and fractional parts of the
                                302                 :                :              * sum separately.
                                303                 :                :              */
                                304                 :             21 :             delta = (non_empty_cnt - 1) / (num_hist - 1);
                                305                 :             21 :             deltafrac = (non_empty_cnt - 1) % (num_hist - 1);
                                306                 :             21 :             pos = posfrac = 0;
                                307                 :                : 
                                308         [ +  + ]:           1281 :             for (i = 0; i < num_hist; i++)
                                309                 :                :             {
 2046 alvherre@alvh.no-ip.      310                 :           1260 :                 bound_hist_values[i] = PointerGetDatum(range_serialize(typcache,
                                311                 :           1260 :                                                                        &lowers[pos],
                                312                 :           1260 :                                                                        &uppers[pos],
                                313                 :                :                                                                        false,
                                314                 :                :                                                                        NULL));
 4758 heikki.linnakangas@i      315                 :           1260 :                 pos += delta;
                                316                 :           1260 :                 posfrac += deltafrac;
                                317         [ +  + ]:           1260 :                 if (posfrac >= (num_hist - 1))
                                318                 :                :                 {
                                319                 :                :                     /* fractional part exceeds 1, carry to integer part */
                                320                 :           1188 :                     pos++;
                                321                 :           1188 :                     posfrac -= (num_hist - 1);
                                322                 :                :                 }
                                323                 :                :             }
                                324                 :                : 
                                325                 :             21 :             stats->stakind[slot_idx] = STATISTIC_KIND_BOUNDS_HISTOGRAM;
                                326                 :             21 :             stats->stavalues[slot_idx] = bound_hist_values;
                                327                 :             21 :             stats->numvalues[slot_idx] = num_hist;
                                328                 :                : 
                                329                 :                :             /* Store ranges even if we're analyzing a multirange column */
 1721 akorotkov@postgresql      330                 :             21 :             stats->statypid[slot_idx] = typcache->type_id;
                                331                 :             21 :             stats->statyplen[slot_idx] = typcache->typlen;
                                332                 :             21 :             stats->statypbyval[slot_idx] = typcache->typbyval;
 1578 tgl@sss.pgh.pa.us         333                 :             21 :             stats->statypalign[slot_idx] = typcache->typalign;
                                334                 :                : 
 4758 heikki.linnakangas@i      335                 :             21 :             slot_idx++;
                                336                 :                :         }
                                337                 :                : 
                                338                 :                :         /*
                                339                 :                :          * Generate a length histogram slot entry if there are at least two
                                340                 :                :          * values.
                                341                 :                :          */
 4559                           342         [ +  - ]:             21 :         if (non_empty_cnt >= 2)
                                343                 :                :         {
                                344                 :                :             /*
                                345                 :                :              * Ascending sort of range lengths for further filling of
                                346                 :                :              * histogram
                                347                 :                :              */
 1152 tgl@sss.pgh.pa.us         348                 :             21 :             qsort_interruptible(lengths, non_empty_cnt, sizeof(float8),
                                349                 :                :                                 float8_qsort_cmp, NULL);
                                350                 :                : 
 4559 heikki.linnakangas@i      351                 :             21 :             num_hist = non_empty_cnt;
                                352         [ +  + ]:             21 :             if (num_hist > num_bins)
                                353                 :             12 :                 num_hist = num_bins + 1;
                                354                 :                : 
                                355                 :             21 :             length_hist_values = (Datum *) palloc(num_hist * sizeof(Datum));
                                356                 :                : 
                                357                 :                :             /*
                                358                 :                :              * The object of this loop is to copy the first and last lengths[]
                                359                 :                :              * entries along with evenly-spaced values in between. So the i'th
                                360                 :                :              * value is lengths[(i * (nvals - 1)) / (num_hist - 1)]. But
                                361                 :                :              * computing that subscript directly risks integer overflow when
                                362                 :                :              * the stats target is more than a couple thousand.  Instead we
                                363                 :                :              * add (nvals - 1) / (num_hist - 1) to pos at each step, tracking
                                364                 :                :              * the integral and fractional parts of the sum separately.
                                365                 :                :              */
                                366                 :             21 :             delta = (non_empty_cnt - 1) / (num_hist - 1);
                                367                 :             21 :             deltafrac = (non_empty_cnt - 1) % (num_hist - 1);
                                368                 :             21 :             pos = posfrac = 0;
                                369                 :                : 
                                370         [ +  + ]:           1281 :             for (i = 0; i < num_hist; i++)
                                371                 :                :             {
                                372                 :           1260 :                 length_hist_values[i] = Float8GetDatum(lengths[pos]);
                                373                 :           1260 :                 pos += delta;
                                374                 :           1260 :                 posfrac += deltafrac;
                                375         [ +  + ]:           1260 :                 if (posfrac >= (num_hist - 1))
                                376                 :                :                 {
                                377                 :                :                     /* fractional part exceeds 1, carry to integer part */
                                378                 :           1188 :                     pos++;
                                379                 :           1188 :                     posfrac -= (num_hist - 1);
                                380                 :                :                 }
                                381                 :                :             }
                                382                 :                :         }
                                383                 :                :         else
                                384                 :                :         {
                                385                 :                :             /*
                                386                 :                :              * Even when we don't create the histogram, store an empty array
                                387                 :                :              * to mean "no histogram". We can't just leave stavalues NULL,
                                388                 :                :              * because get_attstatsslot() errors if you ask for stavalues, and
                                389                 :                :              * it's NULL. We'll still store the empty fraction in stanumbers.
                                390                 :                :              */
 4559 heikki.linnakangas@i      391                 :UBC           0 :             length_hist_values = palloc(0);
                                392                 :              0 :             num_hist = 0;
                                393                 :                :         }
 4559 heikki.linnakangas@i      394                 :CBC          21 :         stats->staop[slot_idx] = Float8LessOperator;
 2458 tgl@sss.pgh.pa.us         395                 :             21 :         stats->stacoll[slot_idx] = InvalidOid;
 4559 heikki.linnakangas@i      396                 :             21 :         stats->stavalues[slot_idx] = length_hist_values;
                                397                 :             21 :         stats->numvalues[slot_idx] = num_hist;
                                398                 :             21 :         stats->statypid[slot_idx] = FLOAT8OID;
                                399                 :             21 :         stats->statyplen[slot_idx] = sizeof(float8);
   24 tgl@sss.pgh.pa.us         400                 :GNC          21 :         stats->statypbyval[slot_idx] = true;
 4559 heikki.linnakangas@i      401                 :CBC          21 :         stats->statypalign[slot_idx] = 'd';
                                402                 :                : 
                                403                 :                :         /* Store the fraction of empty ranges */
 4758                           404                 :             21 :         emptyfrac = (float4 *) palloc(sizeof(float4));
                                405                 :             21 :         *emptyfrac = ((double) empty_cnt) / ((double) non_null_cnt);
                                406                 :             21 :         stats->stanumbers[slot_idx] = emptyfrac;
                                407                 :             21 :         stats->numnumbers[slot_idx] = 1;
                                408                 :                : 
 4559                           409                 :             21 :         stats->stakind[slot_idx] = STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM;
 4758                           410                 :             21 :         slot_idx++;
                                411                 :                : 
                                412                 :             21 :         MemoryContextSwitchTo(old_cxt);
                                413                 :                :     }
 4758 heikki.linnakangas@i      414         [ #  # ]:UBC           0 :     else if (null_cnt > 0)
                                415                 :                :     {
                                416                 :                :         /* We found only nulls; assume the column is entirely null */
                                417                 :              0 :         stats->stats_valid = true;
                                418                 :              0 :         stats->stanullfrac = 1.0;
 4483 bruce@momjian.us          419                 :              0 :         stats->stawidth = 0; /* "unknown" */
 2999 tgl@sss.pgh.pa.us         420                 :              0 :         stats->stadistinct = 0.0;    /* "unknown" */
                                421                 :                :     }
                                422                 :                : 
                                423                 :                :     /*
                                424                 :                :      * We don't need to bother cleaning up any of our temporary palloc's. The
                                425                 :                :      * hashtable should also go away, as it used a child memory context.
                                426                 :                :      */
 4758 heikki.linnakangas@i      427                 :CBC          21 : }
        

Generated by: LCOV version 2.4-beta