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