PostgreSQL Source Code  git master
lquery_op.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "catalog/pg_collation.h"
#include "utils/formatting.h"
#include "ltree.h"
Include dependency graph for lquery_op.c:

Go to the source code of this file.

Data Structures

struct  FieldNot
 

Macros

#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
 

Macro Definition Documentation

◆ NEXTVAL

#define NEXTVAL (   x)    ( (lquery*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )

Definition at line 20 of file lquery_op.c.

Referenced by lt_q_regex().

Function Documentation

◆ checkCond()

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, lquery_level::numvar, FieldNot::posq, FieldNot::post, FieldNot::q, SomeStack, and FieldNot::t.

Referenced by ltq_regex().

158 {
159  uint32 low_pos = 0,
160  high_pos = 0,
161  cur_tpos = 0;
162  int tlen = tree_numlevel,
163  qlen = query_numlevel;
164  int isok;
165  lquery_level *prevq = NULL;
166  ltree_level *prevt = NULL;
167 
168  if (SomeStack.muse)
169  {
170  high_pos = SomeStack.high_pos;
171  qlen--;
172  prevq = curq;
173  curq = LQL_NEXT(curq);
174  SomeStack.muse = false;
175  }
176 
177  while (tlen > 0 && qlen > 0)
178  {
179  if (curq->numvar)
180  {
181  prevt = curt;
182  while (cur_tpos < low_pos)
183  {
184  curt = LEVEL_NEXT(curt);
185  tlen--;
186  cur_tpos++;
187  if (tlen == 0)
188  return false;
189  if (ptr && ptr->q)
190  ptr->nt++;
191  }
192 
193  if (ptr && curq->flag & LQL_NOT)
194  {
195  if (!(prevq && prevq->numvar == 0))
196  prevq = curq;
197  if (ptr->q == NULL)
198  {
199  ptr->t = prevt;
200  ptr->q = prevq;
201  ptr->nt = 1;
202  ptr->nq = 1 + ((prevq == curq) ? 0 : 1);
203  ptr->posq = query_numlevel - qlen - ((prevq == curq) ? 0 : 1);
204  ptr->post = cur_tpos;
205  }
206  else
207  {
208  ptr->nt++;
209  ptr->nq++;
210  }
211 
212  if (qlen == 1 && ptr->q->numvar == 0)
213  ptr->nt = tree_numlevel - ptr->post;
214  curt = LEVEL_NEXT(curt);
215  tlen--;
216  cur_tpos++;
217  if (high_pos < cur_tpos)
218  high_pos++;
219  }
220  else
221  {
222  isok = false;
223  while (cur_tpos <= high_pos && tlen > 0 && !isok)
224  {
225  isok = checkLevel(curq, curt);
226  curt = LEVEL_NEXT(curt);
227  tlen--;
228  cur_tpos++;
229  if (isok && prevq && prevq->numvar == 0 && tlen > 0 && cur_tpos <= high_pos)
230  {
231  FieldNot tmpptr;
232 
233  if (ptr)
234  memcpy(&tmpptr, ptr, sizeof(FieldNot));
235  SomeStack.high_pos = high_pos - cur_tpos;
236  SomeStack.muse = true;
237  if (checkCond(prevq, qlen + 1, curt, tlen, (ptr) ? &tmpptr : NULL))
238  return true;
239  }
240  if (!isok && ptr)
241  ptr->nt++;
242  }
243  if (!isok)
244  return false;
245 
246  if (ptr && ptr->q)
247  {
248  if (checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL))
249  return false;
250  ptr->q = NULL;
251  }
252  low_pos = cur_tpos;
253  high_pos = cur_tpos;
254  }
255  }
256  else
257  {
258  low_pos = cur_tpos + curq->low;
259  high_pos = cur_tpos + curq->high;
260  if (ptr && ptr->q)
261  {
262  ptr->nq++;
263  if (qlen == 1)
264  ptr->nt = tree_numlevel - ptr->post;
265  }
266  }
267 
268  prevq = curq;
269  curq = LQL_NEXT(curq);
270  qlen--;
271  }
272 
273  if (low_pos > tree_numlevel || tree_numlevel > high_pos)
274  return false;
275 
276  while (qlen > 0)
277  {
278  if (curq->numvar)
279  {
280  if (!(curq->flag & LQL_NOT))
281  return false;
282  }
283  else
284  {
285  low_pos = cur_tpos + curq->low;
286  high_pos = cur_tpos + curq->high;
287  }
288 
289  curq = LQL_NEXT(curq);
290  qlen--;
291  }
292 
293  if (low_pos > tree_numlevel || tree_numlevel > high_pos)
294  return false;
295 
296  if (ptr && ptr->q && checkCond(ptr->q, ptr->nq, ptr->t, ptr->nt, NULL))
297  return false;
298 
299  return true;
300 }
uint32 high_pos
Definition: lquery_op.c:149
uint16 low
Definition: ltree.h:52
#define LQL_NEXT(x)
Definition: ltree.h:58
lquery_level * q
Definition: lquery_op.c:24
int posq
Definition: lquery_op.c:28
ltree_level * t
Definition: lquery_op.c:26
int post
Definition: lquery_op.c:29
uint16 flag
Definition: ltree.h:50
static bool checkLevel(lquery_level *curq, ltree_level *curt)
Definition: lquery_op.c:106
#define LQL_NOT
Definition: ltree.h:61
int nq
Definition: lquery_op.c:25
unsigned int uint32
Definition: c.h:306
#define LEVEL_NEXT(x)
Definition: ltree.h:17
int nt
Definition: lquery_op.c:27
static struct @0 SomeStack
uint16 numvar
Definition: ltree.h:51
static bool checkCond(lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_numlevel, FieldNot *ptr)
Definition: lquery_op.c:157
uint16 high
Definition: ltree.h:53

◆ checkLevel()

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_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, ltree_level::name, lquery_variant::name, and lquery_level::numvar.

Referenced by checkCond().

107 {
108  int (*cmpptr) (const char *, const char *, size_t);
109  lquery_variant *curvar = LQL_FIRST(curq);
110  int i;
111 
112  for (i = 0; i < curq->numvar; i++)
113  {
114  cmpptr = (curvar->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
115 
116  if (curvar->flag & LVAR_SUBLEXEME)
117  {
118  if (compare_subnode(curt, curvar->name, curvar->len, cmpptr, (curvar->flag & LVAR_ANYEND)))
119  return true;
120  }
121  else if (
122  (
123  curvar->len == curt->len ||
124  (curt->len > curvar->len && (curvar->flag & LVAR_ANYEND))
125  ) &&
126  (*cmpptr) (curvar->name, curt->name, curvar->len) == 0)
127  {
128 
129  return true;
130  }
131  curvar = LVAR_NEXT(curvar);
132  }
133  return false;
134 }
int ltree_strncasecmp(const char *a, const char *b, size_t s)
Definition: lquery_op.c:91
bool compare_subnode(ltree_level *t, char *qn, int len, int(*cmpptr)(const char *, const char *, size_t), bool anyend)
Definition: lquery_op.c:53
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:13
#define LVAR_INCASE
Definition: ltree.h:44
uint8 flag
Definition: ltree.h:36
uint16 len
Definition: ltree.h:35
uint16 len
Definition: ltree.h:12
#define LVAR_ANYEND
Definition: ltree.h:43
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:37
#define LQL_FIRST(x)
Definition: ltree.h:59
#define LVAR_NEXT(x)
Definition: ltree.h:41
#define LVAR_SUBLEXEME
Definition: ltree.h:45
uint16 numvar
Definition: ltree.h:51
int i

◆ compare_subnode()

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, and ltree_level::name.

Referenced by checkcondition_str(), and checkLevel().

54 {
55  char *endt = t->name + t->len;
56  char *endq = qn + len;
57  char *tn;
58  int lent,
59  lenq;
60  bool isok;
61 
62  while ((qn = getlexeme(qn, endq, &lenq)) != NULL)
63  {
64  tn = t->name;
65  isok = false;
66  while ((tn = getlexeme(tn, endt, &lent)) != NULL)
67  {
68  if (
69  (
70  lent == lenq ||
71  (lent > lenq && anyend)
72  ) &&
73  (*cmpptr) (qn, tn, lenq) == 0)
74  {
75 
76  isok = true;
77  break;
78  }
79  tn += lent;
80  }
81 
82  if (!isok)
83  return false;
84  qn += lenq;
85  }
86 
87  return true;
88 }
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:13
uint16 len
Definition: ltree.h:12
static char * getlexeme(char *start, char *end, int *len)
Definition: lquery_op.c:33

◆ getlexeme()

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().

34 {
35  char *ptr;
36  int charlen;
37 
38  while (start < end && (charlen = pg_mblen(start)) == 1 && t_iseq(start, '_'))
39  start += charlen;
40 
41  ptr = start;
42  if (ptr >= end)
43  return NULL;
44 
45  while (ptr < end && !((charlen = pg_mblen(ptr)) == 1 && t_iseq(ptr, '_')))
46  ptr += charlen;
47 
48  *len = ptr - start;
49  return start;
50 }
#define t_iseq(x, c)
Definition: ts_locale.h:45
int pg_mblen(const char *mbstr)
Definition: mbutils.c:760

◆ lt_q_regex()

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_P, PG_RETURN_BOOL, and PointerGetDatum.

Referenced by lt_q_rregex(), and ltree_consistent().

340 {
341  ltree *tree = PG_GETARG_LTREE_P(0);
342  ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
343  lquery *query = (lquery *) ARR_DATA_PTR(_query);
344  bool res = false;
345  int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
346 
347  if (ARR_NDIM(_query) > 1)
348  ereport(ERROR,
349  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
350  errmsg("array must be one-dimensional")));
351  if (array_contains_nulls(_query))
352  ereport(ERROR,
353  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
354  errmsg("array must not contain nulls")));
355 
356  while (num > 0)
357  {
359  PointerGetDatum(tree), PointerGetDatum(query))))
360  {
361 
362  res = true;
363  break;
364  }
365  num--;
366  query = NEXTVAL(query);
367  }
368 
369  PG_FREE_IF_COPY(tree, 0);
370  PG_FREE_IF_COPY(_query, 1);
371  PG_RETURN_BOOL(res);
372 }
#define PointerGetDatum(X)
Definition: postgres.h:562
Definition: ltree.h:69
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PG_GETARG_LTREE_P(n)
Definition: ltree.h:171
#define NEXTVAL(x)
Definition: lquery_op.c:20
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:279
Datum ltq_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:303
#define ARR_DATA_PTR(a)
Definition: array.h:307
#define DatumGetBool(X)
Definition: postgres.h:399
#define ereport(elevel, rest)
Definition: elog.h:122
Definition: ltree.h:19
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:225
#define ARR_NDIM(a)
Definition: array.h:275
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3516
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ lt_q_rregex()

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.

376 {
378  PG_GETARG_DATUM(1),
379  PG_GETARG_DATUM(0)
380  ));
381 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
Datum lt_q_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:339
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ ltq_regex()

Datum ltq_regex ( PG_FUNCTION_ARGS  )

Definition at line 303 of file lquery_op.c.

References checkCond(), lquery::flag, fn(), LQUERY_FIRST, LQUERY_HASNOT, LTREE_FIRST, ltree::numlevel, lquery::numlevel, PG_FREE_IF_COPY, PG_GETARG_LQUERY_P, PG_GETARG_LTREE_P, PG_RETURN_BOOL, and FieldNot::q.

Referenced by _lt_q_regex(), _ltq_extract_regex(), _ltq_regex(), lt_q_regex(), ltq_rregex(), and ltree_consistent().

304 {
305  ltree *tree = PG_GETARG_LTREE_P(0);
306  lquery *query = PG_GETARG_LQUERY_P(1);
307  bool res = false;
308 
309  if (query->flag & LQUERY_HASNOT)
310  {
311  FieldNot fn;
312 
313  fn.q = NULL;
314 
315  res = checkCond(LQUERY_FIRST(query), query->numlevel,
316  LTREE_FIRST(tree), tree->numlevel, &fn);
317  }
318  else
319  {
320  res = checkCond(LQUERY_FIRST(query), query->numlevel,
321  LTREE_FIRST(tree), tree->numlevel, NULL);
322  }
323 
324  PG_FREE_IF_COPY(tree, 0);
325  PG_FREE_IF_COPY(query, 1);
326  PG_RETURN_BOOL(res);
327 }
#define LQUERY_FIRST(x)
Definition: ltree.h:79
Definition: ltree.h:69
lquery_level * q
Definition: lquery_op.c:24
#define PG_GETARG_LTREE_P(n)
Definition: ltree.h:171
uint16 flag
Definition: ltree.h:74
#define PG_GETARG_LQUERY_P(n)
Definition: ltree.h:176
Definition: ltree.h:19
uint16 numlevel
Definition: ltree.h:22
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:319
static void * fn(void *arg)
uint16 numlevel
Definition: ltree.h:72
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:225
static bool checkCond(lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_numlevel, FieldNot *ptr)
Definition: lquery_op.c:157
#define LTREE_FIRST(x)
Definition: ltree.h:27
#define LQUERY_HASNOT
Definition: ltree.h:81

◆ ltq_rregex()

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.

331 {
333  PG_GETARG_DATUM(1),
334  PG_GETARG_DATUM(0)
335  ));
336 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
Datum ltq_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:303
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:587

◆ ltree_strncasecmp()

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().

92 {
93  char *al = str_tolower(a, s, DEFAULT_COLLATION_OID);
94  char *bl = str_tolower(b, s, DEFAULT_COLLATION_OID);
95  int res;
96 
97  res = strncmp(al, bl, s);
98 
99  pfree(al);
100  pfree(bl);
101 
102  return res;
103 }
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
Definition: formatting.c:1508
void pfree(void *pointer)
Definition: mcxt.c:936
#define DEFAULT_COLLATION_OID
Definition: pg_collation.h:75

◆ PG_FUNCTION_INFO_V1() [1/4]

PG_FUNCTION_INFO_V1 ( ltq_regex  )

◆ PG_FUNCTION_INFO_V1() [2/4]

PG_FUNCTION_INFO_V1 ( ltq_rregex  )

◆ PG_FUNCTION_INFO_V1() [3/4]

PG_FUNCTION_INFO_V1 ( lt_q_regex  )

◆ PG_FUNCTION_INFO_V1() [4/4]

PG_FUNCTION_INFO_V1 ( lt_q_rregex  )

Variable Documentation

◆ high_pos

uint32 high_pos

Definition at line 149 of file lquery_op.c.

Referenced by checkCond().

◆ muse

bool muse

Definition at line 148 of file lquery_op.c.

◆ SomeStack

struct { ... } SomeStack
Initial value:
=
{
false, 0,
}

Referenced by checkCond().