1 /*
2  * contrib/btree_gist/btree_text.c
3  */
4 #include "postgres.h"
5 
6 #include "btree_gist.h"
7 #include "btree_utils_var.h"
8 #include "utils/builtins.h"
9 
10 /*
11 ** Text ops
12 */
13 PG_FUNCTION_INFO_V1(gbt_text_compress);
14 PG_FUNCTION_INFO_V1(gbt_bpchar_compress);
15 PG_FUNCTION_INFO_V1(gbt_text_union);
16 PG_FUNCTION_INFO_V1(gbt_text_picksplit);
17 PG_FUNCTION_INFO_V1(gbt_text_consistent);
18 PG_FUNCTION_INFO_V1(gbt_bpchar_consistent);
19 PG_FUNCTION_INFO_V1(gbt_text_penalty);
20 PG_FUNCTION_INFO_V1(gbt_text_same);
21 
22 
23 /* define for comparison */
24 
25 static bool
gbt_textgt(const void * a,const void * b,Oid collation)26 gbt_textgt(const void *a, const void *b, Oid collation)
27 {
28 	return DatumGetBool(DirectFunctionCall2Coll(text_gt,
29 												collation,
30 												PointerGetDatum(a),
31 												PointerGetDatum(b)));
32 }
33 
34 static bool
gbt_textge(const void * a,const void * b,Oid collation)35 gbt_textge(const void *a, const void *b, Oid collation)
36 {
37 	return DatumGetBool(DirectFunctionCall2Coll(text_ge,
38 												collation,
39 												PointerGetDatum(a),
40 												PointerGetDatum(b)));
41 }
42 
43 static bool
gbt_texteq(const void * a,const void * b,Oid collation)44 gbt_texteq(const void *a, const void *b, Oid collation)
45 {
46 	return DatumGetBool(DirectFunctionCall2Coll(texteq,
47 												collation,
48 												PointerGetDatum(a),
49 												PointerGetDatum(b)));
50 }
51 
52 static bool
gbt_textle(const void * a,const void * b,Oid collation)53 gbt_textle(const void *a, const void *b, Oid collation)
54 {
55 	return DatumGetBool(DirectFunctionCall2Coll(text_le,
56 												collation,
57 												PointerGetDatum(a),
58 												PointerGetDatum(b)));
59 }
60 
61 static bool
gbt_textlt(const void * a,const void * b,Oid collation)62 gbt_textlt(const void *a, const void *b, Oid collation)
63 {
64 	return DatumGetBool(DirectFunctionCall2Coll(text_lt,
65 												collation,
66 												PointerGetDatum(a),
67 												PointerGetDatum(b)));
68 }
69 
70 static int32
gbt_textcmp(const void * a,const void * b,Oid collation)71 gbt_textcmp(const void *a, const void *b, Oid collation)
72 {
73 	return DatumGetInt32(DirectFunctionCall2Coll(bttextcmp,
74 												 collation,
75 												 PointerGetDatum(a),
76 												 PointerGetDatum(b)));
77 }
78 
79 static gbtree_vinfo tinfo =
80 {
81 	gbt_t_text,
82 	0,
83 	FALSE,
84 	gbt_textgt,
85 	gbt_textge,
86 	gbt_texteq,
87 	gbt_textle,
88 	gbt_textlt,
89 	gbt_textcmp,
90 	NULL
91 };
92 
93 
94 /**************************************************
95  * Text ops
96  **************************************************/
97 
98 
99 Datum
gbt_text_compress(PG_FUNCTION_ARGS)100 gbt_text_compress(PG_FUNCTION_ARGS)
101 {
102 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
103 
104 	if (tinfo.eml == 0)
105 	{
106 		tinfo.eml = pg_database_encoding_max_length();
107 	}
108 
109 	PG_RETURN_POINTER(gbt_var_compress(entry, &tinfo));
110 }
111 
112 Datum
gbt_bpchar_compress(PG_FUNCTION_ARGS)113 gbt_bpchar_compress(PG_FUNCTION_ARGS)
114 {
115 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
116 	GISTENTRY  *retval;
117 
118 	if (tinfo.eml == 0)
119 	{
120 		tinfo.eml = pg_database_encoding_max_length();
121 	}
122 
123 	if (entry->leafkey)
124 	{
125 
126 		Datum		d = DirectFunctionCall1(rtrim1, entry->key);
127 		GISTENTRY	trim;
128 
129 		gistentryinit(trim, d,
130 					  entry->rel, entry->page,
131 					  entry->offset, TRUE);
132 		retval = gbt_var_compress(&trim, &tinfo);
133 	}
134 	else
135 		retval = entry;
136 
137 	PG_RETURN_POINTER(retval);
138 }
139 
140 
141 
142 Datum
gbt_text_consistent(PG_FUNCTION_ARGS)143 gbt_text_consistent(PG_FUNCTION_ARGS)
144 {
145 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
146 	void	   *query = (void *) DatumGetTextP(PG_GETARG_DATUM(1));
147 	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
148 
149 	/* Oid		subtype = PG_GETARG_OID(3); */
150 	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
151 	bool		retval;
152 	GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
153 	GBT_VARKEY_R r = gbt_var_key_readable(key);
154 
155 	/* All cases served by this function are exact */
156 	*recheck = false;
157 
158 	if (tinfo.eml == 0)
159 	{
160 		tinfo.eml = pg_database_encoding_max_length();
161 	}
162 
163 	retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
164 								GIST_LEAF(entry), &tinfo);
165 
166 	PG_RETURN_BOOL(retval);
167 }
168 
169 
170 Datum
gbt_bpchar_consistent(PG_FUNCTION_ARGS)171 gbt_bpchar_consistent(PG_FUNCTION_ARGS)
172 {
173 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
174 	void	   *query = (void *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
175 	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
176 
177 	/* Oid		subtype = PG_GETARG_OID(3); */
178 	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
179 	bool		retval;
180 	GBT_VARKEY *key = (GBT_VARKEY *) DatumGetPointer(entry->key);
181 	GBT_VARKEY_R r = gbt_var_key_readable(key);
182 	void	   *trim = (void *) DatumGetPointer(DirectFunctionCall1(rtrim1, PointerGetDatum(query)));
183 
184 	/* All cases served by this function are exact */
185 	*recheck = false;
186 
187 	if (tinfo.eml == 0)
188 	{
189 		tinfo.eml = pg_database_encoding_max_length();
190 	}
191 
192 	retval = gbt_var_consistent(&r, trim, strategy, PG_GET_COLLATION(),
193 								GIST_LEAF(entry), &tinfo);
194 	PG_RETURN_BOOL(retval);
195 }
196 
197 
198 Datum
gbt_text_union(PG_FUNCTION_ARGS)199 gbt_text_union(PG_FUNCTION_ARGS)
200 {
201 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
202 	int32	   *size = (int *) PG_GETARG_POINTER(1);
203 
204 	PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
205 									&tinfo));
206 }
207 
208 
209 Datum
gbt_text_picksplit(PG_FUNCTION_ARGS)210 gbt_text_picksplit(PG_FUNCTION_ARGS)
211 {
212 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
213 	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
214 
215 	gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
216 					  &tinfo);
217 	PG_RETURN_POINTER(v);
218 }
219 
220 Datum
gbt_text_same(PG_FUNCTION_ARGS)221 gbt_text_same(PG_FUNCTION_ARGS)
222 {
223 	Datum		d1 = PG_GETARG_DATUM(0);
224 	Datum		d2 = PG_GETARG_DATUM(1);
225 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
226 
227 	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
228 	PG_RETURN_POINTER(result);
229 }
230 
231 
232 Datum
gbt_text_penalty(PG_FUNCTION_ARGS)233 gbt_text_penalty(PG_FUNCTION_ARGS)
234 {
235 	GISTENTRY  *o = (GISTENTRY *) PG_GETARG_POINTER(0);
236 	GISTENTRY  *n = (GISTENTRY *) PG_GETARG_POINTER(1);
237 	float	   *result = (float *) PG_GETARG_POINTER(2);
238 
239 	PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
240 									  &tinfo));
241 }
242