PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
lquery_op.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "catalog/pg_collation.h"
#include "ltree.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/formatting.h"
Include dependency graph for lquery_op.c:

Go to the source code of this file.

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 qlen, ltree_level *curt, int tlen)
 
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)
 

Macro Definition Documentation

◆ NEXTVAL

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

Definition at line 22 of file lquery_op.c.

Function Documentation

◆ checkCond()

static bool checkCond ( lquery_level curq,
int  qlen,
ltree_level curt,
int  tlen 
)
static

Definition at line 136 of file lquery_op.c.

138{
139 /* Since this function recurses, it could be driven to stack overflow */
141
142 /* Pathological patterns could take awhile, too */
144
145 /* Loop while we have query items to consider */
146 while (qlen > 0)
147 {
148 int low,
149 high;
150 lquery_level *nextq;
151
152 /*
153 * Get min and max repetition counts for this query item, dealing with
154 * the backwards-compatibility hack that the low/high fields aren't
155 * meaningful for non-'*' items unless LQL_COUNT is set.
156 */
157 if ((curq->flag & LQL_COUNT) || curq->numvar == 0)
158 low = curq->low, high = curq->high;
159 else
160 low = high = 1;
161
162 /*
163 * We may limit "high" to the remaining text length; this avoids
164 * separate tests below.
165 */
166 if (high > tlen)
167 high = tlen;
168
169 /* Fail if a match of required number of items is impossible */
170 if (high < low)
171 return false;
172
173 /*
174 * Recursively check the rest of the pattern against each possible
175 * start point following some of this item's match(es).
176 */
177 nextq = LQL_NEXT(curq);
178 qlen--;
179
180 for (int matchcnt = 0; matchcnt < high; matchcnt++)
181 {
182 /*
183 * If we've consumed an acceptable number of matches of this item,
184 * and the rest of the pattern matches beginning here, we're good.
185 */
186 if (matchcnt >= low && checkCond(nextq, qlen, curt, tlen))
187 return true;
188
189 /*
190 * Otherwise, try to match one more text item to this query item.
191 */
192 if (!checkLevel(curq, curt))
193 return false;
194
195 curt = LEVEL_NEXT(curt);
196 tlen--;
197 }
198
199 /*
200 * Once we've consumed "high" matches, we can succeed only if the rest
201 * of the pattern matches beginning here. Loop around (if you prefer,
202 * think of this as tail recursion).
203 */
204 curq = nextq;
205 }
206
207 /*
208 * Once we're out of query items, we match only if there's no remaining
209 * text either.
210 */
211 return (tlen == 0);
212}
static bool checkCond(lquery_level *curq, int qlen, ltree_level *curt, int tlen)
Definition: lquery_op.c:136
static bool checkLevel(lquery_level *curq, ltree_level *curt)
Definition: lquery_op.c:99
#define LEVEL_NEXT(x)
Definition: ltree.h:40
#define LQL_NEXT(x)
Definition: ltree.h:100
#define LQL_COUNT
Definition: ltree.h:104
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
void check_stack_depth(void)
Definition: stack_depth.c:95
uint16 numvar
Definition: ltree.h:92
uint16 high
Definition: ltree.h:94
uint16 flag
Definition: ltree.h:91
uint16 low
Definition: ltree.h:93

References CHECK_FOR_INTERRUPTS, check_stack_depth(), checkCond(), checkLevel(), lquery_level::flag, lquery_level::high, LEVEL_NEXT, lquery_level::low, LQL_COUNT, LQL_NEXT, and lquery_level::numvar.

Referenced by checkCond(), and ltq_regex().

◆ checkLevel()

static bool checkLevel ( lquery_level curq,
ltree_level curt 
)
static

Definition at line 99 of file lquery_op.c.

100{
101 lquery_variant *curvar = LQL_FIRST(curq);
102 bool success;
103
104 success = (curq->flag & LQL_NOT) ? false : true;
105
106 /* numvar == 0 means '*' which matches anything */
107 if (curq->numvar == 0)
108 return success;
109
110 for (int i = 0; i < curq->numvar; i++)
111 {
112 int (*cmpptr) (const char *, const char *, size_t);
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,
119 (curvar->flag & LVAR_ANYEND)))
120 return success;
121 }
122 else if ((curvar->len == curt->len ||
123 (curt->len > curvar->len && (curvar->flag & LVAR_ANYEND))) &&
124 (*cmpptr) (curvar->name, curt->name, curvar->len) == 0)
125 return success;
126
127 curvar = LVAR_NEXT(curvar);
128 }
129 return !success;
130}
static bool success
Definition: initdb.c:186
int i
Definition: isn.c:72
bool compare_subnode(ltree_level *t, char *qn, int len, int(*cmpptr)(const char *, const char *, size_t), bool anyend)
Definition: lquery_op.c:44
int ltree_strncasecmp(const char *a, const char *b, size_t s)
Definition: lquery_op.c:78
#define LVAR_INCASE
Definition: ltree.h:75
#define LVAR_ANYEND
Definition: ltree.h:74
#define LQL_FIRST(x)
Definition: ltree.h:101
#define LVAR_NEXT(x)
Definition: ltree.h:72
#define LQL_NOT
Definition: ltree.h:103
#define LVAR_SUBLEXEME
Definition: ltree.h:76
uint8 flag
Definition: ltree.h:62
uint16 len
Definition: ltree.h:61
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:63
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: ltree.h:36
uint16 len
Definition: ltree.h:35

References compare_subnode(), lquery_variant::flag, lquery_level::flag, i, ltree_level::len, lquery_variant::len, LQL_FIRST, LQL_NOT, ltree_strncasecmp(), LVAR_ANYEND, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, ltree_level::name, lquery_variant::name, lquery_level::numvar, and success.

Referenced by checkCond().

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

45{
46 char *endt = t->name + t->len;
47 char *endq = qn + len;
48 char *tn;
49 int lent,
50 lenq;
51 bool isok;
52
53 while ((qn = getlexeme(qn, endq, &lenq)) != NULL)
54 {
55 tn = t->name;
56 isok = false;
57 while ((tn = getlexeme(tn, endt, &lent)) != NULL)
58 {
59 if ((lent == lenq || (lent > lenq && anyend)) &&
60 (*cmpptr) (qn, tn, lenq) == 0)
61 {
62
63 isok = true;
64 break;
65 }
66 tn += lent;
67 }
68
69 if (!isok)
70 return false;
71 qn += lenq;
72 }
73
74 return true;
75}
static char * getlexeme(char *start, char *end, int *len)
Definition: lquery_op.c:25
const void size_t len

References getlexeme(), ltree_level::len, len, and ltree_level::name.

Referenced by checkcondition_str(), and checkLevel().

◆ getlexeme()

static char * getlexeme ( char *  start,
char *  end,
int *  len 
)
static

Definition at line 25 of file lquery_op.c.

26{
27 char *ptr;
28
29 while (start < end && t_iseq(start, '_'))
31
32 ptr = start;
33 if (ptr >= end)
34 return NULL;
35
36 while (ptr < end && !t_iseq(ptr, '_'))
37 ptr += pg_mblen(ptr);
38
39 *len = ptr - start;
40 return start;
41}
return str start
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
#define t_iseq(x, c)
Definition: ts_locale.h:38

References len, pg_mblen(), start, and t_iseq.

Referenced by compare_subnode().

◆ lt_q_regex()

Datum lt_q_regex ( PG_FUNCTION_ARGS  )

Definition at line 239 of file lquery_op.c.

240{
242 ArrayType *_query = PG_GETARG_ARRAYTYPE_P(1);
243 lquery *query = (lquery *) ARR_DATA_PTR(_query);
244 bool res = false;
245 int num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
246
247 if (ARR_NDIM(_query) > 1)
249 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
250 errmsg("array must be one-dimensional")));
251 if (array_contains_nulls(_query))
253 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
254 errmsg("array must not contain nulls")));
255
256 while (num > 0)
257 {
260 {
261
262 res = true;
263 break;
264 }
265 num--;
266 query = NEXTVAL(query);
267 }
268
270 PG_FREE_IF_COPY(_query, 1);
272}
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define ARR_DATA_PTR(a)
Definition: array.h:322
#define ARR_DIMS(a)
Definition: array.h:294
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3767
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define NEXTVAL(x)
Definition: lquery_op.c:22
Datum ltq_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:215
#define PG_GETARG_LTREE_P(n)
Definition: ltree.h:218
static bool DatumGetBool(Datum X)
Definition: postgres.h:95
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
tree
Definition: radixtree.h:1828
Definition: ltree.h:114
Definition: ltree.h:43

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, PointerGetDatum(), res, and tree.

Referenced by lt_q_rregex(), and ltree_consistent().

◆ lt_q_rregex()

Datum lt_q_rregex ( PG_FUNCTION_ARGS  )

Definition at line 275 of file lquery_op.c.

276{
280 ));
281}
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
Datum lt_q_regex(PG_FUNCTION_ARGS)
Definition: lquery_op.c:239

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

◆ ltq_regex()

Datum ltq_regex ( PG_FUNCTION_ARGS  )

Definition at line 215 of file lquery_op.c.

216{
218 lquery *query = PG_GETARG_LQUERY_P(1);
219 bool res;
220
221 res = checkCond(LQUERY_FIRST(query), query->numlevel,
222 LTREE_FIRST(tree), tree->numlevel);
223
225 PG_FREE_IF_COPY(query, 1);
227}
#define LTREE_FIRST(x)
Definition: ltree.h:51
#define PG_GETARG_LQUERY_P(n)
Definition: ltree.h:223
#define LQUERY_FIRST(x)
Definition: ltree.h:124
uint16 numlevel
Definition: ltree.h:116

References checkCond(), LQUERY_FIRST, LTREE_FIRST, lquery::numlevel, PG_FREE_IF_COPY, PG_GETARG_LQUERY_P, PG_GETARG_LTREE_P, PG_RETURN_BOOL, res, and tree.

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

◆ ltq_rregex()

Datum ltq_rregex ( PG_FUNCTION_ARGS  )

◆ ltree_strncasecmp()

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

Definition at line 78 of file lquery_op.c.

79{
80 char *al = str_tolower(a, s, DEFAULT_COLLATION_OID);
81 char *bl = str_tolower(b, s, DEFAULT_COLLATION_OID);
82 int res;
83
84 res = strncmp(al, bl, s);
85
86 pfree(al);
87 pfree(bl);
88
89 return res;
90}
char * str_tolower(const char *buff, size_t nbytes, Oid collid)
Definition: formatting.c:1591
int b
Definition: isn.c:69
int a
Definition: isn.c:68
void pfree(void *pointer)
Definition: mcxt.c:1521

References a, b, pfree(), res, and str_tolower().

Referenced by checkcondition_str(), and checkLevel().

◆ PG_FUNCTION_INFO_V1() [1/4]

PG_FUNCTION_INFO_V1 ( lt_q_regex  )

◆ PG_FUNCTION_INFO_V1() [2/4]

PG_FUNCTION_INFO_V1 ( lt_q_rregex  )

◆ PG_FUNCTION_INFO_V1() [3/4]

PG_FUNCTION_INFO_V1 ( ltq_regex  )

◆ PG_FUNCTION_INFO_V1() [4/4]

PG_FUNCTION_INFO_V1 ( ltq_rregex  )