summaryrefslogtreecommitdiffstats
path: root/src/include/utils/rangetypes.h
blob: b77c41cf1b85897d61d0cfd9a0cbda408be4d32f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*-------------------------------------------------------------------------
 *
 * rangetypes.h
 *	  Declarations for Postgres range types.
 *
 *
 * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/utils/rangetypes.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef RANGETYPES_H
#define RANGETYPES_H

#include "utils/typcache.h"


/*
 * Ranges are varlena objects, so must meet the varlena convention that
 * the first int32 of the object contains the total object size in bytes.
 * Be sure to use VARSIZE() and SET_VARSIZE() to access it, though!
 */
typedef struct
{
	int32		vl_len_;		/* varlena header (do not touch directly!) */
	Oid			rangetypid;		/* range type's own OID */
	/* Following the OID are zero to two bound values, then a flags byte */
} RangeType;

/* Use this macro in preference to fetching rangetypid field directly */
#define RangeTypeGetOid(r)	((r)->rangetypid)

/* A range's flags byte contains these bits: */
#define RANGE_EMPTY			0x01	/* range is empty */
#define RANGE_LB_INC		0x02	/* lower bound is inclusive */
#define RANGE_UB_INC		0x04	/* upper bound is inclusive */
#define RANGE_LB_INF		0x08	/* lower bound is -infinity */
#define RANGE_UB_INF		0x10	/* upper bound is +infinity */
#define RANGE_LB_NULL		0x20	/* lower bound is null (NOT USED) */
#define RANGE_UB_NULL		0x40	/* upper bound is null (NOT USED) */
#define RANGE_CONTAIN_EMPTY 0x80	/* marks a GiST internal-page entry whose
									 * subtree contains some empty ranges */

#define RANGE_HAS_LBOUND(flags) (!((flags) & (RANGE_EMPTY | \
											  RANGE_LB_NULL | \
											  RANGE_LB_INF)))

#define RANGE_HAS_UBOUND(flags) (!((flags) & (RANGE_EMPTY | \
											  RANGE_UB_NULL | \
											  RANGE_UB_INF)))

#define RangeIsEmpty(r)  ((range_get_flags(r) & RANGE_EMPTY) != 0)
#define RangeIsOrContainsEmpty(r)  \
	((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)


/* Internal representation of either bound of a range (not what's on disk) */
typedef struct
{
	Datum		val;			/* the bound value, if any */
	bool		infinite;		/* bound is +/- infinity */
	bool		inclusive;		/* bound is inclusive (vs exclusive) */
	bool		lower;			/* this is the lower (vs upper) bound */
} RangeBound;

/*
 * fmgr macros for range type objects
 */
#define DatumGetRangeTypeP(X)		((RangeType *) PG_DETOAST_DATUM(X))
#define DatumGetRangeTypePCopy(X)	((RangeType *) PG_DETOAST_DATUM_COPY(X))
#define RangeTypePGetDatum(X)		PointerGetDatum(X)
#define PG_GETARG_RANGE_P(n)		DatumGetRangeTypeP(PG_GETARG_DATUM(n))
#define PG_GETARG_RANGE_P_COPY(n)	DatumGetRangeTypePCopy(PG_GETARG_DATUM(n))
#define PG_RETURN_RANGE_P(x)		return RangeTypePGetDatum(x)

/* Operator strategy numbers used in the GiST and SP-GiST range opclasses */
/* Numbers are chosen to match up operator names with existing usages */
#define RANGESTRAT_BEFORE				RTLeftStrategyNumber
#define RANGESTRAT_OVERLEFT				RTOverLeftStrategyNumber
#define RANGESTRAT_OVERLAPS				RTOverlapStrategyNumber
#define RANGESTRAT_OVERRIGHT			RTOverRightStrategyNumber
#define RANGESTRAT_AFTER				RTRightStrategyNumber
#define RANGESTRAT_ADJACENT				RTSameStrategyNumber
#define RANGESTRAT_CONTAINS				RTContainsStrategyNumber
#define RANGESTRAT_CONTAINED_BY			RTContainedByStrategyNumber
#define RANGESTRAT_CONTAINS_ELEM		RTContainsElemStrategyNumber
#define RANGESTRAT_EQ					RTEqualStrategyNumber

/*
 * prototypes for functions defined in rangetypes.c
 */

extern bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val);

/* internal versions of the above */
extern bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1,
							  const RangeType *r2);
extern bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1,
							  const RangeType *r2);
extern bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1,
									const RangeType *r2);
extern bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1,
										const RangeType *r2);
extern bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1,
								  const RangeType *r2);
extern bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1,
								 const RangeType *r2);
extern bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1,
									const RangeType *r2);
extern bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1,
									const RangeType *r2);
extern bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1,
									const RangeType *r2);
extern bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1,
									 const RangeType *r2);

/* assorted support functions */
extern TypeCacheEntry *range_get_typcache(FunctionCallInfo fcinfo,
										  Oid rngtypid);
extern RangeType *range_serialize(TypeCacheEntry *typcache, RangeBound *lower,
								  RangeBound *upper, bool empty);
extern void range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
							  RangeBound *lower, RangeBound *upper,
							  bool *empty);
extern char range_get_flags(const RangeType *range);
extern void range_set_contain_empty(RangeType *range);
extern RangeType *make_range(TypeCacheEntry *typcache, RangeBound *lower,
							 RangeBound *upper, bool empty);
extern int	range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1,
							 const RangeBound *b2);
extern int	range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
								   const RangeBound *b2);
extern bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound bound1,
							RangeBound bound2);
extern RangeType *make_empty_range(TypeCacheEntry *typcache);

#endif							/* RANGETYPES_H */