PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 chargetlexeme (char *start, char *end, int *len)
 
bool compare_subnode (ltree_level *t, char *qn, int len, bool prefix, bool ci)
 
bool ltree_label_match (const char *pred, size_t pred_len, const char *label, size_t label_len, bool prefix, bool ci)
 
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 184 of file lquery_op.c.

186{
187 /* Since this function recurses, it could be driven to stack overflow */
189
190 /* Pathological patterns could take awhile, too */
192
193 /* Loop while we have query items to consider */
194 while (qlen > 0)
195 {
196 int low,
197 high;
199
200 /*
201 * Get min and max repetition counts for this query item, dealing with
202 * the backwards-compatibility hack that the low/high fields aren't
203 * meaningful for non-'*' items unless LQL_COUNT is set.
204 */
205 if ((curq->flag & LQL_COUNT) || curq->numvar == 0)
206 low = curq->low, high = curq->high;
207 else
208 low = high = 1;
209
210 /*
211 * We may limit "high" to the remaining text length; this avoids
212 * separate tests below.
213 */
214 if (high > tlen)
215 high = tlen;
216
217 /* Fail if a match of required number of items is impossible */
218 if (high < low)
219 return false;
220
221 /*
222 * Recursively check the rest of the pattern against each possible
223 * start point following some of this item's match(es).
224 */
226 qlen--;
227
228 for (int matchcnt = 0; matchcnt < high; matchcnt++)
229 {
230 /*
231 * If we've consumed an acceptable number of matches of this item,
232 * and the rest of the pattern matches beginning here, we're good.
233 */
234 if (matchcnt >= low && checkCond(nextq, qlen, curt, tlen))
235 return true;
236
237 /*
238 * Otherwise, try to match one more text item to this query item.
239 */
240 if (!checkLevel(curq, curt))
241 return false;
242
244 tlen--;
245 }
246
247 /*
248 * Once we've consumed "high" matches, we can succeed only if the rest
249 * of the pattern matches beginning here. Loop around (if you prefer,
250 * think of this as tail recursion).
251 */
252 curq = nextq;
253 }
254
255 /*
256 * Once we're out of query items, we match only if there's no remaining
257 * text either.
258 */
259 return (tlen == 0);
260}
static bool checkCond(lquery_level *curq, int qlen, ltree_level *curt, int tlen)
Definition lquery_op.c:184
static bool checkLevel(lquery_level *curq, ltree_level *curt)
Definition lquery_op.c:150
#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:123
static int fb(int x)
void check_stack_depth(void)
Definition stack_depth.c:95
uint16 low
Definition ltree.h:93

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

Referenced by checkCond(), and ltq_regex().

◆ checkLevel()

static bool checkLevel ( lquery_level curq,
ltree_level curt 
)
static

Definition at line 150 of file lquery_op.c.

151{
152 lquery_variant *curvar = LQL_FIRST(curq);
153 bool success;
154
155 success = (curq->flag & LQL_NOT) ? false : true;
156
157 /* numvar == 0 means '*' which matches anything */
158 if (curq->numvar == 0)
159 return success;
160
161 for (int i = 0; i < curq->numvar; i++)
162 {
163 bool prefix = (curvar->flag & LVAR_ANYEND);
164 bool ci = (curvar->flag & LVAR_INCASE);
165
166 if (curvar->flag & LVAR_SUBLEXEME)
167 {
168 if (compare_subnode(curt, curvar->name, curvar->len, prefix, ci))
169 return success;
170 }
171 else if (ltree_label_match(curvar->name, curvar->len, curt->name,
172 curt->len, prefix, ci))
173 return success;
174
175 curvar = LVAR_NEXT(curvar);
176 }
177 return !success;
178}
static bool success
Definition initdb.c:187
return true
Definition isn.c:130
int i
Definition isn.c:77
bool compare_subnode(ltree_level *t, char *qn, int len, bool prefix, bool ci)
Definition lquery_op.c:44
bool ltree_label_match(const char *pred, size_t pred_len, const char *label, size_t label_len, bool prefix, bool ci)
Definition lquery_op.c:81
#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

References compare_subnode(), fb(), lquery_variant::flag, i, lquery_variant::len, LQL_FIRST, LQL_NOT, ltree_label_match(), LVAR_ANYEND, LVAR_INCASE, LVAR_NEXT, LVAR_SUBLEXEME, lquery_variant::name, and success.

Referenced by checkCond().

◆ compare_subnode()

bool compare_subnode ( ltree_level t,
char qn,
int  len,
bool  prefix,
bool  ci 
)

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 (ltree_label_match(qn, lenq, tn, lent, prefix, ci))
60 {
61 isok = true;
62 break;
63 }
64 tn += lent;
65 }
66
67 if (!isok)
68 return false;
69 qn += lenq;
70 }
71
72 return true;
73}
static char * getlexeme(char *start, char *end, int *len)
Definition lquery_op.c:25
const void size_t len
char name[FLEXIBLE_ARRAY_MEMBER]
Definition ltree.h:36
uint16 len
Definition ltree.h:35

References fb(), getlexeme(), ltree_level::len, len, ltree_label_match(), 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, '_'))
30 start += pg_mblen_range(start, end);
31
32 ptr = start;
33 if (ptr >= end)
34 return NULL;
35
36 while (ptr < end && !t_iseq(ptr, '_'))
37 ptr += pg_mblen_range(ptr, end);
38
39 *len = ptr - start;
40 return start;
41}
return str start
int pg_mblen_range(const char *mbstr, const char *end)
Definition mbutils.c:1084
#define t_iseq(x, c)
Definition ts_locale.h:38

References fb(), len, pg_mblen_range(), start, and t_iseq.

Referenced by compare_subnode().

◆ lt_q_regex()

Datum lt_q_regex ( PG_FUNCTION_ARGS  )

Definition at line 287 of file lquery_op.c.

288{
291 lquery *query = (lquery *) ARR_DATA_PTR(_query);
292 bool res = false;
294
295 if (ARR_NDIM(_query) > 1)
298 errmsg("array must be one-dimensional")));
302 errmsg("array must not contain nulls")));
303
304 while (num > 0)
305 {
308 {
309
310 res = true;
311 break;
312 }
313 num--;
314 query = NEXTVAL(query);
315 }
316
319 PG_RETURN_BOOL(res);
320}
#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(const ArrayType *array)
int ArrayGetNItems(int ndim, const int *dims)
Definition arrayutils.c:57
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define PG_FREE_IF_COPY(ptr, n)
Definition fmgr.h:260
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:686
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define NEXTVAL(x)
Definition lquery_op.c:22
Datum ltq_regex(PG_FUNCTION_ARGS)
Definition lquery_op.c:263
#define PG_GETARG_LTREE_P(n)
Definition ltree.h:219
static char * errmsg
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
tree
Definition radixtree.h:1828
Definition ltree.h:43

References ARR_DATA_PTR, ARR_DIMS, ARR_NDIM, array_contains_nulls(), ArrayGetNItems(), DatumGetBool(), DirectFunctionCall2, ereport, errcode(), errmsg, ERROR, fb(), ltq_regex(), NEXTVAL, PG_FREE_IF_COPY, PG_GETARG_ARRAYTYPE_P, PG_GETARG_LTREE_P, PG_RETURN_BOOL, PointerGetDatum(), and tree.

Referenced by lt_q_rregex(), and ltree_consistent().

◆ lt_q_rregex()

Datum lt_q_rregex ( PG_FUNCTION_ARGS  )

Definition at line 323 of file lquery_op.c.

324{
328 ));
329}
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
Datum lt_q_regex(PG_FUNCTION_ARGS)
Definition lquery_op.c:287

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

◆ ltq_regex()

Datum ltq_regex ( PG_FUNCTION_ARGS  )

Definition at line 263 of file lquery_op.c.

264{
266 lquery *query = PG_GETARG_LQUERY_P(1);
267 bool res;
268
269 res = checkCond(LQUERY_FIRST(query), query->numlevel,
270 LTREE_FIRST(tree), tree->numlevel);
271
273 PG_FREE_IF_COPY(query, 1);
274 PG_RETURN_BOOL(res);
275}
#define LTREE_FIRST(x)
Definition ltree.h:51
#define PG_GETARG_LQUERY_P(n)
Definition ltree.h:224
#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, 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_label_match()

bool ltree_label_match ( const char pred,
size_t  pred_len,
const char label,
size_t  label_len,
bool  prefix,
bool  ci 
)

Definition at line 81 of file lquery_op.c.

83{
84 static pg_locale_t locale = NULL;
85 char *fpred; /* casefolded predicate */
86 size_t fpred_len = pred_len;
87 char *flabel; /* casefolded label */
88 size_t flabel_len = label_len;
89 size_t len;
90 bool res;
91
92 /* fast path for binary match or binary prefix match */
93 if ((pred_len == label_len || (prefix && pred_len < label_len)) &&
94 strncmp(pred, label, pred_len) == 0)
95 return true;
96 else if (!ci)
97 return false;
98
99 /*
100 * Slow path for case-insensitive comparison: case fold and then compare.
101 * This path is necessary even if pred_len > label_len, because the byte
102 * lengths may change after casefolding.
103 */
104 if (!locale)
105 locale = pg_database_locale();
106
107 fpred = palloc(fpred_len + 1);
108 len = pg_strfold(fpred, fpred_len + 1, pred, pred_len, locale);
109 if (len > fpred_len)
110 {
111 /* grow buffer if needed and retry */
112 fpred_len = len;
114 len = pg_strfold(fpred, fpred_len + 1, pred, pred_len, locale);
115 }
116 Assert(len <= fpred_len);
117 fpred_len = len;
118
119 flabel = palloc(flabel_len + 1);
120 len = pg_strfold(flabel, flabel_len + 1, label, label_len, locale);
121 if (len > flabel_len)
122 {
123 /* grow buffer if needed and retry */
124 flabel_len = len;
126 len = pg_strfold(flabel, flabel_len + 1, label, label_len, locale);
127 }
129 flabel_len = len;
130
131 if ((fpred_len == flabel_len || (prefix && fpred_len < flabel_len)) &&
133 res = true;
134 else
135 res = false;
136
137 pfree(fpred);
138 pfree(flabel);
139
140 return res;
141}
#define Assert(condition)
Definition c.h:915
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
static char * label
size_t pg_strfold(char *dst, size_t dstsize, const char *src, ssize_t srclen, pg_locale_t locale)
Definition pg_locale.c:1348
pg_locale_t pg_database_locale(void)
Definition pg_locale.c:1175

References Assert, fb(), label, len, palloc(), pfree(), pg_database_locale(), pg_strfold(), and repalloc().

Referenced by checkcondition_str(), checkLevel(), and compare_subnode().

◆ 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  )