Branch data Line data Source code
1 : : /*
2 : : * contrib/btree_gist/btree_text.c
3 : : *
4 : : * Support for text and bpchar types.
5 : : */
6 : : #include "postgres.h"
7 : :
8 : : #include "btree_gist.h"
9 : : #include "btree_utils_var.h"
10 : : #include "mb/pg_wchar.h"
11 : : #include "utils/fmgrprotos.h"
12 : : #include "utils/sortsupport.h"
13 : :
14 : : /* GiST support functions */
15 : 6 : PG_FUNCTION_INFO_V1(gbt_text_compress);
16 : 4 : PG_FUNCTION_INFO_V1(gbt_bpchar_compress);
17 : 7 : PG_FUNCTION_INFO_V1(gbt_text_union);
18 : 7 : PG_FUNCTION_INFO_V1(gbt_text_picksplit);
19 : 6 : PG_FUNCTION_INFO_V1(gbt_text_consistent);
20 : 4 : PG_FUNCTION_INFO_V1(gbt_bpchar_consistent);
21 : 7 : PG_FUNCTION_INFO_V1(gbt_text_penalty);
22 : 7 : PG_FUNCTION_INFO_V1(gbt_text_same);
23 : 6 : PG_FUNCTION_INFO_V1(gbt_text_sortsupport);
24 : 4 : PG_FUNCTION_INFO_V1(gbt_bpchar_sortsupport);
25 : :
26 : :
27 : : /* define for comparison */
28 : :
29 : : static bool
30 : 989 : gbt_textgt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
31 : : {
32 : 989 : return DatumGetBool(DirectFunctionCall2Coll(text_gt,
33 : : collation,
34 : : PointerGetDatum(a),
35 : : PointerGetDatum(b)));
36 : : }
37 : :
38 : : static bool
39 : 1112 : gbt_textge(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
40 : : {
41 : 1112 : return DatumGetBool(DirectFunctionCall2Coll(text_ge,
42 : : collation,
43 : : PointerGetDatum(a),
44 : : PointerGetDatum(b)));
45 : : }
46 : :
47 : : static bool
48 : 376 : gbt_texteq(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
49 : : {
50 : 376 : return DatumGetBool(DirectFunctionCall2Coll(texteq,
51 : : collation,
52 : : PointerGetDatum(a),
53 : : PointerGetDatum(b)));
54 : : }
55 : :
56 : : static bool
57 : 1263 : gbt_textle(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
58 : : {
59 : 1263 : return DatumGetBool(DirectFunctionCall2Coll(text_le,
60 : : collation,
61 : : PointerGetDatum(a),
62 : : PointerGetDatum(b)));
63 : : }
64 : :
65 : : static bool
66 : 1234 : gbt_textlt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
67 : : {
68 : 1234 : return DatumGetBool(DirectFunctionCall2Coll(text_lt,
69 : : collation,
70 : : PointerGetDatum(a),
71 : : PointerGetDatum(b)));
72 : : }
73 : :
74 : : static int32
75 : 28465 : gbt_textcmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
76 : : {
77 : 28465 : return DatumGetInt32(DirectFunctionCall2Coll(bttextcmp,
78 : : collation,
79 : : PointerGetDatum(a),
80 : : PointerGetDatum(b)));
81 : : }
82 : :
83 : : /*
84 : : * Originally this module permitted truncation of internal keys, but that
85 : : * tends to result in wrong comparison answers if the collation is any
86 : : * more complicated than C. The prefix-match hack used for simpler types
87 : : * can't fix it, either.
88 : : */
89 : : static const gbtree_vinfo tinfo =
90 : : {
91 : : gbt_t_text,
92 : : false, /* no truncation permitted */
93 : : gbt_textgt,
94 : : gbt_textge,
95 : : gbt_texteq,
96 : : gbt_textle,
97 : : gbt_textlt,
98 : : gbt_textcmp,
99 : : NULL
100 : : };
101 : :
102 : : /* bpchar needs its own comparison rules */
103 : :
104 : : static bool
105 : 520 : gbt_bpchargt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
106 : : {
107 : 520 : return DatumGetBool(DirectFunctionCall2Coll(bpchargt,
108 : : collation,
109 : : PointerGetDatum(a),
110 : : PointerGetDatum(b)));
111 : : }
112 : :
113 : : static bool
114 : 676 : gbt_bpcharge(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
115 : : {
116 : 676 : return DatumGetBool(DirectFunctionCall2Coll(bpcharge,
117 : : collation,
118 : : PointerGetDatum(a),
119 : : PointerGetDatum(b)));
120 : : }
121 : :
122 : : static bool
123 : 156 : gbt_bpchareq(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
124 : : {
125 : 156 : return DatumGetBool(DirectFunctionCall2Coll(bpchareq,
126 : : collation,
127 : : PointerGetDatum(a),
128 : : PointerGetDatum(b)));
129 : : }
130 : :
131 : : static bool
132 : 661 : gbt_bpcharle(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
133 : : {
134 : 661 : return DatumGetBool(DirectFunctionCall2Coll(bpcharle,
135 : : collation,
136 : : PointerGetDatum(a),
137 : : PointerGetDatum(b)));
138 : : }
139 : :
140 : : static bool
141 : 624 : gbt_bpcharlt(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
142 : : {
143 : 624 : return DatumGetBool(DirectFunctionCall2Coll(bpcharlt,
144 : : collation,
145 : : PointerGetDatum(a),
146 : : PointerGetDatum(b)));
147 : : }
148 : :
149 : : static int32
150 : 57 : gbt_bpcharcmp(const void *a, const void *b, Oid collation, FmgrInfo *flinfo)
151 : : {
152 : 57 : return DatumGetInt32(DirectFunctionCall2Coll(bpcharcmp,
153 : : collation,
154 : : PointerGetDatum(a),
155 : : PointerGetDatum(b)));
156 : : }
157 : :
158 : : static const gbtree_vinfo bptinfo =
159 : : {
160 : : gbt_t_bpchar,
161 : : false, /* as above, no truncation permitted */
162 : : gbt_bpchargt,
163 : : gbt_bpcharge,
164 : : gbt_bpchareq,
165 : : gbt_bpcharle,
166 : : gbt_bpcharlt,
167 : : gbt_bpcharcmp,
168 : : NULL
169 : : };
170 : :
171 : :
172 : : /**************************************************
173 : : * GiST support functions
174 : : **************************************************/
175 : :
176 : : Datum
177 : 2989 : gbt_text_compress(PG_FUNCTION_ARGS)
178 : : {
179 : 2989 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
180 : :
181 : 2989 : PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
182 : : }
183 : :
184 : : Datum
185 : 996 : gbt_bpchar_compress(PG_FUNCTION_ARGS)
186 : : {
187 : : /* This should never have been distinct from gbt_text_compress */
188 : 996 : return gbt_text_compress(fcinfo);
189 : : }
190 : :
191 : : Datum
192 : 5050 : gbt_text_consistent(PG_FUNCTION_ARGS)
193 : : {
194 : 5050 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
195 : 5050 : void *query = DatumGetTextP(PG_GETARG_DATUM(1));
196 : 5050 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
197 : : #ifdef NOT_USED
198 : : Oid subtype = PG_GETARG_OID(3);
199 : : #endif
200 : 5050 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
201 : : bool retval;
202 : 5050 : GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
203 : 5050 : GBT_VARKEY_R r = gbt_var_key_readable(key);
204 : :
205 : : /* All cases served by this function are exact */
206 : 5050 : *recheck = false;
207 : :
208 : 10100 : retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
209 : 5050 : GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
210 : :
211 : 5050 : PG_RETURN_BOOL(retval);
212 : : }
213 : :
214 : : Datum
215 : 2690 : gbt_bpchar_consistent(PG_FUNCTION_ARGS)
216 : : {
217 : 2690 : GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
218 : 2690 : void *query = DatumGetTextP(PG_GETARG_DATUM(1));
219 : 2690 : StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
220 : : #ifdef NOT_USED
221 : : Oid subtype = PG_GETARG_OID(3);
222 : : #endif
223 : 2690 : bool *recheck = (bool *) PG_GETARG_POINTER(4);
224 : : bool retval;
225 : 2690 : GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
226 : 2690 : GBT_VARKEY_R r = gbt_var_key_readable(key);
227 : :
228 : : /* All cases served by this function are exact */
229 : 2690 : *recheck = false;
230 : :
231 : 5380 : retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
232 : 2690 : GIST_LEAF(entry), &bptinfo, fcinfo->flinfo);
233 : 2690 : PG_RETURN_BOOL(retval);
234 : : }
235 : :
236 : : Datum
237 : 3 : gbt_text_union(PG_FUNCTION_ARGS)
238 : : {
239 : 3 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
240 : 3 : int32 *size = (int *) PG_GETARG_POINTER(1);
241 : :
242 : 3 : PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
243 : : &tinfo, fcinfo->flinfo));
244 : : }
245 : :
246 : : Datum
247 : 16 : gbt_text_picksplit(PG_FUNCTION_ARGS)
248 : : {
249 : 16 : GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
250 : 16 : GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
251 : :
252 : 16 : gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
253 : : &tinfo, fcinfo->flinfo);
254 : 16 : PG_RETURN_POINTER(v);
255 : : }
256 : :
257 : : Datum
258 : 0 : gbt_text_same(PG_FUNCTION_ARGS)
259 : : {
260 : 0 : Datum d1 = PG_GETARG_DATUM(0);
261 : 0 : Datum d2 = PG_GETARG_DATUM(1);
262 : 0 : bool *result = (bool *) PG_GETARG_POINTER(2);
263 : :
264 : 0 : *result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
265 : 0 : PG_RETURN_POINTER(result);
266 : : }
267 : :
268 : : Datum
269 : 0 : gbt_text_penalty(PG_FUNCTION_ARGS)
270 : : {
271 : 0 : GISTENTRY *o = (GISTENTRY *) PG_GETARG_POINTER(0);
272 : 0 : GISTENTRY *n = (GISTENTRY *) PG_GETARG_POINTER(1);
273 : 0 : float *result = (float *) PG_GETARG_POINTER(2);
274 : :
275 : 0 : PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
276 : : &tinfo, fcinfo->flinfo));
277 : : }
278 : :
279 : : static int
280 : 22034 : gbt_text_ssup_cmp(Datum x, Datum y, SortSupport ssup)
281 : : {
282 : 22034 : GBT_VARKEY *key1 = PG_DETOAST_DATUM(x);
283 : 22034 : GBT_VARKEY *key2 = PG_DETOAST_DATUM(y);
284 : :
285 : 22034 : GBT_VARKEY_R arg1 = gbt_var_key_readable(key1);
286 : 22034 : GBT_VARKEY_R arg2 = gbt_var_key_readable(key2);
287 : : Datum result;
288 : :
289 : : /* for leaf items we expect lower == upper, so only compare lower */
290 : 22034 : result = DirectFunctionCall2Coll(bttextcmp,
291 : : ssup->ssup_collation,
292 : 22034 : PointerGetDatum(arg1.lower),
293 : 22034 : PointerGetDatum(arg2.lower));
294 : :
295 [ + - ]: 22034 : GBT_FREE_IF_COPY(key1, x);
296 [ + - ]: 22034 : GBT_FREE_IF_COPY(key2, y);
297 : :
298 : 22034 : return DatumGetInt32(result);
299 : : }
300 : :
301 : : Datum
302 : 3 : gbt_text_sortsupport(PG_FUNCTION_ARGS)
303 : : {
304 : 3 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
305 : :
306 : 3 : ssup->comparator = gbt_text_ssup_cmp;
307 : 3 : ssup->ssup_extra = NULL;
308 : :
309 : 3 : PG_RETURN_VOID();
310 : : }
311 : :
312 : : static int
313 : 11261 : gbt_bpchar_ssup_cmp(Datum x, Datum y, SortSupport ssup)
314 : : {
315 : 11261 : GBT_VARKEY *key1 = PG_DETOAST_DATUM(x);
316 : 11261 : GBT_VARKEY *key2 = PG_DETOAST_DATUM(y);
317 : :
318 : 11261 : GBT_VARKEY_R arg1 = gbt_var_key_readable(key1);
319 : 11261 : GBT_VARKEY_R arg2 = gbt_var_key_readable(key2);
320 : : Datum result;
321 : :
322 : : /* for leaf items we expect lower == upper, so only compare lower */
323 : 11261 : result = DirectFunctionCall2Coll(bpcharcmp,
324 : : ssup->ssup_collation,
325 : 11261 : PointerGetDatum(arg1.lower),
326 : 11261 : PointerGetDatum(arg2.lower));
327 : :
328 [ + - ]: 11261 : GBT_FREE_IF_COPY(key1, x);
329 [ + - ]: 11261 : GBT_FREE_IF_COPY(key2, y);
330 : :
331 : 11261 : return DatumGetInt32(result);
332 : : }
333 : :
334 : : Datum
335 : 1 : gbt_bpchar_sortsupport(PG_FUNCTION_ARGS)
336 : : {
337 : 1 : SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
338 : :
339 : 1 : ssup->comparator = gbt_bpchar_ssup_cmp;
340 : 1 : ssup->ssup_extra = NULL;
341 : :
342 : 1 : PG_RETURN_VOID();
343 : : }
|