2 * contrib/ltree/_ltree_op.c
5 * op function for ltree[]
6 * Teodor Sigaev <teodor@stack.net>
14 PG_FUNCTION_INFO_V1(_ltree_isparent
);
15 PG_FUNCTION_INFO_V1(_ltree_r_isparent
);
16 PG_FUNCTION_INFO_V1(_ltree_risparent
);
17 PG_FUNCTION_INFO_V1(_ltree_r_risparent
);
18 PG_FUNCTION_INFO_V1(_ltq_regex
);
19 PG_FUNCTION_INFO_V1(_ltq_rregex
);
20 PG_FUNCTION_INFO_V1(_lt_q_regex
);
21 PG_FUNCTION_INFO_V1(_lt_q_rregex
);
22 PG_FUNCTION_INFO_V1(_ltxtq_exec
);
23 PG_FUNCTION_INFO_V1(_ltxtq_rexec
);
25 PG_FUNCTION_INFO_V1(_ltree_extract_isparent
);
26 PG_FUNCTION_INFO_V1(_ltree_extract_risparent
);
27 PG_FUNCTION_INFO_V1(_ltq_extract_regex
);
28 PG_FUNCTION_INFO_V1(_ltxtq_extract_exec
);
30 PG_FUNCTION_INFO_V1(_lca
);
32 typedef Datum (*PGCALL2
) (PG_FUNCTION_ARGS
);
34 #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
37 array_iterator(ArrayType
*la
, PGCALL2 callback
, void *param
, ltree
**found
)
39 int num
= ArrayGetNItems(ARR_NDIM(la
), ARR_DIMS(la
));
40 ltree
*item
= (ltree
*) ARR_DATA_PTR(la
);
44 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
45 errmsg("array must be one-dimensional")));
46 if (array_contains_nulls(la
))
48 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED
),
49 errmsg("array must not contain nulls")));
55 if (DatumGetBool(DirectFunctionCall2(callback
,
56 PointerGetDatum(item
), PointerGetDatum(param
))))
71 _ltree_isparent(PG_FUNCTION_ARGS
)
73 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
74 ltree
*query
= PG_GETARG_LTREE_P(1);
75 bool res
= array_iterator(la
, ltree_isparent
, (void *) query
, NULL
);
77 PG_FREE_IF_COPY(la
, 0);
78 PG_FREE_IF_COPY(query
, 1);
83 _ltree_r_isparent(PG_FUNCTION_ARGS
)
85 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent
,
92 _ltree_risparent(PG_FUNCTION_ARGS
)
94 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
95 ltree
*query
= PG_GETARG_LTREE_P(1);
96 bool res
= array_iterator(la
, ltree_risparent
, (void *) query
, NULL
);
98 PG_FREE_IF_COPY(la
, 0);
99 PG_FREE_IF_COPY(query
, 1);
104 _ltree_r_risparent(PG_FUNCTION_ARGS
)
106 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent
,
113 _ltq_regex(PG_FUNCTION_ARGS
)
115 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
116 lquery
*query
= PG_GETARG_LQUERY_P(1);
117 bool res
= array_iterator(la
, ltq_regex
, (void *) query
, NULL
);
119 PG_FREE_IF_COPY(la
, 0);
120 PG_FREE_IF_COPY(query
, 1);
125 _ltq_rregex(PG_FUNCTION_ARGS
)
127 PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex
,
134 _lt_q_regex(PG_FUNCTION_ARGS
)
136 ArrayType
*_tree
= PG_GETARG_ARRAYTYPE_P(0);
137 ArrayType
*_query
= PG_GETARG_ARRAYTYPE_P(1);
138 lquery
*query
= (lquery
*) ARR_DATA_PTR(_query
);
140 int num
= ArrayGetNItems(ARR_NDIM(_query
), ARR_DIMS(_query
));
142 if (ARR_NDIM(_query
) > 1)
144 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
145 errmsg("array must be one-dimensional")));
146 if (array_contains_nulls(_query
))
148 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED
),
149 errmsg("array must not contain nulls")));
153 if (array_iterator(_tree
, ltq_regex
, (void *) query
, NULL
))
159 query
= (lquery
*) NEXTVAL(query
);
162 PG_FREE_IF_COPY(_tree
, 0);
163 PG_FREE_IF_COPY(_query
, 1);
168 _lt_q_rregex(PG_FUNCTION_ARGS
)
170 PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex
,
178 _ltxtq_exec(PG_FUNCTION_ARGS
)
180 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
181 ltxtquery
*query
= PG_GETARG_LTXTQUERY_P(1);
182 bool res
= array_iterator(la
, ltxtq_exec
, (void *) query
, NULL
);
184 PG_FREE_IF_COPY(la
, 0);
185 PG_FREE_IF_COPY(query
, 1);
190 _ltxtq_rexec(PG_FUNCTION_ARGS
)
192 PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec
,
200 _ltree_extract_isparent(PG_FUNCTION_ARGS
)
202 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
203 ltree
*query
= PG_GETARG_LTREE_P(1);
207 if (!array_iterator(la
, ltree_isparent
, (void *) query
, &found
))
209 PG_FREE_IF_COPY(la
, 0);
210 PG_FREE_IF_COPY(query
, 1);
214 item
= (ltree
*) palloc0(VARSIZE(found
));
215 memcpy(item
, found
, VARSIZE(found
));
217 PG_FREE_IF_COPY(la
, 0);
218 PG_FREE_IF_COPY(query
, 1);
219 PG_RETURN_POINTER(item
);
223 _ltree_extract_risparent(PG_FUNCTION_ARGS
)
225 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
226 ltree
*query
= PG_GETARG_LTREE_P(1);
230 if (!array_iterator(la
, ltree_risparent
, (void *) query
, &found
))
232 PG_FREE_IF_COPY(la
, 0);
233 PG_FREE_IF_COPY(query
, 1);
237 item
= (ltree
*) palloc0(VARSIZE(found
));
238 memcpy(item
, found
, VARSIZE(found
));
240 PG_FREE_IF_COPY(la
, 0);
241 PG_FREE_IF_COPY(query
, 1);
242 PG_RETURN_POINTER(item
);
246 _ltq_extract_regex(PG_FUNCTION_ARGS
)
248 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
249 lquery
*query
= PG_GETARG_LQUERY_P(1);
253 if (!array_iterator(la
, ltq_regex
, (void *) query
, &found
))
255 PG_FREE_IF_COPY(la
, 0);
256 PG_FREE_IF_COPY(query
, 1);
260 item
= (ltree
*) palloc0(VARSIZE(found
));
261 memcpy(item
, found
, VARSIZE(found
));
263 PG_FREE_IF_COPY(la
, 0);
264 PG_FREE_IF_COPY(query
, 1);
265 PG_RETURN_POINTER(item
);
269 _ltxtq_extract_exec(PG_FUNCTION_ARGS
)
271 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
272 ltxtquery
*query
= PG_GETARG_LTXTQUERY_P(1);
276 if (!array_iterator(la
, ltxtq_exec
, (void *) query
, &found
))
278 PG_FREE_IF_COPY(la
, 0);
279 PG_FREE_IF_COPY(query
, 1);
283 item
= (ltree
*) palloc0(VARSIZE(found
));
284 memcpy(item
, found
, VARSIZE(found
));
286 PG_FREE_IF_COPY(la
, 0);
287 PG_FREE_IF_COPY(query
, 1);
288 PG_RETURN_POINTER(item
);
292 _lca(PG_FUNCTION_ARGS
)
294 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
295 int num
= ArrayGetNItems(ARR_NDIM(la
), ARR_DIMS(la
));
296 ltree
*item
= (ltree
*) ARR_DATA_PTR(la
);
300 if (ARR_NDIM(la
) > 1)
302 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
303 errmsg("array must be one-dimensional")));
304 if (array_contains_nulls(la
))
306 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED
),
307 errmsg("array must not contain nulls")));
309 a
= (ltree
**) palloc(sizeof(ltree
*) * num
);
314 item
= NEXTVAL(item
);
316 res
= lca_inner(a
, ArrayGetNItems(ARR_NDIM(la
), ARR_DIMS(la
)));
319 PG_FREE_IF_COPY(la
, 0);
322 PG_RETURN_POINTER(res
);