00001
00002
00003
00004
00005
00006
00007
00008 #include "postgres.h"
00009
00010 #include <ctype.h>
00011
00012 #include "ltree.h"
00013
00014 PG_FUNCTION_INFO_V1(_ltree_isparent);
00015 PG_FUNCTION_INFO_V1(_ltree_r_isparent);
00016 PG_FUNCTION_INFO_V1(_ltree_risparent);
00017 PG_FUNCTION_INFO_V1(_ltree_r_risparent);
00018 PG_FUNCTION_INFO_V1(_ltq_regex);
00019 PG_FUNCTION_INFO_V1(_ltq_rregex);
00020 PG_FUNCTION_INFO_V1(_lt_q_regex);
00021 PG_FUNCTION_INFO_V1(_lt_q_rregex);
00022 PG_FUNCTION_INFO_V1(_ltxtq_exec);
00023 PG_FUNCTION_INFO_V1(_ltxtq_rexec);
00024
00025 Datum _ltree_r_isparent(PG_FUNCTION_ARGS);
00026 Datum _ltree_r_risparent(PG_FUNCTION_ARGS);
00027
00028 PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
00029 PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
00030 PG_FUNCTION_INFO_V1(_ltq_extract_regex);
00031 PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
00032 Datum _ltree_extract_isparent(PG_FUNCTION_ARGS);
00033 Datum _ltree_extract_risparent(PG_FUNCTION_ARGS);
00034 Datum _ltq_extract_regex(PG_FUNCTION_ARGS);
00035 Datum _ltxtq_extract_exec(PG_FUNCTION_ARGS);
00036
00037 PG_FUNCTION_INFO_V1(_lca);
00038 Datum _lca(PG_FUNCTION_ARGS);
00039
00040 typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
00041
00042 #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
00043
00044 static bool
00045 array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree **found)
00046 {
00047 int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
00048 ltree *item = (ltree *) ARR_DATA_PTR(la);
00049
00050 if (ARR_NDIM(la) > 1)
00051 ereport(ERROR,
00052 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
00053 errmsg("array must be one-dimensional")));
00054 if (array_contains_nulls(la))
00055 ereport(ERROR,
00056 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
00057 errmsg("array must not contain nulls")));
00058
00059 if (found)
00060 *found = NULL;
00061 while (num > 0)
00062 {
00063 if (DatumGetBool(DirectFunctionCall2(callback,
00064 PointerGetDatum(item), PointerGetDatum(param))))
00065 {
00066
00067 if (found)
00068 *found = item;
00069 return true;
00070 }
00071 num--;
00072 item = NEXTVAL(item);
00073 }
00074
00075 return false;
00076 }
00077
00078 Datum
00079 _ltree_isparent(PG_FUNCTION_ARGS)
00080 {
00081 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00082 ltree *query = PG_GETARG_LTREE(1);
00083 bool res = array_iterator(la, ltree_isparent, (void *) query, NULL);
00084
00085 PG_FREE_IF_COPY(la, 0);
00086 PG_FREE_IF_COPY(query, 1);
00087 PG_RETURN_BOOL(res);
00088 }
00089
00090 Datum
00091 _ltree_r_isparent(PG_FUNCTION_ARGS)
00092 {
00093 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
00094 PG_GETARG_DATUM(1),
00095 PG_GETARG_DATUM(0)
00096 ));
00097 }
00098
00099 Datum
00100 _ltree_risparent(PG_FUNCTION_ARGS)
00101 {
00102 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00103 ltree *query = PG_GETARG_LTREE(1);
00104 bool res = array_iterator(la, ltree_risparent, (void *) query, NULL);
00105
00106 PG_FREE_IF_COPY(la, 0);
00107 PG_FREE_IF_COPY(query, 1);
00108 PG_RETURN_BOOL(res);
00109 }
00110
00111 Datum
00112 _ltree_r_risparent(PG_FUNCTION_ARGS)
00113 {
00114 PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
00115 PG_GETARG_DATUM(1),
00116 PG_GETARG_DATUM(0)
00117 ));
00118 }
00119
00120 Datum
00121 _ltq_regex(PG_FUNCTION_ARGS)
00122 {
00123 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00124 lquery *query = PG_GETARG_LQUERY(1);
00125 bool res = array_iterator(la, ltq_regex, (void *) query, NULL);
00126
00127 PG_FREE_IF_COPY(la, 0);
00128 PG_FREE_IF_COPY(query, 1);
00129 PG_RETURN_BOOL(res);
00130 }
00131
00132 Datum
00133 _ltq_rregex(PG_FUNCTION_ARGS)
00134 {
00135 PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
00136 PG_GETARG_DATUM(1),
00137 PG_GETARG_DATUM(0)
00138 ));
00139 }
00140
00141 Datum
00142 _lt_q_regex(PG_FUNCTION_ARGS)
00143 {
00144 ArrayType *_tree = PG_GETARG_ARRAYTYPE_P(0);
00145 ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
00146 lquery *query = (lquery *) ARR_DATA_PTR(_query);
00147 bool res = false;
00148 int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
00149
00150 if (ARR_NDIM(_query) > 1)
00151 ereport(ERROR,
00152 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
00153 errmsg("array must be one-dimensional")));
00154 if (array_contains_nulls(_query))
00155 ereport(ERROR,
00156 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
00157 errmsg("array must not contain nulls")));
00158
00159 while (num > 0)
00160 {
00161 if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
00162 {
00163 res = true;
00164 break;
00165 }
00166 num--;
00167 query = (lquery *) NEXTVAL(query);
00168 }
00169
00170 PG_FREE_IF_COPY(_tree, 0);
00171 PG_FREE_IF_COPY(_query, 1);
00172 PG_RETURN_BOOL(res);
00173 }
00174
00175 Datum
00176 _lt_q_rregex(PG_FUNCTION_ARGS)
00177 {
00178 PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
00179 PG_GETARG_DATUM(1),
00180 PG_GETARG_DATUM(0)
00181 ));
00182 }
00183
00184
00185 Datum
00186 _ltxtq_exec(PG_FUNCTION_ARGS)
00187 {
00188 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00189 ltxtquery *query = PG_GETARG_LTXTQUERY(1);
00190 bool res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
00191
00192 PG_FREE_IF_COPY(la, 0);
00193 PG_FREE_IF_COPY(query, 1);
00194 PG_RETURN_BOOL(res);
00195 }
00196
00197 Datum
00198 _ltxtq_rexec(PG_FUNCTION_ARGS)
00199 {
00200 PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
00201 PG_GETARG_DATUM(1),
00202 PG_GETARG_DATUM(0)
00203 ));
00204 }
00205
00206
00207 Datum
00208 _ltree_extract_isparent(PG_FUNCTION_ARGS)
00209 {
00210 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00211 ltree *query = PG_GETARG_LTREE(1);
00212 ltree *found,
00213 *item;
00214
00215 if (!array_iterator(la, ltree_isparent, (void *) query, &found))
00216 {
00217 PG_FREE_IF_COPY(la, 0);
00218 PG_FREE_IF_COPY(query, 1);
00219 PG_RETURN_NULL();
00220 }
00221
00222 item = (ltree *) palloc(VARSIZE(found));
00223 memcpy(item, found, VARSIZE(found));
00224
00225 PG_FREE_IF_COPY(la, 0);
00226 PG_FREE_IF_COPY(query, 1);
00227 PG_RETURN_POINTER(item);
00228 }
00229
00230 Datum
00231 _ltree_extract_risparent(PG_FUNCTION_ARGS)
00232 {
00233 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00234 ltree *query = PG_GETARG_LTREE(1);
00235 ltree *found,
00236 *item;
00237
00238 if (!array_iterator(la, ltree_risparent, (void *) query, &found))
00239 {
00240 PG_FREE_IF_COPY(la, 0);
00241 PG_FREE_IF_COPY(query, 1);
00242 PG_RETURN_NULL();
00243 }
00244
00245 item = (ltree *) palloc(VARSIZE(found));
00246 memcpy(item, found, VARSIZE(found));
00247
00248 PG_FREE_IF_COPY(la, 0);
00249 PG_FREE_IF_COPY(query, 1);
00250 PG_RETURN_POINTER(item);
00251 }
00252
00253 Datum
00254 _ltq_extract_regex(PG_FUNCTION_ARGS)
00255 {
00256 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00257 lquery *query = PG_GETARG_LQUERY(1);
00258 ltree *found,
00259 *item;
00260
00261 if (!array_iterator(la, ltq_regex, (void *) query, &found))
00262 {
00263 PG_FREE_IF_COPY(la, 0);
00264 PG_FREE_IF_COPY(query, 1);
00265 PG_RETURN_NULL();
00266 }
00267
00268 item = (ltree *) palloc(VARSIZE(found));
00269 memcpy(item, found, VARSIZE(found));
00270
00271 PG_FREE_IF_COPY(la, 0);
00272 PG_FREE_IF_COPY(query, 1);
00273 PG_RETURN_POINTER(item);
00274 }
00275
00276 Datum
00277 _ltxtq_extract_exec(PG_FUNCTION_ARGS)
00278 {
00279 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00280 ltxtquery *query = PG_GETARG_LTXTQUERY(1);
00281 ltree *found,
00282 *item;
00283
00284 if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
00285 {
00286 PG_FREE_IF_COPY(la, 0);
00287 PG_FREE_IF_COPY(query, 1);
00288 PG_RETURN_NULL();
00289 }
00290
00291 item = (ltree *) palloc(VARSIZE(found));
00292 memcpy(item, found, VARSIZE(found));
00293
00294 PG_FREE_IF_COPY(la, 0);
00295 PG_FREE_IF_COPY(query, 1);
00296 PG_RETURN_POINTER(item);
00297 }
00298
00299 Datum
00300 _lca(PG_FUNCTION_ARGS)
00301 {
00302 ArrayType *la = PG_GETARG_ARRAYTYPE_P(0);
00303 int num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
00304 ltree *item = (ltree *) ARR_DATA_PTR(la);
00305 ltree **a,
00306 *res;
00307
00308 if (ARR_NDIM(la) > 1)
00309 ereport(ERROR,
00310 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
00311 errmsg("array must be one-dimensional")));
00312 if (array_contains_nulls(la))
00313 ereport(ERROR,
00314 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
00315 errmsg("array must not contain nulls")));
00316
00317 a = (ltree **) palloc(sizeof(ltree *) * num);
00318 while (num > 0)
00319 {
00320 num--;
00321 a[num] = item;
00322 item = NEXTVAL(item);
00323 }
00324 res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
00325 pfree(a);
00326
00327 PG_FREE_IF_COPY(la, 0);
00328
00329 if (res)
00330 PG_RETURN_POINTER(res);
00331 else
00332 PG_RETURN_NULL();
00333 }