LCOV - code coverage report
Current view: top level - src/backend/utils/adt - rangetypes.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 86.2 % 1120 966
Test Date: 2026-03-27 22:16:19 Functions: 90.9 % 88 80
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * rangetypes.c
       4              :  *    I/O functions, operators, and support functions for range types.
       5              :  *
       6              :  * The stored (serialized) format of a range value is:
       7              :  *
       8              :  *  4 bytes: varlena header
       9              :  *  4 bytes: range type's OID
      10              :  *  Lower boundary value, if any, aligned according to subtype's typalign
      11              :  *  Upper boundary value, if any, aligned according to subtype's typalign
      12              :  *  1 byte for flags
      13              :  *
      14              :  * This representation is chosen to avoid needing any padding before the
      15              :  * lower boundary value, even when it requires double alignment.  We can
      16              :  * expect that the varlena header is presented to us on a suitably aligned
      17              :  * boundary (possibly after detoasting), and then the lower boundary is too.
      18              :  * Note that this means we can't work with a packed (short varlena header)
      19              :  * value; we must detoast it first.
      20              :  *
      21              :  *
      22              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      23              :  * Portions Copyright (c) 1994, Regents of the University of California
      24              :  *
      25              :  *
      26              :  * IDENTIFICATION
      27              :  *    src/backend/utils/adt/rangetypes.c
      28              :  *
      29              :  *-------------------------------------------------------------------------
      30              :  */
      31              : #include "postgres.h"
      32              : 
      33              : #include "access/tupmacs.h"
      34              : #include "common/hashfn.h"
      35              : #include "funcapi.h"
      36              : #include "libpq/pqformat.h"
      37              : #include "miscadmin.h"
      38              : #include "nodes/makefuncs.h"
      39              : #include "nodes/miscnodes.h"
      40              : #include "nodes/supportnodes.h"
      41              : #include "optimizer/clauses.h"
      42              : #include "optimizer/cost.h"
      43              : #include "optimizer/optimizer.h"
      44              : #include "port/pg_bitutils.h"
      45              : #include "utils/builtins.h"
      46              : #include "utils/date.h"
      47              : #include "utils/lsyscache.h"
      48              : #include "utils/rangetypes.h"
      49              : #include "utils/sortsupport.h"
      50              : #include "utils/timestamp.h"
      51              : #include "varatt.h"
      52              : 
      53              : 
      54              : /* fn_extra cache entry for one of the range I/O functions */
      55              : typedef struct RangeIOData
      56              : {
      57              :     TypeCacheEntry *typcache;   /* range type's typcache entry */
      58              :     FmgrInfo    typioproc;      /* element type's I/O function */
      59              :     Oid         typioparam;     /* element type's I/O parameter */
      60              : } RangeIOData;
      61              : 
      62              : 
      63              : static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
      64              :                                       IOFuncSelector func);
      65              : static int  range_fast_cmp(Datum a, Datum b, SortSupport ssup);
      66              : static char range_parse_flags(const char *flags_str);
      67              : static bool range_parse(const char *string, char *flags, char **lbound_str,
      68              :                         char **ubound_str, Node *escontext);
      69              : static const char *range_parse_bound(const char *string, const char *ptr,
      70              :                                      char **bound_str, bool *infinite,
      71              :                                      Node *escontext);
      72              : static char *range_deparse(char flags, const char *lbound_str,
      73              :                            const char *ubound_str);
      74              : static char *range_bound_escape(const char *value);
      75              : static Size datum_compute_size(Size data_length, Datum val, bool typbyval,
      76              :                                char typalign, int16 typlen, char typstorage);
      77              : static char *datum_write(char *ptr, Datum datum, bool typbyval,
      78              :                          char typalign, int16 typlen, char typstorage);
      79              : static Node *find_simplified_clause(PlannerInfo *root,
      80              :                                     Expr *rangeExpr, Expr *elemExpr);
      81              : static Expr *build_bound_expr(Expr *elemExpr, Datum val,
      82              :                               bool isLowerBound, bool isInclusive,
      83              :                               TypeCacheEntry *typeCache,
      84              :                               Oid opfamily, Oid rng_collation);
      85              : 
      86              : 
      87              : /*
      88              :  *----------------------------------------------------------
      89              :  * I/O FUNCTIONS
      90              :  *----------------------------------------------------------
      91              :  */
      92              : 
      93              : Datum
      94         4945 : range_in(PG_FUNCTION_ARGS)
      95              : {
      96         4945 :     char       *input_str = PG_GETARG_CSTRING(0);
      97         4945 :     Oid         rngtypoid = PG_GETARG_OID(1);
      98         4945 :     Oid         typmod = PG_GETARG_INT32(2);
      99         4945 :     Node       *escontext = fcinfo->context;
     100              :     RangeType  *range;
     101              :     RangeIOData *cache;
     102              :     char        flags;
     103              :     char       *lbound_str;
     104              :     char       *ubound_str;
     105              :     RangeBound  lower;
     106              :     RangeBound  upper;
     107              : 
     108         4945 :     check_stack_depth();        /* recurses when subtype is a range type */
     109              : 
     110         4945 :     cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
     111              : 
     112              :     /* parse */
     113         4945 :     if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
     114           12 :         PG_RETURN_NULL();
     115              : 
     116              :     /* call element type's input function */
     117         4881 :     if (RANGE_HAS_LBOUND(flags))
     118         4388 :         if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
     119              :                                    cache->typioparam, typmod,
     120              :                                    escontext, &lower.val))
     121            0 :             PG_RETURN_NULL();
     122         4881 :     if (RANGE_HAS_UBOUND(flags))
     123         4324 :         if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
     124              :                                    cache->typioparam, typmod,
     125              :                                    escontext, &upper.val))
     126           16 :             PG_RETURN_NULL();
     127              : 
     128         4865 :     lower.infinite = (flags & RANGE_LB_INF) != 0;
     129         4865 :     lower.inclusive = (flags & RANGE_LB_INC) != 0;
     130         4865 :     lower.lower = true;
     131         4865 :     upper.infinite = (flags & RANGE_UB_INF) != 0;
     132         4865 :     upper.inclusive = (flags & RANGE_UB_INC) != 0;
     133         4865 :     upper.lower = false;
     134              : 
     135              :     /* serialize and canonicalize */
     136         4865 :     range = make_range(cache->typcache, &lower, &upper,
     137         4865 :                        flags & RANGE_EMPTY, escontext);
     138              : 
     139         4853 :     PG_RETURN_RANGE_P(range);
     140              : }
     141              : 
     142              : Datum
     143        55591 : range_out(PG_FUNCTION_ARGS)
     144              : {
     145        55591 :     RangeType  *range = PG_GETARG_RANGE_P(0);
     146              :     char       *output_str;
     147              :     RangeIOData *cache;
     148              :     char        flags;
     149        55591 :     char       *lbound_str = NULL;
     150        55591 :     char       *ubound_str = NULL;
     151              :     RangeBound  lower;
     152              :     RangeBound  upper;
     153              :     bool        empty;
     154              : 
     155        55591 :     check_stack_depth();        /* recurses when subtype is a range type */
     156              : 
     157        55591 :     cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
     158              : 
     159              :     /* deserialize */
     160        55591 :     range_deserialize(cache->typcache, range, &lower, &upper, &empty);
     161        55591 :     flags = range_get_flags(range);
     162              : 
     163              :     /* call element type's output function */
     164        55591 :     if (RANGE_HAS_LBOUND(flags))
     165        45704 :         lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
     166        55591 :     if (RANGE_HAS_UBOUND(flags))
     167        45612 :         ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
     168              : 
     169              :     /* construct result string */
     170        55591 :     output_str = range_deparse(flags, lbound_str, ubound_str);
     171              : 
     172        55591 :     PG_RETURN_CSTRING(output_str);
     173              : }
     174              : 
     175              : /*
     176              :  * Binary representation: The first byte is the flags, then the lower bound
     177              :  * (if present), then the upper bound (if present).  Each bound is represented
     178              :  * by a 4-byte length header and the binary representation of that bound (as
     179              :  * returned by a call to the send function for the subtype).
     180              :  */
     181              : 
     182              : Datum
     183            0 : range_recv(PG_FUNCTION_ARGS)
     184              : {
     185            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     186            0 :     Oid         rngtypoid = PG_GETARG_OID(1);
     187            0 :     int32       typmod = PG_GETARG_INT32(2);
     188              :     RangeType  *range;
     189              :     RangeIOData *cache;
     190              :     char        flags;
     191              :     RangeBound  lower;
     192              :     RangeBound  upper;
     193              : 
     194            0 :     check_stack_depth();        /* recurses when subtype is a range type */
     195              : 
     196            0 :     cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
     197              : 
     198              :     /* receive the flags... */
     199            0 :     flags = (unsigned char) pq_getmsgbyte(buf);
     200              : 
     201              :     /*
     202              :      * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
     203              :      * confuse following tests.  Note that range_serialize will take care of
     204              :      * cleaning up any inconsistencies in the remaining flags.
     205              :      */
     206            0 :     flags &= (RANGE_EMPTY |
     207              :               RANGE_LB_INC |
     208              :               RANGE_LB_INF |
     209              :               RANGE_UB_INC |
     210              :               RANGE_UB_INF);
     211              : 
     212              :     /* receive the bounds ... */
     213            0 :     if (RANGE_HAS_LBOUND(flags))
     214              :     {
     215            0 :         uint32      bound_len = pq_getmsgint(buf, 4);
     216            0 :         const char *bound_data = pq_getmsgbytes(buf, bound_len);
     217              :         StringInfoData bound_buf;
     218              : 
     219            0 :         initStringInfo(&bound_buf);
     220            0 :         appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
     221              : 
     222            0 :         lower.val = ReceiveFunctionCall(&cache->typioproc,
     223              :                                         &bound_buf,
     224              :                                         cache->typioparam,
     225              :                                         typmod);
     226            0 :         pfree(bound_buf.data);
     227              :     }
     228              :     else
     229            0 :         lower.val = (Datum) 0;
     230              : 
     231            0 :     if (RANGE_HAS_UBOUND(flags))
     232              :     {
     233            0 :         uint32      bound_len = pq_getmsgint(buf, 4);
     234            0 :         const char *bound_data = pq_getmsgbytes(buf, bound_len);
     235              :         StringInfoData bound_buf;
     236              : 
     237            0 :         initStringInfo(&bound_buf);
     238            0 :         appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
     239              : 
     240            0 :         upper.val = ReceiveFunctionCall(&cache->typioproc,
     241              :                                         &bound_buf,
     242              :                                         cache->typioparam,
     243              :                                         typmod);
     244            0 :         pfree(bound_buf.data);
     245              :     }
     246              :     else
     247            0 :         upper.val = (Datum) 0;
     248              : 
     249            0 :     pq_getmsgend(buf);
     250              : 
     251              :     /* finish constructing RangeBound representation */
     252            0 :     lower.infinite = (flags & RANGE_LB_INF) != 0;
     253            0 :     lower.inclusive = (flags & RANGE_LB_INC) != 0;
     254            0 :     lower.lower = true;
     255            0 :     upper.infinite = (flags & RANGE_UB_INF) != 0;
     256            0 :     upper.inclusive = (flags & RANGE_UB_INC) != 0;
     257            0 :     upper.lower = false;
     258              : 
     259              :     /* serialize and canonicalize */
     260            0 :     range = make_range(cache->typcache, &lower, &upper,
     261            0 :                        flags & RANGE_EMPTY, NULL);
     262              : 
     263            0 :     PG_RETURN_RANGE_P(range);
     264              : }
     265              : 
     266              : Datum
     267            0 : range_send(PG_FUNCTION_ARGS)
     268              : {
     269            0 :     RangeType  *range = PG_GETARG_RANGE_P(0);
     270              :     StringInfoData buf;
     271              :     RangeIOData *cache;
     272              :     char        flags;
     273              :     RangeBound  lower;
     274              :     RangeBound  upper;
     275              :     bool        empty;
     276              : 
     277            0 :     check_stack_depth();        /* recurses when subtype is a range type */
     278              : 
     279            0 :     initStringInfo(&buf);
     280              : 
     281            0 :     cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
     282              : 
     283              :     /* deserialize */
     284            0 :     range_deserialize(cache->typcache, range, &lower, &upper, &empty);
     285            0 :     flags = range_get_flags(range);
     286              : 
     287              :     /* construct output */
     288            0 :     pq_begintypsend(&buf);
     289              : 
     290            0 :     pq_sendbyte(&buf, flags);
     291              : 
     292            0 :     if (RANGE_HAS_LBOUND(flags))
     293              :     {
     294            0 :         bytea      *bound = SendFunctionCall(&cache->typioproc, lower.val);
     295            0 :         uint32      bound_len = VARSIZE(bound) - VARHDRSZ;
     296            0 :         char       *bound_data = VARDATA(bound);
     297              : 
     298            0 :         pq_sendint32(&buf, bound_len);
     299            0 :         pq_sendbytes(&buf, bound_data, bound_len);
     300              :     }
     301              : 
     302            0 :     if (RANGE_HAS_UBOUND(flags))
     303              :     {
     304            0 :         bytea      *bound = SendFunctionCall(&cache->typioproc, upper.val);
     305            0 :         uint32      bound_len = VARSIZE(bound) - VARHDRSZ;
     306            0 :         char       *bound_data = VARDATA(bound);
     307              : 
     308            0 :         pq_sendint32(&buf, bound_len);
     309            0 :         pq_sendbytes(&buf, bound_data, bound_len);
     310              :     }
     311              : 
     312            0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     313              : }
     314              : 
     315              : /*
     316              :  * get_range_io_data: get cached information needed for range type I/O
     317              :  *
     318              :  * The range I/O functions need a bit more cached info than other range
     319              :  * functions, so they store a RangeIOData struct in fn_extra, not just a
     320              :  * pointer to a type cache entry.
     321              :  */
     322              : static RangeIOData *
     323        60536 : get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
     324              : {
     325        60536 :     RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
     326              : 
     327        60536 :     if (cache == NULL || cache->typcache->type_id != rngtypid)
     328              :     {
     329              :         int16       typlen;
     330              :         bool        typbyval;
     331              :         char        typalign;
     332              :         char        typdelim;
     333              :         Oid         typiofunc;
     334              : 
     335         6920 :         cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
     336              :                                                    sizeof(RangeIOData));
     337         6920 :         cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
     338         6920 :         if (cache->typcache->rngelemtype == NULL)
     339            0 :             elog(ERROR, "type %u is not a range type", rngtypid);
     340              : 
     341              :         /* get_type_io_data does more than we need, but is convenient */
     342         6920 :         get_type_io_data(cache->typcache->rngelemtype->type_id,
     343              :                          func,
     344              :                          &typlen,
     345              :                          &typbyval,
     346              :                          &typalign,
     347              :                          &typdelim,
     348              :                          &cache->typioparam,
     349              :                          &typiofunc);
     350              : 
     351         6920 :         if (!OidIsValid(typiofunc))
     352              :         {
     353              :             /* this could only happen for receive or send */
     354            0 :             if (func == IOFunc_receive)
     355            0 :                 ereport(ERROR,
     356              :                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
     357              :                          errmsg("no binary input function available for type %s",
     358              :                                 format_type_be(cache->typcache->rngelemtype->type_id))));
     359              :             else
     360            0 :                 ereport(ERROR,
     361              :                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
     362              :                          errmsg("no binary output function available for type %s",
     363              :                                 format_type_be(cache->typcache->rngelemtype->type_id))));
     364              :         }
     365         6920 :         fmgr_info_cxt(typiofunc, &cache->typioproc,
     366         6920 :                       fcinfo->flinfo->fn_mcxt);
     367              : 
     368         6920 :         fcinfo->flinfo->fn_extra = cache;
     369              :     }
     370              : 
     371        60536 :     return cache;
     372              : }
     373              : 
     374              : 
     375              : /*
     376              :  *----------------------------------------------------------
     377              :  * GENERIC FUNCTIONS
     378              :  *----------------------------------------------------------
     379              :  */
     380              : 
     381              : /* Construct standard-form range value from two arguments */
     382              : Datum
     383        74848 : range_constructor2(PG_FUNCTION_ARGS)
     384              : {
     385        74848 :     Datum       arg1 = PG_GETARG_DATUM(0);
     386        74848 :     Datum       arg2 = PG_GETARG_DATUM(1);
     387        74848 :     Oid         rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
     388              :     RangeType  *range;
     389              :     TypeCacheEntry *typcache;
     390              :     RangeBound  lower;
     391              :     RangeBound  upper;
     392              : 
     393        74848 :     typcache = range_get_typcache(fcinfo, rngtypid);
     394              : 
     395        74848 :     lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
     396        74848 :     lower.infinite = PG_ARGISNULL(0);
     397        74848 :     lower.inclusive = true;
     398        74848 :     lower.lower = true;
     399              : 
     400        74848 :     upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
     401        74848 :     upper.infinite = PG_ARGISNULL(1);
     402        74848 :     upper.inclusive = false;
     403        74848 :     upper.lower = false;
     404              : 
     405        74848 :     range = make_range(typcache, &lower, &upper, false, NULL);
     406              : 
     407        74824 :     PG_RETURN_RANGE_P(range);
     408              : }
     409              : 
     410              : /* Construct general range value from three arguments */
     411              : Datum
     412         3540 : range_constructor3(PG_FUNCTION_ARGS)
     413              : {
     414         3540 :     Datum       arg1 = PG_GETARG_DATUM(0);
     415         3540 :     Datum       arg2 = PG_GETARG_DATUM(1);
     416         3540 :     Oid         rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
     417              :     RangeType  *range;
     418              :     TypeCacheEntry *typcache;
     419              :     RangeBound  lower;
     420              :     RangeBound  upper;
     421              :     char        flags;
     422              : 
     423         3540 :     typcache = range_get_typcache(fcinfo, rngtypid);
     424              : 
     425         3540 :     if (PG_ARGISNULL(2))
     426            0 :         ereport(ERROR,
     427              :                 (errcode(ERRCODE_DATA_EXCEPTION),
     428              :                  errmsg("range constructor flags argument must not be null")));
     429              : 
     430         3540 :     flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
     431              : 
     432         3540 :     lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
     433         3540 :     lower.infinite = PG_ARGISNULL(0);
     434         3540 :     lower.inclusive = (flags & RANGE_LB_INC) != 0;
     435         3540 :     lower.lower = true;
     436              : 
     437         3540 :     upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
     438         3540 :     upper.infinite = PG_ARGISNULL(1);
     439         3540 :     upper.inclusive = (flags & RANGE_UB_INC) != 0;
     440         3540 :     upper.lower = false;
     441              : 
     442         3540 :     range = make_range(typcache, &lower, &upper, false, NULL);
     443              : 
     444         3540 :     PG_RETURN_RANGE_P(range);
     445              : }
     446              : 
     447              : 
     448              : /* range -> subtype functions */
     449              : 
     450              : /* extract lower bound value */
     451              : Datum
     452          288 : range_lower(PG_FUNCTION_ARGS)
     453              : {
     454          288 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     455              :     TypeCacheEntry *typcache;
     456              :     RangeBound  lower;
     457              :     RangeBound  upper;
     458              :     bool        empty;
     459              : 
     460          288 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     461              : 
     462          288 :     range_deserialize(typcache, r1, &lower, &upper, &empty);
     463              : 
     464              :     /* Return NULL if there's no finite lower bound */
     465          288 :     if (empty || lower.infinite)
     466           24 :         PG_RETURN_NULL();
     467              : 
     468          264 :     PG_RETURN_DATUM(lower.val);
     469              : }
     470              : 
     471              : /* extract upper bound value */
     472              : Datum
     473          168 : range_upper(PG_FUNCTION_ARGS)
     474              : {
     475          168 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     476              :     TypeCacheEntry *typcache;
     477              :     RangeBound  lower;
     478              :     RangeBound  upper;
     479              :     bool        empty;
     480              : 
     481          168 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     482              : 
     483          168 :     range_deserialize(typcache, r1, &lower, &upper, &empty);
     484              : 
     485              :     /* Return NULL if there's no finite upper bound */
     486          168 :     if (empty || upper.infinite)
     487           24 :         PG_RETURN_NULL();
     488              : 
     489          144 :     PG_RETURN_DATUM(upper.val);
     490              : }
     491              : 
     492              : 
     493              : /* range -> bool functions */
     494              : 
     495              : /* is range empty? */
     496              : Datum
     497         1464 : range_empty(PG_FUNCTION_ARGS)
     498              : {
     499         1464 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     500         1464 :     char        flags = range_get_flags(r1);
     501              : 
     502         1464 :     PG_RETURN_BOOL(flags & RANGE_EMPTY);
     503              : }
     504              : 
     505              : /* is lower bound inclusive? */
     506              : Datum
     507           48 : range_lower_inc(PG_FUNCTION_ARGS)
     508              : {
     509           48 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     510           48 :     char        flags = range_get_flags(r1);
     511              : 
     512           48 :     PG_RETURN_BOOL(flags & RANGE_LB_INC);
     513              : }
     514              : 
     515              : /* is upper bound inclusive? */
     516              : Datum
     517           48 : range_upper_inc(PG_FUNCTION_ARGS)
     518              : {
     519           48 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     520           48 :     char        flags = range_get_flags(r1);
     521              : 
     522           48 :     PG_RETURN_BOOL(flags & RANGE_UB_INC);
     523              : }
     524              : 
     525              : /* is lower bound infinite? */
     526              : Datum
     527           48 : range_lower_inf(PG_FUNCTION_ARGS)
     528              : {
     529           48 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     530           48 :     char        flags = range_get_flags(r1);
     531              : 
     532           48 :     PG_RETURN_BOOL(flags & RANGE_LB_INF);
     533              : }
     534              : 
     535              : /* is upper bound infinite? */
     536              : Datum
     537           48 : range_upper_inf(PG_FUNCTION_ARGS)
     538              : {
     539           48 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     540           48 :     char        flags = range_get_flags(r1);
     541              : 
     542           48 :     PG_RETURN_BOOL(flags & RANGE_UB_INF);
     543              : }
     544              : 
     545              : 
     546              : /* range, element -> bool functions */
     547              : 
     548              : /* contains? */
     549              : Datum
     550        50805 : range_contains_elem(PG_FUNCTION_ARGS)
     551              : {
     552        50805 :     RangeType  *r = PG_GETARG_RANGE_P(0);
     553        50805 :     Datum       val = PG_GETARG_DATUM(1);
     554              :     TypeCacheEntry *typcache;
     555              : 
     556        50805 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
     557              : 
     558        50805 :     PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
     559              : }
     560              : 
     561              : /* contained by? */
     562              : Datum
     563           58 : elem_contained_by_range(PG_FUNCTION_ARGS)
     564              : {
     565           58 :     Datum       val = PG_GETARG_DATUM(0);
     566           58 :     RangeType  *r = PG_GETARG_RANGE_P(1);
     567              :     TypeCacheEntry *typcache;
     568              : 
     569           58 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
     570              : 
     571           58 :     PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
     572              : }
     573              : 
     574              : 
     575              : /* range, range -> bool functions */
     576              : 
     577              : /* equality (internal version) */
     578              : bool
     579       106157 : range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     580              : {
     581              :     RangeBound  lower1,
     582              :                 lower2;
     583              :     RangeBound  upper1,
     584              :                 upper2;
     585              :     bool        empty1,
     586              :                 empty2;
     587              : 
     588              :     /* Different types should be prevented by ANYRANGE matching rules */
     589       106157 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     590            0 :         elog(ERROR, "range types do not match");
     591              : 
     592       106157 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     593       106157 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     594              : 
     595       106157 :     if (empty1 && empty2)
     596         5044 :         return true;
     597       101113 :     if (empty1 != empty2)
     598         9008 :         return false;
     599              : 
     600        92105 :     if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
     601        54095 :         return false;
     602              : 
     603        38010 :     if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
     604        22271 :         return false;
     605              : 
     606        15739 :     return true;
     607              : }
     608              : 
     609              : /* equality */
     610              : Datum
     611        52813 : range_eq(PG_FUNCTION_ARGS)
     612              : {
     613        52813 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     614        52813 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     615              :     TypeCacheEntry *typcache;
     616              : 
     617        52813 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     618              : 
     619        52813 :     PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
     620              : }
     621              : 
     622              : /* inequality (internal version) */
     623              : bool
     624            0 : range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     625              : {
     626            0 :     return (!range_eq_internal(typcache, r1, r2));
     627              : }
     628              : 
     629              : /* inequality */
     630              : Datum
     631            0 : range_ne(PG_FUNCTION_ARGS)
     632              : {
     633            0 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     634            0 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     635              :     TypeCacheEntry *typcache;
     636              : 
     637            0 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     638              : 
     639            0 :     PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
     640              : }
     641              : 
     642              : /* contains? */
     643              : Datum
     644       102980 : range_contains(PG_FUNCTION_ARGS)
     645              : {
     646       102980 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     647       102980 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     648              :     TypeCacheEntry *typcache;
     649              : 
     650       102980 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     651              : 
     652       102980 :     PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
     653              : }
     654              : 
     655              : /* contained by? */
     656              : Datum
     657        51290 : range_contained_by(PG_FUNCTION_ARGS)
     658              : {
     659        51290 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     660        51290 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     661              :     TypeCacheEntry *typcache;
     662              : 
     663        51290 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     664              : 
     665        51290 :     PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
     666              : }
     667              : 
     668              : /* strictly left of? (internal version) */
     669              : bool
     670        82505 : range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     671              : {
     672              :     RangeBound  lower1,
     673              :                 lower2;
     674              :     RangeBound  upper1,
     675              :                 upper2;
     676              :     bool        empty1,
     677              :                 empty2;
     678              : 
     679              :     /* Different types should be prevented by ANYRANGE matching rules */
     680        82505 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     681            0 :         elog(ERROR, "range types do not match");
     682              : 
     683        82505 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     684        82505 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     685              : 
     686              :     /* An empty range is neither before nor after any other range */
     687        82505 :     if (empty1 || empty2)
     688         9940 :         return false;
     689              : 
     690        72565 :     return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
     691              : }
     692              : 
     693              : /* strictly left of? */
     694              : Datum
     695        52615 : range_before(PG_FUNCTION_ARGS)
     696              : {
     697        52615 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     698        52615 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     699              :     TypeCacheEntry *typcache;
     700              : 
     701        52615 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     702              : 
     703        52615 :     PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
     704              : }
     705              : 
     706              : /* strictly right of? (internal version) */
     707              : bool
     708       132161 : range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     709              : {
     710              :     RangeBound  lower1,
     711              :                 lower2;
     712              :     RangeBound  upper1,
     713              :                 upper2;
     714              :     bool        empty1,
     715              :                 empty2;
     716              : 
     717              :     /* Different types should be prevented by ANYRANGE matching rules */
     718       132161 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     719            0 :         elog(ERROR, "range types do not match");
     720              : 
     721       132161 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     722       132161 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     723              : 
     724              :     /* An empty range is neither before nor after any other range */
     725       132161 :     if (empty1 || empty2)
     726         9540 :         return false;
     727              : 
     728       122621 :     return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
     729              : }
     730              : 
     731              : /* strictly right of? */
     732              : Datum
     733        52205 : range_after(PG_FUNCTION_ARGS)
     734              : {
     735        52205 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     736        52205 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     737              :     TypeCacheEntry *typcache;
     738              : 
     739        52205 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     740              : 
     741        52205 :     PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
     742              : }
     743              : 
     744              : /*
     745              :  * Check if two bounds A and B are "adjacent", where A is an upper bound and B
     746              :  * is a lower bound. For the bounds to be adjacent, each subtype value must
     747              :  * satisfy strictly one of the bounds: there are no values which satisfy both
     748              :  * bounds (i.e. less than A and greater than B); and there are no values which
     749              :  * satisfy neither bound (i.e. greater than A and less than B).
     750              :  *
     751              :  * For discrete ranges, we rely on the canonicalization function to see if A..B
     752              :  * normalizes to empty. (If there is no canonicalization function, it's
     753              :  * impossible for such a range to normalize to empty, so we needn't bother to
     754              :  * try.)
     755              :  *
     756              :  * If A == B, the ranges are adjacent only if the bounds have different
     757              :  * inclusive flags (i.e., exactly one of the ranges includes the common
     758              :  * boundary point).
     759              :  *
     760              :  * And if A > B then the ranges are not adjacent in this order.
     761              :  */
     762              : bool
     763       316152 : bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
     764              : {
     765              :     int         cmp;
     766              : 
     767              :     Assert(!boundA.lower && boundB.lower);
     768              : 
     769       316152 :     cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
     770       316152 :     if (cmp < 0)
     771              :     {
     772              :         RangeType  *r;
     773              : 
     774              :         /*
     775              :          * Bounds do not overlap; see if there are points in between.
     776              :          */
     777              : 
     778              :         /* in a continuous subtype, there are assumed to be points between */
     779        97188 :         if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
     780          713 :             return false;
     781              : 
     782              :         /*
     783              :          * The bounds are of a discrete range type; so make a range A..B and
     784              :          * see if it's empty.
     785              :          */
     786              : 
     787              :         /* flip the inclusion flags */
     788        96475 :         boundA.inclusive = !boundA.inclusive;
     789        96475 :         boundB.inclusive = !boundB.inclusive;
     790              :         /* change upper/lower labels to avoid Assert failures */
     791        96475 :         boundA.lower = true;
     792        96475 :         boundB.lower = false;
     793        96475 :         r = make_range(typcache, &boundA, &boundB, false, NULL);
     794        96475 :         return RangeIsEmpty(r);
     795              :     }
     796       218964 :     else if (cmp == 0)
     797         1276 :         return boundA.inclusive != boundB.inclusive;
     798              :     else
     799       217688 :         return false;           /* bounds overlap */
     800              : }
     801              : 
     802              : /* adjacent to (but not overlapping)? (internal version) */
     803              : bool
     804        95767 : range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     805              : {
     806              :     RangeBound  lower1,
     807              :                 lower2;
     808              :     RangeBound  upper1,
     809              :                 upper2;
     810              :     bool        empty1,
     811              :                 empty2;
     812              : 
     813              :     /* Different types should be prevented by ANYRANGE matching rules */
     814        95767 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     815            0 :         elog(ERROR, "range types do not match");
     816              : 
     817        95767 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     818        95767 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     819              : 
     820              :     /* An empty range is not adjacent to any other range */
     821        95767 :     if (empty1 || empty2)
     822         8000 :         return false;
     823              : 
     824              :     /*
     825              :      * Given two ranges A..B and C..D, the ranges are adjacent if and only if
     826              :      * B is adjacent to C, or D is adjacent to A.
     827              :      */
     828       174521 :     return (bounds_adjacent(typcache, upper1, lower2) ||
     829        86754 :             bounds_adjacent(typcache, upper2, lower1));
     830              : }
     831              : 
     832              : /* adjacent to (but not overlapping)? */
     833              : Datum
     834        49630 : range_adjacent(PG_FUNCTION_ARGS)
     835              : {
     836        49630 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     837        49630 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     838              :     TypeCacheEntry *typcache;
     839              : 
     840        49630 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     841              : 
     842        49630 :     PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
     843              : }
     844              : 
     845              : /* overlaps? (internal version) */
     846              : bool
     847        66857 : range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     848              : {
     849              :     RangeBound  lower1,
     850              :                 lower2;
     851              :     RangeBound  upper1,
     852              :                 upper2;
     853              :     bool        empty1,
     854              :                 empty2;
     855              : 
     856              :     /* Different types should be prevented by ANYRANGE matching rules */
     857        66857 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     858            0 :         elog(ERROR, "range types do not match");
     859              : 
     860        66857 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     861        66857 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     862              : 
     863              :     /* An empty range does not overlap any other range */
     864        66857 :     if (empty1 || empty2)
     865         9560 :         return false;
     866              : 
     867       109455 :     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
     868        52158 :         range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
     869         4114 :         return true;
     870              : 
     871        58322 :     if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
     872         5139 :         range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
     873         4196 :         return true;
     874              : 
     875        48987 :     return false;
     876              : }
     877              : 
     878              : /* overlaps? */
     879              : Datum
     880        52016 : range_overlaps(PG_FUNCTION_ARGS)
     881              : {
     882        52016 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     883        52016 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     884              :     TypeCacheEntry *typcache;
     885              : 
     886        52016 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     887              : 
     888        52016 :     PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
     889              : }
     890              : 
     891              : /* does not extend to right of? (internal version) */
     892              : bool
     893        87786 : range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     894              : {
     895              :     RangeBound  lower1,
     896              :                 lower2;
     897              :     RangeBound  upper1,
     898              :                 upper2;
     899              :     bool        empty1,
     900              :                 empty2;
     901              : 
     902              :     /* Different types should be prevented by ANYRANGE matching rules */
     903        87786 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     904            0 :         elog(ERROR, "range types do not match");
     905              : 
     906        87786 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     907        87786 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     908              : 
     909              :     /* An empty range is neither before nor after any other range */
     910        87786 :     if (empty1 || empty2)
     911         8764 :         return false;
     912              : 
     913        79022 :     if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
     914        27095 :         return true;
     915              : 
     916        51927 :     return false;
     917              : }
     918              : 
     919              : /* does not extend to right of? */
     920              : Datum
     921        51005 : range_overleft(PG_FUNCTION_ARGS)
     922              : {
     923        51005 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     924        51005 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     925              :     TypeCacheEntry *typcache;
     926              : 
     927        51005 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     928              : 
     929        51005 :     PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
     930              : }
     931              : 
     932              : /* does not extend to left of? (internal version) */
     933              : bool
     934       145343 : range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     935              : {
     936              :     RangeBound  lower1,
     937              :                 lower2;
     938              :     RangeBound  upper1,
     939              :                 upper2;
     940              :     bool        empty1,
     941              :                 empty2;
     942              : 
     943              :     /* Different types should be prevented by ANYRANGE matching rules */
     944       145343 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     945            0 :         elog(ERROR, "range types do not match");
     946              : 
     947       145343 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     948       145343 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     949              : 
     950              :     /* An empty range is neither before nor after any other range */
     951       145343 :     if (empty1 || empty2)
     952         8764 :         return false;
     953              : 
     954       136579 :     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
     955       127301 :         return true;
     956              : 
     957         9278 :     return false;
     958              : }
     959              : 
     960              : /* does not extend to left of? */
     961              : Datum
     962        51000 : range_overright(PG_FUNCTION_ARGS)
     963              : {
     964        51000 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     965        51000 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     966              :     TypeCacheEntry *typcache;
     967              : 
     968        51000 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     969              : 
     970        51000 :     PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
     971              : }
     972              : 
     973              : 
     974              : /* range, range -> range functions */
     975              : 
     976              : /* set difference */
     977              : Datum
     978           25 : range_minus(PG_FUNCTION_ARGS)
     979              : {
     980           25 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     981           25 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     982              :     RangeType  *ret;
     983              :     TypeCacheEntry *typcache;
     984              : 
     985              :     /* Different types should be prevented by ANYRANGE matching rules */
     986           25 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     987            0 :         elog(ERROR, "range types do not match");
     988              : 
     989           25 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     990              : 
     991           25 :     ret = range_minus_internal(typcache, r1, r2);
     992           25 :     if (ret)
     993           25 :         PG_RETURN_RANGE_P(ret);
     994              :     else
     995            0 :         PG_RETURN_NULL();
     996              : }
     997              : 
     998              : RangeType *
     999          124 : range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
    1000              : {
    1001              :     RangeBound  lower1,
    1002              :                 lower2;
    1003              :     RangeBound  upper1,
    1004              :                 upper2;
    1005              :     bool        empty1,
    1006              :                 empty2;
    1007              :     int         cmp_l1l2,
    1008              :                 cmp_l1u2,
    1009              :                 cmp_u1l2,
    1010              :                 cmp_u1u2;
    1011              : 
    1012          124 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1013          124 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1014              : 
    1015              :     /* if either is empty, r1 is the correct answer */
    1016          124 :     if (empty1 || empty2)
    1017            0 :         return r1;
    1018              : 
    1019          124 :     cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
    1020          124 :     cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
    1021          124 :     cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
    1022          124 :     cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
    1023              : 
    1024          124 :     if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
    1025            0 :         ereport(ERROR,
    1026              :                 (errcode(ERRCODE_DATA_EXCEPTION),
    1027              :                  errmsg("result of range difference would not be contiguous")));
    1028              : 
    1029          124 :     if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
    1030           10 :         return r1;
    1031              : 
    1032          114 :     if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
    1033           59 :         return make_empty_range(typcache);
    1034              : 
    1035           55 :     if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
    1036              :     {
    1037           28 :         lower2.inclusive = !lower2.inclusive;
    1038           28 :         lower2.lower = false;   /* it will become the upper bound */
    1039           28 :         return make_range(typcache, &lower1, &lower2, false, NULL);
    1040              :     }
    1041              : 
    1042           27 :     if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
    1043              :     {
    1044           27 :         upper2.inclusive = !upper2.inclusive;
    1045           27 :         upper2.lower = true;    /* it will become the lower bound */
    1046           27 :         return make_range(typcache, &upper2, &upper1, false, NULL);
    1047              :     }
    1048              : 
    1049            0 :     elog(ERROR, "unexpected case in range_minus");
    1050              :     return NULL;
    1051              : }
    1052              : 
    1053              : /*
    1054              :  * Set union.  If strict is true, it is an error that the two input ranges
    1055              :  * are not adjacent or overlapping.
    1056              :  */
    1057              : RangeType *
    1058         1086 : range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
    1059              :                      bool strict)
    1060              : {
    1061              :     RangeBound  lower1,
    1062              :                 lower2;
    1063              :     RangeBound  upper1,
    1064              :                 upper2;
    1065              :     bool        empty1,
    1066              :                 empty2;
    1067              :     RangeBound *result_lower;
    1068              :     RangeBound *result_upper;
    1069              : 
    1070              :     /* Different types should be prevented by ANYRANGE matching rules */
    1071         1086 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1072            0 :         elog(ERROR, "range types do not match");
    1073              : 
    1074         1086 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1075         1086 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1076              : 
    1077              :     /* if either is empty, the other is the correct answer */
    1078         1086 :     if (empty1)
    1079            4 :         return r2;
    1080         1082 :     if (empty2)
    1081            0 :         return r1;
    1082              : 
    1083         1082 :     if (strict &&
    1084          122 :         !range_overlaps_internal(typcache, r1, r2) &&
    1085            9 :         !range_adjacent_internal(typcache, r1, r2))
    1086            4 :         ereport(ERROR,
    1087              :                 (errcode(ERRCODE_DATA_EXCEPTION),
    1088              :                  errmsg("result of range union would not be contiguous")));
    1089              : 
    1090         1078 :     if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
    1091         1052 :         result_lower = &lower1;
    1092              :     else
    1093           26 :         result_lower = &lower2;
    1094              : 
    1095         1078 :     if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
    1096           34 :         result_upper = &upper1;
    1097              :     else
    1098         1044 :         result_upper = &upper2;
    1099              : 
    1100         1078 :     return make_range(typcache, result_lower, result_upper, false, NULL);
    1101              : }
    1102              : 
    1103              : Datum
    1104           38 : range_union(PG_FUNCTION_ARGS)
    1105              : {
    1106           38 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1107           38 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1108              :     TypeCacheEntry *typcache;
    1109              : 
    1110           38 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1111              : 
    1112           38 :     PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
    1113              : }
    1114              : 
    1115              : /*
    1116              :  * range merge: like set union, except also allow and account for non-adjacent
    1117              :  * input ranges.
    1118              :  */
    1119              : Datum
    1120           23 : range_merge(PG_FUNCTION_ARGS)
    1121              : {
    1122           23 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1123           23 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1124              :     TypeCacheEntry *typcache;
    1125              : 
    1126           23 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1127              : 
    1128           23 :     PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
    1129              : }
    1130              : 
    1131              : /* set intersection */
    1132              : Datum
    1133         1294 : range_intersect(PG_FUNCTION_ARGS)
    1134              : {
    1135         1294 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1136         1294 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1137              :     TypeCacheEntry *typcache;
    1138              : 
    1139              :     /* Different types should be prevented by ANYRANGE matching rules */
    1140         1294 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1141            0 :         elog(ERROR, "range types do not match");
    1142              : 
    1143         1294 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1144              : 
    1145         1294 :     PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
    1146              : }
    1147              : 
    1148              : RangeType *
    1149         1514 : range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
    1150              : {
    1151              :     RangeBound  lower1,
    1152              :                 lower2;
    1153              :     RangeBound  upper1,
    1154              :                 upper2;
    1155              :     bool        empty1,
    1156              :                 empty2;
    1157              :     RangeBound *result_lower;
    1158              :     RangeBound *result_upper;
    1159              : 
    1160         1514 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1161         1514 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1162              : 
    1163         1514 :     if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
    1164          502 :         return make_empty_range(typcache);
    1165              : 
    1166         1012 :     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
    1167          820 :         result_lower = &lower1;
    1168              :     else
    1169          192 :         result_lower = &lower2;
    1170              : 
    1171         1012 :     if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
    1172          939 :         result_upper = &upper1;
    1173              :     else
    1174           73 :         result_upper = &upper2;
    1175              : 
    1176         1012 :     return make_range(typcache, result_lower, result_upper, false, NULL);
    1177              : }
    1178              : 
    1179              : /* range, range -> range, range functions */
    1180              : 
    1181              : /*
    1182              :  * range_split_internal - if r2 intersects the middle of r1, leaving non-empty
    1183              :  * ranges on both sides, then return true and set output1 and output2 to the
    1184              :  * results of r1 - r2 (in order). Otherwise return false and don't set output1
    1185              :  * or output2. Neither input range should be empty.
    1186              :  */
    1187              : bool
    1188          198 : range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2,
    1189              :                      RangeType **output1, RangeType **output2)
    1190              : {
    1191              :     RangeBound  lower1,
    1192              :                 lower2;
    1193              :     RangeBound  upper1,
    1194              :                 upper2;
    1195              :     bool        empty1,
    1196              :                 empty2;
    1197              : 
    1198          198 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1199          198 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1200              : 
    1201          315 :     if (range_cmp_bounds(typcache, &lower1, &lower2) < 0 &&
    1202          117 :         range_cmp_bounds(typcache, &upper1, &upper2) > 0)
    1203              :     {
    1204              :         /*
    1205              :          * Need to invert inclusive/exclusive for the lower2 and upper2
    1206              :          * points. They can't be infinite though. We're allowed to overwrite
    1207              :          * these RangeBounds since they only exist locally.
    1208              :          */
    1209           27 :         lower2.inclusive = !lower2.inclusive;
    1210           27 :         lower2.lower = false;
    1211           27 :         upper2.inclusive = !upper2.inclusive;
    1212           27 :         upper2.lower = true;
    1213              : 
    1214           27 :         *output1 = make_range(typcache, &lower1, &lower2, false, NULL);
    1215           27 :         *output2 = make_range(typcache, &upper2, &upper1, false, NULL);
    1216           27 :         return true;
    1217              :     }
    1218              : 
    1219          171 :     return false;
    1220              : }
    1221              : 
    1222              : /*
    1223              :  * range_minus_multi - like range_minus but as a SRF to accommodate splits,
    1224              :  * with no result rows if the result would be empty.
    1225              :  */
    1226              : Datum
    1227           72 : range_minus_multi(PG_FUNCTION_ARGS)
    1228              : {
    1229              :     struct range_minus_multi_fctx
    1230              :     {
    1231              :         RangeType  *rs[2];
    1232              :         int         n;
    1233              :     };
    1234              : 
    1235              :     FuncCallContext *funcctx;
    1236              :     struct range_minus_multi_fctx *fctx;
    1237              :     MemoryContext oldcontext;
    1238              : 
    1239              :     /* stuff done only on the first call of the function */
    1240           72 :     if (SRF_IS_FIRSTCALL())
    1241              :     {
    1242              :         RangeType  *r1;
    1243              :         RangeType  *r2;
    1244              :         Oid         rngtypid;
    1245              :         TypeCacheEntry *typcache;
    1246              : 
    1247              :         /* create a function context for cross-call persistence */
    1248           36 :         funcctx = SRF_FIRSTCALL_INIT();
    1249              : 
    1250              :         /*
    1251              :          * switch to memory context appropriate for multiple function calls
    1252              :          */
    1253           36 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1254              : 
    1255           36 :         r1 = PG_GETARG_RANGE_P(0);
    1256           36 :         r2 = PG_GETARG_RANGE_P(1);
    1257              : 
    1258              :         /* Different types should be prevented by ANYRANGE matching rules */
    1259           36 :         if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1260            0 :             elog(ERROR, "range types do not match");
    1261              : 
    1262              :         /* allocate memory for user context */
    1263           36 :         fctx = palloc_object(struct range_minus_multi_fctx);
    1264              : 
    1265              :         /*
    1266              :          * Initialize state. We can't store the range typcache in fn_extra
    1267              :          * because the caller uses that for the SRF state.
    1268              :          */
    1269           36 :         rngtypid = RangeTypeGetOid(r1);
    1270           36 :         typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
    1271           36 :         if (typcache->rngelemtype == NULL)
    1272            0 :             elog(ERROR, "type %u is not a range type", rngtypid);
    1273           36 :         range_minus_multi_internal(typcache, r1, r2, fctx->rs, &fctx->n);
    1274              : 
    1275           36 :         funcctx->user_fctx = fctx;
    1276           36 :         MemoryContextSwitchTo(oldcontext);
    1277              :     }
    1278              : 
    1279              :     /* stuff done on every call of the function */
    1280           72 :     funcctx = SRF_PERCALL_SETUP();
    1281           72 :     fctx = funcctx->user_fctx;
    1282              : 
    1283           72 :     if (funcctx->call_cntr < fctx->n)
    1284              :     {
    1285              :         /*
    1286              :          * We must keep these on separate lines because SRF_RETURN_NEXT does
    1287              :          * call_cntr++:
    1288              :          */
    1289           36 :         RangeType  *ret = fctx->rs[funcctx->call_cntr];
    1290              : 
    1291           36 :         SRF_RETURN_NEXT(funcctx, RangeTypePGetDatum(ret));
    1292              :     }
    1293              :     else
    1294              :         /* do when there is no more left */
    1295           36 :         SRF_RETURN_DONE(funcctx);
    1296              : }
    1297              : 
    1298              : /*
    1299              :  * range_minus_multi_internal - Subtracts r2 from r1
    1300              :  *
    1301              :  * The subtraction can produce zero, one, or two resulting ranges. We return
    1302              :  * the results by setting outputs and outputn to the ranges remaining and their
    1303              :  * count (respectively). The results will never contain empty ranges and will
    1304              :  * be ordered. Caller should set outputs to a two-element array of RangeType
    1305              :  * pointers.
    1306              :  */
    1307              : void
    1308           36 : range_minus_multi_internal(TypeCacheEntry *typcache, RangeType *r1,
    1309              :                            RangeType *r2, RangeType **outputs, int *outputn)
    1310              : {
    1311              :     int         cmp_l1l2,
    1312              :                 cmp_l1u2,
    1313              :                 cmp_u1l2,
    1314              :                 cmp_u1u2;
    1315              :     RangeBound  lower1,
    1316              :                 lower2;
    1317              :     RangeBound  upper1,
    1318              :                 upper2;
    1319              :     bool        empty1,
    1320              :                 empty2;
    1321              : 
    1322           36 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1323           36 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1324              : 
    1325           36 :     if (empty1)
    1326              :     {
    1327              :         /* if r1 is empty then r1 - r2 is empty, so return zero results */
    1328            4 :         *outputn = 0;
    1329            8 :         return;
    1330              :     }
    1331           32 :     else if (empty2)
    1332              :     {
    1333              :         /* r2 is empty so the result is just r1 (which we know is not empty) */
    1334            4 :         outputs[0] = r1;
    1335            4 :         *outputn = 1;
    1336            4 :         return;
    1337              :     }
    1338              : 
    1339              :     /*
    1340              :      * Use the same logic as range_minus_internal, but support the split case
    1341              :      */
    1342           28 :     cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
    1343           28 :     cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
    1344           28 :     cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
    1345           28 :     cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
    1346              : 
    1347           28 :     if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
    1348              :     {
    1349            8 :         lower2.inclusive = !lower2.inclusive;
    1350            8 :         lower2.lower = false;   /* it will become the upper bound */
    1351            8 :         outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
    1352              : 
    1353            8 :         upper2.inclusive = !upper2.inclusive;
    1354            8 :         upper2.lower = true;    /* it will become the lower bound */
    1355            8 :         outputs[1] = make_range(typcache, &upper2, &upper1, false, NULL);
    1356              : 
    1357            8 :         *outputn = 2;
    1358              :     }
    1359           20 :     else if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
    1360              :     {
    1361            8 :         outputs[0] = r1;
    1362            8 :         *outputn = 1;
    1363              :     }
    1364           12 :     else if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
    1365              :     {
    1366            4 :         *outputn = 0;
    1367              :     }
    1368            8 :     else if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
    1369              :     {
    1370            8 :         lower2.inclusive = !lower2.inclusive;
    1371            8 :         lower2.lower = false;   /* it will become the upper bound */
    1372            8 :         outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
    1373            8 :         *outputn = 1;
    1374              :     }
    1375            0 :     else if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
    1376              :     {
    1377            0 :         upper2.inclusive = !upper2.inclusive;
    1378            0 :         upper2.lower = true;    /* it will become the lower bound */
    1379            0 :         outputs[0] = make_range(typcache, &upper2, &upper1, false, NULL);
    1380            0 :         *outputn = 1;
    1381              :     }
    1382              :     else
    1383              :     {
    1384            0 :         elog(ERROR, "unexpected case in range_minus_multi");
    1385              :     }
    1386              : }
    1387              : 
    1388              : /* range -> range aggregate functions */
    1389              : 
    1390              : Datum
    1391           28 : range_intersect_agg_transfn(PG_FUNCTION_ARGS)
    1392              : {
    1393              :     MemoryContext aggContext;
    1394              :     Oid         rngtypoid;
    1395              :     TypeCacheEntry *typcache;
    1396              :     RangeType  *result;
    1397              :     RangeType  *current;
    1398              : 
    1399           28 :     if (!AggCheckCallContext(fcinfo, &aggContext))
    1400            0 :         elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
    1401              : 
    1402           28 :     rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
    1403           28 :     if (!type_is_range(rngtypoid))
    1404            0 :         elog(ERROR, "range_intersect_agg must be called with a range");
    1405              : 
    1406           28 :     typcache = range_get_typcache(fcinfo, rngtypoid);
    1407              : 
    1408              :     /* strictness ensures these are non-null */
    1409           28 :     result = PG_GETARG_RANGE_P(0);
    1410           28 :     current = PG_GETARG_RANGE_P(1);
    1411              : 
    1412           28 :     result = range_intersect_internal(typcache, result, current);
    1413           28 :     PG_RETURN_RANGE_P(result);
    1414              : }
    1415              : 
    1416              : 
    1417              : /* Btree support */
    1418              : 
    1419              : /* btree comparator */
    1420              : Datum
    1421        12574 : range_cmp(PG_FUNCTION_ARGS)
    1422              : {
    1423        12574 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1424        12574 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1425              :     TypeCacheEntry *typcache;
    1426              :     RangeBound  lower1,
    1427              :                 lower2;
    1428              :     RangeBound  upper1,
    1429              :                 upper2;
    1430              :     bool        empty1,
    1431              :                 empty2;
    1432              :     int         cmp;
    1433              : 
    1434        12574 :     check_stack_depth();        /* recurses when subtype is a range type */
    1435              : 
    1436              :     /* Different types should be prevented by ANYRANGE matching rules */
    1437        12574 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1438            0 :         elog(ERROR, "range types do not match");
    1439              : 
    1440        12574 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1441              : 
    1442        12574 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1443        12574 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1444              : 
    1445              :     /* For b-tree use, empty ranges sort before all else */
    1446        12574 :     if (empty1 && empty2)
    1447         1756 :         cmp = 0;
    1448        10818 :     else if (empty1)
    1449         2316 :         cmp = -1;
    1450         8502 :     else if (empty2)
    1451         1361 :         cmp = 1;
    1452              :     else
    1453              :     {
    1454         7141 :         cmp = range_cmp_bounds(typcache, &lower1, &lower2);
    1455         7141 :         if (cmp == 0)
    1456          390 :             cmp = range_cmp_bounds(typcache, &upper1, &upper2);
    1457              :     }
    1458              : 
    1459        12574 :     PG_FREE_IF_COPY(r1, 0);
    1460        12574 :     PG_FREE_IF_COPY(r2, 1);
    1461              : 
    1462        12574 :     PG_RETURN_INT32(cmp);
    1463              : }
    1464              : 
    1465              : /* Sort support strategy routine */
    1466              : Datum
    1467         1159 : range_sortsupport(PG_FUNCTION_ARGS)
    1468              : {
    1469         1159 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
    1470              : 
    1471         1159 :     ssup->comparator = range_fast_cmp;
    1472         1159 :     ssup->ssup_extra = NULL;
    1473              : 
    1474         1159 :     PG_RETURN_VOID();
    1475              : }
    1476              : 
    1477              : /* like range_cmp, but uses the new sortsupport interface */
    1478              : static int
    1479       373433 : range_fast_cmp(Datum a, Datum b, SortSupport ssup)
    1480              : {
    1481       373433 :     RangeType  *range_a = DatumGetRangeTypeP(a);
    1482       373433 :     RangeType  *range_b = DatumGetRangeTypeP(b);
    1483              :     TypeCacheEntry *typcache;
    1484              :     RangeBound  lower1,
    1485              :                 lower2;
    1486              :     RangeBound  upper1,
    1487              :                 upper2;
    1488              :     bool        empty1,
    1489              :                 empty2;
    1490              :     int         cmp;
    1491              : 
    1492              :     /* cache the range info between calls */
    1493       373433 :     if (ssup->ssup_extra == NULL)
    1494              :     {
    1495              :         Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b));
    1496          285 :         ssup->ssup_extra =
    1497          285 :             lookup_type_cache(RangeTypeGetOid(range_a), TYPECACHE_RANGE_INFO);
    1498              :     }
    1499       373433 :     typcache = ssup->ssup_extra;
    1500              : 
    1501       373433 :     range_deserialize(typcache, range_a, &lower1, &upper1, &empty1);
    1502       373433 :     range_deserialize(typcache, range_b, &lower2, &upper2, &empty2);
    1503              : 
    1504              :     /* For b-tree use, empty ranges sort before all else */
    1505       373433 :     if (empty1 && empty2)
    1506        52724 :         cmp = 0;
    1507       320709 :     else if (empty1)
    1508        13564 :         cmp = -1;
    1509       307145 :     else if (empty2)
    1510         1804 :         cmp = 1;
    1511              :     else
    1512              :     {
    1513       305341 :         cmp = range_cmp_bounds(typcache, &lower1, &lower2);
    1514       305341 :         if (cmp == 0)
    1515        22672 :             cmp = range_cmp_bounds(typcache, &upper1, &upper2);
    1516              :     }
    1517              : 
    1518       373433 :     if (range_a != DatumGetPointer(a))
    1519       360461 :         pfree(range_a);
    1520       373433 :     if (range_b != DatumGetPointer(b))
    1521       360461 :         pfree(range_b);
    1522              : 
    1523       373433 :     return cmp;
    1524              : }
    1525              : 
    1526              : 
    1527              : /* inequality operators using the range_cmp function */
    1528              : Datum
    1529          894 : range_lt(PG_FUNCTION_ARGS)
    1530              : {
    1531          894 :     int         cmp = DatumGetInt32(range_cmp(fcinfo));
    1532              : 
    1533          894 :     PG_RETURN_BOOL(cmp < 0);
    1534              : }
    1535              : 
    1536              : Datum
    1537         2008 : range_le(PG_FUNCTION_ARGS)
    1538              : {
    1539         2008 :     int         cmp = DatumGetInt32(range_cmp(fcinfo));
    1540              : 
    1541         2008 :     PG_RETURN_BOOL(cmp <= 0);
    1542              : }
    1543              : 
    1544              : Datum
    1545         2024 : range_ge(PG_FUNCTION_ARGS)
    1546              : {
    1547         2024 :     int         cmp = DatumGetInt32(range_cmp(fcinfo));
    1548              : 
    1549         2024 :     PG_RETURN_BOOL(cmp >= 0);
    1550              : }
    1551              : 
    1552              : Datum
    1553         2048 : range_gt(PG_FUNCTION_ARGS)
    1554              : {
    1555         2048 :     int         cmp = DatumGetInt32(range_cmp(fcinfo));
    1556              : 
    1557         2048 :     PG_RETURN_BOOL(cmp > 0);
    1558              : }
    1559              : 
    1560              : /* Hash support */
    1561              : 
    1562              : /* hash a range value */
    1563              : Datum
    1564          140 : hash_range(PG_FUNCTION_ARGS)
    1565              : {
    1566          140 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1567              :     uint32      result;
    1568              :     TypeCacheEntry *typcache;
    1569              :     TypeCacheEntry *scache;
    1570              :     RangeBound  lower;
    1571              :     RangeBound  upper;
    1572              :     bool        empty;
    1573              :     char        flags;
    1574              :     uint32      lower_hash;
    1575              :     uint32      upper_hash;
    1576              : 
    1577          140 :     check_stack_depth();        /* recurses when subtype is a range type */
    1578              : 
    1579          140 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1580              : 
    1581              :     /* deserialize */
    1582          140 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1583          140 :     flags = range_get_flags(r);
    1584              : 
    1585              :     /*
    1586              :      * Look up the element type's hash function, if not done already.
    1587              :      */
    1588          140 :     scache = typcache->rngelemtype;
    1589          140 :     if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
    1590              :     {
    1591            4 :         scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
    1592            4 :         if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
    1593            0 :             ereport(ERROR,
    1594              :                     (errcode(ERRCODE_UNDEFINED_FUNCTION),
    1595              :                      errmsg("could not identify a hash function for type %s",
    1596              :                             format_type_be(scache->type_id))));
    1597              :     }
    1598              : 
    1599              :     /*
    1600              :      * Apply the hash function to each bound.
    1601              :      */
    1602          140 :     if (RANGE_HAS_LBOUND(flags))
    1603           96 :         lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
    1604              :                                                       typcache->rng_collation,
    1605              :                                                       lower.val));
    1606              :     else
    1607           44 :         lower_hash = 0;
    1608              : 
    1609          140 :     if (RANGE_HAS_UBOUND(flags))
    1610          104 :         upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
    1611              :                                                       typcache->rng_collation,
    1612              :                                                       upper.val));
    1613              :     else
    1614           36 :         upper_hash = 0;
    1615              : 
    1616              :     /* Merge hashes of flags and bounds */
    1617          140 :     result = hash_bytes_uint32((uint32) flags);
    1618          140 :     result ^= lower_hash;
    1619          140 :     result = pg_rotate_left32(result, 1);
    1620          140 :     result ^= upper_hash;
    1621              : 
    1622          140 :     PG_RETURN_INT32(result);
    1623              : }
    1624              : 
    1625              : /*
    1626              :  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
    1627              :  * Otherwise, similar to hash_range.
    1628              :  */
    1629              : Datum
    1630           40 : hash_range_extended(PG_FUNCTION_ARGS)
    1631              : {
    1632           40 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1633           40 :     Datum       seed = PG_GETARG_DATUM(1);
    1634              :     uint64      result;
    1635              :     TypeCacheEntry *typcache;
    1636              :     TypeCacheEntry *scache;
    1637              :     RangeBound  lower;
    1638              :     RangeBound  upper;
    1639              :     bool        empty;
    1640              :     char        flags;
    1641              :     uint64      lower_hash;
    1642              :     uint64      upper_hash;
    1643              : 
    1644           40 :     check_stack_depth();
    1645              : 
    1646           40 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1647              : 
    1648           40 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1649           40 :     flags = range_get_flags(r);
    1650              : 
    1651           40 :     scache = typcache->rngelemtype;
    1652           40 :     if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
    1653              :     {
    1654            0 :         scache = lookup_type_cache(scache->type_id,
    1655              :                                    TYPECACHE_HASH_EXTENDED_PROC_FINFO);
    1656            0 :         if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
    1657            0 :             ereport(ERROR,
    1658              :                     (errcode(ERRCODE_UNDEFINED_FUNCTION),
    1659              :                      errmsg("could not identify a hash function for type %s",
    1660              :                             format_type_be(scache->type_id))));
    1661              :     }
    1662              : 
    1663           40 :     if (RANGE_HAS_LBOUND(flags))
    1664           40 :         lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
    1665              :                                                       typcache->rng_collation,
    1666              :                                                       lower.val,
    1667              :                                                       seed));
    1668              :     else
    1669            0 :         lower_hash = 0;
    1670              : 
    1671           40 :     if (RANGE_HAS_UBOUND(flags))
    1672           40 :         upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
    1673              :                                                       typcache->rng_collation,
    1674              :                                                       upper.val,
    1675              :                                                       seed));
    1676              :     else
    1677            0 :         upper_hash = 0;
    1678              : 
    1679              :     /* Merge hashes of flags and bounds */
    1680           40 :     result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
    1681           40 :                                                  DatumGetInt64(seed)));
    1682           40 :     result ^= lower_hash;
    1683           40 :     result = ROTATE_HIGH_AND_LOW_32BITS(result);
    1684           40 :     result ^= upper_hash;
    1685              : 
    1686           40 :     PG_RETURN_UINT64(result);
    1687              : }
    1688              : 
    1689              : /*
    1690              :  *----------------------------------------------------------
    1691              :  * CANONICAL FUNCTIONS
    1692              :  *
    1693              :  *   Functions for specific built-in range types.
    1694              :  *----------------------------------------------------------
    1695              :  */
    1696              : 
    1697              : Datum
    1698       298265 : int4range_canonical(PG_FUNCTION_ARGS)
    1699              : {
    1700       298265 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1701       298265 :     Node       *escontext = fcinfo->context;
    1702              :     TypeCacheEntry *typcache;
    1703              :     RangeBound  lower;
    1704              :     RangeBound  upper;
    1705              :     bool        empty;
    1706              : 
    1707       298265 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1708              : 
    1709       298265 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1710              : 
    1711       298265 :     if (empty)
    1712            0 :         PG_RETURN_RANGE_P(r);
    1713              : 
    1714       298265 :     if (!lower.infinite && !lower.inclusive)
    1715              :     {
    1716         2168 :         int32       bnd = DatumGetInt32(lower.val);
    1717              : 
    1718              :         /* Handle possible overflow manually */
    1719         2168 :         if (unlikely(bnd == PG_INT32_MAX))
    1720            0 :             ereturn(escontext, (Datum) 0,
    1721              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1722              :                      errmsg("integer out of range")));
    1723         2168 :         lower.val = Int32GetDatum(bnd + 1);
    1724         2168 :         lower.inclusive = true;
    1725              :     }
    1726              : 
    1727       298265 :     if (!upper.infinite && upper.inclusive)
    1728              :     {
    1729         2175 :         int32       bnd = DatumGetInt32(upper.val);
    1730              : 
    1731              :         /* Handle possible overflow manually */
    1732         2175 :         if (unlikely(bnd == PG_INT32_MAX))
    1733            8 :             ereturn(escontext, (Datum) 0,
    1734              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1735              :                      errmsg("integer out of range")));
    1736         2167 :         upper.val = Int32GetDatum(bnd + 1);
    1737         2167 :         upper.inclusive = false;
    1738              :     }
    1739              : 
    1740       298257 :     PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
    1741              :                                       false, escontext));
    1742              : }
    1743              : 
    1744              : Datum
    1745           63 : int8range_canonical(PG_FUNCTION_ARGS)
    1746              : {
    1747           63 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1748           63 :     Node       *escontext = fcinfo->context;
    1749              :     TypeCacheEntry *typcache;
    1750              :     RangeBound  lower;
    1751              :     RangeBound  upper;
    1752              :     bool        empty;
    1753              : 
    1754           63 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1755              : 
    1756           63 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1757              : 
    1758           63 :     if (empty)
    1759            0 :         PG_RETURN_RANGE_P(r);
    1760              : 
    1761           63 :     if (!lower.infinite && !lower.inclusive)
    1762              :     {
    1763           13 :         int64       bnd = DatumGetInt64(lower.val);
    1764              : 
    1765              :         /* Handle possible overflow manually */
    1766           13 :         if (unlikely(bnd == PG_INT64_MAX))
    1767            0 :             ereturn(escontext, (Datum) 0,
    1768              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1769              :                      errmsg("bigint out of range")));
    1770           13 :         lower.val = Int64GetDatum(bnd + 1);
    1771           13 :         lower.inclusive = true;
    1772              :     }
    1773              : 
    1774           63 :     if (!upper.infinite && upper.inclusive)
    1775              :     {
    1776           14 :         int64       bnd = DatumGetInt64(upper.val);
    1777              : 
    1778              :         /* Handle possible overflow manually */
    1779           14 :         if (unlikely(bnd == PG_INT64_MAX))
    1780            0 :             ereturn(escontext, (Datum) 0,
    1781              :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1782              :                      errmsg("bigint out of range")));
    1783           14 :         upper.val = Int64GetDatum(bnd + 1);
    1784           14 :         upper.inclusive = false;
    1785              :     }
    1786              : 
    1787           63 :     PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
    1788              :                                       false, escontext));
    1789              : }
    1790              : 
    1791              : Datum
    1792         2655 : daterange_canonical(PG_FUNCTION_ARGS)
    1793              : {
    1794         2655 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1795         2655 :     Node       *escontext = fcinfo->context;
    1796              :     TypeCacheEntry *typcache;
    1797              :     RangeBound  lower;
    1798              :     RangeBound  upper;
    1799              :     bool        empty;
    1800              : 
    1801         2655 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1802              : 
    1803         2655 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1804              : 
    1805         2655 :     if (empty)
    1806            0 :         PG_RETURN_RANGE_P(r);
    1807              : 
    1808         2655 :     if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
    1809         2615 :         !lower.inclusive)
    1810              :     {
    1811           28 :         DateADT     bnd = DatumGetDateADT(lower.val);
    1812              : 
    1813              :         /* Check for overflow -- note we already eliminated PG_INT32_MAX */
    1814           28 :         bnd++;
    1815           28 :         if (unlikely(!IS_VALID_DATE(bnd)))
    1816            0 :             ereturn(escontext, (Datum) 0,
    1817              :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1818              :                      errmsg("date out of range")));
    1819           28 :         lower.val = DateADTGetDatum(bnd);
    1820           28 :         lower.inclusive = true;
    1821              :     }
    1822              : 
    1823         2655 :     if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
    1824         2521 :         upper.inclusive)
    1825              :     {
    1826           28 :         DateADT     bnd = DatumGetDateADT(upper.val);
    1827              : 
    1828              :         /* Check for overflow -- note we already eliminated PG_INT32_MAX */
    1829           28 :         bnd++;
    1830           28 :         if (unlikely(!IS_VALID_DATE(bnd)))
    1831            8 :             ereturn(escontext, (Datum) 0,
    1832              :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1833              :                      errmsg("date out of range")));
    1834           20 :         upper.val = DateADTGetDatum(bnd);
    1835           20 :         upper.inclusive = false;
    1836              :     }
    1837              : 
    1838         2647 :     PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
    1839              :                                       false, escontext));
    1840              : }
    1841              : 
    1842              : /*
    1843              :  *----------------------------------------------------------
    1844              :  * SUBTYPE_DIFF FUNCTIONS
    1845              :  *
    1846              :  * Functions for specific built-in range types.
    1847              :  *
    1848              :  * Note that subtype_diff does return the difference, not the absolute value
    1849              :  * of the difference, and it must take care to avoid overflow.
    1850              :  * (numrange_subdiff is at some risk there ...)
    1851              :  *----------------------------------------------------------
    1852              :  */
    1853              : 
    1854              : Datum
    1855       564346 : int4range_subdiff(PG_FUNCTION_ARGS)
    1856              : {
    1857       564346 :     int32       v1 = PG_GETARG_INT32(0);
    1858       564346 :     int32       v2 = PG_GETARG_INT32(1);
    1859              : 
    1860       564346 :     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
    1861              : }
    1862              : 
    1863              : Datum
    1864            0 : int8range_subdiff(PG_FUNCTION_ARGS)
    1865              : {
    1866            0 :     int64       v1 = PG_GETARG_INT64(0);
    1867            0 :     int64       v2 = PG_GETARG_INT64(1);
    1868              : 
    1869            0 :     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
    1870              : }
    1871              : 
    1872              : Datum
    1873          200 : numrange_subdiff(PG_FUNCTION_ARGS)
    1874              : {
    1875          200 :     Datum       v1 = PG_GETARG_DATUM(0);
    1876          200 :     Datum       v2 = PG_GETARG_DATUM(1);
    1877              :     Datum       numresult;
    1878              :     float8      floatresult;
    1879              : 
    1880          200 :     numresult = DirectFunctionCall2(numeric_sub, v1, v2);
    1881              : 
    1882          200 :     floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
    1883              :                                                      numresult));
    1884              : 
    1885          200 :     PG_RETURN_FLOAT8(floatresult);
    1886              : }
    1887              : 
    1888              : Datum
    1889            0 : daterange_subdiff(PG_FUNCTION_ARGS)
    1890              : {
    1891            0 :     int32       v1 = PG_GETARG_INT32(0);
    1892            0 :     int32       v2 = PG_GETARG_INT32(1);
    1893              : 
    1894            0 :     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
    1895              : }
    1896              : 
    1897              : Datum
    1898            0 : tsrange_subdiff(PG_FUNCTION_ARGS)
    1899              : {
    1900            0 :     Timestamp   v1 = PG_GETARG_TIMESTAMP(0);
    1901            0 :     Timestamp   v2 = PG_GETARG_TIMESTAMP(1);
    1902              :     float8      result;
    1903              : 
    1904            0 :     result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
    1905            0 :     PG_RETURN_FLOAT8(result);
    1906              : }
    1907              : 
    1908              : Datum
    1909            0 : tstzrange_subdiff(PG_FUNCTION_ARGS)
    1910              : {
    1911            0 :     Timestamp   v1 = PG_GETARG_TIMESTAMP(0);
    1912            0 :     Timestamp   v2 = PG_GETARG_TIMESTAMP(1);
    1913              :     float8      result;
    1914              : 
    1915            0 :     result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
    1916            0 :     PG_RETURN_FLOAT8(result);
    1917              : }
    1918              : 
    1919              : /*
    1920              :  *----------------------------------------------------------
    1921              :  * SUPPORT FUNCTIONS
    1922              :  *
    1923              :  *   These functions aren't in pg_proc, but are useful for
    1924              :  *   defining new generic range functions in C.
    1925              :  *----------------------------------------------------------
    1926              :  */
    1927              : 
    1928              : /*
    1929              :  * range_get_typcache: get cached information about a range type
    1930              :  *
    1931              :  * This is for use by range-related functions that follow the convention
    1932              :  * of using the fn_extra field as a pointer to the type cache entry for
    1933              :  * the range type.  Functions that need to cache more information than
    1934              :  * that must fend for themselves.
    1935              :  */
    1936              : TypeCacheEntry *
    1937      2756188 : range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
    1938              : {
    1939      2756188 :     TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
    1940              : 
    1941      2756188 :     if (typcache == NULL ||
    1942      2742215 :         typcache->type_id != rngtypid)
    1943              :     {
    1944        13973 :         typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
    1945        13973 :         if (typcache->rngelemtype == NULL)
    1946            0 :             elog(ERROR, "type %u is not a range type", rngtypid);
    1947        13973 :         fcinfo->flinfo->fn_extra = typcache;
    1948              :     }
    1949              : 
    1950      2756188 :     return typcache;
    1951              : }
    1952              : 
    1953              : /*
    1954              :  * range_serialize: construct a range value from bounds and empty-flag
    1955              :  *
    1956              :  * This does not force canonicalization of the range value.  In most cases,
    1957              :  * external callers should only be canonicalization functions.  Note that
    1958              :  * we perform some datatype-independent canonicalization checks anyway.
    1959              :  */
    1960              : RangeType *
    1961       612375 : range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
    1962              :                 bool empty, struct Node *escontext)
    1963              : {
    1964              :     RangeType  *range;
    1965              :     int         cmp;
    1966              :     Size        msize;
    1967              :     Pointer     ptr;
    1968              :     int16       typlen;
    1969              :     bool        typbyval;
    1970              :     char        typalign;
    1971              :     char        typstorage;
    1972       612375 :     char        flags = 0;
    1973              : 
    1974              :     /*
    1975              :      * Verify range is not invalid on its face, and construct flags value,
    1976              :      * preventing any non-canonical combinations such as infinite+inclusive.
    1977              :      */
    1978              :     Assert(lower->lower);
    1979              :     Assert(!upper->lower);
    1980              : 
    1981       612375 :     if (empty)
    1982         3022 :         flags |= RANGE_EMPTY;
    1983              :     else
    1984              :     {
    1985       609353 :         cmp = range_cmp_bound_values(typcache, lower, upper);
    1986              : 
    1987              :         /* error check: if lower bound value is above upper, it's wrong */
    1988       609353 :         if (cmp > 0)
    1989           44 :             ereturn(escontext, NULL,
    1990              :                     (errcode(ERRCODE_DATA_EXCEPTION),
    1991              :                      errmsg("range lower bound must be less than or equal to range upper bound")));
    1992              : 
    1993              :         /* if bounds are equal, and not both inclusive, range is empty */
    1994       609309 :         if (cmp == 0 && !(lower->inclusive && upper->inclusive))
    1995          258 :             flags |= RANGE_EMPTY;
    1996              :         else
    1997              :         {
    1998              :             /* infinite boundaries are never inclusive */
    1999       609051 :             if (lower->infinite)
    2000         7399 :                 flags |= RANGE_LB_INF;
    2001       601652 :             else if (lower->inclusive)
    2002       599189 :                 flags |= RANGE_LB_INC;
    2003       609051 :             if (upper->infinite)
    2004         4779 :                 flags |= RANGE_UB_INF;
    2005       604272 :             else if (upper->inclusive)
    2006         2877 :                 flags |= RANGE_UB_INC;
    2007              :         }
    2008              :     }
    2009              : 
    2010              :     /* Fetch information about range's element type */
    2011       612331 :     typlen = typcache->rngelemtype->typlen;
    2012       612331 :     typbyval = typcache->rngelemtype->typbyval;
    2013       612331 :     typalign = typcache->rngelemtype->typalign;
    2014       612331 :     typstorage = typcache->rngelemtype->typstorage;
    2015              : 
    2016              :     /* Count space for varlena header and range type's OID */
    2017       612331 :     msize = sizeof(RangeType);
    2018              :     Assert(msize == MAXALIGN(msize));
    2019              : 
    2020              :     /* Count space for bounds */
    2021       612331 :     if (RANGE_HAS_LBOUND(flags))
    2022              :     {
    2023              :         /*
    2024              :          * Make sure item to be inserted is not toasted.  It is essential that
    2025              :          * we not insert an out-of-line toast value pointer into a range
    2026              :          * object, for the same reasons that arrays and records can't contain
    2027              :          * them.  It would work to store a compressed-in-line value, but we
    2028              :          * prefer to decompress and then let compression be applied to the
    2029              :          * whole range object if necessary.  But, unlike arrays, we do allow
    2030              :          * short-header varlena objects to stay as-is.
    2031              :          */
    2032       601652 :         if (typlen == -1)
    2033         4105 :             lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
    2034              : 
    2035       601652 :         msize = datum_compute_size(msize, lower->val, typbyval, typalign,
    2036              :                                    typlen, typstorage);
    2037              :     }
    2038              : 
    2039       612331 :     if (RANGE_HAS_UBOUND(flags))
    2040              :     {
    2041              :         /* Make sure item to be inserted is not toasted */
    2042       604272 :         if (typlen == -1)
    2043         4073 :             upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
    2044              : 
    2045       604272 :         msize = datum_compute_size(msize, upper->val, typbyval, typalign,
    2046              :                                    typlen, typstorage);
    2047              :     }
    2048              : 
    2049              :     /* Add space for flag byte */
    2050       612331 :     msize += sizeof(char);
    2051              : 
    2052              :     /* Note: zero-fill is required here, just as in heap tuples */
    2053       612331 :     range = (RangeType *) palloc0(msize);
    2054       612331 :     SET_VARSIZE(range, msize);
    2055              : 
    2056              :     /* Now fill in the datum */
    2057       612331 :     range->rangetypid = typcache->type_id;
    2058              : 
    2059       612331 :     ptr = (char *) (range + 1);
    2060              : 
    2061       612331 :     if (RANGE_HAS_LBOUND(flags))
    2062              :     {
    2063              :         Assert(lower->lower);
    2064       601652 :         ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
    2065              :                           typstorage);
    2066              :     }
    2067              : 
    2068       612331 :     if (RANGE_HAS_UBOUND(flags))
    2069              :     {
    2070              :         Assert(!upper->lower);
    2071       604272 :         ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
    2072              :                           typstorage);
    2073              :     }
    2074              : 
    2075       612331 :     *((char *) ptr) = flags;
    2076              : 
    2077       612331 :     return range;
    2078              : }
    2079              : 
    2080              : /*
    2081              :  * range_deserialize: deconstruct a range value
    2082              :  *
    2083              :  * NB: the given range object must be fully detoasted; it cannot have a
    2084              :  * short varlena header.
    2085              :  *
    2086              :  * Note that if the element type is pass-by-reference, the datums in the
    2087              :  * RangeBound structs will be pointers into the given range object.
    2088              :  */
    2089              : void
    2090      6530306 : range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
    2091              :                   RangeBound *lower, RangeBound *upper, bool *empty)
    2092              : {
    2093              :     char        flags;
    2094              :     int16       typlen;
    2095              :     bool        typbyval;
    2096              :     char        typalign;
    2097              :     const char *ptr;
    2098              :     Datum       lbound;
    2099              :     Datum       ubound;
    2100              : 
    2101              :     /* assert caller passed the right typcache entry */
    2102              :     Assert(RangeTypeGetOid(range) == typcache->type_id);
    2103              : 
    2104              :     /* fetch the flag byte from datum's last byte */
    2105      6530306 :     flags = *((const char *) range + VARSIZE(range) - 1);
    2106              : 
    2107              :     /* fetch information about range's element type */
    2108      6530306 :     typlen = typcache->rngelemtype->typlen;
    2109      6530306 :     typbyval = typcache->rngelemtype->typbyval;
    2110      6530306 :     typalign = typcache->rngelemtype->typalign;
    2111              : 
    2112              :     /* initialize data pointer just after the range OID */
    2113      6530306 :     ptr = (const char *) (range + 1);
    2114              : 
    2115              :     /* fetch lower bound, if any */
    2116      6530306 :     if (RANGE_HAS_LBOUND(flags))
    2117              :     {
    2118              :         /* att_align_pointer cannot be necessary here */
    2119      5758833 :         lbound = fetch_att(ptr, typbyval, typlen);
    2120      5758833 :         ptr = (char *) att_addlength_pointer(ptr, typlen, ptr);
    2121              :     }
    2122              :     else
    2123       771473 :         lbound = (Datum) 0;
    2124              : 
    2125              :     /* fetch upper bound, if any */
    2126      6530306 :     if (RANGE_HAS_UBOUND(flags))
    2127              :     {
    2128      5774039 :         ptr = (char *) att_align_pointer(ptr, typalign, typlen, ptr);
    2129      5774039 :         ubound = fetch_att(ptr, typbyval, typlen);
    2130              :         /* no need for att_addlength_pointer */
    2131              :     }
    2132              :     else
    2133       756267 :         ubound = (Datum) 0;
    2134              : 
    2135              :     /* emit results */
    2136              : 
    2137      6530306 :     *empty = (flags & RANGE_EMPTY) != 0;
    2138              : 
    2139      6530306 :     lower->val = lbound;
    2140      6530306 :     lower->infinite = (flags & RANGE_LB_INF) != 0;
    2141      6530306 :     lower->inclusive = (flags & RANGE_LB_INC) != 0;
    2142      6530306 :     lower->lower = true;
    2143              : 
    2144      6530306 :     upper->val = ubound;
    2145      6530306 :     upper->infinite = (flags & RANGE_UB_INF) != 0;
    2146      6530306 :     upper->inclusive = (flags & RANGE_UB_INC) != 0;
    2147      6530306 :     upper->lower = false;
    2148      6530306 : }
    2149              : 
    2150              : /*
    2151              :  * range_get_flags: just get the flags from a RangeType value.
    2152              :  *
    2153              :  * This is frequently useful in places that only need the flags and not
    2154              :  * the full results of range_deserialize.
    2155              :  */
    2156              : char
    2157      1951846 : range_get_flags(const RangeType *range)
    2158              : {
    2159              :     /* fetch the flag byte from datum's last byte */
    2160      1951846 :     return *((const char *) range + VARSIZE(range) - 1);
    2161              : }
    2162              : 
    2163              : /*
    2164              :  * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
    2165              :  *
    2166              :  * This is only needed in GiST operations, so we don't include a provision
    2167              :  * for setting it in range_serialize; rather, this function must be applied
    2168              :  * afterwards.
    2169              :  */
    2170              : void
    2171          412 : range_set_contain_empty(RangeType *range)
    2172              : {
    2173              :     char       *flagsp;
    2174              : 
    2175              :     /* flag byte is datum's last byte */
    2176          412 :     flagsp = (char *) range + VARSIZE(range) - 1;
    2177              : 
    2178          412 :     *flagsp |= RANGE_CONTAIN_EMPTY;
    2179          412 : }
    2180              : 
    2181              : /*
    2182              :  * This both serializes and canonicalizes (if applicable) the range.
    2183              :  * This should be used by most callers.
    2184              :  */
    2185              : RangeType *
    2186       308752 : make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
    2187              :            bool empty, struct Node *escontext)
    2188              : {
    2189              :     RangeType  *range;
    2190              : 
    2191       308752 :     range = range_serialize(typcache, lower, upper, empty, escontext);
    2192              : 
    2193       308716 :     if (SOFT_ERROR_OCCURRED(escontext))
    2194            8 :         return NULL;
    2195              : 
    2196              :     /* no need to call canonical on empty ranges ... */
    2197       308708 :     if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
    2198       303943 :         !RangeIsEmpty(range))
    2199              :     {
    2200              :         /* Do this the hard way so that we can pass escontext */
    2201       300983 :         LOCAL_FCINFO(fcinfo, 1);
    2202              :         Datum       result;
    2203              : 
    2204       300983 :         InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
    2205              :                                  InvalidOid, escontext, NULL);
    2206              : 
    2207       300983 :         fcinfo->args[0].value = RangeTypePGetDatum(range);
    2208       300983 :         fcinfo->args[0].isnull = false;
    2209              : 
    2210       300983 :         result = FunctionCallInvoke(fcinfo);
    2211              : 
    2212       300983 :         if (SOFT_ERROR_OCCURRED(escontext))
    2213           16 :             return NULL;
    2214              : 
    2215              :         /* Should not get a null result if there was no error */
    2216       300967 :         if (fcinfo->isnull)
    2217            0 :             elog(ERROR, "function %u returned NULL",
    2218              :                  typcache->rng_canonical_finfo.fn_oid);
    2219              : 
    2220       300967 :         range = DatumGetRangeTypeP(result);
    2221              :     }
    2222              : 
    2223       308692 :     return range;
    2224              : }
    2225              : 
    2226              : /*
    2227              :  * Compare two range boundary points, returning <0, 0, or >0 according to
    2228              :  * whether b1 is less than, equal to, or greater than b2.
    2229              :  *
    2230              :  * The boundaries can be any combination of upper and lower; so it's useful
    2231              :  * for a variety of operators.
    2232              :  *
    2233              :  * The simple case is when b1 and b2 are both finite and inclusive, in which
    2234              :  * case the result is just a comparison of the values held in b1 and b2.
    2235              :  *
    2236              :  * If a bound is exclusive, then we need to know whether it's a lower bound,
    2237              :  * in which case we treat the boundary point as "just greater than" the held
    2238              :  * value; or an upper bound, in which case we treat the boundary point as
    2239              :  * "just less than" the held value.
    2240              :  *
    2241              :  * If a bound is infinite, it represents minus infinity (less than every other
    2242              :  * point) if it's a lower bound; or plus infinity (greater than every other
    2243              :  * point) if it's an upper bound.
    2244              :  *
    2245              :  * There is only one case where two boundaries compare equal but are not
    2246              :  * identical: when both bounds are inclusive and hold the same finite value,
    2247              :  * but one is an upper bound and the other a lower bound.
    2248              :  */
    2249              : int
    2250      8076241 : range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
    2251              : {
    2252              :     int32       result;
    2253              : 
    2254              :     /*
    2255              :      * First, handle cases involving infinity, which don't require invoking
    2256              :      * the comparison proc.
    2257              :      */
    2258      8076241 :     if (b1->infinite && b2->infinite)
    2259              :     {
    2260              :         /*
    2261              :          * Both are infinity, so they are equal unless one is lower and the
    2262              :          * other not.
    2263              :          */
    2264        13602 :         if (b1->lower == b2->lower)
    2265        13538 :             return 0;
    2266              :         else
    2267           64 :             return b1->lower ? -1 : 1;
    2268              :     }
    2269      8062639 :     else if (b1->infinite)
    2270        64047 :         return b1->lower ? -1 : 1;
    2271      7998592 :     else if (b2->infinite)
    2272        20945 :         return b2->lower ? 1 : -1;
    2273              : 
    2274              :     /*
    2275              :      * Both boundaries are finite, so compare the held values.
    2276              :      */
    2277      7977647 :     result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2278              :                                              typcache->rng_collation,
    2279      7977647 :                                              b1->val, b2->val));
    2280              : 
    2281              :     /*
    2282              :      * If the comparison is anything other than equal, we're done. If they
    2283              :      * compare equal though, we still have to consider whether the boundaries
    2284              :      * are inclusive or exclusive.
    2285              :      */
    2286      7977647 :     if (result == 0)
    2287              :     {
    2288       565295 :         if (!b1->inclusive && !b2->inclusive)
    2289              :         {
    2290              :             /* both are exclusive */
    2291       251133 :             if (b1->lower == b2->lower)
    2292       251128 :                 return 0;
    2293              :             else
    2294            5 :                 return b1->lower ? 1 : -1;
    2295              :         }
    2296       314162 :         else if (!b1->inclusive)
    2297          532 :             return b1->lower ? 1 : -1;
    2298       313630 :         else if (!b2->inclusive)
    2299          849 :             return b2->lower ? -1 : 1;
    2300              :         else
    2301              :         {
    2302              :             /*
    2303              :              * Both are inclusive and the values held are equal, so they are
    2304              :              * equal regardless of whether they are upper or lower boundaries,
    2305              :              * or a mix.
    2306              :              */
    2307       312781 :             return 0;
    2308              :         }
    2309              :     }
    2310              : 
    2311      7412352 :     return result;
    2312              : }
    2313              : 
    2314              : /*
    2315              :  * Compare two range boundary point values, returning <0, 0, or >0 according
    2316              :  * to whether b1 is less than, equal to, or greater than b2.
    2317              :  *
    2318              :  * This is similar to but simpler than range_cmp_bounds().  We just compare
    2319              :  * the values held in b1 and b2, ignoring inclusive/exclusive flags.  The
    2320              :  * lower/upper flags only matter for infinities, where they tell us if the
    2321              :  * infinity is plus or minus.
    2322              :  */
    2323              : int
    2324       925505 : range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
    2325              :                        const RangeBound *b2)
    2326              : {
    2327              :     /*
    2328              :      * First, handle cases involving infinity, which don't require invoking
    2329              :      * the comparison proc.
    2330              :      */
    2331       925505 :     if (b1->infinite && b2->infinite)
    2332              :     {
    2333              :         /*
    2334              :          * Both are infinity, so they are equal unless one is lower and the
    2335              :          * other not.
    2336              :          */
    2337          231 :         if (b1->lower == b2->lower)
    2338            0 :             return 0;
    2339              :         else
    2340          231 :             return b1->lower ? -1 : 1;
    2341              :     }
    2342       925274 :     else if (b1->infinite)
    2343        11609 :         return b1->lower ? -1 : 1;
    2344       913665 :     else if (b2->infinite)
    2345         9460 :         return b2->lower ? 1 : -1;
    2346              : 
    2347              :     /*
    2348              :      * Both boundaries are finite, so compare the held values.
    2349              :      */
    2350       904205 :     return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2351              :                                            typcache->rng_collation,
    2352       904205 :                                            b1->val, b2->val));
    2353              : }
    2354              : 
    2355              : /*
    2356              :  * qsort callback for sorting ranges.
    2357              :  *
    2358              :  * Two empty ranges compare equal; an empty range sorts to the left of any
    2359              :  * non-empty range.  Two non-empty ranges are sorted by lower bound first
    2360              :  * and by upper bound next.
    2361              :  */
    2362              : int
    2363        18385 : range_compare(const void *key1, const void *key2, void *arg)
    2364              : {
    2365        18385 :     RangeType  *r1 = *(RangeType *const *) key1;
    2366        18385 :     RangeType  *r2 = *(RangeType *const *) key2;
    2367        18385 :     TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
    2368              :     RangeBound  lower1;
    2369              :     RangeBound  upper1;
    2370              :     RangeBound  lower2;
    2371              :     RangeBound  upper2;
    2372              :     bool        empty1;
    2373              :     bool        empty2;
    2374              :     int         cmp;
    2375              : 
    2376        18385 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    2377        18385 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    2378              : 
    2379        18385 :     if (empty1 && empty2)
    2380           37 :         cmp = 0;
    2381        18348 :     else if (empty1)
    2382           28 :         cmp = -1;
    2383        18320 :     else if (empty2)
    2384           18 :         cmp = 1;
    2385              :     else
    2386              :     {
    2387        18302 :         cmp = range_cmp_bounds(typcache, &lower1, &lower2);
    2388        18302 :         if (cmp == 0)
    2389           34 :             cmp = range_cmp_bounds(typcache, &upper1, &upper2);
    2390              :     }
    2391              : 
    2392        18385 :     return cmp;
    2393              : }
    2394              : 
    2395              : /*
    2396              :  * Build an empty range value of the type indicated by the typcache entry.
    2397              :  */
    2398              : RangeType *
    2399         2622 : make_empty_range(TypeCacheEntry *typcache)
    2400              : {
    2401              :     RangeBound  lower;
    2402              :     RangeBound  upper;
    2403              : 
    2404         2622 :     lower.val = (Datum) 0;
    2405         2622 :     lower.infinite = false;
    2406         2622 :     lower.inclusive = false;
    2407         2622 :     lower.lower = true;
    2408              : 
    2409         2622 :     upper.val = (Datum) 0;
    2410         2622 :     upper.infinite = false;
    2411         2622 :     upper.inclusive = false;
    2412         2622 :     upper.lower = false;
    2413              : 
    2414         2622 :     return make_range(typcache, &lower, &upper, true, NULL);
    2415              : }
    2416              : 
    2417              : /*
    2418              :  * Planner support function for elem_contained_by_range (<@ operator).
    2419              :  */
    2420              : Datum
    2421          105 : elem_contained_by_range_support(PG_FUNCTION_ARGS)
    2422              : {
    2423          105 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    2424          105 :     Node       *ret = NULL;
    2425              : 
    2426          105 :     if (IsA(rawreq, SupportRequestSimplify))
    2427              :     {
    2428           80 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
    2429           80 :         FuncExpr   *fexpr = req->fcall;
    2430              :         Expr       *leftop,
    2431              :                    *rightop;
    2432              : 
    2433              :         Assert(list_length(fexpr->args) == 2);
    2434           80 :         leftop = linitial(fexpr->args);
    2435           80 :         rightop = lsecond(fexpr->args);
    2436              : 
    2437           80 :         ret = find_simplified_clause(req->root, rightop, leftop);
    2438              :     }
    2439              : 
    2440          105 :     PG_RETURN_POINTER(ret);
    2441              : }
    2442              : 
    2443              : /*
    2444              :  * Planner support function for range_contains_elem (@> operator).
    2445              :  */
    2446              : Datum
    2447          255 : range_contains_elem_support(PG_FUNCTION_ARGS)
    2448              : {
    2449          255 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    2450          255 :     Node       *ret = NULL;
    2451              : 
    2452          255 :     if (IsA(rawreq, SupportRequestSimplify))
    2453              :     {
    2454          130 :         SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq;
    2455          130 :         FuncExpr   *fexpr = req->fcall;
    2456              :         Expr       *leftop,
    2457              :                    *rightop;
    2458              : 
    2459              :         Assert(list_length(fexpr->args) == 2);
    2460          130 :         leftop = linitial(fexpr->args);
    2461          130 :         rightop = lsecond(fexpr->args);
    2462              : 
    2463          130 :         ret = find_simplified_clause(req->root, leftop, rightop);
    2464              :     }
    2465              : 
    2466          255 :     PG_RETURN_POINTER(ret);
    2467              : }
    2468              : 
    2469              : 
    2470              : /*
    2471              :  *----------------------------------------------------------
    2472              :  * STATIC FUNCTIONS
    2473              :  *----------------------------------------------------------
    2474              :  */
    2475              : 
    2476              : /*
    2477              :  * Given a string representing the flags for the range type, return the flags
    2478              :  * represented as a char.
    2479              :  */
    2480              : static char
    2481         3540 : range_parse_flags(const char *flags_str)
    2482              : {
    2483         3540 :     char        flags = 0;
    2484              : 
    2485         3540 :     if (flags_str[0] == '\0' ||
    2486         3540 :         flags_str[1] == '\0' ||
    2487         3540 :         flags_str[2] != '\0')
    2488            0 :         ereport(ERROR,
    2489              :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2490              :                  errmsg("invalid range bound flags"),
    2491              :                  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
    2492              : 
    2493         3540 :     switch (flags_str[0])
    2494              :     {
    2495          220 :         case '[':
    2496          220 :             flags |= RANGE_LB_INC;
    2497          220 :             break;
    2498         3320 :         case '(':
    2499         3320 :             break;
    2500            0 :         default:
    2501            0 :             ereport(ERROR,
    2502              :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2503              :                      errmsg("invalid range bound flags"),
    2504              :                      errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
    2505              :     }
    2506              : 
    2507         3540 :     switch (flags_str[1])
    2508              :     {
    2509         3445 :         case ']':
    2510         3445 :             flags |= RANGE_UB_INC;
    2511         3445 :             break;
    2512           95 :         case ')':
    2513           95 :             break;
    2514            0 :         default:
    2515            0 :             ereport(ERROR,
    2516              :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2517              :                      errmsg("invalid range bound flags"),
    2518              :                      errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
    2519              :     }
    2520              : 
    2521         3540 :     return flags;
    2522              : }
    2523              : 
    2524              : /*
    2525              :  * Parse range input.
    2526              :  *
    2527              :  * Input parameters:
    2528              :  *  string: input string to be parsed
    2529              :  * Output parameters:
    2530              :  *  *flags: receives flags bitmask
    2531              :  *  *lbound_str: receives palloc'd lower bound string, or NULL if none
    2532              :  *  *ubound_str: receives palloc'd upper bound string, or NULL if none
    2533              :  *
    2534              :  * This is modeled somewhat after record_in in rowtypes.c.
    2535              :  * The input syntax is:
    2536              :  *  <range>   := EMPTY
    2537              :  *             | <lb-inc> <string>, <string> <ub-inc>
    2538              :  *  <lb-inc>  := '[' | '('
    2539              :  *  <ub-inc>  := ']' | ')'
    2540              :  *
    2541              :  * Whitespace before or after <range> is ignored.  Whitespace within a <string>
    2542              :  * is taken literally and becomes part of the input string for that bound.
    2543              :  *
    2544              :  * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
    2545              :  * is surrounded by double-quotes, in which case it is the literal empty
    2546              :  * string.
    2547              :  *
    2548              :  * Within a <string>, special characters (such as comma, parenthesis, or
    2549              :  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
    2550              :  * double-quotes, a double-quote can be escaped with double-quote or backslash.
    2551              :  *
    2552              :  * Returns true on success, false on failure (but failures will return only if
    2553              :  * escontext is an ErrorSaveContext).
    2554              :  */
    2555              : static bool
    2556         4945 : range_parse(const char *string, char *flags, char **lbound_str,
    2557              :             char **ubound_str, Node *escontext)
    2558              : {
    2559         4945 :     const char *ptr = string;
    2560              :     bool        infinite;
    2561              : 
    2562         4945 :     *flags = 0;
    2563              : 
    2564              :     /* consume whitespace */
    2565         4961 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
    2566           16 :         ptr++;
    2567              : 
    2568              :     /* check for empty range */
    2569         4945 :     if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
    2570              :                        strlen(RANGE_EMPTY_LITERAL)) == 0)
    2571              :     {
    2572          400 :         *flags = RANGE_EMPTY;
    2573          400 :         *lbound_str = NULL;
    2574          400 :         *ubound_str = NULL;
    2575              : 
    2576          400 :         ptr += strlen(RANGE_EMPTY_LITERAL);
    2577              : 
    2578              :         /* the rest should be whitespace */
    2579          408 :         while (*ptr != '\0' && isspace((unsigned char) *ptr))
    2580            8 :             ptr++;
    2581              : 
    2582              :         /* should have consumed everything */
    2583          400 :         if (*ptr != '\0')
    2584            0 :             ereturn(escontext, false,
    2585              :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2586              :                      errmsg("malformed range literal: \"%s\"",
    2587              :                             string),
    2588              :                      errdetail("Junk after \"empty\" key word.")));
    2589              : 
    2590          400 :         return true;
    2591              :     }
    2592              : 
    2593         4545 :     if (*ptr == '[')
    2594              :     {
    2595         4079 :         *flags |= RANGE_LB_INC;
    2596         4079 :         ptr++;
    2597              :     }
    2598          466 :     else if (*ptr == '(')
    2599          450 :         ptr++;
    2600              :     else
    2601           16 :         ereturn(escontext, false,
    2602              :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2603              :                  errmsg("malformed range literal: \"%s\"",
    2604              :                         string),
    2605              :                  errdetail("Missing left parenthesis or bracket.")));
    2606              : 
    2607         4529 :     ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
    2608         4525 :     if (ptr == NULL)
    2609            0 :         return false;
    2610         4525 :     if (infinite)
    2611          117 :         *flags |= RANGE_LB_INF;
    2612              : 
    2613         4525 :     if (*ptr == ',')
    2614         4509 :         ptr++;
    2615              :     else
    2616           16 :         ereturn(escontext, false,
    2617              :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2618              :                  errmsg("malformed range literal: \"%s\"",
    2619              :                         string),
    2620              :                  errdetail("Missing comma after lower bound.")));
    2621              : 
    2622         4509 :     ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
    2623         4509 :     if (ptr == NULL)
    2624            8 :         return false;
    2625         4501 :     if (infinite)
    2626          173 :         *flags |= RANGE_UB_INF;
    2627              : 
    2628         4501 :     if (*ptr == ']')
    2629              :     {
    2630          433 :         *flags |= RANGE_UB_INC;
    2631          433 :         ptr++;
    2632              :     }
    2633         4068 :     else if (*ptr == ')')
    2634         4060 :         ptr++;
    2635              :     else                        /* must be a comma */
    2636            8 :         ereturn(escontext, false,
    2637              :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2638              :                  errmsg("malformed range literal: \"%s\"",
    2639              :                         string),
    2640              :                  errdetail("Too many commas.")));
    2641              : 
    2642              :     /* consume whitespace */
    2643         4513 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
    2644           20 :         ptr++;
    2645              : 
    2646         4493 :     if (*ptr != '\0')
    2647           12 :         ereturn(escontext, false,
    2648              :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2649              :                  errmsg("malformed range literal: \"%s\"",
    2650              :                         string),
    2651              :                  errdetail("Junk after right parenthesis or bracket.")));
    2652              : 
    2653         4481 :     return true;
    2654              : }
    2655              : 
    2656              : /*
    2657              :  * Helper for range_parse: parse and de-quote one bound string.
    2658              :  *
    2659              :  * We scan until finding comma, right parenthesis, or right bracket.
    2660              :  *
    2661              :  * Input parameters:
    2662              :  *  string: entire input string (used only for error reports)
    2663              :  *  ptr: where to start parsing bound
    2664              :  * Output parameters:
    2665              :  *  *bound_str: receives palloc'd bound string, or NULL if none
    2666              :  *  *infinite: set true if no bound, else false
    2667              :  *
    2668              :  * The return value is the scan ptr, advanced past the bound string.
    2669              :  * However, if escontext is an ErrorSaveContext, we return NULL on failure.
    2670              :  */
    2671              : static const char *
    2672         9038 : range_parse_bound(const char *string, const char *ptr,
    2673              :                   char **bound_str, bool *infinite, Node *escontext)
    2674              : {
    2675              :     StringInfoData buf;
    2676              : 
    2677              :     /* Check for null: completely empty input means null */
    2678         9038 :     if (*ptr == ',' || *ptr == ')' || *ptr == ']')
    2679              :     {
    2680          290 :         *bound_str = NULL;
    2681          290 :         *infinite = true;
    2682              :     }
    2683              :     else
    2684              :     {
    2685              :         /* Extract string for this bound */
    2686         8748 :         bool        inquote = false;
    2687              : 
    2688         8748 :         initStringInfo(&buf);
    2689        28085 :         while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
    2690              :         {
    2691        19349 :             char        ch = *ptr++;
    2692              : 
    2693        19349 :             if (ch == '\0')
    2694           12 :                 ereturn(escontext, NULL,
    2695              :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2696              :                          errmsg("malformed range literal: \"%s\"",
    2697              :                                 string),
    2698              :                          errdetail("Unexpected end of input.")));
    2699        19337 :             if (ch == '\\')
    2700              :             {
    2701           28 :                 if (*ptr == '\0')
    2702            0 :                     ereturn(escontext, NULL,
    2703              :                             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2704              :                              errmsg("malformed range literal: \"%s\"",
    2705              :                                     string),
    2706              :                              errdetail("Unexpected end of input.")));
    2707           28 :                 appendStringInfoChar(&buf, *ptr++);
    2708              :             }
    2709        19309 :             else if (ch == '"')
    2710              :             {
    2711          258 :                 if (!inquote)
    2712          129 :                     inquote = true;
    2713          129 :                 else if (*ptr == '"')
    2714              :                 {
    2715              :                     /* doubled quote within quote sequence */
    2716            4 :                     appendStringInfoChar(&buf, *ptr++);
    2717              :                 }
    2718              :                 else
    2719          125 :                     inquote = false;
    2720              :             }
    2721              :             else
    2722        19051 :                 appendStringInfoChar(&buf, ch);
    2723              :         }
    2724              : 
    2725         8736 :         *bound_str = buf.data;
    2726         8736 :         *infinite = false;
    2727              :     }
    2728              : 
    2729         9026 :     return ptr;
    2730              : }
    2731              : 
    2732              : /*
    2733              :  * Convert a deserialized range value to text form
    2734              :  *
    2735              :  * Inputs are the flags byte, and the two bound values already converted to
    2736              :  * text (but not yet quoted).  If no bound value, pass NULL.
    2737              :  *
    2738              :  * Result is a palloc'd string
    2739              :  */
    2740              : static char *
    2741        55591 : range_deparse(char flags, const char *lbound_str, const char *ubound_str)
    2742              : {
    2743              :     StringInfoData buf;
    2744              : 
    2745        55591 :     if (flags & RANGE_EMPTY)
    2746         8496 :         return pstrdup(RANGE_EMPTY_LITERAL);
    2747              : 
    2748        47095 :     initStringInfo(&buf);
    2749              : 
    2750        47095 :     appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
    2751              : 
    2752        47095 :     if (RANGE_HAS_LBOUND(flags))
    2753        45704 :         appendStringInfoString(&buf, range_bound_escape(lbound_str));
    2754              : 
    2755        47095 :     appendStringInfoChar(&buf, ',');
    2756              : 
    2757        47095 :     if (RANGE_HAS_UBOUND(flags))
    2758        45612 :         appendStringInfoString(&buf, range_bound_escape(ubound_str));
    2759              : 
    2760        47095 :     appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
    2761              : 
    2762        47095 :     return buf.data;
    2763              : }
    2764              : 
    2765              : /*
    2766              :  * Helper for range_deparse: quote a bound value as needed
    2767              :  *
    2768              :  * Result is a palloc'd string
    2769              :  */
    2770              : static char *
    2771        91316 : range_bound_escape(const char *value)
    2772              : {
    2773              :     bool        nq;
    2774              :     const char *ptr;
    2775              :     StringInfoData buf;
    2776              : 
    2777        91316 :     initStringInfo(&buf);
    2778              : 
    2779              :     /* Detect whether we need double quotes for this value */
    2780        91316 :     nq = (value[0] == '\0');    /* force quotes for empty string */
    2781       417660 :     for (ptr = value; *ptr; ptr++)
    2782              :     {
    2783       326656 :         char        ch = *ptr;
    2784              : 
    2785       326656 :         if (ch == '"' || ch == '\\' ||
    2786       326564 :             ch == '(' || ch == ')' ||
    2787       326548 :             ch == '[' || ch == ']' ||
    2788       326516 :             ch == ',' ||
    2789       326516 :             isspace((unsigned char) ch))
    2790              :         {
    2791          312 :             nq = true;
    2792          312 :             break;
    2793              :         }
    2794              :     }
    2795              : 
    2796              :     /* And emit the string */
    2797        91316 :     if (nq)
    2798          328 :         appendStringInfoChar(&buf, '"');
    2799       420160 :     for (ptr = value; *ptr; ptr++)
    2800              :     {
    2801       328844 :         char        ch = *ptr;
    2802              : 
    2803       328844 :         if (ch == '"' || ch == '\\')
    2804           80 :             appendStringInfoChar(&buf, ch);
    2805       328844 :         appendStringInfoChar(&buf, ch);
    2806              :     }
    2807        91316 :     if (nq)
    2808          328 :         appendStringInfoChar(&buf, '"');
    2809              : 
    2810        91316 :     return buf.data;
    2811              : }
    2812              : 
    2813              : /*
    2814              :  * Test whether range r1 contains range r2.
    2815              :  *
    2816              :  * Caller has already checked that they are the same range type, and looked up
    2817              :  * the necessary typcache entry.
    2818              :  */
    2819              : bool
    2820       322622 : range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
    2821              : {
    2822              :     RangeBound  lower1;
    2823              :     RangeBound  upper1;
    2824              :     bool        empty1;
    2825              :     RangeBound  lower2;
    2826              :     RangeBound  upper2;
    2827              :     bool        empty2;
    2828              : 
    2829              :     /* Different types should be prevented by ANYRANGE matching rules */
    2830       322622 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    2831            0 :         elog(ERROR, "range types do not match");
    2832              : 
    2833       322622 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    2834       322622 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    2835              : 
    2836              :     /* If either range is empty, the answer is easy */
    2837       322622 :     if (empty2)
    2838       209806 :         return true;
    2839       112816 :     else if (empty1)
    2840         9044 :         return false;
    2841              : 
    2842              :     /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
    2843       103772 :     if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
    2844        49711 :         return false;
    2845        54061 :     if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
    2846        48552 :         return false;
    2847              : 
    2848         5509 :     return true;
    2849              : }
    2850              : 
    2851              : bool
    2852        81490 : range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
    2853              : {
    2854        81490 :     return range_contains_internal(typcache, r2, r1);
    2855              : }
    2856              : 
    2857              : /*
    2858              :  * Test whether range r contains a specific element value.
    2859              :  */
    2860              : bool
    2861        59627 : range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
    2862              : {
    2863              :     RangeBound  lower;
    2864              :     RangeBound  upper;
    2865              :     bool        empty;
    2866              :     int32       cmp;
    2867              : 
    2868        59627 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    2869              : 
    2870        59627 :     if (empty)
    2871         8576 :         return false;
    2872              : 
    2873        51051 :     if (!lower.infinite)
    2874              :     {
    2875        48215 :         cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2876              :                                               typcache->rng_collation,
    2877              :                                               lower.val, val));
    2878        48215 :         if (cmp > 0)
    2879        46641 :             return false;
    2880         1574 :         if (cmp == 0 && !lower.inclusive)
    2881            0 :             return false;
    2882              :     }
    2883              : 
    2884         4410 :     if (!upper.infinite)
    2885              :     {
    2886         4359 :         cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2887              :                                               typcache->rng_collation,
    2888              :                                               upper.val, val));
    2889         4359 :         if (cmp < 0)
    2890          321 :             return false;
    2891         4038 :         if (cmp == 0 && !upper.inclusive)
    2892            0 :             return false;
    2893              :     }
    2894              : 
    2895         4089 :     return true;
    2896              : }
    2897              : 
    2898              : 
    2899              : /*
    2900              :  * datum_compute_size() and datum_write() are used to insert the bound
    2901              :  * values into a range object.  They are modeled after heaptuple.c's
    2902              :  * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
    2903              :  * null values here.  TYPE_IS_PACKABLE must test the same conditions as
    2904              :  * heaptuple.c's ATT_IS_PACKABLE macro.  See the comments there for more
    2905              :  * details.
    2906              :  */
    2907              : 
    2908              : /* Does datatype allow packing into the 1-byte-header varlena format? */
    2909              : #define TYPE_IS_PACKABLE(typlen, typstorage) \
    2910              :     ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
    2911              : 
    2912              : /*
    2913              :  * Increment data_length by the space needed by the datum, including any
    2914              :  * preceding alignment padding.
    2915              :  */
    2916              : static Size
    2917      1205924 : datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
    2918              :                    int16 typlen, char typstorage)
    2919              : {
    2920      1214102 :     if (TYPE_IS_PACKABLE(typlen, typstorage) &&
    2921         8178 :         VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
    2922              :     {
    2923              :         /*
    2924              :          * we're anticipating converting to a short varlena header, so adjust
    2925              :          * length and don't count any alignment
    2926              :          */
    2927         7329 :         data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
    2928              :     }
    2929              :     else
    2930              :     {
    2931      1198595 :         data_length = att_align_datum(data_length, typalign, typlen, val);
    2932      1198595 :         data_length = att_addlength_datum(data_length, typlen, val);
    2933              :     }
    2934              : 
    2935      1205924 :     return data_length;
    2936              : }
    2937              : 
    2938              : /*
    2939              :  * Write the given datum beginning at ptr (after advancing to correct
    2940              :  * alignment, if needed).  Return the pointer incremented by space used.
    2941              :  */
    2942              : static char *
    2943      1205924 : datum_write(char *ptr, Datum datum, bool typbyval, char typalign,
    2944              :             int16 typlen, char typstorage)
    2945              : {
    2946              :     Size        data_length;
    2947              : 
    2948      1205924 :     if (typbyval)
    2949              :     {
    2950              :         /* pass-by-value */
    2951      1197746 :         ptr = (char *) att_align_nominal(ptr, typalign);
    2952      1197746 :         store_att_byval(ptr, datum, typlen);
    2953      1197746 :         data_length = typlen;
    2954              :     }
    2955         8178 :     else if (typlen == -1)
    2956              :     {
    2957              :         /* varlena */
    2958         8178 :         Pointer     val = DatumGetPointer(datum);
    2959              : 
    2960         8178 :         if (VARATT_IS_EXTERNAL(val))
    2961              :         {
    2962              :             /*
    2963              :              * Throw error, because we must never put a toast pointer inside a
    2964              :              * range object.  Caller should have detoasted it.
    2965              :              */
    2966            0 :             elog(ERROR, "cannot store a toast pointer inside a range");
    2967              :             data_length = 0;    /* keep compiler quiet */
    2968              :         }
    2969         8178 :         else if (VARATT_IS_SHORT(val))
    2970              :         {
    2971              :             /* no alignment for short varlenas */
    2972          820 :             data_length = VARSIZE_SHORT(val);
    2973          820 :             memcpy(ptr, val, data_length);
    2974              :         }
    2975        14716 :         else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
    2976         7358 :                  VARATT_CAN_MAKE_SHORT(val))
    2977              :         {
    2978              :             /* convert to short varlena -- no alignment */
    2979         7329 :             data_length = VARATT_CONVERTED_SHORT_SIZE(val);
    2980         7329 :             SET_VARSIZE_SHORT(ptr, data_length);
    2981         7329 :             memcpy(ptr + 1, VARDATA(val), data_length - 1);
    2982              :         }
    2983              :         else
    2984              :         {
    2985              :             /* full 4-byte header varlena */
    2986           29 :             ptr = (char *) att_align_nominal(ptr, typalign);
    2987           29 :             data_length = VARSIZE(val);
    2988           29 :             memcpy(ptr, val, data_length);
    2989              :         }
    2990              :     }
    2991            0 :     else if (typlen == -2)
    2992              :     {
    2993              :         /* cstring ... never needs alignment */
    2994              :         Assert(typalign == TYPALIGN_CHAR);
    2995            0 :         data_length = strlen(DatumGetCString(datum)) + 1;
    2996            0 :         memcpy(ptr, DatumGetPointer(datum), data_length);
    2997              :     }
    2998              :     else
    2999              :     {
    3000              :         /* fixed-length pass-by-reference */
    3001            0 :         ptr = (char *) att_align_nominal(ptr, typalign);
    3002              :         Assert(typlen > 0);
    3003            0 :         data_length = typlen;
    3004            0 :         memcpy(ptr, DatumGetPointer(datum), data_length);
    3005              :     }
    3006              : 
    3007      1205924 :     ptr += data_length;
    3008              : 
    3009      1205924 :     return ptr;
    3010              : }
    3011              : 
    3012              : /*
    3013              :  * Common code for the elem_contained_by_range and range_contains_elem
    3014              :  * support functions.  The caller has extracted the function argument
    3015              :  * expressions, and swapped them if necessary to pass the range first.
    3016              :  *
    3017              :  * Returns a simplified replacement expression, or NULL if we can't simplify.
    3018              :  */
    3019              : static Node *
    3020          210 : find_simplified_clause(PlannerInfo *root, Expr *rangeExpr, Expr *elemExpr)
    3021              : {
    3022              :     RangeType  *range;
    3023              :     TypeCacheEntry *rangetypcache;
    3024              :     RangeBound  lower;
    3025              :     RangeBound  upper;
    3026              :     bool        empty;
    3027              : 
    3028              :     /* can't do anything unless the range is a non-null constant */
    3029          210 :     if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
    3030          130 :         return NULL;
    3031           80 :     range = DatumGetRangeTypeP(((Const *) rangeExpr)->constvalue);
    3032              : 
    3033           80 :     rangetypcache = lookup_type_cache(RangeTypeGetOid(range),
    3034              :                                       TYPECACHE_RANGE_INFO);
    3035           80 :     if (rangetypcache->rngelemtype == NULL)
    3036            0 :         elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
    3037              : 
    3038           80 :     range_deserialize(rangetypcache, range, &lower, &upper, &empty);
    3039              : 
    3040           80 :     if (empty)
    3041              :     {
    3042              :         /* if the range is empty, then there can be no matches */
    3043            5 :         return makeBoolConst(false, false);
    3044              :     }
    3045           75 :     else if (lower.infinite && upper.infinite)
    3046              :     {
    3047              :         /* the range has infinite bounds, so it matches everything */
    3048            5 :         return makeBoolConst(true, false);
    3049              :     }
    3050              :     else
    3051              :     {
    3052              :         /* at least one bound is available, we have something to work with */
    3053           70 :         TypeCacheEntry *elemTypcache = rangetypcache->rngelemtype;
    3054           70 :         Oid         opfamily = rangetypcache->rng_opfamily;
    3055           70 :         Oid         rng_collation = rangetypcache->rng_collation;
    3056           70 :         Expr       *lowerExpr = NULL;
    3057           70 :         Expr       *upperExpr = NULL;
    3058              : 
    3059           70 :         if (!lower.infinite && !upper.infinite)
    3060              :         {
    3061              :             /*
    3062              :              * When both bounds are present, we have a problem: the
    3063              :              * "simplified" clause would need to evaluate the elemExpr twice.
    3064              :              * That's definitely not okay if the elemExpr is volatile, and
    3065              :              * it's also unattractive if the elemExpr is expensive.
    3066              :              */
    3067              :             QualCost    eval_cost;
    3068              : 
    3069           55 :             if (contain_volatile_functions((Node *) elemExpr))
    3070            5 :                 return NULL;
    3071              : 
    3072              :             /*
    3073              :              * We define "expensive" as "contains any subplan or more than 10
    3074              :              * operators".  Note that the subplan search has to be done
    3075              :              * explicitly, since cost_qual_eval() will barf on unplanned
    3076              :              * subselects.
    3077              :              */
    3078           50 :             if (contain_subplans((Node *) elemExpr))
    3079            0 :                 return NULL;
    3080           50 :             cost_qual_eval_node(&eval_cost, (Node *) elemExpr, root);
    3081           50 :             if (eval_cost.startup + eval_cost.per_tuple >
    3082           50 :                 10 * cpu_operator_cost)
    3083            0 :                 return NULL;
    3084              :         }
    3085              : 
    3086              :         /* Okay, try to build boundary comparison expressions */
    3087           65 :         if (!lower.infinite)
    3088              :         {
    3089           60 :             lowerExpr = build_bound_expr(elemExpr,
    3090              :                                          lower.val,
    3091              :                                          true,
    3092           60 :                                          lower.inclusive,
    3093              :                                          elemTypcache,
    3094              :                                          opfamily,
    3095              :                                          rng_collation);
    3096           60 :             if (lowerExpr == NULL)
    3097            0 :                 return NULL;
    3098              :         }
    3099              : 
    3100           65 :         if (!upper.infinite)
    3101              :         {
    3102              :             /* Copy the elemExpr if we need two copies */
    3103           55 :             if (!lower.infinite)
    3104           50 :                 elemExpr = copyObject(elemExpr);
    3105           55 :             upperExpr = build_bound_expr(elemExpr,
    3106              :                                          upper.val,
    3107              :                                          false,
    3108           55 :                                          upper.inclusive,
    3109              :                                          elemTypcache,
    3110              :                                          opfamily,
    3111              :                                          rng_collation);
    3112           55 :             if (upperExpr == NULL)
    3113            0 :                 return NULL;
    3114              :         }
    3115              : 
    3116           65 :         if (lowerExpr != NULL && upperExpr != NULL)
    3117           50 :             return (Node *) make_andclause(list_make2(lowerExpr, upperExpr));
    3118           15 :         else if (lowerExpr != NULL)
    3119           10 :             return (Node *) lowerExpr;
    3120            5 :         else if (upperExpr != NULL)
    3121            5 :             return (Node *) upperExpr;
    3122              :         else
    3123              :         {
    3124              :             Assert(false);
    3125            0 :             return NULL;
    3126              :         }
    3127              :     }
    3128              : }
    3129              : 
    3130              : /*
    3131              :  * Helper function for find_simplified_clause().
    3132              :  *
    3133              :  * Build the expression (elemExpr Operator val), where the operator is
    3134              :  * the appropriate member of the given opfamily depending on
    3135              :  * isLowerBound and isInclusive.  typeCache is the typcache entry for
    3136              :  * the "val" value (presently, this will be the same type as elemExpr).
    3137              :  * rng_collation is the collation to use in the comparison.
    3138              :  *
    3139              :  * Return NULL on failure (if, for some reason, we can't find the operator).
    3140              :  */
    3141              : static Expr *
    3142          115 : build_bound_expr(Expr *elemExpr, Datum val,
    3143              :                  bool isLowerBound, bool isInclusive,
    3144              :                  TypeCacheEntry *typeCache,
    3145              :                  Oid opfamily, Oid rng_collation)
    3146              : {
    3147          115 :     Oid         elemType = typeCache->type_id;
    3148          115 :     int16       elemTypeLen = typeCache->typlen;
    3149          115 :     bool        elemByValue = typeCache->typbyval;
    3150          115 :     Oid         elemCollation = typeCache->typcollation;
    3151              :     int16       strategy;
    3152              :     Oid         oproid;
    3153              :     Expr       *constExpr;
    3154              : 
    3155              :     /* Identify the comparison operator to use */
    3156          115 :     if (isLowerBound)
    3157           60 :         strategy = isInclusive ? BTGreaterEqualStrategyNumber : BTGreaterStrategyNumber;
    3158              :     else
    3159           55 :         strategy = isInclusive ? BTLessEqualStrategyNumber : BTLessStrategyNumber;
    3160              : 
    3161              :     /*
    3162              :      * We could use exprType(elemExpr) here, if it ever becomes possible that
    3163              :      * elemExpr is not the exact same type as the range elements.
    3164              :      */
    3165          115 :     oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
    3166              : 
    3167              :     /* We don't really expect failure here, but just in case ... */
    3168          115 :     if (!OidIsValid(oproid))
    3169            0 :         return NULL;
    3170              : 
    3171              :     /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
    3172          115 :     constExpr = (Expr *) makeConst(elemType,
    3173              :                                    -1,
    3174              :                                    elemCollation,
    3175              :                                    elemTypeLen,
    3176              :                                    val,
    3177              :                                    false,
    3178              :                                    elemByValue);
    3179              : 
    3180          115 :     return make_opclause(oproid,
    3181              :                          BOOLOID,
    3182              :                          false,
    3183              :                          elemExpr,
    3184              :                          constExpr,
    3185              :                          InvalidOid,
    3186              :                          rng_collation);
    3187              : }
        

Generated by: LCOV version 2.0-1