Header And Logo

PostgreSQL
| The world's most advanced open source database.

rangetypes.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * rangetypes.c
00004  *    I/O functions, operators, and support functions for range types.
00005  *
00006  * The stored (serialized) format of a range value is:
00007  *
00008  *  4 bytes: varlena header
00009  *  4 bytes: range type's OID
00010  *  Lower boundary value, if any, aligned according to subtype's typalign
00011  *  Upper boundary value, if any, aligned according to subtype's typalign
00012  *  1 byte for flags
00013  *
00014  * This representation is chosen to avoid needing any padding before the
00015  * lower boundary value, even when it requires double alignment.  We can
00016  * expect that the varlena header is presented to us on a suitably aligned
00017  * boundary (possibly after detoasting), and then the lower boundary is too.
00018  * Note that this means we can't work with a packed (short varlena header)
00019  * value; we must detoast it first.
00020  *
00021  *
00022  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00023  * Portions Copyright (c) 1994, Regents of the University of California
00024  *
00025  *
00026  * IDENTIFICATION
00027  *    src/backend/utils/adt/rangetypes.c
00028  *
00029  *-------------------------------------------------------------------------
00030  */
00031 #include "postgres.h"
00032 
00033 #include "access/hash.h"
00034 #include "lib/stringinfo.h"
00035 #include "libpq/pqformat.h"
00036 #include "utils/builtins.h"
00037 #include "utils/date.h"
00038 #include "utils/int8.h"
00039 #include "utils/lsyscache.h"
00040 #include "utils/rangetypes.h"
00041 #include "utils/timestamp.h"
00042 
00043 
00044 #define RANGE_EMPTY_LITERAL "empty"
00045 
00046 /* fn_extra cache entry for one of the range I/O functions */
00047 typedef struct RangeIOData
00048 {
00049     TypeCacheEntry *typcache;   /* range type's typcache entry */
00050     Oid         typiofunc;      /* element type's I/O function */
00051     Oid         typioparam;     /* element type's I/O parameter */
00052     FmgrInfo    proc;           /* lookup result for typiofunc */
00053 } RangeIOData;
00054 
00055 
00056 static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
00057                   IOFuncSelector func);
00058 static char range_parse_flags(const char *flags_str);
00059 static void range_parse(const char *input_str, char *flags, char **lbound_str,
00060             char **ubound_str);
00061 static const char *range_parse_bound(const char *string, const char *ptr,
00062                   char **bound_str, bool *infinite);
00063 static char *range_deparse(char flags, const char *lbound_str,
00064               const char *ubound_str);
00065 static char *range_bound_escape(const char *value);
00066 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
00067                    char typalign, int16 typlen, char typstorage);
00068 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
00069             char typalign, int16 typlen, char typstorage);
00070 
00071 
00072 /*
00073  *----------------------------------------------------------
00074  * I/O FUNCTIONS
00075  *----------------------------------------------------------
00076  */
00077 
00078 Datum
00079 range_in(PG_FUNCTION_ARGS)
00080 {
00081     char       *input_str = PG_GETARG_CSTRING(0);
00082     Oid         rngtypoid = PG_GETARG_OID(1);
00083     Oid         typmod = PG_GETARG_INT32(2);
00084     RangeType  *range;
00085     RangeIOData *cache;
00086     char        flags;
00087     char       *lbound_str;
00088     char       *ubound_str;
00089     RangeBound  lower;
00090     RangeBound  upper;
00091 
00092     cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
00093 
00094     /* parse */
00095     range_parse(input_str, &flags, &lbound_str, &ubound_str);
00096 
00097     /* call element type's input function */
00098     if (RANGE_HAS_LBOUND(flags))
00099         lower.val = InputFunctionCall(&cache->proc, lbound_str,
00100                                       cache->typioparam, typmod);
00101     if (RANGE_HAS_UBOUND(flags))
00102         upper.val = InputFunctionCall(&cache->proc, ubound_str,
00103                                       cache->typioparam, typmod);
00104 
00105     lower.infinite = (flags & RANGE_LB_INF) != 0;
00106     lower.inclusive = (flags & RANGE_LB_INC) != 0;
00107     lower.lower = true;
00108     upper.infinite = (flags & RANGE_UB_INF) != 0;
00109     upper.inclusive = (flags & RANGE_UB_INC) != 0;
00110     upper.lower = false;
00111 
00112     /* serialize and canonicalize */
00113     range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
00114 
00115     PG_RETURN_RANGE(range);
00116 }
00117 
00118 Datum
00119 range_out(PG_FUNCTION_ARGS)
00120 {
00121     RangeType  *range = PG_GETARG_RANGE(0);
00122     char       *output_str;
00123     RangeIOData *cache;
00124     char        flags;
00125     char       *lbound_str = NULL;
00126     char       *ubound_str = NULL;
00127     RangeBound  lower;
00128     RangeBound  upper;
00129     bool        empty;
00130 
00131     cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
00132 
00133     /* deserialize */
00134     range_deserialize(cache->typcache, range, &lower, &upper, &empty);
00135     flags = range_get_flags(range);
00136 
00137     /* call element type's output function */
00138     if (RANGE_HAS_LBOUND(flags))
00139         lbound_str = OutputFunctionCall(&cache->proc, lower.val);
00140     if (RANGE_HAS_UBOUND(flags))
00141         ubound_str = OutputFunctionCall(&cache->proc, upper.val);
00142 
00143     /* construct result string */
00144     output_str = range_deparse(flags, lbound_str, ubound_str);
00145 
00146     PG_RETURN_CSTRING(output_str);
00147 }
00148 
00149 /*
00150  * Binary representation: The first byte is the flags, then the lower bound
00151  * (if present), then the upper bound (if present).  Each bound is represented
00152  * by a 4-byte length header and the binary representation of that bound (as
00153  * returned by a call to the send function for the subtype).
00154  */
00155 
00156 Datum
00157 range_recv(PG_FUNCTION_ARGS)
00158 {
00159     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
00160     Oid         rngtypoid = PG_GETARG_OID(1);
00161     int32       typmod = PG_GETARG_INT32(2);
00162     RangeType  *range;
00163     RangeIOData *cache;
00164     char        flags;
00165     RangeBound  lower;
00166     RangeBound  upper;
00167 
00168     cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
00169 
00170     /* receive the flags... */
00171     flags = (unsigned char) pq_getmsgbyte(buf);
00172 
00173     /*
00174      * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
00175      * confuse following tests.  Note that range_serialize will take care of
00176      * cleaning up any inconsistencies in the remaining flags.
00177      */
00178     flags &= (RANGE_EMPTY |
00179               RANGE_LB_INC |
00180               RANGE_LB_INF |
00181               RANGE_UB_INC |
00182               RANGE_UB_INF);
00183 
00184     /* receive the bounds ... */
00185     if (RANGE_HAS_LBOUND(flags))
00186     {
00187         uint32      bound_len = pq_getmsgint(buf, 4);
00188         const char *bound_data = pq_getmsgbytes(buf, bound_len);
00189         StringInfoData bound_buf;
00190 
00191         initStringInfo(&bound_buf);
00192         appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
00193 
00194         lower.val = ReceiveFunctionCall(&cache->proc,
00195                                         &bound_buf,
00196                                         cache->typioparam,
00197                                         typmod);
00198         pfree(bound_buf.data);
00199     }
00200     else
00201         lower.val = (Datum) 0;
00202 
00203     if (RANGE_HAS_UBOUND(flags))
00204     {
00205         uint32      bound_len = pq_getmsgint(buf, 4);
00206         const char *bound_data = pq_getmsgbytes(buf, bound_len);
00207         StringInfoData bound_buf;
00208 
00209         initStringInfo(&bound_buf);
00210         appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
00211 
00212         upper.val = ReceiveFunctionCall(&cache->proc,
00213                                         &bound_buf,
00214                                         cache->typioparam,
00215                                         typmod);
00216         pfree(bound_buf.data);
00217     }
00218     else
00219         upper.val = (Datum) 0;
00220 
00221     pq_getmsgend(buf);
00222 
00223     /* finish constructing RangeBound representation */
00224     lower.infinite = (flags & RANGE_LB_INF) != 0;
00225     lower.inclusive = (flags & RANGE_LB_INC) != 0;
00226     lower.lower = true;
00227     upper.infinite = (flags & RANGE_UB_INF) != 0;
00228     upper.inclusive = (flags & RANGE_UB_INC) != 0;
00229     upper.lower = false;
00230 
00231     /* serialize and canonicalize */
00232     range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
00233 
00234     PG_RETURN_RANGE(range);
00235 }
00236 
00237 Datum
00238 range_send(PG_FUNCTION_ARGS)
00239 {
00240     RangeType  *range = PG_GETARG_RANGE(0);
00241     StringInfo  buf = makeStringInfo();
00242     RangeIOData *cache;
00243     char        flags;
00244     RangeBound  lower;
00245     RangeBound  upper;
00246     bool        empty;
00247 
00248     cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
00249 
00250     /* deserialize */
00251     range_deserialize(cache->typcache, range, &lower, &upper, &empty);
00252     flags = range_get_flags(range);
00253 
00254     /* construct output */
00255     pq_begintypsend(buf);
00256 
00257     pq_sendbyte(buf, flags);
00258 
00259     if (RANGE_HAS_LBOUND(flags))
00260     {
00261         Datum       bound = PointerGetDatum(SendFunctionCall(&cache->proc,
00262                                                              lower.val));
00263         uint32      bound_len = VARSIZE(bound) - VARHDRSZ;
00264         char       *bound_data = VARDATA(bound);
00265 
00266         pq_sendint(buf, bound_len, 4);
00267         pq_sendbytes(buf, bound_data, bound_len);
00268     }
00269 
00270     if (RANGE_HAS_UBOUND(flags))
00271     {
00272         Datum       bound = PointerGetDatum(SendFunctionCall(&cache->proc,
00273                                                              upper.val));
00274         uint32      bound_len = VARSIZE(bound) - VARHDRSZ;
00275         char       *bound_data = VARDATA(bound);
00276 
00277         pq_sendint(buf, bound_len, 4);
00278         pq_sendbytes(buf, bound_data, bound_len);
00279     }
00280 
00281     PG_RETURN_BYTEA_P(pq_endtypsend(buf));
00282 }
00283 
00284 /*
00285  * get_range_io_data: get cached information needed for range type I/O
00286  *
00287  * The range I/O functions need a bit more cached info than other range
00288  * functions, so they store a RangeIOData struct in fn_extra, not just a
00289  * pointer to a type cache entry.
00290  */
00291 static RangeIOData *
00292 get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
00293 {
00294     RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
00295 
00296     if (cache == NULL || cache->typcache->type_id != rngtypid)
00297     {
00298         int16       typlen;
00299         bool        typbyval;
00300         char        typalign;
00301         char        typdelim;
00302 
00303         cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
00304                                                    sizeof(RangeIOData));
00305         cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
00306         if (cache->typcache->rngelemtype == NULL)
00307             elog(ERROR, "type %u is not a range type", rngtypid);
00308 
00309         /* get_type_io_data does more than we need, but is convenient */
00310         get_type_io_data(cache->typcache->rngelemtype->type_id,
00311                          func,
00312                          &typlen,
00313                          &typbyval,
00314                          &typalign,
00315                          &typdelim,
00316                          &cache->typioparam,
00317                          &cache->typiofunc);
00318 
00319         if (!OidIsValid(cache->typiofunc))
00320         {
00321             /* this could only happen for receive or send */
00322             if (func == IOFunc_receive)
00323                 ereport(ERROR,
00324                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
00325                      errmsg("no binary input function available for type %s",
00326                     format_type_be(cache->typcache->rngelemtype->type_id))));
00327             else
00328                 ereport(ERROR,
00329                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
00330                     errmsg("no binary output function available for type %s",
00331                     format_type_be(cache->typcache->rngelemtype->type_id))));
00332         }
00333         fmgr_info_cxt(cache->typiofunc, &cache->proc,
00334                       fcinfo->flinfo->fn_mcxt);
00335 
00336         fcinfo->flinfo->fn_extra = (void *) cache;
00337     }
00338 
00339     return cache;
00340 }
00341 
00342 
00343 /*
00344  *----------------------------------------------------------
00345  * GENERIC FUNCTIONS
00346  *----------------------------------------------------------
00347  */
00348 
00349 /* Construct standard-form range value from two arguments */
00350 Datum
00351 range_constructor2(PG_FUNCTION_ARGS)
00352 {
00353     Datum       arg1 = PG_GETARG_DATUM(0);
00354     Datum       arg2 = PG_GETARG_DATUM(1);
00355     Oid         rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
00356     RangeType  *range;
00357     TypeCacheEntry *typcache;
00358     RangeBound  lower;
00359     RangeBound  upper;
00360 
00361     typcache = range_get_typcache(fcinfo, rngtypid);
00362 
00363     lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
00364     lower.infinite = PG_ARGISNULL(0);
00365     lower.inclusive = true;
00366     lower.lower = true;
00367 
00368     upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
00369     upper.infinite = PG_ARGISNULL(1);
00370     upper.inclusive = false;
00371     upper.lower = false;
00372 
00373     range = make_range(typcache, &lower, &upper, false);
00374 
00375     PG_RETURN_RANGE(range);
00376 }
00377 
00378 /* Construct general range value from three arguments */
00379 Datum
00380 range_constructor3(PG_FUNCTION_ARGS)
00381 {
00382     Datum       arg1 = PG_GETARG_DATUM(0);
00383     Datum       arg2 = PG_GETARG_DATUM(1);
00384     Oid         rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
00385     RangeType  *range;
00386     TypeCacheEntry *typcache;
00387     RangeBound  lower;
00388     RangeBound  upper;
00389     char        flags;
00390 
00391     typcache = range_get_typcache(fcinfo, rngtypid);
00392 
00393     if (PG_ARGISNULL(2))
00394         ereport(ERROR,
00395                 (errcode(ERRCODE_DATA_EXCEPTION),
00396                errmsg("range constructor flags argument must not be null")));
00397 
00398     flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_P(2)));
00399 
00400     lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
00401     lower.infinite = PG_ARGISNULL(0);
00402     lower.inclusive = (flags & RANGE_LB_INC) != 0;
00403     lower.lower = true;
00404 
00405     upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
00406     upper.infinite = PG_ARGISNULL(1);
00407     upper.inclusive = (flags & RANGE_UB_INC) != 0;
00408     upper.lower = false;
00409 
00410     range = make_range(typcache, &lower, &upper, false);
00411 
00412     PG_RETURN_RANGE(range);
00413 }
00414 
00415 
00416 /* range -> subtype functions */
00417 
00418 /* extract lower bound value */
00419 Datum
00420 range_lower(PG_FUNCTION_ARGS)
00421 {
00422     RangeType  *r1 = PG_GETARG_RANGE(0);
00423     TypeCacheEntry *typcache;
00424     RangeBound  lower;
00425     RangeBound  upper;
00426     bool        empty;
00427 
00428     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00429 
00430     range_deserialize(typcache, r1, &lower, &upper, &empty);
00431 
00432     /* Return NULL if there's no finite lower bound */
00433     if (empty || lower.infinite)
00434         PG_RETURN_NULL();
00435 
00436     PG_RETURN_DATUM(lower.val);
00437 }
00438 
00439 /* extract upper bound value */
00440 Datum
00441 range_upper(PG_FUNCTION_ARGS)
00442 {
00443     RangeType  *r1 = PG_GETARG_RANGE(0);
00444     TypeCacheEntry *typcache;
00445     RangeBound  lower;
00446     RangeBound  upper;
00447     bool        empty;
00448 
00449     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00450 
00451     range_deserialize(typcache, r1, &lower, &upper, &empty);
00452 
00453     /* Return NULL if there's no finite upper bound */
00454     if (empty || upper.infinite)
00455         PG_RETURN_NULL();
00456 
00457     PG_RETURN_DATUM(upper.val);
00458 }
00459 
00460 
00461 /* range -> bool functions */
00462 
00463 /* is range empty? */
00464 Datum
00465 range_empty(PG_FUNCTION_ARGS)
00466 {
00467     RangeType  *r1 = PG_GETARG_RANGE(0);
00468     char        flags = range_get_flags(r1);
00469 
00470     PG_RETURN_BOOL(flags & RANGE_EMPTY);
00471 }
00472 
00473 /* is lower bound inclusive? */
00474 Datum
00475 range_lower_inc(PG_FUNCTION_ARGS)
00476 {
00477     RangeType  *r1 = PG_GETARG_RANGE(0);
00478     char        flags = range_get_flags(r1);
00479 
00480     PG_RETURN_BOOL(flags & RANGE_LB_INC);
00481 }
00482 
00483 /* is upper bound inclusive? */
00484 Datum
00485 range_upper_inc(PG_FUNCTION_ARGS)
00486 {
00487     RangeType  *r1 = PG_GETARG_RANGE(0);
00488     char        flags = range_get_flags(r1);
00489 
00490     PG_RETURN_BOOL(flags & RANGE_UB_INC);
00491 }
00492 
00493 /* is lower bound infinite? */
00494 Datum
00495 range_lower_inf(PG_FUNCTION_ARGS)
00496 {
00497     RangeType  *r1 = PG_GETARG_RANGE(0);
00498     char        flags = range_get_flags(r1);
00499 
00500     PG_RETURN_BOOL(flags & RANGE_LB_INF);
00501 }
00502 
00503 /* is upper bound infinite? */
00504 Datum
00505 range_upper_inf(PG_FUNCTION_ARGS)
00506 {
00507     RangeType  *r1 = PG_GETARG_RANGE(0);
00508     char        flags = range_get_flags(r1);
00509 
00510     PG_RETURN_BOOL(flags & RANGE_UB_INF);
00511 }
00512 
00513 
00514 /* range, element -> bool functions */
00515 
00516 /* contains? */
00517 Datum
00518 range_contains_elem(PG_FUNCTION_ARGS)
00519 {
00520     RangeType  *r = PG_GETARG_RANGE(0);
00521     Datum       val = PG_GETARG_DATUM(1);
00522     TypeCacheEntry *typcache;
00523 
00524     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
00525 
00526     PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
00527 }
00528 
00529 /* contained by? */
00530 Datum
00531 elem_contained_by_range(PG_FUNCTION_ARGS)
00532 {
00533     Datum       val = PG_GETARG_DATUM(0);
00534     RangeType  *r = PG_GETARG_RANGE(1);
00535     TypeCacheEntry *typcache;
00536 
00537     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
00538 
00539     PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
00540 }
00541 
00542 
00543 /* range, range -> bool functions */
00544 
00545 /* equality (internal version) */
00546 bool
00547 range_eq_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00548 {
00549     RangeBound  lower1,
00550                 lower2;
00551     RangeBound  upper1,
00552                 upper2;
00553     bool        empty1,
00554                 empty2;
00555 
00556     /* Different types should be prevented by ANYRANGE matching rules */
00557     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00558         elog(ERROR, "range types do not match");
00559 
00560     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00561     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00562 
00563     if (empty1 && empty2)
00564         return true;
00565     if (empty1 != empty2)
00566         return false;
00567 
00568     if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
00569         return false;
00570 
00571     if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
00572         return false;
00573 
00574     return true;
00575 }
00576 
00577 /* equality */
00578 Datum
00579 range_eq(PG_FUNCTION_ARGS)
00580 {
00581     RangeType  *r1 = PG_GETARG_RANGE(0);
00582     RangeType  *r2 = PG_GETARG_RANGE(1);
00583     TypeCacheEntry *typcache;
00584 
00585     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00586 
00587     PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
00588 }
00589 
00590 /* inequality (internal version) */
00591 bool
00592 range_ne_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00593 {
00594     return (!range_eq_internal(typcache, r1, r2));
00595 }
00596 
00597 /* inequality */
00598 Datum
00599 range_ne(PG_FUNCTION_ARGS)
00600 {
00601     RangeType  *r1 = PG_GETARG_RANGE(0);
00602     RangeType  *r2 = PG_GETARG_RANGE(1);
00603     TypeCacheEntry *typcache;
00604 
00605     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00606 
00607     PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
00608 }
00609 
00610 /* contains? */
00611 Datum
00612 range_contains(PG_FUNCTION_ARGS)
00613 {
00614     RangeType  *r1 = PG_GETARG_RANGE(0);
00615     RangeType  *r2 = PG_GETARG_RANGE(1);
00616     TypeCacheEntry *typcache;
00617 
00618     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00619 
00620     PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
00621 }
00622 
00623 /* contained by? */
00624 Datum
00625 range_contained_by(PG_FUNCTION_ARGS)
00626 {
00627     RangeType  *r1 = PG_GETARG_RANGE(0);
00628     RangeType  *r2 = PG_GETARG_RANGE(1);
00629     TypeCacheEntry *typcache;
00630 
00631     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00632 
00633     PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
00634 }
00635 
00636 /* strictly left of? (internal version) */
00637 bool
00638 range_before_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00639 {
00640     RangeBound  lower1,
00641                 lower2;
00642     RangeBound  upper1,
00643                 upper2;
00644     bool        empty1,
00645                 empty2;
00646 
00647     /* Different types should be prevented by ANYRANGE matching rules */
00648     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00649         elog(ERROR, "range types do not match");
00650 
00651     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00652     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00653 
00654     /* An empty range is neither before nor after any other range */
00655     if (empty1 || empty2)
00656         return false;
00657 
00658     return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
00659 }
00660 
00661 /* strictly left of? */
00662 Datum
00663 range_before(PG_FUNCTION_ARGS)
00664 {
00665     RangeType  *r1 = PG_GETARG_RANGE(0);
00666     RangeType  *r2 = PG_GETARG_RANGE(1);
00667     TypeCacheEntry *typcache;
00668 
00669     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00670 
00671     PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
00672 }
00673 
00674 /* strictly right of? (internal version) */
00675 bool
00676 range_after_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00677 {
00678     RangeBound  lower1,
00679                 lower2;
00680     RangeBound  upper1,
00681                 upper2;
00682     bool        empty1,
00683                 empty2;
00684 
00685     /* Different types should be prevented by ANYRANGE matching rules */
00686     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00687         elog(ERROR, "range types do not match");
00688 
00689     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00690     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00691 
00692     /* An empty range is neither before nor after any other range */
00693     if (empty1 || empty2)
00694         return false;
00695 
00696     return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
00697 }
00698 
00699 /* strictly right of? */
00700 Datum
00701 range_after(PG_FUNCTION_ARGS)
00702 {
00703     RangeType  *r1 = PG_GETARG_RANGE(0);
00704     RangeType  *r2 = PG_GETARG_RANGE(1);
00705     TypeCacheEntry *typcache;
00706 
00707     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00708 
00709     PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
00710 }
00711 
00712 /*
00713  * Check if two bounds A and B are "adjacent", where A is an upper bound and B
00714  * is a lower bound. For the bounds to be adjacent, each subtype value must
00715  * satisfy strictly one of the bounds: there are no values which satisfy both
00716  * bounds (i.e. less than A and greater than B); and there are no values which
00717  * satisfy neither bound (i.e. greater than A and less than B).
00718  *
00719  * For discrete ranges, we rely on the canonicalization function to see if A..B
00720  * normalizes to empty. (If there is no canonicalization function, it's
00721  * impossible for such a range to normalize to empty, so we needn't bother to
00722  * try.)
00723  *
00724  * If A == B, the ranges are adjacent only if the bounds have different
00725  * inclusive flags (i.e., exactly one of the ranges includes the common
00726  * boundary point).
00727  *
00728  * And if A > B then the ranges are not adjacent in this order.
00729  */
00730 bool
00731 bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
00732 {
00733     int         cmp;
00734 
00735     Assert(!boundA.lower && boundB.lower);
00736 
00737     cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
00738     if (cmp < 0)
00739     {
00740         RangeType *r;
00741 
00742         /*
00743          * Bounds do not overlap; see if there are points in between.
00744          */
00745 
00746         /* in a continuous subtype, there are assumed to be points between */
00747         if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
00748             return false;
00749 
00750         /*
00751          * The bounds are of a discrete range type; so make a range A..B and
00752          * see if it's empty.
00753          */
00754 
00755         /* flip the inclusion flags */
00756         boundA.inclusive = !boundA.inclusive;
00757         boundB.inclusive = !boundB.inclusive;
00758         /* change upper/lower labels to avoid Assert failures */
00759         boundA.lower = true;
00760         boundB.lower = false;
00761         r = make_range(typcache, &boundA, &boundB, false);
00762         return RangeIsEmpty(r);
00763     }
00764     else if (cmp == 0)
00765         return boundA.inclusive != boundB.inclusive;
00766     else
00767         return false;       /* bounds overlap */
00768 }
00769 
00770 /* adjacent to (but not overlapping)? (internal version) */
00771 bool
00772 range_adjacent_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00773 {
00774     RangeBound  lower1,
00775                 lower2;
00776     RangeBound  upper1,
00777                 upper2;
00778     bool        empty1,
00779                 empty2;
00780 
00781     /* Different types should be prevented by ANYRANGE matching rules */
00782     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00783         elog(ERROR, "range types do not match");
00784 
00785     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00786     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00787 
00788     /* An empty range is not adjacent to any other range */
00789     if (empty1 || empty2)
00790         return false;
00791 
00792     /*
00793      * Given two ranges A..B and C..D, the ranges are adjacent if and only if
00794      * B is adjacent to C, or D is adjacent to A.
00795      */
00796     return (bounds_adjacent(typcache, upper1, lower2) ||
00797             bounds_adjacent(typcache, upper2, lower1));
00798 }
00799 
00800 /* adjacent to (but not overlapping)? */
00801 Datum
00802 range_adjacent(PG_FUNCTION_ARGS)
00803 {
00804     RangeType  *r1 = PG_GETARG_RANGE(0);
00805     RangeType  *r2 = PG_GETARG_RANGE(1);
00806     TypeCacheEntry *typcache;
00807 
00808     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00809 
00810     PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
00811 }
00812 
00813 /* overlaps? (internal version) */
00814 bool
00815 range_overlaps_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00816 {
00817     RangeBound  lower1,
00818                 lower2;
00819     RangeBound  upper1,
00820                 upper2;
00821     bool        empty1,
00822                 empty2;
00823 
00824     /* Different types should be prevented by ANYRANGE matching rules */
00825     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00826         elog(ERROR, "range types do not match");
00827 
00828     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00829     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00830 
00831     /* An empty range does not overlap any other range */
00832     if (empty1 || empty2)
00833         return false;
00834 
00835     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
00836         range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
00837         return true;
00838 
00839     if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
00840         range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
00841         return true;
00842 
00843     return false;
00844 }
00845 
00846 /* overlaps? */
00847 Datum
00848 range_overlaps(PG_FUNCTION_ARGS)
00849 {
00850     RangeType  *r1 = PG_GETARG_RANGE(0);
00851     RangeType  *r2 = PG_GETARG_RANGE(1);
00852     TypeCacheEntry *typcache;
00853 
00854     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00855 
00856     PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
00857 }
00858 
00859 /* does not extend to right of? (internal version) */
00860 bool
00861 range_overleft_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00862 {
00863     RangeBound  lower1,
00864                 lower2;
00865     RangeBound  upper1,
00866                 upper2;
00867     bool        empty1,
00868                 empty2;
00869 
00870     /* Different types should be prevented by ANYRANGE matching rules */
00871     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00872         elog(ERROR, "range types do not match");
00873 
00874     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00875     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00876 
00877     /* An empty range is neither before nor after any other range */
00878     if (empty1 || empty2)
00879         return false;
00880 
00881     if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
00882         return true;
00883 
00884     return false;
00885 }
00886 
00887 /* does not extend to right of? */
00888 Datum
00889 range_overleft(PG_FUNCTION_ARGS)
00890 {
00891     RangeType  *r1 = PG_GETARG_RANGE(0);
00892     RangeType  *r2 = PG_GETARG_RANGE(1);
00893     TypeCacheEntry *typcache;
00894 
00895     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00896 
00897     PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
00898 }
00899 
00900 /* does not extend to left of? (internal version) */
00901 bool
00902 range_overright_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
00903 {
00904     RangeBound  lower1,
00905                 lower2;
00906     RangeBound  upper1,
00907                 upper2;
00908     bool        empty1,
00909                 empty2;
00910 
00911     /* Different types should be prevented by ANYRANGE matching rules */
00912     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00913         elog(ERROR, "range types do not match");
00914 
00915     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00916     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00917 
00918     /* An empty range is neither before nor after any other range */
00919     if (empty1 || empty2)
00920         PG_RETURN_BOOL(false);
00921 
00922     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
00923         PG_RETURN_BOOL(true);
00924 
00925     PG_RETURN_BOOL(false);
00926 }
00927 
00928 /* does not extend to left of? */
00929 Datum
00930 range_overright(PG_FUNCTION_ARGS)
00931 {
00932     RangeType  *r1 = PG_GETARG_RANGE(0);
00933     RangeType  *r2 = PG_GETARG_RANGE(1);
00934     TypeCacheEntry *typcache;
00935 
00936     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00937 
00938     PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
00939 }
00940 
00941 
00942 /* range, range -> range functions */
00943 
00944 /* set difference */
00945 Datum
00946 range_minus(PG_FUNCTION_ARGS)
00947 {
00948     RangeType  *r1 = PG_GETARG_RANGE(0);
00949     RangeType  *r2 = PG_GETARG_RANGE(1);
00950     TypeCacheEntry *typcache;
00951     RangeBound  lower1,
00952                 lower2;
00953     RangeBound  upper1,
00954                 upper2;
00955     bool        empty1,
00956                 empty2;
00957     int         cmp_l1l2,
00958                 cmp_l1u2,
00959                 cmp_u1l2,
00960                 cmp_u1u2;
00961 
00962     /* Different types should be prevented by ANYRANGE matching rules */
00963     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
00964         elog(ERROR, "range types do not match");
00965 
00966     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
00967 
00968     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
00969     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
00970 
00971     /* if either is empty, r1 is the correct answer */
00972     if (empty1 || empty2)
00973         PG_RETURN_RANGE(r1);
00974 
00975     cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
00976     cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
00977     cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
00978     cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
00979 
00980     if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
00981         ereport(ERROR,
00982                 (errcode(ERRCODE_DATA_EXCEPTION),
00983               errmsg("result of range difference would not be contiguous")));
00984 
00985     if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
00986         PG_RETURN_RANGE(r1);
00987 
00988     if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
00989         PG_RETURN_RANGE(make_empty_range(typcache));
00990 
00991     if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
00992     {
00993         lower2.inclusive = !lower2.inclusive;
00994         lower2.lower = false;   /* it will become the upper bound */
00995         PG_RETURN_RANGE(make_range(typcache, &lower1, &lower2, false));
00996     }
00997 
00998     if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
00999     {
01000         upper2.inclusive = !upper2.inclusive;
01001         upper2.lower = true;    /* it will become the lower bound */
01002         PG_RETURN_RANGE(make_range(typcache, &upper2, &upper1, false));
01003     }
01004 
01005     elog(ERROR, "unexpected case in range_minus");
01006     PG_RETURN_NULL();
01007 }
01008 
01009 /* set union */
01010 Datum
01011 range_union(PG_FUNCTION_ARGS)
01012 {
01013     RangeType  *r1 = PG_GETARG_RANGE(0);
01014     RangeType  *r2 = PG_GETARG_RANGE(1);
01015     TypeCacheEntry *typcache;
01016     RangeBound  lower1,
01017                 lower2;
01018     RangeBound  upper1,
01019                 upper2;
01020     bool        empty1,
01021                 empty2;
01022     RangeBound *result_lower;
01023     RangeBound *result_upper;
01024 
01025     /* Different types should be prevented by ANYRANGE matching rules */
01026     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
01027         elog(ERROR, "range types do not match");
01028 
01029     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
01030 
01031     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
01032     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
01033 
01034     /* if either is empty, the other is the correct answer */
01035     if (empty1)
01036         PG_RETURN_RANGE(r2);
01037     if (empty2)
01038         PG_RETURN_RANGE(r1);
01039 
01040     if (!DatumGetBool(range_overlaps(fcinfo)) &&
01041         !DatumGetBool(range_adjacent(fcinfo)))
01042         ereport(ERROR,
01043                 (errcode(ERRCODE_DATA_EXCEPTION),
01044                  errmsg("result of range union would not be contiguous")));
01045 
01046     if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
01047         result_lower = &lower1;
01048     else
01049         result_lower = &lower2;
01050 
01051     if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
01052         result_upper = &upper1;
01053     else
01054         result_upper = &upper2;
01055 
01056     PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false));
01057 }
01058 
01059 /* set intersection */
01060 Datum
01061 range_intersect(PG_FUNCTION_ARGS)
01062 {
01063     RangeType  *r1 = PG_GETARG_RANGE(0);
01064     RangeType  *r2 = PG_GETARG_RANGE(1);
01065     TypeCacheEntry *typcache;
01066     RangeBound  lower1,
01067                 lower2;
01068     RangeBound  upper1,
01069                 upper2;
01070     bool        empty1,
01071                 empty2;
01072     RangeBound *result_lower;
01073     RangeBound *result_upper;
01074 
01075     /* Different types should be prevented by ANYRANGE matching rules */
01076     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
01077         elog(ERROR, "range types do not match");
01078 
01079     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
01080 
01081     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
01082     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
01083 
01084     if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
01085         PG_RETURN_RANGE(make_empty_range(typcache));
01086 
01087     if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
01088         result_lower = &lower1;
01089     else
01090         result_lower = &lower2;
01091 
01092     if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
01093         result_upper = &upper1;
01094     else
01095         result_upper = &upper2;
01096 
01097     PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false));
01098 }
01099 
01100 /* Btree support */
01101 
01102 /* btree comparator */
01103 Datum
01104 range_cmp(PG_FUNCTION_ARGS)
01105 {
01106     RangeType  *r1 = PG_GETARG_RANGE(0);
01107     RangeType  *r2 = PG_GETARG_RANGE(1);
01108     TypeCacheEntry *typcache;
01109     RangeBound  lower1,
01110                 lower2;
01111     RangeBound  upper1,
01112                 upper2;
01113     bool        empty1,
01114                 empty2;
01115     int         cmp;
01116 
01117     /* Different types should be prevented by ANYRANGE matching rules */
01118     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
01119         elog(ERROR, "range types do not match");
01120 
01121     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
01122 
01123     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
01124     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
01125 
01126     /* For b-tree use, empty ranges sort before all else */
01127     if (empty1 && empty2)
01128         PG_RETURN_INT32(0);
01129     else if (empty1)
01130         PG_RETURN_INT32(-1);
01131     else if (empty2)
01132         PG_RETURN_INT32(1);
01133 
01134     if ((cmp = range_cmp_bounds(typcache, &lower1, &lower2)) != 0)
01135         PG_RETURN_INT32(cmp);
01136 
01137     PG_RETURN_INT32(range_cmp_bounds(typcache, &upper1, &upper2));
01138 }
01139 
01140 /* inequality operators using the range_cmp function */
01141 Datum
01142 range_lt(PG_FUNCTION_ARGS)
01143 {
01144     int         cmp = range_cmp(fcinfo);
01145 
01146     PG_RETURN_BOOL(cmp < 0);
01147 }
01148 
01149 Datum
01150 range_le(PG_FUNCTION_ARGS)
01151 {
01152     int         cmp = range_cmp(fcinfo);
01153 
01154     PG_RETURN_BOOL(cmp <= 0);
01155 }
01156 
01157 Datum
01158 range_ge(PG_FUNCTION_ARGS)
01159 {
01160     int         cmp = range_cmp(fcinfo);
01161 
01162     PG_RETURN_BOOL(cmp >= 0);
01163 }
01164 
01165 Datum
01166 range_gt(PG_FUNCTION_ARGS)
01167 {
01168     int         cmp = range_cmp(fcinfo);
01169 
01170     PG_RETURN_BOOL(cmp > 0);
01171 }
01172 
01173 /* Hash support */
01174 
01175 /* hash a range value */
01176 Datum
01177 hash_range(PG_FUNCTION_ARGS)
01178 {
01179     RangeType  *r = PG_GETARG_RANGE(0);
01180     uint32      result;
01181     TypeCacheEntry *typcache;
01182     TypeCacheEntry *scache;
01183     RangeBound  lower;
01184     RangeBound  upper;
01185     bool        empty;
01186     char        flags;
01187     uint32      lower_hash;
01188     uint32      upper_hash;
01189 
01190     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
01191 
01192     /* deserialize */
01193     range_deserialize(typcache, r, &lower, &upper, &empty);
01194     flags = range_get_flags(r);
01195 
01196     /*
01197      * Look up the element type's hash function, if not done already.
01198      */
01199     scache = typcache->rngelemtype;
01200     if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
01201     {
01202         scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
01203         if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
01204             ereport(ERROR,
01205                     (errcode(ERRCODE_UNDEFINED_FUNCTION),
01206                      errmsg("could not identify a hash function for type %s",
01207                             format_type_be(scache->type_id))));
01208     }
01209 
01210     /*
01211      * Apply the hash function to each bound.
01212      */
01213     if (RANGE_HAS_LBOUND(flags))
01214         lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
01215                                                       typcache->rng_collation,
01216                                                       lower.val));
01217     else
01218         lower_hash = 0;
01219 
01220     if (RANGE_HAS_UBOUND(flags))
01221         upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
01222                                                       typcache->rng_collation,
01223                                                       upper.val));
01224     else
01225         upper_hash = 0;
01226 
01227     /* Merge hashes of flags and bounds */
01228     result = hash_uint32((uint32) flags);
01229     result ^= lower_hash;
01230     result = (result << 1) | (result >> 31);
01231     result ^= upper_hash;
01232 
01233     PG_RETURN_INT32(result);
01234 }
01235 
01236 /*
01237  *----------------------------------------------------------
01238  * CANONICAL FUNCTIONS
01239  *
01240  *   Functions for specific built-in range types.
01241  *----------------------------------------------------------
01242  */
01243 
01244 Datum
01245 int4range_canonical(PG_FUNCTION_ARGS)
01246 {
01247     RangeType  *r = PG_GETARG_RANGE(0);
01248     TypeCacheEntry *typcache;
01249     RangeBound  lower;
01250     RangeBound  upper;
01251     bool        empty;
01252 
01253     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
01254 
01255     range_deserialize(typcache, r, &lower, &upper, &empty);
01256 
01257     if (empty)
01258         PG_RETURN_RANGE(r);
01259 
01260     if (!lower.infinite && !lower.inclusive)
01261     {
01262         lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
01263         lower.inclusive = true;
01264     }
01265 
01266     if (!upper.infinite && upper.inclusive)
01267     {
01268         upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
01269         upper.inclusive = false;
01270     }
01271 
01272     PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
01273 }
01274 
01275 Datum
01276 int8range_canonical(PG_FUNCTION_ARGS)
01277 {
01278     RangeType  *r = PG_GETARG_RANGE(0);
01279     TypeCacheEntry *typcache;
01280     RangeBound  lower;
01281     RangeBound  upper;
01282     bool        empty;
01283 
01284     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
01285 
01286     range_deserialize(typcache, r, &lower, &upper, &empty);
01287 
01288     if (empty)
01289         PG_RETURN_RANGE(r);
01290 
01291     if (!lower.infinite && !lower.inclusive)
01292     {
01293         lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
01294         lower.inclusive = true;
01295     }
01296 
01297     if (!upper.infinite && upper.inclusive)
01298     {
01299         upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
01300         upper.inclusive = false;
01301     }
01302 
01303     PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
01304 }
01305 
01306 Datum
01307 daterange_canonical(PG_FUNCTION_ARGS)
01308 {
01309     RangeType  *r = PG_GETARG_RANGE(0);
01310     TypeCacheEntry *typcache;
01311     RangeBound  lower;
01312     RangeBound  upper;
01313     bool        empty;
01314 
01315     typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
01316 
01317     range_deserialize(typcache, r, &lower, &upper, &empty);
01318 
01319     if (empty)
01320         PG_RETURN_RANGE(r);
01321 
01322     if (!lower.infinite && !lower.inclusive)
01323     {
01324         lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
01325         lower.inclusive = true;
01326     }
01327 
01328     if (!upper.infinite && upper.inclusive)
01329     {
01330         upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
01331         upper.inclusive = false;
01332     }
01333 
01334     PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
01335 }
01336 
01337 /*
01338  *----------------------------------------------------------
01339  * SUBTYPE_DIFF FUNCTIONS
01340  *
01341  * Functions for specific built-in range types.
01342  *
01343  * Note that subtype_diff does return the difference, not the absolute value
01344  * of the difference, and it must take care to avoid overflow.
01345  * (numrange_subdiff is at some risk there ...)
01346  *----------------------------------------------------------
01347  */
01348 
01349 Datum
01350 int4range_subdiff(PG_FUNCTION_ARGS)
01351 {
01352     int32       v1 = PG_GETARG_INT32(0);
01353     int32       v2 = PG_GETARG_INT32(1);
01354 
01355     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
01356 }
01357 
01358 Datum
01359 int8range_subdiff(PG_FUNCTION_ARGS)
01360 {
01361     int64       v1 = PG_GETARG_INT64(0);
01362     int64       v2 = PG_GETARG_INT64(1);
01363 
01364     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
01365 }
01366 
01367 Datum
01368 numrange_subdiff(PG_FUNCTION_ARGS)
01369 {
01370     Datum       v1 = PG_GETARG_DATUM(0);
01371     Datum       v2 = PG_GETARG_DATUM(1);
01372     Datum       numresult;
01373     float8      floatresult;
01374 
01375     numresult = DirectFunctionCall2(numeric_sub, v1, v2);
01376 
01377     floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
01378                                                      numresult));
01379 
01380     PG_RETURN_FLOAT8(floatresult);
01381 }
01382 
01383 Datum
01384 daterange_subdiff(PG_FUNCTION_ARGS)
01385 {
01386     int32       v1 = PG_GETARG_INT32(0);
01387     int32       v2 = PG_GETARG_INT32(1);
01388 
01389     PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
01390 }
01391 
01392 Datum
01393 tsrange_subdiff(PG_FUNCTION_ARGS)
01394 {
01395     Timestamp   v1 = PG_GETARG_TIMESTAMP(0);
01396     Timestamp   v2 = PG_GETARG_TIMESTAMP(1);
01397     float8      result;
01398 
01399 #ifdef HAVE_INT64_TIMESTAMP
01400     result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
01401 #else
01402     result = v1 - v2;
01403 #endif
01404 
01405     PG_RETURN_FLOAT8(result);
01406 }
01407 
01408 Datum
01409 tstzrange_subdiff(PG_FUNCTION_ARGS)
01410 {
01411     Timestamp   v1 = PG_GETARG_TIMESTAMP(0);
01412     Timestamp   v2 = PG_GETARG_TIMESTAMP(1);
01413     float8      result;
01414 
01415 #ifdef HAVE_INT64_TIMESTAMP
01416     result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
01417 #else
01418     result = v1 - v2;
01419 #endif
01420 
01421     PG_RETURN_FLOAT8(result);
01422 }
01423 
01424 /*
01425  *----------------------------------------------------------
01426  * SUPPORT FUNCTIONS
01427  *
01428  *   These functions aren't in pg_proc, but are useful for
01429  *   defining new generic range functions in C.
01430  *----------------------------------------------------------
01431  */
01432 
01433 /*
01434  * range_get_typcache: get cached information about a range type
01435  *
01436  * This is for use by range-related functions that follow the convention
01437  * of using the fn_extra field as a pointer to the type cache entry for
01438  * the range type.  Functions that need to cache more information than
01439  * that must fend for themselves.
01440  */
01441 TypeCacheEntry *
01442 range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
01443 {
01444     TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
01445 
01446     if (typcache == NULL ||
01447         typcache->type_id != rngtypid)
01448     {
01449         typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
01450         if (typcache->rngelemtype == NULL)
01451             elog(ERROR, "type %u is not a range type", rngtypid);
01452         fcinfo->flinfo->fn_extra = (void *) typcache;
01453     }
01454 
01455     return typcache;
01456 }
01457 
01458 /*
01459  * range_serialize: construct a range value from bounds and empty-flag
01460  *
01461  * This does not force canonicalization of the range value.  In most cases,
01462  * external callers should only be canonicalization functions.  Note that
01463  * we perform some datatype-independent canonicalization checks anyway.
01464  */
01465 RangeType *
01466 range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
01467                 bool empty)
01468 {
01469     RangeType  *range;
01470     int         cmp;
01471     Size        msize;
01472     Pointer     ptr;
01473     int16       typlen;
01474     bool        typbyval;
01475     char        typalign;
01476     char        typstorage;
01477     char        flags = 0;
01478 
01479     /*
01480      * Verify range is not invalid on its face, and construct flags value,
01481      * preventing any non-canonical combinations such as infinite+inclusive.
01482      */
01483     Assert(lower->lower);
01484     Assert(!upper->lower);
01485 
01486     if (empty)
01487         flags |= RANGE_EMPTY;
01488     else
01489     {
01490         cmp = range_cmp_bound_values(typcache, lower, upper);
01491 
01492         /* error check: if lower bound value is above upper, it's wrong */
01493         if (cmp > 0)
01494             ereport(ERROR,
01495                     (errcode(ERRCODE_DATA_EXCEPTION),
01496                      errmsg("range lower bound must be less than or equal to range upper bound")));
01497 
01498         /* if bounds are equal, and not both inclusive, range is empty */
01499         if (cmp == 0 && !(lower->inclusive && upper->inclusive))
01500             flags |= RANGE_EMPTY;
01501         else
01502         {
01503             /* infinite boundaries are never inclusive */
01504             if (lower->infinite)
01505                 flags |= RANGE_LB_INF;
01506             else if (lower->inclusive)
01507                 flags |= RANGE_LB_INC;
01508             if (upper->infinite)
01509                 flags |= RANGE_UB_INF;
01510             else if (upper->inclusive)
01511                 flags |= RANGE_UB_INC;
01512         }
01513     }
01514 
01515     /* Fetch information about range's element type */
01516     typlen = typcache->rngelemtype->typlen;
01517     typbyval = typcache->rngelemtype->typbyval;
01518     typalign = typcache->rngelemtype->typalign;
01519     typstorage = typcache->rngelemtype->typstorage;
01520 
01521     /* Count space for varlena header and range type's OID */
01522     msize = sizeof(RangeType);
01523     Assert(msize == MAXALIGN(msize));
01524 
01525     /* Count space for bounds */
01526     if (RANGE_HAS_LBOUND(flags))
01527     {
01528         /*
01529          * Make sure item to be inserted is not toasted.  It is essential that
01530          * we not insert an out-of-line toast value pointer into a range
01531          * object, for the same reasons that arrays and records can't contain
01532          * them.  It would work to store a compressed-in-line value, but we
01533          * prefer to decompress and then let compression be applied to the
01534          * whole range object if necessary.  But, unlike arrays, we do allow
01535          * short-header varlena objects to stay as-is.
01536          */
01537         if (typlen == -1)
01538             lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
01539 
01540         msize = datum_compute_size(msize, lower->val, typbyval, typalign,
01541                                    typlen, typstorage);
01542     }
01543 
01544     if (RANGE_HAS_UBOUND(flags))
01545     {
01546         /* Make sure item to be inserted is not toasted */
01547         if (typlen == -1)
01548             upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
01549 
01550         msize = datum_compute_size(msize, upper->val, typbyval, typalign,
01551                                    typlen, typstorage);
01552     }
01553 
01554     /* Add space for flag byte */
01555     msize += sizeof(char);
01556 
01557     /* Note: zero-fill is required here, just as in heap tuples */
01558     range = (RangeType *) palloc0(msize);
01559     SET_VARSIZE(range, msize);
01560 
01561     /* Now fill in the datum */
01562     range->rangetypid = typcache->type_id;
01563 
01564     ptr = (char *) (range + 1);
01565 
01566     if (RANGE_HAS_LBOUND(flags))
01567     {
01568         Assert(lower->lower);
01569         ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
01570                           typstorage);
01571     }
01572 
01573     if (RANGE_HAS_UBOUND(flags))
01574     {
01575         Assert(!upper->lower);
01576         ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
01577                           typstorage);
01578     }
01579 
01580     *((char *) ptr) = flags;
01581 
01582     return range;
01583 }
01584 
01585 /*
01586  * range_deserialize: deconstruct a range value
01587  *
01588  * NB: the given range object must be fully detoasted; it cannot have a
01589  * short varlena header.
01590  *
01591  * Note that if the element type is pass-by-reference, the datums in the
01592  * RangeBound structs will be pointers into the given range object.
01593  */
01594 void
01595 range_deserialize(TypeCacheEntry *typcache, RangeType *range,
01596                   RangeBound *lower, RangeBound *upper, bool *empty)
01597 {
01598     char        flags;
01599     int16       typlen;
01600     bool        typbyval;
01601     char        typalign;
01602     Pointer     ptr;
01603     Datum       lbound;
01604     Datum       ubound;
01605 
01606     /* assert caller passed the right typcache entry */
01607     Assert(RangeTypeGetOid(range) == typcache->type_id);
01608 
01609     /* fetch the flag byte from datum's last byte */
01610     flags = *((char *) range + VARSIZE(range) - 1);
01611 
01612     /* fetch information about range's element type */
01613     typlen = typcache->rngelemtype->typlen;
01614     typbyval = typcache->rngelemtype->typbyval;
01615     typalign = typcache->rngelemtype->typalign;
01616 
01617     /* initialize data pointer just after the range OID */
01618     ptr = (Pointer) (range + 1);
01619 
01620     /* fetch lower bound, if any */
01621     if (RANGE_HAS_LBOUND(flags))
01622     {
01623         /* att_align_pointer cannot be necessary here */
01624         lbound = fetch_att(ptr, typbyval, typlen);
01625         ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
01626     }
01627     else
01628         lbound = (Datum) 0;
01629 
01630     /* fetch upper bound, if any */
01631     if (RANGE_HAS_UBOUND(flags))
01632     {
01633         ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
01634         ubound = fetch_att(ptr, typbyval, typlen);
01635         /* no need for att_addlength_pointer */
01636     }
01637     else
01638         ubound = (Datum) 0;
01639 
01640     /* emit results */
01641 
01642     *empty = (flags & RANGE_EMPTY) != 0;
01643 
01644     lower->val = lbound;
01645     lower->infinite = (flags & RANGE_LB_INF) != 0;
01646     lower->inclusive = (flags & RANGE_LB_INC) != 0;
01647     lower->lower = true;
01648 
01649     upper->val = ubound;
01650     upper->infinite = (flags & RANGE_UB_INF) != 0;
01651     upper->inclusive = (flags & RANGE_UB_INC) != 0;
01652     upper->lower = false;
01653 }
01654 
01655 /*
01656  * range_get_flags: just get the flags from a RangeType value.
01657  *
01658  * This is frequently useful in places that only need the flags and not
01659  * the full results of range_deserialize.
01660  */
01661 char
01662 range_get_flags(RangeType *range)
01663 {
01664     /* fetch the flag byte from datum's last byte */
01665     return *((char *) range + VARSIZE(range) - 1);
01666 }
01667 
01668 /*
01669  * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
01670  *
01671  * This is only needed in GiST operations, so we don't include a provision
01672  * for setting it in range_serialize; rather, this function must be applied
01673  * afterwards.
01674  */
01675 void
01676 range_set_contain_empty(RangeType *range)
01677 {
01678     char       *flagsp;
01679 
01680     /* flag byte is datum's last byte */
01681     flagsp = (char *) range + VARSIZE(range) - 1;
01682 
01683     *flagsp |= RANGE_CONTAIN_EMPTY;
01684 }
01685 
01686 /*
01687  * This both serializes and canonicalizes (if applicable) the range.
01688  * This should be used by most callers.
01689  */
01690 RangeType *
01691 make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
01692            bool empty)
01693 {
01694     RangeType  *range;
01695 
01696     range = range_serialize(typcache, lower, upper, empty);
01697 
01698     /* no need to call canonical on empty ranges ... */
01699     if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
01700         !RangeIsEmpty(range))
01701         range = DatumGetRangeType(FunctionCall1(&typcache->rng_canonical_finfo,
01702                                                 RangeTypeGetDatum(range)));
01703 
01704     return range;
01705 }
01706 
01707 /*
01708  * Compare two range boundary points, returning <0, 0, or >0 according to
01709  * whether b1 is less than, equal to, or greater than b2.
01710  *
01711  * The boundaries can be any combination of upper and lower; so it's useful
01712  * for a variety of operators.
01713  *
01714  * The simple case is when b1 and b2 are both finite and inclusive, in which
01715  * case the result is just a comparison of the values held in b1 and b2.
01716  *
01717  * If a bound is exclusive, then we need to know whether it's a lower bound,
01718  * in which case we treat the boundary point as "just greater than" the held
01719  * value; or an upper bound, in which case we treat the boundary point as
01720  * "just less than" the held value.
01721  *
01722  * If a bound is infinite, it represents minus infinity (less than every other
01723  * point) if it's a lower bound; or plus infinity (greater than every other
01724  * point) if it's an upper bound.
01725  *
01726  * There is only one case where two boundaries compare equal but are not
01727  * identical: when both bounds are inclusive and hold the same finite value,
01728  * but one is an upper bound and the other a lower bound.
01729  */
01730 int
01731 range_cmp_bounds(TypeCacheEntry *typcache, RangeBound *b1, RangeBound *b2)
01732 {
01733     int32       result;
01734 
01735     /*
01736      * First, handle cases involving infinity, which don't require invoking
01737      * the comparison proc.
01738      */
01739     if (b1->infinite && b2->infinite)
01740     {
01741         /*
01742          * Both are infinity, so they are equal unless one is lower and the
01743          * other not.
01744          */
01745         if (b1->lower == b2->lower)
01746             return 0;
01747         else
01748             return b1->lower ? -1 : 1;
01749     }
01750     else if (b1->infinite)
01751         return b1->lower ? -1 : 1;
01752     else if (b2->infinite)
01753         return b2->lower ? 1 : -1;
01754 
01755     /*
01756      * Both boundaries are finite, so compare the held values.
01757      */
01758     result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
01759                                              typcache->rng_collation,
01760                                              b1->val, b2->val));
01761 
01762     /*
01763      * If the comparison is anything other than equal, we're done. If they
01764      * compare equal though, we still have to consider whether the boundaries
01765      * are inclusive or exclusive.
01766      */
01767     if (result == 0)
01768     {
01769         if (!b1->inclusive && !b2->inclusive)
01770         {
01771             /* both are exclusive */
01772             if (b1->lower == b2->lower)
01773                 return 0;
01774             else
01775                 return b1->lower ? 1 : -1;
01776         }
01777         else if (!b1->inclusive)
01778             return b1->lower ? 1 : -1;
01779         else if (!b2->inclusive)
01780             return b2->lower ? -1 : 1;
01781         else
01782         {
01783             /*
01784              * Both are inclusive and the values held are equal, so they are
01785              * equal regardless of whether they are upper or lower boundaries,
01786              * or a mix.
01787              */
01788             return 0;
01789         }
01790     }
01791 
01792     return result;
01793 }
01794 
01795 /*
01796  * Compare two range boundary point values, returning <0, 0, or >0 according
01797  * to whether b1 is less than, equal to, or greater than b2.
01798  *
01799  * This is similar to but simpler than range_cmp_bounds().  We just compare
01800  * the values held in b1 and b2, ignoring inclusive/exclusive flags.  The
01801  * lower/upper flags only matter for infinities, where they tell us if the
01802  * infinity is plus or minus.
01803  */
01804 int
01805 range_cmp_bound_values(TypeCacheEntry *typcache, RangeBound *b1,
01806                        RangeBound *b2)
01807 {
01808     /*
01809      * First, handle cases involving infinity, which don't require invoking
01810      * the comparison proc.
01811      */
01812     if (b1->infinite && b2->infinite)
01813     {
01814         /*
01815          * Both are infinity, so they are equal unless one is lower and the
01816          * other not.
01817          */
01818         if (b1->lower == b2->lower)
01819             return 0;
01820         else
01821             return b1->lower ? -1 : 1;
01822     }
01823     else if (b1->infinite)
01824         return b1->lower ? -1 : 1;
01825     else if (b2->infinite)
01826         return b2->lower ? 1 : -1;
01827 
01828     /*
01829      * Both boundaries are finite, so compare the held values.
01830      */
01831     return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
01832                                            typcache->rng_collation,
01833                                            b1->val, b2->val));
01834 }
01835 
01836 /*
01837  * Build an empty range value of the type indicated by the typcache entry.
01838  */
01839 RangeType *
01840 make_empty_range(TypeCacheEntry *typcache)
01841 {
01842     RangeBound  lower;
01843     RangeBound  upper;
01844 
01845     lower.val = (Datum) 0;
01846     lower.infinite = false;
01847     lower.inclusive = false;
01848     lower.lower = true;
01849 
01850     upper.val = (Datum) 0;
01851     upper.infinite = false;
01852     upper.inclusive = false;
01853     upper.lower = false;
01854 
01855     return make_range(typcache, &lower, &upper, true);
01856 }
01857 
01858 
01859 /*
01860  *----------------------------------------------------------
01861  * STATIC FUNCTIONS
01862  *----------------------------------------------------------
01863  */
01864 
01865 /*
01866  * Given a string representing the flags for the range type, return the flags
01867  * represented as a char.
01868  */
01869 static char
01870 range_parse_flags(const char *flags_str)
01871 {
01872     char        flags = 0;
01873 
01874     if (flags_str[0] == '\0' ||
01875         flags_str[1] == '\0' ||
01876         flags_str[2] != '\0')
01877         ereport(ERROR,
01878                 (errcode(ERRCODE_SYNTAX_ERROR),
01879                  errmsg("invalid range bound flags"),
01880                  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
01881 
01882     switch (flags_str[0])
01883     {
01884         case '[':
01885             flags |= RANGE_LB_INC;
01886             break;
01887         case '(':
01888             break;
01889         default:
01890             ereport(ERROR,
01891                     (errcode(ERRCODE_SYNTAX_ERROR),
01892                      errmsg("invalid range bound flags"),
01893                  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
01894     }
01895 
01896     switch (flags_str[1])
01897     {
01898         case ']':
01899             flags |= RANGE_UB_INC;
01900             break;
01901         case ')':
01902             break;
01903         default:
01904             ereport(ERROR,
01905                     (errcode(ERRCODE_SYNTAX_ERROR),
01906                      errmsg("invalid range bound flags"),
01907                  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
01908     }
01909 
01910     return flags;
01911 }
01912 
01913 /*
01914  * Parse range input.
01915  *
01916  * Input parameters:
01917  *  string: input string to be parsed
01918  * Output parameters:
01919  *  *flags: receives flags bitmask
01920  *  *lbound_str: receives palloc'd lower bound string, or NULL if none
01921  *  *ubound_str: receives palloc'd upper bound string, or NULL if none
01922  *
01923  * This is modeled somewhat after record_in in rowtypes.c.
01924  * The input syntax is:
01925  *  <range>   := EMPTY
01926  *             | <lb-inc> <string>, <string> <ub-inc>
01927  *  <lb-inc>  := '[' | '('
01928  *  <ub-inc>  := ']' | ')'
01929  *
01930  * Whitespace before or after <range> is ignored.  Whitespace within a <string>
01931  * is taken literally and becomes part of the input string for that bound.
01932  *
01933  * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
01934  * is surrounded by double-quotes, in which case it is the literal empty
01935  * string.
01936  *
01937  * Within a <string>, special characters (such as comma, parenthesis, or
01938  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
01939  * double-quotes, a double-quote can be escaped with double-quote or backslash.
01940  */
01941 static void
01942 range_parse(const char *string, char *flags, char **lbound_str,
01943             char **ubound_str)
01944 {
01945     const char *ptr = string;
01946     bool        infinite;
01947 
01948     *flags = 0;
01949 
01950     /* consume whitespace */
01951     while (*ptr != '\0' && isspace((unsigned char) *ptr))
01952         ptr++;
01953 
01954     /* check for empty range */
01955     if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
01956                        strlen(RANGE_EMPTY_LITERAL)) == 0)
01957     {
01958         *flags = RANGE_EMPTY;
01959         *lbound_str = NULL;
01960         *ubound_str = NULL;
01961 
01962         ptr += strlen(RANGE_EMPTY_LITERAL);
01963 
01964         /* the rest should be whitespace */
01965         while (*ptr != '\0' && isspace((unsigned char) *ptr))
01966             ptr++;
01967 
01968         /* should have consumed everything */
01969         if (*ptr != '\0')
01970             ereport(ERROR,
01971                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
01972                      errmsg("malformed range literal: \"%s\"",
01973                             string),
01974                      errdetail("Junk after \"empty\" key word.")));
01975 
01976         return;
01977     }
01978 
01979     if (*ptr == '[')
01980     {
01981         *flags |= RANGE_LB_INC;
01982         ptr++;
01983     }
01984     else if (*ptr == '(')
01985         ptr++;
01986     else
01987         ereport(ERROR,
01988                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
01989                  errmsg("malformed range literal: \"%s\"",
01990                         string),
01991                  errdetail("Missing left parenthesis or bracket.")));
01992 
01993     ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
01994     if (infinite)
01995         *flags |= RANGE_LB_INF;
01996 
01997     if (*ptr == ',')
01998         ptr++;
01999     else
02000         ereport(ERROR,
02001                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
02002                  errmsg("malformed range literal: \"%s\"",
02003                         string),
02004                  errdetail("Missing comma after lower bound.")));
02005 
02006     ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
02007     if (infinite)
02008         *flags |= RANGE_UB_INF;
02009 
02010     if (*ptr == ']')
02011     {
02012         *flags |= RANGE_UB_INC;
02013         ptr++;
02014     }
02015     else if (*ptr == ')')
02016         ptr++;
02017     else    /* must be a comma */
02018         ereport(ERROR,
02019                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
02020                  errmsg("malformed range literal: \"%s\"",
02021                         string),
02022                  errdetail("Too many commas.")));
02023 
02024     /* consume whitespace */
02025     while (*ptr != '\0' && isspace((unsigned char) *ptr))
02026         ptr++;
02027 
02028     if (*ptr != '\0')
02029         ereport(ERROR,
02030                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
02031                  errmsg("malformed range literal: \"%s\"",
02032                         string),
02033                  errdetail("Junk after right parenthesis or bracket.")));
02034 }
02035 
02036 /*
02037  * Helper for range_parse: parse and de-quote one bound string.
02038  *
02039  * We scan until finding comma, right parenthesis, or right bracket.
02040  *
02041  * Input parameters:
02042  *  string: entire input string (used only for error reports)
02043  *  ptr: where to start parsing bound
02044  * Output parameters:
02045  *  *bound_str: receives palloc'd bound string, or NULL if none
02046  *  *infinite: set true if no bound, else false
02047  *
02048  * The return value is the scan ptr, advanced past the bound string.
02049  */
02050 static const char *
02051 range_parse_bound(const char *string, const char *ptr,
02052                   char **bound_str, bool *infinite)
02053 {
02054     StringInfoData buf;
02055 
02056     /* Check for null: completely empty input means null */
02057     if (*ptr == ',' || *ptr == ')' || *ptr == ']')
02058     {
02059         *bound_str = NULL;
02060         *infinite = true;
02061     }
02062     else
02063     {
02064         /* Extract string for this bound */
02065         bool        inquote = false;
02066 
02067         initStringInfo(&buf);
02068         while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
02069         {
02070             char        ch = *ptr++;
02071 
02072             if (ch == '\0')
02073                 ereport(ERROR,
02074                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
02075                          errmsg("malformed range literal: \"%s\"",
02076                                 string),
02077                          errdetail("Unexpected end of input.")));
02078             if (ch == '\\')
02079             {
02080                 if (*ptr == '\0')
02081                     ereport(ERROR,
02082                             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
02083                              errmsg("malformed range literal: \"%s\"",
02084                                     string),
02085                              errdetail("Unexpected end of input.")));
02086                 appendStringInfoChar(&buf, *ptr++);
02087             }
02088             else if (ch == '\"')
02089             {
02090                 if (!inquote)
02091                     inquote = true;
02092                 else if (*ptr == '\"')
02093                 {
02094                     /* doubled quote within quote sequence */
02095                     appendStringInfoChar(&buf, *ptr++);
02096                 }
02097                 else
02098                     inquote = false;
02099             }
02100             else
02101                 appendStringInfoChar(&buf, ch);
02102         }
02103 
02104         *bound_str = buf.data;
02105         *infinite = false;
02106     }
02107 
02108     return ptr;
02109 }
02110 
02111 /*
02112  * Convert a deserialized range value to text form
02113  *
02114  * Inputs are the flags byte, and the two bound values already converted to
02115  * text (but not yet quoted).  If no bound value, pass NULL.
02116  *
02117  * Result is a palloc'd string
02118  */
02119 static char *
02120 range_deparse(char flags, const char *lbound_str, const char *ubound_str)
02121 {
02122     StringInfoData buf;
02123 
02124     if (flags & RANGE_EMPTY)
02125         return pstrdup(RANGE_EMPTY_LITERAL);
02126 
02127     initStringInfo(&buf);
02128 
02129     appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
02130 
02131     if (RANGE_HAS_LBOUND(flags))
02132         appendStringInfoString(&buf, range_bound_escape(lbound_str));
02133 
02134     appendStringInfoChar(&buf, ',');
02135 
02136     if (RANGE_HAS_UBOUND(flags))
02137         appendStringInfoString(&buf, range_bound_escape(ubound_str));
02138 
02139     appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
02140 
02141     return buf.data;
02142 }
02143 
02144 /*
02145  * Helper for range_deparse: quote a bound value as needed
02146  *
02147  * Result is a palloc'd string
02148  */
02149 static char *
02150 range_bound_escape(const char *value)
02151 {
02152     bool        nq;
02153     const char *ptr;
02154     StringInfoData buf;
02155 
02156     initStringInfo(&buf);
02157 
02158     /* Detect whether we need double quotes for this value */
02159     nq = (value[0] == '\0');    /* force quotes for empty string */
02160     for (ptr = value; *ptr; ptr++)
02161     {
02162         char        ch = *ptr;
02163 
02164         if (ch == '"' || ch == '\\' ||
02165             ch == '(' || ch == ')' ||
02166             ch == '[' || ch == ']' ||
02167             ch == ',' ||
02168             isspace((unsigned char) ch))
02169         {
02170             nq = true;
02171             break;
02172         }
02173     }
02174 
02175     /* And emit the string */
02176     if (nq)
02177         appendStringInfoChar(&buf, '"');
02178     for (ptr = value; *ptr; ptr++)
02179     {
02180         char        ch = *ptr;
02181 
02182         if (ch == '"' || ch == '\\')
02183             appendStringInfoChar(&buf, ch);
02184         appendStringInfoChar(&buf, ch);
02185     }
02186     if (nq)
02187         appendStringInfoChar(&buf, '"');
02188 
02189     return buf.data;
02190 }
02191 
02192 /*
02193  * Test whether range r1 contains range r2.
02194  *
02195  * Caller has already checked that they are the same range type, and looked up
02196  * the necessary typcache entry.
02197  */
02198 bool
02199 range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
02200 {
02201     RangeBound  lower1;
02202     RangeBound  upper1;
02203     bool        empty1;
02204     RangeBound  lower2;
02205     RangeBound  upper2;
02206     bool        empty2;
02207 
02208     /* Different types should be prevented by ANYRANGE matching rules */
02209     if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
02210         elog(ERROR, "range types do not match");
02211 
02212     range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
02213     range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
02214 
02215     /* If either range is empty, the answer is easy */
02216     if (empty2)
02217         return true;
02218     else if (empty1)
02219         return false;
02220 
02221     /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
02222     if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
02223         return false;
02224     if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
02225         return false;
02226 
02227     return true;
02228 }
02229 
02230 bool
02231 range_contained_by_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
02232 {
02233     return range_contains_internal(typcache, r2, r1);
02234 }
02235 
02236 /*
02237  * Test whether range r contains a specific element value.
02238  */
02239 bool
02240 range_contains_elem_internal(TypeCacheEntry *typcache, RangeType *r, Datum val)
02241 {
02242     RangeBound  lower;
02243     RangeBound  upper;
02244     bool        empty;
02245     int32       cmp;
02246 
02247     range_deserialize(typcache, r, &lower, &upper, &empty);
02248 
02249     if (empty)
02250         return false;
02251 
02252     if (!lower.infinite)
02253     {
02254         cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
02255                                               typcache->rng_collation,
02256                                               lower.val, val));
02257         if (cmp > 0)
02258             return false;
02259         if (cmp == 0 && !lower.inclusive)
02260             return false;
02261     }
02262 
02263     if (!upper.infinite)
02264     {
02265         cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
02266                                               typcache->rng_collation,
02267                                               upper.val, val));
02268         if (cmp < 0)
02269             return false;
02270         if (cmp == 0 && !upper.inclusive)
02271             return false;
02272     }
02273 
02274     return true;
02275 }
02276 
02277 
02278 /*
02279  * datum_compute_size() and datum_write() are used to insert the bound
02280  * values into a range object.  They are modeled after heaptuple.c's
02281  * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
02282  * null values here.  TYPE_IS_PACKABLE must test the same conditions as
02283  * heaptuple.c's ATT_IS_PACKABLE macro.
02284  */
02285 
02286 /* Does datatype allow packing into the 1-byte-header varlena format? */
02287 #define TYPE_IS_PACKABLE(typlen, typstorage) \
02288     ((typlen) == -1 && (typstorage) != 'p')
02289 
02290 /*
02291  * Increment data_length by the space needed by the datum, including any
02292  * preceding alignment padding.
02293  */
02294 static Size
02295 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
02296                    int16 typlen, char typstorage)
02297 {
02298     if (TYPE_IS_PACKABLE(typlen, typstorage) &&
02299         VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
02300     {
02301         /*
02302          * we're anticipating converting to a short varlena header, so adjust
02303          * length and don't count any alignment
02304          */
02305         data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
02306     }
02307     else
02308     {
02309         data_length = att_align_datum(data_length, typalign, typlen, val);
02310         data_length = att_addlength_datum(data_length, typlen, val);
02311     }
02312 
02313     return data_length;
02314 }
02315 
02316 /*
02317  * Write the given datum beginning at ptr (after advancing to correct
02318  * alignment, if needed).  Return the pointer incremented by space used.
02319  */
02320 static Pointer
02321 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
02322             int16 typlen, char typstorage)
02323 {
02324     Size        data_length;
02325 
02326     if (typbyval)
02327     {
02328         /* pass-by-value */
02329         ptr = (char *) att_align_nominal(ptr, typalign);
02330         store_att_byval(ptr, datum, typlen);
02331         data_length = typlen;
02332     }
02333     else if (typlen == -1)
02334     {
02335         /* varlena */
02336         Pointer     val = DatumGetPointer(datum);
02337 
02338         if (VARATT_IS_EXTERNAL(val))
02339         {
02340             /*
02341              * Throw error, because we must never put a toast pointer inside a
02342              * range object.  Caller should have detoasted it.
02343              */
02344             elog(ERROR, "cannot store a toast pointer inside a range");
02345             data_length = 0;    /* keep compiler quiet */
02346         }
02347         else if (VARATT_IS_SHORT(val))
02348         {
02349             /* no alignment for short varlenas */
02350             data_length = VARSIZE_SHORT(val);
02351             memcpy(ptr, val, data_length);
02352         }
02353         else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
02354                  VARATT_CAN_MAKE_SHORT(val))
02355         {
02356             /* convert to short varlena -- no alignment */
02357             data_length = VARATT_CONVERTED_SHORT_SIZE(val);
02358             SET_VARSIZE_SHORT(ptr, data_length);
02359             memcpy(ptr + 1, VARDATA(val), data_length - 1);
02360         }
02361         else
02362         {
02363             /* full 4-byte header varlena */
02364             ptr = (char *) att_align_nominal(ptr, typalign);
02365             data_length = VARSIZE(val);
02366             memcpy(ptr, val, data_length);
02367         }
02368     }
02369     else if (typlen == -2)
02370     {
02371         /* cstring ... never needs alignment */
02372         Assert(typalign == 'c');
02373         data_length = strlen(DatumGetCString(datum)) + 1;
02374         memcpy(ptr, DatumGetPointer(datum), data_length);
02375     }
02376     else
02377     {
02378         /* fixed-length pass-by-reference */
02379         ptr = (char *) att_align_nominal(ptr, typalign);
02380         Assert(typlen > 0);
02381         data_length = typlen;
02382         memcpy(ptr, DatumGetPointer(datum), data_length);
02383     }
02384 
02385     ptr += data_length;
02386 
02387     return ptr;
02388 }