]> granicus.if.org Git - postgresql/blob - src/backend/access/nbtree/nbtcompare.c
Update copyright for 2014
[postgresql] / src / backend / access / nbtree / nbtcompare.c
1 /*-------------------------------------------------------------------------
2  *
3  * nbtcompare.c
4  *        Comparison functions for btree access method.
5  *
6  * Portions Copyright (c) 1996-2014, 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 btboolcmp(PG_FUNCTION_ARGS)
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
65 btint2cmp(PG_FUNCTION_ARGS)
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
74 btint2fastcmp(Datum x, Datum y, SortSupport ssup)
75 {
76         int16           a = DatumGetInt16(x);
77         int16           b = DatumGetInt16(y);
78
79         return (int) a - (int) b;
80 }
81
82 Datum
83 btint2sortsupport(PG_FUNCTION_ARGS)
84 {
85         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
86
87         ssup->comparator = btint2fastcmp;
88         PG_RETURN_VOID();
89 }
90
91 Datum
92 btint4cmp(PG_FUNCTION_ARGS)
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
106 btint4fastcmp(Datum x, Datum y, SortSupport ssup)
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
120 btint4sortsupport(PG_FUNCTION_ARGS)
121 {
122         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
123
124         ssup->comparator = btint4fastcmp;
125         PG_RETURN_VOID();
126 }
127
128 Datum
129 btint8cmp(PG_FUNCTION_ARGS)
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
143 btint8fastcmp(Datum x, Datum y, SortSupport ssup)
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
157 btint8sortsupport(PG_FUNCTION_ARGS)
158 {
159         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
160
161         ssup->comparator = btint8fastcmp;
162         PG_RETURN_VOID();
163 }
164
165 Datum
166 btint48cmp(PG_FUNCTION_ARGS)
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
180 btint84cmp(PG_FUNCTION_ARGS)
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
194 btint24cmp(PG_FUNCTION_ARGS)
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
208 btint42cmp(PG_FUNCTION_ARGS)
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
222 btint28cmp(PG_FUNCTION_ARGS)
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
236 btint82cmp(PG_FUNCTION_ARGS)
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
250 btoidcmp(PG_FUNCTION_ARGS)
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
264 btoidfastcmp(Datum x, Datum y, SortSupport ssup)
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
278 btoidsortsupport(PG_FUNCTION_ARGS)
279 {
280         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
281
282         ssup->comparator = btoidfastcmp;
283         PG_RETURN_VOID();
284 }
285
286 Datum
287 btoidvectorcmp(PG_FUNCTION_ARGS)
288 {
289         oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
290         oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
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
311 btcharcmp(PG_FUNCTION_ARGS)
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
321 btnamecmp(PG_FUNCTION_ARGS)
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
330 btnamefastcmp(Datum x, Datum y, SortSupport ssup)
331 {
332         Name            a = DatumGetName(x);
333         Name            b = DatumGetName(y);
334
335         return strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN);
336 }
337
338 Datum
339 btnamesortsupport(PG_FUNCTION_ARGS)
340 {
341         SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
342
343         ssup->comparator = btnamefastcmp;
344         PG_RETURN_VOID();
345 }