PostgreSQL Source Code  git master
lquery_op.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "catalog/pg_collation.h"
#include "ltree.h"
#include "utils/formatting.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 150 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().

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

◆ checkLevel()

static bool checkLevel ( lquery_level curq,
ltree_level curt 
)
static

Definition at line 102 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().

103 {
104  int (*cmpptr) (const char *, const char *, size_t);
105  lquery_variant *curvar = LQL_FIRST(curq);
106  int i;
107 
108  for (i = 0; i < curq->numvar; i++)
109  {
110  cmpptr = (curvar->flag & LVAR_INCASE) ? ltree_strncasecmp : strncmp;
111 
112  if (curvar->flag & LVAR_SUBLEXEME)
113  {
114  if (compare_subnode(curt, curvar->name, curvar->len, cmpptr, (curvar->flag & LVAR_ANYEND)))
115  return true;
116  }
117  else if ((curvar->len == curt->len ||
118  (curt->len > curvar->len && (curvar->flag & LVAR_ANYEND))) &&
119  (*cmpptr) (curvar->name, curt->name, curvar->len) == 0)
120  {
121 
122  return true;
123  }
124  curvar = LVAR_NEXT(curvar);
125  }
126  return false;
127 }
int ltree_strncasecmp(const char *a, const char *b, size_t s)
Definition: lquery_op.c:87
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 ((lent == lenq || (lent > lenq && anyend)) &&
69  (*cmpptr) (qn, tn, lenq) == 0)
70  {
71 
72  isok = true;
73  break;
74  }
75  tn += lent;
76  }
77 
78  if (!isok)
79  return false;
80  qn += lenq;
81  }
82 
83  return true;
84 }
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:43
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802

◆ lt_q_regex()

Datum lt_q_regex ( PG_FUNCTION_ARGS  )

Definition at line 332 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().

333 {
334  ltree *tree = PG_GETARG_LTREE_P(0);
335  ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
336  lquery *query = (lquery *) ARR_DATA_PTR(_query);
337  bool res = false;
338  int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
339 
340  if (ARR_NDIM(_query) > 1)
341  ereport(ERROR,
342  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
343  errmsg("array must be one-dimensional")));
344  if (array_contains_nulls(_query))
345  ereport(ERROR,
346  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
347  errmsg("array must not contain nulls")));
348 
349  while (num > 0)
350  {
352  PointerGetDatum(tree), PointerGetDatum(query))))
353  {
354 
355  res = true;
356  break;
357  }
358  num--;
359  query = NEXTVAL(query);
360  }
361 
362  PG_FREE_IF_COPY(tree, 0);
363  PG_FREE_IF_COPY(_query, 1);
364  PG_RETURN_BOOL(res);
365 }
#define PointerGetDatum(X)
Definition: postgres.h:556
Definition: ltree.h:69
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
int errcode(int sqlerrcode)
Definition: elog.c:608
#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:251
#define ERROR
Definition: elog.h:43
#define ARR_DIMS(a)
Definition: array.h:282
Datum ltq_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:296
#define ARR_DATA_PTR(a)
Definition: array.h:310
#define DatumGetBool(X)
Definition: postgres.h:393
#define ereport(elevel, rest)
Definition: elog.h:141
Definition: ltree.h:19
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
#define ARR_NDIM(a)
Definition: array.h:278
int errmsg(const char *fmt,...)
Definition: elog.c:822
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3528
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:617

◆ lt_q_rregex()

Datum lt_q_rregex ( PG_FUNCTION_ARGS  )

Definition at line 368 of file lquery_op.c.

References DirectFunctionCall2, lt_q_regex(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

369 {
371  PG_GETARG_DATUM(1),
372  PG_GETARG_DATUM(0)
373  ));
374 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
Datum lt_q_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:332
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:617

◆ ltq_regex()

Datum ltq_regex ( PG_FUNCTION_ARGS  )

Definition at line 296 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().

297 {
298  ltree *tree = PG_GETARG_LTREE_P(0);
299  lquery *query = PG_GETARG_LQUERY_P(1);
300  bool res = false;
301 
302  if (query->flag & LQUERY_HASNOT)
303  {
304  FieldNot fn;
305 
306  fn.q = NULL;
307 
308  res = checkCond(LQUERY_FIRST(query), query->numlevel,
309  LTREE_FIRST(tree), tree->numlevel, &fn);
310  }
311  else
312  {
313  res = checkCond(LQUERY_FIRST(query), query->numlevel,
314  LTREE_FIRST(tree), tree->numlevel, NULL);
315  }
316 
317  PG_FREE_IF_COPY(tree, 0);
318  PG_FREE_IF_COPY(query, 1);
319  PG_RETURN_BOOL(res);
320 }
#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:349
static void * fn(void *arg)
uint16 numlevel
Definition: ltree.h:72
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:255
static bool checkCond(lquery_level *curq, int query_numlevel, ltree_level *curt, int tree_numlevel, FieldNot *ptr)
Definition: lquery_op.c:150
#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 323 of file lquery_op.c.

References DirectFunctionCall2, ltq_regex(), PG_GETARG_DATUM, and PG_RETURN_DATUM.

324 {
326  PG_GETARG_DATUM(1),
327  PG_GETARG_DATUM(0)
328  ));
329 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:263
Datum ltq_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:296
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:343
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:617

◆ ltree_strncasecmp()

int ltree_strncasecmp ( const char *  a,
const char *  b,
size_t  s 
)

Definition at line 87 of file lquery_op.c.

References pfree(), and str_tolower().

Referenced by checkcondition_str(), and checkLevel().

88 {
89  char *al = str_tolower(a, s, DEFAULT_COLLATION_OID);
90  char *bl = str_tolower(b, s, DEFAULT_COLLATION_OID);
91  int res;
92 
93  res = strncmp(al, bl, s);
94 
95  pfree(al);
96  pfree(bl);
97 
98  return res;
99 }
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
Definition: formatting.c:1634
void pfree(void *pointer)
Definition: mcxt.c:1056

◆ 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 142 of file lquery_op.c.

Referenced by checkCond().

◆ muse

bool muse

Definition at line 141 of file lquery_op.c.

◆ SomeStack

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

Referenced by checkCond().