Fix UNLISTEN to fall out quickly if the current backend has never executed
[PostgreSQL.git] / contrib / ltree / _ltree_op.c
blob316f20b48e282f472cbe4d553ca68cf4f76e2898
1 /*
2 * $PostgreSQL:$
5 * op function for ltree[]
6 * Teodor Sigaev <teodor@stack.net>
7 */
8 #include "postgres.h"
10 #include <ctype.h>
12 #include "utils/array.h"
13 #include "ltree.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 Datum _ltree_r_isparent(PG_FUNCTION_ARGS);
27 Datum _ltree_r_risparent(PG_FUNCTION_ARGS);
29 PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
30 PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
31 PG_FUNCTION_INFO_V1(_ltq_extract_regex);
32 PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
33 Datum _ltree_extract_isparent(PG_FUNCTION_ARGS);
34 Datum _ltree_extract_risparent(PG_FUNCTION_ARGS);
35 Datum _ltq_extract_regex(PG_FUNCTION_ARGS);
36 Datum _ltxtq_extract_exec(PG_FUNCTION_ARGS);
38 PG_FUNCTION_INFO_V1(_lca);
39 Datum _lca(PG_FUNCTION_ARGS);
41 typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
43 #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
45 static bool
46 array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree ** found)
48 int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
49 ltree *item = (ltree *) ARR_DATA_PTR(la);
51 if (ARR_NDIM(la) != 1)
52 ereport(ERROR,
53 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
54 errmsg("array must be one-dimensional")));
55 if (ARR_HASNULL(la))
56 ereport(ERROR,
57 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
58 errmsg("array must not contain nulls")));
60 if (found)
61 *found = NULL;
62 while (num > 0)
64 if (DatumGetBool(DirectFunctionCall2(callback,
65 PointerGetDatum(item), PointerGetDatum(param))))
68 if (found)
69 *found = item;
70 return true;
72 num--;
73 item = NEXTVAL(item);
76 return false;
79 Datum
80 _ltree_isparent(PG_FUNCTION_ARGS)
82 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
83 ltree *query = PG_GETARG_LTREE(1);
84 bool res = array_iterator(la, ltree_isparent, (void *) query, NULL);
86 PG_FREE_IF_COPY(la, 0);
87 PG_FREE_IF_COPY(query, 1);
88 PG_RETURN_BOOL(res);
91 Datum
92 _ltree_r_isparent(PG_FUNCTION_ARGS)
94 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
95 PG_GETARG_DATUM(1),
96 PG_GETARG_DATUM(0)
97 ));
100 Datum
101 _ltree_risparent(PG_FUNCTION_ARGS)
103 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
104 ltree *query = PG_GETARG_LTREE(1);
105 bool res = array_iterator(la, ltree_risparent, (void *) query, NULL);
107 PG_FREE_IF_COPY(la, 0);
108 PG_FREE_IF_COPY(query, 1);
109 PG_RETURN_BOOL(res);
112 Datum
113 _ltree_r_risparent(PG_FUNCTION_ARGS)
115 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
116 PG_GETARG_DATUM(1),
117 PG_GETARG_DATUM(0)
121 Datum
122 _ltq_regex(PG_FUNCTION_ARGS)
124 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
125 lquery *query = PG_GETARG_LQUERY(1);
126 bool res = array_iterator(la, ltq_regex, (void *) query, NULL);
128 PG_FREE_IF_COPY(la, 0);
129 PG_FREE_IF_COPY(query, 1);
130 PG_RETURN_BOOL(res);
133 Datum
134 _ltq_rregex(PG_FUNCTION_ARGS)
136 PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
137 PG_GETARG_DATUM(1),
138 PG_GETARG_DATUM(0)
142 Datum
143 _lt_q_regex(PG_FUNCTION_ARGS)
145 ArrayType *_tree = PG_GETARG_ARRAYTYPE_P(0);
146 ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
147 lquery *query = (lquery *) ARR_DATA_PTR(_query);
148 bool res = false;
149 int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
151 if (ARR_NDIM(_query) != 1)
152 ereport(ERROR,
153 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
154 errmsg("array must be one-dimensional")));
155 if (ARR_HASNULL(_query))
156 ereport(ERROR,
157 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
158 errmsg("array must not contain nulls")));
160 while (num > 0)
162 if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
164 res = true;
165 break;
167 num--;
168 query = (lquery *) NEXTVAL(query);
171 PG_FREE_IF_COPY(_tree, 0);
172 PG_FREE_IF_COPY(_query, 1);
173 PG_RETURN_BOOL(res);
176 Datum
177 _lt_q_rregex(PG_FUNCTION_ARGS)
179 PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
180 PG_GETARG_DATUM(1),
181 PG_GETARG_DATUM(0)
186 Datum
187 _ltxtq_exec(PG_FUNCTION_ARGS)
189 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
190 ltxtquery *query = PG_GETARG_LTXTQUERY(1);
191 bool res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
193 PG_FREE_IF_COPY(la, 0);
194 PG_FREE_IF_COPY(query, 1);
195 PG_RETURN_BOOL(res);
198 Datum
199 _ltxtq_rexec(PG_FUNCTION_ARGS)
201 PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
202 PG_GETARG_DATUM(1),
203 PG_GETARG_DATUM(0)
208 Datum
209 _ltree_extract_isparent(PG_FUNCTION_ARGS)
211 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
212 ltree *query = PG_GETARG_LTREE(1);
213 ltree *found,
214 *item;
216 if (!array_iterator(la, ltree_isparent, (void *) query, &found))
218 PG_FREE_IF_COPY(la, 0);
219 PG_FREE_IF_COPY(query, 1);
220 PG_RETURN_NULL();
223 item = (ltree *) palloc(VARSIZE(found));
224 memcpy(item, found, VARSIZE(found));
226 PG_FREE_IF_COPY(la, 0);
227 PG_FREE_IF_COPY(query, 1);
228 PG_RETURN_POINTER(item);
231 Datum
232 _ltree_extract_risparent(PG_FUNCTION_ARGS)
234 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
235 ltree *query = PG_GETARG_LTREE(1);
236 ltree *found,
237 *item;
239 if (!array_iterator(la, ltree_risparent, (void *) query, &found))
241 PG_FREE_IF_COPY(la, 0);
242 PG_FREE_IF_COPY(query, 1);
243 PG_RETURN_NULL();
246 item = (ltree *) palloc(VARSIZE(found));
247 memcpy(item, found, VARSIZE(found));
249 PG_FREE_IF_COPY(la, 0);
250 PG_FREE_IF_COPY(query, 1);
251 PG_RETURN_POINTER(item);
254 Datum
255 _ltq_extract_regex(PG_FUNCTION_ARGS)
257 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
258 lquery *query = PG_GETARG_LQUERY(1);
259 ltree *found,
260 *item;
262 if (!array_iterator(la, ltq_regex, (void *) query, &found))
264 PG_FREE_IF_COPY(la, 0);
265 PG_FREE_IF_COPY(query, 1);
266 PG_RETURN_NULL();
269 item = (ltree *) palloc(VARSIZE(found));
270 memcpy(item, found, VARSIZE(found));
272 PG_FREE_IF_COPY(la, 0);
273 PG_FREE_IF_COPY(query, 1);
274 PG_RETURN_POINTER(item);
277 Datum
278 _ltxtq_extract_exec(PG_FUNCTION_ARGS)
280 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
281 ltxtquery *query = PG_GETARG_LTXTQUERY(1);
282 ltree *found,
283 *item;
285 if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
287 PG_FREE_IF_COPY(la, 0);
288 PG_FREE_IF_COPY(query, 1);
289 PG_RETURN_NULL();
292 item = (ltree *) palloc(VARSIZE(found));
293 memcpy(item, found, VARSIZE(found));
295 PG_FREE_IF_COPY(la, 0);
296 PG_FREE_IF_COPY(query, 1);
297 PG_RETURN_POINTER(item);
300 Datum
301 _lca(PG_FUNCTION_ARGS)
303 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
304 int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
305 ltree *item = (ltree *) ARR_DATA_PTR(la);
306 ltree **a,
307 *res;
309 if (ARR_NDIM(la) != 1)
310 ereport(ERROR,
311 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
312 errmsg("array must be one-dimensional")));
313 if (ARR_HASNULL(la))
314 ereport(ERROR,
315 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
316 errmsg("array must not contain nulls")));
318 a = (ltree **) palloc(sizeof(ltree *) * num);
319 while (num > 0)
321 num--;
322 a[num] = item;
323 item = NEXTVAL(item);
325 res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
326 pfree(a);
328 PG_FREE_IF_COPY(la, 0);
330 if (res)
331 PG_RETURN_POINTER(res);
332 else
333 PG_RETURN_NULL();