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