]> granicus.if.org Git - postgresql/blob - src/backend/access/nbtree/nbtcompare.c
23f2b61fe902cff7eebcf8526cf8116d90be75e8
[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-2011, 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
53
54 Datum
55 btboolcmp(PG_FUNCTION_ARGS)
56 {
57         bool            a = PG_GETARG_BOOL(0);
58         bool            b = PG_GETARG_BOOL(1);
59
60         PG_RETURN_INT32((int32) a - (int32) b);
61 }
62
63 Datum
64 btint2cmp(PG_FUNCTION_ARGS)
65 {
66         int16           a = PG_GETARG_INT16(0);
67         int16           b = PG_GETARG_INT16(1);
68
69         PG_RETURN_INT32((int32) a - (int32) b);
70 }
71
72 Datum
73 btint4cmp(PG_FUNCTION_ARGS)
74 {
75         int32           a = PG_GETARG_INT32(0);
76         int32           b = PG_GETARG_INT32(1);
77
78         if (a > b)
79                 PG_RETURN_INT32(1);
80         else if (a == b)
81                 PG_RETURN_INT32(0);
82         else
83                 PG_RETURN_INT32(-1);
84 }
85
86 Datum
87 btint8cmp(PG_FUNCTION_ARGS)
88 {
89         int64           a = PG_GETARG_INT64(0);
90         int64           b = PG_GETARG_INT64(1);
91
92         if (a > b)
93                 PG_RETURN_INT32(1);
94         else if (a == b)
95                 PG_RETURN_INT32(0);
96         else
97                 PG_RETURN_INT32(-1);
98 }
99
100 Datum
101 btint48cmp(PG_FUNCTION_ARGS)
102 {
103         int32           a = PG_GETARG_INT32(0);
104         int64           b = PG_GETARG_INT64(1);
105
106         if (a > b)
107                 PG_RETURN_INT32(1);
108         else if (a == b)
109                 PG_RETURN_INT32(0);
110         else
111                 PG_RETURN_INT32(-1);
112 }
113
114 Datum
115 btint84cmp(PG_FUNCTION_ARGS)
116 {
117         int64           a = PG_GETARG_INT64(0);
118         int32           b = PG_GETARG_INT32(1);
119
120         if (a > b)
121                 PG_RETURN_INT32(1);
122         else if (a == b)
123                 PG_RETURN_INT32(0);
124         else
125                 PG_RETURN_INT32(-1);
126 }
127
128 Datum
129 btint24cmp(PG_FUNCTION_ARGS)
130 {
131         int16           a = PG_GETARG_INT16(0);
132         int32           b = PG_GETARG_INT32(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 Datum
143 btint42cmp(PG_FUNCTION_ARGS)
144 {
145         int32           a = PG_GETARG_INT32(0);
146         int16           b = PG_GETARG_INT16(1);
147
148         if (a > b)
149                 PG_RETURN_INT32(1);
150         else if (a == b)
151                 PG_RETURN_INT32(0);
152         else
153                 PG_RETURN_INT32(-1);
154 }
155
156 Datum
157 btint28cmp(PG_FUNCTION_ARGS)
158 {
159         int16           a = PG_GETARG_INT16(0);
160         int64           b = PG_GETARG_INT64(1);
161
162         if (a > b)
163                 PG_RETURN_INT32(1);
164         else if (a == b)
165                 PG_RETURN_INT32(0);
166         else
167                 PG_RETURN_INT32(-1);
168 }
169
170 Datum
171 btint82cmp(PG_FUNCTION_ARGS)
172 {
173         int64           a = PG_GETARG_INT64(0);
174         int16           b = PG_GETARG_INT16(1);
175
176         if (a > b)
177                 PG_RETURN_INT32(1);
178         else if (a == b)
179                 PG_RETURN_INT32(0);
180         else
181                 PG_RETURN_INT32(-1);
182 }
183
184 Datum
185 btoidcmp(PG_FUNCTION_ARGS)
186 {
187         Oid                     a = PG_GETARG_OID(0);
188         Oid                     b = PG_GETARG_OID(1);
189
190         if (a > b)
191                 PG_RETURN_INT32(1);
192         else if (a == b)
193                 PG_RETURN_INT32(0);
194         else
195                 PG_RETURN_INT32(-1);
196 }
197
198 Datum
199 btoidvectorcmp(PG_FUNCTION_ARGS)
200 {
201         oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
202         oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
203         int                     i;
204
205         /* We arbitrarily choose to sort first by vector length */
206         if (a->dim1 != b->dim1)
207                 PG_RETURN_INT32(a->dim1 - b->dim1);
208
209         for (i = 0; i < a->dim1; i++)
210         {
211                 if (a->values[i] != b->values[i])
212                 {
213                         if (a->values[i] > b->values[i])
214                                 PG_RETURN_INT32(1);
215                         else
216                                 PG_RETURN_INT32(-1);
217                 }
218         }
219         PG_RETURN_INT32(0);
220 }
221
222 Datum
223 btcharcmp(PG_FUNCTION_ARGS)
224 {
225         char            a = PG_GETARG_CHAR(0);
226         char            b = PG_GETARG_CHAR(1);
227
228         /* Be careful to compare chars as unsigned */
229         PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
230 }
231
232 Datum
233 btnamecmp(PG_FUNCTION_ARGS)
234 {
235         Name            a = PG_GETARG_NAME(0);
236         Name            b = PG_GETARG_NAME(1);
237
238         PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN));
239 }