Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nbtcompare.c
4 : * Comparison functions for btree access method.
5 : *
6 : * Portions Copyright (c) 1996-2023, 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/builtins.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
8343 tgl 73 CBC 92359605 : btboolcmp(PG_FUNCTION_ARGS)
74 : {
75 92359605 : bool a = PG_GETARG_BOOL(0);
76 92359605 : bool b = PG_GETARG_BOOL(1);
77 :
78 92359605 : PG_RETURN_INT32((int32) a - (int32) b);
79 : }
80 :
81 : Datum
82 8321455 : btint2cmp(PG_FUNCTION_ARGS)
83 : {
84 8321455 : int16 a = PG_GETARG_INT16(0);
85 8321455 : int16 b = PG_GETARG_INT16(1);
86 :
87 8321455 : PG_RETURN_INT32((int32) a - (int32) b);
88 : }
89 :
90 : static int
4141 91 81347810 : btint2fastcmp(Datum x, Datum y, SortSupport ssup)
92 : {
93 81347810 : int16 a = DatumGetInt16(x);
94 81347810 : int16 b = DatumGetInt16(y);
95 :
96 81347810 : return (int) a - (int) b;
97 : }
98 :
99 : Datum
100 9270 : btint2sortsupport(PG_FUNCTION_ARGS)
101 : {
3955 bruce 102 9270 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
103 :
4141 tgl 104 9270 : ssup->comparator = btint2fastcmp;
105 9270 : PG_RETURN_VOID();
106 : }
107 :
108 : Datum
8343 109 47213355 : btint4cmp(PG_FUNCTION_ARGS)
110 : {
111 47213355 : int32 a = PG_GETARG_INT32(0);
112 47213355 : int32 b = PG_GETARG_INT32(1);
113 :
8397 bruce 114 47213355 : if (a > b)
1647 tgl 115 17169383 : PG_RETURN_INT32(A_GREATER_THAN_B);
8397 bruce 116 30043972 : else if (a == b)
8343 tgl 117 10833823 : PG_RETURN_INT32(0);
118 : else
1647 119 19210149 : PG_RETURN_INT32(A_LESS_THAN_B);
120 : }
121 :
122 : Datum
4141 123 103323 : btint4sortsupport(PG_FUNCTION_ARGS)
124 : {
3955 bruce 125 103323 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
126 :
372 john.naylor 127 103323 : ssup->comparator = ssup_datum_int32_cmp;
4141 tgl 128 103323 : PG_RETURN_VOID();
129 : }
130 :
131 : Datum
8343 132 7801644 : btint8cmp(PG_FUNCTION_ARGS)
133 : {
134 7801644 : int64 a = PG_GETARG_INT64(0);
135 7801644 : int64 b = PG_GETARG_INT64(1);
136 :
137 7801644 : if (a > b)
1647 138 4355459 : PG_RETURN_INT32(A_GREATER_THAN_B);
8343 139 3446185 : else if (a == b)
140 420127 : PG_RETURN_INT32(0);
141 : else
1647 142 3026058 : PG_RETURN_INT32(A_LESS_THAN_B);
143 : }
144 :
145 : #if SIZEOF_DATUM < 8
146 : static int
147 : btint8fastcmp(Datum x, Datum y, SortSupport ssup)
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
4141 162 1422 : btint8sortsupport(PG_FUNCTION_ARGS)
163 : {
3955 bruce 164 1422 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
165 :
166 : #if SIZEOF_DATUM >= 8
372 john.naylor 167 1422 : ssup->comparator = ssup_datum_signed_cmp;
168 : #else
169 : ssup->comparator = btint8fastcmp;
170 : #endif
4141 tgl 171 1422 : PG_RETURN_VOID();
172 : }
173 :
174 : Datum
7088 175 717 : btint48cmp(PG_FUNCTION_ARGS)
176 : {
177 717 : int32 a = PG_GETARG_INT32(0);
178 717 : int64 b = PG_GETARG_INT64(1);
179 :
180 717 : if (a > b)
1647 181 249 : PG_RETURN_INT32(A_GREATER_THAN_B);
7088 182 468 : else if (a == b)
183 33 : PG_RETURN_INT32(0);
184 : else
1647 185 435 : PG_RETURN_INT32(A_LESS_THAN_B);
186 : }
187 :
188 : Datum
7088 189 45 : btint84cmp(PG_FUNCTION_ARGS)
190 : {
191 45 : int64 a = PG_GETARG_INT64(0);
192 45 : int32 b = PG_GETARG_INT32(1);
193 :
194 45 : if (a > b)
1647 195 15 : PG_RETURN_INT32(A_GREATER_THAN_B);
7088 196 30 : else if (a == b)
197 15 : PG_RETURN_INT32(0);
198 : else
1647 199 15 : PG_RETURN_INT32(A_LESS_THAN_B);
200 : }
201 :
202 : Datum
7088 203 16437 : btint24cmp(PG_FUNCTION_ARGS)
204 : {
205 16437 : int16 a = PG_GETARG_INT16(0);
206 16437 : int32 b = PG_GETARG_INT32(1);
207 :
208 16437 : if (a > b)
1647 209 9536 : PG_RETURN_INT32(A_GREATER_THAN_B);
7088 210 6901 : else if (a == b)
211 1748 : PG_RETURN_INT32(0);
212 : else
1647 213 5153 : PG_RETURN_INT32(A_LESS_THAN_B);
214 : }
215 :
216 : Datum
7088 217 627 : btint42cmp(PG_FUNCTION_ARGS)
218 : {
219 627 : int32 a = PG_GETARG_INT32(0);
220 627 : int16 b = PG_GETARG_INT16(1);
221 :
222 627 : if (a > b)
1647 223 36 : PG_RETURN_INT32(A_GREATER_THAN_B);
7088 224 591 : else if (a == b)
225 127 : PG_RETURN_INT32(0);
226 : else
1647 227 464 : PG_RETURN_INT32(A_LESS_THAN_B);
228 : }
229 :
230 : Datum
7088 231 18 : btint28cmp(PG_FUNCTION_ARGS)
232 : {
233 18 : int16 a = PG_GETARG_INT16(0);
234 18 : int64 b = PG_GETARG_INT64(1);
235 :
236 18 : if (a > b)
1647 tgl 237 UBC 0 : PG_RETURN_INT32(A_GREATER_THAN_B);
7088 tgl 238 CBC 18 : else if (a == b)
7088 tgl 239 UBC 0 : PG_RETURN_INT32(0);
240 : else
1647 tgl 241 CBC 18 : PG_RETURN_INT32(A_LESS_THAN_B);
242 : }
243 :
244 : Datum
7088 tgl 245 UBC 0 : btint82cmp(PG_FUNCTION_ARGS)
246 : {
247 0 : int64 a = PG_GETARG_INT64(0);
248 0 : int16 b = PG_GETARG_INT16(1);
249 :
250 0 : if (a > b)
1647 251 0 : PG_RETURN_INT32(A_GREATER_THAN_B);
7088 252 0 : else if (a == b)
253 0 : PG_RETURN_INT32(0);
254 : else
1647 255 0 : PG_RETURN_INT32(A_LESS_THAN_B);
256 : }
257 :
258 : Datum
8343 tgl 259 CBC 143511100 : btoidcmp(PG_FUNCTION_ARGS)
260 : {
261 143511100 : Oid a = PG_GETARG_OID(0);
262 143511100 : Oid b = PG_GETARG_OID(1);
263 :
9345 bruce 264 143511100 : if (a > b)
1647 tgl 265 32440154 : PG_RETURN_INT32(A_GREATER_THAN_B);
9345 bruce 266 111070946 : else if (a == b)
8343 tgl 267 36247307 : PG_RETURN_INT32(0);
268 : else
1647 269 74823639 : PG_RETURN_INT32(A_LESS_THAN_B);
270 : }
271 :
272 : static int
4141 273 362043838 : btoidfastcmp(Datum x, Datum y, SortSupport ssup)
274 : {
275 362043838 : Oid a = DatumGetObjectId(x);
276 362043838 : Oid b = DatumGetObjectId(y);
277 :
278 362043838 : if (a > b)
1647 279 89397142 : return A_GREATER_THAN_B;
4141 280 272646696 : else if (a == b)
281 183443992 : return 0;
282 : else
1647 283 89202704 : return A_LESS_THAN_B;
284 : }
285 :
286 : Datum
4141 287 179850 : btoidsortsupport(PG_FUNCTION_ARGS)
288 : {
3955 bruce 289 179850 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
290 :
4141 tgl 291 179850 : ssup->comparator = btoidfastcmp;
292 179850 : PG_RETURN_VOID();
293 : }
294 :
295 : Datum
8343 296 14546183 : btoidvectorcmp(PG_FUNCTION_ARGS)
297 : {
6585 298 14546183 : oidvector *a = (oidvector *) PG_GETARG_POINTER(0);
299 14546183 : oidvector *b = (oidvector *) PG_GETARG_POINTER(1);
300 : int i;
301 :
302 : /* We arbitrarily choose to sort first by vector length */
303 14546183 : if (a->dim1 != b->dim1)
304 2425930 : PG_RETURN_INT32(a->dim1 - b->dim1);
305 :
306 21431084 : for (i = 0; i < a->dim1; i++)
307 : {
308 16479988 : if (a->values[i] != b->values[i])
309 : {
310 7169157 : if (a->values[i] > b->values[i])
1647 311 3822871 : PG_RETURN_INT32(A_GREATER_THAN_B);
312 : else
313 3346286 : PG_RETURN_INT32(A_LESS_THAN_B);
314 : }
315 : }
8343 316 4951096 : PG_RETURN_INT32(0);
317 : }
318 :
319 : Datum
320 105151804 : btcharcmp(PG_FUNCTION_ARGS)
321 : {
322 105151804 : char a = PG_GETARG_CHAR(0);
323 105151804 : char b = PG_GETARG_CHAR(1);
324 :
325 : /* Be careful to compare chars as unsigned */
326 105151804 : PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
327 : }
|