2
* contrib/citext/citext.c
6
#include "access/hash.h"
8
#include "utils/builtins.h"
9
#include "utils/formatting.h"
11
#ifdef PG_MODULE_MAGIC
16
* ====================
17
* FORWARD DECLARATIONS
18
* ====================
21
static int32 citextcmp(text *left, text *right, Oid collid);
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);
41
* Internal comparison function for citext strings.
42
* Returns int32 negative, zero, or positive.
45
citextcmp(text *left, text *right, Oid collid)
51
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), collid);
52
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), collid);
54
result = varstr_cmp(lcstr, strlen(lcstr),
70
PG_FUNCTION_INFO_V1(citext_cmp);
73
citext_cmp(PG_FUNCTION_ARGS)
75
text *left = PG_GETARG_TEXT_PP(0);
76
text *right = PG_GETARG_TEXT_PP(1);
79
result = citextcmp(left, right, PG_GET_COLLATION());
81
PG_FREE_IF_COPY(left, 0);
82
PG_FREE_IF_COPY(right, 1);
84
PG_RETURN_INT32(result);
87
PG_FUNCTION_INFO_V1(citext_hash);
90
citext_hash(PG_FUNCTION_ARGS)
92
text *txt = PG_GETARG_TEXT_PP(0);
96
str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), PG_GET_COLLATION());
97
result = hash_any((unsigned char *) str, strlen(str));
100
/* Avoid leaking memory for toasted inputs */
101
PG_FREE_IF_COPY(txt, 0);
103
PG_RETURN_DATUM(result);
112
PG_FUNCTION_INFO_V1(citext_eq);
115
citext_eq(PG_FUNCTION_ARGS)
117
text *left = PG_GETARG_TEXT_PP(0);
118
text *right = PG_GETARG_TEXT_PP(1);
123
/* We can't compare lengths in advance of downcasing ... */
125
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), PG_GET_COLLATION());
126
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), PG_GET_COLLATION());
129
* Since we only care about equality or not-equality, we can avoid all the
130
* expense of strcoll() here, and just do bitwise comparison.
132
result = (strcmp(lcstr, rcstr) == 0);
136
PG_FREE_IF_COPY(left, 0);
137
PG_FREE_IF_COPY(right, 1);
139
PG_RETURN_BOOL(result);
142
PG_FUNCTION_INFO_V1(citext_ne);
145
citext_ne(PG_FUNCTION_ARGS)
147
text *left = PG_GETARG_TEXT_PP(0);
148
text *right = PG_GETARG_TEXT_PP(1);
153
/* We can't compare lengths in advance of downcasing ... */
155
lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), PG_GET_COLLATION());
156
rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), PG_GET_COLLATION());
159
* Since we only care about equality or not-equality, we can avoid all the
160
* expense of strcoll() here, and just do bitwise comparison.
162
result = (strcmp(lcstr, rcstr) != 0);
166
PG_FREE_IF_COPY(left, 0);
167
PG_FREE_IF_COPY(right, 1);
169
PG_RETURN_BOOL(result);
172
PG_FUNCTION_INFO_V1(citext_lt);
175
citext_lt(PG_FUNCTION_ARGS)
177
text *left = PG_GETARG_TEXT_PP(0);
178
text *right = PG_GETARG_TEXT_PP(1);
181
result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
183
PG_FREE_IF_COPY(left, 0);
184
PG_FREE_IF_COPY(right, 1);
186
PG_RETURN_BOOL(result);
189
PG_FUNCTION_INFO_V1(citext_le);
192
citext_le(PG_FUNCTION_ARGS)
194
text *left = PG_GETARG_TEXT_PP(0);
195
text *right = PG_GETARG_TEXT_PP(1);
198
result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
200
PG_FREE_IF_COPY(left, 0);
201
PG_FREE_IF_COPY(right, 1);
203
PG_RETURN_BOOL(result);
206
PG_FUNCTION_INFO_V1(citext_gt);
209
citext_gt(PG_FUNCTION_ARGS)
211
text *left = PG_GETARG_TEXT_PP(0);
212
text *right = PG_GETARG_TEXT_PP(1);
215
result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
217
PG_FREE_IF_COPY(left, 0);
218
PG_FREE_IF_COPY(right, 1);
220
PG_RETURN_BOOL(result);
223
PG_FUNCTION_INFO_V1(citext_ge);
226
citext_ge(PG_FUNCTION_ARGS)
228
text *left = PG_GETARG_TEXT_PP(0);
229
text *right = PG_GETARG_TEXT_PP(1);
232
result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
234
PG_FREE_IF_COPY(left, 0);
235
PG_FREE_IF_COPY(right, 1);
237
PG_RETURN_BOOL(result);
241
* ===================
242
* AGGREGATE FUNCTIONS
243
* ===================
246
PG_FUNCTION_INFO_V1(citext_smaller);
249
citext_smaller(PG_FUNCTION_ARGS)
251
text *left = PG_GETARG_TEXT_PP(0);
252
text *right = PG_GETARG_TEXT_PP(1);
255
result = citextcmp(left, right, PG_GET_COLLATION()) < 0 ? left : right;
256
PG_RETURN_TEXT_P(result);
259
PG_FUNCTION_INFO_V1(citext_larger);
262
citext_larger(PG_FUNCTION_ARGS)
264
text *left = PG_GETARG_TEXT_PP(0);
265
text *right = PG_GETARG_TEXT_PP(1);
268
result = citextcmp(left, right, PG_GET_COLLATION()) > 0 ? left : right;
269
PG_RETURN_TEXT_P(result);