PostgreSQL Source Code  git master
nbtcompare.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * nbtcompare.c
4  * Comparison functions for btree access method.
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/access/nbtree/nbtcompare.c
12  *
13  * NOTES
14  *
15  * These functions are stored in pg_amproc. For each operator class
16  * defined on btrees, they compute
17  *
18  * compare(a, b):
19  * < 0 if a < b,
20  * = 0 if a == b,
21  * > 0 if a > b.
22  *
23  * The result is always an int32 regardless of the input datatype.
24  *
25  * Although any negative int32 (except INT_MIN) is acceptable for reporting
26  * "<", and any positive int32 is acceptable for reporting ">", routines
27  * that work on 32-bit or wider datatypes can't just return "a - b".
28  * That could overflow and give the wrong answer. Also, one must not
29  * return INT_MIN to report "<", since some callers will negate the result.
30  *
31  * NOTE: it is critical that the comparison function impose a total order
32  * on all non-NULL values of the data type, and that the datatype's
33  * boolean comparison operators (= < >= etc) yield results consistent
34  * with the comparison routine. Otherwise bad behavior may ensue.
35  * (For example, the comparison operators must NOT punt when faced with
36  * NAN or other funny values; you must devise some collation sequence for
37  * all such values.) If the datatype is not trivial, this is most
38  * reliably done by having the boolean operators invoke the same
39  * three-way comparison code that the btree function does. Therefore,
40  * this file contains only btree support for "trivial" datatypes ---
41  * all others are in the /utils/adt/ files that implement their datatypes.
42  *
43  * NOTE: these routines must not leak memory, since memory allocated
44  * during an index access won't be recovered till end of query. This
45  * primarily affects comparison routines for toastable datatypes;
46  * they have to be careful to free any detoasted copy of an input datum.
47  *-------------------------------------------------------------------------
48  */
49 #include "postgres.h"
50 
51 #include "utils/builtins.h"
52 #include "utils/sortsupport.h"
53 
54 
55 Datum
57 {
58  bool a = PG_GETARG_BOOL(0);
59  bool b = PG_GETARG_BOOL(1);
60 
61  PG_RETURN_INT32((int32) a - (int32) b);
62 }
63 
64 Datum
66 {
67  int16 a = PG_GETARG_INT16(0);
68  int16 b = PG_GETARG_INT16(1);
69 
70  PG_RETURN_INT32((int32) a - (int32) b);
71 }
72 
73 static int
75 {
76  int16 a = DatumGetInt16(x);
77  int16 b = DatumGetInt16(y);
78 
79  return (int) a - (int) b;
80 }
81 
82 Datum
84 {
86 
87  ssup->comparator = btint2fastcmp;
89 }
90 
91 Datum
93 {
94  int32 a = PG_GETARG_INT32(0);
95  int32 b = PG_GETARG_INT32(1);
96 
97  if (a > b)
98  PG_RETURN_INT32(1);
99  else if (a == b)
100  PG_RETURN_INT32(0);
101  else
102  PG_RETURN_INT32(-1);
103 }
104 
105 static int
107 {
108  int32 a = DatumGetInt32(x);
109  int32 b = DatumGetInt32(y);
110 
111  if (a > b)
112  return 1;
113  else if (a == b)
114  return 0;
115  else
116  return -1;
117 }
118 
119 Datum
121 {
123 
124  ssup->comparator = btint4fastcmp;
125  PG_RETURN_VOID();
126 }
127 
128 Datum
130 {
131  int64 a = PG_GETARG_INT64(0);
132  int64 b = PG_GETARG_INT64(1);
133 
134  if (a > b)
135  PG_RETURN_INT32(1);
136  else if (a == b)
137  PG_RETURN_INT32(0);
138  else
139  PG_RETURN_INT32(-1);
140 }
141 
142 static int
144 {
145  int64 a = DatumGetInt64(x);
146  int64 b = DatumGetInt64(y);
147 
148  if (a > b)
149  return 1;
150  else if (a == b)
151  return 0;
152  else
153  return -1;
154 }
155 
156 Datum
158 {
160 
161  ssup->comparator = btint8fastcmp;
162  PG_RETURN_VOID();
163 }
164 
165 Datum
167 {
168  int32 a = PG_GETARG_INT32(0);
169  int64 b = PG_GETARG_INT64(1);
170 
171  if (a > b)
172  PG_RETURN_INT32(1);
173  else if (a == b)
174  PG_RETURN_INT32(0);
175  else
176  PG_RETURN_INT32(-1);
177 }
178 
179 Datum
181 {
182  int64 a = PG_GETARG_INT64(0);
183  int32 b = PG_GETARG_INT32(1);
184 
185  if (a > b)
186  PG_RETURN_INT32(1);
187  else if (a == b)
188  PG_RETURN_INT32(0);
189  else
190  PG_RETURN_INT32(-1);
191 }
192 
193 Datum
195 {
196  int16 a = PG_GETARG_INT16(0);
197  int32 b = PG_GETARG_INT32(1);
198 
199  if (a > b)
200  PG_RETURN_INT32(1);
201  else if (a == b)
202  PG_RETURN_INT32(0);
203  else
204  PG_RETURN_INT32(-1);
205 }
206 
207 Datum
209 {
210  int32 a = PG_GETARG_INT32(0);
211  int16 b = PG_GETARG_INT16(1);
212 
213  if (a > b)
214  PG_RETURN_INT32(1);
215  else if (a == b)
216  PG_RETURN_INT32(0);
217  else
218  PG_RETURN_INT32(-1);
219 }
220 
221 Datum
223 {
224  int16 a = PG_GETARG_INT16(0);
225  int64 b = PG_GETARG_INT64(1);
226 
227  if (a > b)
228  PG_RETURN_INT32(1);
229  else if (a == b)
230  PG_RETURN_INT32(0);
231  else
232  PG_RETURN_INT32(-1);
233 }
234 
235 Datum
237 {
238  int64 a = PG_GETARG_INT64(0);
239  int16 b = PG_GETARG_INT16(1);
240 
241  if (a > b)
242  PG_RETURN_INT32(1);
243  else if (a == b)
244  PG_RETURN_INT32(0);
245  else
246  PG_RETURN_INT32(-1);
247 }
248 
249 Datum
251 {
252  Oid a = PG_GETARG_OID(0);
253  Oid b = PG_GETARG_OID(1);
254 
255  if (a > b)
256  PG_RETURN_INT32(1);
257  else if (a == b)
258  PG_RETURN_INT32(0);
259  else
260  PG_RETURN_INT32(-1);
261 }
262 
263 static int
265 {
266  Oid a = DatumGetObjectId(x);
267  Oid b = DatumGetObjectId(y);
268 
269  if (a > b)
270  return 1;
271  else if (a == b)
272  return 0;
273  else
274  return -1;
275 }
276 
277 Datum
279 {
281 
282  ssup->comparator = btoidfastcmp;
283  PG_RETURN_VOID();
284 }
285 
286 Datum
288 {
291  int i;
292 
293  /* We arbitrarily choose to sort first by vector length */
294  if (a->dim1 != b->dim1)
295  PG_RETURN_INT32(a->dim1 - b->dim1);
296 
297  for (i = 0; i < a->dim1; i++)
298  {
299  if (a->values[i] != b->values[i])
300  {
301  if (a->values[i] > b->values[i])
302  PG_RETURN_INT32(1);
303  else
304  PG_RETURN_INT32(-1);
305  }
306  }
307  PG_RETURN_INT32(0);
308 }
309 
310 Datum
312 {
313  char a = PG_GETARG_CHAR(0);
314  char b = PG_GETARG_CHAR(1);
315 
316  /* Be careful to compare chars as unsigned */
317  PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
318 }
319 
320 Datum
322 {
323  Name a = PG_GETARG_NAME(0);
324  Name b = PG_GETARG_NAME(1);
325 
326  PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
327 }
328 
329 static int
331 {
332  Name a = DatumGetName(x);
333  Name b = DatumGetName(y);
334 
335  return strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN);
336 }
337 
338 Datum
340 {
342 
343  ssup->comparator = btnamefastcmp;
344  PG_RETURN_VOID();
345 }
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
signed short int16
Definition: c.h:283
Definition: c.h:526
#define PG_GETARG_INT32(n)
Definition: fmgr.h:234
static int btint4fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:106
#define DatumGetInt32(X)
Definition: postgres.h:478
#define DatumGetObjectId(X)
Definition: postgres.h:506
Datum btint84cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:180
Datum btint8sortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:157
Datum btint24cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:194
Datum btint48cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:166
unsigned char uint8
Definition: c.h:294
#define PG_RETURN_INT32(x)
Definition: fmgr.h:314
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:239
unsigned int Oid
Definition: postgres_ext.h:31
static int btnamefastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:330
Datum btboolcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:56
signed int int32
Definition: c.h:284
Datum btoidcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:250
#define NAMEDATALEN
#define DatumGetName(X)
Definition: postgres.h:591
static int btoidfastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:264
Datum btint28cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:222
Datum btcharcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:311
#define DatumGetInt64(X)
Definition: postgres.h:613
Datum btint42cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:208
Definition: c.h:541
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:107
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:534
int dim1
Definition: c.h:532
#define DatumGetInt16(X)
Definition: postgres.h:450
Datum btoidvectorcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:287
Datum btint4cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:92
uintptr_t Datum
Definition: postgres.h:372
#define PG_GETARG_INT16(n)
Definition: fmgr.h:236
#define PG_RETURN_VOID()
Definition: fmgr.h:309
Datum btint82cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:236
Datum btint2sortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:83
Datum btnamesortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:339
Datum btint8cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:129
Datum btint4sortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:120
static int btint8fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:143
Datum btoidsortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:278
int i
#define NameStr(name)
Definition: c.h:547
Datum btint2cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:65
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
#define PG_GETARG_INT64(n)
Definition: fmgr.h:247
#define PG_GETARG_CHAR(n)
Definition: fmgr.h:238
#define PG_GETARG_NAME(n)
Definition: fmgr.h:243
Datum btnamecmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:321
static int btint2fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:74