LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - rangetypes.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 85.5 % 963 823 11 25 80 24 21 489 71 242 93 544 2 12
Current Date: 2023-04-08 15:15:32 Functions: 90.0 % 80 72 8 72 8 71 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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-2023, 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 "lib/stringinfo.h"
      36                 : #include "libpq/pqformat.h"
      37                 : #include "miscadmin.h"
      38                 : #include "nodes/miscnodes.h"
      39                 : #include "port/pg_bitutils.h"
      40                 : #include "utils/builtins.h"
      41                 : #include "utils/date.h"
      42                 : #include "utils/lsyscache.h"
      43                 : #include "utils/rangetypes.h"
      44                 : #include "utils/timestamp.h"
      45                 : #include "varatt.h"
      46                 : 
      47                 : 
      48                 : /* fn_extra cache entry for one of the range I/O functions */
      49                 : typedef struct RangeIOData
      50                 : {
      51                 :     TypeCacheEntry *typcache;   /* range type's typcache entry */
      52                 :     FmgrInfo    typioproc;      /* element type's I/O function */
      53                 :     Oid         typioparam;     /* element type's I/O parameter */
      54                 : } RangeIOData;
      55                 : 
      56                 : 
      57                 : static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
      58                 :                                       IOFuncSelector func);
      59                 : static char range_parse_flags(const char *flags_str);
      60                 : static bool range_parse(const char *string, char *flags, char **lbound_str,
      61                 :                         char **ubound_str, Node *escontext);
      62                 : static const char *range_parse_bound(const char *string, const char *ptr,
      63                 :                                      char **bound_str, bool *infinite,
      64                 :                                      Node *escontext);
      65                 : static char *range_deparse(char flags, const char *lbound_str,
      66                 :                            const char *ubound_str);
      67                 : static char *range_bound_escape(const char *value);
      68                 : static Size datum_compute_size(Size data_length, Datum val, bool typbyval,
      69                 :                                char typalign, int16 typlen, char typstorage);
      70                 : static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
      71                 :                            char typalign, int16 typlen, char typstorage);
      72                 : 
      73                 : 
      74                 : /*
      75                 :  *----------------------------------------------------------
      76                 :  * I/O FUNCTIONS
      77                 :  *----------------------------------------------------------
      78                 :  */
      79                 : 
      80                 : Datum
      81 GIC        1471 : range_in(PG_FUNCTION_ARGS)
      82                 : {
      83            1471 :     char       *input_str = PG_GETARG_CSTRING(0);
      84 CBC        1471 :     Oid         rngtypoid = PG_GETARG_OID(1);
      85 GIC        1471 :     Oid         typmod = PG_GETARG_INT32(2);
      86 GNC        1471 :     Node       *escontext = fcinfo->context;
      87 ECB             :     RangeType  *range;
      88                 :     RangeIOData *cache;
      89                 :     char        flags;
      90                 :     char       *lbound_str;
      91                 :     char       *ubound_str;
      92                 :     RangeBound  lower;
      93                 :     RangeBound  upper;
      94                 : 
      95 GIC        1471 :     check_stack_depth();        /* recurses when subtype is a range type */
      96                 : 
      97            1471 :     cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
      98                 : 
      99 ECB             :     /* parse */
     100 GNC        1471 :     if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
     101               6 :         PG_RETURN_NULL();
     102 ECB             : 
     103                 :     /* call element type's input function */
     104 GIC        1429 :     if (RANGE_HAS_LBOUND(flags))
     105 GNC        1096 :         if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
     106                 :                                    cache->typioparam, typmod,
     107                 :                                    escontext, &lower.val))
     108 UNC           0 :             PG_RETURN_NULL();
     109 GIC        1429 :     if (RANGE_HAS_UBOUND(flags))
     110 GNC        1048 :         if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
     111                 :                                    cache->typioparam, typmod,
     112                 :                                    escontext, &upper.val))
     113              12 :             PG_RETURN_NULL();
     114 ECB             : 
     115 GIC        1417 :     lower.infinite = (flags & RANGE_LB_INF) != 0;
     116            1417 :     lower.inclusive = (flags & RANGE_LB_INC) != 0;
     117 GBC        1417 :     lower.lower = true;
     118 CBC        1417 :     upper.infinite = (flags & RANGE_UB_INF) != 0;
     119            1417 :     upper.inclusive = (flags & RANGE_UB_INC) != 0;
     120 GIC        1417 :     upper.lower = false;
     121                 : 
     122 ECB             :     /* serialize and canonicalize */
     123 GNC        1417 :     range = make_range(cache->typcache, &lower, &upper,
     124            1417 :                        flags & RANGE_EMPTY, escontext);
     125 ECB             : 
     126 CBC        1408 :     PG_RETURN_RANGE_P(range);
     127 ECB             : }
     128                 : 
     129                 : Datum
     130 CBC       52061 : range_out(PG_FUNCTION_ARGS)
     131                 : {
     132 GIC       52061 :     RangeType  *range = PG_GETARG_RANGE_P(0);
     133 ECB             :     char       *output_str;
     134                 :     RangeIOData *cache;
     135                 :     char        flags;
     136 CBC       52061 :     char       *lbound_str = NULL;
     137 GIC       52061 :     char       *ubound_str = NULL;
     138                 :     RangeBound  lower;
     139                 :     RangeBound  upper;
     140 ECB             :     bool        empty;
     141                 : 
     142 CBC       52061 :     check_stack_depth();        /* recurses when subtype is a range type */
     143                 : 
     144 GIC       52061 :     cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
     145                 : 
     146 ECB             :     /* deserialize */
     147 CBC       52061 :     range_deserialize(cache->typcache, range, &lower, &upper, &empty);
     148 GIC       52061 :     flags = range_get_flags(range);
     149                 : 
     150                 :     /* call element type's output function */
     151           52061 :     if (RANGE_HAS_LBOUND(flags))
     152 CBC       42382 :         lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
     153 GIC       52061 :     if (RANGE_HAS_UBOUND(flags))
     154 CBC       42349 :         ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
     155                 : 
     156                 :     /* construct result string */
     157           52061 :     output_str = range_deparse(flags, lbound_str, ubound_str);
     158 ECB             : 
     159 GIC       52061 :     PG_RETURN_CSTRING(output_str);
     160                 : }
     161 ECB             : 
     162                 : /*
     163                 :  * Binary representation: The first byte is the flags, then the lower bound
     164                 :  * (if present), then the upper bound (if present).  Each bound is represented
     165                 :  * by a 4-byte length header and the binary representation of that bound (as
     166                 :  * returned by a call to the send function for the subtype).
     167                 :  */
     168                 : 
     169                 : Datum
     170 UIC           0 : range_recv(PG_FUNCTION_ARGS)
     171                 : {
     172               0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     173               0 :     Oid         rngtypoid = PG_GETARG_OID(1);
     174               0 :     int32       typmod = PG_GETARG_INT32(2);
     175                 :     RangeType  *range;
     176                 :     RangeIOData *cache;
     177                 :     char        flags;
     178                 :     RangeBound  lower;
     179                 :     RangeBound  upper;
     180 EUB             : 
     181 UIC           0 :     check_stack_depth();        /* recurses when subtype is a range type */
     182 EUB             : 
     183 UBC           0 :     cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
     184 EUB             : 
     185                 :     /* receive the flags... */
     186 UIC           0 :     flags = (unsigned char) pq_getmsgbyte(buf);
     187                 : 
     188                 :     /*
     189                 :      * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
     190                 :      * confuse following tests.  Note that range_serialize will take care of
     191 EUB             :      * cleaning up any inconsistencies in the remaining flags.
     192                 :      */
     193 UBC           0 :     flags &= (RANGE_EMPTY |
     194                 :               RANGE_LB_INC |
     195                 :               RANGE_LB_INF |
     196 EUB             :               RANGE_UB_INC |
     197                 :               RANGE_UB_INF);
     198                 : 
     199                 :     /* receive the bounds ... */
     200 UIC           0 :     if (RANGE_HAS_LBOUND(flags))
     201                 :     {
     202               0 :         uint32      bound_len = pq_getmsgint(buf, 4);
     203 UBC           0 :         const char *bound_data = pq_getmsgbytes(buf, bound_len);
     204                 :         StringInfoData bound_buf;
     205                 : 
     206 UIC           0 :         initStringInfo(&bound_buf);
     207               0 :         appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
     208                 : 
     209               0 :         lower.val = ReceiveFunctionCall(&cache->typioproc,
     210 EUB             :                                         &bound_buf,
     211                 :                                         cache->typioparam,
     212                 :                                         typmod);
     213 UBC           0 :         pfree(bound_buf.data);
     214                 :     }
     215                 :     else
     216               0 :         lower.val = (Datum) 0;
     217 EUB             : 
     218 UIC           0 :     if (RANGE_HAS_UBOUND(flags))
     219 EUB             :     {
     220 UIC           0 :         uint32      bound_len = pq_getmsgint(buf, 4);
     221               0 :         const char *bound_data = pq_getmsgbytes(buf, bound_len);
     222                 :         StringInfoData bound_buf;
     223 EUB             : 
     224 UIC           0 :         initStringInfo(&bound_buf);
     225               0 :         appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
     226 EUB             : 
     227 UIC           0 :         upper.val = ReceiveFunctionCall(&cache->typioproc,
     228 EUB             :                                         &bound_buf,
     229                 :                                         cache->typioparam,
     230                 :                                         typmod);
     231 UBC           0 :         pfree(bound_buf.data);
     232                 :     }
     233                 :     else
     234               0 :         upper.val = (Datum) 0;
     235 EUB             : 
     236 UIC           0 :     pq_getmsgend(buf);
     237 EUB             : 
     238                 :     /* finish constructing RangeBound representation */
     239 UIC           0 :     lower.infinite = (flags & RANGE_LB_INF) != 0;
     240               0 :     lower.inclusive = (flags & RANGE_LB_INC) != 0;
     241 UBC           0 :     lower.lower = true;
     242 UIC           0 :     upper.infinite = (flags & RANGE_UB_INF) != 0;
     243               0 :     upper.inclusive = (flags & RANGE_UB_INC) != 0;
     244 UBC           0 :     upper.lower = false;
     245                 : 
     246 EUB             :     /* serialize and canonicalize */
     247 UNC           0 :     range = make_range(cache->typcache, &lower, &upper,
     248               0 :                        flags & RANGE_EMPTY, NULL);
     249                 : 
     250 UBC           0 :     PG_RETURN_RANGE_P(range);
     251 EUB             : }
     252                 : 
     253                 : Datum
     254 UBC           0 : range_send(PG_FUNCTION_ARGS)
     255 EUB             : {
     256 UIC           0 :     RangeType  *range = PG_GETARG_RANGE_P(0);
     257               0 :     StringInfo  buf = makeStringInfo();
     258 EUB             :     RangeIOData *cache;
     259                 :     char        flags;
     260                 :     RangeBound  lower;
     261                 :     RangeBound  upper;
     262                 :     bool        empty;
     263                 : 
     264 UIC           0 :     check_stack_depth();        /* recurses when subtype is a range type */
     265 EUB             : 
     266 UIC           0 :     cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
     267 EUB             : 
     268                 :     /* deserialize */
     269 UIC           0 :     range_deserialize(cache->typcache, range, &lower, &upper, &empty);
     270               0 :     flags = range_get_flags(range);
     271                 : 
     272                 :     /* construct output */
     273               0 :     pq_begintypsend(buf);
     274                 : 
     275 UBC           0 :     pq_sendbyte(buf, flags);
     276                 : 
     277               0 :     if (RANGE_HAS_LBOUND(flags))
     278                 :     {
     279 UIC           0 :         Datum       bound = PointerGetDatum(SendFunctionCall(&cache->typioproc,
     280 EUB             :                                                              lower.val));
     281 UBC           0 :         uint32      bound_len = VARSIZE(bound) - VARHDRSZ;
     282 UIC           0 :         char       *bound_data = VARDATA(bound);
     283                 : 
     284 UBC           0 :         pq_sendint32(buf, bound_len);
     285 UIC           0 :         pq_sendbytes(buf, bound_data, bound_len);
     286 EUB             :     }
     287                 : 
     288 UBC           0 :     if (RANGE_HAS_UBOUND(flags))
     289                 :     {
     290               0 :         Datum       bound = PointerGetDatum(SendFunctionCall(&cache->typioproc,
     291                 :                                                              upper.val));
     292               0 :         uint32      bound_len = VARSIZE(bound) - VARHDRSZ;
     293               0 :         char       *bound_data = VARDATA(bound);
     294                 : 
     295               0 :         pq_sendint32(buf, bound_len);
     296               0 :         pq_sendbytes(buf, bound_data, bound_len);
     297                 :     }
     298                 : 
     299               0 :     PG_RETURN_BYTEA_P(pq_endtypsend(buf));
     300                 : }
     301 EUB             : 
     302                 : /*
     303                 :  * get_range_io_data: get cached information needed for range type I/O
     304                 :  *
     305                 :  * The range I/O functions need a bit more cached info than other range
     306                 :  * functions, so they store a RangeIOData struct in fn_extra, not just a
     307                 :  * pointer to a type cache entry.
     308                 :  */
     309                 : static RangeIOData *
     310 GBC       53532 : get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
     311                 : {
     312 GIC       53532 :     RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
     313                 : 
     314           53532 :     if (cache == NULL || cache->typcache->type_id != rngtypid)
     315                 :     {
     316                 :         int16       typlen;
     317                 :         bool        typbyval;
     318                 :         char        typalign;
     319                 :         char        typdelim;
     320                 :         Oid         typiofunc;
     321 ECB             : 
     322 GIC        2298 :         cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
     323 ECB             :                                                    sizeof(RangeIOData));
     324 GIC        2298 :         cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
     325 CBC        2298 :         if (cache->typcache->rngelemtype == NULL)
     326 UIC           0 :             elog(ERROR, "type %u is not a range type", rngtypid);
     327                 : 
     328                 :         /* get_type_io_data does more than we need, but is convenient */
     329 GIC        2298 :         get_type_io_data(cache->typcache->rngelemtype->type_id,
     330                 :                          func,
     331                 :                          &typlen,
     332                 :                          &typbyval,
     333 ECB             :                          &typalign,
     334                 :                          &typdelim,
     335                 :                          &cache->typioparam,
     336                 :                          &typiofunc);
     337 EUB             : 
     338 GIC        2298 :         if (!OidIsValid(typiofunc))
     339                 :         {
     340 ECB             :             /* this could only happen for receive or send */
     341 UIC           0 :             if (func == IOFunc_receive)
     342               0 :                 ereport(ERROR,
     343                 :                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
     344                 :                          errmsg("no binary input function available for type %s",
     345                 :                                 format_type_be(cache->typcache->rngelemtype->type_id))));
     346                 :             else
     347               0 :                 ereport(ERROR,
     348                 :                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
     349 ECB             :                          errmsg("no binary output function available for type %s",
     350                 :                                 format_type_be(cache->typcache->rngelemtype->type_id))));
     351                 :         }
     352 GBC        2298 :         fmgr_info_cxt(typiofunc, &cache->typioproc,
     353            2298 :                       fcinfo->flinfo->fn_mcxt);
     354                 : 
     355 GIC        2298 :         fcinfo->flinfo->fn_extra = (void *) cache;
     356                 :     }
     357                 : 
     358 GBC       53532 :     return cache;
     359                 : }
     360                 : 
     361                 : 
     362                 : /*
     363 ECB             :  *----------------------------------------------------------
     364                 :  * GENERIC FUNCTIONS
     365                 :  *----------------------------------------------------------
     366                 :  */
     367                 : 
     368                 : /* Construct standard-form range value from two arguments */
     369                 : Datum
     370 GIC       53973 : range_constructor2(PG_FUNCTION_ARGS)
     371                 : {
     372           53973 :     Datum       arg1 = PG_GETARG_DATUM(0);
     373           53973 :     Datum       arg2 = PG_GETARG_DATUM(1);
     374           53973 :     Oid         rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
     375                 :     RangeType  *range;
     376                 :     TypeCacheEntry *typcache;
     377                 :     RangeBound  lower;
     378                 :     RangeBound  upper;
     379                 : 
     380           53973 :     typcache = range_get_typcache(fcinfo, rngtypid);
     381 ECB             : 
     382 GIC       53973 :     lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
     383 CBC       53973 :     lower.infinite = PG_ARGISNULL(0);
     384           53973 :     lower.inclusive = true;
     385           53973 :     lower.lower = true;
     386                 : 
     387 GIC       53973 :     upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
     388           53973 :     upper.infinite = PG_ARGISNULL(1);
     389           53973 :     upper.inclusive = false;
     390           53973 :     upper.lower = false;
     391 ECB             : 
     392 GNC       53973 :     range = make_range(typcache, &lower, &upper, false, NULL);
     393 ECB             : 
     394 CBC       53955 :     PG_RETURN_RANGE_P(range);
     395 ECB             : }
     396                 : 
     397                 : /* Construct general range value from three arguments */
     398                 : Datum
     399 CBC        2559 : range_constructor3(PG_FUNCTION_ARGS)
     400 ECB             : {
     401 CBC        2559 :     Datum       arg1 = PG_GETARG_DATUM(0);
     402 GIC        2559 :     Datum       arg2 = PG_GETARG_DATUM(1);
     403 CBC        2559 :     Oid         rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
     404                 :     RangeType  *range;
     405 ECB             :     TypeCacheEntry *typcache;
     406                 :     RangeBound  lower;
     407                 :     RangeBound  upper;
     408                 :     char        flags;
     409                 : 
     410 CBC        2559 :     typcache = range_get_typcache(fcinfo, rngtypid);
     411                 : 
     412            2559 :     if (PG_ARGISNULL(2))
     413 LBC           0 :         ereport(ERROR,
     414 ECB             :                 (errcode(ERRCODE_DATA_EXCEPTION),
     415                 :                  errmsg("range constructor flags argument must not be null")));
     416                 : 
     417 GIC        2559 :     flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
     418                 : 
     419            2559 :     lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
     420            2559 :     lower.infinite = PG_ARGISNULL(0);
     421 CBC        2559 :     lower.inclusive = (flags & RANGE_LB_INC) != 0;
     422 GIC        2559 :     lower.lower = true;
     423 ECB             : 
     424 GBC        2559 :     upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
     425 GIC        2559 :     upper.infinite = PG_ARGISNULL(1);
     426            2559 :     upper.inclusive = (flags & RANGE_UB_INC) != 0;
     427            2559 :     upper.lower = false;
     428 ECB             : 
     429 GNC        2559 :     range = make_range(typcache, &lower, &upper, false, NULL);
     430 ECB             : 
     431 CBC        2559 :     PG_RETURN_RANGE_P(range);
     432 ECB             : }
     433                 : 
     434                 : 
     435                 : /* range -> subtype functions */
     436                 : 
     437                 : /* extract lower bound value */
     438                 : Datum
     439 GIC         120 : range_lower(PG_FUNCTION_ARGS)
     440 ECB             : {
     441 GIC         120 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     442 ECB             :     TypeCacheEntry *typcache;
     443                 :     RangeBound  lower;
     444                 :     RangeBound  upper;
     445                 :     bool        empty;
     446                 : 
     447 GIC         120 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     448                 : 
     449             120 :     range_deserialize(typcache, r1, &lower, &upper, &empty);
     450 ECB             : 
     451                 :     /* Return NULL if there's no finite lower bound */
     452 CBC         120 :     if (empty || lower.infinite)
     453 GIC          18 :         PG_RETURN_NULL();
     454                 : 
     455             102 :     PG_RETURN_DATUM(lower.val);
     456                 : }
     457                 : 
     458 ECB             : /* extract upper bound value */
     459                 : Datum
     460 CBC         114 : range_upper(PG_FUNCTION_ARGS)
     461                 : {
     462 GIC         114 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     463 ECB             :     TypeCacheEntry *typcache;
     464                 :     RangeBound  lower;
     465                 :     RangeBound  upper;
     466                 :     bool        empty;
     467                 : 
     468 GIC         114 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     469                 : 
     470             114 :     range_deserialize(typcache, r1, &lower, &upper, &empty);
     471 ECB             : 
     472                 :     /* Return NULL if there's no finite upper bound */
     473 CBC         114 :     if (empty || upper.infinite)
     474 GIC          18 :         PG_RETURN_NULL();
     475                 : 
     476              96 :     PG_RETURN_DATUM(upper.val);
     477                 : }
     478                 : 
     479 ECB             : 
     480                 : /* range -> bool functions */
     481                 : 
     482                 : /* is range empty? */
     483                 : Datum
     484 CBC        1098 : range_empty(PG_FUNCTION_ARGS)
     485 ECB             : {
     486 GIC        1098 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     487 CBC        1098 :     char        flags = range_get_flags(r1);
     488                 : 
     489 GIC        1098 :     PG_RETURN_BOOL(flags & RANGE_EMPTY);
     490                 : }
     491                 : 
     492                 : /* is lower bound inclusive? */
     493                 : Datum
     494              36 : range_lower_inc(PG_FUNCTION_ARGS)
     495 ECB             : {
     496 GIC          36 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     497 CBC          36 :     char        flags = range_get_flags(r1);
     498 ECB             : 
     499 GIC          36 :     PG_RETURN_BOOL(flags & RANGE_LB_INC);
     500 ECB             : }
     501                 : 
     502                 : /* is upper bound inclusive? */
     503                 : Datum
     504 GIC          36 : range_upper_inc(PG_FUNCTION_ARGS)
     505 ECB             : {
     506 GIC          36 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     507 CBC          36 :     char        flags = range_get_flags(r1);
     508 ECB             : 
     509 GIC          36 :     PG_RETURN_BOOL(flags & RANGE_UB_INC);
     510 ECB             : }
     511                 : 
     512                 : /* is lower bound infinite? */
     513                 : Datum
     514 GIC          36 : range_lower_inf(PG_FUNCTION_ARGS)
     515 ECB             : {
     516 GIC          36 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     517 CBC          36 :     char        flags = range_get_flags(r1);
     518 ECB             : 
     519 GIC          36 :     PG_RETURN_BOOL(flags & RANGE_LB_INF);
     520 ECB             : }
     521                 : 
     522                 : /* is upper bound infinite? */
     523                 : Datum
     524 GIC          36 : range_upper_inf(PG_FUNCTION_ARGS)
     525 ECB             : {
     526 GIC          36 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     527 CBC          36 :     char        flags = range_get_flags(r1);
     528 ECB             : 
     529 GIC          36 :     PG_RETURN_BOOL(flags & RANGE_UB_INF);
     530 ECB             : }
     531                 : 
     532                 : 
     533                 : /* range, element -> bool functions */
     534                 : 
     535                 : /* contains? */
     536                 : Datum
     537 CBC       38019 : range_contains_elem(PG_FUNCTION_ARGS)
     538 ECB             : {
     539 GIC       38019 :     RangeType  *r = PG_GETARG_RANGE_P(0);
     540 CBC       38019 :     Datum       val = PG_GETARG_DATUM(1);
     541                 :     TypeCacheEntry *typcache;
     542                 : 
     543 GIC       38019 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
     544                 : 
     545           38019 :     PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
     546                 : }
     547                 : 
     548 ECB             : /* contained by? */
     549                 : Datum
     550 CBC         342 : elem_contained_by_range(PG_FUNCTION_ARGS)
     551 ECB             : {
     552 GIC         342 :     Datum       val = PG_GETARG_DATUM(0);
     553             342 :     RangeType  *r = PG_GETARG_RANGE_P(1);
     554 ECB             :     TypeCacheEntry *typcache;
     555                 : 
     556 CBC         342 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
     557                 : 
     558 GIC         342 :     PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
     559                 : }
     560                 : 
     561 ECB             : 
     562                 : /* range, range -> bool functions */
     563                 : 
     564                 : /* equality (internal version) */
     565                 : bool
     566 GIC       89394 : range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     567 ECB             : {
     568                 :     RangeBound  lower1,
     569                 :                 lower2;
     570                 :     RangeBound  upper1,
     571                 :                 upper2;
     572                 :     bool        empty1,
     573                 :                 empty2;
     574                 : 
     575                 :     /* Different types should be prevented by ANYRANGE matching rules */
     576 GIC       89394 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     577 LBC           0 :         elog(ERROR, "range types do not match");
     578                 : 
     579 GIC       89394 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     580           89394 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     581                 : 
     582           89394 :     if (empty1 && empty2)
     583            6231 :         return true;
     584           83163 :     if (empty1 != empty2)
     585            6756 :         return false;
     586                 : 
     587 CBC       76407 :     if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
     588 GBC       36252 :         return false;
     589                 : 
     590 CBC       40155 :     if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
     591           25171 :         return false;
     592                 : 
     593           14984 :     return true;
     594 ECB             : }
     595                 : 
     596                 : /* equality */
     597                 : Datum
     598 CBC       38622 : range_eq(PG_FUNCTION_ARGS)
     599 ECB             : {
     600 GIC       38622 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     601 CBC       38622 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     602 ECB             :     TypeCacheEntry *typcache;
     603                 : 
     604 CBC       38622 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     605                 : 
     606 GIC       38622 :     PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
     607                 : }
     608                 : 
     609 ECB             : /* inequality (internal version) */
     610                 : bool
     611 LBC           0 : range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     612 ECB             : {
     613 UIC           0 :     return (!range_eq_internal(typcache, r1, r2));
     614                 : }
     615 ECB             : 
     616                 : /* inequality */
     617                 : Datum
     618 UIC           0 : range_ne(PG_FUNCTION_ARGS)
     619                 : {
     620               0 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     621               0 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     622 EUB             :     TypeCacheEntry *typcache;
     623                 : 
     624 UBC           0 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     625                 : 
     626 UIC           0 :     PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
     627                 : }
     628                 : 
     629 EUB             : /* contains? */
     630                 : Datum
     631 GBC       77235 : range_contains(PG_FUNCTION_ARGS)
     632 EUB             : {
     633 GIC       77235 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     634           77235 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     635 EUB             :     TypeCacheEntry *typcache;
     636                 : 
     637 GBC       77235 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     638                 : 
     639 GIC       77235 :     PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
     640                 : }
     641                 : 
     642 ECB             : /* contained by? */
     643                 : Datum
     644 CBC       38454 : range_contained_by(PG_FUNCTION_ARGS)
     645 ECB             : {
     646 GIC       38454 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     647           38454 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     648 ECB             :     TypeCacheEntry *typcache;
     649                 : 
     650 CBC       38454 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     651                 : 
     652 GIC       38454 :     PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
     653                 : }
     654                 : 
     655 ECB             : /* strictly left of? (internal version) */
     656                 : bool
     657 CBC       62944 : range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     658 ECB             : {
     659                 :     RangeBound  lower1,
     660                 :                 lower2;
     661                 :     RangeBound  upper1,
     662                 :                 upper2;
     663                 :     bool        empty1,
     664                 :                 empty2;
     665                 : 
     666                 :     /* Different types should be prevented by ANYRANGE matching rules */
     667 GIC       62944 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     668 LBC           0 :         elog(ERROR, "range types do not match");
     669                 : 
     670 GIC       62944 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     671           62944 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     672                 : 
     673                 :     /* An empty range is neither before nor after any other range */
     674           62944 :     if (empty1 || empty2)
     675            7455 :         return false;
     676                 : 
     677           55489 :     return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
     678 ECB             : }
     679 EUB             : 
     680                 : /* strictly left of? */
     681 ECB             : Datum
     682 CBC       39459 : range_before(PG_FUNCTION_ARGS)
     683                 : {
     684 GIC       39459 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     685 CBC       39459 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     686 ECB             :     TypeCacheEntry *typcache;
     687                 : 
     688 CBC       39459 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     689                 : 
     690 GIC       39459 :     PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
     691                 : }
     692                 : 
     693 ECB             : /* strictly right of? (internal version) */
     694                 : bool
     695 CBC       98402 : range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     696 ECB             : {
     697                 :     RangeBound  lower1,
     698                 :                 lower2;
     699                 :     RangeBound  upper1,
     700                 :                 upper2;
     701                 :     bool        empty1,
     702                 :                 empty2;
     703                 : 
     704                 :     /* Different types should be prevented by ANYRANGE matching rules */
     705 GIC       98402 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     706 LBC           0 :         elog(ERROR, "range types do not match");
     707                 : 
     708 GIC       98402 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     709           98402 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     710                 : 
     711                 :     /* An empty range is neither before nor after any other range */
     712           98402 :     if (empty1 || empty2)
     713            7155 :         return false;
     714                 : 
     715           91247 :     return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
     716 ECB             : }
     717 EUB             : 
     718                 : /* strictly right of? */
     719 ECB             : Datum
     720 CBC       39153 : range_after(PG_FUNCTION_ARGS)
     721                 : {
     722 GIC       39153 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     723 CBC       39153 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     724 ECB             :     TypeCacheEntry *typcache;
     725                 : 
     726 CBC       39153 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     727                 : 
     728 GIC       39153 :     PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
     729                 : }
     730                 : 
     731 ECB             : /*
     732                 :  * Check if two bounds A and B are "adjacent", where A is an upper bound and B
     733                 :  * is a lower bound. For the bounds to be adjacent, each subtype value must
     734                 :  * satisfy strictly one of the bounds: there are no values which satisfy both
     735                 :  * bounds (i.e. less than A and greater than B); and there are no values which
     736                 :  * satisfy neither bound (i.e. greater than A and less than B).
     737                 :  *
     738                 :  * For discrete ranges, we rely on the canonicalization function to see if A..B
     739                 :  * normalizes to empty. (If there is no canonicalization function, it's
     740                 :  * impossible for such a range to normalize to empty, so we needn't bother to
     741                 :  * try.)
     742                 :  *
     743                 :  * If A == B, the ranges are adjacent only if the bounds have different
     744                 :  * inclusive flags (i.e., exactly one of the ranges includes the common
     745                 :  * boundary point).
     746                 :  *
     747                 :  * And if A > B then the ranges are not adjacent in this order.
     748                 :  */
     749                 : bool
     750 GIC      236310 : bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
     751                 : {
     752                 :     int         cmp;
     753                 : 
     754          236310 :     Assert(!boundA.lower && boundB.lower);
     755                 : 
     756          236310 :     cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
     757          236310 :     if (cmp < 0)
     758                 :     {
     759                 :         RangeType  *r;
     760                 : 
     761 ECB             :         /*
     762                 :          * Bounds do not overlap; see if there are points in between.
     763                 :          */
     764                 : 
     765                 :         /* in a continuous subtype, there are assumed to be points between */
     766 GIC       72527 :         if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
     767 CBC         408 :             return false;
     768 ECB             : 
     769                 :         /*
     770                 :          * The bounds are of a discrete range type; so make a range A..B and
     771                 :          * see if it's empty.
     772                 :          */
     773                 : 
     774                 :         /* flip the inclusion flags */
     775 GIC       72119 :         boundA.inclusive = !boundA.inclusive;
     776           72119 :         boundB.inclusive = !boundB.inclusive;
     777 ECB             :         /* change upper/lower labels to avoid Assert failures */
     778 CBC       72119 :         boundA.lower = true;
     779 GIC       72119 :         boundB.lower = false;
     780 GNC       72119 :         r = make_range(typcache, &boundA, &boundB, false, NULL);
     781 GIC       72119 :         return RangeIsEmpty(r);
     782                 :     }
     783          163783 :     else if (cmp == 0)
     784             873 :         return boundA.inclusive != boundB.inclusive;
     785                 :     else
     786 CBC      162910 :         return false;           /* bounds overlap */
     787 ECB             : }
     788                 : 
     789                 : /* adjacent to (but not overlapping)? (internal version) */
     790                 : bool
     791 CBC       71402 : range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     792 ECB             : {
     793                 :     RangeBound  lower1,
     794                 :                 lower2;
     795                 :     RangeBound  upper1,
     796                 :                 upper2;
     797                 :     bool        empty1,
     798                 :                 empty2;
     799                 : 
     800                 :     /* Different types should be prevented by ANYRANGE matching rules */
     801 GIC       71402 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     802 LBC           0 :         elog(ERROR, "range types do not match");
     803                 : 
     804 GIC       71402 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     805           71402 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     806                 : 
     807                 :     /* An empty range is not adjacent to any other range */
     808           71402 :     if (empty1 || empty2)
     809            6000 :         return false;
     810                 : 
     811                 :     /*
     812 ECB             :      * Given two ranges A..B and C..D, the ranges are adjacent if and only if
     813 EUB             :      * B is adjacent to C, or D is adjacent to A.
     814                 :      */
     815 CBC      130123 :     return (bounds_adjacent(typcache, upper1, lower2) ||
     816           64721 :             bounds_adjacent(typcache, upper2, lower1));
     817                 : }
     818                 : 
     819 ECB             : /* adjacent to (but not overlapping)? */
     820                 : Datum
     821 GIC       37218 : range_adjacent(PG_FUNCTION_ARGS)
     822                 : {
     823           37218 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     824           37218 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     825                 :     TypeCacheEntry *typcache;
     826 ECB             : 
     827 CBC       37218 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     828                 : 
     829 GIC       37218 :     PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
     830                 : }
     831                 : 
     832 ECB             : /* overlaps? (internal version) */
     833                 : bool
     834 CBC       48353 : range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     835 ECB             : {
     836                 :     RangeBound  lower1,
     837                 :                 lower2;
     838                 :     RangeBound  upper1,
     839                 :                 upper2;
     840                 :     bool        empty1,
     841                 :                 empty2;
     842                 : 
     843                 :     /* Different types should be prevented by ANYRANGE matching rules */
     844 GIC       48353 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     845 LBC           0 :         elog(ERROR, "range types do not match");
     846                 : 
     847 GIC       48353 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     848           48353 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     849                 : 
     850                 :     /* An empty range does not overlap any other range */
     851           48353 :     if (empty1 || empty2)
     852            7044 :         return false;
     853                 : 
     854           79669 :     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
     855 CBC       38360 :         range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
     856 GBC        1341 :         return true;
     857                 : 
     858 CBC       42917 :     if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
     859            2949 :         range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
     860 GIC        2901 :         return true;
     861                 : 
     862 CBC       37067 :     return false;
     863 ECB             : }
     864                 : 
     865                 : /* overlaps? */
     866                 : Datum
     867 CBC       38705 : range_overlaps(PG_FUNCTION_ARGS)
     868                 : {
     869           38705 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     870           38705 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     871 ECB             :     TypeCacheEntry *typcache;
     872                 : 
     873 CBC       38705 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     874                 : 
     875 GIC       38705 :     PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
     876                 : }
     877                 : 
     878 ECB             : /* does not extend to right of? (internal version) */
     879                 : bool
     880 CBC       65695 : range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     881 ECB             : {
     882                 :     RangeBound  lower1,
     883                 :                 lower2;
     884                 :     RangeBound  upper1,
     885                 :                 upper2;
     886                 :     bool        empty1,
     887                 :                 empty2;
     888                 : 
     889                 :     /* Different types should be prevented by ANYRANGE matching rules */
     890 GIC       65695 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     891 LBC           0 :         elog(ERROR, "range types do not match");
     892                 : 
     893 GIC       65695 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     894           65695 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     895                 : 
     896                 :     /* An empty range is neither before nor after any other range */
     897           65695 :     if (empty1 || empty2)
     898            6573 :         return false;
     899                 : 
     900           59122 :     if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
     901 CBC       20309 :         return true;
     902 EUB             : 
     903 GIC       38813 :     return false;
     904 ECB             : }
     905                 : 
     906                 : /* does not extend to right of? */
     907                 : Datum
     908 CBC       38253 : range_overleft(PG_FUNCTION_ARGS)
     909 ECB             : {
     910 GIC       38253 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     911 CBC       38253 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     912 ECB             :     TypeCacheEntry *typcache;
     913                 : 
     914 CBC       38253 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     915                 : 
     916 GIC       38253 :     PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
     917                 : }
     918                 : 
     919 ECB             : /* does not extend to left of? (internal version) */
     920                 : bool
     921 CBC      109035 : range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
     922 ECB             : {
     923                 :     RangeBound  lower1,
     924                 :                 lower2;
     925                 :     RangeBound  upper1,
     926                 :                 upper2;
     927                 :     bool        empty1,
     928                 :                 empty2;
     929                 : 
     930                 :     /* Different types should be prevented by ANYRANGE matching rules */
     931 GIC      109035 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     932 LBC           0 :         elog(ERROR, "range types do not match");
     933                 : 
     934 GIC      109035 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
     935          109035 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
     936                 : 
     937                 :     /* An empty range is neither before nor after any other range */
     938          109035 :     if (empty1 || empty2)
     939            6573 :         return false;
     940                 : 
     941          102462 :     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
     942 CBC       95487 :         return true;
     943 EUB             : 
     944 GIC        6975 :     return false;
     945 ECB             : }
     946                 : 
     947                 : /* does not extend to left of? */
     948                 : Datum
     949 CBC       38250 : range_overright(PG_FUNCTION_ARGS)
     950 ECB             : {
     951 GIC       38250 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     952 CBC       38250 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     953 ECB             :     TypeCacheEntry *typcache;
     954                 : 
     955 CBC       38250 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     956                 : 
     957 GIC       38250 :     PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
     958                 : }
     959                 : 
     960 ECB             : 
     961                 : /* range, range -> range functions */
     962                 : 
     963                 : /* set difference */
     964                 : Datum
     965 GIC          15 : range_minus(PG_FUNCTION_ARGS)
     966 ECB             : {
     967 GIC          15 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
     968 CBC          15 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
     969                 :     RangeType  *ret;
     970                 :     TypeCacheEntry *typcache;
     971                 : 
     972                 :     /* Different types should be prevented by ANYRANGE matching rules */
     973 GIC          15 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
     974 UIC           0 :         elog(ERROR, "range types do not match");
     975                 : 
     976 CBC          15 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
     977                 : 
     978              15 :     ret = range_minus_internal(typcache, r1, r2);
     979              15 :     if (ret)
     980 GIC          15 :         PG_RETURN_RANGE_P(ret);
     981                 :     else
     982 UIC           0 :         PG_RETURN_NULL();
     983                 : }
     984 ECB             : 
     985 EUB             : RangeType *
     986 GIC          48 : range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
     987 ECB             : {
     988                 :     RangeBound  lower1,
     989                 :                 lower2;
     990                 :     RangeBound  upper1,
     991                 :                 upper2;
     992                 :     bool        empty1,
     993 EUB             :                 empty2;
     994                 :     int         cmp_l1l2,
     995                 :                 cmp_l1u2,
     996                 :                 cmp_u1l2,
     997 ECB             :                 cmp_u1u2;
     998                 : 
     999 GIC          48 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1000              48 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1001                 : 
    1002                 :     /* if either is empty, r1 is the correct answer */
    1003              48 :     if (empty1 || empty2)
    1004 UIC           0 :         return r1;
    1005                 : 
    1006 GIC          48 :     cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
    1007              48 :     cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
    1008              48 :     cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
    1009              48 :     cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
    1010 ECB             : 
    1011 CBC          48 :     if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
    1012 UIC           0 :         ereport(ERROR,
    1013                 :                 (errcode(ERRCODE_DATA_EXCEPTION),
    1014 ECB             :                  errmsg("result of range difference would not be contiguous")));
    1015 EUB             : 
    1016 GIC          48 :     if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
    1017 CBC           6 :         return r1;
    1018 ECB             : 
    1019 CBC          42 :     if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
    1020              21 :         return make_empty_range(typcache);
    1021                 : 
    1022              21 :     if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
    1023 EUB             :     {
    1024 GIC          12 :         lower2.inclusive = !lower2.inclusive;
    1025              12 :         lower2.lower = false;   /* it will become the upper bound */
    1026 GNC          12 :         return make_range(typcache, &lower1, &lower2, false, NULL);
    1027 ECB             :     }
    1028                 : 
    1029 GIC           9 :     if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
    1030 ECB             :     {
    1031 CBC           9 :         upper2.inclusive = !upper2.inclusive;
    1032 GIC           9 :         upper2.lower = true;    /* it will become the lower bound */
    1033 GNC           9 :         return make_range(typcache, &upper2, &upper1, false, NULL);
    1034                 :     }
    1035 ECB             : 
    1036 LBC           0 :     elog(ERROR, "unexpected case in range_minus");
    1037 ECB             :     return NULL;
    1038                 : }
    1039                 : 
    1040                 : /*
    1041                 :  * Set union.  If strict is true, it is an error that the two input ranges
    1042                 :  * are not adjacent or overlapping.
    1043                 :  */
    1044                 : RangeType *
    1045 GIC         714 : range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
    1046                 :                      bool strict)
    1047 EUB             : {
    1048                 :     RangeBound  lower1,
    1049                 :                 lower2;
    1050                 :     RangeBound  upper1,
    1051                 :                 upper2;
    1052                 :     bool        empty1,
    1053                 :                 empty2;
    1054                 :     RangeBound *result_lower;
    1055                 :     RangeBound *result_upper;
    1056 ECB             : 
    1057                 :     /* Different types should be prevented by ANYRANGE matching rules */
    1058 GIC         714 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1059 UIC           0 :         elog(ERROR, "range types do not match");
    1060                 : 
    1061 GIC         714 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1062             714 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1063                 : 
    1064                 :     /* if either is empty, the other is the correct answer */
    1065             714 :     if (empty1)
    1066               3 :         return r2;
    1067             711 :     if (empty2)
    1068 UIC           0 :         return r1;
    1069 ECB             : 
    1070 GBC         711 :     if (strict &&
    1071 GIC          69 :         !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
    1072 CBC           6 :         !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
    1073               3 :         ereport(ERROR,
    1074                 :                 (errcode(ERRCODE_DATA_EXCEPTION),
    1075                 :                  errmsg("result of range union would not be contiguous")));
    1076 ECB             : 
    1077 CBC         708 :     if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
    1078             690 :         result_lower = &lower1;
    1079 EUB             :     else
    1080 GIC          18 :         result_lower = &lower2;
    1081 ECB             : 
    1082 CBC         708 :     if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
    1083              24 :         result_upper = &upper1;
    1084 ECB             :     else
    1085 GIC         684 :         result_upper = &upper2;
    1086                 : 
    1087 GNC         708 :     return make_range(typcache, result_lower, result_upper, false, NULL);
    1088 ECB             : }
    1089                 : 
    1090                 : Datum
    1091 CBC           9 : range_union(PG_FUNCTION_ARGS)
    1092                 : {
    1093               9 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1094               9 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1095                 :     TypeCacheEntry *typcache;
    1096 ECB             : 
    1097 GIC           9 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1098 ECB             : 
    1099 GIC           9 :     PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
    1100                 : }
    1101                 : 
    1102 ECB             : /*
    1103                 :  * range merge: like set union, except also allow and account for non-adjacent
    1104                 :  * input ranges.
    1105                 :  */
    1106                 : Datum
    1107 GIC          15 : range_merge(PG_FUNCTION_ARGS)
    1108 ECB             : {
    1109 GIC          15 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1110 CBC          15 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1111                 :     TypeCacheEntry *typcache;
    1112                 : 
    1113 GIC          15 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1114                 : 
    1115              15 :     PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
    1116                 : }
    1117                 : 
    1118 ECB             : /* set intersection */
    1119                 : Datum
    1120 CBC           9 : range_intersect(PG_FUNCTION_ARGS)
    1121 ECB             : {
    1122 GIC           9 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1123               9 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1124 ECB             :     TypeCacheEntry *typcache;
    1125                 : 
    1126                 :     /* Different types should be prevented by ANYRANGE matching rules */
    1127 GIC           9 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1128 UIC           0 :         elog(ERROR, "range types do not match");
    1129                 : 
    1130 GIC           9 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1131 ECB             : 
    1132 GIC           9 :     PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
    1133 ECB             : }
    1134                 : 
    1135                 : RangeType *
    1136 GIC         108 : range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
    1137                 : {
    1138 ECB             :     RangeBound  lower1,
    1139 EUB             :                 lower2;
    1140                 :     RangeBound  upper1,
    1141 ECB             :                 upper2;
    1142                 :     bool        empty1,
    1143                 :                 empty2;
    1144                 :     RangeBound *result_lower;
    1145                 :     RangeBound *result_upper;
    1146                 : 
    1147 CBC         108 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1148 GIC         108 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1149                 : 
    1150             108 :     if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
    1151              15 :         return make_empty_range(typcache);
    1152                 : 
    1153              93 :     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
    1154              45 :         result_lower = &lower1;
    1155                 :     else
    1156              48 :         result_lower = &lower2;
    1157                 : 
    1158 CBC          93 :     if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
    1159              63 :         result_upper = &upper1;
    1160                 :     else
    1161              30 :         result_upper = &upper2;
    1162 ECB             : 
    1163 GNC          93 :     return make_range(typcache, result_lower, result_upper, false, NULL);
    1164 ECB             : }
    1165                 : 
    1166                 : /* range, range -> range, range functions */
    1167                 : 
    1168                 : /*
    1169                 :  * range_split_internal - if r2 intersects the middle of r1, leaving non-empty
    1170                 :  * ranges on both sides, then return true and set output1 and output2 to the
    1171                 :  * results of r1 - r2 (in order). Otherwise return false and don't set output1
    1172                 :  * or output2. Neither input range should be empty.
    1173                 :  */
    1174                 : bool
    1175 GIC          66 : range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2,
    1176                 :                      RangeType **output1, RangeType **output2)
    1177                 : {
    1178                 :     RangeBound  lower1,
    1179                 :                 lower2;
    1180                 :     RangeBound  upper1,
    1181                 :                 upper2;
    1182                 :     bool        empty1,
    1183                 :                 empty2;
    1184                 : 
    1185              66 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1186 CBC          66 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1187                 : 
    1188 GIC         105 :     if (range_cmp_bounds(typcache, &lower1, &lower2) < 0 &&
    1189              39 :         range_cmp_bounds(typcache, &upper1, &upper2) > 0)
    1190                 :     {
    1191                 :         /*
    1192                 :          * Need to invert inclusive/exclusive for the lower2 and upper2
    1193                 :          * points. They can't be infinite though. We're allowed to overwrite
    1194                 :          * these RangeBounds since they only exist locally.
    1195                 :          */
    1196 CBC           9 :         lower2.inclusive = !lower2.inclusive;
    1197               9 :         lower2.lower = false;
    1198 GIC           9 :         upper2.inclusive = !upper2.inclusive;
    1199 CBC           9 :         upper2.lower = true;
    1200 ECB             : 
    1201 GNC           9 :         *output1 = make_range(typcache, &lower1, &lower2, false, NULL);
    1202               9 :         *output2 = make_range(typcache, &upper2, &upper1, false, NULL);
    1203 GIC           9 :         return true;
    1204                 :     }
    1205                 : 
    1206              57 :     return false;
    1207 ECB             : }
    1208                 : 
    1209                 : /* range -> range aggregate functions */
    1210                 : 
    1211                 : Datum
    1212 CBC          21 : range_intersect_agg_transfn(PG_FUNCTION_ARGS)
    1213 ECB             : {
    1214                 :     MemoryContext aggContext;
    1215                 :     Oid         rngtypoid;
    1216                 :     TypeCacheEntry *typcache;
    1217                 :     RangeType  *result;
    1218                 :     RangeType  *current;
    1219                 : 
    1220 GIC          21 :     if (!AggCheckCallContext(fcinfo, &aggContext))
    1221 UIC           0 :         elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
    1222                 : 
    1223 CBC          21 :     rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
    1224 GIC          21 :     if (!type_is_range(rngtypoid))
    1225 UIC           0 :         elog(ERROR, "range_intersect_agg must be called with a range");
    1226                 : 
    1227 GIC          21 :     typcache = range_get_typcache(fcinfo, rngtypoid);
    1228                 : 
    1229                 :     /* strictness ensures these are non-null */
    1230              21 :     result = PG_GETARG_RANGE_P(0);
    1231 CBC          21 :     current = PG_GETARG_RANGE_P(1);
    1232 EUB             : 
    1233 GIC          21 :     result = range_intersect_internal(typcache, result, current);
    1234 CBC          21 :     PG_RETURN_RANGE_P(result);
    1235 ECB             : }
    1236 EUB             : 
    1237                 : 
    1238 ECB             : /* Btree support */
    1239                 : 
    1240                 : /* btree comparator */
    1241                 : Datum
    1242 CBC        5511 : range_cmp(PG_FUNCTION_ARGS)
    1243                 : {
    1244            5511 :     RangeType  *r1 = PG_GETARG_RANGE_P(0);
    1245            5511 :     RangeType  *r2 = PG_GETARG_RANGE_P(1);
    1246                 :     TypeCacheEntry *typcache;
    1247                 :     RangeBound  lower1,
    1248                 :                 lower2;
    1249                 :     RangeBound  upper1,
    1250                 :                 upper2;
    1251                 :     bool        empty1,
    1252                 :                 empty2;
    1253 ECB             :     int         cmp;
    1254                 : 
    1255 CBC        5511 :     check_stack_depth();        /* recurses when subtype is a range type */
    1256 ECB             : 
    1257                 :     /* Different types should be prevented by ANYRANGE matching rules */
    1258 GIC        5511 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    1259 UIC           0 :         elog(ERROR, "range types do not match");
    1260                 : 
    1261 GIC        5511 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
    1262                 : 
    1263            5511 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    1264            5511 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    1265                 : 
    1266 ECB             :     /* For b-tree use, empty ranges sort before all else */
    1267 GIC        5511 :     if (empty1 && empty2)
    1268            1320 :         cmp = 0;
    1269 CBC        4191 :     else if (empty1)
    1270 GBC        1740 :         cmp = -1;
    1271 GIC        2451 :     else if (empty2)
    1272 CBC        1065 :         cmp = 1;
    1273                 :     else
    1274 ECB             :     {
    1275 CBC        1386 :         cmp = range_cmp_bounds(typcache, &lower1, &lower2);
    1276 GIC        1386 :         if (cmp == 0)
    1277              54 :             cmp = range_cmp_bounds(typcache, &upper1, &upper2);
    1278 ECB             :     }
    1279                 : 
    1280 CBC        5511 :     PG_FREE_IF_COPY(r1, 0);
    1281            5511 :     PG_FREE_IF_COPY(r2, 1);
    1282 ECB             : 
    1283 CBC        5511 :     PG_RETURN_INT32(cmp);
    1284                 : }
    1285                 : 
    1286 ECB             : /* inequality operators using the range_cmp function */
    1287                 : Datum
    1288 CBC         669 : range_lt(PG_FUNCTION_ARGS)
    1289                 : {
    1290 GIC         669 :     int         cmp = range_cmp(fcinfo);
    1291 ECB             : 
    1292 CBC         669 :     PG_RETURN_BOOL(cmp < 0);
    1293                 : }
    1294 ECB             : 
    1295                 : Datum
    1296 GIC        1506 : range_le(PG_FUNCTION_ARGS)
    1297                 : {
    1298            1506 :     int         cmp = range_cmp(fcinfo);
    1299 ECB             : 
    1300 GIC        1506 :     PG_RETURN_BOOL(cmp <= 0);
    1301 ECB             : }
    1302                 : 
    1303                 : Datum
    1304 GIC        1518 : range_ge(PG_FUNCTION_ARGS)
    1305                 : {
    1306            1518 :     int         cmp = range_cmp(fcinfo);
    1307 ECB             : 
    1308 GIC        1518 :     PG_RETURN_BOOL(cmp >= 0);
    1309 ECB             : }
    1310                 : 
    1311                 : Datum
    1312 GIC        1536 : range_gt(PG_FUNCTION_ARGS)
    1313                 : {
    1314            1536 :     int         cmp = range_cmp(fcinfo);
    1315 ECB             : 
    1316 GIC        1536 :     PG_RETURN_BOOL(cmp > 0);
    1317 ECB             : }
    1318                 : 
    1319                 : /* Hash support */
    1320                 : 
    1321                 : /* hash a range value */
    1322                 : Datum
    1323 CBC         105 : hash_range(PG_FUNCTION_ARGS)
    1324                 : {
    1325             105 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1326                 :     uint32      result;
    1327 ECB             :     TypeCacheEntry *typcache;
    1328                 :     TypeCacheEntry *scache;
    1329                 :     RangeBound  lower;
    1330                 :     RangeBound  upper;
    1331                 :     bool        empty;
    1332                 :     char        flags;
    1333                 :     uint32      lower_hash;
    1334                 :     uint32      upper_hash;
    1335                 : 
    1336 CBC         105 :     check_stack_depth();        /* recurses when subtype is a range type */
    1337                 : 
    1338 GIC         105 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1339                 : 
    1340                 :     /* deserialize */
    1341             105 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1342             105 :     flags = range_get_flags(r);
    1343                 : 
    1344                 :     /*
    1345                 :      * Look up the element type's hash function, if not done already.
    1346                 :      */
    1347 CBC         105 :     scache = typcache->rngelemtype;
    1348 GIC         105 :     if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
    1349 ECB             :     {
    1350 GIC           3 :         scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
    1351               3 :         if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
    1352 LBC           0 :             ereport(ERROR,
    1353 ECB             :                     (errcode(ERRCODE_UNDEFINED_FUNCTION),
    1354                 :                      errmsg("could not identify a hash function for type %s",
    1355                 :                             format_type_be(scache->type_id))));
    1356                 :     }
    1357                 : 
    1358                 :     /*
    1359                 :      * Apply the hash function to each bound.
    1360                 :      */
    1361 CBC         105 :     if (RANGE_HAS_LBOUND(flags))
    1362              72 :         lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
    1363 EUB             :                                                       typcache->rng_collation,
    1364                 :                                                       lower.val));
    1365                 :     else
    1366 GIC          33 :         lower_hash = 0;
    1367                 : 
    1368             105 :     if (RANGE_HAS_UBOUND(flags))
    1369              78 :         upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
    1370                 :                                                       typcache->rng_collation,
    1371                 :                                                       upper.val));
    1372 ECB             :     else
    1373 CBC          27 :         upper_hash = 0;
    1374                 : 
    1375                 :     /* Merge hashes of flags and bounds */
    1376 GIC         105 :     result = hash_uint32((uint32) flags);
    1377 CBC         105 :     result ^= lower_hash;
    1378 GIC         105 :     result = pg_rotate_left32(result, 1);
    1379 CBC         105 :     result ^= upper_hash;
    1380 ECB             : 
    1381 GIC         105 :     PG_RETURN_INT32(result);
    1382                 : }
    1383                 : 
    1384 ECB             : /*
    1385                 :  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
    1386                 :  * Otherwise, similar to hash_range.
    1387                 :  */
    1388                 : Datum
    1389 CBC          30 : hash_range_extended(PG_FUNCTION_ARGS)
    1390 ECB             : {
    1391 GIC          30 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1392 CBC          30 :     Datum       seed = PG_GETARG_DATUM(1);
    1393                 :     uint64      result;
    1394                 :     TypeCacheEntry *typcache;
    1395                 :     TypeCacheEntry *scache;
    1396                 :     RangeBound  lower;
    1397                 :     RangeBound  upper;
    1398                 :     bool        empty;
    1399                 :     char        flags;
    1400 ECB             :     uint64      lower_hash;
    1401                 :     uint64      upper_hash;
    1402                 : 
    1403 CBC          30 :     check_stack_depth();
    1404                 : 
    1405 GIC          30 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1406                 : 
    1407              30 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1408              30 :     flags = range_get_flags(r);
    1409                 : 
    1410              30 :     scache = typcache->rngelemtype;
    1411              30 :     if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
    1412                 :     {
    1413 UIC           0 :         scache = lookup_type_cache(scache->type_id,
    1414 ECB             :                                    TYPECACHE_HASH_EXTENDED_PROC_FINFO);
    1415 UIC           0 :         if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
    1416 LBC           0 :             ereport(ERROR,
    1417                 :                     (errcode(ERRCODE_UNDEFINED_FUNCTION),
    1418 ECB             :                      errmsg("could not identify a hash function for type %s",
    1419                 :                             format_type_be(scache->type_id))));
    1420                 :     }
    1421                 : 
    1422 CBC          30 :     if (RANGE_HAS_LBOUND(flags))
    1423 GIC          30 :         lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
    1424 EUB             :                                                       typcache->rng_collation,
    1425                 :                                                       lower.val,
    1426                 :                                                       seed));
    1427                 :     else
    1428 UIC           0 :         lower_hash = 0;
    1429                 : 
    1430 GIC          30 :     if (RANGE_HAS_UBOUND(flags))
    1431              30 :         upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
    1432                 :                                                       typcache->rng_collation,
    1433 ECB             :                                                       upper.val,
    1434                 :                                                       seed));
    1435                 :     else
    1436 UIC           0 :         upper_hash = 0;
    1437                 : 
    1438                 :     /* Merge hashes of flags and bounds */
    1439 GBC          30 :     result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
    1440 GIC          30 :                                                  DatumGetInt64(seed)));
    1441 CBC          30 :     result ^= lower_hash;
    1442              30 :     result = ROTATE_HIGH_AND_LOW_32BITS(result);
    1443 GIC          30 :     result ^= upper_hash;
    1444                 : 
    1445              30 :     PG_RETURN_UINT64(result);
    1446                 : }
    1447 EUB             : 
    1448                 : /*
    1449                 :  *----------------------------------------------------------
    1450 ECB             :  * CANONICAL FUNCTIONS
    1451                 :  *
    1452                 :  *   Functions for specific built-in range types.
    1453                 :  *----------------------------------------------------------
    1454                 :  */
    1455                 : 
    1456                 : Datum
    1457 GIC      231834 : int4range_canonical(PG_FUNCTION_ARGS)
    1458                 : {
    1459          231834 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1460 GNC      231834 :     Node       *escontext = fcinfo->context;
    1461                 :     TypeCacheEntry *typcache;
    1462                 :     RangeBound  lower;
    1463                 :     RangeBound  upper;
    1464                 :     bool        empty;
    1465                 : 
    1466 GIC      231834 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1467                 : 
    1468          231834 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1469 ECB             : 
    1470 GIC      231834 :     if (empty)
    1471 LBC           0 :         PG_RETURN_RANGE_P(r);
    1472 ECB             : 
    1473 GIC      231834 :     if (!lower.infinite && !lower.inclusive)
    1474                 :     {
    1475 GNC        1624 :         int32       bnd = DatumGetInt32(lower.val);
    1476                 : 
    1477                 :         /* Handle possible overflow manually */
    1478            1624 :         if (unlikely(bnd == PG_INT32_MAX))
    1479 UNC           0 :             ereturn(escontext, (Datum) 0,
    1480                 :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1481                 :                      errmsg("integer out of range")));
    1482 GNC        1624 :         lower.val = Int32GetDatum(bnd + 1);
    1483 GIC        1624 :         lower.inclusive = true;
    1484                 :     }
    1485 ECB             : 
    1486 GIC      231834 :     if (!upper.infinite && upper.inclusive)
    1487 ECB             :     {
    1488 GNC        1609 :         int32       bnd = DatumGetInt32(upper.val);
    1489                 : 
    1490                 :         /* Handle possible overflow manually */
    1491            1609 :         if (unlikely(bnd == PG_INT32_MAX))
    1492               6 :             ereturn(escontext, (Datum) 0,
    1493                 :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1494                 :                      errmsg("integer out of range")));
    1495            1603 :         upper.val = Int32GetDatum(bnd + 1);
    1496 CBC        1603 :         upper.inclusive = false;
    1497 EUB             :     }
    1498                 : 
    1499 GNC      231828 :     PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
    1500                 :                                       false, escontext));
    1501                 : }
    1502 ECB             : 
    1503                 : Datum
    1504 GIC          43 : int8range_canonical(PG_FUNCTION_ARGS)
    1505 ECB             : {
    1506 GBC          43 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1507 GNC          43 :     Node       *escontext = fcinfo->context;
    1508                 :     TypeCacheEntry *typcache;
    1509                 :     RangeBound  lower;
    1510 ECB             :     RangeBound  upper;
    1511                 :     bool        empty;
    1512                 : 
    1513 GIC          43 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1514 ECB             : 
    1515 GIC          43 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1516 ECB             : 
    1517 GIC          43 :     if (empty)
    1518 UIC           0 :         PG_RETURN_RANGE_P(r);
    1519 ECB             : 
    1520 CBC          43 :     if (!lower.infinite && !lower.inclusive)
    1521                 :     {
    1522 GNC           9 :         int64       bnd = DatumGetInt64(lower.val);
    1523                 : 
    1524                 :         /* Handle possible overflow manually */
    1525               9 :         if (unlikely(bnd == PG_INT64_MAX))
    1526 UNC           0 :             ereturn(escontext, (Datum) 0,
    1527                 :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1528                 :                      errmsg("bigint out of range")));
    1529 GNC           9 :         lower.val = Int64GetDatum(bnd + 1);
    1530 CBC           9 :         lower.inclusive = true;
    1531 ECB             :     }
    1532                 : 
    1533 GIC          43 :     if (!upper.infinite && upper.inclusive)
    1534 ECB             :     {
    1535 GNC          12 :         int64       bnd = DatumGetInt64(upper.val);
    1536                 : 
    1537                 :         /* Handle possible overflow manually */
    1538              12 :         if (unlikely(bnd == PG_INT64_MAX))
    1539 UNC           0 :             ereturn(escontext, (Datum) 0,
    1540                 :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1541                 :                      errmsg("bigint out of range")));
    1542 GNC          12 :         upper.val = Int64GetDatum(bnd + 1);
    1543 GIC          12 :         upper.inclusive = false;
    1544                 :     }
    1545                 : 
    1546 GNC          43 :     PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
    1547                 :                                       false, escontext));
    1548                 : }
    1549 ECB             : 
    1550                 : Datum
    1551 GIC          81 : daterange_canonical(PG_FUNCTION_ARGS)
    1552                 : {
    1553              81 :     RangeType  *r = PG_GETARG_RANGE_P(0);
    1554 GNC          81 :     Node       *escontext = fcinfo->context;
    1555                 :     TypeCacheEntry *typcache;
    1556                 :     RangeBound  lower;
    1557 ECB             :     RangeBound  upper;
    1558                 :     bool        empty;
    1559                 : 
    1560 GIC          81 :     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
    1561 ECB             : 
    1562 GBC          81 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    1563                 : 
    1564 CBC          81 :     if (empty)
    1565 UIC           0 :         PG_RETURN_RANGE_P(r);
    1566 ECB             : 
    1567 GIC          81 :     if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
    1568              75 :         !lower.inclusive)
    1569 ECB             :     {
    1570 GNC          18 :         DateADT     bnd = DatumGetDateADT(lower.val);
    1571                 : 
    1572                 :         /* Check for overflow -- note we already eliminated PG_INT32_MAX */
    1573              18 :         bnd++;
    1574              18 :         if (unlikely(!IS_VALID_DATE(bnd)))
    1575 UNC           0 :             ereturn(escontext, (Datum) 0,
    1576                 :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1577                 :                      errmsg("date out of range")));
    1578 GNC          18 :         lower.val = DateADTGetDatum(bnd);
    1579 GIC          18 :         lower.inclusive = true;
    1580                 :     }
    1581 ECB             : 
    1582 CBC          81 :     if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
    1583 GIC          75 :         upper.inclusive)
    1584                 :     {
    1585 GNC          15 :         DateADT     bnd = DatumGetDateADT(upper.val);
    1586                 : 
    1587                 :         /* Check for overflow -- note we already eliminated PG_INT32_MAX */
    1588              15 :         bnd++;
    1589              15 :         if (unlikely(!IS_VALID_DATE(bnd)))
    1590               6 :             ereturn(escontext, (Datum) 0,
    1591                 :                     (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
    1592                 :                      errmsg("date out of range")));
    1593               9 :         upper.val = DateADTGetDatum(bnd);
    1594 GIC           9 :         upper.inclusive = false;
    1595 ECB             :     }
    1596                 : 
    1597 GNC          75 :     PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
    1598                 :                                       false, escontext));
    1599 ECB             : }
    1600 EUB             : 
    1601                 : /*
    1602                 :  *----------------------------------------------------------
    1603 ECB             :  * SUBTYPE_DIFF FUNCTIONS
    1604                 :  *
    1605                 :  * Functions for specific built-in range types.
    1606                 :  *
    1607                 :  * Note that subtype_diff does return the difference, not the absolute value
    1608                 :  * of the difference, and it must take care to avoid overflow.
    1609                 :  * (numrange_subdiff is at some risk there ...)
    1610                 :  *----------------------------------------------------------
    1611                 :  */
    1612                 : 
    1613                 : Datum
    1614 CBC      610854 : int4range_subdiff(PG_FUNCTION_ARGS)
    1615 ECB             : {
    1616 GIC      610854 :     int32       v1 = PG_GETARG_INT32(0);
    1617          610854 :     int32       v2 = PG_GETARG_INT32(1);
    1618                 : 
    1619          610854 :     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
    1620                 : }
    1621 ECB             : 
    1622                 : Datum
    1623 LBC           0 : int8range_subdiff(PG_FUNCTION_ARGS)
    1624                 : {
    1625               0 :     int64       v1 = PG_GETARG_INT64(0);
    1626 UBC           0 :     int64       v2 = PG_GETARG_INT64(1);
    1627                 : 
    1628 LBC           0 :     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
    1629 ECB             : }
    1630                 : 
    1631                 : Datum
    1632 GIC         123 : numrange_subdiff(PG_FUNCTION_ARGS)
    1633                 : {
    1634 CBC         123 :     Datum       v1 = PG_GETARG_DATUM(0);
    1635             123 :     Datum       v2 = PG_GETARG_DATUM(1);
    1636 EUB             :     Datum       numresult;
    1637                 :     float8      floatresult;
    1638                 : 
    1639 CBC         123 :     numresult = DirectFunctionCall2(numeric_sub, v1, v2);
    1640 ECB             : 
    1641 GIC         123 :     floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
    1642                 :                                                      numresult));
    1643 ECB             : 
    1644 CBC         123 :     PG_RETURN_FLOAT8(floatresult);
    1645                 : }
    1646 ECB             : 
    1647                 : Datum
    1648 UIC           0 : daterange_subdiff(PG_FUNCTION_ARGS)
    1649 ECB             : {
    1650 LBC           0 :     int32       v1 = PG_GETARG_INT32(0);
    1651               0 :     int32       v2 = PG_GETARG_INT32(1);
    1652                 : 
    1653 UIC           0 :     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
    1654 ECB             : }
    1655                 : 
    1656                 : Datum
    1657 UIC           0 : tsrange_subdiff(PG_FUNCTION_ARGS)
    1658 ECB             : {
    1659 UIC           0 :     Timestamp   v1 = PG_GETARG_TIMESTAMP(0);
    1660               0 :     Timestamp   v2 = PG_GETARG_TIMESTAMP(1);
    1661                 :     float8      result;
    1662                 : 
    1663               0 :     result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
    1664               0 :     PG_RETURN_FLOAT8(result);
    1665                 : }
    1666                 : 
    1667                 : Datum
    1668               0 : tstzrange_subdiff(PG_FUNCTION_ARGS)
    1669                 : {
    1670               0 :     Timestamp   v1 = PG_GETARG_TIMESTAMP(0);
    1671               0 :     Timestamp   v2 = PG_GETARG_TIMESTAMP(1);
    1672                 :     float8      result;
    1673                 : 
    1674               0 :     result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
    1675 LBC           0 :     PG_RETURN_FLOAT8(result);
    1676                 : }
    1677 ECB             : 
    1678                 : /*
    1679                 :  *----------------------------------------------------------
    1680                 :  * SUPPORT FUNCTIONS
    1681                 :  *
    1682                 :  *   These functions aren't in pg_proc, but are useful for
    1683                 :  *   defining new generic range functions in C.
    1684 EUB             :  *----------------------------------------------------------
    1685                 :  */
    1686                 : 
    1687                 : /*
    1688                 :  * range_get_typcache: get cached information about a range type
    1689                 :  *
    1690                 :  * This is for use by range-related functions that follow the convention
    1691                 :  * of using the fn_extra field as a pointer to the type cache entry for
    1692                 :  * the range type.  Functions that need to cache more information than
    1693 ECB             :  * that must fend for themselves.
    1694                 :  */
    1695                 : TypeCacheEntry *
    1696 CBC     2357008 : range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
    1697                 : {
    1698 GIC     2357008 :     TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
    1699                 : 
    1700 CBC     2357008 :     if (typcache == NULL ||
    1701 GIC     2352722 :         typcache->type_id != rngtypid)
    1702 ECB             :     {
    1703 GIC        4286 :         typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
    1704            4286 :         if (typcache->rngelemtype == NULL)
    1705 LBC           0 :             elog(ERROR, "type %u is not a range type", rngtypid);
    1706 GIC        4286 :         fcinfo->flinfo->fn_extra = (void *) typcache;
    1707                 :     }
    1708                 : 
    1709 GBC     2357008 :     return typcache;
    1710                 : }
    1711 EUB             : 
    1712                 : /*
    1713                 :  * range_serialize: construct a range value from bounds and empty-flag
    1714                 :  *
    1715                 :  * This does not force canonicalization of the range value.  In most cases,
    1716                 :  * external callers should only be canonicalization functions.  Note that
    1717                 :  * we perform some datatype-independent canonicalization checks anyway.
    1718                 :  */
    1719                 : RangeType *
    1720 GBC      469852 : range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
    1721                 :                 bool empty, struct Node *escontext)
    1722                 : {
    1723                 :     RangeType  *range;
    1724 EUB             :     int         cmp;
    1725                 :     Size        msize;
    1726                 :     Pointer     ptr;
    1727                 :     int16       typlen;
    1728                 :     bool        typbyval;
    1729                 :     char        typalign;
    1730                 :     char        typstorage;
    1731 GBC      469852 :     char        flags = 0;
    1732 EUB             : 
    1733                 :     /*
    1734                 :      * Verify range is not invalid on its face, and construct flags value,
    1735                 :      * preventing any non-canonical combinations such as infinite+inclusive.
    1736                 :      */
    1737 GIC      469852 :     Assert(lower->lower);
    1738          469852 :     Assert(!upper->lower);
    1739                 : 
    1740          469852 :     if (empty)
    1741            1830 :         flags |= RANGE_EMPTY;
    1742                 :     else
    1743                 :     {
    1744          468022 :         cmp = range_cmp_bound_values(typcache, lower, upper);
    1745                 : 
    1746                 :         /* error check: if lower bound value is above upper, it's wrong */
    1747          468022 :         if (cmp > 0)
    1748 GNC          33 :             ereturn(escontext, NULL,
    1749                 :                     (errcode(ERRCODE_DATA_EXCEPTION),
    1750                 :                      errmsg("range lower bound must be less than or equal to range upper bound")));
    1751                 : 
    1752                 :         /* if bounds are equal, and not both inclusive, range is empty */
    1753 GIC      467989 :         if (cmp == 0 && !(lower->inclusive && upper->inclusive))
    1754             192 :             flags |= RANGE_EMPTY;
    1755                 :         else
    1756                 :         {
    1757 ECB             :             /* infinite boundaries are never inclusive */
    1758 GIC      467797 :             if (lower->infinite)
    1759 CBC        4911 :                 flags |= RANGE_LB_INF;
    1760 GIC      462886 :             else if (lower->inclusive)
    1761 CBC      461082 :                 flags |= RANGE_LB_INC;
    1762          467797 :             if (upper->infinite)
    1763 GIC        3363 :                 flags |= RANGE_UB_INF;
    1764 CBC      464434 :             else if (upper->inclusive)
    1765            1969 :                 flags |= RANGE_UB_INC;
    1766 EUB             :         }
    1767 ECB             :     }
    1768                 : 
    1769                 :     /* Fetch information about range's element type */
    1770 CBC      469819 :     typlen = typcache->rngelemtype->typlen;
    1771 GIC      469819 :     typbyval = typcache->rngelemtype->typbyval;
    1772          469819 :     typalign = typcache->rngelemtype->typalign;
    1773          469819 :     typstorage = typcache->rngelemtype->typstorage;
    1774                 : 
    1775                 :     /* Count space for varlena header and range type's OID */
    1776          469819 :     msize = sizeof(RangeType);
    1777          469819 :     Assert(msize == MAXALIGN(msize));
    1778                 : 
    1779                 :     /* Count space for bounds */
    1780          469819 :     if (RANGE_HAS_LBOUND(flags))
    1781 ECB             :     {
    1782                 :         /*
    1783                 :          * Make sure item to be inserted is not toasted.  It is essential that
    1784                 :          * we not insert an out-of-line toast value pointer into a range
    1785                 :          * object, for the same reasons that arrays and records can't contain
    1786                 :          * them.  It would work to store a compressed-in-line value, but we
    1787                 :          * prefer to decompress and then let compression be applied to the
    1788                 :          * whole range object if necessary.  But, unlike arrays, we do allow
    1789                 :          * short-header varlena objects to stay as-is.
    1790                 :          */
    1791 GIC      462886 :         if (typlen == -1)
    1792 CBC        2361 :             lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
    1793                 : 
    1794 GIC      462886 :         msize = datum_compute_size(msize, lower->val, typbyval, typalign,
    1795                 :                                    typlen, typstorage);
    1796                 :     }
    1797                 : 
    1798 CBC      469819 :     if (RANGE_HAS_UBOUND(flags))
    1799 ECB             :     {
    1800                 :         /* Make sure item to be inserted is not toasted */
    1801 CBC      464434 :         if (typlen == -1)
    1802            2343 :             upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
    1803                 : 
    1804 GIC      464434 :         msize = datum_compute_size(msize, upper->val, typbyval, typalign,
    1805 ECB             :                                    typlen, typstorage);
    1806                 :     }
    1807                 : 
    1808                 :     /* Add space for flag byte */
    1809 CBC      469819 :     msize += sizeof(char);
    1810                 : 
    1811                 :     /* Note: zero-fill is required here, just as in heap tuples */
    1812 GIC      469819 :     range = (RangeType *) palloc0(msize);
    1813          469819 :     SET_VARSIZE(range, msize);
    1814 ECB             : 
    1815                 :     /* Now fill in the datum */
    1816 GIC      469819 :     range->rangetypid = typcache->type_id;
    1817                 : 
    1818          469819 :     ptr = (char *) (range + 1);
    1819 ECB             : 
    1820 CBC      469819 :     if (RANGE_HAS_LBOUND(flags))
    1821 ECB             :     {
    1822 CBC      462886 :         Assert(lower->lower);
    1823          462886 :         ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
    1824 ECB             :                           typstorage);
    1825                 :     }
    1826                 : 
    1827 GIC      469819 :     if (RANGE_HAS_UBOUND(flags))
    1828                 :     {
    1829          464434 :         Assert(!upper->lower);
    1830          464434 :         ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
    1831 ECB             :                           typstorage);
    1832                 :     }
    1833                 : 
    1834 CBC      469819 :     *((char *) ptr) = flags;
    1835                 : 
    1836 GIC      469819 :     return range;
    1837 ECB             : }
    1838                 : 
    1839                 : /*
    1840                 :  * range_deserialize: deconstruct a range value
    1841                 :  *
    1842                 :  * NB: the given range object must be fully detoasted; it cannot have a
    1843                 :  * short varlena header.
    1844                 :  *
    1845                 :  * Note that if the element type is pass-by-reference, the datums in the
    1846                 :  * RangeBound structs will be pointers into the given range object.
    1847                 :  */
    1848                 : void
    1849 GIC     4814011 : range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
    1850                 :                   RangeBound *lower, RangeBound *upper, bool *empty)
    1851                 : {
    1852 ECB             :     char        flags;
    1853                 :     int16       typlen;
    1854                 :     bool        typbyval;
    1855                 :     char        typalign;
    1856                 :     Pointer     ptr;
    1857                 :     Datum       lbound;
    1858                 :     Datum       ubound;
    1859                 : 
    1860                 :     /* assert caller passed the right typcache entry */
    1861 GIC     4814011 :     Assert(RangeTypeGetOid(range) == typcache->type_id);
    1862 ECB             : 
    1863                 :     /* fetch the flag byte from datum's last byte */
    1864 GIC     4814011 :     flags = *((const char *) range + VARSIZE(range) - 1);
    1865 ECB             : 
    1866                 :     /* fetch information about range's element type */
    1867 GIC     4814011 :     typlen = typcache->rngelemtype->typlen;
    1868         4814011 :     typbyval = typcache->rngelemtype->typbyval;
    1869         4814011 :     typalign = typcache->rngelemtype->typalign;
    1870 ECB             : 
    1871                 :     /* initialize data pointer just after the range OID */
    1872 GIC     4814011 :     ptr = (Pointer) (range + 1);
    1873 ECB             : 
    1874                 :     /* fetch lower bound, if any */
    1875 GIC     4814011 :     if (RANGE_HAS_LBOUND(flags))
    1876                 :     {
    1877 ECB             :         /* att_align_pointer cannot be necessary here */
    1878 GIC     4258782 :         lbound = fetch_att(ptr, typbyval, typlen);
    1879 CBC     4258782 :         ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
    1880                 :     }
    1881 ECB             :     else
    1882 GIC      555229 :         lbound = (Datum) 0;
    1883 ECB             : 
    1884                 :     /* fetch upper bound, if any */
    1885 GIC     4814011 :     if (RANGE_HAS_UBOUND(flags))
    1886                 :     {
    1887         4266555 :         ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
    1888 CBC     4266555 :         ubound = fetch_att(ptr, typbyval, typlen);
    1889                 :         /* no need for att_addlength_pointer */
    1890 ECB             :     }
    1891                 :     else
    1892 GIC      547456 :         ubound = (Datum) 0;
    1893                 : 
    1894                 :     /* emit results */
    1895 ECB             : 
    1896 GIC     4814011 :     *empty = (flags & RANGE_EMPTY) != 0;
    1897 ECB             : 
    1898 GIC     4814011 :     lower->val = lbound;
    1899         4814011 :     lower->infinite = (flags & RANGE_LB_INF) != 0;
    1900         4814011 :     lower->inclusive = (flags & RANGE_LB_INC) != 0;
    1901         4814011 :     lower->lower = true;
    1902                 : 
    1903         4814011 :     upper->val = ubound;
    1904         4814011 :     upper->infinite = (flags & RANGE_UB_INF) != 0;
    1905         4814011 :     upper->inclusive = (flags & RANGE_UB_INC) != 0;
    1906         4814011 :     upper->lower = false;
    1907         4814011 : }
    1908                 : 
    1909                 : /*
    1910 ECB             :  * range_get_flags: just get the flags from a RangeType value.
    1911                 :  *
    1912                 :  * This is frequently useful in places that only need the flags and not
    1913                 :  * the full results of range_deserialize.
    1914                 :  */
    1915                 : char
    1916 GIC     1477088 : range_get_flags(const RangeType *range)
    1917                 : {
    1918                 :     /* fetch the flag byte from datum's last byte */
    1919         1477088 :     return *((char *) range + VARSIZE(range) - 1);
    1920                 : }
    1921                 : 
    1922 ECB             : /*
    1923                 :  * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
    1924                 :  *
    1925                 :  * This is only needed in GiST operations, so we don't include a provision
    1926                 :  * for setting it in range_serialize; rather, this function must be applied
    1927                 :  * afterwards.
    1928                 :  */
    1929                 : void
    1930 CBC           9 : range_set_contain_empty(RangeType *range)
    1931                 : {
    1932                 :     char       *flagsp;
    1933 ECB             : 
    1934                 :     /* flag byte is datum's last byte */
    1935 GIC           9 :     flagsp = (char *) range + VARSIZE(range) - 1;
    1936 ECB             : 
    1937 GIC           9 :     *flagsp |= RANGE_CONTAIN_EMPTY;
    1938               9 : }
    1939 ECB             : 
    1940                 : /*
    1941                 :  * This both serializes and canonicalizes (if applicable) the range.
    1942                 :  * This should be used by most callers.
    1943                 :  */
    1944                 : RangeType *
    1945 GIC      236600 : make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
    1946                 :            bool empty, struct Node *escontext)
    1947                 : {
    1948 ECB             :     RangeType  *range;
    1949                 : 
    1950 GNC      236600 :     range = range_serialize(typcache, lower, upper, empty, escontext);
    1951                 : 
    1952          236573 :     if (SOFT_ERROR_OCCURRED(escontext))
    1953               6 :         return NULL;
    1954                 : 
    1955                 :     /* no need to call canonical on empty ranges ... */
    1956 CBC      236567 :     if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
    1957 GIC      233773 :         !RangeIsEmpty(range))
    1958                 :     {
    1959                 :         /* Do this the hard way so that we can pass escontext */
    1960 GNC      231958 :         LOCAL_FCINFO(fcinfo, 1);
    1961                 :         Datum       result;
    1962                 : 
    1963          231958 :         InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
    1964                 :                                  InvalidOid, escontext, NULL);
    1965                 : 
    1966          231958 :         fcinfo->args[0].value = RangeTypePGetDatum(range);
    1967          231958 :         fcinfo->args[0].isnull = false;
    1968                 : 
    1969          231958 :         result = FunctionCallInvoke(fcinfo);
    1970                 : 
    1971          231958 :         if (SOFT_ERROR_OCCURRED(escontext))
    1972              12 :             return NULL;
    1973                 : 
    1974                 :         /* Should not get a null result if there was no error */
    1975          231946 :         if (fcinfo->isnull)
    1976 UNC           0 :             elog(ERROR, "function %u returned NULL",
    1977                 :                  typcache->rng_canonical_finfo.fn_oid);
    1978                 : 
    1979 GNC      231946 :         range = DatumGetRangeTypeP(result);
    1980                 :     }
    1981 ECB             : 
    1982 GIC      236555 :     return range;
    1983 ECB             : }
    1984                 : 
    1985                 : /*
    1986                 :  * Compare two range boundary points, returning <0, 0, or >0 according to
    1987                 :  * whether b1 is less than, equal to, or greater than b2.
    1988                 :  *
    1989                 :  * The boundaries can be any combination of upper and lower; so it's useful
    1990                 :  * for a variety of operators.
    1991                 :  *
    1992                 :  * The simple case is when b1 and b2 are both finite and inclusive, in which
    1993                 :  * case the result is just a comparison of the values held in b1 and b2.
    1994                 :  *
    1995                 :  * If a bound is exclusive, then we need to know whether it's a lower bound,
    1996                 :  * in which case we treat the boundary point as "just greater than" the held
    1997                 :  * value; or an upper bound, in which case we treat the boundary point as
    1998                 :  * "just less than" the held value.
    1999                 :  *
    2000                 :  * If a bound is infinite, it represents minus infinity (less than every other
    2001                 :  * point) if it's a lower bound; or plus infinity (greater than every other
    2002                 :  * point) if it's an upper bound.
    2003                 :  *
    2004                 :  * There is only one case where two boundaries compare equal but are not
    2005                 :  * identical: when both bounds are inclusive and hold the same finite value,
    2006                 :  * but one is an upper bound and the other a lower bound.
    2007                 :  */
    2008                 : int
    2009 GIC     6066546 : range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
    2010                 : {
    2011                 :     int32       result;
    2012                 : 
    2013                 :     /*
    2014                 :      * First, handle cases involving infinity, which don't require invoking
    2015 ECB             :      * the comparison proc.
    2016                 :      */
    2017 GIC     6066546 :     if (b1->infinite && b2->infinite)
    2018                 :     {
    2019                 :         /*
    2020 ECB             :          * Both are infinity, so they are equal unless one is lower and the
    2021                 :          * other not.
    2022                 :          */
    2023 CBC        8101 :         if (b1->lower == b2->lower)
    2024 GIC        8059 :             return 0;
    2025                 :         else
    2026              42 :             return b1->lower ? -1 : 1;
    2027                 :     }
    2028         6058445 :     else if (b1->infinite)
    2029           47572 :         return b1->lower ? -1 : 1;
    2030 CBC     6010873 :     else if (b2->infinite)
    2031 GIC       14006 :         return b2->lower ? 1 : -1;
    2032                 : 
    2033                 :     /*
    2034                 :      * Both boundaries are finite, so compare the held values.
    2035 ECB             :      */
    2036 GIC     5996867 :     result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2037 ECB             :                                              typcache->rng_collation,
    2038 CBC     5996867 :                                              b1->val, b2->val));
    2039                 : 
    2040                 :     /*
    2041 ECB             :      * If the comparison is anything other than equal, we're done. If they
    2042                 :      * compare equal though, we still have to consider whether the boundaries
    2043                 :      * are inclusive or exclusive.
    2044                 :      */
    2045 CBC     5996867 :     if (result == 0)
    2046                 :     {
    2047 GIC      346864 :         if (!b1->inclusive && !b2->inclusive)
    2048 ECB             :         {
    2049                 :             /* both are exclusive */
    2050 GIC      153823 :             if (b1->lower == b2->lower)
    2051 CBC      153820 :                 return 0;
    2052 ECB             :             else
    2053 GIC           3 :                 return b1->lower ? 1 : -1;
    2054 ECB             :         }
    2055 GIC      193041 :         else if (!b1->inclusive)
    2056 CBC         315 :             return b1->lower ? 1 : -1;
    2057          192726 :         else if (!b2->inclusive)
    2058 GIC         413 :             return b2->lower ? -1 : 1;
    2059                 :         else
    2060 ECB             :         {
    2061 EUB             :             /*
    2062                 :              * Both are inclusive and the values held are equal, so they are
    2063                 :              * equal regardless of whether they are upper or lower boundaries,
    2064 ECB             :              * or a mix.
    2065                 :              */
    2066 GIC      192313 :             return 0;
    2067 ECB             :         }
    2068                 :     }
    2069                 : 
    2070 GIC     5650003 :     return result;
    2071                 : }
    2072                 : 
    2073                 : /*
    2074                 :  * Compare two range boundary point values, returning <0, 0, or >0 according
    2075                 :  * to whether b1 is less than, equal to, or greater than b2.
    2076                 :  *
    2077                 :  * This is similar to but simpler than range_cmp_bounds().  We just compare
    2078                 :  * the values held in b1 and b2, ignoring inclusive/exclusive flags.  The
    2079                 :  * lower/upper flags only matter for infinities, where they tell us if the
    2080                 :  * infinity is plus or minus.
    2081                 :  */
    2082                 : int
    2083          704332 : range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
    2084                 :                        const RangeBound *b2)
    2085                 : {
    2086                 :     /*
    2087                 :      * First, handle cases involving infinity, which don't require invoking
    2088                 :      * the comparison proc.
    2089                 :      */
    2090          704332 :     if (b1->infinite && b2->infinite)
    2091                 :     {
    2092                 :         /*
    2093                 :          * Both are infinity, so they are equal unless one is lower and the
    2094 ECB             :          * other not.
    2095                 :          */
    2096 GIC         137 :         if (b1->lower == b2->lower)
    2097 UIC           0 :             return 0;
    2098                 :         else
    2099 GIC         137 :             return b1->lower ? -1 : 1;
    2100                 :     }
    2101          704195 :     else if (b1->infinite)
    2102 CBC        8166 :         return b1->lower ? -1 : 1;
    2103 GIC      696029 :     else if (b2->infinite)
    2104            6910 :         return b2->lower ? 1 : -1;
    2105                 : 
    2106                 :     /*
    2107                 :      * Both boundaries are finite, so compare the held values.
    2108 ECB             :      */
    2109 CBC      689119 :     return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2110                 :                                            typcache->rng_collation,
    2111          689119 :                                            b1->val, b2->val));
    2112                 : }
    2113 ECB             : 
    2114                 : /*
    2115                 :  * qsort callback for sorting ranges.
    2116                 :  *
    2117                 :  * Two empty ranges compare equal; an empty range sorts to the left of any
    2118                 :  * non-empty range.  Two non-empty ranges are sorted by lower bound first
    2119                 :  * and by upper bound next.
    2120                 :  */
    2121                 : int
    2122 GIC       13359 : range_compare(const void *key1, const void *key2, void *arg)
    2123 ECB             : {
    2124 GIC       13359 :     RangeType  *r1 = *(RangeType **) key1;
    2125           13359 :     RangeType  *r2 = *(RangeType **) key2;
    2126           13359 :     TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
    2127                 :     RangeBound  lower1;
    2128                 :     RangeBound  upper1;
    2129                 :     RangeBound  lower2;
    2130 ECB             :     RangeBound  upper2;
    2131                 :     bool        empty1;
    2132                 :     bool        empty2;
    2133                 :     int         cmp;
    2134                 : 
    2135 CBC       13359 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    2136           13359 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    2137                 : 
    2138           13359 :     if (empty1 && empty2)
    2139 GIC          24 :         cmp = 0;
    2140 CBC       13335 :     else if (empty1)
    2141              21 :         cmp = -1;
    2142           13314 :     else if (empty2)
    2143               6 :         cmp = 1;
    2144                 :     else
    2145                 :     {
    2146 GIC       13308 :         cmp = range_cmp_bounds(typcache, &lower1, &lower2);
    2147           13308 :         if (cmp == 0)
    2148              24 :             cmp = range_cmp_bounds(typcache, &upper1, &upper2);
    2149                 :     }
    2150                 : 
    2151 CBC       13359 :     return cmp;
    2152                 : }
    2153                 : 
    2154                 : /*
    2155 ECB             :  * Build an empty range value of the type indicated by the typcache entry.
    2156                 :  */
    2157                 : RangeType *
    2158 GIC        1560 : make_empty_range(TypeCacheEntry *typcache)
    2159                 : {
    2160                 :     RangeBound  lower;
    2161                 :     RangeBound  upper;
    2162                 : 
    2163            1560 :     lower.val = (Datum) 0;
    2164            1560 :     lower.infinite = false;
    2165            1560 :     lower.inclusive = false;
    2166            1560 :     lower.lower = true;
    2167                 : 
    2168 CBC        1560 :     upper.val = (Datum) 0;
    2169 GIC        1560 :     upper.infinite = false;
    2170            1560 :     upper.inclusive = false;
    2171            1560 :     upper.lower = false;
    2172                 : 
    2173 GNC        1560 :     return make_range(typcache, &lower, &upper, true, NULL);
    2174                 : }
    2175 ECB             : 
    2176                 : 
    2177                 : /*
    2178                 :  *----------------------------------------------------------
    2179                 :  * STATIC FUNCTIONS
    2180                 :  *----------------------------------------------------------
    2181                 :  */
    2182 EUB             : 
    2183                 : /*
    2184 ECB             :  * Given a string representing the flags for the range type, return the flags
    2185                 :  * represented as a char.
    2186                 :  */
    2187                 : static char
    2188 CBC        2559 : range_parse_flags(const char *flags_str)
    2189 ECB             : {
    2190 GIC        2559 :     char        flags = 0;
    2191                 : 
    2192            2559 :     if (flags_str[0] == '\0' ||
    2193            2559 :         flags_str[1] == '\0' ||
    2194 CBC        2559 :         flags_str[2] != '\0')
    2195 UIC           0 :         ereport(ERROR,
    2196 ECB             :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2197                 :                  errmsg("invalid range bound flags"),
    2198                 :                  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
    2199                 : 
    2200 GIC        2559 :     switch (flags_str[0])
    2201                 :     {
    2202             105 :         case '[':
    2203             105 :             flags |= RANGE_LB_INC;
    2204             105 :             break;
    2205            2454 :         case '(':
    2206            2454 :             break;
    2207 LBC           0 :         default:
    2208 UIC           0 :             ereport(ERROR,
    2209 ECB             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2210                 :                      errmsg("invalid range bound flags"),
    2211                 :                      errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
    2212                 :     }
    2213                 : 
    2214 GIC        2559 :     switch (flags_str[1])
    2215                 :     {
    2216            2517 :         case ']':
    2217            2517 :             flags |= RANGE_UB_INC;
    2218            2517 :             break;
    2219              42 :         case ')':
    2220 CBC          42 :             break;
    2221 LBC           0 :         default:
    2222 UIC           0 :             ereport(ERROR,
    2223 ECB             :                     (errcode(ERRCODE_SYNTAX_ERROR),
    2224                 :                      errmsg("invalid range bound flags"),
    2225                 :                      errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
    2226                 :     }
    2227                 : 
    2228 CBC        2559 :     return flags;
    2229                 : }
    2230                 : 
    2231 ECB             : /*
    2232                 :  * Parse range input.
    2233                 :  *
    2234                 :  * Input parameters:
    2235                 :  *  string: input string to be parsed
    2236                 :  * Output parameters:
    2237                 :  *  *flags: receives flags bitmask
    2238                 :  *  *lbound_str: receives palloc'd lower bound string, or NULL if none
    2239                 :  *  *ubound_str: receives palloc'd upper bound string, or NULL if none
    2240                 :  *
    2241                 :  * This is modeled somewhat after record_in in rowtypes.c.
    2242                 :  * The input syntax is:
    2243                 :  *  <range>   := EMPTY
    2244                 :  *             | <lb-inc> <string>, <string> <ub-inc>
    2245                 :  *  <lb-inc>  := '[' | '('
    2246                 :  *  <ub-inc>  := ']' | ')'
    2247                 :  *
    2248                 :  * Whitespace before or after <range> is ignored.  Whitespace within a <string>
    2249                 :  * is taken literally and becomes part of the input string for that bound.
    2250                 :  *
    2251                 :  * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
    2252                 :  * is surrounded by double-quotes, in which case it is the literal empty
    2253                 :  * string.
    2254                 :  *
    2255                 :  * Within a <string>, special characters (such as comma, parenthesis, or
    2256                 :  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
    2257                 :  * double-quotes, a double-quote can be escaped with double-quote or backslash.
    2258                 :  *
    2259                 :  * Returns true on success, false on failure (but failures will return only if
    2260                 :  * escontext is an ErrorSaveContext).
    2261                 :  */
    2262                 : static bool
    2263 GIC        1471 : range_parse(const char *string, char *flags, char **lbound_str,
    2264                 :             char **ubound_str, Node *escontext)
    2265                 : {
    2266            1471 :     const char *ptr = string;
    2267                 :     bool        infinite;
    2268                 : 
    2269            1471 :     *flags = 0;
    2270                 : 
    2271                 :     /* consume whitespace */
    2272            1483 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
    2273              12 :         ptr++;
    2274                 : 
    2275                 :     /* check for empty range */
    2276 CBC        1471 :     if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
    2277                 :                        strlen(RANGE_EMPTY_LITERAL)) == 0)
    2278 ECB             :     {
    2279 GIC         270 :         *flags = RANGE_EMPTY;
    2280 CBC         270 :         *lbound_str = NULL;
    2281             270 :         *ubound_str = NULL;
    2282 ECB             : 
    2283 GBC         270 :         ptr += strlen(RANGE_EMPTY_LITERAL);
    2284                 : 
    2285                 :         /* the rest should be whitespace */
    2286 GIC         276 :         while (*ptr != '\0' && isspace((unsigned char) *ptr))
    2287               6 :             ptr++;
    2288 ECB             : 
    2289                 :         /* should have consumed everything */
    2290 CBC         270 :         if (*ptr != '\0')
    2291 UNC           0 :             ereturn(escontext, false,
    2292 ECB             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2293                 :                      errmsg("malformed range literal: \"%s\"",
    2294                 :                             string),
    2295 EUB             :                      errdetail("Junk after \"empty\" key word.")));
    2296                 : 
    2297 GNC         270 :         return true;
    2298                 :     }
    2299                 : 
    2300 GIC        1201 :     if (*ptr == '[')
    2301                 :     {
    2302 CBC         864 :         *flags |= RANGE_LB_INC;
    2303 GIC         864 :         ptr++;
    2304 ECB             :     }
    2305 CBC         337 :     else if (*ptr == '(')
    2306             331 :         ptr++;
    2307 ECB             :     else
    2308 GNC           6 :         ereturn(escontext, false,
    2309 EUB             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2310                 :                  errmsg("malformed range literal: \"%s\"",
    2311                 :                         string),
    2312                 :                  errdetail("Missing left parenthesis or bracket.")));
    2313                 : 
    2314 GNC        1195 :     ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
    2315            1192 :     if (ptr == NULL)
    2316 UNC           0 :         return false;
    2317 GIC        1192 :     if (infinite)
    2318 CBC          81 :         *flags |= RANGE_LB_INF;
    2319                 : 
    2320 GIC        1192 :     if (*ptr == ',')
    2321            1180 :         ptr++;
    2322                 :     else
    2323 GNC          12 :         ereturn(escontext, false,
    2324                 :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2325                 :                  errmsg("malformed range literal: \"%s\"",
    2326                 :                         string),
    2327                 :                  errdetail("Missing comma after lower bound.")));
    2328                 : 
    2329            1180 :     ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
    2330            1180 :     if (ptr == NULL)
    2331               6 :         return false;
    2332 GIC        1174 :     if (infinite)
    2333             123 :         *flags |= RANGE_UB_INF;
    2334                 : 
    2335            1174 :     if (*ptr == ']')
    2336                 :     {
    2337             313 :         *flags |= RANGE_UB_INC;
    2338             313 :         ptr++;
    2339                 :     }
    2340             861 :     else if (*ptr == ')')
    2341             855 :         ptr++;
    2342                 :     else                        /* must be a comma */
    2343 GNC           6 :         ereturn(escontext, false,
    2344                 :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2345                 :                  errmsg("malformed range literal: \"%s\"",
    2346                 :                         string),
    2347                 :                  errdetail("Too many commas.")));
    2348                 : 
    2349                 :     /* consume whitespace */
    2350 GIC        1183 :     while (*ptr != '\0' && isspace((unsigned char) *ptr))
    2351              15 :         ptr++;
    2352                 : 
    2353            1168 :     if (*ptr != '\0')
    2354 GNC           9 :         ereturn(escontext, false,
    2355 ECB             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2356                 :                  errmsg("malformed range literal: \"%s\"",
    2357                 :                         string),
    2358                 :                  errdetail("Junk after right parenthesis or bracket.")));
    2359                 : 
    2360 GNC        1159 :     return true;
    2361                 : }
    2362                 : 
    2363 ECB             : /*
    2364                 :  * Helper for range_parse: parse and de-quote one bound string.
    2365                 :  *
    2366                 :  * We scan until finding comma, right parenthesis, or right bracket.
    2367                 :  *
    2368                 :  * Input parameters:
    2369                 :  *  string: entire input string (used only for error reports)
    2370                 :  *  ptr: where to start parsing bound
    2371                 :  * Output parameters:
    2372                 :  *  *bound_str: receives palloc'd bound string, or NULL if none
    2373                 :  *  *infinite: set true if no bound, else false
    2374                 :  *
    2375                 :  * The return value is the scan ptr, advanced past the bound string.
    2376                 :  * However, if escontext is an ErrorSaveContext, we return NULL on failure.
    2377                 :  */
    2378                 : static const char *
    2379 GIC        2375 : range_parse_bound(const char *string, const char *ptr,
    2380                 :                   char **bound_str, bool *infinite, Node *escontext)
    2381 ECB             : {
    2382                 :     StringInfoData buf;
    2383                 : 
    2384                 :     /* Check for null: completely empty input means null */
    2385 CBC        2375 :     if (*ptr == ',' || *ptr == ')' || *ptr == ']')
    2386 EUB             :     {
    2387 GIC         204 :         *bound_str = NULL;
    2388             204 :         *infinite = true;
    2389                 :     }
    2390                 :     else
    2391                 :     {
    2392 ECB             :         /* Extract string for this bound */
    2393 GIC        2171 :         bool        inquote = false;
    2394                 : 
    2395 CBC        2171 :         initStringInfo(&buf);
    2396 GIC        7868 :         while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
    2397 ECB             :         {
    2398 CBC        5706 :             char        ch = *ptr++;
    2399                 : 
    2400            5706 :             if (ch == '\0')
    2401 GNC           9 :                 ereturn(escontext, NULL,
    2402                 :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2403 ECB             :                          errmsg("malformed range literal: \"%s\"",
    2404                 :                                 string),
    2405                 :                          errdetail("Unexpected end of input.")));
    2406 GIC        5697 :             if (ch == '\\')
    2407                 :             {
    2408              21 :                 if (*ptr == '\0')
    2409 UNC           0 :                     ereturn(escontext, NULL,
    2410 ECB             :                             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    2411 EUB             :                              errmsg("malformed range literal: \"%s\"",
    2412 ECB             :                                     string),
    2413                 :                              errdetail("Unexpected end of input.")));
    2414 GIC          21 :                 appendStringInfoChar(&buf, *ptr++);
    2415 ECB             :             }
    2416 CBC        5676 :             else if (ch == '"')
    2417                 :             {
    2418             200 :                 if (!inquote)
    2419 GIC         100 :                     inquote = true;
    2420             100 :                 else if (*ptr == '"')
    2421                 :                 {
    2422                 :                     /* doubled quote within quote sequence */
    2423               3 :                     appendStringInfoChar(&buf, *ptr++);
    2424 ECB             :                 }
    2425                 :                 else
    2426 CBC          97 :                     inquote = false;
    2427 ECB             :             }
    2428                 :             else
    2429 GIC        5476 :                 appendStringInfoChar(&buf, ch);
    2430 ECB             :         }
    2431                 : 
    2432 CBC        2162 :         *bound_str = buf.data;
    2433            2162 :         *infinite = false;
    2434                 :     }
    2435 ECB             : 
    2436 CBC        2366 :     return ptr;
    2437                 : }
    2438 ECB             : 
    2439                 : /*
    2440                 :  * Convert a deserialized range value to text form
    2441                 :  *
    2442                 :  * Inputs are the flags byte, and the two bound values already converted to
    2443                 :  * text (but not yet quoted).  If no bound value, pass NULL.
    2444                 :  *
    2445                 :  * Result is a palloc'd string
    2446                 :  */
    2447                 : static char *
    2448 CBC       52061 : range_deparse(char flags, const char *lbound_str, const char *ubound_str)
    2449 ECB             : {
    2450                 :     StringInfoData buf;
    2451                 : 
    2452 GIC       52061 :     if (flags & RANGE_EMPTY)
    2453            8452 :         return pstrdup(RANGE_EMPTY_LITERAL);
    2454                 : 
    2455 CBC       43609 :     initStringInfo(&buf);
    2456                 : 
    2457 GIC       43609 :     appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
    2458                 : 
    2459           43609 :     if (RANGE_HAS_LBOUND(flags))
    2460           42382 :         appendStringInfoString(&buf, range_bound_escape(lbound_str));
    2461                 : 
    2462           43609 :     appendStringInfoChar(&buf, ',');
    2463                 : 
    2464           43609 :     if (RANGE_HAS_UBOUND(flags))
    2465           42349 :         appendStringInfoString(&buf, range_bound_escape(ubound_str));
    2466                 : 
    2467           43609 :     appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
    2468                 : 
    2469           43609 :     return buf.data;
    2470                 : }
    2471                 : 
    2472                 : /*
    2473                 :  * Helper for range_deparse: quote a bound value as needed
    2474 ECB             :  *
    2475                 :  * Result is a palloc'd string
    2476                 :  */
    2477                 : static char *
    2478 GIC       84731 : range_bound_escape(const char *value)
    2479                 : {
    2480 ECB             :     bool        nq;
    2481                 :     const char *ptr;
    2482                 :     StringInfoData buf;
    2483                 : 
    2484 GIC       84731 :     initStringInfo(&buf);
    2485                 : 
    2486                 :     /* Detect whether we need double quotes for this value */
    2487           84731 :     nq = (value[0] == '\0');    /* force quotes for empty string */
    2488 CBC      383970 :     for (ptr = value; *ptr; ptr++)
    2489                 :     {
    2490          299488 :         char        ch = *ptr;
    2491 ECB             : 
    2492 GIC      299488 :         if (ch == '"' || ch == '\\' ||
    2493 CBC      299419 :             ch == '(' || ch == ')' ||
    2494 GIC      299407 :             ch == '[' || ch == ']' ||
    2495 CBC      299383 :             ch == ',' ||
    2496          299383 :             isspace((unsigned char) ch))
    2497                 :         {
    2498 GIC         249 :             nq = true;
    2499             249 :             break;
    2500                 :         }
    2501 ECB             :     }
    2502                 : 
    2503                 :     /* And emit the string */
    2504 GBC       84731 :     if (nq)
    2505 GIC         261 :         appendStringInfoChar(&buf, '"');
    2506          385917 :     for (ptr = value; *ptr; ptr++)
    2507                 :     {
    2508          301186 :         char        ch = *ptr;
    2509 ECB             : 
    2510 GIC      301186 :         if (ch == '"' || ch == '\\')
    2511 CBC          60 :             appendStringInfoChar(&buf, ch);
    2512 GIC      301186 :         appendStringInfoChar(&buf, ch);
    2513 ECB             :     }
    2514 CBC       84731 :     if (nq)
    2515             261 :         appendStringInfoChar(&buf, '"');
    2516                 : 
    2517 GIC       84731 :     return buf.data;
    2518 ECB             : }
    2519                 : 
    2520                 : /*
    2521                 :  * Test whether range r1 contains range r2.
    2522                 :  *
    2523                 :  * Caller has already checked that they are the same range type, and looked up
    2524                 :  * the necessary typcache entry.
    2525                 :  */
    2526                 : bool
    2527 CBC      243953 : range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
    2528 ECB             : {
    2529                 :     RangeBound  lower1;
    2530                 :     RangeBound  upper1;
    2531                 :     bool        empty1;
    2532                 :     RangeBound  lower2;
    2533                 :     RangeBound  upper2;
    2534                 :     bool        empty2;
    2535                 : 
    2536                 :     /* Different types should be prevented by ANYRANGE matching rules */
    2537 GIC      243953 :     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
    2538 UIC           0 :         elog(ERROR, "range types do not match");
    2539                 : 
    2540 GIC      243953 :     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
    2541          243953 :     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
    2542                 : 
    2543 ECB             :     /* If either range is empty, the answer is easy */
    2544 GIC      243953 :     if (empty2)
    2545          157373 :         return true;
    2546           86580 :     else if (empty1)
    2547 CBC        6783 :         return false;
    2548 ECB             : 
    2549                 :     /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
    2550 CBC       79797 :     if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
    2551 GIC       38018 :         return false;
    2552 CBC       41779 :     if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
    2553 GIC       37646 :         return false;
    2554 ECB             : 
    2555 CBC        4133 :     return true;
    2556                 : }
    2557 ECB             : 
    2558                 : bool
    2559 CBC       62345 : range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
    2560 ECB             : {
    2561 GIC       62345 :     return range_contains_internal(typcache, r2, r1);
    2562 ECB             : }
    2563                 : 
    2564                 : /*
    2565                 :  * Test whether range r contains a specific element value.
    2566                 :  */
    2567                 : bool
    2568 GIC       45578 : range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
    2569                 : {
    2570                 :     RangeBound  lower;
    2571                 :     RangeBound  upper;
    2572                 :     bool        empty;
    2573 ECB             :     int32       cmp;
    2574                 : 
    2575 GIC       45578 :     range_deserialize(typcache, r, &lower, &upper, &empty);
    2576                 : 
    2577           45578 :     if (empty)
    2578            6432 :         return false;
    2579 ECB             : 
    2580 GIC       39146 :     if (!lower.infinite)
    2581                 :     {
    2582 CBC       37019 :         cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2583 ECB             :                                               typcache->rng_collation,
    2584                 :                                               lower.val, val));
    2585 CBC       37019 :         if (cmp > 0)
    2586 GIC       35691 :             return false;
    2587 CBC        1328 :         if (cmp == 0 && !lower.inclusive)
    2588 LBC           0 :             return false;
    2589 ECB             :     }
    2590                 : 
    2591 CBC        3455 :     if (!upper.infinite)
    2592                 :     {
    2593            3437 :         cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
    2594 ECB             :                                               typcache->rng_collation,
    2595                 :                                               upper.val, val));
    2596 GIC        3437 :         if (cmp < 0)
    2597             357 :             return false;
    2598            3080 :         if (cmp == 0 && !upper.inclusive)
    2599 CBC           3 :             return false;
    2600 ECB             :     }
    2601                 : 
    2602 GIC        3095 :     return true;
    2603 ECB             : }
    2604                 : 
    2605                 : 
    2606                 : /*
    2607                 :  * datum_compute_size() and datum_write() are used to insert the bound
    2608                 :  * values into a range object.  They are modeled after heaptuple.c's
    2609                 :  * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
    2610                 :  * null values here.  TYPE_IS_PACKABLE must test the same conditions as
    2611                 :  * heaptuple.c's ATT_IS_PACKABLE macro.
    2612                 :  */
    2613                 : 
    2614                 : /* Does datatype allow packing into the 1-byte-header varlena format? */
    2615                 : #define TYPE_IS_PACKABLE(typlen, typstorage) \
    2616                 :     ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
    2617                 : 
    2618                 : /*
    2619                 :  * Increment data_length by the space needed by the datum, including any
    2620                 :  * preceding alignment padding.
    2621                 :  */
    2622                 : static Size
    2623 GIC      927320 : datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
    2624                 :                    int16 typlen, char typstorage)
    2625                 : {
    2626          927320 :     if (TYPE_IS_PACKABLE(typlen, typstorage) &&
    2627            4704 :         VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
    2628                 :     {
    2629                 :         /*
    2630                 :          * we're anticipating converting to a short varlena header, so adjust
    2631                 :          * length and don't count any alignment
    2632 ECB             :          */
    2633 GBC        4245 :         data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
    2634                 :     }
    2635 ECB             :     else
    2636                 :     {
    2637 GIC      923075 :         data_length = att_align_datum(data_length, typalign, typlen, val);
    2638          923075 :         data_length = att_addlength_datum(data_length, typlen, val);
    2639 ECB             :     }
    2640                 : 
    2641 CBC      927320 :     return data_length;
    2642 ECB             : }
    2643                 : 
    2644                 : /*
    2645                 :  * Write the given datum beginning at ptr (after advancing to correct
    2646                 :  * alignment, if needed).  Return the pointer incremented by space used.
    2647                 :  */
    2648                 : static Pointer
    2649 GIC      927320 : datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
    2650 ECB             :             int16 typlen, char typstorage)
    2651                 : {
    2652                 :     Size        data_length;
    2653                 : 
    2654 CBC      927320 :     if (typbyval)
    2655                 :     {
    2656 ECB             :         /* pass-by-value */
    2657 GIC      922616 :         ptr = (char *) att_align_nominal(ptr, typalign);
    2658          922616 :         store_att_byval(ptr, datum, typlen);
    2659          922616 :         data_length = typlen;
    2660                 :     }
    2661            4704 :     else if (typlen == -1)
    2662                 :     {
    2663 ECB             :         /* varlena */
    2664 GIC        4704 :         Pointer     val = DatumGetPointer(datum);
    2665                 : 
    2666            4704 :         if (VARATT_IS_EXTERNAL(val))
    2667                 :         {
    2668                 :             /*
    2669                 :              * Throw error, because we must never put a toast pointer inside a
    2670 ECB             :              * range object.  Caller should have detoasted it.
    2671                 :              */
    2672 LBC           0 :             elog(ERROR, "cannot store a toast pointer inside a range");
    2673 ECB             :             data_length = 0;    /* keep compiler quiet */
    2674                 :         }
    2675 CBC        4704 :         else if (VARATT_IS_SHORT(val))
    2676                 :         {
    2677 ECB             :             /* no alignment for short varlenas */
    2678 GIC         441 :             data_length = VARSIZE_SHORT(val);
    2679             441 :             memcpy(ptr, val, data_length);
    2680 ECB             :         }
    2681 CBC        4263 :         else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
    2682            4263 :                  VARATT_CAN_MAKE_SHORT(val))
    2683 EUB             :         {
    2684                 :             /* convert to short varlena -- no alignment */
    2685 GIC        4245 :             data_length = VARATT_CONVERTED_SHORT_SIZE(val);
    2686 CBC        4245 :             SET_VARSIZE_SHORT(ptr, data_length);
    2687 GIC        4245 :             memcpy(ptr + 1, VARDATA(val), data_length - 1);
    2688 ECB             :         }
    2689                 :         else
    2690                 :         {
    2691                 :             /* full 4-byte header varlena */
    2692 CBC          18 :             ptr = (char *) att_align_nominal(ptr, typalign);
    2693              18 :             data_length = VARSIZE(val);
    2694              18 :             memcpy(ptr, val, data_length);
    2695                 :         }
    2696                 :     }
    2697 LBC           0 :     else if (typlen == -2)
    2698                 :     {
    2699                 :         /* cstring ... never needs alignment */
    2700 UIC           0 :         Assert(typalign == TYPALIGN_CHAR);
    2701               0 :         data_length = strlen(DatumGetCString(datum)) + 1;
    2702               0 :         memcpy(ptr, DatumGetPointer(datum), data_length);
    2703                 :     }
    2704                 :     else
    2705                 :     {
    2706                 :         /* fixed-length pass-by-reference */
    2707               0 :         ptr = (char *) att_align_nominal(ptr, typalign);
    2708               0 :         Assert(typlen > 0);
    2709               0 :         data_length = typlen;
    2710               0 :         memcpy(ptr, DatumGetPointer(datum), data_length);
    2711                 :     }
    2712                 : 
    2713 GIC      927320 :     ptr += data_length;
    2714                 : 
    2715          927320 :     return ptr;
    2716                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a