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
);
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
)
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
));
69 PG_FUNCTION_INFO_V1(citext_cmp
);
72 citext_cmp(PG_FUNCTION_ARGS
)
74 text
*left
= PG_GETARG_TEXT_PP(0);
75 text
*right
= PG_GETARG_TEXT_PP(1);
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
);
89 citext_hash(PG_FUNCTION_ARGS
)
91 text
*txt
= PG_GETARG_TEXT_PP(0);
95 str
= str_tolower(VARDATA_ANY(txt
), VARSIZE_ANY_EXHDR(txt
));
96 result
= hash_any((unsigned char *) str
, strlen(str
));
99 /* Avoid leaking memory for toasted inputs */
100 PG_FREE_IF_COPY(txt
, 0);
102 PG_RETURN_DATUM(result
);
111 PG_FUNCTION_INFO_V1(citext_eq
);
114 citext_eq(PG_FUNCTION_ARGS
)
116 text
*left
= PG_GETARG_TEXT_PP(0);
117 text
*right
= PG_GETARG_TEXT_PP(1);
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);
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
);
144 citext_ne(PG_FUNCTION_ARGS
)
146 text
*left
= PG_GETARG_TEXT_PP(0);
147 text
*right
= PG_GETARG_TEXT_PP(1);
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);
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
);
174 citext_lt(PG_FUNCTION_ARGS
)
176 text
*left
= PG_GETARG_TEXT_PP(0);
177 text
*right
= PG_GETARG_TEXT_PP(1);
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
);
191 citext_le(PG_FUNCTION_ARGS
)
193 text
*left
= PG_GETARG_TEXT_PP(0);
194 text
*right
= PG_GETARG_TEXT_PP(1);
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
);
208 citext_gt(PG_FUNCTION_ARGS
)
210 text
*left
= PG_GETARG_TEXT_PP(0);
211 text
*right
= PG_GETARG_TEXT_PP(1);
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
);
225 citext_ge(PG_FUNCTION_ARGS
)
227 text
*left
= PG_GETARG_TEXT_PP(0);
228 text
*right
= PG_GETARG_TEXT_PP(1);
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
);
248 citext_smaller(PG_FUNCTION_ARGS
)
250 text
*left
= PG_GETARG_TEXT_PP(0);
251 text
*right
= PG_GETARG_TEXT_PP(1);
254 result
= citextcmp(left
, right
) < 0 ? left
: right
;
255 PG_RETURN_TEXT_P(result
);
258 PG_FUNCTION_INFO_V1(citext_larger
);
261 citext_larger(PG_FUNCTION_ARGS
)
263 text
*left
= PG_GETARG_TEXT_PP(0);
264 text
*right
= PG_GETARG_TEXT_PP(1);
267 result
= citextcmp(left
, right
) > 0 ? left
: right
;
268 PG_RETURN_TEXT_P(result
);