Line data Source code
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
56 638823 : btboolcmp(PG_FUNCTION_ARGS)
57 : {
58 638823 : bool a = PG_GETARG_BOOL(0);
59 638823 : bool b = PG_GETARG_BOOL(1);
60 :
61 638823 : PG_RETURN_INT32((int32) a - (int32) b);
62 : }
63 :
64 : Datum
65 207563 : btint2cmp(PG_FUNCTION_ARGS)
66 : {
67 207563 : int16 a = PG_GETARG_INT16(0);
68 207563 : int16 b = PG_GETARG_INT16(1);
69 :
70 207563 : PG_RETURN_INT32((int32) a - (int32) b);
71 : }
72 :
73 : static int
74 277484 : btint2fastcmp(Datum x, Datum y, SortSupport ssup)
75 : {
76 277484 : int16 a = DatumGetInt16(x);
77 277484 : int16 b = DatumGetInt16(y);
78 :
79 277484 : return (int) a - (int) b;
80 : }
81 :
82 : Datum
83 50 : btint2sortsupport(PG_FUNCTION_ARGS)
84 : {
85 50 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
86 :
87 50 : ssup->comparator = btint2fastcmp;
88 50 : PG_RETURN_VOID();
89 : }
90 :
91 : Datum
92 4785401 : btint4cmp(PG_FUNCTION_ARGS)
93 : {
94 4785401 : int32 a = PG_GETARG_INT32(0);
95 4785401 : int32 b = PG_GETARG_INT32(1);
96 :
97 4785401 : if (a > b)
98 2218216 : PG_RETURN_INT32(1);
99 2567185 : else if (a == b)
100 595732 : PG_RETURN_INT32(0);
101 : else
102 1971453 : PG_RETURN_INT32(-1);
103 : }
104 :
105 : static int
106 19218425 : btint4fastcmp(Datum x, Datum y, SortSupport ssup)
107 : {
108 19218425 : int32 a = DatumGetInt32(x);
109 19218425 : int32 b = DatumGetInt32(y);
110 :
111 19218425 : if (a > b)
112 5024687 : return 1;
113 14193738 : else if (a == b)
114 8970009 : return 0;
115 : else
116 5223729 : return -1;
117 : }
118 :
119 : Datum
120 4227 : btint4sortsupport(PG_FUNCTION_ARGS)
121 : {
122 4227 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
123 :
124 4227 : ssup->comparator = btint4fastcmp;
125 4227 : PG_RETURN_VOID();
126 : }
127 :
128 : Datum
129 127 : btint8cmp(PG_FUNCTION_ARGS)
130 : {
131 127 : int64 a = PG_GETARG_INT64(0);
132 127 : int64 b = PG_GETARG_INT64(1);
133 :
134 127 : if (a > b)
135 30 : PG_RETURN_INT32(1);
136 97 : else if (a == b)
137 50 : PG_RETURN_INT32(0);
138 : else
139 47 : PG_RETURN_INT32(-1);
140 : }
141 :
142 : static int
143 1332 : btint8fastcmp(Datum x, Datum y, SortSupport ssup)
144 : {
145 1332 : int64 a = DatumGetInt64(x);
146 1332 : int64 b = DatumGetInt64(y);
147 :
148 1332 : if (a > b)
149 317 : return 1;
150 1015 : else if (a == b)
151 626 : return 0;
152 : else
153 389 : return -1;
154 : }
155 :
156 : Datum
157 111 : btint8sortsupport(PG_FUNCTION_ARGS)
158 : {
159 111 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
160 :
161 111 : ssup->comparator = btint8fastcmp;
162 111 : PG_RETURN_VOID();
163 : }
164 :
165 : Datum
166 281 : btint48cmp(PG_FUNCTION_ARGS)
167 : {
168 281 : int32 a = PG_GETARG_INT32(0);
169 281 : int64 b = PG_GETARG_INT64(1);
170 :
171 281 : if (a > b)
172 105 : PG_RETURN_INT32(1);
173 176 : else if (a == b)
174 14 : PG_RETURN_INT32(0);
175 : else
176 162 : PG_RETURN_INT32(-1);
177 : }
178 :
179 : Datum
180 0 : btint84cmp(PG_FUNCTION_ARGS)
181 : {
182 0 : int64 a = PG_GETARG_INT64(0);
183 0 : int32 b = PG_GETARG_INT32(1);
184 :
185 0 : if (a > b)
186 0 : PG_RETURN_INT32(1);
187 0 : else if (a == b)
188 0 : PG_RETURN_INT32(0);
189 : else
190 0 : PG_RETURN_INT32(-1);
191 : }
192 :
193 : Datum
194 2040 : btint24cmp(PG_FUNCTION_ARGS)
195 : {
196 2040 : int16 a = PG_GETARG_INT16(0);
197 2040 : int32 b = PG_GETARG_INT32(1);
198 :
199 2040 : if (a > b)
200 1334 : PG_RETURN_INT32(1);
201 706 : else if (a == b)
202 0 : PG_RETURN_INT32(0);
203 : else
204 706 : PG_RETURN_INT32(-1);
205 : }
206 :
207 : Datum
208 0 : btint42cmp(PG_FUNCTION_ARGS)
209 : {
210 0 : int32 a = PG_GETARG_INT32(0);
211 0 : int16 b = PG_GETARG_INT16(1);
212 :
213 0 : if (a > b)
214 0 : PG_RETURN_INT32(1);
215 0 : else if (a == b)
216 0 : PG_RETURN_INT32(0);
217 : else
218 0 : PG_RETURN_INT32(-1);
219 : }
220 :
221 : Datum
222 0 : btint28cmp(PG_FUNCTION_ARGS)
223 : {
224 0 : int16 a = PG_GETARG_INT16(0);
225 0 : int64 b = PG_GETARG_INT64(1);
226 :
227 0 : if (a > b)
228 0 : PG_RETURN_INT32(1);
229 0 : else if (a == b)
230 0 : PG_RETURN_INT32(0);
231 : else
232 0 : PG_RETURN_INT32(-1);
233 : }
234 :
235 : Datum
236 0 : btint82cmp(PG_FUNCTION_ARGS)
237 : {
238 0 : int64 a = PG_GETARG_INT64(0);
239 0 : int16 b = PG_GETARG_INT16(1);
240 :
241 0 : if (a > b)
242 0 : PG_RETURN_INT32(1);
243 0 : else if (a == b)
244 0 : PG_RETURN_INT32(0);
245 : else
246 0 : PG_RETURN_INT32(-1);
247 : }
248 :
249 : Datum
250 6778687 : btoidcmp(PG_FUNCTION_ARGS)
251 : {
252 6778687 : Oid a = PG_GETARG_OID(0);
253 6778687 : Oid b = PG_GETARG_OID(1);
254 :
255 6778687 : if (a > b)
256 1671914 : PG_RETURN_INT32(1);
257 5106773 : else if (a == b)
258 2224976 : PG_RETURN_INT32(0);
259 : else
260 2881797 : PG_RETURN_INT32(-1);
261 : }
262 :
263 : static int
264 1863635 : btoidfastcmp(Datum x, Datum y, SortSupport ssup)
265 : {
266 1863635 : Oid a = DatumGetObjectId(x);
267 1863635 : Oid b = DatumGetObjectId(y);
268 :
269 1863635 : if (a > b)
270 396559 : return 1;
271 1467076 : else if (a == b)
272 1108336 : return 0;
273 : else
274 358740 : return -1;
275 : }
276 :
277 : Datum
278 2177 : btoidsortsupport(PG_FUNCTION_ARGS)
279 : {
280 2177 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
281 :
282 2177 : ssup->comparator = btoidfastcmp;
283 2177 : PG_RETURN_VOID();
284 : }
285 :
286 : Datum
287 46581 : btoidvectorcmp(PG_FUNCTION_ARGS)
288 : {
289 46581 : oidvector *a = (oidvector *) PG_GETARG_POINTER(0);
290 46581 : oidvector *b = (oidvector *) PG_GETARG_POINTER(1);
291 : int i;
292 :
293 : /* We arbitrarily choose to sort first by vector length */
294 46581 : if (a->dim1 != b->dim1)
295 7813 : PG_RETURN_INT32(a->dim1 - b->dim1);
296 :
297 72370 : for (i = 0; i < a->dim1; i++)
298 : {
299 53643 : if (a->values[i] != b->values[i])
300 : {
301 20041 : if (a->values[i] > b->values[i])
302 10842 : PG_RETURN_INT32(1);
303 : else
304 9199 : PG_RETURN_INT32(-1);
305 : }
306 : }
307 18727 : PG_RETURN_INT32(0);
308 : }
309 :
310 : Datum
311 664708 : btcharcmp(PG_FUNCTION_ARGS)
312 : {
313 664708 : char a = PG_GETARG_CHAR(0);
314 664708 : char b = PG_GETARG_CHAR(1);
315 :
316 : /* Be careful to compare chars as unsigned */
317 664708 : PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
318 : }
319 :
320 : Datum
321 665472 : btnamecmp(PG_FUNCTION_ARGS)
322 : {
323 665472 : Name a = PG_GETARG_NAME(0);
324 665472 : Name b = PG_GETARG_NAME(1);
325 :
326 665472 : PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
327 : }
328 :
329 : static int
330 1771272 : btnamefastcmp(Datum x, Datum y, SortSupport ssup)
331 : {
332 1771272 : Name a = DatumGetName(x);
333 1771272 : Name b = DatumGetName(y);
334 :
335 1771272 : return strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN);
336 : }
337 :
338 : Datum
339 1413 : btnamesortsupport(PG_FUNCTION_ARGS)
340 : {
341 1413 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
342 :
343 1413 : ssup->comparator = btnamefastcmp;
344 1413 : PG_RETURN_VOID();
345 : }
|