#include "postgres.h"
#include <ctype.h>
#include "catalog/pg_collation.h"
#include "utils/formatting.h"
#include "ltree.h"
Go to the source code of this file.
Data Structures | |
struct | FieldNot |
Defines | |
#define | NEXTVAL(x) ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) ) |
Functions | |
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) | |
static char * | getlexeme (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) |
int | ltree_strncasecmp (const char *a, const char *b, size_t s) |
static bool | checkLevel (lquery_level *curq, ltree_level *curt) |
static bool | checkCond (lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_numlevel, FieldNot *ptr) |
Datum | ltq_regex (PG_FUNCTION_ARGS) |
Datum | ltq_rregex (PG_FUNCTION_ARGS) |
Datum | lt_q_regex (PG_FUNCTION_ARGS) |
Datum | lt_q_rregex (PG_FUNCTION_ARGS) |
Variables | |
struct { | |
bool muse | |
uint32 high_pos | |
} | SomeStack |
#define NEXTVAL | ( | x | ) | ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) ) |
Definition at line 20 of file lquery_op.c.
Referenced by lt_q_regex().
static bool checkCond | ( | lquery_level * | curq, | |
int | query_numlevel, | |||
ltree_level * | curt, | |||
int | tree_numlevel, | |||
FieldNot * | ptr | |||
) | [static] |
Definition at line 157 of file lquery_op.c.
References checkLevel(), lquery_level::flag, lquery_level::high, high_pos, LEVEL_NEXT, lquery_level::low, LQL_NEXT, LQL_NOT, FieldNot::nq, FieldNot::nt, NULL, lquery_level::numvar, FieldNot::posq, FieldNot::post, FieldNot::q, SomeStack, and FieldNot::t.
Referenced by ltq_regex().
{ uint32 low_pos = 0, high_pos = 0, cur_tpos = 0; int tlen = tree_numlevel, qlen = query_numlevel; int isok; 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) { prevt = curt; while (cur_tpos < low_pos) { curt = LEVEL_NEXT(curt); tlen--; cur_tpos++; if (tlen == 0) return false; if (ptr && ptr->q) ptr->nt++; } if (ptr && curq->flag & LQL_NOT) { if (!(prevq && prevq->numvar == 0)) prevq = curq; if (ptr->q == NULL) { ptr->t = prevt; ptr->q = prevq; ptr->nt = 1; ptr->nq = 1 + ((prevq == curq) ? 0 : 1); ptr->posq = query_numlevel - qlen - ((prevq == curq) ? 0 : 1); ptr->post = cur_tpos; } else { ptr->nt++; ptr->nq++; } if (qlen == 1 && ptr->q->numvar == 0) ptr->nt = tree_numlevel - ptr->post; curt = LEVEL_NEXT(curt); tlen--; cur_tpos++; if (high_pos < cur_tpos) high_pos++; } else { isok = false; while (cur_tpos <= high_pos && tlen > 0 && !isok) { isok = checkLevel(curq, curt); 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++; } if (!isok) return false; if (ptr && ptr->q) { if (checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL)) return false; ptr->q = NULL; } low_pos = cur_tpos; high_pos = cur_tpos; } } else { low_pos = cur_tpos + curq->low; high_pos = cur_tpos + curq->high; if (ptr && ptr->q) { ptr->nq++; if (qlen == 1) ptr->nt = tree_numlevel - ptr->post; } } prevq = curq; curq = LQL_NEXT(curq); qlen--; } if (low_pos > tree_numlevel || tree_numlevel > high_pos) return false; while (qlen > 0) { if (curq->numvar) { if (!(curq->flag & LQL_NOT)) return false; } else { low_pos = cur_tpos + curq->low; high_pos = cur_tpos + curq->high; } curq = LQL_NEXT(curq); qlen--; } if (low_pos > tree_numlevel || tree_numlevel > high_pos) return false; if (ptr && ptr->q && checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL)) return false; return true; }
static bool checkLevel | ( | lquery_level * | curq, | |
ltree_level * | curt | |||
) | [static] |
Definition at line 106 of file lquery_op.c.
References compare_subnode(), lquery_variant::flag, i, ltree_level::len, lquery_variant::len, LQL_FIRST, ltree_strncasecmp(), LVAR_ANYEND, LVAR_NEXT, LVAR_SUBLEXEME, ltree_level::name, lquery_variant::name, and lquery_level::numvar.
Referenced by checkCond().
{ int (*cmpptr) (const char *, const char *, size_t); lquery_variant *curvar = LQL_FIRST(curq); int i; for (i = 0; i < curq->numvar; i++) { cmpptr = (curvar->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp; if (curvar->flag & LVAR_SUBLEXEME) { if (compare_subnode(curt, curvar->name, curvar->len, cmpptr, (curvar->flag & LVAR_ANYEND))) return true; } else if ( ( curvar->len == curt->len || (curt->len > curvar->len && (curvar->flag & LVAR_ANYEND)) ) && (*cmpptr) (curvar->name, curt->name, curvar->len) == 0) { return true; } curvar = LVAR_NEXT(curvar); } return false; }
bool compare_subnode | ( | ltree_level * | t, | |
char * | qn, | |||
int | len, | |||
int(*)(const char *, const char *, size_t) | cmpptr, | |||
bool | anyend | |||
) |
Definition at line 53 of file lquery_op.c.
References getlexeme(), ltree_level::len, ltree_level::name, and NULL.
Referenced by checkcondition_str(), and checkLevel().
{ char *endt = t->name + t->len; char *endq = qn + len; char *tn; int lent, lenq; bool isok; while ((qn = getlexeme(qn, endq, &lenq)) != NULL) { tn = t->name; isok = false; while ((tn = getlexeme(tn, endt, &lent)) != NULL) { if ( ( lent == lenq || (lent > lenq && anyend) ) && (*cmpptr) (qn, tn, lenq) == 0) { isok = true; break; } tn += lent; } if (!isok) return false; qn += lenq; } return true; }
static char* getlexeme | ( | char * | start, | |
char * | end, | |||
int * | len | |||
) | [static] |
Definition at line 33 of file lquery_op.c.
References pg_mblen(), and t_iseq.
Referenced by compare_subnode().
Datum lt_q_regex | ( | PG_FUNCTION_ARGS | ) |
Definition at line 339 of file lquery_op.c.
References ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, array_contains_nulls(), ArrayGetNItems(), DatumGetBool, DirectFunctionCall2, ereport, errcode(), errmsg(), ERROR, ltq_regex(), NEXTVAL, PG_FREE_IF_COPY, PG_GETARG_ARRAYTYPE_P, PG_GETARG_LTREE, PG_RETURN_BOOL, and PointerGetDatum.
Referenced by lt_q_rregex(), and ltree_consistent().
{ 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) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("array must be one-dimensional"))); if (array_contains_nulls(_query)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("array must not contain nulls"))); 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 | ) |
Definition at line 375 of file lquery_op.c.
References DirectFunctionCall2, lt_q_regex(), PG_GETARG_DATUM, and PG_RETURN_DATUM.
{ PG_RETURN_DATUM(DirectFunctionCall2(lt_q_regex, PG_GETARG_DATUM(1), PG_GETARG_DATUM(0) )); }
Datum ltq_regex | ( | PG_FUNCTION_ARGS | ) |
Definition at line 303 of file lquery_op.c.
References checkCond(), lquery::flag, LQUERY_FIRST, LQUERY_HASNOT, LTREE_FIRST, NULL, ltree::numlevel, lquery::numlevel, PG_FREE_IF_COPY, PG_GETARG_LQUERY, PG_GETARG_LTREE, PG_RETURN_BOOL, and FieldNot::q.
Referenced by _lt_q_regex(), _ltq_extract_regex(), _ltq_regex(), lt_q_regex(), ltq_rregex(), and ltree_consistent().
{ ltree *tree = PG_GETARG_LTREE(0); lquery *query = PG_GETARG_LQUERY(1); bool res = false; if (query->flag & LQUERY_HASNOT) { FieldNot fn; fn.q = NULL; res = checkCond(LQUERY_FIRST(query), query->numlevel, LTREE_FIRST(tree), tree->numlevel, &fn); } else { res = checkCond(LQUERY_FIRST(query), query->numlevel, LTREE_FIRST(tree), tree->numlevel, NULL); } PG_FREE_IF_COPY(tree, 0); PG_FREE_IF_COPY(query, 1); PG_RETURN_BOOL(res); }
Datum ltq_rregex | ( | PG_FUNCTION_ARGS | ) |
Definition at line 330 of file lquery_op.c.
References DirectFunctionCall2, ltq_regex(), PG_GETARG_DATUM, and PG_RETURN_DATUM.
{ PG_RETURN_DATUM(DirectFunctionCall2(ltq_regex, PG_GETARG_DATUM(1), PG_GETARG_DATUM(0) )); }
int ltree_strncasecmp | ( | const char * | a, | |
const char * | b, | |||
size_t | s | |||
) |
Definition at line 91 of file lquery_op.c.
References DEFAULT_COLLATION_OID, pfree(), and str_tolower().
Referenced by checkcondition_str(), and checkLevel().
{ char *al = str_tolower(a, s, DEFAULT_COLLATION_OID); char *bl = str_tolower(b, s, DEFAULT_COLLATION_OID); int res; res = strncmp(al, bl, s); pfree(al); pfree(bl); return res; }
PG_FUNCTION_INFO_V1 | ( | ltq_regex | ) |
PG_FUNCTION_INFO_V1 | ( | lt_q_regex | ) |
PG_FUNCTION_INFO_V1 | ( | ltq_rregex | ) |
PG_FUNCTION_INFO_V1 | ( | lt_q_rregex | ) |
Definition at line 149 of file lquery_op.c.
Referenced by checkCond().
Definition at line 148 of file lquery_op.c.
struct { ... } SomeStack [static] |
Referenced by checkCond().