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-2024, 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 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.
29  *
30  * NOTE: it is critical that the comparison function impose a total order
31  * on all non-NULL values of the data type, and that the datatype's
32  * boolean comparison operators (= < >= etc) yield results consistent
33  * with the comparison routine. Otherwise bad behavior may ensue.
34  * (For example, the comparison operators must NOT punt when faced with
35  * NAN or other funny values; you must devise some collation sequence for
36  * all such values.) If the datatype is not trivial, this is most
37  * reliably done by having the boolean operators invoke the same
38  * three-way comparison code that the btree function does. Therefore,
39  * this file contains only btree support for "trivial" datatypes ---
40  * all others are in the /utils/adt/ files that implement their datatypes.
41  *
42  * NOTE: these routines must not leak memory, since memory allocated
43  * during an index access won't be recovered till end of query. This
44  * primarily affects comparison routines for toastable datatypes;
45  * they have to be careful to free any detoasted copy of an input datum.
46  *
47  * NOTE: we used to forbid comparison functions from returning INT_MIN,
48  * but that proves to be too error-prone because some platforms' versions
49  * of memcmp() etc can return INT_MIN. As a means of stress-testing
50  * callers, this file can be compiled with STRESS_SORT_INT_MIN defined
51  * to cause many of these functions to return INT_MIN or INT_MAX instead of
52  * their customary -1/+1. For production, though, that's not a good idea
53  * since users or third-party code might expect the traditional results.
54  *-------------------------------------------------------------------------
55  */
56 #include "postgres.h"
57 
58 #include <limits.h>
59 
60 #include "utils/fmgrprotos.h"
61 #include "utils/sortsupport.h"
62 
63 #ifdef STRESS_SORT_INT_MIN
64 #define A_LESS_THAN_B INT_MIN
65 #define A_GREATER_THAN_B INT_MAX
66 #else
67 #define A_LESS_THAN_B (-1)
68 #define A_GREATER_THAN_B 1
69 #endif
70 
71 
72 Datum
74 {
75  bool a = PG_GETARG_BOOL(0);
76  bool b = PG_GETARG_BOOL(1);
77 
78  PG_RETURN_INT32((int32) a - (int32) b);
79 }
80 
81 Datum
83 {
84  int16 a = PG_GETARG_INT16(0);
85  int16 b = PG_GETARG_INT16(1);
86 
87  PG_RETURN_INT32((int32) a - (int32) b);
88 }
89 
90 static int
92 {
95 
96  return (int) a - (int) b;
97 }
98 
99 Datum
101 {
103 
104  ssup->comparator = btint2fastcmp;
105  PG_RETURN_VOID();
106 }
107 
108 Datum
110 {
111  int32 a = PG_GETARG_INT32(0);
112  int32 b = PG_GETARG_INT32(1);
113 
114  if (a > b)
116  else if (a == b)
117  PG_RETURN_INT32(0);
118  else
120 }
121 
122 Datum
124 {
126 
128  PG_RETURN_VOID();
129 }
130 
131 Datum
133 {
134  int64 a = PG_GETARG_INT64(0);
135  int64 b = PG_GETARG_INT64(1);
136 
137  if (a > b)
139  else if (a == b)
140  PG_RETURN_INT32(0);
141  else
143 }
144 
145 #if SIZEOF_DATUM < 8
146 static int
148 {
149  int64 a = DatumGetInt64(x);
150  int64 b = DatumGetInt64(y);
151 
152  if (a > b)
153  return A_GREATER_THAN_B;
154  else if (a == b)
155  return 0;
156  else
157  return A_LESS_THAN_B;
158 }
159 #endif
160 
161 Datum
163 {
165 
166 #if SIZEOF_DATUM >= 8
167  ssup->comparator = ssup_datum_signed_cmp;
168 #else
169  ssup->comparator = btint8fastcmp;
170 #endif
171  PG_RETURN_VOID();
172 }
173 
174 Datum
176 {
177  int32 a = PG_GETARG_INT32(0);
178  int64 b = PG_GETARG_INT64(1);
179 
180  if (a > b)
182  else if (a == b)
183  PG_RETURN_INT32(0);
184  else
186 }
187 
188 Datum
190 {
191  int64 a = PG_GETARG_INT64(0);
192  int32 b = PG_GETARG_INT32(1);
193 
194  if (a > b)
196  else if (a == b)
197  PG_RETURN_INT32(0);
198  else
200 }
201 
202 Datum
204 {
205  int16 a = PG_GETARG_INT16(0);
206  int32 b = PG_GETARG_INT32(1);
207 
208  if (a > b)
210  else if (a == b)
211  PG_RETURN_INT32(0);
212  else
214 }
215 
216 Datum
218 {
219  int32 a = PG_GETARG_INT32(0);
220  int16 b = PG_GETARG_INT16(1);
221 
222  if (a > b)
224  else if (a == b)
225  PG_RETURN_INT32(0);
226  else
228 }
229 
230 Datum
232 {
233  int16 a = PG_GETARG_INT16(0);
234  int64 b = PG_GETARG_INT64(1);
235 
236  if (a > b)
238  else if (a == b)
239  PG_RETURN_INT32(0);
240  else
242 }
243 
244 Datum
246 {
247  int64 a = PG_GETARG_INT64(0);
248  int16 b = PG_GETARG_INT16(1);
249 
250  if (a > b)
252  else if (a == b)
253  PG_RETURN_INT32(0);
254  else
256 }
257 
258 Datum
260 {
261  Oid a = PG_GETARG_OID(0);
262  Oid b = PG_GETARG_OID(1);
263 
264  if (a > b)
266  else if (a == b)
267  PG_RETURN_INT32(0);
268  else
270 }
271 
272 static int
274 {
275  Oid a = DatumGetObjectId(x);
276  Oid b = DatumGetObjectId(y);
277 
278  if (a > b)
279  return A_GREATER_THAN_B;
280  else if (a == b)
281  return 0;
282  else
283  return A_LESS_THAN_B;
284 }
285 
286 Datum
288 {
290 
291  ssup->comparator = btoidfastcmp;
292  PG_RETURN_VOID();
293 }
294 
295 Datum
297 {
300  int i;
301 
302  /* We arbitrarily choose to sort first by vector length */
303  if (a->dim1 != b->dim1)
304  PG_RETURN_INT32(a->dim1 - b->dim1);
305 
306  for (i = 0; i < a->dim1; i++)
307  {
308  if (a->values[i] != b->values[i])
309  {
310  if (a->values[i] > b->values[i])
312  else
314  }
315  }
316  PG_RETURN_INT32(0);
317 }
318 
319 Datum
321 {
322  char a = PG_GETARG_CHAR(0);
323  char b = PG_GETARG_CHAR(1);
324 
325  /* Be careful to compare chars as unsigned */
326  PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
327 }
signed short int16
Definition: c.h:480
signed int int32
Definition: c.h:481
unsigned char uint8
Definition: c.h:491
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_CHAR(n)
Definition: fmgr.h:273
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_GETARG_INT16(n)
Definition: fmgr.h:271
int y
Definition: isn.c:72
int b
Definition: isn.c:70
int x
Definition: isn.c:71
int a
Definition: isn.c:69
int i
Definition: isn.c:73
Datum btoidvectorcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:296
Datum btint4cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:109
Datum btboolcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:73
#define A_GREATER_THAN_B
Definition: nbtcompare.c:68
Datum btint2cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:82
Datum btint24cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:203
Datum btoidcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:259
static int btint2fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:91
Datum btint84cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:189
Datum btoidsortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:287
Datum btcharcmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:320
#define A_LESS_THAN_B
Definition: nbtcompare.c:67
static int btoidfastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:273
static int btint8fastcmp(Datum x, Datum y, SortSupport ssup)
Definition: nbtcompare.c:147
Datum btint8sortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:162
Datum btint82cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:245
Datum btint48cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:175
Datum btint8cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:132
Datum btint4sortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:123
Datum btint42cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:217
Datum btint28cmp(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:231
Datum btint2sortsupport(PG_FUNCTION_ARGS)
Definition: nbtcompare.c:100
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
uintptr_t Datum
Definition: postgres.h:64
static Oid DatumGetObjectId(Datum X)
Definition: postgres.h:242
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:162
unsigned int Oid
Definition: postgres_ext.h:31
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
Definition: c.h:713
int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup)
Definition: tuplesort.c:3198