LCOV - code coverage report
Current view: top level - src/backend/utils/adt - rangetypes_gist.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 86.6 % 584 506
Test Date: 2026-07-22 12:15:41 Functions: 92.3 % 26 24
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 78.0 % 396 309

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * rangetypes_gist.c
       4                 :             :  *    GiST support for range types.
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *    src/backend/utils/adt/rangetypes_gist.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "access/gist.h"
      18                 :             : #include "access/stratnum.h"
      19                 :             : #include "utils/datum.h"
      20                 :             : #include "utils/float.h"
      21                 :             : #include "utils/fmgrprotos.h"
      22                 :             : #include "utils/multirangetypes.h"
      23                 :             : #include "utils/rangetypes.h"
      24                 :             : 
      25                 :             : /*
      26                 :             :  * Range class properties used to segregate different classes of ranges in
      27                 :             :  * GiST.  Each unique combination of properties is a class.  CLS_EMPTY cannot
      28                 :             :  * be combined with anything else.
      29                 :             :  */
      30                 :             : #define CLS_NORMAL          0   /* Ordinary finite range (no bits set) */
      31                 :             : #define CLS_LOWER_INF       1   /* Lower bound is infinity */
      32                 :             : #define CLS_UPPER_INF       2   /* Upper bound is infinity */
      33                 :             : #define CLS_CONTAIN_EMPTY   4   /* Contains underlying empty ranges */
      34                 :             : #define CLS_EMPTY           8   /* Special class for empty ranges */
      35                 :             : 
      36                 :             : #define CLS_COUNT           9   /* # of classes; includes all combinations of
      37                 :             :                                  * properties. CLS_EMPTY doesn't combine with
      38                 :             :                                  * anything else, so it's only 2^3 + 1. */
      39                 :             : 
      40                 :             : /*
      41                 :             :  * Minimum accepted ratio of split for items of the same class.  If the items
      42                 :             :  * are of different classes, we will separate along those lines regardless of
      43                 :             :  * the ratio.
      44                 :             :  */
      45                 :             : #define LIMIT_RATIO  0.3
      46                 :             : 
      47                 :             : /* Constants for fixed penalty values */
      48                 :             : #define INFINITE_BOUND_PENALTY  2.0
      49                 :             : #define CONTAIN_EMPTY_PENALTY  1.0
      50                 :             : #define DEFAULT_SUBTYPE_DIFF_PENALTY  1.0
      51                 :             : 
      52                 :             : /*
      53                 :             :  * Per-item data for range_gist_single_sorting_split.
      54                 :             :  */
      55                 :             : typedef struct
      56                 :             : {
      57                 :             :     int         index;
      58                 :             :     RangeBound  bound;
      59                 :             : } SingleBoundSortItem;
      60                 :             : 
      61                 :             : /* place on left or right side of split? */
      62                 :             : typedef enum
      63                 :             : {
      64                 :             :     SPLIT_LEFT = 0,             /* makes initialization to SPLIT_LEFT easier */
      65                 :             :     SPLIT_RIGHT,
      66                 :             : } SplitLR;
      67                 :             : 
      68                 :             : /*
      69                 :             :  * Context for range_gist_consider_split.
      70                 :             :  */
      71                 :             : typedef struct
      72                 :             : {
      73                 :             :     TypeCacheEntry *typcache;   /* typcache for range type */
      74                 :             :     bool        has_subtype_diff;   /* does it have subtype_diff? */
      75                 :             :     int         entries_count;  /* total number of entries being split */
      76                 :             : 
      77                 :             :     /* Information about currently selected split follows */
      78                 :             : 
      79                 :             :     bool        first;          /* true if no split was selected yet */
      80                 :             : 
      81                 :             :     RangeBound *left_upper;     /* upper bound of left interval */
      82                 :             :     RangeBound *right_lower;    /* lower bound of right interval */
      83                 :             : 
      84                 :             :     float4      ratio;          /* split ratio */
      85                 :             :     float4      overlap;        /* overlap between left and right predicate */
      86                 :             :     int         common_left;    /* # common entries destined for each side */
      87                 :             :     int         common_right;
      88                 :             : } ConsiderSplitContext;
      89                 :             : 
      90                 :             : /*
      91                 :             :  * Bounds extracted from a non-empty range, for use in
      92                 :             :  * range_gist_double_sorting_split.
      93                 :             :  */
      94                 :             : typedef struct
      95                 :             : {
      96                 :             :     RangeBound  lower;
      97                 :             :     RangeBound  upper;
      98                 :             : } NonEmptyRange;
      99                 :             : 
     100                 :             : /*
     101                 :             :  * Represents information about an entry that can be placed in either group
     102                 :             :  * without affecting overlap over selected axis ("common entry").
     103                 :             :  */
     104                 :             : typedef struct
     105                 :             : {
     106                 :             :     /* Index of entry in the initial array */
     107                 :             :     int         index;
     108                 :             :     /* Delta between closeness of range to each of the two groups */
     109                 :             :     double      delta;
     110                 :             : } CommonEntry;
     111                 :             : 
     112                 :             : /* Helper macros to place an entry in the left or right group during split */
     113                 :             : /* Note direct access to variables v, typcache, left_range, right_range */
     114                 :             : #define PLACE_LEFT(range, off)                  \
     115                 :             :     do {                                        \
     116                 :             :         if (v->spl_nleft > 0)                 \
     117                 :             :             left_range = range_super_union(typcache, left_range, range); \
     118                 :             :         else                                    \
     119                 :             :             left_range = (range);               \
     120                 :             :         v->spl_left[v->spl_nleft++] = (off);  \
     121                 :             :     } while(0)
     122                 :             : 
     123                 :             : #define PLACE_RIGHT(range, off)                 \
     124                 :             :     do {                                        \
     125                 :             :         if (v->spl_nright > 0)                    \
     126                 :             :             right_range = range_super_union(typcache, right_range, range); \
     127                 :             :         else                                    \
     128                 :             :             right_range = (range);              \
     129                 :             :         v->spl_right[v->spl_nright++] = (off);    \
     130                 :             :     } while(0)
     131                 :             : 
     132                 :             : /* Copy a RangeType datum (hardwires typbyval and typlen for ranges...) */
     133                 :             : #define rangeCopy(r) \
     134                 :             :     ((RangeType *) DatumGetPointer(datumCopy(PointerGetDatum(r), \
     135                 :             :                                              false, -1)))
     136                 :             : 
     137                 :             : static RangeType *range_super_union(TypeCacheEntry *typcache, RangeType *r1,
     138                 :             :                                     RangeType *r2);
     139                 :             : static bool range_gist_consistent_int_range(TypeCacheEntry *typcache,
     140                 :             :                                             StrategyNumber strategy,
     141                 :             :                                             const RangeType *key,
     142                 :             :                                             const RangeType *query);
     143                 :             : static bool range_gist_consistent_int_multirange(TypeCacheEntry *typcache,
     144                 :             :                                                  StrategyNumber strategy,
     145                 :             :                                                  const RangeType *key,
     146                 :             :                                                  const MultirangeType *query);
     147                 :             : static bool range_gist_consistent_int_element(TypeCacheEntry *typcache,
     148                 :             :                                               StrategyNumber strategy,
     149                 :             :                                               const RangeType *key,
     150                 :             :                                               Datum query);
     151                 :             : static bool range_gist_consistent_leaf_range(TypeCacheEntry *typcache,
     152                 :             :                                              StrategyNumber strategy,
     153                 :             :                                              const RangeType *key,
     154                 :             :                                              const RangeType *query);
     155                 :             : static bool range_gist_consistent_leaf_multirange(TypeCacheEntry *typcache,
     156                 :             :                                                   StrategyNumber strategy,
     157                 :             :                                                   const RangeType *key,
     158                 :             :                                                   const MultirangeType *query);
     159                 :             : static bool range_gist_consistent_leaf_element(TypeCacheEntry *typcache,
     160                 :             :                                                StrategyNumber strategy,
     161                 :             :                                                const RangeType *key,
     162                 :             :                                                Datum query);
     163                 :             : static void range_gist_fallback_split(TypeCacheEntry *typcache,
     164                 :             :                                       GistEntryVector *entryvec,
     165                 :             :                                       GIST_SPLITVEC *v);
     166                 :             : static void range_gist_class_split(TypeCacheEntry *typcache,
     167                 :             :                                    GistEntryVector *entryvec,
     168                 :             :                                    GIST_SPLITVEC *v,
     169                 :             :                                    SplitLR *classes_groups);
     170                 :             : static void range_gist_single_sorting_split(TypeCacheEntry *typcache,
     171                 :             :                                             GistEntryVector *entryvec,
     172                 :             :                                             GIST_SPLITVEC *v,
     173                 :             :                                             bool use_upper_bound);
     174                 :             : static void range_gist_double_sorting_split(TypeCacheEntry *typcache,
     175                 :             :                                             GistEntryVector *entryvec,
     176                 :             :                                             GIST_SPLITVEC *v);
     177                 :             : static void range_gist_consider_split(ConsiderSplitContext *context,
     178                 :             :                                       RangeBound *right_lower, int min_left_count,
     179                 :             :                                       RangeBound *left_upper, int max_left_count);
     180                 :             : static int  get_gist_range_class(RangeType *range);
     181                 :             : static int  single_bound_cmp(const void *a, const void *b, void *arg);
     182                 :             : static int  interval_cmp_lower(const void *a, const void *b, void *arg);
     183                 :             : static int  interval_cmp_upper(const void *a, const void *b, void *arg);
     184                 :             : static int  common_entry_cmp(const void *i1, const void *i2);
     185                 :             : static float8 call_subtype_diff(TypeCacheEntry *typcache,
     186                 :             :                                 Datum val1, Datum val2);
     187                 :             : 
     188                 :             : 
     189                 :             : /* GiST query consistency check */
     190                 :             : Datum
     191                 :      458357 : range_gist_consistent(PG_FUNCTION_ARGS)
     192                 :             : {
     193                 :      458357 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     194                 :      458357 :     Datum       query = PG_GETARG_DATUM(1);
     195                 :      458357 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     196                 :             :     bool        result;
     197                 :      458357 :     Oid         subtype = PG_GETARG_OID(3);
     198                 :      458357 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     199                 :      458357 :     RangeType  *key = DatumGetRangeTypeP(entry->key);
     200                 :             :     TypeCacheEntry *typcache;
     201                 :             : 
     202                 :             :     /* All operators served by this function are exact */
     203                 :      458357 :     *recheck = false;
     204                 :             : 
     205                 :      458357 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(key));
     206                 :             : 
     207                 :             :     /*
     208                 :             :      * Perform consistent checking using function corresponding to key type
     209                 :             :      * (leaf or internal) and query subtype (range, multirange, or element).
     210                 :             :      * Note that invalid subtype means that query type matches key type
     211                 :             :      * (range).
     212                 :             :      */
     213         [ +  + ]:      458357 :     if (GIST_LEAF(entry))
     214                 :             :     {
     215   [ +  +  +  + ]:      453597 :         if (!OidIsValid(subtype) || subtype == ANYRANGEOID)
     216                 :      248627 :             result = range_gist_consistent_leaf_range(typcache, strategy, key,
     217                 :      248627 :                                                       DatumGetRangeTypeP(query));
     218         [ +  + ]:      204970 :         else if (subtype == ANYMULTIRANGEOID)
     219                 :      200680 :             result = range_gist_consistent_leaf_multirange(typcache, strategy, key,
     220                 :      200680 :                                                            DatumGetMultirangeTypeP(query));
     221                 :             :         else
     222                 :        4290 :             result = range_gist_consistent_leaf_element(typcache, strategy,
     223                 :             :                                                         key, query);
     224                 :             :     }
     225                 :             :     else
     226                 :             :     {
     227   [ +  -  +  + ]:        4760 :         if (!OidIsValid(subtype) || subtype == ANYRANGEOID)
     228                 :        2380 :             result = range_gist_consistent_int_range(typcache, strategy, key,
     229                 :        2380 :                                                      DatumGetRangeTypeP(query));
     230         [ +  + ]:        2380 :         else if (subtype == ANYMULTIRANGEOID)
     231                 :        2142 :             result = range_gist_consistent_int_multirange(typcache, strategy, key,
     232                 :        2142 :                                                           DatumGetMultirangeTypeP(query));
     233                 :             :         else
     234                 :         238 :             result = range_gist_consistent_int_element(typcache, strategy,
     235                 :             :                                                        key, query);
     236                 :             :     }
     237                 :      458357 :     PG_RETURN_BOOL(result);
     238                 :             : }
     239                 :             : 
     240                 :             : /*
     241                 :             :  * GiST compress method for multiranges: multirange is approximated as union
     242                 :             :  * range with no gaps.
     243                 :             :  */
     244                 :             : Datum
     245                 :       26961 : multirange_gist_compress(PG_FUNCTION_ARGS)
     246                 :             : {
     247                 :       26961 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     248                 :             : 
     249         [ +  + ]:       26961 :     if (entry->leafkey)
     250                 :             :     {
     251                 :       15484 :         MultirangeType *mr = DatumGetMultirangeTypeP(entry->key);
     252                 :             :         RangeType  *r;
     253                 :             :         TypeCacheEntry *typcache;
     254                 :       15484 :         GISTENTRY  *retval = palloc_object(GISTENTRY);
     255                 :             : 
     256                 :       15484 :         typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
     257                 :       15484 :         r = multirange_get_union_range(typcache->rngtype, mr);
     258                 :             : 
     259                 :       15484 :         gistentryinit(*retval, RangeTypePGetDatum(r),
     260                 :             :                       entry->rel, entry->page, entry->offset, false);
     261                 :             : 
     262                 :       15484 :         PG_RETURN_POINTER(retval);
     263                 :             :     }
     264                 :             : 
     265                 :       11477 :     PG_RETURN_POINTER(entry);
     266                 :             : }
     267                 :             : 
     268                 :             : /* GiST query consistency check for multiranges */
     269                 :             : Datum
     270                 :      181337 : multirange_gist_consistent(PG_FUNCTION_ARGS)
     271                 :             : {
     272                 :      181337 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
     273                 :      181337 :     Datum       query = PG_GETARG_DATUM(1);
     274                 :      181337 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     275                 :             :     bool        result;
     276                 :      181337 :     Oid         subtype = PG_GETARG_OID(3);
     277                 :      181337 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
     278                 :      181337 :     RangeType  *key = DatumGetRangeTypeP(entry->key);
     279                 :             :     TypeCacheEntry *typcache;
     280                 :             : 
     281                 :             :     /*
     282                 :             :      * All operators served by this function are inexact because multirange is
     283                 :             :      * approximated by union range with no gaps.
     284                 :             :      */
     285                 :      181337 :     *recheck = true;
     286                 :             : 
     287                 :      181337 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(key));
     288                 :             : 
     289                 :             :     /*
     290                 :             :      * Perform consistent checking using function corresponding to key type
     291                 :             :      * (leaf or internal) and query subtype (range, multirange, or element).
     292                 :             :      * Note that invalid subtype means that query type matches key type
     293                 :             :      * (multirange).
     294                 :             :      */
     295         [ +  + ]:      181337 :     if (GIST_LEAF(entry))
     296                 :             :     {
     297   [ +  +  +  + ]:      177157 :         if (!OidIsValid(subtype) || subtype == ANYMULTIRANGEOID)
     298                 :       98129 :             result = range_gist_consistent_leaf_multirange(typcache, strategy, key,
     299                 :       98129 :                                                            DatumGetMultirangeTypeP(query));
     300         [ +  + ]:       79028 :         else if (subtype == ANYRANGEOID)
     301                 :       77109 :             result = range_gist_consistent_leaf_range(typcache, strategy, key,
     302                 :       77109 :                                                       DatumGetRangeTypeP(query));
     303                 :             :         else
     304                 :        1919 :             result = range_gist_consistent_leaf_element(typcache, strategy,
     305                 :             :                                                         key, query);
     306                 :             :     }
     307                 :             :     else
     308                 :             :     {
     309   [ +  -  +  + ]:        4180 :         if (!OidIsValid(subtype) || subtype == ANYMULTIRANGEOID)
     310                 :        2200 :             result = range_gist_consistent_int_multirange(typcache, strategy, key,
     311                 :        2200 :                                                           DatumGetMultirangeTypeP(query));
     312         [ +  + ]:        1980 :         else if (subtype == ANYRANGEOID)
     313                 :        1870 :             result = range_gist_consistent_int_range(typcache, strategy, key,
     314                 :        1870 :                                                      DatumGetRangeTypeP(query));
     315                 :             :         else
     316                 :         110 :             result = range_gist_consistent_int_element(typcache, strategy,
     317                 :             :                                                        key, query);
     318                 :             :     }
     319                 :      181337 :     PG_RETURN_BOOL(result);
     320                 :             : }
     321                 :             : 
     322                 :             : /* form union range */
     323                 :             : Datum
     324                 :       37534 : range_gist_union(PG_FUNCTION_ARGS)
     325                 :             : {
     326                 :       37534 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     327                 :       37534 :     GISTENTRY  *ent = entryvec->vector;
     328                 :             :     RangeType  *result_range;
     329                 :             :     TypeCacheEntry *typcache;
     330                 :             :     int         i;
     331                 :             : 
     332                 :       37534 :     result_range = DatumGetRangeTypeP(ent[0].key);
     333                 :             : 
     334                 :       37534 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(result_range));
     335                 :             : 
     336         [ +  + ]:      112108 :     for (i = 1; i < entryvec->n; i++)
     337                 :             :     {
     338                 :       74574 :         result_range = range_super_union(typcache, result_range,
     339                 :       74574 :                                          DatumGetRangeTypeP(ent[i].key));
     340                 :             :     }
     341                 :             : 
     342                 :       37534 :     PG_RETURN_RANGE_P(result_range);
     343                 :             : }
     344                 :             : 
     345                 :             : /*
     346                 :             :  * We store ranges as ranges in GiST indexes, so we do not need
     347                 :             :  * compress, decompress, or fetch functions.  Note this implies a limit
     348                 :             :  * on the size of range values that can be indexed.
     349                 :             :  */
     350                 :             : 
     351                 :             : /*
     352                 :             :  * GiST page split penalty function.
     353                 :             :  *
     354                 :             :  * The penalty function has the following goals (in order from most to least
     355                 :             :  * important):
     356                 :             :  * - Keep normal ranges separate
     357                 :             :  * - Avoid broadening the class of the original predicate
     358                 :             :  * - Avoid broadening (as determined by subtype_diff) the original predicate
     359                 :             :  * - Favor adding ranges to narrower original predicates
     360                 :             :  */
     361                 :             : Datum
     362                 :      493980 : range_gist_penalty(PG_FUNCTION_ARGS)
     363                 :             : {
     364                 :      493980 :     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
     365                 :      493980 :     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
     366                 :      493980 :     float      *penalty = (float *) PG_GETARG_POINTER(2);
     367                 :      493980 :     RangeType  *orig = DatumGetRangeTypeP(origentry->key);
     368                 :      493980 :     RangeType  *new = DatumGetRangeTypeP(newentry->key);
     369                 :             :     TypeCacheEntry *typcache;
     370                 :             :     bool        has_subtype_diff;
     371                 :             :     RangeBound  orig_lower,
     372                 :             :                 new_lower,
     373                 :             :                 orig_upper,
     374                 :             :                 new_upper;
     375                 :             :     bool        orig_empty,
     376                 :             :                 new_empty;
     377                 :             : 
     378         [ -  + ]:      493980 :     if (RangeTypeGetOid(orig) != RangeTypeGetOid(new))
     379         [ #  # ]:           0 :         elog(ERROR, "range types do not match");
     380                 :             : 
     381                 :      493980 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(orig));
     382                 :             : 
     383                 :      493980 :     has_subtype_diff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
     384                 :             : 
     385                 :      493980 :     range_deserialize(typcache, orig, &orig_lower, &orig_upper, &orig_empty);
     386                 :      493980 :     range_deserialize(typcache, new, &new_lower, &new_upper, &new_empty);
     387                 :             : 
     388                 :             :     /*
     389                 :             :      * Distinct branches for handling distinct classes of ranges.  Note that
     390                 :             :      * penalty values only need to be commensurate within the same class of
     391                 :             :      * new range.
     392                 :             :      */
     393         [ +  + ]:      493980 :     if (new_empty)
     394                 :             :     {
     395                 :             :         /* Handle insertion of empty range */
     396         [ +  + ]:       93630 :         if (orig_empty)
     397                 :             :         {
     398                 :             :             /*
     399                 :             :              * The best case is to insert it to empty original range.
     400                 :             :              * Insertion here means no broadening of original range. Also
     401                 :             :              * original range is the most narrow.
     402                 :             :              */
     403                 :        6220 :             *penalty = 0.0;
     404                 :             :         }
     405         [ +  + ]:       87410 :         else if (RangeIsOrContainsEmpty(orig))
     406                 :             :         {
     407                 :             :             /*
     408                 :             :              * The second case is to insert empty range into range which
     409                 :             :              * contains at least one underlying empty range.  There is still
     410                 :             :              * no broadening of original range, but original range is not as
     411                 :             :              * narrow as possible.
     412                 :             :              */
     413                 :        1544 :             *penalty = CONTAIN_EMPTY_PENALTY;
     414                 :             :         }
     415   [ -  +  -  - ]:       85866 :         else if (orig_lower.infinite && orig_upper.infinite)
     416                 :             :         {
     417                 :             :             /*
     418                 :             :              * Original range requires broadening.  (-inf; +inf) is most far
     419                 :             :              * from normal range in this case.
     420                 :             :              */
     421                 :           0 :             *penalty = 2 * CONTAIN_EMPTY_PENALTY;
     422                 :             :         }
     423   [ +  -  -  + ]:       85866 :         else if (orig_lower.infinite || orig_upper.infinite)
     424                 :             :         {
     425                 :             :             /*
     426                 :             :              * (-inf, x) or (x, +inf) original ranges are closer to normal
     427                 :             :              * ranges, so it's worse to mix it with empty ranges.
     428                 :             :              */
     429                 :           0 :             *penalty = 3 * CONTAIN_EMPTY_PENALTY;
     430                 :             :         }
     431                 :             :         else
     432                 :             :         {
     433                 :             :             /*
     434                 :             :              * The least preferred case is broadening of normal range.
     435                 :             :              */
     436                 :       85866 :             *penalty = 4 * CONTAIN_EMPTY_PENALTY;
     437                 :             :         }
     438                 :             :     }
     439   [ +  +  -  + ]:      400350 :     else if (new_lower.infinite && new_upper.infinite)
     440                 :             :     {
     441                 :             :         /* Handle insertion of (-inf, +inf) range */
     442   [ #  #  #  # ]:           0 :         if (orig_lower.infinite && orig_upper.infinite)
     443                 :             :         {
     444                 :             :             /*
     445                 :             :              * Best case is inserting to (-inf, +inf) original range.
     446                 :             :              */
     447                 :           0 :             *penalty = 0.0;
     448                 :             :         }
     449   [ #  #  #  # ]:           0 :         else if (orig_lower.infinite || orig_upper.infinite)
     450                 :             :         {
     451                 :             :             /*
     452                 :             :              * When original range is (-inf, x) or (x, +inf) it requires
     453                 :             :              * broadening of original range (extension of one bound to
     454                 :             :              * infinity).
     455                 :             :              */
     456                 :           0 :             *penalty = INFINITE_BOUND_PENALTY;
     457                 :             :         }
     458                 :             :         else
     459                 :             :         {
     460                 :             :             /*
     461                 :             :              * Insertion to normal original range is least preferred.
     462                 :             :              */
     463                 :           0 :             *penalty = 2 * INFINITE_BOUND_PENALTY;
     464                 :             :         }
     465                 :             : 
     466         [ #  # ]:           0 :         if (RangeIsOrContainsEmpty(orig))
     467                 :             :         {
     468                 :             :             /*
     469                 :             :              * Original range is narrower when it doesn't contain empty
     470                 :             :              * ranges. Add additional penalty otherwise.
     471                 :             :              */
     472                 :           0 :             *penalty += CONTAIN_EMPTY_PENALTY;
     473                 :             :         }
     474                 :             :     }
     475         [ +  + ]:      400350 :     else if (new_lower.infinite)
     476                 :             :     {
     477                 :             :         /* Handle insertion of (-inf, x) range */
     478   [ +  +  +  + ]:       18214 :         if (!orig_empty && orig_lower.infinite)
     479                 :             :         {
     480         [ -  + ]:         792 :             if (orig_upper.infinite)
     481                 :             :             {
     482                 :             :                 /*
     483                 :             :                  * (-inf, +inf) range won't be extended by insertion of (-inf,
     484                 :             :                  * x) range. It's a less desirable case than insertion to
     485                 :             :                  * (-inf, y) original range without extension, because in that
     486                 :             :                  * case original range is narrower. But we can't express that
     487                 :             :                  * in single float value.
     488                 :             :                  */
     489                 :           0 :                 *penalty = 0.0;
     490                 :             :             }
     491                 :             :             else
     492                 :             :             {
     493         [ +  + ]:         792 :                 if (range_cmp_bounds(typcache, &new_upper, &orig_upper) > 0)
     494                 :             :                 {
     495                 :             :                     /*
     496                 :             :                      * Get extension of original range using subtype_diff. Use
     497                 :             :                      * constant if subtype_diff unavailable.
     498                 :             :                      */
     499         [ +  - ]:         568 :                     if (has_subtype_diff)
     500                 :         568 :                         *penalty = call_subtype_diff(typcache,
     501                 :             :                                                      new_upper.val,
     502                 :             :                                                      orig_upper.val);
     503                 :             :                     else
     504                 :           0 :                         *penalty = DEFAULT_SUBTYPE_DIFF_PENALTY;
     505                 :             :                 }
     506                 :             :                 else
     507                 :             :                 {
     508                 :             :                     /* No extension of original range */
     509                 :         224 :                     *penalty = 0.0;
     510                 :             :                 }
     511                 :             :             }
     512                 :             :         }
     513                 :             :         else
     514                 :             :         {
     515                 :             :             /*
     516                 :             :              * If lower bound of original range is not -inf, then extension of
     517                 :             :              * it is infinity.
     518                 :             :              */
     519                 :       17422 :             *penalty = get_float4_infinity();
     520                 :             :         }
     521                 :             :     }
     522         [ +  + ]:      382136 :     else if (new_upper.infinite)
     523                 :             :     {
     524                 :             :         /* Handle insertion of (x, +inf) range */
     525   [ +  +  +  + ]:       13998 :         if (!orig_empty && orig_upper.infinite)
     526                 :             :         {
     527         [ +  + ]:         792 :             if (orig_lower.infinite)
     528                 :             :             {
     529                 :             :                 /*
     530                 :             :                  * (-inf, +inf) range won't be extended by insertion of (x,
     531                 :             :                  * +inf) range. It's a less desirable case than insertion to
     532                 :             :                  * (y, +inf) original range without extension, because in that
     533                 :             :                  * case original range is narrower. But we can't express that
     534                 :             :                  * in single float value.
     535                 :             :                  */
     536                 :         297 :                 *penalty = 0.0;
     537                 :             :             }
     538                 :             :             else
     539                 :             :             {
     540         [ -  + ]:         495 :                 if (range_cmp_bounds(typcache, &new_lower, &orig_lower) < 0)
     541                 :             :                 {
     542                 :             :                     /*
     543                 :             :                      * Get extension of original range using subtype_diff. Use
     544                 :             :                      * constant if subtype_diff unavailable.
     545                 :             :                      */
     546         [ #  # ]:           0 :                     if (has_subtype_diff)
     547                 :           0 :                         *penalty = call_subtype_diff(typcache,
     548                 :             :                                                      orig_lower.val,
     549                 :             :                                                      new_lower.val);
     550                 :             :                     else
     551                 :           0 :                         *penalty = DEFAULT_SUBTYPE_DIFF_PENALTY;
     552                 :             :                 }
     553                 :             :                 else
     554                 :             :                 {
     555                 :             :                     /* No extension of original range */
     556                 :         495 :                     *penalty = 0.0;
     557                 :             :                 }
     558                 :             :             }
     559                 :             :         }
     560                 :             :         else
     561                 :             :         {
     562                 :             :             /*
     563                 :             :              * If upper bound of original range is not +inf, then extension of
     564                 :             :              * it is infinity.
     565                 :             :              */
     566                 :       13206 :             *penalty = get_float4_infinity();
     567                 :             :         }
     568                 :             :     }
     569                 :             :     else
     570                 :             :     {
     571                 :             :         /* Handle insertion of normal (non-empty, non-infinite) range */
     572   [ +  +  +  +  :      368138 :         if (orig_empty || orig_lower.infinite || orig_upper.infinite)
                   +  + ]
     573                 :             :         {
     574                 :             :             /*
     575                 :             :              * Avoid mixing normal ranges with infinite and empty ranges.
     576                 :             :              */
     577                 :       32478 :             *penalty = get_float4_infinity();
     578                 :             :         }
     579                 :             :         else
     580                 :             :         {
     581                 :             :             /*
     582                 :             :              * Calculate extension of original range by calling subtype_diff.
     583                 :             :              * Use constant if subtype_diff unavailable.
     584                 :             :              */
     585                 :      335660 :             float8      diff = 0.0;
     586                 :             : 
     587         [ +  + ]:      335660 :             if (range_cmp_bounds(typcache, &new_lower, &orig_lower) < 0)
     588                 :             :             {
     589         [ +  - ]:      109216 :                 if (has_subtype_diff)
     590                 :      109216 :                     diff += call_subtype_diff(typcache,
     591                 :             :                                               orig_lower.val,
     592                 :             :                                               new_lower.val);
     593                 :             :                 else
     594                 :           0 :                     diff += DEFAULT_SUBTYPE_DIFF_PENALTY;
     595                 :             :             }
     596         [ +  + ]:      335660 :             if (range_cmp_bounds(typcache, &new_upper, &orig_upper) > 0)
     597                 :             :             {
     598         [ +  - ]:      289371 :                 if (has_subtype_diff)
     599                 :      289371 :                     diff += call_subtype_diff(typcache,
     600                 :             :                                               new_upper.val,
     601                 :             :                                               orig_upper.val);
     602                 :             :                 else
     603                 :           0 :                     diff += DEFAULT_SUBTYPE_DIFF_PENALTY;
     604                 :             :             }
     605                 :      335660 :             *penalty = diff;
     606                 :             :         }
     607                 :             :     }
     608                 :             : 
     609                 :      493980 :     PG_RETURN_POINTER(penalty);
     610                 :             : }
     611                 :             : 
     612                 :             : /*
     613                 :             :  * The GiST PickSplit method for ranges
     614                 :             :  *
     615                 :             :  * Primarily, we try to segregate ranges of different classes.  If splitting
     616                 :             :  * ranges of the same class, use the appropriate split method for that class.
     617                 :             :  */
     618                 :             : Datum
     619                 :         316 : range_gist_picksplit(PG_FUNCTION_ARGS)
     620                 :             : {
     621                 :         316 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
     622                 :         316 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     623                 :             :     TypeCacheEntry *typcache;
     624                 :             :     OffsetNumber i;
     625                 :             :     RangeType  *pred_left;
     626                 :             :     int         nbytes;
     627                 :             :     OffsetNumber maxoff;
     628                 :             :     int         count_in_classes[CLS_COUNT];
     629                 :             :     int         j;
     630                 :         316 :     int         non_empty_classes_count = 0;
     631                 :         316 :     int         biggest_class = -1;
     632                 :         316 :     int         biggest_class_count = 0;
     633                 :             :     int         total_count;
     634                 :             : 
     635                 :             :     /* use first item to look up range type's info */
     636                 :         316 :     pred_left = DatumGetRangeTypeP(entryvec->vector[FirstOffsetNumber].key);
     637                 :         316 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(pred_left));
     638                 :             : 
     639                 :         316 :     maxoff = entryvec->n - 1;
     640                 :         316 :     nbytes = (maxoff + 1) * sizeof(OffsetNumber);
     641                 :         316 :     v->spl_left = (OffsetNumber *) palloc(nbytes);
     642                 :         316 :     v->spl_right = (OffsetNumber *) palloc(nbytes);
     643                 :             : 
     644                 :             :     /*
     645                 :             :      * Get count distribution of range classes.
     646                 :             :      */
     647                 :         316 :     memset(count_in_classes, 0, sizeof(count_in_classes));
     648         [ +  + ]:      137232 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
     649                 :             :     {
     650                 :      136916 :         RangeType  *range = DatumGetRangeTypeP(entryvec->vector[i].key);
     651                 :             : 
     652                 :      136916 :         count_in_classes[get_gist_range_class(range)]++;
     653                 :             :     }
     654                 :             : 
     655                 :             :     /*
     656                 :             :      * Count non-empty classes and find biggest class.
     657                 :             :      */
     658                 :         316 :     total_count = maxoff;
     659         [ +  + ]:        3160 :     for (j = 0; j < CLS_COUNT; j++)
     660                 :             :     {
     661         [ +  + ]:        2844 :         if (count_in_classes[j] > 0)
     662                 :             :         {
     663         [ +  + ]:         362 :             if (count_in_classes[j] > biggest_class_count)
     664                 :             :             {
     665                 :         332 :                 biggest_class_count = count_in_classes[j];
     666                 :         332 :                 biggest_class = j;
     667                 :             :             }
     668                 :         362 :             non_empty_classes_count++;
     669                 :             :         }
     670                 :             :     }
     671                 :             : 
     672                 :             :     Assert(non_empty_classes_count > 0);
     673                 :             : 
     674         [ +  + ]:         316 :     if (non_empty_classes_count == 1)
     675                 :             :     {
     676                 :             :         /* One non-empty class, so split inside class */
     677         [ +  + ]:         285 :         if ((biggest_class & ~CLS_CONTAIN_EMPTY) == CLS_NORMAL)
     678                 :             :         {
     679                 :             :             /* double sorting split for normal ranges */
     680                 :         257 :             range_gist_double_sorting_split(typcache, entryvec, v);
     681                 :             :         }
     682         [ -  + ]:          28 :         else if ((biggest_class & ~CLS_CONTAIN_EMPTY) == CLS_LOWER_INF)
     683                 :             :         {
     684                 :             :             /* upper bound sorting split for (-inf, x) ranges */
     685                 :           0 :             range_gist_single_sorting_split(typcache, entryvec, v, true);
     686                 :             :         }
     687         [ -  + ]:          28 :         else if ((biggest_class & ~CLS_CONTAIN_EMPTY) == CLS_UPPER_INF)
     688                 :             :         {
     689                 :             :             /* lower bound sorting split for (x, +inf) ranges */
     690                 :           0 :             range_gist_single_sorting_split(typcache, entryvec, v, false);
     691                 :             :         }
     692                 :             :         else
     693                 :             :         {
     694                 :             :             /* trivial split for all (-inf, +inf) or all empty ranges */
     695                 :          28 :             range_gist_fallback_split(typcache, entryvec, v);
     696                 :             :         }
     697                 :             :     }
     698                 :             :     else
     699                 :             :     {
     700                 :             :         /*
     701                 :             :          * Class based split.
     702                 :             :          *
     703                 :             :          * To which side of the split should each class go?  Initialize them
     704                 :             :          * all to go to the left side.
     705                 :             :          */
     706                 :             :         SplitLR     classes_groups[CLS_COUNT];
     707                 :             : 
     708                 :          31 :         memset(classes_groups, 0, sizeof(classes_groups));
     709                 :             : 
     710         [ +  + ]:          31 :         if (count_in_classes[CLS_NORMAL] > 0)
     711                 :             :         {
     712                 :             :             /* separate normal ranges if any */
     713                 :          27 :             classes_groups[CLS_NORMAL] = SPLIT_RIGHT;
     714                 :             :         }
     715                 :             :         else
     716                 :             :         {
     717                 :             :             /*----------
     718                 :             :              * Try to split classes in one of two ways:
     719                 :             :              *  1) containing infinities - not containing infinities
     720                 :             :              *  2) containing empty - not containing empty
     721                 :             :              *
     722                 :             :              * Select the way which balances the ranges between left and right
     723                 :             :              * the best. If split in these ways is not possible, there are at
     724                 :             :              * most 3 classes, so just separate biggest class.
     725                 :             :              *----------
     726                 :             :              */
     727                 :             :             int         infCount,
     728                 :             :                         nonInfCount;
     729                 :             :             int         emptyCount,
     730                 :             :                         nonEmptyCount;
     731                 :             : 
     732                 :           4 :             nonInfCount =
     733                 :           4 :                 count_in_classes[CLS_NORMAL] +
     734                 :           4 :                 count_in_classes[CLS_CONTAIN_EMPTY] +
     735                 :           4 :                 count_in_classes[CLS_EMPTY];
     736                 :           4 :             infCount = total_count - nonInfCount;
     737                 :             : 
     738                 :           4 :             nonEmptyCount =
     739                 :           4 :                 count_in_classes[CLS_NORMAL] +
     740                 :           4 :                 count_in_classes[CLS_LOWER_INF] +
     741                 :           4 :                 count_in_classes[CLS_UPPER_INF] +
     742                 :           4 :                 count_in_classes[CLS_LOWER_INF | CLS_UPPER_INF];
     743                 :           4 :             emptyCount = total_count - nonEmptyCount;
     744                 :             : 
     745   [ +  -  +  - ]:           4 :             if (infCount > 0 && nonInfCount > 0 &&
     746                 :           4 :                 (abs(infCount - nonInfCount) <=
     747         [ +  - ]:           4 :                  abs(emptyCount - nonEmptyCount)))
     748                 :             :             {
     749                 :           4 :                 classes_groups[CLS_NORMAL] = SPLIT_RIGHT;
     750                 :           4 :                 classes_groups[CLS_CONTAIN_EMPTY] = SPLIT_RIGHT;
     751                 :           4 :                 classes_groups[CLS_EMPTY] = SPLIT_RIGHT;
     752                 :             :             }
     753   [ #  #  #  # ]:           0 :             else if (emptyCount > 0 && nonEmptyCount > 0)
     754                 :             :             {
     755                 :           0 :                 classes_groups[CLS_NORMAL] = SPLIT_RIGHT;
     756                 :           0 :                 classes_groups[CLS_LOWER_INF] = SPLIT_RIGHT;
     757                 :           0 :                 classes_groups[CLS_UPPER_INF] = SPLIT_RIGHT;
     758                 :           0 :                 classes_groups[CLS_LOWER_INF | CLS_UPPER_INF] = SPLIT_RIGHT;
     759                 :             :             }
     760                 :             :             else
     761                 :             :             {
     762                 :             :                 /*
     763                 :             :                  * Either total_count == emptyCount or total_count ==
     764                 :             :                  * infCount.
     765                 :             :                  */
     766                 :           0 :                 classes_groups[biggest_class] = SPLIT_RIGHT;
     767                 :             :             }
     768                 :             :         }
     769                 :             : 
     770                 :          31 :         range_gist_class_split(typcache, entryvec, v, classes_groups);
     771                 :             :     }
     772                 :             : 
     773                 :         316 :     PG_RETURN_POINTER(v);
     774                 :             : }
     775                 :             : 
     776                 :             : /* equality comparator for GiST */
     777                 :             : Datum
     778                 :       37384 : range_gist_same(PG_FUNCTION_ARGS)
     779                 :             : {
     780                 :       37384 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     781                 :       37384 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     782                 :       37384 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
     783                 :             : 
     784                 :             :     /*
     785                 :             :      * range_eq will ignore the RANGE_CONTAIN_EMPTY flag, so we have to check
     786                 :             :      * that for ourselves.  More generally, if the entries have been properly
     787                 :             :      * normalized, then unequal flags bytes must mean unequal ranges ... so
     788                 :             :      * let's just test all the flag bits at once.
     789                 :             :      */
     790         [ +  + ]:       37384 :     if (range_get_flags(r1) != range_get_flags(r2))
     791                 :          24 :         *result = false;
     792                 :             :     else
     793                 :             :     {
     794                 :             :         TypeCacheEntry *typcache;
     795                 :             : 
     796                 :       37360 :         typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     797                 :             : 
     798                 :       37360 :         *result = range_eq_internal(typcache, r1, r2);
     799                 :             :     }
     800                 :             : 
     801                 :       37384 :     PG_RETURN_POINTER(result);
     802                 :             : }
     803                 :             : 
     804                 :             : /*
     805                 :             :  *----------------------------------------------------------
     806                 :             :  * STATIC FUNCTIONS
     807                 :             :  *----------------------------------------------------------
     808                 :             :  */
     809                 :             : 
     810                 :             : /*
     811                 :             :  * Return the smallest range that contains r1 and r2
     812                 :             :  *
     813                 :             :  * This differs from regular range_union in two critical ways:
     814                 :             :  * 1. It won't throw an error for non-adjacent r1 and r2, but just absorb
     815                 :             :  * the intervening values into the result range.
     816                 :             :  * 2. We track whether any empty range has been union'd into the result,
     817                 :             :  * so that contained_by searches can be indexed.  Note that this means
     818                 :             :  * that *all* unions formed within the GiST index must go through here.
     819                 :             :  */
     820                 :             : static RangeType *
     821                 :      210931 : range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
     822                 :             : {
     823                 :             :     RangeType  *result;
     824                 :             :     RangeBound  lower1,
     825                 :             :                 lower2;
     826                 :             :     RangeBound  upper1,
     827                 :             :                 upper2;
     828                 :             :     bool        empty1,
     829                 :             :                 empty2;
     830                 :             :     char        flags1,
     831                 :             :                 flags2;
     832                 :             :     RangeBound *result_lower;
     833                 :             :     RangeBound *result_upper;
     834                 :             : 
     835                 :      210931 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     836                 :      210931 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     837                 :      210931 :     flags1 = range_get_flags(r1);
     838                 :      210931 :     flags2 = range_get_flags(r2);
     839                 :             : 
     840         [ +  + ]:      210931 :     if (empty1)
     841                 :             :     {
     842                 :             :         /* We can return r2 as-is if it already is or contains empty */
     843         [ +  + ]:       28296 :         if (flags2 & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY))
     844                 :       28292 :             return r2;
     845                 :             :         /* Else we'd better copy it (modify-in-place isn't safe) */
     846                 :           4 :         r2 = rangeCopy(r2);
     847                 :           4 :         range_set_contain_empty(r2);
     848                 :           4 :         return r2;
     849                 :             :     }
     850         [ +  + ]:      182635 :     if (empty2)
     851                 :             :     {
     852                 :             :         /* We can return r1 as-is if it already is or contains empty */
     853         [ +  + ]:        1552 :         if (flags1 & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY))
     854                 :        1544 :             return r1;
     855                 :             :         /* Else we'd better copy it (modify-in-place isn't safe) */
     856                 :           8 :         r1 = rangeCopy(r1);
     857                 :           8 :         range_set_contain_empty(r1);
     858                 :           8 :         return r1;
     859                 :             :     }
     860                 :             : 
     861         [ +  + ]:      181083 :     if (range_cmp_bounds(typcache, &lower1, &lower2) <= 0)
     862                 :      181029 :         result_lower = &lower1;
     863                 :             :     else
     864                 :          54 :         result_lower = &lower2;
     865                 :             : 
     866         [ +  + ]:      181083 :     if (range_cmp_bounds(typcache, &upper1, &upper2) >= 0)
     867                 :       69519 :         result_upper = &upper1;
     868                 :             :     else
     869                 :      111564 :         result_upper = &upper2;
     870                 :             : 
     871                 :             :     /* optimization to avoid constructing a new range */
     872   [ +  +  +  +  :      181083 :     if (result_lower == &lower1 && result_upper == &upper1 &&
                   +  + ]
     873         [ +  - ]:       69471 :         ((flags1 & RANGE_CONTAIN_EMPTY) || !(flags2 & RANGE_CONTAIN_EMPTY)))
     874                 :       69511 :         return r1;
     875   [ +  +  +  +  :      111572 :     if (result_lower == &lower2 && result_upper == &upper2 &&
                   +  - ]
     876         [ +  - ]:          46 :         ((flags2 & RANGE_CONTAIN_EMPTY) || !(flags1 & RANGE_CONTAIN_EMPTY)))
     877                 :          46 :         return r2;
     878                 :             : 
     879                 :      111526 :     result = make_range(typcache, result_lower, result_upper, false, NULL);
     880                 :             : 
     881   [ +  +  -  + ]:      111526 :     if ((flags1 & RANGE_CONTAIN_EMPTY) || (flags2 & RANGE_CONTAIN_EMPTY))
     882                 :         400 :         range_set_contain_empty(result);
     883                 :             : 
     884                 :      111526 :     return result;
     885                 :             : }
     886                 :             : 
     887                 :             : static bool
     888                 :        4048 : multirange_union_range_equal(TypeCacheEntry *typcache,
     889                 :             :                              const RangeType *r,
     890                 :             :                              const MultirangeType *mr)
     891                 :             : {
     892                 :             :     RangeBound  lower1,
     893                 :             :                 upper1,
     894                 :             :                 lower2,
     895                 :             :                 upper2,
     896                 :             :                 tmp;
     897                 :             :     bool        empty;
     898                 :             : 
     899   [ +  +  -  + ]:        4048 :     if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
     900   [ +  -  +  - ]:        2000 :         return (RangeIsEmpty(r) && MultirangeIsEmpty(mr));
     901                 :             : 
     902                 :        2048 :     range_deserialize(typcache, r, &lower1, &upper1, &empty);
     903                 :             :     Assert(!empty);
     904                 :        2048 :     multirange_get_bounds(typcache, mr, 0, &lower2, &tmp);
     905                 :        2048 :     multirange_get_bounds(typcache, mr, mr->rangeCount - 1, &tmp, &upper2);
     906                 :             : 
     907   [ +  +  +  + ]:        2133 :     return (range_cmp_bounds(typcache, &lower1, &lower2) == 0 &&
     908                 :          85 :             range_cmp_bounds(typcache, &upper1, &upper2) == 0);
     909                 :             : }
     910                 :             : 
     911                 :             : /*
     912                 :             :  * GiST consistent test on an index internal page with range query
     913                 :             :  */
     914                 :             : static bool
     915                 :        4250 : range_gist_consistent_int_range(TypeCacheEntry *typcache,
     916                 :             :                                 StrategyNumber strategy,
     917                 :             :                                 const RangeType *key,
     918                 :             :                                 const RangeType *query)
     919                 :             : {
     920   [ +  +  +  +  :        4250 :     switch (strategy)
          +  +  +  +  +  
                      - ]
     921                 :             :     {
     922                 :         458 :         case RANGESTRAT_BEFORE:
     923   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || RangeIsEmpty(query))
     924                 :         150 :                 return false;
     925                 :         308 :             return (!range_overright_internal(typcache, key, query));
     926                 :         458 :         case RANGESTRAT_OVERLEFT:
     927   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || RangeIsEmpty(query))
     928                 :         150 :                 return false;
     929                 :         308 :             return (!range_after_internal(typcache, key, query));
     930                 :         458 :         case RANGESTRAT_OVERLAPS:
     931                 :         458 :             return range_overlaps_internal(typcache, key, query);
     932                 :         458 :         case RANGESTRAT_OVERRIGHT:
     933   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || RangeIsEmpty(query))
     934                 :         150 :                 return false;
     935                 :         308 :             return (!range_before_internal(typcache, key, query));
     936                 :         458 :         case RANGESTRAT_AFTER:
     937   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || RangeIsEmpty(query))
     938                 :         150 :                 return false;
     939                 :         308 :             return (!range_overleft_internal(typcache, key, query));
     940                 :         458 :         case RANGESTRAT_ADJACENT:
     941   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || RangeIsEmpty(query))
     942                 :         150 :                 return false;
     943         [ -  + ]:         308 :             if (range_adjacent_internal(typcache, key, query))
     944                 :           0 :                 return true;
     945                 :         308 :             return range_overlaps_internal(typcache, key, query);
     946                 :         806 :         case RANGESTRAT_CONTAINS:
     947                 :         806 :             return range_contains_internal(typcache, key, query);
     948                 :         458 :         case RANGESTRAT_CONTAINED_BY:
     949                 :             : 
     950                 :             :             /*
     951                 :             :              * Empty ranges are contained by anything, so if key is or
     952                 :             :              * contains any empty ranges, we must descend into it.  Otherwise,
     953                 :             :              * descend only if key overlaps the query.
     954                 :             :              */
     955         [ +  + ]:         458 :             if (RangeIsOrContainsEmpty(key))
     956                 :          48 :                 return true;
     957                 :         410 :             return range_overlaps_internal(typcache, key, query);
     958                 :         238 :         case RANGESTRAT_EQ:
     959                 :             : 
     960                 :             :             /*
     961                 :             :              * If query is empty, descend only if the key is or contains any
     962                 :             :              * empty ranges.  Otherwise, descend if key contains query.
     963                 :             :              */
     964         [ -  + ]:         238 :             if (RangeIsEmpty(query))
     965                 :           0 :                 return RangeIsOrContainsEmpty(key);
     966                 :         238 :             return range_contains_internal(typcache, key, query);
     967                 :           0 :         default:
     968         [ #  # ]:           0 :             elog(ERROR, "unrecognized range strategy: %d", strategy);
     969                 :             :             return false;       /* keep compiler quiet */
     970                 :             :     }
     971                 :             : }
     972                 :             : 
     973                 :             : /*
     974                 :             :  * GiST consistent test on an index internal page with multirange query
     975                 :             :  */
     976                 :             : static bool
     977                 :        4342 : range_gist_consistent_int_multirange(TypeCacheEntry *typcache,
     978                 :             :                                      StrategyNumber strategy,
     979                 :             :                                      const RangeType *key,
     980                 :             :                                      const MultirangeType *query)
     981                 :             : {
     982   [ +  +  +  +  :        4342 :     switch (strategy)
          +  +  +  +  +  
                      - ]
     983                 :             :     {
     984                 :         458 :         case RANGESTRAT_BEFORE:
     985   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || MultirangeIsEmpty(query))
     986                 :         150 :                 return false;
     987                 :         308 :             return (!range_overright_multirange_internal(typcache, key, query));
     988                 :         458 :         case RANGESTRAT_OVERLEFT:
     989   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || MultirangeIsEmpty(query))
     990                 :         150 :                 return false;
     991                 :         308 :             return (!range_after_multirange_internal(typcache, key, query));
     992                 :         458 :         case RANGESTRAT_OVERLAPS:
     993                 :         458 :             return range_overlaps_multirange_internal(typcache, key, query);
     994                 :         458 :         case RANGESTRAT_OVERRIGHT:
     995   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || MultirangeIsEmpty(query))
     996                 :         150 :                 return false;
     997                 :         308 :             return (!range_before_multirange_internal(typcache, key, query));
     998                 :         458 :         case RANGESTRAT_AFTER:
     999   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || MultirangeIsEmpty(query))
    1000                 :         150 :                 return false;
    1001                 :         308 :             return (!range_overleft_multirange_internal(typcache, key, query));
    1002                 :         458 :         case RANGESTRAT_ADJACENT:
    1003   [ +  +  +  + ]:         458 :             if (RangeIsEmpty(key) || MultirangeIsEmpty(query))
    1004                 :         150 :                 return false;
    1005         [ -  + ]:         308 :             if (range_adjacent_multirange_internal(typcache, key, query))
    1006                 :           0 :                 return true;
    1007                 :         308 :             return range_overlaps_multirange_internal(typcache, key, query);
    1008                 :         916 :         case RANGESTRAT_CONTAINS:
    1009                 :         916 :             return range_contains_multirange_internal(typcache, key, query);
    1010                 :         458 :         case RANGESTRAT_CONTAINED_BY:
    1011                 :             : 
    1012                 :             :             /*
    1013                 :             :              * Empty ranges are contained by anything, so if key is or
    1014                 :             :              * contains any empty ranges, we must descend into it.  Otherwise,
    1015                 :             :              * descend only if key overlaps the query.
    1016                 :             :              */
    1017         [ +  + ]:         458 :             if (RangeIsOrContainsEmpty(key))
    1018                 :          48 :                 return true;
    1019                 :         410 :             return range_overlaps_multirange_internal(typcache, key, query);
    1020                 :         220 :         case RANGESTRAT_EQ:
    1021                 :             : 
    1022                 :             :             /*
    1023                 :             :              * If query is empty, descend only if the key is or contains any
    1024                 :             :              * empty ranges.  Otherwise, descend if key contains query.
    1025                 :             :              */
    1026         [ +  + ]:         220 :             if (MultirangeIsEmpty(query))
    1027                 :         110 :                 return RangeIsOrContainsEmpty(key);
    1028                 :         110 :             return range_contains_multirange_internal(typcache, key, query);
    1029                 :           0 :         default:
    1030         [ #  # ]:           0 :             elog(ERROR, "unrecognized range strategy: %d", strategy);
    1031                 :             :             return false;       /* keep compiler quiet */
    1032                 :             :     }
    1033                 :             : }
    1034                 :             : 
    1035                 :             : /*
    1036                 :             :  * GiST consistent test on an index internal page with element query
    1037                 :             :  */
    1038                 :             : static bool
    1039                 :         348 : range_gist_consistent_int_element(TypeCacheEntry *typcache,
    1040                 :             :                                   StrategyNumber strategy,
    1041                 :             :                                   const RangeType *key,
    1042                 :             :                                   Datum query)
    1043                 :             : {
    1044         [ +  - ]:         348 :     switch (strategy)
    1045                 :             :     {
    1046                 :         348 :         case RANGESTRAT_CONTAINS_ELEM:
    1047                 :         348 :             return range_contains_elem_internal(typcache, key, query);
    1048                 :           0 :         default:
    1049         [ #  # ]:           0 :             elog(ERROR, "unrecognized range strategy: %d", strategy);
    1050                 :             :             return false;       /* keep compiler quiet */
    1051                 :             :     }
    1052                 :             : }
    1053                 :             : 
    1054                 :             : /*
    1055                 :             :  * GiST consistent test on an index leaf page with range query
    1056                 :             :  */
    1057                 :             : static bool
    1058                 :      325736 : range_gist_consistent_leaf_range(TypeCacheEntry *typcache,
    1059                 :             :                                  StrategyNumber strategy,
    1060                 :             :                                  const RangeType *key,
    1061                 :             :                                  const RangeType *query)
    1062                 :             : {
    1063   [ +  +  +  +  :      325736 :     switch (strategy)
          +  +  +  +  +  
                      - ]
    1064                 :             :     {
    1065                 :        9543 :         case RANGESTRAT_BEFORE:
    1066                 :        9543 :             return range_before_internal(typcache, key, query);
    1067                 :       23847 :         case RANGESTRAT_OVERLEFT:
    1068                 :       23847 :             return range_overleft_internal(typcache, key, query);
    1069                 :       15910 :         case RANGESTRAT_OVERLAPS:
    1070                 :       15910 :             return range_overlaps_internal(typcache, key, query);
    1071                 :       54400 :         case RANGESTRAT_OVERRIGHT:
    1072                 :       54400 :             return range_overright_internal(typcache, key, query);
    1073                 :       50557 :         case RANGESTRAT_AFTER:
    1074                 :       50557 :             return range_after_internal(typcache, key, query);
    1075                 :       23847 :         case RANGESTRAT_ADJACENT:
    1076                 :       23847 :             return range_adjacent_internal(typcache, key, query);
    1077                 :       85277 :         case RANGESTRAT_CONTAINS:
    1078                 :       85277 :             return range_contains_internal(typcache, key, query);
    1079                 :       20483 :         case RANGESTRAT_CONTAINED_BY:
    1080                 :       20483 :             return range_contained_by_internal(typcache, key, query);
    1081                 :       41872 :         case RANGESTRAT_EQ:
    1082                 :       41872 :             return range_eq_internal(typcache, key, query);
    1083                 :           0 :         default:
    1084         [ #  # ]:           0 :             elog(ERROR, "unrecognized range strategy: %d", strategy);
    1085                 :             :             return false;       /* keep compiler quiet */
    1086                 :             :     }
    1087                 :             : }
    1088                 :             : 
    1089                 :             : /*
    1090                 :             :  * GiST consistent test on an index leaf page with multirange query
    1091                 :             :  */
    1092                 :             : static bool
    1093                 :      298809 : range_gist_consistent_leaf_multirange(TypeCacheEntry *typcache,
    1094                 :             :                                       StrategyNumber strategy,
    1095                 :             :                                       const RangeType *key,
    1096                 :             :                                       const MultirangeType *query)
    1097                 :             : {
    1098   [ +  +  +  +  :      298809 :     switch (strategy)
          +  +  +  +  +  
                      - ]
    1099                 :             :     {
    1100                 :        9543 :         case RANGESTRAT_BEFORE:
    1101                 :        9543 :             return range_before_multirange_internal(typcache, key, query);
    1102                 :       23847 :         case RANGESTRAT_OVERLEFT:
    1103                 :       23847 :             return range_overleft_multirange_internal(typcache, key, query);
    1104                 :       11331 :         case RANGESTRAT_OVERLAPS:
    1105                 :       11331 :             return range_overlaps_multirange_internal(typcache, key, query);
    1106                 :       54400 :         case RANGESTRAT_OVERRIGHT:
    1107                 :       54400 :             return range_overright_multirange_internal(typcache, key, query);
    1108                 :       50557 :         case RANGESTRAT_AFTER:
    1109                 :       50557 :             return range_after_multirange_internal(typcache, key, query);
    1110                 :       23847 :         case RANGESTRAT_ADJACENT:
    1111                 :       23847 :             return range_adjacent_multirange_internal(typcache, key, query);
    1112                 :      100077 :         case RANGESTRAT_CONTAINS:
    1113                 :      100077 :             return range_contains_multirange_internal(typcache, key, query);
    1114                 :       21159 :         case RANGESTRAT_CONTAINED_BY:
    1115                 :       21159 :             return multirange_contains_range_internal(typcache, query, key);
    1116                 :        4048 :         case RANGESTRAT_EQ:
    1117                 :        4048 :             return multirange_union_range_equal(typcache, key, query);
    1118                 :           0 :         default:
    1119         [ #  # ]:           0 :             elog(ERROR, "unrecognized range strategy: %d", strategy);
    1120                 :             :             return false;       /* keep compiler quiet */
    1121                 :             :     }
    1122                 :             : }
    1123                 :             : 
    1124                 :             : /*
    1125                 :             :  * GiST consistent test on an index leaf page with element query
    1126                 :             :  */
    1127                 :             : static bool
    1128                 :        6209 : range_gist_consistent_leaf_element(TypeCacheEntry *typcache,
    1129                 :             :                                    StrategyNumber strategy,
    1130                 :             :                                    const RangeType *key,
    1131                 :             :                                    Datum query)
    1132                 :             : {
    1133         [ +  - ]:        6209 :     switch (strategy)
    1134                 :             :     {
    1135                 :        6209 :         case RANGESTRAT_CONTAINS_ELEM:
    1136                 :        6209 :             return range_contains_elem_internal(typcache, key, query);
    1137                 :           0 :         default:
    1138         [ #  # ]:           0 :             elog(ERROR, "unrecognized range strategy: %d", strategy);
    1139                 :             :             return false;       /* keep compiler quiet */
    1140                 :             :     }
    1141                 :             : }
    1142                 :             : 
    1143                 :             : /*
    1144                 :             :  * Trivial split: half of entries will be placed on one page
    1145                 :             :  * and the other half on the other page.
    1146                 :             :  */
    1147                 :             : static void
    1148                 :          28 : range_gist_fallback_split(TypeCacheEntry *typcache,
    1149                 :             :                           GistEntryVector *entryvec,
    1150                 :             :                           GIST_SPLITVEC *v)
    1151                 :             : {
    1152                 :          28 :     RangeType  *left_range = NULL;
    1153                 :          28 :     RangeType  *right_range = NULL;
    1154                 :             :     OffsetNumber i,
    1155                 :             :                 maxoff,
    1156                 :             :                 split_idx;
    1157                 :             : 
    1158                 :          28 :     maxoff = entryvec->n - 1;
    1159                 :             :     /* Split entries before this to left page, after to right: */
    1160                 :          28 :     split_idx = (maxoff - FirstOffsetNumber) / 2 + FirstOffsetNumber;
    1161                 :             : 
    1162                 :          28 :     v->spl_nleft = 0;
    1163                 :          28 :     v->spl_nright = 0;
    1164         [ +  + ]:       14392 :     for (i = FirstOffsetNumber; i <= maxoff; i++)
    1165                 :             :     {
    1166                 :       14364 :         RangeType  *range = DatumGetRangeTypeP(entryvec->vector[i].key);
    1167                 :             : 
    1168         [ +  + ]:       14364 :         if (i < split_idx)
    1169         [ +  + ]:        7160 :             PLACE_LEFT(range, i);
    1170                 :             :         else
    1171         [ +  + ]:        7204 :             PLACE_RIGHT(range, i);
    1172                 :             :     }
    1173                 :             : 
    1174                 :          28 :     v->spl_ldatum = RangeTypePGetDatum(left_range);
    1175                 :          28 :     v->spl_rdatum = RangeTypePGetDatum(right_range);
    1176                 :          28 : }
    1177                 :             : 
    1178                 :             : /*
    1179                 :             :  * Split based on classes of ranges.
    1180                 :             :  *
    1181                 :             :  * See get_gist_range_class for class definitions.
    1182                 :             :  * classes_groups is an array of length CLS_COUNT indicating the side of the
    1183                 :             :  * split to which each class should go.
    1184                 :             :  */
    1185                 :             : static void
    1186                 :          31 : range_gist_class_split(TypeCacheEntry *typcache,
    1187                 :             :                        GistEntryVector *entryvec,
    1188                 :             :                        GIST_SPLITVEC *v,
    1189                 :             :                        SplitLR *classes_groups)
    1190                 :             : {
    1191                 :          31 :     RangeType  *left_range = NULL;
    1192                 :          31 :     RangeType  *right_range = NULL;
    1193                 :             :     OffsetNumber i,
    1194                 :             :                 maxoff;
    1195                 :             : 
    1196                 :          31 :     maxoff = entryvec->n - 1;
    1197                 :             : 
    1198                 :          31 :     v->spl_nleft = 0;
    1199                 :          31 :     v->spl_nright = 0;
    1200         [ +  + ]:       27715 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
    1201                 :             :     {
    1202                 :       27684 :         RangeType  *range = DatumGetRangeTypeP(entryvec->vector[i].key);
    1203                 :             :         int         class;
    1204                 :             : 
    1205                 :             :         /* Get class of range */
    1206                 :       27684 :         class = get_gist_range_class(range);
    1207                 :             : 
    1208                 :             :         /* Place range to appropriate page */
    1209         [ +  + ]:       27684 :         if (classes_groups[class] == SPLIT_LEFT)
    1210         [ +  + ]:        7204 :             PLACE_LEFT(range, i);
    1211                 :             :         else
    1212                 :             :         {
    1213                 :             :             Assert(classes_groups[class] == SPLIT_RIGHT);
    1214         [ +  + ]:       20480 :             PLACE_RIGHT(range, i);
    1215                 :             :         }
    1216                 :             :     }
    1217                 :             : 
    1218                 :          31 :     v->spl_ldatum = RangeTypePGetDatum(left_range);
    1219                 :          31 :     v->spl_rdatum = RangeTypePGetDatum(right_range);
    1220                 :          31 : }
    1221                 :             : 
    1222                 :             : /*
    1223                 :             :  * Sorting based split. First half of entries according to the sort will be
    1224                 :             :  * placed to one page, and second half of entries will be placed to other
    1225                 :             :  * page. use_upper_bound parameter indicates whether to use upper or lower
    1226                 :             :  * bound for sorting.
    1227                 :             :  */
    1228                 :             : static void
    1229                 :           0 : range_gist_single_sorting_split(TypeCacheEntry *typcache,
    1230                 :             :                                 GistEntryVector *entryvec,
    1231                 :             :                                 GIST_SPLITVEC *v,
    1232                 :             :                                 bool use_upper_bound)
    1233                 :             : {
    1234                 :             :     SingleBoundSortItem *sortItems;
    1235                 :           0 :     RangeType  *left_range = NULL;
    1236                 :           0 :     RangeType  *right_range = NULL;
    1237                 :             :     OffsetNumber i,
    1238                 :             :                 maxoff,
    1239                 :             :                 split_idx;
    1240                 :             : 
    1241                 :           0 :     maxoff = entryvec->n - 1;
    1242                 :             : 
    1243                 :           0 :     sortItems = palloc_array(SingleBoundSortItem, maxoff);
    1244                 :             : 
    1245                 :             :     /*
    1246                 :             :      * Prepare auxiliary array and sort the values.
    1247                 :             :      */
    1248         [ #  # ]:           0 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
    1249                 :             :     {
    1250                 :           0 :         RangeType  *range = DatumGetRangeTypeP(entryvec->vector[i].key);
    1251                 :             :         RangeBound  bound2;
    1252                 :             :         bool        empty;
    1253                 :             : 
    1254                 :           0 :         sortItems[i - 1].index = i;
    1255                 :             :         /* Put appropriate bound into array */
    1256         [ #  # ]:           0 :         if (use_upper_bound)
    1257                 :           0 :             range_deserialize(typcache, range, &bound2,
    1258                 :           0 :                               &sortItems[i - 1].bound, &empty);
    1259                 :             :         else
    1260                 :           0 :             range_deserialize(typcache, range, &sortItems[i - 1].bound,
    1261                 :             :                               &bound2, &empty);
    1262                 :             :         Assert(!empty);
    1263                 :             :     }
    1264                 :             : 
    1265                 :           0 :     qsort_arg(sortItems, maxoff, sizeof(SingleBoundSortItem),
    1266                 :             :               single_bound_cmp, typcache);
    1267                 :             : 
    1268                 :           0 :     split_idx = maxoff / 2;
    1269                 :             : 
    1270                 :           0 :     v->spl_nleft = 0;
    1271                 :           0 :     v->spl_nright = 0;
    1272                 :             : 
    1273         [ #  # ]:           0 :     for (i = 0; i < maxoff; i++)
    1274                 :             :     {
    1275                 :           0 :         int         idx = sortItems[i].index;
    1276                 :           0 :         RangeType  *range = DatumGetRangeTypeP(entryvec->vector[idx].key);
    1277                 :             : 
    1278         [ #  # ]:           0 :         if (i < split_idx)
    1279         [ #  # ]:           0 :             PLACE_LEFT(range, idx);
    1280                 :             :         else
    1281         [ #  # ]:           0 :             PLACE_RIGHT(range, idx);
    1282                 :             :     }
    1283                 :             : 
    1284                 :           0 :     v->spl_ldatum = RangeTypePGetDatum(left_range);
    1285                 :           0 :     v->spl_rdatum = RangeTypePGetDatum(right_range);
    1286                 :           0 : }
    1287                 :             : 
    1288                 :             : /*
    1289                 :             :  * Double sorting split algorithm.
    1290                 :             :  *
    1291                 :             :  * The algorithm considers dividing ranges into two groups. The first (left)
    1292                 :             :  * group contains general left bound. The second (right) group contains
    1293                 :             :  * general right bound. The challenge is to find upper bound of left group
    1294                 :             :  * and lower bound of right group so that overlap of groups is minimal and
    1295                 :             :  * ratio of distribution is acceptable. Algorithm finds for each lower bound of
    1296                 :             :  * right group minimal upper bound of left group, and for each upper bound of
    1297                 :             :  * left group maximal lower bound of right group. For each found pair
    1298                 :             :  * range_gist_consider_split considers replacement of currently selected
    1299                 :             :  * split with the new one.
    1300                 :             :  *
    1301                 :             :  * After that, all the entries are divided into three groups:
    1302                 :             :  * 1) Entries which should be placed to the left group
    1303                 :             :  * 2) Entries which should be placed to the right group
    1304                 :             :  * 3) "Common entries" which can be placed to either group without affecting
    1305                 :             :  *    amount of overlap.
    1306                 :             :  *
    1307                 :             :  * The common ranges are distributed by difference of distance from lower
    1308                 :             :  * bound of common range to lower bound of right group and distance from upper
    1309                 :             :  * bound of common range to upper bound of left group.
    1310                 :             :  *
    1311                 :             :  * For details see:
    1312                 :             :  * "A new double sorting-based node splitting algorithm for R-tree",
    1313                 :             :  * A. Korotkov
    1314                 :             :  * http://syrcose.ispras.ru/2011/files/SYRCoSE2011_Proceedings.pdf#page=36
    1315                 :             :  */
    1316                 :             : static void
    1317                 :         257 : range_gist_double_sorting_split(TypeCacheEntry *typcache,
    1318                 :             :                                 GistEntryVector *entryvec,
    1319                 :             :                                 GIST_SPLITVEC *v)
    1320                 :             : {
    1321                 :             :     ConsiderSplitContext context;
    1322                 :             :     OffsetNumber i,
    1323                 :             :                 maxoff;
    1324                 :         257 :     RangeType  *left_range = NULL,
    1325                 :         257 :                *right_range = NULL;
    1326                 :             :     int         common_entries_count;
    1327                 :             :     NonEmptyRange *by_lower,
    1328                 :             :                *by_upper;
    1329                 :             :     CommonEntry *common_entries;
    1330                 :             :     int         nentries,
    1331                 :             :                 i1,
    1332                 :             :                 i2;
    1333                 :             :     RangeBound *right_lower,
    1334                 :             :                *left_upper;
    1335                 :             : 
    1336                 :         257 :     memset(&context, 0, sizeof(ConsiderSplitContext));
    1337                 :         257 :     context.typcache = typcache;
    1338                 :         257 :     context.has_subtype_diff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
    1339                 :             : 
    1340                 :         257 :     maxoff = entryvec->n - 1;
    1341                 :         257 :     nentries = context.entries_count = maxoff - FirstOffsetNumber + 1;
    1342                 :         257 :     context.first = true;
    1343                 :             : 
    1344                 :             :     /* Allocate arrays for sorted range bounds */
    1345                 :         257 :     by_lower = palloc_array(NonEmptyRange, nentries);
    1346                 :         257 :     by_upper = palloc_array(NonEmptyRange, nentries);
    1347                 :             : 
    1348                 :             :     /* Fill arrays of bounds */
    1349         [ +  + ]:       95125 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
    1350                 :             :     {
    1351                 :       94868 :         RangeType  *range = DatumGetRangeTypeP(entryvec->vector[i].key);
    1352                 :             :         bool        empty;
    1353                 :             : 
    1354                 :       94868 :         range_deserialize(typcache, range,
    1355                 :       94868 :                           &by_lower[i - FirstOffsetNumber].lower,
    1356                 :       94868 :                           &by_lower[i - FirstOffsetNumber].upper,
    1357                 :             :                           &empty);
    1358                 :             :         Assert(!empty);
    1359                 :             :     }
    1360                 :             : 
    1361                 :             :     /*
    1362                 :             :      * Make two arrays of range bounds: one sorted by lower bound and another
    1363                 :             :      * sorted by upper bound.
    1364                 :             :      */
    1365                 :         257 :     memcpy(by_upper, by_lower, nentries * sizeof(NonEmptyRange));
    1366                 :         257 :     qsort_arg(by_lower, nentries, sizeof(NonEmptyRange),
    1367                 :             :               interval_cmp_lower, typcache);
    1368                 :         257 :     qsort_arg(by_upper, nentries, sizeof(NonEmptyRange),
    1369                 :             :               interval_cmp_upper, typcache);
    1370                 :             : 
    1371                 :             :     /*----------
    1372                 :             :      * The goal is to form a left and right range, so that every entry
    1373                 :             :      * range is contained by either left or right interval (or both).
    1374                 :             :      *
    1375                 :             :      * For example, with the ranges (0,1), (1,3), (2,3), (2,4):
    1376                 :             :      *
    1377                 :             :      * 0 1 2 3 4
    1378                 :             :      * +-+
    1379                 :             :      *   +---+
    1380                 :             :      *     +-+
    1381                 :             :      *     +---+
    1382                 :             :      *
    1383                 :             :      * The left and right ranges are of the form (0,a) and (b,4).
    1384                 :             :      * We first consider splits where b is the lower bound of an entry.
    1385                 :             :      * We iterate through all entries, and for each b, calculate the
    1386                 :             :      * smallest possible a. Then we consider splits where a is the
    1387                 :             :      * upper bound of an entry, and for each a, calculate the greatest
    1388                 :             :      * possible b.
    1389                 :             :      *
    1390                 :             :      * In the above example, the first loop would consider splits:
    1391                 :             :      * b=0: (0,1)-(0,4)
    1392                 :             :      * b=1: (0,1)-(1,4)
    1393                 :             :      * b=2: (0,3)-(2,4)
    1394                 :             :      *
    1395                 :             :      * And the second loop:
    1396                 :             :      * a=1: (0,1)-(1,4)
    1397                 :             :      * a=3: (0,3)-(2,4)
    1398                 :             :      * a=4: (0,4)-(2,4)
    1399                 :             :      *----------
    1400                 :             :      */
    1401                 :             : 
    1402                 :             :     /*
    1403                 :             :      * Iterate over lower bound of right group, finding smallest possible
    1404                 :             :      * upper bound of left group.
    1405                 :             :      */
    1406                 :         257 :     i1 = 0;
    1407                 :         257 :     i2 = 0;
    1408                 :         257 :     right_lower = &by_lower[i1].lower;
    1409                 :         257 :     left_upper = &by_upper[i2].lower;
    1410                 :             :     while (true)
    1411                 :             :     {
    1412                 :             :         /*
    1413                 :             :          * Find next lower bound of right group.
    1414                 :             :          */
    1415   [ +  +  +  + ]:      331529 :         while (i1 < nentries &&
    1416                 :      165636 :                range_cmp_bounds(typcache, right_lower,
    1417                 :      165636 :                                 &by_lower[i1].lower) == 0)
    1418                 :             :         {
    1419         [ +  + ]:       94868 :             if (range_cmp_bounds(typcache, &by_lower[i1].upper,
    1420                 :             :                                  left_upper) > 0)
    1421                 :       62039 :                 left_upper = &by_lower[i1].upper;
    1422                 :       94868 :             i1++;
    1423                 :             :         }
    1424         [ +  + ]:       71025 :         if (i1 >= nentries)
    1425                 :         257 :             break;
    1426                 :       70768 :         right_lower = &by_lower[i1].lower;
    1427                 :             : 
    1428                 :             :         /*
    1429                 :             :          * Find count of ranges which anyway should be placed to the left
    1430                 :             :          * group.
    1431                 :             :          */
    1432   [ +  +  +  + ]:      321951 :         while (i2 < nentries &&
    1433                 :      156471 :                range_cmp_bounds(typcache, &by_upper[i2].upper,
    1434                 :             :                                 left_upper) <= 0)
    1435                 :       94712 :             i2++;
    1436                 :             : 
    1437                 :             :         /*
    1438                 :             :          * Consider found split to see if it's better than what we had.
    1439                 :             :          */
    1440                 :       70768 :         range_gist_consider_split(&context, right_lower, i1, left_upper, i2);
    1441                 :             :     }
    1442                 :             : 
    1443                 :             :     /*
    1444                 :             :      * Iterate over upper bound of left group finding greatest possible lower
    1445                 :             :      * bound of right group.
    1446                 :             :      */
    1447                 :         257 :     i1 = nentries - 1;
    1448                 :         257 :     i2 = nentries - 1;
    1449                 :         257 :     right_lower = &by_lower[i1].upper;
    1450                 :         257 :     left_upper = &by_upper[i2].upper;
    1451                 :             :     while (true)
    1452                 :             :     {
    1453                 :             :         /*
    1454                 :             :          * Find next upper bound of left group.
    1455                 :             :          */
    1456   [ +  +  +  + ]:      347657 :         while (i2 >= 0 &&
    1457                 :      173700 :                range_cmp_bounds(typcache, left_upper,
    1458                 :      173700 :                                 &by_upper[i2].upper) == 0)
    1459                 :             :         {
    1460         [ +  + ]:       94868 :             if (range_cmp_bounds(typcache, &by_upper[i2].lower,
    1461                 :             :                                  right_lower) < 0)
    1462                 :       62016 :                 right_lower = &by_upper[i2].lower;
    1463                 :       94868 :             i2--;
    1464                 :             :         }
    1465         [ +  + ]:       79089 :         if (i2 < 0)
    1466                 :         257 :             break;
    1467                 :       78832 :         left_upper = &by_upper[i2].upper;
    1468                 :             : 
    1469                 :             :         /*
    1470                 :             :          * Find count of intervals which anyway should be placed to the right
    1471                 :             :          * group.
    1472                 :             :          */
    1473   [ +  +  +  + ]:      330015 :         while (i1 >= 0 &&
    1474                 :      156471 :                range_cmp_bounds(typcache, &by_lower[i1].lower,
    1475                 :             :                                 right_lower) >= 0)
    1476                 :       94712 :             i1--;
    1477                 :             : 
    1478                 :             :         /*
    1479                 :             :          * Consider found split to see if it's better than what we had.
    1480                 :             :          */
    1481                 :       78832 :         range_gist_consider_split(&context, right_lower, i1 + 1,
    1482                 :             :                                   left_upper, i2 + 1);
    1483                 :             :     }
    1484                 :             : 
    1485                 :             :     /*
    1486                 :             :      * If we failed to find any acceptable splits, use trivial split.
    1487                 :             :      */
    1488         [ -  + ]:         257 :     if (context.first)
    1489                 :             :     {
    1490                 :           0 :         range_gist_fallback_split(typcache, entryvec, v);
    1491                 :           0 :         return;
    1492                 :             :     }
    1493                 :             : 
    1494                 :             :     /*
    1495                 :             :      * Ok, we have now selected bounds of the groups. Now we have to
    1496                 :             :      * distribute entries themselves. At first we distribute entries which can
    1497                 :             :      * be placed unambiguously and collect "common entries" to array.
    1498                 :             :      */
    1499                 :             : 
    1500                 :             :     /* Allocate vectors for results */
    1501                 :         257 :     v->spl_left = palloc_array(OffsetNumber, nentries);
    1502                 :         257 :     v->spl_right = palloc_array(OffsetNumber, nentries);
    1503                 :         257 :     v->spl_nleft = 0;
    1504                 :         257 :     v->spl_nright = 0;
    1505                 :             : 
    1506                 :             :     /*
    1507                 :             :      * Allocate an array for "common entries" - entries which can be placed to
    1508                 :             :      * either group without affecting overlap along selected axis.
    1509                 :             :      */
    1510                 :         257 :     common_entries_count = 0;
    1511                 :         257 :     common_entries = palloc_array(CommonEntry, nentries);
    1512                 :             : 
    1513                 :             :     /*
    1514                 :             :      * Distribute entries which can be distributed unambiguously, and collect
    1515                 :             :      * common entries.
    1516                 :             :      */
    1517         [ +  + ]:       95125 :     for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
    1518                 :             :     {
    1519                 :             :         RangeType  *range;
    1520                 :             :         RangeBound  lower,
    1521                 :             :                     upper;
    1522                 :             :         bool        empty;
    1523                 :             : 
    1524                 :             :         /*
    1525                 :             :          * Get upper and lower bounds along selected axis.
    1526                 :             :          */
    1527                 :       94868 :         range = DatumGetRangeTypeP(entryvec->vector[i].key);
    1528                 :             : 
    1529                 :       94868 :         range_deserialize(typcache, range, &lower, &upper, &empty);
    1530                 :             : 
    1531         [ +  + ]:       94868 :         if (range_cmp_bounds(typcache, &upper, context.left_upper) <= 0)
    1532                 :             :         {
    1533                 :             :             /* Fits in the left group */
    1534         [ +  + ]:       40100 :             if (range_cmp_bounds(typcache, &lower, context.right_lower) >= 0)
    1535                 :             :             {
    1536                 :             :                 /* Fits also in the right group, so "common entry" */
    1537                 :       12657 :                 common_entries[common_entries_count].index = i;
    1538         [ +  - ]:       12657 :                 if (context.has_subtype_diff)
    1539                 :             :                 {
    1540                 :             :                     /*
    1541                 :             :                      * delta = (lower - context.right_lower) -
    1542                 :             :                      * (context.left_upper - upper)
    1543                 :             :                      */
    1544                 :       12657 :                     common_entries[common_entries_count].delta =
    1545                 :       12657 :                         call_subtype_diff(typcache,
    1546                 :             :                                           lower.val,
    1547                 :       25314 :                                           context.right_lower->val) -
    1548                 :       12657 :                         call_subtype_diff(typcache,
    1549                 :       12657 :                                           context.left_upper->val,
    1550                 :             :                                           upper.val);
    1551                 :             :                 }
    1552                 :             :                 else
    1553                 :             :                 {
    1554                 :             :                     /* Without subtype_diff, take all deltas as zero */
    1555                 :           0 :                     common_entries[common_entries_count].delta = 0;
    1556                 :             :                 }
    1557                 :       12657 :                 common_entries_count++;
    1558                 :             :             }
    1559                 :             :             else
    1560                 :             :             {
    1561                 :             :                 /* Doesn't fit to the right group, so join to the left group */
    1562         [ +  + ]:       27443 :                 PLACE_LEFT(range, i);
    1563                 :             :             }
    1564                 :             :         }
    1565                 :             :         else
    1566                 :             :         {
    1567                 :             :             /*
    1568                 :             :              * Each entry should fit on either left or right group. Since this
    1569                 :             :              * entry didn't fit in the left group, it better fit in the right
    1570                 :             :              * group.
    1571                 :             :              */
    1572                 :             :             Assert(range_cmp_bounds(typcache, &lower,
    1573                 :             :                                     context.right_lower) >= 0);
    1574         [ +  + ]:       54768 :             PLACE_RIGHT(range, i);
    1575                 :             :         }
    1576                 :             :     }
    1577                 :             : 
    1578                 :             :     /*
    1579                 :             :      * Distribute "common entries", if any.
    1580                 :             :      */
    1581         [ +  + ]:         257 :     if (common_entries_count > 0)
    1582                 :             :     {
    1583                 :             :         /*
    1584                 :             :          * Sort "common entries" by calculated deltas in order to distribute
    1585                 :             :          * the most ambiguous entries first.
    1586                 :             :          */
    1587                 :         113 :         qsort(common_entries, common_entries_count, sizeof(CommonEntry),
    1588                 :             :               common_entry_cmp);
    1589                 :             : 
    1590                 :             :         /*
    1591                 :             :          * Distribute "common entries" between groups according to sorting.
    1592                 :             :          */
    1593         [ +  + ]:       12770 :         for (i = 0; i < common_entries_count; i++)
    1594                 :             :         {
    1595                 :             :             RangeType  *range;
    1596                 :       12657 :             int         idx = common_entries[i].index;
    1597                 :             : 
    1598                 :       12657 :             range = DatumGetRangeTypeP(entryvec->vector[idx].key);
    1599                 :             : 
    1600                 :             :             /*
    1601                 :             :              * Check if we have to place this entry in either group to achieve
    1602                 :             :              * LIMIT_RATIO.
    1603                 :             :              */
    1604         [ -  + ]:       12657 :             if (i < context.common_left)
    1605         [ #  # ]:           0 :                 PLACE_LEFT(range, idx);
    1606                 :             :             else
    1607         [ +  - ]:       12657 :                 PLACE_RIGHT(range, idx);
    1608                 :             :         }
    1609                 :             :     }
    1610                 :             : 
    1611                 :         257 :     v->spl_ldatum = PointerGetDatum(left_range);
    1612                 :         257 :     v->spl_rdatum = PointerGetDatum(right_range);
    1613                 :             : }
    1614                 :             : 
    1615                 :             : /*
    1616                 :             :  * Consider replacement of currently selected split with a better one
    1617                 :             :  * during range_gist_double_sorting_split.
    1618                 :             :  */
    1619                 :             : static void
    1620                 :      149600 : range_gist_consider_split(ConsiderSplitContext *context,
    1621                 :             :                           RangeBound *right_lower, int min_left_count,
    1622                 :             :                           RangeBound *left_upper, int max_left_count)
    1623                 :             : {
    1624                 :             :     int         left_count,
    1625                 :             :                 right_count;
    1626                 :             :     float4      ratio,
    1627                 :             :                 overlap;
    1628                 :             : 
    1629                 :             :     /*
    1630                 :             :      * Calculate entries distribution ratio assuming most uniform distribution
    1631                 :             :      * of common entries.
    1632                 :             :      */
    1633         [ +  + ]:      149600 :     if (min_left_count >= (context->entries_count + 1) / 2)
    1634                 :       63948 :         left_count = min_left_count;
    1635         [ +  + ]:       85652 :     else if (max_left_count <= context->entries_count / 2)
    1636                 :       61781 :         left_count = max_left_count;
    1637                 :             :     else
    1638                 :       23871 :         left_count = context->entries_count / 2;
    1639                 :      149600 :     right_count = context->entries_count - left_count;
    1640                 :             : 
    1641                 :             :     /*
    1642                 :             :      * Ratio of split: quotient between size of smaller group and total
    1643                 :             :      * entries count.  This is necessarily 0.5 or less; if it's less than
    1644                 :             :      * LIMIT_RATIO then we will never accept the new split.
    1645                 :             :      */
    1646         [ +  + ]:      149600 :     ratio = ((float4) Min(left_count, right_count)) /
    1647                 :      149600 :         ((float4) context->entries_count);
    1648                 :             : 
    1649         [ +  + ]:      149600 :     if (ratio > LIMIT_RATIO)
    1650                 :             :     {
    1651                 :       76064 :         bool        selectthis = false;
    1652                 :             : 
    1653                 :             :         /*
    1654                 :             :          * The ratio is acceptable, so compare current split with previously
    1655                 :             :          * selected one. We search for minimal overlap (allowing negative
    1656                 :             :          * values) and minimal ratio secondarily.  If subtype_diff is
    1657                 :             :          * available, it's used for overlap measure.  Without subtype_diff we
    1658                 :             :          * use number of "common entries" as an overlap measure.
    1659                 :             :          */
    1660         [ +  - ]:       76064 :         if (context->has_subtype_diff)
    1661                 :       76064 :             overlap = call_subtype_diff(context->typcache,
    1662                 :             :                                         left_upper->val,
    1663                 :             :                                         right_lower->val);
    1664                 :             :         else
    1665                 :           0 :             overlap = max_left_count - min_left_count;
    1666                 :             : 
    1667                 :             :         /* If there is no previous selection, select this split */
    1668         [ +  + ]:       76064 :         if (context->first)
    1669                 :         257 :             selectthis = true;
    1670                 :             :         else
    1671                 :             :         {
    1672                 :             :             /*
    1673                 :             :              * Choose the new split if it has a smaller overlap, or same
    1674                 :             :              * overlap but better ratio.
    1675                 :             :              */
    1676         [ +  + ]:       75807 :             if (overlap < context->overlap ||
    1677   [ +  +  +  + ]:       64060 :                 (overlap == context->overlap && ratio > context->ratio))
    1678                 :       22147 :                 selectthis = true;
    1679                 :             :         }
    1680                 :             : 
    1681         [ +  + ]:       76064 :         if (selectthis)
    1682                 :             :         {
    1683                 :             :             /* save information about selected split */
    1684                 :       22404 :             context->first = false;
    1685                 :       22404 :             context->ratio = ratio;
    1686                 :       22404 :             context->overlap = overlap;
    1687                 :       22404 :             context->right_lower = right_lower;
    1688                 :       22404 :             context->left_upper = left_upper;
    1689                 :       22404 :             context->common_left = max_left_count - left_count;
    1690                 :       22404 :             context->common_right = left_count - min_left_count;
    1691                 :             :         }
    1692                 :             :     }
    1693                 :      149600 : }
    1694                 :             : 
    1695                 :             : /*
    1696                 :             :  * Find class number for range.
    1697                 :             :  *
    1698                 :             :  * The class number is a valid combination of the properties of the
    1699                 :             :  * range.  Note: the highest possible number is 8, because CLS_EMPTY
    1700                 :             :  * can't be combined with anything else.
    1701                 :             :  */
    1702                 :             : static int
    1703                 :      164600 : get_gist_range_class(RangeType *range)
    1704                 :             : {
    1705                 :             :     int         classNumber;
    1706                 :             :     char        flags;
    1707                 :             : 
    1708                 :      164600 :     flags = range_get_flags(range);
    1709         [ +  + ]:      164600 :     if (flags & RANGE_EMPTY)
    1710                 :             :     {
    1711                 :       33468 :         classNumber = CLS_EMPTY;
    1712                 :             :     }
    1713                 :             :     else
    1714                 :             :     {
    1715                 :      131132 :         classNumber = 0;
    1716         [ +  + ]:      131132 :         if (flags & RANGE_LB_INF)
    1717                 :        2200 :             classNumber |= CLS_LOWER_INF;
    1718         [ +  + ]:      131132 :         if (flags & RANGE_UB_INF)
    1719                 :        1104 :             classNumber |= CLS_UPPER_INF;
    1720         [ -  + ]:      131132 :         if (flags & RANGE_CONTAIN_EMPTY)
    1721                 :           0 :             classNumber |= CLS_CONTAIN_EMPTY;
    1722                 :             :     }
    1723                 :      164600 :     return classNumber;
    1724                 :             : }
    1725                 :             : 
    1726                 :             : /*
    1727                 :             :  * Comparison function for range_gist_single_sorting_split.
    1728                 :             :  */
    1729                 :             : static int
    1730                 :           0 : single_bound_cmp(const void *a, const void *b, void *arg)
    1731                 :             : {
    1732                 :           0 :     const SingleBoundSortItem *i1 = a;
    1733                 :           0 :     const SingleBoundSortItem *i2 = b;
    1734                 :           0 :     TypeCacheEntry *typcache = arg;
    1735                 :             : 
    1736                 :           0 :     return range_cmp_bounds(typcache, &i1->bound, &i2->bound);
    1737                 :             : }
    1738                 :             : 
    1739                 :             : /*
    1740                 :             :  * Compare NonEmptyRanges by lower bound.
    1741                 :             :  */
    1742                 :             : static int
    1743                 :      255076 : interval_cmp_lower(const void *a, const void *b, void *arg)
    1744                 :             : {
    1745                 :      255076 :     const NonEmptyRange *i1 = a;
    1746                 :      255076 :     const NonEmptyRange *i2 = b;
    1747                 :      255076 :     TypeCacheEntry *typcache = arg;
    1748                 :             : 
    1749                 :      255076 :     return range_cmp_bounds(typcache, &i1->lower, &i2->lower);
    1750                 :             : }
    1751                 :             : 
    1752                 :             : /*
    1753                 :             :  * Compare NonEmptyRanges by upper bound.
    1754                 :             :  */
    1755                 :             : static int
    1756                 :      442950 : interval_cmp_upper(const void *a, const void *b, void *arg)
    1757                 :             : {
    1758                 :      442950 :     const NonEmptyRange *i1 = a;
    1759                 :      442950 :     const NonEmptyRange *i2 = b;
    1760                 :      442950 :     TypeCacheEntry *typcache = arg;
    1761                 :             : 
    1762                 :      442950 :     return range_cmp_bounds(typcache, &i1->upper, &i2->upper);
    1763                 :             : }
    1764                 :             : 
    1765                 :             : /*
    1766                 :             :  * Compare CommonEntrys by their deltas.
    1767                 :             :  */
    1768                 :             : static int
    1769                 :       12544 : common_entry_cmp(const void *i1, const void *i2)
    1770                 :             : {
    1771                 :       12544 :     double      delta1 = ((const CommonEntry *) i1)->delta;
    1772                 :       12544 :     double      delta2 = ((const CommonEntry *) i2)->delta;
    1773                 :             : 
    1774         [ +  + ]:       12544 :     if (delta1 < delta2)
    1775                 :        8588 :         return -1;
    1776         [ -  + ]:        3956 :     else if (delta1 > delta2)
    1777                 :           0 :         return 1;
    1778                 :             :     else
    1779                 :        3956 :         return 0;
    1780                 :             : }
    1781                 :             : 
    1782                 :             : /*
    1783                 :             :  * Convenience function to invoke type-specific subtype_diff function.
    1784                 :             :  * Caller must have already checked that there is one for the range type.
    1785                 :             :  */
    1786                 :             : static float8
    1787                 :      500533 : call_subtype_diff(TypeCacheEntry *typcache, Datum val1, Datum val2)
    1788                 :             : {
    1789                 :             :     float8      value;
    1790                 :             : 
    1791                 :      500533 :     value = DatumGetFloat8(FunctionCall2Coll(&typcache->rng_subdiff_finfo,
    1792                 :             :                                              typcache->rng_collation,
    1793                 :             :                                              val1, val2));
    1794                 :             :     /* Cope with buggy subtype_diff function by returning zero */
    1795         [ +  - ]:      500533 :     if (value >= 0.0)
    1796                 :      500533 :         return value;
    1797                 :           0 :     return 0.0;
    1798                 :             : }
        

Generated by: LCOV version 2.0-1