PostgreSQL Source Code: src/backend/utils/adt/like_match.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73#ifdef MATCH_LOWER
74#define GETCHAR(t, locale) MATCH_LOWER(t, locale)
75#else
76#define GETCHAR(t, locale) (t)
77#endif
78
79static int
81{
82
83 if (plen == 1 && *p == '%')
85
86
88
89
90
91
92
93
94
95
96
97 while (tlen > 0 && plen > 0)
98 {
99 if (*p == '\\')
100 {
101
103
104 if (plen <= 0)
106 (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
107 errmsg("LIKE pattern must not end with escape character")));
110 }
111 else if (*p == '%')
112 {
113 char firstpat;
114
115
116
117
118
119
120
121
122
123
124
125
126
127
129
130 while (plen > 0)
131 {
132 if (*p == '%')
134 else if (*p == '_')
135 {
136
137 if (tlen <= 0)
141 }
142 else
143 break;
144 }
145
146
147
148
149
150 if (plen <= 0)
152
153
154
155
156
157
158
159
160
161
162
163
164 if (*p == '\\')
165 {
166 if (plen < 2)
168 (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
169 errmsg("LIKE pattern must not end with escape character")));
171 }
172 else
174
175 while (tlen > 0)
176 {
178 {
180
182 return matched;
183 }
184
186 }
187
188
189
190
191
193 }
194 else if (*p == '_')
195 {
196
199 continue;
200 }
202 {
203
204
205
206
207
208
209
210
211 const char *p1;
212 size_t p1len;
213 const char *t1;
214 size_t t1len;
215 bool found_escape;
216 const char *subpat;
217 size_t subpatlen;
218 char *buf = NULL;
219
220
221
222
223
224
225 p1 = p;
226 p1len = plen;
227 found_escape = false;
228 while (p1len > 0)
229 {
230 if (*p1 == '\\')
231 {
232 found_escape = true;
234 if (p1len == 0)
236 (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
237 errmsg("LIKE pattern must not end with escape character")));
238 }
239 else if (*p1 == '_' || *p1 == '%')
240 break;
242 }
243
244
245
246
247
248 if (found_escape)
249 {
250 char *b;
251
253 for (const char *c = p; c < p1; c++)
254 {
255 if (*c == '\\')
256 ;
257 else
259 }
260
261 subpat = buf;
263 }
264 else
265 {
266 subpat = p;
267 subpatlen = p1 - p;
268 }
269
270
271
272
273
274 if (p1len == 0)
275 {
277
279
282 if (cmp == 0)
284 else
286 }
287
288
289
290
291
292
293 t1 = t;
294 t1len = tlen;
295 for (;;)
296 {
298
300
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319 if (cmp == 0)
320 {
322
324 {
327 return matched;
328 }
329 }
330
331
332
333
334
335 if (t1len == 0)
336 {
340 }
341 else
343 }
344 }
346 {
347
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
365 }
366
367 if (tlen > 0)
368 return LIKE_FALSE;
369
370
371
372
373
374 while (plen > 0 && *p == '%')
376 if (plen <= 0)
378
379
380
381
382
384}
385
386
387
388
389
390#ifdef do_like_escape
391
394{
395 text *result;
396 char *p,
397 *e,
398 *r;
399 int plen,
400 elen;
401 bool afterescape;
402
407
408
409
410
411
414
415 if (elen == 0)
416 {
417
418
419
420
421 while (plen > 0)
422 {
423 if (*p == '\\')
424 *r++ = '\\';
426 }
427 }
428 else
429 {
430
431
432
434 if (elen != 0)
436 (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
437 errmsg("invalid escape string"),
438 errhint("Escape string must be empty or one character.")));
439
441
442
443
444
445 if (*e == '\\')
446 {
448 return result;
449 }
450
451
452
453
454
455
456 afterescape = false;
457 while (plen > 0)
458 {
459 if (CHAREQ(p, e) && !afterescape)
460 {
461 *r++ = '\\';
463 afterescape = true;
464 }
465 else if (*p == '\\')
466 {
467 *r++ = '\\';
468 if (!afterescape)
469 *r++ = '\\';
471 afterescape = false;
472 }
473 else
474 {
476 afterescape = false;
477 }
478 }
479 }
480
481 SET_VARSIZE(result, r - ((char *) result));
482
483 return result;
484}
485#endif
486
487#ifdef CHAREQ
488#undef CHAREQ
489#endif
490
491#undef NextChar
492#undef CopyAdvChar
493#undef MatchText
494
495#ifdef do_like_escape
496#undef do_like_escape
497#endif
498
499#undef GETCHAR
500
501#ifdef MATCH_LOWER
502#undef MATCH_LOWER
503
504#endif
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define CopyAdvChar(dst, src, srclen)
#define NextByte(p, plen)
#define NextChar(p, plen)
static int MatchText(const char *t, int tlen, const char *p, int plen, pg_locale_t locale)
#define GETCHAR(t, locale)
void pfree(void *pointer)
#define CHECK_FOR_INTERRUPTS()
int pg_strncoll(const char *arg1, ssize_t len1, const char *arg2, ssize_t len2, pg_locale_t locale)
static int cmp(const chr *x, const chr *y, size_t len)
void check_stack_depth(void)
#define SET_VARSIZE(PTR, len)
#define VARSIZE_ANY_EXHDR(PTR)