More sensible character_octet_length
[PostgreSQL.git] / contrib / citext / citext.c
blob006d0e471c4347d3068ba7025f62632d1ca22e57
1 /*
2 * $PostgreSQL$
3 */
4 #include "postgres.h"
6 #include "access/hash.h"
7 #include "fmgr.h"
8 #include "utils/builtins.h"
9 #include "utils/formatting.h"
11 #ifdef PG_MODULE_MAGIC
12 PG_MODULE_MAGIC;
13 #endif
16 * ====================
17 * FORWARD DECLARATIONS
18 * ====================
21 static int32 citextcmp(text *left, text *right);
22 extern Datum citext_cmp(PG_FUNCTION_ARGS);
23 extern Datum citext_hash(PG_FUNCTION_ARGS);
24 extern Datum citext_eq(PG_FUNCTION_ARGS);
25 extern Datum citext_ne(PG_FUNCTION_ARGS);
26 extern Datum citext_gt(PG_FUNCTION_ARGS);
27 extern Datum citext_ge(PG_FUNCTION_ARGS);
28 extern Datum citext_lt(PG_FUNCTION_ARGS);
29 extern Datum citext_le(PG_FUNCTION_ARGS);
30 extern Datum citext_smaller(PG_FUNCTION_ARGS);
31 extern Datum citext_larger(PG_FUNCTION_ARGS);
34 * =================
35 * UTILITY FUNCTIONS
36 * =================
40 * citextcmp()
41 * Internal comparison function for citext strings.
42 * Returns int32 negative, zero, or positive.
44 static int32
45 citextcmp(text *left, text *right)
47 char *lcstr,
48 *rcstr;
49 int32 result;
51 lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
52 rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
54 result = varstr_cmp(lcstr, strlen(lcstr),
55 rcstr, strlen(rcstr));
57 pfree(lcstr);
58 pfree(rcstr);
60 return result;
64 * ==================
65 * INDEXING FUNCTIONS
66 * ==================
69 PG_FUNCTION_INFO_V1(citext_cmp);
71 Datum
72 citext_cmp(PG_FUNCTION_ARGS)
74 text *left = PG_GETARG_TEXT_PP(0);
75 text *right = PG_GETARG_TEXT_PP(1);
76 int32 result;
78 result = citextcmp(left, right);
80 PG_FREE_IF_COPY(left, 0);
81 PG_FREE_IF_COPY(right, 1);
83 PG_RETURN_INT32(result);
86 PG_FUNCTION_INFO_V1(citext_hash);
88 Datum
89 citext_hash(PG_FUNCTION_ARGS)
91 text *txt = PG_GETARG_TEXT_PP(0);
92 char *str;
93 Datum result;
95 str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt));
96 result = hash_any((unsigned char *) str, strlen(str));
97 pfree(str);
99 /* Avoid leaking memory for toasted inputs */
100 PG_FREE_IF_COPY(txt, 0);
102 PG_RETURN_DATUM(result);
106 * ==================
107 * OPERATOR FUNCTIONS
108 * ==================
111 PG_FUNCTION_INFO_V1(citext_eq);
113 Datum
114 citext_eq(PG_FUNCTION_ARGS)
116 text *left = PG_GETARG_TEXT_PP(0);
117 text *right = PG_GETARG_TEXT_PP(1);
118 char *lcstr,
119 *rcstr;
120 bool result;
122 /* We can't compare lengths in advance of downcasing ... */
124 lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
125 rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
128 * Since we only care about equality or not-equality, we can avoid all the
129 * expense of strcoll() here, and just do bitwise comparison.
131 result = (strcmp(lcstr, rcstr) == 0);
133 pfree(lcstr);
134 pfree(rcstr);
135 PG_FREE_IF_COPY(left, 0);
136 PG_FREE_IF_COPY(right, 1);
138 PG_RETURN_BOOL(result);
141 PG_FUNCTION_INFO_V1(citext_ne);
143 Datum
144 citext_ne(PG_FUNCTION_ARGS)
146 text *left = PG_GETARG_TEXT_PP(0);
147 text *right = PG_GETARG_TEXT_PP(1);
148 char *lcstr,
149 *rcstr;
150 bool result;
152 /* We can't compare lengths in advance of downcasing ... */
154 lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left));
155 rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right));
158 * Since we only care about equality or not-equality, we can avoid all the
159 * expense of strcoll() here, and just do bitwise comparison.
161 result = (strcmp(lcstr, rcstr) != 0);
163 pfree(lcstr);
164 pfree(rcstr);
165 PG_FREE_IF_COPY(left, 0);
166 PG_FREE_IF_COPY(right, 1);
168 PG_RETURN_BOOL(result);
171 PG_FUNCTION_INFO_V1(citext_lt);
173 Datum
174 citext_lt(PG_FUNCTION_ARGS)
176 text *left = PG_GETARG_TEXT_PP(0);
177 text *right = PG_GETARG_TEXT_PP(1);
178 bool result;
180 result = citextcmp(left, right) < 0;
182 PG_FREE_IF_COPY(left, 0);
183 PG_FREE_IF_COPY(right, 1);
185 PG_RETURN_BOOL(result);
188 PG_FUNCTION_INFO_V1(citext_le);
190 Datum
191 citext_le(PG_FUNCTION_ARGS)
193 text *left = PG_GETARG_TEXT_PP(0);
194 text *right = PG_GETARG_TEXT_PP(1);
195 bool result;
197 result = citextcmp(left, right) <= 0;
199 PG_FREE_IF_COPY(left, 0);
200 PG_FREE_IF_COPY(right, 1);
202 PG_RETURN_BOOL(result);
205 PG_FUNCTION_INFO_V1(citext_gt);
207 Datum
208 citext_gt(PG_FUNCTION_ARGS)
210 text *left = PG_GETARG_TEXT_PP(0);
211 text *right = PG_GETARG_TEXT_PP(1);
212 bool result;
214 result = citextcmp(left, right) > 0;
216 PG_FREE_IF_COPY(left, 0);
217 PG_FREE_IF_COPY(right, 1);
219 PG_RETURN_BOOL(result);
222 PG_FUNCTION_INFO_V1(citext_ge);
224 Datum
225 citext_ge(PG_FUNCTION_ARGS)
227 text *left = PG_GETARG_TEXT_PP(0);
228 text *right = PG_GETARG_TEXT_PP(1);
229 bool result;
231 result = citextcmp(left, right) >= 0;
233 PG_FREE_IF_COPY(left, 0);
234 PG_FREE_IF_COPY(right, 1);
236 PG_RETURN_BOOL(result);
240 * ===================
241 * AGGREGATE FUNCTIONS
242 * ===================
245 PG_FUNCTION_INFO_V1(citext_smaller);
247 Datum
248 citext_smaller(PG_FUNCTION_ARGS)
250 text *left = PG_GETARG_TEXT_PP(0);
251 text *right = PG_GETARG_TEXT_PP(1);
252 text *result;
254 result = citextcmp(left, right) < 0 ? left : right;
255 PG_RETURN_TEXT_P(result);
258 PG_FUNCTION_INFO_V1(citext_larger);
260 Datum
261 citext_larger(PG_FUNCTION_ARGS)
263 text *left = PG_GETARG_TEXT_PP(0);
264 text *right = PG_GETARG_TEXT_PP(1);
265 text *result;
267 result = citextcmp(left, right) > 0 ? left : right;
268 PG_RETURN_TEXT_P(result);