5
* op function for ltree[]
6
* Teodor Sigaev <teodor@stack.net>
12
#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
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) ) ) )
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)
53
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
54
errmsg("array must be one-dimensional")));
57
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
58
errmsg("array must not contain nulls")));
64
if (DatumGetBool(DirectFunctionCall2(callback,
65
PointerGetDatum(item), PointerGetDatum(param))))
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);
92
_ltree_r_isparent(PG_FUNCTION_ARGS)
94
PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
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);
113
_ltree_r_risparent(PG_FUNCTION_ARGS)
115
PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
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);
134
_ltq_rregex(PG_FUNCTION_ARGS)
136
PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
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);
149
int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
151
if (ARR_NDIM(_query) != 1)
153
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
154
errmsg("array must be one-dimensional")));
155
if (ARR_HASNULL(_query))
157
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
158
errmsg("array must not contain nulls")));
162
if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
168
query = (lquery *) NEXTVAL(query);
171
PG_FREE_IF_COPY(_tree, 0);
172
PG_FREE_IF_COPY(_query, 1);
177
_lt_q_rregex(PG_FUNCTION_ARGS)
179
PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
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);
199
_ltxtq_rexec(PG_FUNCTION_ARGS)
201
PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
209
_ltree_extract_isparent(PG_FUNCTION_ARGS)
211
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
212
ltree *query = PG_GETARG_LTREE(1);
216
if (!array_iterator(la, ltree_isparent, (void *) query, &found))
218
PG_FREE_IF_COPY(la, 0);
219
PG_FREE_IF_COPY(query, 1);
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);
232
_ltree_extract_risparent(PG_FUNCTION_ARGS)
234
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
235
ltree *query = PG_GETARG_LTREE(1);
239
if (!array_iterator(la, ltree_risparent, (void *) query, &found))
241
PG_FREE_IF_COPY(la, 0);
242
PG_FREE_IF_COPY(query, 1);
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);
255
_ltq_extract_regex(PG_FUNCTION_ARGS)
257
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
258
lquery *query = PG_GETARG_LQUERY(1);
262
if (!array_iterator(la, ltq_regex, (void *) query, &found))
264
PG_FREE_IF_COPY(la, 0);
265
PG_FREE_IF_COPY(query, 1);
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);
278
_ltxtq_extract_exec(PG_FUNCTION_ARGS)
280
ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
281
ltxtquery *query = PG_GETARG_LTXTQUERY(1);
285
if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
287
PG_FREE_IF_COPY(la, 0);
288
PG_FREE_IF_COPY(query, 1);
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);
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);
309
if (ARR_NDIM(la) != 1)
311
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
312
errmsg("array must be one-dimensional")));
315
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
316
errmsg("array must not contain nulls")));
318
a = (ltree **) palloc(sizeof(ltree *) * num);
323
item = NEXTVAL(item);
325
res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
328
PG_FREE_IF_COPY(la, 0);
331
PG_RETURN_POINTER(res);