Use a safer outfuncs/readfuncs representation for BitStrings.
[pgsql.git] / contrib / ltree / _ltree_op.c
blob2fdb5ea97bf40a644f161ddbb9f59672bd990b2e
1 /*
2 * contrib/ltree/_ltree_op.c
5 * op function for ltree[]
6 * Teodor Sigaev <teodor@stack.net>
7 */
8 #include "postgres.h"
10 #include <ctype.h>
12 #include "ltree.h"
13 #include "utils/array.h"
15 PG_FUNCTION_INFO_V1(_ltree_isparent);
16 PG_FUNCTION_INFO_V1(_ltree_r_isparent);
17 PG_FUNCTION_INFO_V1(_ltree_risparent);
18 PG_FUNCTION_INFO_V1(_ltree_r_risparent);
19 PG_FUNCTION_INFO_V1(_ltq_regex);
20 PG_FUNCTION_INFO_V1(_ltq_rregex);
21 PG_FUNCTION_INFO_V1(_lt_q_regex);
22 PG_FUNCTION_INFO_V1(_lt_q_rregex);
23 PG_FUNCTION_INFO_V1(_ltxtq_exec);
24 PG_FUNCTION_INFO_V1(_ltxtq_rexec);
26 PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
27 PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
28 PG_FUNCTION_INFO_V1(_ltq_extract_regex);
29 PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
31 PG_FUNCTION_INFO_V1(_lca);
33 typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
35 #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
37 static bool
38 array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
40 int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
41 ltree *item = (ltree *) ARR_DATA_PTR(la);
43 if (ARR_NDIM(la) > 1)
44 ereport(ERROR,
45 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
46 errmsg("array must be one-dimensional")));
47 if (array_contains_nulls(la))
48 ereport(ERROR,
49 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
50 errmsg("array must not contain nulls")));
52 if (found)
53 *found = NULL;
54 while (num > 0)
56 if (DatumGetBool(DirectFunctionCall2(callback,
57 PointerGetDatum(item), PointerGetDatum(param))))
60 if (found)
61 *found = item;
62 return true;
64 num--;
65 item = NEXTVAL(item);
68 return false;
71 Datum
72 _ltree_isparent(PG_FUNCTION_ARGS)
74 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
75 ltree *query = PG_GETARG_LTREE_P(1);
76 bool res = array_iterator(la, ltree_isparent, (void *) query, NULL);
78 PG_FREE_IF_COPY(la, 0);
79 PG_FREE_IF_COPY(query, 1);
80 PG_RETURN_BOOL(res);
83 Datum
84 _ltree_r_isparent(PG_FUNCTION_ARGS)
86 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
87 PG_GETARG_DATUM(1),
88 PG_GETARG_DATUM(0)
89 ));
92 Datum
93 _ltree_risparent(PG_FUNCTION_ARGS)
95 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
96 ltree *query = PG_GETARG_LTREE_P(1);
97 bool res = array_iterator(la, ltree_risparent, (void *) query, NULL);
99 PG_FREE_IF_COPY(la, 0);
100 PG_FREE_IF_COPY(query, 1);
101 PG_RETURN_BOOL(res);
104 Datum
105 _ltree_r_risparent(PG_FUNCTION_ARGS)
107 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
108 PG_GETARG_DATUM(1),
109 PG_GETARG_DATUM(0)
113 Datum
114 _ltq_regex(PG_FUNCTION_ARGS)
116 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
117 lquery *query = PG_GETARG_LQUERY_P(1);
118 bool res = array_iterator(la, ltq_regex, (void *) query, NULL);
120 PG_FREE_IF_COPY(la, 0);
121 PG_FREE_IF_COPY(query, 1);
122 PG_RETURN_BOOL(res);
125 Datum
126 _ltq_rregex(PG_FUNCTION_ARGS)
128 PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
129 PG_GETARG_DATUM(1),
130 PG_GETARG_DATUM(0)
134 Datum
135 _lt_q_regex(PG_FUNCTION_ARGS)
137 ArrayType *_tree = PG_GETARG_ARRAYTYPE_P(0);
138 ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
139 lquery *query = (lquery *) ARR_DATA_PTR(_query);
140 bool res = false;
141 int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
143 if (ARR_NDIM(_query) > 1)
144 ereport(ERROR,
145 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
146 errmsg("array must be one-dimensional")));
147 if (array_contains_nulls(_query))
148 ereport(ERROR,
149 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
150 errmsg("array must not contain nulls")));
152 while (num > 0)
154 if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
156 res = true;
157 break;
159 num--;
160 query = (lquery *) NEXTVAL(query);
163 PG_FREE_IF_COPY(_tree, 0);
164 PG_FREE_IF_COPY(_query, 1);
165 PG_RETURN_BOOL(res);
168 Datum
169 _lt_q_rregex(PG_FUNCTION_ARGS)
171 PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
172 PG_GETARG_DATUM(1),
173 PG_GETARG_DATUM(0)
178 Datum
179 _ltxtq_exec(PG_FUNCTION_ARGS)
181 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
182 ltxtquery *query = PG_GETARG_LTXTQUERY_P(1);
183 bool res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
185 PG_FREE_IF_COPY(la, 0);
186 PG_FREE_IF_COPY(query, 1);
187 PG_RETURN_BOOL(res);
190 Datum
191 _ltxtq_rexec(PG_FUNCTION_ARGS)
193 PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
194 PG_GETARG_DATUM(1),
195 PG_GETARG_DATUM(0)
200 Datum
201 _ltree_extract_isparent(PG_FUNCTION_ARGS)
203 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
204 ltree *query = PG_GETARG_LTREE_P(1);
205 ltree *found,
206 *item;
208 if (!array_iterator(la, ltree_isparent, (void *) query, &found))
210 PG_FREE_IF_COPY(la, 0);
211 PG_FREE_IF_COPY(query, 1);
212 PG_RETURN_NULL();
215 item = (ltree *) palloc0(VARSIZE(found));
216 memcpy(item, found, VARSIZE(found));
218 PG_FREE_IF_COPY(la, 0);
219 PG_FREE_IF_COPY(query, 1);
220 PG_RETURN_POINTER(item);
223 Datum
224 _ltree_extract_risparent(PG_FUNCTION_ARGS)
226 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
227 ltree *query = PG_GETARG_LTREE_P(1);
228 ltree *found,
229 *item;
231 if (!array_iterator(la, ltree_risparent, (void *) query, &found))
233 PG_FREE_IF_COPY(la, 0);
234 PG_FREE_IF_COPY(query, 1);
235 PG_RETURN_NULL();
238 item = (ltree *) palloc0(VARSIZE(found));
239 memcpy(item, found, VARSIZE(found));
241 PG_FREE_IF_COPY(la, 0);
242 PG_FREE_IF_COPY(query, 1);
243 PG_RETURN_POINTER(item);
246 Datum
247 _ltq_extract_regex(PG_FUNCTION_ARGS)
249 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
250 lquery *query = PG_GETARG_LQUERY_P(1);
251 ltree *found,
252 *item;
254 if (!array_iterator(la, ltq_regex, (void *) query, &found))
256 PG_FREE_IF_COPY(la, 0);
257 PG_FREE_IF_COPY(query, 1);
258 PG_RETURN_NULL();
261 item = (ltree *) palloc0(VARSIZE(found));
262 memcpy(item, found, VARSIZE(found));
264 PG_FREE_IF_COPY(la, 0);
265 PG_FREE_IF_COPY(query, 1);
266 PG_RETURN_POINTER(item);
269 Datum
270 _ltxtq_extract_exec(PG_FUNCTION_ARGS)
272 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
273 ltxtquery *query = PG_GETARG_LTXTQUERY_P(1);
274 ltree *found,
275 *item;
277 if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
279 PG_FREE_IF_COPY(la, 0);
280 PG_FREE_IF_COPY(query, 1);
281 PG_RETURN_NULL();
284 item = (ltree *) palloc0(VARSIZE(found));
285 memcpy(item, found, VARSIZE(found));
287 PG_FREE_IF_COPY(la, 0);
288 PG_FREE_IF_COPY(query, 1);
289 PG_RETURN_POINTER(item);
292 Datum
293 _lca(PG_FUNCTION_ARGS)
295 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
296 int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
297 ltree *item = (ltree *) ARR_DATA_PTR(la);
298 ltree **a,
299 *res;
301 if (ARR_NDIM(la) > 1)
302 ereport(ERROR,
303 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
304 errmsg("array must be one-dimensional")));
305 if (array_contains_nulls(la))
306 ereport(ERROR,
307 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
308 errmsg("array must not contain nulls")));
310 a = (ltree **) palloc(sizeof(ltree *) * num);
311 while (num > 0)
313 num--;
314 a[num] = item;
315 item = NEXTVAL(item);
317 res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
318 pfree(a);
320 PG_FREE_IF_COPY(la, 0);
322 if (res)
323 PG_RETURN_POINTER(res);
324 else
325 PG_RETURN_NULL();