Header And Logo

PostgreSQL
| The world's most advanced open source database.

_ltree_op.c

Go to the documentation of this file.
00001 /*
00002  * contrib/ltree/_ltree_op.c
00003  *
00004  *
00005  * op function for ltree[]
00006  * Teodor Sigaev <[email protected]>
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 }