Age Owner Branch data TLA Line data Source code
1 : : /*
2 : : * contrib/ltree/_ltree_op.c
3 : : *
4 : : *
5 : : * op function for ltree[]
6 : : * Teodor Sigaev <teodor@stack.net>
7 : : */
8 : : #include "postgres.h"
9 : :
10 : : #include <ctype.h>
11 : :
12 : : #include "ltree.h"
13 : : #include "utils/array.h"
14 : :
7929 bruce@momjian.us 15 :CBC 3 : PG_FUNCTION_INFO_V1(_ltree_isparent);
16 : 2 : PG_FUNCTION_INFO_V1(_ltree_r_isparent);
17 : 3 : PG_FUNCTION_INFO_V1(_ltree_risparent);
18 : 2 : PG_FUNCTION_INFO_V1(_ltree_r_risparent);
19 : 3 : PG_FUNCTION_INFO_V1(_ltq_regex);
20 : 2 : PG_FUNCTION_INFO_V1(_ltq_rregex);
7725 21 : 3 : PG_FUNCTION_INFO_V1(_lt_q_regex);
22 : 2 : PG_FUNCTION_INFO_V1(_lt_q_rregex);
7929 23 : 3 : PG_FUNCTION_INFO_V1(_ltxtq_exec);
24 : 2 : PG_FUNCTION_INFO_V1(_ltxtq_rexec);
25 : :
26 : 3 : PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
27 : 3 : PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
28 : 3 : PG_FUNCTION_INFO_V1(_ltq_extract_regex);
29 : 3 : PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
30 : :
7924 31 : 3 : PG_FUNCTION_INFO_V1(_lca);
32 : :
33 : : typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
34 : :
35 : : #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
36 : :
37 : : static bool
5421 38 : 20323 : array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
39 : : {
7893 40 : 20323 : int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
41 [ - + ]: 20323 : ltree *item = (ltree *) ARR_DATA_PTR(la);
42 : :
5163 tgl@sss.pgh.pa.us 43 [ - + ]: 20323 : if (ARR_NDIM(la) > 1)
7570 tgl@sss.pgh.pa.us 44 [ # # ]:UBC 0 : ereport(ERROR,
45 : : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
46 : : errmsg("array must be one-dimensional")));
4844 tgl@sss.pgh.pa.us 47 [ - + ]:CBC 20323 : if (array_contains_nulls(la))
6721 tgl@sss.pgh.pa.us 48 [ # # ]:UBC 0 : ereport(ERROR,
49 : : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
50 : : errmsg("array must not contain nulls")));
51 : :
7893 bruce@momjian.us 52 [ + + ]:CBC 20323 : if (found)
53 : 6 : *found = NULL;
54 [ + + ]: 91782 : while (num > 0)
55 : : {
56 [ + + ]: 72507 : if (DatumGetBool(DirectFunctionCall2(callback,
57 : : PointerGetDatum(item), PointerGetDatum(param))))
58 : : {
59 : :
60 [ + + ]: 1048 : if (found)
7929 61 : 4 : *found = item;
62 : 1048 : return true;
63 : : }
64 : 71459 : num--;
7893 65 : 71459 : item = NEXTVAL(item);
66 : : }
67 : :
7929 68 : 19275 : return false;
69 : : }
70 : :
71 : : Datum
7893 72 : 3012 : _ltree_isparent(PG_FUNCTION_ARGS)
73 : : {
74 : 3012 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 75 : 3012 : ltree *query = PG_GETARG_LTREE_P(1);
7893 bruce@momjian.us 76 : 3012 : bool res = array_iterator(la, ltree_isparent, (void *) query, NULL);
77 : :
78 [ + + ]: 3012 : PG_FREE_IF_COPY(la, 0);
79 [ - + ]: 3012 : PG_FREE_IF_COPY(query, 1);
7929 80 : 3012 : PG_RETURN_BOOL(res);
81 : : }
82 : :
83 : : Datum
7893 bruce@momjian.us 84 :UBC 0 : _ltree_r_isparent(PG_FUNCTION_ARGS)
85 : : {
86 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
87 : : PG_GETARG_DATUM(1),
88 : : PG_GETARG_DATUM(0)
89 : : ));
90 : : }
91 : :
92 : : Datum
7893 bruce@momjian.us 93 :CBC 2310 : _ltree_risparent(PG_FUNCTION_ARGS)
94 : : {
95 : 2310 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 96 : 2310 : ltree *query = PG_GETARG_LTREE_P(1);
7893 bruce@momjian.us 97 : 2310 : bool res = array_iterator(la, ltree_risparent, (void *) query, NULL);
98 : :
99 [ + + ]: 2310 : PG_FREE_IF_COPY(la, 0);
100 [ - + ]: 2310 : PG_FREE_IF_COPY(query, 1);
7929 101 : 2310 : PG_RETURN_BOOL(res);
102 : : }
103 : :
104 : : Datum
7893 bruce@momjian.us 105 :UBC 0 : _ltree_r_risparent(PG_FUNCTION_ARGS)
106 : : {
107 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
108 : : PG_GETARG_DATUM(1),
109 : : PG_GETARG_DATUM(0)
110 : : ));
111 : : }
112 : :
113 : : Datum
7893 bruce@momjian.us 114 :CBC 9575 : _ltq_regex(PG_FUNCTION_ARGS)
115 : : {
116 : 9575 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 117 : 9575 : lquery *query = PG_GETARG_LQUERY_P(1);
7893 bruce@momjian.us 118 : 9575 : bool res = array_iterator(la, ltq_regex, (void *) query, NULL);
119 : :
120 [ + + ]: 9575 : PG_FREE_IF_COPY(la, 0);
121 [ - + ]: 9575 : PG_FREE_IF_COPY(query, 1);
7929 122 : 9575 : PG_RETURN_BOOL(res);
123 : : }
124 : :
125 : : Datum
7893 bruce@momjian.us 126 :UBC 0 : _ltq_rregex(PG_FUNCTION_ARGS)
127 : : {
128 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
129 : : PG_GETARG_DATUM(1),
130 : : PG_GETARG_DATUM(0)
131 : : ));
132 : : }
133 : :
134 : : Datum
7725 bruce@momjian.us 135 :CBC 1868 : _lt_q_regex(PG_FUNCTION_ARGS)
136 : : {
7559 137 : 1868 : ArrayType *_tree = PG_GETARG_ARRAYTYPE_P(0);
138 : 1868 : ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
139 [ - + ]: 1868 : lquery *query = (lquery *) ARR_DATA_PTR(_query);
140 : 1868 : bool res = false;
141 : 1868 : int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
142 : :
5163 tgl@sss.pgh.pa.us 143 [ - + ]: 1868 : if (ARR_NDIM(_query) > 1)
7559 bruce@momjian.us 144 [ # # ]:UBC 0 : ereport(ERROR,
145 : : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
146 : : errmsg("array must be one-dimensional")));
4844 tgl@sss.pgh.pa.us 147 [ - + ]:CBC 1868 : if (array_contains_nulls(_query))
6721 tgl@sss.pgh.pa.us 148 [ # # ]:UBC 0 : ereport(ERROR,
149 : : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
150 : : errmsg("array must not contain nulls")));
151 : :
7559 bruce@momjian.us 152 [ + + ]:CBC 5524 : while (num > 0)
153 : : {
154 [ + + ]: 3702 : if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
155 : : {
156 : 46 : res = true;
157 : 46 : break;
158 : : }
159 : 3656 : num--;
160 : 3656 : query = (lquery *) NEXTVAL(query);
161 : : }
162 : :
163 [ + + ]: 1868 : PG_FREE_IF_COPY(_tree, 0);
164 [ - + ]: 1868 : PG_FREE_IF_COPY(_query, 1);
165 : 1868 : PG_RETURN_BOOL(res);
166 : : }
167 : :
168 : : Datum
7725 bruce@momjian.us 169 :UBC 0 : _lt_q_rregex(PG_FUNCTION_ARGS)
170 : : {
7559 171 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
172 : : PG_GETARG_DATUM(1),
173 : : PG_GETARG_DATUM(0)
174 : : ));
175 : : }
176 : :
177 : :
178 : : Datum
7893 bruce@momjian.us 179 :CBC 1718 : _ltxtq_exec(PG_FUNCTION_ARGS)
180 : : {
181 : 1718 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 182 : 1718 : ltxtquery *query = PG_GETARG_LTXTQUERY_P(1);
7893 bruce@momjian.us 183 : 1718 : bool res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
184 : :
185 [ + + ]: 1718 : PG_FREE_IF_COPY(la, 0);
186 [ - + ]: 1718 : PG_FREE_IF_COPY(query, 1);
7929 187 : 1718 : PG_RETURN_BOOL(res);
188 : : }
189 : :
190 : : Datum
7893 bruce@momjian.us 191 :UBC 0 : _ltxtq_rexec(PG_FUNCTION_ARGS)
192 : : {
193 : 0 : PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
194 : : PG_GETARG_DATUM(1),
195 : : PG_GETARG_DATUM(0)
196 : : ));
197 : : }
198 : :
199 : :
200 : : Datum
7893 bruce@momjian.us 201 :CBC 2 : _ltree_extract_isparent(PG_FUNCTION_ARGS)
202 : : {
203 : 2 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 204 : 2 : ltree *query = PG_GETARG_LTREE_P(1);
205 : : ltree *found,
206 : : *item;
207 : :
7893 bruce@momjian.us 208 [ + + ]: 2 : if (!array_iterator(la, ltree_isparent, (void *) query, &found))
209 : : {
210 [ - + ]: 1 : PG_FREE_IF_COPY(la, 0);
211 [ - + ]: 1 : PG_FREE_IF_COPY(query, 1);
7929 212 : 1 : PG_RETURN_NULL();
213 : : }
214 : :
2959 andres@anarazel.de 215 : 1 : item = (ltree *) palloc0(VARSIZE(found));
6255 tgl@sss.pgh.pa.us 216 : 1 : memcpy(item, found, VARSIZE(found));
217 : :
7893 bruce@momjian.us 218 [ - + ]: 1 : PG_FREE_IF_COPY(la, 0);
219 [ - + ]: 1 : PG_FREE_IF_COPY(query, 1);
7929 220 : 1 : PG_RETURN_POINTER(item);
221 : : }
222 : :
223 : : Datum
7893 224 : 2 : _ltree_extract_risparent(PG_FUNCTION_ARGS)
225 : : {
226 : 2 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 227 : 2 : ltree *query = PG_GETARG_LTREE_P(1);
228 : : ltree *found,
229 : : *item;
230 : :
7893 bruce@momjian.us 231 [ + + ]: 2 : if (!array_iterator(la, ltree_risparent, (void *) query, &found))
232 : : {
233 [ - + ]: 1 : PG_FREE_IF_COPY(la, 0);
234 [ - + ]: 1 : PG_FREE_IF_COPY(query, 1);
7929 235 : 1 : PG_RETURN_NULL();
236 : : }
237 : :
2959 andres@anarazel.de 238 : 1 : item = (ltree *) palloc0(VARSIZE(found));
6255 tgl@sss.pgh.pa.us 239 : 1 : memcpy(item, found, VARSIZE(found));
240 : :
7893 bruce@momjian.us 241 [ - + ]: 1 : PG_FREE_IF_COPY(la, 0);
242 [ - + ]: 1 : PG_FREE_IF_COPY(query, 1);
7929 243 : 1 : PG_RETURN_POINTER(item);
244 : : }
245 : :
246 : : Datum
7893 247 : 1 : _ltq_extract_regex(PG_FUNCTION_ARGS)
248 : : {
249 : 1 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 250 : 1 : lquery *query = PG_GETARG_LQUERY_P(1);
251 : : ltree *found,
252 : : *item;
253 : :
7893 bruce@momjian.us 254 [ - + ]: 1 : if (!array_iterator(la, ltq_regex, (void *) query, &found))
255 : : {
7893 bruce@momjian.us 256 [ # # ]:UBC 0 : PG_FREE_IF_COPY(la, 0);
257 [ # # ]: 0 : PG_FREE_IF_COPY(query, 1);
7929 258 : 0 : PG_RETURN_NULL();
259 : : }
260 : :
2959 andres@anarazel.de 261 :CBC 1 : item = (ltree *) palloc0(VARSIZE(found));
6255 tgl@sss.pgh.pa.us 262 : 1 : memcpy(item, found, VARSIZE(found));
263 : :
7893 bruce@momjian.us 264 [ - + ]: 1 : PG_FREE_IF_COPY(la, 0);
265 [ - + ]: 1 : PG_FREE_IF_COPY(query, 1);
7929 266 : 1 : PG_RETURN_POINTER(item);
267 : : }
268 : :
269 : : Datum
7893 270 : 1 : _ltxtq_extract_exec(PG_FUNCTION_ARGS)
271 : : {
272 : 1 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
2400 tgl@sss.pgh.pa.us 273 : 1 : ltxtquery *query = PG_GETARG_LTXTQUERY_P(1);
274 : : ltree *found,
275 : : *item;
276 : :
7893 bruce@momjian.us 277 [ - + ]: 1 : if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
278 : : {
7893 bruce@momjian.us 279 [ # # ]:UBC 0 : PG_FREE_IF_COPY(la, 0);
280 [ # # ]: 0 : PG_FREE_IF_COPY(query, 1);
7929 281 : 0 : PG_RETURN_NULL();
282 : : }
283 : :
2959 andres@anarazel.de 284 :CBC 1 : item = (ltree *) palloc0(VARSIZE(found));
6255 tgl@sss.pgh.pa.us 285 : 1 : memcpy(item, found, VARSIZE(found));
286 : :
7893 bruce@momjian.us 287 [ - + ]: 1 : PG_FREE_IF_COPY(la, 0);
288 [ - + ]: 1 : PG_FREE_IF_COPY(query, 1);
7929 289 : 1 : PG_RETURN_POINTER(item);
290 : : }
291 : :
292 : : Datum
7893 293 : 8 : _lca(PG_FUNCTION_ARGS)
294 : : {
295 : 8 : ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
296 : 8 : int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
297 [ - + ]: 8 : ltree *item = (ltree *) ARR_DATA_PTR(la);
298 : : ltree **a,
299 : : *res;
300 : :
5163 tgl@sss.pgh.pa.us 301 [ - + ]: 8 : if (ARR_NDIM(la) > 1)
6721 tgl@sss.pgh.pa.us 302 [ # # ]:UBC 0 : ereport(ERROR,
303 : : (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
304 : : errmsg("array must be one-dimensional")));
4844 tgl@sss.pgh.pa.us 305 [ - + ]:CBC 8 : if (array_contains_nulls(la))
6721 tgl@sss.pgh.pa.us 306 [ # # ]:UBC 0 : ereport(ERROR,
307 : : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
308 : : errmsg("array must not contain nulls")));
309 : :
7893 bruce@momjian.us 310 :CBC 8 : a = (ltree **) palloc(sizeof(ltree *) * num);
311 [ + + ]: 20 : while (num > 0)
312 : : {
7924 313 : 12 : num--;
314 : 12 : a[num] = item;
315 : 12 : item = NEXTVAL(item);
316 : : }
7893 317 : 8 : res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
7924 318 : 8 : pfree(a);
319 : :
7893 320 [ - + ]: 8 : PG_FREE_IF_COPY(la, 0);
321 : :
322 [ + + ]: 8 : if (res)
323 : 6 : PG_RETURN_POINTER(res);
324 : : else
325 : 2 : PG_RETURN_NULL();
326 : : }
|