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 813618 : btboolcmp(PG_FUNCTION_ARGS)
57 : {
58 813618 : bool a = PG_GETARG_BOOL(0);
59 813618 : bool b = PG_GETARG_BOOL(1);
60 :
61 813618 : PG_RETURN_INT32((int32) a - (int32) b);
62 : }
63 :
64 : Datum
65 210667 : btint2cmp(PG_FUNCTION_ARGS)
66 : {
67 210667 : int16 a = PG_GETARG_INT16(0);
68 210667 : int16 b = PG_GETARG_INT16(1);
69 :
70 210667 : PG_RETURN_INT32((int32) a - (int32) b);
71 : }
72 :
73 : static int
74 336601 : btint2fastcmp(Datum x, Datum y, SortSupport ssup)
75 : {
76 336601 : int16 a = DatumGetInt16(x);
77 336601 : int16 b = DatumGetInt16(y);
78 :
79 336601 : return (int) a - (int) b;
80 : }
81 :
82 : Datum
83 52 : btint2sortsupport(PG_FUNCTION_ARGS)
84 : {
85 52 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
86 :
87 52 : ssup->comparator = btint2fastcmp;
88 52 : PG_RETURN_VOID();
89 : }
90 :
91 : Datum
92 4790758 : btint4cmp(PG_FUNCTION_ARGS)
93 : {
94 4790758 : int32 a = PG_GETARG_INT32(0);
95 4790758 : int32 b = PG_GETARG_INT32(1);
96 :
97 4790758 : if (a > b)
98 2222345 : PG_RETURN_INT32(1);
99 2568413 : else if (a == b)
100 596037 : PG_RETURN_INT32(0);
101 : else
102 1972376 : PG_RETURN_INT32(-1);
103 : }
104 :
105 : static int
106 19266392 : btint4fastcmp(Datum x, Datum y, SortSupport ssup)
107 : {
108 19266392 : int32 a = DatumGetInt32(x);
109 19266392 : int32 b = DatumGetInt32(y);
110 :
111 19266392 : if (a > b)
112 5029360 : return 1;
113 14237032 : else if (a == b)
114 8998685 : return 0;
115 : else
116 5238347 : return -1;
117 : }
118 :
119 : Datum
120 4233 : btint4sortsupport(PG_FUNCTION_ARGS)
121 : {
122 4233 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
123 :
124 4233 : ssup->comparator = btint4fastcmp;
125 4233 : 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 2058 : btint8fastcmp(Datum x, Datum y, SortSupport ssup)
144 : {
145 2058 : int64 a = DatumGetInt64(x);
146 2058 : int64 b = DatumGetInt64(y);
147 :
148 2058 : if (a > b)
149 688 : return 1;
150 1370 : else if (a == b)
151 637 : return 0;
152 : else
153 733 : return -1;
154 : }
155 :
156 : Datum
157 112 : btint8sortsupport(PG_FUNCTION_ARGS)
158 : {
159 112 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
160 :
161 112 : ssup->comparator = btint8fastcmp;
162 112 : 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 2048 : btint24cmp(PG_FUNCTION_ARGS)
195 : {
196 2048 : int16 a = PG_GETARG_INT16(0);
197 2048 : int32 b = PG_GETARG_INT32(1);
198 :
199 2048 : if (a > b)
200 1337 : PG_RETURN_INT32(1);
201 711 : else if (a == b)
202 0 : PG_RETURN_INT32(0);
203 : else
204 711 : 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 6757994 : btoidcmp(PG_FUNCTION_ARGS)
251 : {
252 6757994 : Oid a = PG_GETARG_OID(0);
253 6757994 : Oid b = PG_GETARG_OID(1);
254 :
255 6757994 : if (a > b)
256 1665756 : PG_RETURN_INT32(1);
257 5092238 : else if (a == b)
258 2219449 : PG_RETURN_INT32(0);
259 : else
260 2872789 : PG_RETURN_INT32(-1);
261 : }
262 :
263 : static int
264 1949179 : btoidfastcmp(Datum x, Datum y, SortSupport ssup)
265 : {
266 1949179 : Oid a = DatumGetObjectId(x);
267 1949179 : Oid b = DatumGetObjectId(y);
268 :
269 1949179 : if (a > b)
270 410839 : return 1;
271 1538340 : else if (a == b)
272 1166915 : return 0;
273 : else
274 371425 : return -1;
275 : }
276 :
277 : Datum
278 2181 : btoidsortsupport(PG_FUNCTION_ARGS)
279 : {
280 2181 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
281 :
282 2181 : ssup->comparator = btoidfastcmp;
283 2181 : PG_RETURN_VOID();
284 : }
285 :
286 : Datum
287 84223 : btoidvectorcmp(PG_FUNCTION_ARGS)
288 : {
289 84223 : oidvector *a = (oidvector *) PG_GETARG_POINTER(0);
290 84223 : oidvector *b = (oidvector *) PG_GETARG_POINTER(1);
291 : int i;
292 :
293 : /* We arbitrarily choose to sort first by vector length */
294 84223 : if (a->dim1 != b->dim1)
295 12504 : PG_RETURN_INT32(a->dim1 - b->dim1);
296 :
297 128324 : for (i = 0; i < a->dim1; i++)
298 : {
299 96974 : if (a->values[i] != b->values[i])
300 : {
301 40369 : if (a->values[i] > b->values[i])
302 21766 : PG_RETURN_INT32(1);
303 : else
304 18603 : PG_RETURN_INT32(-1);
305 : }
306 : }
307 31350 : PG_RETURN_INT32(0);
308 : }
309 :
310 : Datum
311 712445 : btcharcmp(PG_FUNCTION_ARGS)
312 : {
313 712445 : char a = PG_GETARG_CHAR(0);
314 712445 : char b = PG_GETARG_CHAR(1);
315 :
316 : /* Be careful to compare chars as unsigned */
317 712445 : PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
318 : }
319 :
320 : Datum
321 656933 : btnamecmp(PG_FUNCTION_ARGS)
322 : {
323 656933 : Name a = PG_GETARG_NAME(0);
324 656933 : Name b = PG_GETARG_NAME(1);
325 :
326 656933 : PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
327 : }
328 :
329 : static int
330 1823508 : btnamefastcmp(Datum x, Datum y, SortSupport ssup)
331 : {
332 1823508 : Name a = DatumGetName(x);
333 1823508 : Name b = DatumGetName(y);
334 :
335 1823508 : return strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN);
336 : }
337 :
338 : Datum
339 1332 : btnamesortsupport(PG_FUNCTION_ARGS)
340 : {
341 1332 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
342 :
343 1332 : ssup->comparator = btnamefastcmp;
344 1332 : PG_RETURN_VOID();
345 : }
|