2 * contrib/ltree/_ltree_op.c
5 * op function for ltree[]
6 * Teodor Sigaev <teodor@stack.net>
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) ) ) )
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
);
45 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
46 errmsg("array must be one-dimensional")));
47 if (array_contains_nulls(la
))
49 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED
),
50 errmsg("array must not contain nulls")));
56 if (DatumGetBool(DirectFunctionCall2(callback
,
57 PointerGetDatum(item
), PointerGetDatum(param
))))
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);
84 _ltree_r_isparent(PG_FUNCTION_ARGS
)
86 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent
,
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);
105 _ltree_r_risparent(PG_FUNCTION_ARGS
)
107 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent
,
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);
126 _ltq_rregex(PG_FUNCTION_ARGS
)
128 PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex
,
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
);
141 int num
= ArrayGetNItems(ARR_NDIM(_query
), ARR_DIMS(_query
));
143 if (ARR_NDIM(_query
) > 1)
145 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
146 errmsg("array must be one-dimensional")));
147 if (array_contains_nulls(_query
))
149 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED
),
150 errmsg("array must not contain nulls")));
154 if (array_iterator(_tree
, ltq_regex
, (void *) query
, NULL
))
160 query
= (lquery
*) NEXTVAL(query
);
163 PG_FREE_IF_COPY(_tree
, 0);
164 PG_FREE_IF_COPY(_query
, 1);
169 _lt_q_rregex(PG_FUNCTION_ARGS
)
171 PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex
,
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);
191 _ltxtq_rexec(PG_FUNCTION_ARGS
)
193 PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec
,
201 _ltree_extract_isparent(PG_FUNCTION_ARGS
)
203 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
204 ltree
*query
= PG_GETARG_LTREE_P(1);
208 if (!array_iterator(la
, ltree_isparent
, (void *) query
, &found
))
210 PG_FREE_IF_COPY(la
, 0);
211 PG_FREE_IF_COPY(query
, 1);
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
);
224 _ltree_extract_risparent(PG_FUNCTION_ARGS
)
226 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
227 ltree
*query
= PG_GETARG_LTREE_P(1);
231 if (!array_iterator(la
, ltree_risparent
, (void *) query
, &found
))
233 PG_FREE_IF_COPY(la
, 0);
234 PG_FREE_IF_COPY(query
, 1);
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
);
247 _ltq_extract_regex(PG_FUNCTION_ARGS
)
249 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
250 lquery
*query
= PG_GETARG_LQUERY_P(1);
254 if (!array_iterator(la
, ltq_regex
, (void *) query
, &found
))
256 PG_FREE_IF_COPY(la
, 0);
257 PG_FREE_IF_COPY(query
, 1);
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
);
270 _ltxtq_extract_exec(PG_FUNCTION_ARGS
)
272 ArrayType
*la
= PG_GETARG_ARRAYTYPE_P(0);
273 ltxtquery
*query
= PG_GETARG_LTXTQUERY_P(1);
277 if (!array_iterator(la
, ltxtq_exec
, (void *) query
, &found
))
279 PG_FREE_IF_COPY(la
, 0);
280 PG_FREE_IF_COPY(query
, 1);
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
);
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
);
301 if (ARR_NDIM(la
) > 1)
303 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR
),
304 errmsg("array must be one-dimensional")));
305 if (array_contains_nulls(la
))
307 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED
),
308 errmsg("array must not contain nulls")));
310 a
= (ltree
**) palloc(sizeof(ltree
*) * num
);
315 item
= NEXTVAL(item
);
317 res
= lca_inner(a
, ArrayGetNItems(ARR_NDIM(la
), ARR_DIMS(la
)));
320 PG_FREE_IF_COPY(la
, 0);
323 PG_RETURN_POINTER(res
);