Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * contrib/citext/citext.c
3 : : */
4 : : #include "postgres.h"
5 : :
6 : : #include "catalog/pg_collation.h"
7 : : #include "common/hashfn.h"
8 : : #include "utils/builtins.h"
9 : : #include "utils/formatting.h"
10 : : #include "utils/varlena.h"
11 : : #include "varatt.h"
12 : :
5738 tgl@sss.pgh.pa.us 13 :CBC 3 : PG_MODULE_MAGIC;
14 : :
15 : : /*
16 : : * ====================
17 : : * FORWARD DECLARATIONS
18 : : * ====================
19 : : */
20 : :
21 : : static int32 citextcmp(text *left, text *right, Oid collid);
22 : : static int32 internal_citext_pattern_cmp(text *left, text *right, Oid collid);
23 : :
24 : : /*
25 : : * =================
26 : : * UTILITY FUNCTIONS
27 : : * =================
28 : : */
29 : :
30 : : /*
31 : : * citextcmp()
32 : : * Internal comparison function for citext strings.
33 : : * Returns int32 negative, zero, or positive.
34 : : */
35 : : static int32
4814 peter_e@gmx.net 36 : 163 : citextcmp(text *left, text *right, Oid collid)
37 : : {
38 : : char *lcstr,
39 : : *rcstr;
40 : : int32 result;
41 : :
42 : : /*
43 : : * We must do our str_tolower calls with DEFAULT_COLLATION_OID, not the
44 : : * input collation as you might expect. This is so that the behavior of
45 : : * citext's equality and hashing functions is not collation-dependent. We
46 : : * should change this once the core infrastructure is able to cope with
47 : : * collation-dependent equality and hashing functions.
48 : : */
49 : :
4694 tgl@sss.pgh.pa.us 50 [ - + - - : 163 : lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
51 [ - + - - : 163 : rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
52 : :
5421 bruce@momjian.us 53 : 163 : result = varstr_cmp(lcstr, strlen(lcstr),
4814 peter_e@gmx.net 54 : 163 : rcstr, strlen(rcstr),
55 : : collid);
56 : :
5421 bruce@momjian.us 57 : 163 : pfree(lcstr);
58 : 163 : pfree(rcstr);
59 : :
60 : 163 : return result;
61 : : }
62 : :
63 : : /*
64 : : * citext_pattern_cmp()
65 : : * Internal character-by-character comparison function for citext strings.
66 : : * Returns int32 negative, zero, or positive.
67 : : */
68 : : static int32
2399 andrew@dunslane.net 69 : 55 : internal_citext_pattern_cmp(text *left, text *right, Oid collid)
70 : : {
71 : : char *lcstr,
72 : : *rcstr;
73 : : int llen,
74 : : rlen;
75 : : int32 result;
76 : :
77 [ - + - - : 55 : lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
78 [ - + - - : 55 : rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
79 : :
80 : 55 : llen = strlen(lcstr);
81 : 55 : rlen = strlen(rcstr);
82 : :
432 peter@eisentraut.org 83 : 55 : result = memcmp(lcstr, rcstr, Min(llen, rlen));
2399 andrew@dunslane.net 84 [ + + ]: 55 : if (result == 0)
85 : : {
86 [ + + ]: 20 : if (llen < rlen)
87 : 1 : result = -1;
88 [ + + ]: 19 : else if (llen > rlen)
89 : 1 : result = 1;
90 : : }
91 : :
92 : 55 : pfree(lcstr);
93 : 55 : pfree(rcstr);
94 : :
95 : 55 : return result;
96 : : }
97 : :
98 : : /*
99 : : * ==================
100 : : * INDEXING FUNCTIONS
101 : : * ==================
102 : : */
103 : :
5738 tgl@sss.pgh.pa.us 104 : 5 : PG_FUNCTION_INFO_V1(citext_cmp);
105 : :
106 : : Datum
107 : 144 : citext_cmp(PG_FUNCTION_ARGS)
108 : : {
5421 bruce@momjian.us 109 : 144 : text *left = PG_GETARG_TEXT_PP(0);
110 : 144 : text *right = PG_GETARG_TEXT_PP(1);
111 : : int32 result;
112 : :
4814 peter_e@gmx.net 113 : 144 : result = citextcmp(left, right, PG_GET_COLLATION());
114 : :
5421 bruce@momjian.us 115 [ - + ]: 144 : PG_FREE_IF_COPY(left, 0);
116 [ - + ]: 144 : PG_FREE_IF_COPY(right, 1);
117 : :
118 : 144 : PG_RETURN_INT32(result);
119 : : }
120 : :
2399 andrew@dunslane.net 121 : 4 : PG_FUNCTION_INFO_V1(citext_pattern_cmp);
122 : :
123 : : Datum
124 : 11 : citext_pattern_cmp(PG_FUNCTION_ARGS)
125 : : {
126 : 11 : text *left = PG_GETARG_TEXT_PP(0);
127 : 11 : text *right = PG_GETARG_TEXT_PP(1);
128 : : int32 result;
129 : :
130 : 11 : result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION());
131 : :
132 [ - + ]: 11 : PG_FREE_IF_COPY(left, 0);
133 [ - + ]: 11 : PG_FREE_IF_COPY(right, 1);
134 : :
135 : 11 : PG_RETURN_INT32(result);
136 : : }
137 : :
5738 tgl@sss.pgh.pa.us 138 : 3 : PG_FUNCTION_INFO_V1(citext_hash);
139 : :
140 : : Datum
141 : 10 : citext_hash(PG_FUNCTION_ARGS)
142 : : {
5421 bruce@momjian.us 143 : 10 : text *txt = PG_GETARG_TEXT_PP(0);
144 : : char *str;
145 : : Datum result;
146 : :
4694 tgl@sss.pgh.pa.us 147 [ - + - - : 10 : str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
- - - - -
+ - + ]
5421 bruce@momjian.us 148 : 10 : result = hash_any((unsigned char *) str, strlen(str));
149 : 10 : pfree(str);
150 : :
151 : : /* Avoid leaking memory for toasted inputs */
152 [ - + ]: 10 : PG_FREE_IF_COPY(txt, 0);
153 : :
154 : 10 : PG_RETURN_DATUM(result);
155 : : }
156 : :
1969 tgl@sss.pgh.pa.us 157 : 3 : PG_FUNCTION_INFO_V1(citext_hash_extended);
158 : :
159 : : Datum
160 : 10 : citext_hash_extended(PG_FUNCTION_ARGS)
161 : : {
162 : 10 : text *txt = PG_GETARG_TEXT_PP(0);
163 : 10 : uint64 seed = PG_GETARG_INT64(1);
164 : : char *str;
165 : : Datum result;
166 : :
167 [ - + - - : 10 : str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
- - - - -
+ - + ]
168 : 10 : result = hash_any_extended((unsigned char *) str, strlen(str), seed);
169 : 10 : pfree(str);
170 : :
171 : : /* Avoid leaking memory for toasted inputs */
172 [ - + ]: 10 : PG_FREE_IF_COPY(txt, 0);
173 : :
174 : 10 : PG_RETURN_DATUM(result);
175 : : }
176 : :
177 : : /*
178 : : * ==================
179 : : * OPERATOR FUNCTIONS
180 : : * ==================
181 : : */
182 : :
5738 183 : 5 : PG_FUNCTION_INFO_V1(citext_eq);
184 : :
185 : : Datum
186 : 90 : citext_eq(PG_FUNCTION_ARGS)
187 : : {
5421 bruce@momjian.us 188 : 90 : text *left = PG_GETARG_TEXT_PP(0);
189 : 90 : text *right = PG_GETARG_TEXT_PP(1);
190 : : char *lcstr,
191 : : *rcstr;
192 : : bool result;
193 : :
194 : : /* We can't compare lengths in advance of downcasing ... */
195 : :
4694 tgl@sss.pgh.pa.us 196 [ - + - - : 90 : lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
197 [ - + - - : 90 : rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
198 : :
199 : : /*
200 : : * Since we only care about equality or not-equality, we can avoid all the
201 : : * expense of strcoll() here, and just do bitwise comparison.
202 : : */
5421 bruce@momjian.us 203 : 90 : result = (strcmp(lcstr, rcstr) == 0);
204 : :
205 : 90 : pfree(lcstr);
206 : 90 : pfree(rcstr);
207 [ - + ]: 90 : PG_FREE_IF_COPY(left, 0);
208 [ - + ]: 90 : PG_FREE_IF_COPY(right, 1);
209 : :
210 : 90 : PG_RETURN_BOOL(result);
211 : : }
212 : :
5738 tgl@sss.pgh.pa.us 213 : 4 : PG_FUNCTION_INFO_V1(citext_ne);
214 : :
215 : : Datum
216 : 22 : citext_ne(PG_FUNCTION_ARGS)
217 : : {
5421 bruce@momjian.us 218 : 22 : text *left = PG_GETARG_TEXT_PP(0);
219 : 22 : text *right = PG_GETARG_TEXT_PP(1);
220 : : char *lcstr,
221 : : *rcstr;
222 : : bool result;
223 : :
224 : : /* We can't compare lengths in advance of downcasing ... */
225 : :
4694 tgl@sss.pgh.pa.us 226 [ - + - - : 22 : lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
- - - - +
+ + + ]
227 [ - + - - : 22 : rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
- - - - -
+ - + ]
228 : :
229 : : /*
230 : : * Since we only care about equality or not-equality, we can avoid all the
231 : : * expense of strcoll() here, and just do bitwise comparison.
232 : : */
5421 bruce@momjian.us 233 : 22 : result = (strcmp(lcstr, rcstr) != 0);
234 : :
235 : 22 : pfree(lcstr);
236 : 22 : pfree(rcstr);
237 [ - + ]: 22 : PG_FREE_IF_COPY(left, 0);
238 [ - + ]: 22 : PG_FREE_IF_COPY(right, 1);
239 : :
240 : 22 : PG_RETURN_BOOL(result);
241 : : }
242 : :
5738 tgl@sss.pgh.pa.us 243 : 3 : PG_FUNCTION_INFO_V1(citext_lt);
244 : :
245 : : Datum
246 : 1 : citext_lt(PG_FUNCTION_ARGS)
247 : : {
5421 bruce@momjian.us 248 : 1 : text *left = PG_GETARG_TEXT_PP(0);
249 : 1 : text *right = PG_GETARG_TEXT_PP(1);
250 : : bool result;
251 : :
4814 peter_e@gmx.net 252 : 1 : result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
253 : :
5421 bruce@momjian.us 254 [ - + ]: 1 : PG_FREE_IF_COPY(left, 0);
255 [ - + ]: 1 : PG_FREE_IF_COPY(right, 1);
256 : :
257 : 1 : PG_RETURN_BOOL(result);
258 : : }
259 : :
5738 tgl@sss.pgh.pa.us 260 : 3 : PG_FUNCTION_INFO_V1(citext_le);
261 : :
262 : : Datum
263 : 1 : citext_le(PG_FUNCTION_ARGS)
264 : : {
5421 bruce@momjian.us 265 : 1 : text *left = PG_GETARG_TEXT_PP(0);
266 : 1 : text *right = PG_GETARG_TEXT_PP(1);
267 : : bool result;
268 : :
4814 peter_e@gmx.net 269 : 1 : result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
270 : :
5421 bruce@momjian.us 271 [ - + ]: 1 : PG_FREE_IF_COPY(left, 0);
272 [ - + ]: 1 : PG_FREE_IF_COPY(right, 1);
273 : :
274 : 1 : PG_RETURN_BOOL(result);
275 : : }
276 : :
5738 tgl@sss.pgh.pa.us 277 : 3 : PG_FUNCTION_INFO_V1(citext_gt);
278 : :
279 : : Datum
280 : 3 : citext_gt(PG_FUNCTION_ARGS)
281 : : {
5421 bruce@momjian.us 282 : 3 : text *left = PG_GETARG_TEXT_PP(0);
283 : 3 : text *right = PG_GETARG_TEXT_PP(1);
284 : : bool result;
285 : :
4814 peter_e@gmx.net 286 : 3 : result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
287 : :
5421 bruce@momjian.us 288 [ - + ]: 3 : PG_FREE_IF_COPY(left, 0);
289 [ - + ]: 3 : PG_FREE_IF_COPY(right, 1);
290 : :
291 : 3 : PG_RETURN_BOOL(result);
292 : : }
293 : :
5738 tgl@sss.pgh.pa.us 294 : 3 : PG_FUNCTION_INFO_V1(citext_ge);
295 : :
296 : : Datum
297 : 1 : citext_ge(PG_FUNCTION_ARGS)
298 : : {
5421 bruce@momjian.us 299 : 1 : text *left = PG_GETARG_TEXT_PP(0);
300 : 1 : text *right = PG_GETARG_TEXT_PP(1);
301 : : bool result;
302 : :
4814 peter_e@gmx.net 303 : 1 : result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
304 : :
5421 bruce@momjian.us 305 [ - + ]: 1 : PG_FREE_IF_COPY(left, 0);
306 [ - + ]: 1 : PG_FREE_IF_COPY(right, 1);
307 : :
308 : 1 : PG_RETURN_BOOL(result);
309 : : }
310 : :
2399 andrew@dunslane.net 311 : 4 : PG_FUNCTION_INFO_V1(citext_pattern_lt);
312 : :
313 : : Datum
314 : 9 : citext_pattern_lt(PG_FUNCTION_ARGS)
315 : : {
316 : 9 : text *left = PG_GETARG_TEXT_PP(0);
317 : 9 : text *right = PG_GETARG_TEXT_PP(1);
318 : : bool result;
319 : :
320 : 9 : result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) < 0;
321 : :
322 [ - + ]: 9 : PG_FREE_IF_COPY(left, 0);
323 [ - + ]: 9 : PG_FREE_IF_COPY(right, 1);
324 : :
325 : 9 : PG_RETURN_BOOL(result);
326 : : }
327 : :
328 : 4 : PG_FUNCTION_INFO_V1(citext_pattern_le);
329 : :
330 : : Datum
331 : 13 : citext_pattern_le(PG_FUNCTION_ARGS)
332 : : {
333 : 13 : text *left = PG_GETARG_TEXT_PP(0);
334 : 13 : text *right = PG_GETARG_TEXT_PP(1);
335 : : bool result;
336 : :
337 : 13 : result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) <= 0;
338 : :
339 [ - + ]: 13 : PG_FREE_IF_COPY(left, 0);
340 [ - + ]: 13 : PG_FREE_IF_COPY(right, 1);
341 : :
342 : 13 : PG_RETURN_BOOL(result);
343 : : }
344 : :
345 : 4 : PG_FUNCTION_INFO_V1(citext_pattern_gt);
346 : :
347 : : Datum
348 : 10 : citext_pattern_gt(PG_FUNCTION_ARGS)
349 : : {
350 : 10 : text *left = PG_GETARG_TEXT_PP(0);
351 : 10 : text *right = PG_GETARG_TEXT_PP(1);
352 : : bool result;
353 : :
354 : 10 : result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) > 0;
355 : :
356 [ - + ]: 10 : PG_FREE_IF_COPY(left, 0);
357 [ - + ]: 10 : PG_FREE_IF_COPY(right, 1);
358 : :
359 : 10 : PG_RETURN_BOOL(result);
360 : : }
361 : :
362 : 4 : PG_FUNCTION_INFO_V1(citext_pattern_ge);
363 : :
364 : : Datum
365 : 12 : citext_pattern_ge(PG_FUNCTION_ARGS)
366 : : {
367 : 12 : text *left = PG_GETARG_TEXT_PP(0);
368 : 12 : text *right = PG_GETARG_TEXT_PP(1);
369 : : bool result;
370 : :
371 : 12 : result = internal_citext_pattern_cmp(left, right, PG_GET_COLLATION()) >= 0;
372 : :
373 [ - + ]: 12 : PG_FREE_IF_COPY(left, 0);
374 [ - + ]: 12 : PG_FREE_IF_COPY(right, 1);
375 : :
376 : 12 : PG_RETURN_BOOL(result);
377 : : }
378 : :
379 : : /*
380 : : * ===================
381 : : * AGGREGATE FUNCTIONS
382 : : * ===================
383 : : */
384 : :
5738 tgl@sss.pgh.pa.us 385 : 3 : PG_FUNCTION_INFO_V1(citext_smaller);
386 : :
387 : : Datum
388 : 7 : citext_smaller(PG_FUNCTION_ARGS)
389 : : {
5421 bruce@momjian.us 390 : 7 : text *left = PG_GETARG_TEXT_PP(0);
391 : 7 : text *right = PG_GETARG_TEXT_PP(1);
392 : : text *result;
393 : :
4814 peter_e@gmx.net 394 [ + + ]: 7 : result = citextcmp(left, right, PG_GET_COLLATION()) < 0 ? left : right;
5421 bruce@momjian.us 395 : 7 : PG_RETURN_TEXT_P(result);
396 : : }
397 : :
5738 tgl@sss.pgh.pa.us 398 : 3 : PG_FUNCTION_INFO_V1(citext_larger);
399 : :
400 : : Datum
401 : 6 : citext_larger(PG_FUNCTION_ARGS)
402 : : {
5421 bruce@momjian.us 403 : 6 : text *left = PG_GETARG_TEXT_PP(0);
404 : 6 : text *right = PG_GETARG_TEXT_PP(1);
405 : : text *result;
406 : :
4814 peter_e@gmx.net 407 [ + + ]: 6 : result = citextcmp(left, right, PG_GET_COLLATION()) > 0 ? left : right;
5421 bruce@momjian.us 408 : 6 : PG_RETURN_TEXT_P(result);
409 : : }
|