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
);