OSDN Git Service

Add composite-type attributes to information_schema.element_types view
[pg-rex/syncrep.git] / contrib / citext / citext.c
1 /*
2  * contrib/citext/citext.c
3  */
4 #include "postgres.h"
5
6 #include "access/hash.h"
7 #include "catalog/pg_collation.h"
8 #include "fmgr.h"
9 #include "utils/builtins.h"
10 #include "utils/formatting.h"
11
12 #ifdef PG_MODULE_MAGIC
13 PG_MODULE_MAGIC;
14 #endif
15
16 /*
17  *              ====================
18  *              FORWARD DECLARATIONS
19  *              ====================
20  */
21
22 static int32 citextcmp(text *left, text *right, Oid collid);
23 extern Datum citext_cmp(PG_FUNCTION_ARGS);
24 extern Datum citext_hash(PG_FUNCTION_ARGS);
25 extern Datum citext_eq(PG_FUNCTION_ARGS);
26 extern Datum citext_ne(PG_FUNCTION_ARGS);
27 extern Datum citext_gt(PG_FUNCTION_ARGS);
28 extern Datum citext_ge(PG_FUNCTION_ARGS);
29 extern Datum citext_lt(PG_FUNCTION_ARGS);
30 extern Datum citext_le(PG_FUNCTION_ARGS);
31 extern Datum citext_smaller(PG_FUNCTION_ARGS);
32 extern Datum citext_larger(PG_FUNCTION_ARGS);
33
34 /*
35  *              =================
36  *              UTILITY FUNCTIONS
37  *              =================
38  */
39
40 /*
41  * citextcmp()
42  * Internal comparison function for citext strings.
43  * Returns int32 negative, zero, or positive.
44  */
45 static int32
46 citextcmp(text *left, text *right, Oid collid)
47 {
48         char       *lcstr,
49                            *rcstr;
50         int32           result;
51
52         /*
53          * We must do our str_tolower calls with DEFAULT_COLLATION_OID, not the
54          * input collation as you might expect.  This is so that the behavior of
55          * citext's equality and hashing functions is not collation-dependent.  We
56          * should change this once the core infrastructure is able to cope with
57          * collation-dependent equality and hashing functions.
58          */
59
60         lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
61         rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
62
63         result = varstr_cmp(lcstr, strlen(lcstr),
64                                                 rcstr, strlen(rcstr),
65                                                 collid);
66
67         pfree(lcstr);
68         pfree(rcstr);
69
70         return result;
71 }
72
73 /*
74  *              ==================
75  *              INDEXING FUNCTIONS
76  *              ==================
77  */
78
79 PG_FUNCTION_INFO_V1(citext_cmp);
80
81 Datum
82 citext_cmp(PG_FUNCTION_ARGS)
83 {
84         text       *left = PG_GETARG_TEXT_PP(0);
85         text       *right = PG_GETARG_TEXT_PP(1);
86         int32           result;
87
88         result = citextcmp(left, right, PG_GET_COLLATION());
89
90         PG_FREE_IF_COPY(left, 0);
91         PG_FREE_IF_COPY(right, 1);
92
93         PG_RETURN_INT32(result);
94 }
95
96 PG_FUNCTION_INFO_V1(citext_hash);
97
98 Datum
99 citext_hash(PG_FUNCTION_ARGS)
100 {
101         text       *txt = PG_GETARG_TEXT_PP(0);
102         char       *str;
103         Datum           result;
104
105         str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID);
106         result = hash_any((unsigned char *) str, strlen(str));
107         pfree(str);
108
109         /* Avoid leaking memory for toasted inputs */
110         PG_FREE_IF_COPY(txt, 0);
111
112         PG_RETURN_DATUM(result);
113 }
114
115 /*
116  *              ==================
117  *              OPERATOR FUNCTIONS
118  *              ==================
119  */
120
121 PG_FUNCTION_INFO_V1(citext_eq);
122
123 Datum
124 citext_eq(PG_FUNCTION_ARGS)
125 {
126         text       *left = PG_GETARG_TEXT_PP(0);
127         text       *right = PG_GETARG_TEXT_PP(1);
128         char       *lcstr,
129                            *rcstr;
130         bool            result;
131
132         /* We can't compare lengths in advance of downcasing ... */
133
134         lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
135         rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
136
137         /*
138          * Since we only care about equality or not-equality, we can avoid all the
139          * expense of strcoll() here, and just do bitwise comparison.
140          */
141         result = (strcmp(lcstr, rcstr) == 0);
142
143         pfree(lcstr);
144         pfree(rcstr);
145         PG_FREE_IF_COPY(left, 0);
146         PG_FREE_IF_COPY(right, 1);
147
148         PG_RETURN_BOOL(result);
149 }
150
151 PG_FUNCTION_INFO_V1(citext_ne);
152
153 Datum
154 citext_ne(PG_FUNCTION_ARGS)
155 {
156         text       *left = PG_GETARG_TEXT_PP(0);
157         text       *right = PG_GETARG_TEXT_PP(1);
158         char       *lcstr,
159                            *rcstr;
160         bool            result;
161
162         /* We can't compare lengths in advance of downcasing ... */
163
164         lcstr = str_tolower(VARDATA_ANY(left), VARSIZE_ANY_EXHDR(left), DEFAULT_COLLATION_OID);
165         rcstr = str_tolower(VARDATA_ANY(right), VARSIZE_ANY_EXHDR(right), DEFAULT_COLLATION_OID);
166
167         /*
168          * Since we only care about equality or not-equality, we can avoid all the
169          * expense of strcoll() here, and just do bitwise comparison.
170          */
171         result = (strcmp(lcstr, rcstr) != 0);
172
173         pfree(lcstr);
174         pfree(rcstr);
175         PG_FREE_IF_COPY(left, 0);
176         PG_FREE_IF_COPY(right, 1);
177
178         PG_RETURN_BOOL(result);
179 }
180
181 PG_FUNCTION_INFO_V1(citext_lt);
182
183 Datum
184 citext_lt(PG_FUNCTION_ARGS)
185 {
186         text       *left = PG_GETARG_TEXT_PP(0);
187         text       *right = PG_GETARG_TEXT_PP(1);
188         bool            result;
189
190         result = citextcmp(left, right, PG_GET_COLLATION()) < 0;
191
192         PG_FREE_IF_COPY(left, 0);
193         PG_FREE_IF_COPY(right, 1);
194
195         PG_RETURN_BOOL(result);
196 }
197
198 PG_FUNCTION_INFO_V1(citext_le);
199
200 Datum
201 citext_le(PG_FUNCTION_ARGS)
202 {
203         text       *left = PG_GETARG_TEXT_PP(0);
204         text       *right = PG_GETARG_TEXT_PP(1);
205         bool            result;
206
207         result = citextcmp(left, right, PG_GET_COLLATION()) <= 0;
208
209         PG_FREE_IF_COPY(left, 0);
210         PG_FREE_IF_COPY(right, 1);
211
212         PG_RETURN_BOOL(result);
213 }
214
215 PG_FUNCTION_INFO_V1(citext_gt);
216
217 Datum
218 citext_gt(PG_FUNCTION_ARGS)
219 {
220         text       *left = PG_GETARG_TEXT_PP(0);
221         text       *right = PG_GETARG_TEXT_PP(1);
222         bool            result;
223
224         result = citextcmp(left, right, PG_GET_COLLATION()) > 0;
225
226         PG_FREE_IF_COPY(left, 0);
227         PG_FREE_IF_COPY(right, 1);
228
229         PG_RETURN_BOOL(result);
230 }
231
232 PG_FUNCTION_INFO_V1(citext_ge);
233
234 Datum
235 citext_ge(PG_FUNCTION_ARGS)
236 {
237         text       *left = PG_GETARG_TEXT_PP(0);
238         text       *right = PG_GETARG_TEXT_PP(1);
239         bool            result;
240
241         result = citextcmp(left, right, PG_GET_COLLATION()) >= 0;
242
243         PG_FREE_IF_COPY(left, 0);
244         PG_FREE_IF_COPY(right, 1);
245
246         PG_RETURN_BOOL(result);
247 }
248
249 /*
250  *              ===================
251  *              AGGREGATE FUNCTIONS
252  *              ===================
253  */
254
255 PG_FUNCTION_INFO_V1(citext_smaller);
256
257 Datum
258 citext_smaller(PG_FUNCTION_ARGS)
259 {
260         text       *left = PG_GETARG_TEXT_PP(0);
261         text       *right = PG_GETARG_TEXT_PP(1);
262         text       *result;
263
264         result = citextcmp(left, right, PG_GET_COLLATION()) < 0 ? left : right;
265         PG_RETURN_TEXT_P(result);
266 }
267
268 PG_FUNCTION_INFO_V1(citext_larger);
269
270 Datum
271 citext_larger(PG_FUNCTION_ARGS)
272 {
273         text       *left = PG_GETARG_TEXT_PP(0);
274         text       *right = PG_GETARG_TEXT_PP(1);
275         text       *result;
276
277         result = citextcmp(left, right, PG_GET_COLLATION()) > 0 ? left : right;
278         PG_RETURN_TEXT_P(result);
279 }