summaryrefslogtreecommitdiff
path: root/contrib/ltree/lquery_op.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ltree/lquery_op.c')
-rw-r--r--contrib/ltree/lquery_op.c69
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)
+ ));
+}
+
+