diff options
Diffstat (limited to 'contrib/ltree/lquery_op.c')
-rw-r--r-- | contrib/ltree/lquery_op.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/contrib/ltree/lquery_op.c b/contrib/ltree/lquery_op.c index e24cc8559fc..1156723d58a 100644 --- a/contrib/ltree/lquery_op.c +++ b/contrib/ltree/lquery_op.c @@ -5,10 +5,16 @@ #include "ltree.h" #include <ctype.h> +#include "utils/array.h" PG_FUNCTION_INFO_V1(ltq_regex); PG_FUNCTION_INFO_V1(ltq_rregex); +PG_FUNCTION_INFO_V1(lt_q_regex); +PG_FUNCTION_INFO_V1(lt_q_rregex); + +#define NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) ) + typedef struct { lquery_level *q; @@ -39,7 +45,7 @@ getlexem(char *start, char *end, int *len) } bool - compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend) +compare_subnode(ltree_level * t, char *qn, int len, int (*cmpptr) (const char *, const char *, size_t), bool anyend) { char *endt = t->name + t->len; char *endq = qn + len; @@ -117,6 +123,11 @@ printFieldNot(FieldNot *fn ) { } */ +static struct { + bool muse; + uint32 high_pos; +} SomeStack = {false,0,}; + static bool checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_numlevel, FieldNot * ptr) { @@ -129,6 +140,14 @@ checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_ lquery_level *prevq = NULL; ltree_level *prevt = NULL; + if ( SomeStack.muse ) { + high_pos = SomeStack.high_pos; + qlen--; + prevq = curq; + curq = LQL_NEXT(curq); + SomeStack.muse = false; + } + while (tlen > 0 && qlen > 0) { if (curq->numvar) @@ -181,6 +200,15 @@ checkCond(lquery_level * curq, int query_numlevel, ltree_level * curt, int tree_ curt = LEVEL_NEXT(curt); tlen--; cur_tpos++; + if ( isok && prevq && prevq->numvar==0 && tlen>0 && cur_tpos <= high_pos ) { + FieldNot tmpptr; + if ( ptr ) + memcpy(&tmpptr,ptr,sizeof(FieldNot)); + SomeStack.high_pos = high_pos-cur_tpos; + SomeStack.muse = true; + if ( checkCond(prevq, qlen+1, curt, tlen, (ptr) ? &tmpptr : NULL) ) + return true; + } if (!isok && ptr) ptr->nt++; } @@ -278,3 +306,42 @@ ltq_rregex(PG_FUNCTION_ARGS) PG_GETARG_DATUM(0) )); } + +Datum +lt_q_regex(PG_FUNCTION_ARGS) +{ + ltree *tree = PG_GETARG_LTREE(0); + ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1); + lquery *query = (lquery *) ARR_DATA_PTR(_query); + bool res = false; + int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query)); + + if (ARR_NDIM(_query) != 1) + elog(ERROR, "Dimension of array != 1"); + + while (num > 0) { + if (DatumGetBool(DirectFunctionCall2(ltq_regex, + PointerGetDatum(tree), PointerGetDatum(query)))) { + + res = true; + break; + } + num--; + query = NEXTVAL(query); + } + + PG_FREE_IF_COPY(tree, 0); + PG_FREE_IF_COPY(_query, 1); + PG_RETURN_BOOL(res); +} + +Datum +lt_q_rregex(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(DirectFunctionCall2(lt_q_regex, + PG_GETARG_DATUM(1), + PG_GETARG_DATUM(0) + )); +} + + |